blob: 521cb4683a8a6906275c393629ff01c2d6cfce80 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_STREAM_WRAPPER_H_
#define MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_STREAM_WRAPPER_H_
#include <mfapi.h>
#include <mfidl.h>
#include <wrl.h>
#include <memory>
#include <queue>
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_log.h"
namespace media {
namespace {
struct MediaFoundationSubsampleEntry {
MediaFoundationSubsampleEntry(SubsampleEntry entry)
: clear_bytes(entry.clear_bytes), cipher_bytes(entry.cypher_bytes) {}
MediaFoundationSubsampleEntry() = default;
DWORD clear_bytes = 0;
DWORD cipher_bytes = 0;
};
} // namespace
// IMFMediaStream implementation
// (https://msdn.microsoft.com/en-us/windows/desktop/ms697561) based on the
// given |demuxer_stream|.
//
class MediaFoundationStreamWrapper
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::RuntimeClassType::ClassicCom>,
IMFMediaStream> {
public:
MediaFoundationStreamWrapper();
~MediaFoundationStreamWrapper() override;
static HRESULT Create(int stream_id,
IMFMediaSource* parent_source,
DemuxerStream* demuxer_stream,
std::unique_ptr<MediaLog> media_log,
scoped_refptr<base::SequencedTaskRunner> task_runner,
MediaFoundationStreamWrapper** stream_out);
HRESULT RuntimeClassInitialize(int stream_id,
IMFMediaSource* parent_source,
DemuxerStream* demuxer_stream,
std::unique_ptr<MediaLog> media_log);
void SetTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner);
void DetachParent();
void DetachDemuxerStream();
bool HasEnded() const;
// The following methods can be invoked by media stack thread or MF threadpool
// thread via MediaFoundationSourceWrapper::Start().
void SetSelected(bool selected);
bool IsSelected();
bool IsEnabled();
void SetEnabled(bool enabled);
void SetFlushed(bool flushed);
// TODO: revisting inheritance and potentially replacing it with composition.
// The stream is encrypted or not.
virtual bool IsEncrypted() const = 0;
// Let derived class to adjust the IMFSample if necessary.
virtual HRESULT TransformSample(Microsoft::WRL::ComPtr<IMFSample>& sample);
// Allow derived class to tell us if we can send MEStreamFormatChanged to MF.
virtual bool AreFormatChangesEnabled();
HRESULT QueueStartedEvent(const PROPVARIANT* start_position);
HRESULT QueueSeekedEvent(const PROPVARIANT* start_position);
HRESULT QueueStoppedEvent();
HRESULT QueuePausedEvent();
HRESULT QueueFormatChangedEvent();
DemuxerStream::Type StreamType() const;
void ProcessRequestsIfPossible();
void OnDemuxerStreamRead(DemuxerStream::Status status,
scoped_refptr<DecoderBuffer> buffer);
// IMFMediaStream implementation - it is in general running in MF threadpool
// thread.
IFACEMETHODIMP GetMediaSource(IMFMediaSource** media_source_out) override;
IFACEMETHODIMP GetStreamDescriptor(
IMFStreamDescriptor** stream_descriptor_out) override;
IFACEMETHODIMP RequestSample(IUnknown* token) override;
// IMFMediaEventGenerator implementation - IMFMediaStream derives from
// IMFMediaEventGenerator.
IFACEMETHODIMP GetEvent(DWORD flags, IMFMediaEvent** event_out) override;
IFACEMETHODIMP BeginGetEvent(IMFAsyncCallback* callback,
IUnknown* state) override;
IFACEMETHODIMP EndGetEvent(IMFAsyncResult* result,
IMFMediaEvent** event_out) override;
IFACEMETHODIMP QueueEvent(MediaEventType type,
REFGUID extended_type,
HRESULT status,
const PROPVARIANT* value) override;
GUID GetLastKeyId() const;
protected:
HRESULT GenerateStreamDescriptor();
HRESULT GenerateSampleFromDecoderBuffer(DecoderBuffer* buffer,
IMFSample** sample_out);
HRESULT ServiceSampleRequest(IUnknown* token, DecoderBuffer* buffer)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
// Returns true when a sample request has been serviced.
bool ServicePostFlushSampleRequest();
virtual HRESULT GetMediaType(IMFMediaType** media_type_out) = 0;
void ReportEncryptionType(const scoped_refptr<DecoderBuffer>& buffer);
scoped_refptr<base::SequencedTaskRunner> task_runner_;
enum class State {
kInitialized,
kStarted,
kStopped,
kPaused
} state_ = State::kInitialized;
DemuxerStream* demuxer_stream_ = nullptr;
DemuxerStream::Type stream_type_ = DemuxerStream::Type::UNKNOWN;
std::unique_ptr<MediaLog> media_log_;
// Need exclusive access to some members between calls from MF threadpool
// thread and calling thread from Chromium media stack.
base::Lock lock_;
// Indicates whether the stream is selected in the MF pipeline.
bool selected_ GUARDED_BY(lock_) = false;
// Indicates whether the stream is enabled in the Chromium media pipeline.
bool enabled_ GUARDED_BY(lock_) = true;
// Indicates whether the Chromium pipeline has flushed the renderer
// (prior to a seek).
// Since SetFlushed() can be invoked by media stack thread or MF threadpool
// thread, |flushed_| and |post_flush_buffers_| are protected by lock.
bool flushed_ GUARDED_BY(lock_) = false;
int stream_id_;
// |mf_media_event_queue_| is safe to be called on any thread.
Microsoft::WRL::ComPtr<IMFMediaEventQueue> mf_media_event_queue_;
Microsoft::WRL::ComPtr<IMFStreamDescriptor> mf_stream_descriptor_;
// The IMFMediaSource that contains this stream.
Microsoft::WRL::ComPtr<IMFMediaSource> parent_source_ GUARDED_BY(lock_);
// If non-zero, there are pending sample request from MF.
std::queue<Microsoft::WRL::ComPtr<IUnknown>> pending_sample_request_tokens_
GUARDED_BY(lock_);
// If true, there is a pending a read completion from Chromium media stack.
bool pending_stream_read_ = false;
bool stream_ended_ = false;
GUID last_key_id_ = GUID_NULL;
// Save media::DecoderBuffer from OnDemuxerStreamRead call when we are in
// progress of a flush operation.
std::queue<scoped_refptr<DecoderBuffer>> post_flush_buffers_
GUARDED_BY(lock_);
bool encryption_type_reported_ = false;
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<MediaFoundationStreamWrapper> weak_factory_{this};
};
} // namespace media
#endif // MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_STREAM_WRAPPER_H_