diff options
Diffstat (limited to 'media')
41 files changed, 404 insertions, 455 deletions
diff --git a/media/base/audio_renderer.h b/media/base/audio_renderer.h index 733daa6..668d919 100644 --- a/media/base/audio_renderer.h +++ b/media/base/audio_renderer.h @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/time/time.h" #include "media/base/buffering_state.h" +#include "media/base/decryptor.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" @@ -26,6 +27,9 @@ class MEDIA_EXPORT AudioRenderer { // Initialize an AudioRenderer with |stream|, executing |init_cb| upon // completion. // + // |set_decryptor_ready_cb| is fired when a Decryptor is needed, i.e. when the + // |stream| is encrypted. + // // |statistics_cb| is executed periodically with audio rendering stats. // // |buffering_state_cb| is executed when audio rendering has either run out of @@ -36,6 +40,7 @@ class MEDIA_EXPORT AudioRenderer { // |error_cb| is executed if an error was encountered. virtual void Initialize(DemuxerStream* stream, const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const base::Closure& ended_cb, diff --git a/media/base/cdm_context.cc b/media/base/cdm_context.cc index 9b0336f..ec2b633 100644 --- a/media/base/cdm_context.cc +++ b/media/base/cdm_context.cc @@ -10,4 +10,7 @@ CdmContext::CdmContext() {} CdmContext::~CdmContext() {} +void IgnoreCdmAttached(bool success) { +} + } // namespace media diff --git a/media/base/cdm_context.h b/media/base/cdm_context.h index db9c516..2a3e8cd2 100644 --- a/media/base/cdm_context.h +++ b/media/base/cdm_context.h @@ -5,6 +5,7 @@ #ifndef MEDIA_BASE_CDM_CONTEXT_H_ #define MEDIA_BASE_CDM_CONTEXT_H_ +#include "base/callback.h" #include "base/macros.h" #include "media/base/media_export.h" @@ -40,6 +41,13 @@ class MEDIA_EXPORT CdmContext { DISALLOW_COPY_AND_ASSIGN(CdmContext); }; +// Callback to notify that the CdmContext has been completely attached to +// the media pipeline. Parameter indicates whether the operation succeeded. +typedef base::Callback<void(bool)> CdmAttachedCB; + +// A dummy implementation of CdmAttachedCB. +MEDIA_EXPORT void IgnoreCdmAttached(bool success); + } // namespace media #endif // MEDIA_BASE_CDM_CONTEXT_H_ diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 92c997c..8a507b4 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -121,14 +121,16 @@ class MockVideoRenderer : public VideoRenderer { virtual ~MockVideoRenderer(); // VideoRenderer implementation. - MOCK_METHOD8(Initialize, void(DemuxerStream* stream, - const PipelineStatusCB& init_cb, - const StatisticsCB& statistics_cb, - const BufferingStateCB& buffering_state_cb, - const PaintCB& paint_cb, - const base::Closure& ended_cb, - const PipelineStatusCB& error_cb, - const TimeDeltaCB& get_time_cb)); + MOCK_METHOD9(Initialize, + void(DemuxerStream* stream, + const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, + const StatisticsCB& statistics_cb, + const BufferingStateCB& buffering_state_cb, + const PaintCB& paint_cb, + const base::Closure& ended_cb, + const PipelineStatusCB& error_cb, + const TimeDeltaCB& get_time_cb)); MOCK_METHOD1(Flush, void(const base::Closure& callback)); MOCK_METHOD1(StartPlayingFrom, void(base::TimeDelta)); @@ -142,12 +144,14 @@ class MockAudioRenderer : public AudioRenderer { virtual ~MockAudioRenderer(); // AudioRenderer implementation. - MOCK_METHOD6(Initialize, void(DemuxerStream* stream, - const PipelineStatusCB& init_cb, - const StatisticsCB& statistics_cb, - const BufferingStateCB& buffering_state_cb, - const base::Closure& ended_cb, - const PipelineStatusCB& error_cb)); + MOCK_METHOD7(Initialize, + void(DemuxerStream* stream, + const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, + const StatisticsCB& statistics_cb, + const BufferingStateCB& buffering_state_cb, + const base::Closure& ended_cb, + const PipelineStatusCB& error_cb)); MOCK_METHOD0(GetTimeSource, TimeSource*()); MOCK_METHOD1(Flush, void(const base::Closure& callback)); MOCK_METHOD0(StartPlaying, void()); @@ -177,7 +181,9 @@ class MockRenderer : public Renderer { MOCK_METHOD0(GetMediaTime, base::TimeDelta()); MOCK_METHOD0(HasAudio, bool()); MOCK_METHOD0(HasVideo, bool()); - MOCK_METHOD1(SetCdm, void(MediaKeys* cdm)); + MOCK_METHOD2(SetCdm, + void(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb)); private: DISALLOW_COPY_AND_ASSIGN(MockRenderer); diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc index 7534688..79a50fd 100644 --- a/media/base/pipeline.cc +++ b/media/base/pipeline.cc @@ -44,6 +44,7 @@ Pipeline::Pipeline( renderer_ended_(false), text_renderer_ended_(false), demuxer_(NULL), + pending_cdm_context_(nullptr), weak_factory_(this) { media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); media_log_->AddEvent( @@ -191,6 +192,13 @@ PipelineStatistics Pipeline::GetStatistics() const { return statistics_; } +void Pipeline::SetCdm(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) { + task_runner_->PostTask( + FROM_HERE, base::Bind(&Pipeline::SetCdmTask, weak_factory_.GetWeakPtr(), + cdm_context, cdm_attached_cb)); +} + void Pipeline::SetErrorForTesting(PipelineStatus status) { OnError(status); } @@ -496,6 +504,12 @@ void Pipeline::StartTask() { base::Bind(&Pipeline::OnTextRendererEnded, weak_factory_.GetWeakPtr())); } + // Set CDM early to avoid unnecessary delay in Renderer::Initialize(). + if (pending_cdm_context_) { + renderer_->SetCdm(pending_cdm_context_, base::Bind(&IgnoreCdmAttached)); + pending_cdm_context_ = nullptr; + } + StateTransitionTask(PIPELINE_OK); } @@ -602,6 +616,17 @@ void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { base::Bind(&Pipeline::OnStateTransition, weak_factory_.GetWeakPtr())); } +void Pipeline::SetCdmTask(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) { + if (!renderer_) { + pending_cdm_context_ = cdm_context; + cdm_attached_cb.Run(true); + return; + } + + renderer_->SetCdm(cdm_context, cdm_attached_cb); +} + void Pipeline::OnRendererEnded() { DCHECK(task_runner_->BelongsToCurrentThread()); media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 2fef5d0..6cbb5e7 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -12,6 +12,7 @@ #include "base/threading/thread_checker.h" #include "base/time/default_tick_clock.h" #include "media/base/buffering_state.h" +#include "media/base/cdm_context.h" #include "media/base/demuxer.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" @@ -180,6 +181,8 @@ class MEDIA_EXPORT Pipeline : public DemuxerHost { // Gets the current pipeline statistics. PipelineStatistics GetStatistics() const; + void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb); + void SetErrorForTesting(PipelineStatus status); bool HasWeakPtrsForTesting() const; @@ -247,6 +250,13 @@ class MEDIA_EXPORT Pipeline : public DemuxerHost { // Carries out notifying filters that we are seeking to a new timestamp. void SeekTask(base::TimeDelta time, const PipelineStatusCB& seek_cb); + // Carries out setting the |cdm_context| in |renderer_|, and then fires + // |cdm_attached_cb| with the result. If |renderer_| is null, + // |cdm_attached_cb| will be fired immediately with true, and |cdm_context| + // will be set in |renderer_| later when |renderer_| is created. + void SetCdmTask(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb); + // Callbacks executed when a renderer has ended. void OnRendererEnded(); void OnTextRendererEnded(); @@ -366,6 +376,11 @@ class MEDIA_EXPORT Pipeline : public DemuxerHost { scoped_ptr<SerialRunner> pending_callbacks_; + // CdmContext to be used to decrypt (and decode) encrypted stream in this + // pipeline. Non-null only when SetCdm() is called and the pipeline has not + // been started. Then during Start(), this value will be set on |renderer_|. + CdmContext* pending_cdm_context_; + base::ThreadChecker thread_checker_; // NOTE: Weak pointers must be invalidated before all other member variables. diff --git a/media/base/renderer.h b/media/base/renderer.h index d6cb74a..f909350 100644 --- a/media/base/renderer.h +++ b/media/base/renderer.h @@ -9,13 +9,13 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "media/base/buffering_state.h" +#include "media/base/cdm_context.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" namespace media { class DemuxerStreamProvider; -class MediaKeys; class VideoFrame; class MEDIA_EXPORT Renderer { @@ -49,6 +49,11 @@ class MEDIA_EXPORT Renderer { const base::Closure& ended_cb, const PipelineStatusCB& error_cb) = 0; + // Associates the |cdm_context| with this Renderer for decryption (and + // decoding) of media data, then fires |cdm_attached_cb| with the result. + virtual void SetCdm(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) = 0; + // The following functions must be called after Initialize(). // Discards any buffered data, executing |flush_cb| when completed. @@ -72,9 +77,6 @@ class MEDIA_EXPORT Renderer { // Returns whether |this| renders video. virtual bool HasVideo() = 0; - // Associates the |cdm| with this Renderer. - virtual void SetCdm(MediaKeys* cdm) = 0; - private: DISALLOW_COPY_AND_ASSIGN(Renderer); }; diff --git a/media/base/video_renderer.h b/media/base/video_renderer.h index 360f7ad..94196eb 100644 --- a/media/base/video_renderer.h +++ b/media/base/video_renderer.h @@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "media/base/buffering_state.h" +#include "media/base/decryptor.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" @@ -34,6 +35,9 @@ class MEDIA_EXPORT VideoRenderer { // Initializes a VideoRenderer with |stream|, executing |init_cb| upon // completion. // + // |set_decryptor_ready_cb| is fired when a Decryptor is needed, i.e. when the + // |stream| is encrypted. + // // |statistics_cb| is executed periodically with video rendering stats, such // as dropped frames. // @@ -50,6 +54,7 @@ class MEDIA_EXPORT VideoRenderer { // |get_time_cb| is used to query the current media playback time. virtual void Initialize(DemuxerStream* stream, const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, diff --git a/media/blink/cdm_session_adapter.cc b/media/blink/cdm_session_adapter.cc index 3804306..43ce395 100644 --- a/media/blink/cdm_session_adapter.cc +++ b/media/blink/cdm_session_adapter.cc @@ -127,20 +127,14 @@ void CdmSessionAdapter::GetUsableKeyIds( media_keys_->GetUsableKeyIds(web_session_id, promise.Pass()); } -Decryptor* CdmSessionAdapter::GetDecryptor() { - return media_keys_->GetCdmContext()->GetDecryptor(); +CdmContext* CdmSessionAdapter::GetCdmContext() { + return media_keys_->GetCdmContext(); } const std::string& CdmSessionAdapter::GetKeySystemUMAPrefix() const { return key_system_uma_prefix_; } -#if defined(ENABLE_BROWSER_CDMS) -int CdmSessionAdapter::GetCdmId() const { - return media_keys_->GetCdmContext()->GetCdmId(); -} -#endif // defined(ENABLE_BROWSER_CDMS) - void CdmSessionAdapter::OnSessionMessage(const std::string& web_session_id, const std::vector<uint8>& message, const GURL& destination_url) { diff --git a/media/blink/cdm_session_adapter.h b/media/blink/cdm_session_adapter.h index 8721fc3..bfb5690 100644 --- a/media/blink/cdm_session_adapter.h +++ b/media/blink/cdm_session_adapter.h @@ -20,7 +20,6 @@ class GURL; namespace media { class CdmFactory; -class Decryptor; class WebContentDecryptionModuleSessionImpl; // Owns the CDM instance and makes calls from session objects to the CDM. @@ -89,21 +88,14 @@ class CdmSessionAdapter : public base::RefCounted<CdmSessionAdapter> { void GetUsableKeyIds(const std::string& web_session_id, scoped_ptr<KeyIdsPromise> promise); - // Returns the Decryptor associated with this CDM. May be NULL if no - // Decryptor is associated with the MediaKeys object. + // Returns the CdmContext associated with |media_keys_|. // TODO(jrummell): Figure out lifetimes, as WMPI may still use the decryptor // after WebContentDecryptionModule is freed. http://crbug.com/330324 - Decryptor* GetDecryptor(); + CdmContext* GetCdmContext(); // Returns a prefix to use for UMAs. const std::string& GetKeySystemUMAPrefix() const; -#if defined(ENABLE_BROWSER_CDMS) - // Returns the CDM ID associated with the |media_keys_|. May be kInvalidCdmId - // if no CDM ID is associated. - int GetCdmId() const; -#endif - private: friend class base::RefCounted<CdmSessionAdapter>; typedef base::hash_map<std::string, diff --git a/media/blink/encrypted_media_player_support.cc b/media/blink/encrypted_media_player_support.cc index ab4bcb5..bfb6ed5 100644 --- a/media/blink/encrypted_media_player_support.cc +++ b/media/blink/encrypted_media_player_support.cc @@ -37,10 +37,6 @@ namespace media { // Prefix for histograms related to Encrypted Media Extensions. static const char* kMediaEme = "Media.EME."; -// Used for calls to decryptor_ready_cb where the result can be ignored. -static void DoNothing(bool success) { -} - // Convert a WebString to ASCII, falling back on an empty string in the case // of a non-ASCII string. static std::string ToASCIIOrEmpty(const WebString& string) { @@ -120,10 +116,10 @@ static std::string GuessInitDataType(const unsigned char* init_data, EncryptedMediaPlayerSupport::EncryptedMediaPlayerSupport( scoped_ptr<CdmFactory> cdm_factory, blink::WebMediaPlayerClient* client, - blink::WebContentDecryptionModule* initial_cdm) + const SetCdmContextCB& set_cdm_context_cb) : cdm_factory_(cdm_factory.Pass()), client_(client), - web_cdm_(ToWebContentDecryptionModuleImpl(initial_cdm)) { + set_cdm_context_cb_(set_cdm_context_cb) { } EncryptedMediaPlayerSupport::~EncryptedMediaPlayerSupport() { @@ -174,9 +170,10 @@ EncryptedMediaPlayerSupport::GenerateKeyRequestInternal( return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; } - if (proxy_decryptor_ && !decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(proxy_decryptor_->GetDecryptor(), base::Bind(DoNothing)); + if (proxy_decryptor_ && !set_cdm_context_cb_.is_null()) { + base::ResetAndReturn(&set_cdm_context_cb_) + .Run(proxy_decryptor_->GetCdmContext(), + base::Bind(&IgnoreCdmAttached)); } current_key_system_ = key_system; @@ -281,64 +278,6 @@ EncryptedMediaPlayerSupport::CancelKeyRequestInternal( return WebMediaPlayer::MediaKeyExceptionNoError; } -void EncryptedMediaPlayerSupport::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) { - // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 - if (!cdm) - return; - - web_cdm_ = ToWebContentDecryptionModuleImpl(cdm); - - if (web_cdm_ && !decryptor_ready_cb_.is_null()) - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); -} - -void EncryptedMediaPlayerSupport::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) { - // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 - if (!cdm) { - result.completeWithError( - blink::WebContentDecryptionModuleExceptionNotSupportedError, - 0, - "Null MediaKeys object is not supported."); - return; - } - - web_cdm_ = ToWebContentDecryptionModuleImpl(cdm); - - if (web_cdm_ && !decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(web_cdm_->GetDecryptor(), BIND_TO_RENDER_LOOP1( - &EncryptedMediaPlayerSupport::ContentDecryptionModuleAttached, - result)); - } else { - // No pipeline/decoder connected, so resolve the promise. When something - // is connected, setting the CDM will happen in SetDecryptorReadyCallback(). - ContentDecryptionModuleAttached(result, true); - } -} - -void EncryptedMediaPlayerSupport::ContentDecryptionModuleAttached( - blink::WebContentDecryptionModuleResult result, - bool success) { - if (success) { - result.complete(); - return; - } - - result.completeWithError( - blink::WebContentDecryptionModuleExceptionNotSupportedError, - 0, - "Unable to set MediaKeys object"); -} - -SetDecryptorReadyCB EncryptedMediaPlayerSupport::CreateSetDecryptorReadyCB() { - return BIND_TO_RENDER_LOOP( - &EncryptedMediaPlayerSupport::SetDecryptorReadyCallback); -} - Demuxer::NeedKeyCB EncryptedMediaPlayerSupport::CreateNeedKeyCB() { return BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupport::OnNeedKey); } @@ -409,39 +348,4 @@ void EncryptedMediaPlayerSupport::OnKeyMessage( destination_url); } -void EncryptedMediaPlayerSupport::SetDecryptorReadyCallback( - const DecryptorReadyCB& decryptor_ready_cb) { - // Cancels the previous decryptor request. - if (decryptor_ready_cb.is_null()) { - if (!decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(NULL, base::Bind(DoNothing)); - } - return; - } - - // TODO(xhwang): Support multiple decryptor notification request (e.g. from - // video and audio). The current implementation is okay for the current - // media pipeline since we initialize audio and video decoders in sequence. - // But WebMediaPlayerImpl should not depend on media pipeline's implementation - // detail. - DCHECK(decryptor_ready_cb_.is_null()); - - // Mixed use of prefixed and unprefixed EME APIs is disallowed by Blink. - DCHECK(!proxy_decryptor_ || !web_cdm_); - - if (proxy_decryptor_) { - decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor(), - base::Bind(DoNothing)); - return; - } - - if (web_cdm_) { - decryptor_ready_cb.Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); - return; - } - - decryptor_ready_cb_ = decryptor_ready_cb; -} - } // namespace media diff --git a/media/blink/encrypted_media_player_support.h b/media/blink/encrypted_media_player_support.h index 4f4c937..a80ff58 100644 --- a/media/blink/encrypted_media_player_support.h +++ b/media/blink/encrypted_media_player_support.h @@ -8,8 +8,10 @@ #include <string> #include <vector> +#include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "media/base/cdm_context.h" #include "media/base/cdm_factory.h" #include "media/base/demuxer.h" #include "media/cdm/proxy_decryptor.h" @@ -27,12 +29,20 @@ namespace media { class WebContentDecryptionModuleImpl; +// Provides support to prefixed EME implementation. +// Do NOT add unprefixed EME functionality to this class! +// TODO(xhwang): Move CreateNeedKeyCB() outside this class. Then when we +// deprecate prefixed EME support, drop this whole file. + class EncryptedMediaPlayerSupport : public base::SupportsWeakPtr<EncryptedMediaPlayerSupport> { public: + typedef base::Callback<void(CdmContext*, const CdmAttachedCB&)> + SetCdmContextCB; + EncryptedMediaPlayerSupport(scoped_ptr<CdmFactory> cdm_factory, blink::WebMediaPlayerClient* client, - blink::WebContentDecryptionModule* initial_cdm); + const SetCdmContextCB& set_cdm_context_cb); ~EncryptedMediaPlayerSupport(); blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest( @@ -53,24 +63,11 @@ class EncryptedMediaPlayerSupport const blink::WebString& key_system, const blink::WebString& session_id); - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm); - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result); - - SetDecryptorReadyCB CreateSetDecryptorReadyCB(); Demuxer::NeedKeyCB CreateNeedKeyCB(); void OnPipelineDecryptError(); private: - // Requests that this object notifies when a decryptor is ready through the - // |decryptor_ready_cb| provided. - // If |decryptor_ready_cb| is null, the existing callback will be fired with - // NULL immediately and reset. - void SetDecryptorReadyCallback(const DecryptorReadyCB& decryptor_ready_cb); - blink::WebMediaPlayer::MediaKeyException GenerateKeyRequestInternal( blink::WebLocalFrame* frame, const std::string& key_system, @@ -100,10 +97,6 @@ class EncryptedMediaPlayerSupport const std::vector<uint8>& message, const GURL& destination_url); - void ContentDecryptionModuleAttached( - blink::WebContentDecryptionModuleResult result, - bool success); - scoped_ptr<CdmFactory> cdm_factory_; blink::WebMediaPlayerClient* client_; @@ -116,15 +109,11 @@ class EncryptedMediaPlayerSupport // through GenerateKeyRequest() directly from WebKit. std::string init_data_type_; + SetCdmContextCB set_cdm_context_cb_; + // Manages decryption keys and decrypts encrypted frames. scoped_ptr<ProxyDecryptor> proxy_decryptor_; - // Non-owned pointer to the CDM. Updated via calls to - // setContentDecryptionModule(). - WebContentDecryptionModuleImpl* web_cdm_; - - DecryptorReadyCB decryptor_ready_cb_; - DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupport); }; diff --git a/media/blink/webcontentdecryptionmodule_impl.cc b/media/blink/webcontentdecryptionmodule_impl.cc index 70002d4..e2fa8aa 100644 --- a/media/blink/webcontentdecryptionmodule_impl.cc +++ b/media/blink/webcontentdecryptionmodule_impl.cc @@ -91,14 +91,8 @@ void WebContentDecryptionModuleImpl::setServerCertificate( new CdmResultPromise<>(result, std::string()))); } -Decryptor* WebContentDecryptionModuleImpl::GetDecryptor() { - return adapter_->GetDecryptor(); +CdmContext* WebContentDecryptionModuleImpl::GetCdmContext() { + return adapter_->GetCdmContext(); } -#if defined(ENABLE_BROWSER_CDMS) -int WebContentDecryptionModuleImpl::GetCdmId() const { - return adapter_->GetCdmId(); -} -#endif // defined(ENABLE_BROWSER_CDMS) - } // namespace media diff --git a/media/blink/webcontentdecryptionmodule_impl.h b/media/blink/webcontentdecryptionmodule_impl.h index 38388c4..bf1915e 100644 --- a/media/blink/webcontentdecryptionmodule_impl.h +++ b/media/blink/webcontentdecryptionmodule_impl.h @@ -21,10 +21,9 @@ class WebSecurityOrigin; namespace media { +class CdmContext; class CdmFactory; class CdmSessionAdapter; -class Decryptor; -class MediaKeys; class WebContentDecryptionModuleSessionImpl; class MEDIA_EXPORT WebContentDecryptionModuleImpl @@ -37,18 +36,6 @@ class MEDIA_EXPORT WebContentDecryptionModuleImpl virtual ~WebContentDecryptionModuleImpl(); - // Returns the Decryptor associated with this CDM. May be NULL if no - // Decryptor associated with the MediaKeys object. - // TODO(jrummell): Figure out lifetimes, as WMPI may still use the decryptor - // after WebContentDecryptionModule is freed. http://crbug.com/330324 - Decryptor* GetDecryptor(); - -#if defined(ENABLE_BROWSER_CDMS) - // Returns the CDM ID associated with this object. May be kInvalidCdmId if no - // CDM ID is associated, such as when Clear Key is used. - int GetCdmId() const; -#endif // defined(ENABLE_BROWSER_CDMS) - // blink::WebContentDecryptionModule implementation. virtual blink::WebContentDecryptionModuleSession* createSession(); // TODO(jrummell): Remove this method once blink updated. @@ -60,6 +47,11 @@ class MEDIA_EXPORT WebContentDecryptionModuleImpl size_t server_certificate_length, blink::WebContentDecryptionModuleResult result); + // Returns the CdmContext associated with this CDM, which must not be nullptr. + // TODO(jrummell): Figure out lifetimes, as WMPI may still use the decryptor + // after WebContentDecryptionModule is freed. http://crbug.com/330324 + CdmContext* GetCdmContext(); + private: // Takes reference to |adapter|. WebContentDecryptionModuleImpl(scoped_refptr<CdmSessionAdapter> adapter); diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 0d9a6a3..56c467d 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc @@ -36,6 +36,7 @@ #include "media/blink/encrypted_media_player_support.h" #include "media/blink/texttrack_impl.h" #include "media/blink/webaudiosourceprovider_impl.h" +#include "media/blink/webcontentdecryptionmodule_impl.h" #include "media/blink/webinbandtexttrack_impl.h" #include "media/blink/webmediaplayer_delegate.h" #include "media/blink/webmediaplayer_params.h" @@ -168,9 +169,10 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))), text_track_index_(0), - encrypted_media_support_(cdm_factory.Pass(), - client, - params.initial_cdm()), + encrypted_media_support_( + cdm_factory.Pass(), + client, + base::Bind(&WebMediaPlayerImpl::SetCdm, AsWeakPtr())), audio_hardware_config_(params.audio_hardware_config()), renderer_(renderer.Pass()) { // Threaded compositing isn't enabled universally yet. @@ -674,18 +676,38 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest( } void WebMediaPlayerImpl::setContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) { + blink::WebContentDecryptionModule* cdm, + blink::WebContentDecryptionModuleResult result) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - encrypted_media_support_.SetContentDecryptionModule(cdm); + // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 + if (!cdm) { + result.completeWithError( + blink::WebContentDecryptionModuleExceptionNotSupportedError, 0, + "Null MediaKeys object is not supported."); + return; + } + + SetCdm(ToWebContentDecryptionModuleImpl(cdm)->GetCdmContext(), + BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnCdmAttached, result)); } -void WebMediaPlayerImpl::setContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); +void WebMediaPlayerImpl::SetCdm(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) { + pipeline_.SetCdm(cdm_context, cdm_attached_cb); +} - encrypted_media_support_.SetContentDecryptionModule(cdm, result); +void WebMediaPlayerImpl::OnCdmAttached( + blink::WebContentDecryptionModuleResult result, + bool success) { + if (success) { + result.complete(); + return; + } + + result.completeWithError( + blink::WebContentDecryptionModuleExceptionNotSupportedError, 0, + "Unable to set MediaKeys object"); } void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, @@ -841,9 +863,6 @@ void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { // TODO(xhwang): Move this to a factory class so that we can create different // renderers. scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() { - SetDecryptorReadyCB set_decryptor_ready_cb = - encrypted_media_support_.CreateSetDecryptorReadyCB(); - // Create our audio decoders and renderer. ScopedVector<AudioDecoder> audio_decoders; @@ -851,13 +870,9 @@ scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() { media_task_runner_, base::Bind(&LogMediaSourceError, media_log_))); audio_decoders.push_back(new OpusAudioDecoder(media_task_runner_)); - scoped_ptr<AudioRenderer> audio_renderer( - new AudioRendererImpl(media_task_runner_, - audio_source_provider_.get(), - audio_decoders.Pass(), - set_decryptor_ready_cb, - audio_hardware_config_, - media_log_)); + scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl( + media_task_runner_, audio_source_provider_.get(), audio_decoders.Pass(), + audio_hardware_config_, media_log_)); // Create our video decoders and renderer. ScopedVector<VideoDecoder> video_decoders; @@ -872,11 +887,7 @@ scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() { video_decoders.push_back(new FFmpegVideoDecoder(media_task_runner_)); scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl( - media_task_runner_, - video_decoders.Pass(), - set_decryptor_ready_cb, - true, - media_log_)); + media_task_runner_, video_decoders.Pass(), true, media_log_)); // Create renderer. return scoped_ptr<Renderer>(new RendererImpl( diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 674a378..596df9e 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h @@ -156,10 +156,6 @@ class MEDIA_EXPORT WebMediaPlayerImpl const blink::WebString& key_system, const blink::WebString& session_id); - // TODO(jrummell): Remove this method once Blink updated to use the other - // method. - virtual void setContentDecryptionModule( - blink::WebContentDecryptionModule* cdm); virtual void setContentDecryptionModule( blink::WebContentDecryptionModule* cdm, blink::WebContentDecryptionModuleResult result); @@ -213,6 +209,12 @@ class MEDIA_EXPORT WebMediaPlayerImpl // compositor can return the frame. scoped_refptr<VideoFrame> GetCurrentFrameFromCompositor(); + void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb); + + // Called when a CDM has been attached to the |pipeline_|. + void OnCdmAttached(blink::WebContentDecryptionModuleResult result, + bool success); + blink::WebLocalFrame* frame_; // TODO(hclam): get rid of these members and read from the pipeline directly. diff --git a/media/cdm/proxy_decryptor.cc b/media/cdm/proxy_decryptor.cc index 0c25dff..2daa10c 100644 --- a/media/cdm/proxy_decryptor.cc +++ b/media/cdm/proxy_decryptor.cc @@ -42,16 +42,10 @@ ProxyDecryptor::~ProxyDecryptor() { media_keys_.reset(); } -Decryptor* ProxyDecryptor::GetDecryptor() { - return media_keys_ ? media_keys_->GetCdmContext()->GetDecryptor() : NULL; +CdmContext* ProxyDecryptor::GetCdmContext() { + return media_keys_ ? media_keys_->GetCdmContext() : nullptr; } -#if defined(ENABLE_BROWSER_CDMS) -int ProxyDecryptor::GetCdmId() { - return media_keys_->GetCdmContext()->GetCdmId(); -} -#endif - bool ProxyDecryptor::InitializeCDM(CdmFactory* cdm_factory, const std::string& key_system, const GURL& security_origin) { diff --git a/media/cdm/proxy_decryptor.h b/media/cdm/proxy_decryptor.h index 193c6b0..308ee99 100644 --- a/media/cdm/proxy_decryptor.h +++ b/media/cdm/proxy_decryptor.h @@ -46,15 +46,8 @@ class MEDIA_EXPORT ProxyDecryptor { const KeyMessageCB& key_message_cb); virtual ~ProxyDecryptor(); - // Returns the Decryptor associated with this object. May be NULL if no - // Decryptor is associated. - Decryptor* GetDecryptor(); - -#if defined(ENABLE_BROWSER_CDMS) - // Returns the CDM ID associated with this object. May be kInvalidCdmId if no - // CDM ID is associated, such as when Clear Key is used. - int GetCdmId(); -#endif + // Returns the CdmContext associated with this object. + CdmContext* GetCdmContext(); // Only call this once. bool InitializeCDM(CdmFactory* cdm_factory, @@ -115,10 +108,6 @@ class MEDIA_EXPORT ProxyDecryptor { bool is_clear_key_; -#if defined(ENABLE_BROWSER_CDMS) - int cdm_id_; -#endif - // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<ProxyDecryptor> weak_ptr_factory_; diff --git a/media/filters/audio_decoder_selector_unittest.cc b/media/filters/audio_decoder_selector_unittest.cc index 09b21e030..36f7ca64 100644 --- a/media/filters/audio_decoder_selector_unittest.cc +++ b/media/filters/audio_decoder_selector_unittest.cc @@ -92,13 +92,6 @@ class AudioDecoderSelectorTest : public ::testing::Test { void InitializeDecoderSelector(DecryptorCapability decryptor_capability, int num_decoders) { - SetDecryptorReadyCB set_decryptor_ready_cb; - if (decryptor_capability != kNoDecryptor) { - set_decryptor_ready_cb = - base::Bind(&AudioDecoderSelectorTest::SetDecryptorReadyCallback, - base::Unretained(this)); - } - if (decryptor_capability == kDecryptOnly || decryptor_capability == kDecryptAndDecode) { EXPECT_CALL(*this, SetDecryptorReadyCallback(_)) @@ -121,6 +114,10 @@ class AudioDecoderSelectorTest : public ::testing::Test { // Set and cancel DecryptorReadyCB but the callback is never fired. EXPECT_CALL(*this, SetDecryptorReadyCallback(_)) .Times(2); + } else if (decryptor_capability == kNoDecryptor) { + EXPECT_CALL(*this, SetDecryptorReadyCallback(_)) + .WillRepeatedly( + RunCallback<0>(nullptr, base::Bind(&IgnoreCdmAttached))); } DCHECK_GE(all_decoders_.size(), static_cast<size_t>(num_decoders)); @@ -128,14 +125,14 @@ class AudioDecoderSelectorTest : public ::testing::Test { all_decoders_.begin() + num_decoders, all_decoders_.end()); decoder_selector_.reset(new AudioDecoderSelector( - message_loop_.message_loop_proxy(), - all_decoders_.Pass(), - set_decryptor_ready_cb)); + message_loop_.message_loop_proxy(), all_decoders_.Pass())); } void SelectDecoder() { decoder_selector_->SelectDecoder( demuxer_stream_.get(), + base::Bind(&AudioDecoderSelectorTest::SetDecryptorReadyCallback, + base::Unretained(this)), base::Bind(&AudioDecoderSelectorTest::MockOnDecoderSelected, base::Unretained(this)), base::Bind(&AudioDecoderSelectorTest::OnDecoderOutput)); diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc index d8db70d..82ba0be 100644 --- a/media/filters/audio_renderer_impl.cc +++ b/media/filters/audio_renderer_impl.cc @@ -44,16 +44,13 @@ AudioRendererImpl::AudioRendererImpl( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, media::AudioRendererSink* sink, ScopedVector<AudioDecoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb, const AudioHardwareConfig& hardware_config, const scoped_refptr<MediaLog>& media_log) : task_runner_(task_runner), expecting_config_changes_(false), sink_(sink), - audio_buffer_stream_(new AudioBufferStream(task_runner, - decoders.Pass(), - set_decryptor_ready_cb, - media_log)), + audio_buffer_stream_( + new AudioBufferStream(task_runner, decoders.Pass(), media_log)), hardware_config_(hardware_config), playback_rate_(0), state_(kUninitialized), @@ -253,12 +250,14 @@ void AudioRendererImpl::StartPlaying() { AttemptRead_Locked(); } -void AudioRendererImpl::Initialize(DemuxerStream* stream, - const PipelineStatusCB& init_cb, - const StatisticsCB& statistics_cb, - const BufferingStateCB& buffering_state_cb, - const base::Closure& ended_cb, - const PipelineStatusCB& error_cb) { +void AudioRendererImpl::Initialize( + DemuxerStream* stream, + const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, + const StatisticsCB& statistics_cb, + const BufferingStateCB& buffering_state_cb, + const base::Closure& ended_cb, + const PipelineStatusCB& error_cb) { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(stream); @@ -316,9 +315,9 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream, new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate())); audio_buffer_stream_->Initialize( - stream, statistics_cb, - base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, - weak_factory_.GetWeakPtr())); + stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, + weak_factory_.GetWeakPtr()), + set_decryptor_ready_cb, statistics_cb); } void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { diff --git a/media/filters/audio_renderer_impl.h b/media/filters/audio_renderer_impl.h index 8065b26..f47a9dd 100644 --- a/media/filters/audio_renderer_impl.h +++ b/media/filters/audio_renderer_impl.h @@ -57,14 +57,10 @@ class MEDIA_EXPORT AudioRendererImpl // |sink| is used as the destination for the rendered audio. // // |decoders| contains the AudioDecoders to use when initializing. - // - // |set_decryptor_ready_cb| is fired when the audio decryptor is available - // (only applicable if the stream is encrypted and we have a decryptor). AudioRendererImpl( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, AudioRendererSink* sink, ScopedVector<AudioDecoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb, const AudioHardwareConfig& hardware_params, const scoped_refptr<MediaLog>& media_log); ~AudioRendererImpl() override; @@ -80,6 +76,7 @@ class MEDIA_EXPORT AudioRendererImpl // AudioRenderer implementation. void Initialize(DemuxerStream* stream, const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const base::Closure& ended_cb, diff --git a/media/filters/audio_renderer_impl_unittest.cc b/media/filters/audio_renderer_impl_unittest.cc index 288d27c..0682446 100644 --- a/media/filters/audio_renderer_impl_unittest.cc +++ b/media/filters/audio_renderer_impl_unittest.cc @@ -95,7 +95,6 @@ class AudioRendererImplTest : public ::testing::Test { renderer_.reset(new AudioRendererImpl(message_loop_.message_loop_proxy(), sink_.get(), decoders.Pass(), - SetDecryptorReadyCB(), hardware_config_, new MediaLog())); } @@ -116,16 +115,13 @@ class AudioRendererImplTest : public ::testing::Test { void InitializeRenderer(const PipelineStatusCB& pipeline_status_cb) { renderer_->Initialize( - &demuxer_stream_, - pipeline_status_cb, + &demuxer_stream_, pipeline_status_cb, SetDecryptorReadyCB(), base::Bind(&AudioRendererImplTest::OnStatistics, base::Unretained(this)), base::Bind(&AudioRendererImplTest::OnBufferingStateChange, base::Unretained(this)), - base::Bind(&AudioRendererImplTest::OnEnded, - base::Unretained(this)), - base::Bind(&AudioRendererImplTest::OnError, - base::Unretained(this))); + base::Bind(&AudioRendererImplTest::OnEnded, base::Unretained(this)), + base::Bind(&AudioRendererImplTest::OnError, base::Unretained(this))); } void Initialize() { diff --git a/media/filters/decoder_selector.cc b/media/filters/decoder_selector.cc index d99c736..f472be7 100644 --- a/media/filters/decoder_selector.cc +++ b/media/filters/decoder_selector.cc @@ -51,13 +51,12 @@ static bool IsStreamEncrypted(DemuxerStream* stream) { template <DemuxerStream::Type StreamType> DecoderSelector<StreamType>::DecoderSelector( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - ScopedVector<Decoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb) + ScopedVector<Decoder> decoders) : task_runner_(task_runner), decoders_(decoders.Pass()), - set_decryptor_ready_cb_(set_decryptor_ready_cb), input_stream_(NULL), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { +} template <DemuxerStream::Type StreamType> DecoderSelector<StreamType>::~DecoderSelector() { @@ -74,11 +73,16 @@ DecoderSelector<StreamType>::~DecoderSelector() { template <DemuxerStream::Type StreamType> void DecoderSelector<StreamType>::SelectDecoder( DemuxerStream* stream, + const SetDecryptorReadyCB& set_decryptor_ready_cb, const SelectDecoderCB& select_decoder_cb, const typename Decoder::OutputCB& output_cb) { DVLOG(2) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(stream); + DCHECK(set_decryptor_ready_cb_.is_null()); + DCHECK(select_decoder_cb_.is_null()); + + set_decryptor_ready_cb_ = set_decryptor_ready_cb; // Make sure |select_decoder_cb| runs on a different execution stack. select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); diff --git a/media/filters/decoder_selector.h b/media/filters/decoder_selector.h index fbe3dc7..277410e 100644 --- a/media/filters/decoder_selector.h +++ b/media/filters/decoder_selector.h @@ -50,13 +50,9 @@ class MEDIA_EXPORT DecoderSelector { SelectDecoderCB; // |decoders| contains the Decoders to use when initializing. - // - // |set_decryptor_ready_cb| is optional. If |set_decryptor_ready_cb| is null, - // no decryptor will be available to perform decryption. DecoderSelector( const scoped_refptr<base::SingleThreadTaskRunner>& message_loop, - ScopedVector<Decoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb); + ScopedVector<Decoder> decoders); // Aborts pending Decoder selection and fires |select_decoder_cb| with // NULL and NULL immediately if it's pending. @@ -65,7 +61,12 @@ class MEDIA_EXPORT DecoderSelector { // Initializes and selects a Decoder that can decode the |stream|. // Selected Decoder (and DecryptingDemuxerStream) is returned via // the |select_decoder_cb|. + // Notes: + // 1. This function can be only called once. + // 2. |set_decryptor_ready_cb| is optional. If |set_decryptor_ready_cb| is + // null, no decryptor will be available to perform decryption. void SelectDecoder(DemuxerStream* stream, + const SetDecryptorReadyCB& set_decryptor_ready_cb, const SelectDecoderCB& select_decoder_cb, const typename Decoder::OutputCB& output_cb); @@ -78,9 +79,9 @@ class MEDIA_EXPORT DecoderSelector { scoped_refptr<base::SingleThreadTaskRunner> task_runner_; ScopedVector<Decoder> decoders_; - SetDecryptorReadyCB set_decryptor_ready_cb_; DemuxerStream* input_stream_; + SetDecryptorReadyCB set_decryptor_ready_cb_; SelectDecoderCB select_decoder_cb_; typename Decoder::OutputCB output_cb_; diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc index 3fc95a3..b54eaa4 100644 --- a/media/filters/decoder_stream.cc +++ b/media/filters/decoder_stream.cc @@ -42,20 +42,18 @@ template <DemuxerStream::Type StreamType> DecoderStream<StreamType>::DecoderStream( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, ScopedVector<Decoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb, const scoped_refptr<MediaLog>& media_log) : task_runner_(task_runner), media_log_(media_log), state_(STATE_UNINITIALIZED), stream_(NULL), decoder_selector_( - new DecoderSelector<StreamType>(task_runner, - decoders.Pass(), - set_decryptor_ready_cb)), + new DecoderSelector<StreamType>(task_runner, decoders.Pass())), active_splice_(false), decoding_eos_(false), pending_decode_requests_(0), - weak_factory_(this) {} + weak_factory_(this) { +} template <DemuxerStream::Type StreamType> DecoderStream<StreamType>::~DecoderStream() { @@ -81,9 +79,11 @@ DecoderStream<StreamType>::~DecoderStream() { } template <DemuxerStream::Type StreamType> -void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, - const StatisticsCB& statistics_cb, - const InitCB& init_cb) { +void DecoderStream<StreamType>::Initialize( + DemuxerStream* stream, + const InitCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, + const StatisticsCB& statistics_cb) { FUNCTION_DVLOG(2); DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK_EQ(state_, STATE_UNINITIALIZED) << state_; @@ -97,7 +97,7 @@ void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, state_ = STATE_INITIALIZING; // TODO(xhwang): DecoderSelector only needs a config to select a decoder. decoder_selector_->SelectDecoder( - stream, + stream, set_decryptor_ready_cb, base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, weak_factory_.GetWeakPtr()), base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, diff --git a/media/filters/decoder_stream.h b/media/filters/decoder_stream.h index 360a497..625f7b9 100644 --- a/media/filters/decoder_stream.h +++ b/media/filters/decoder_stream.h @@ -53,15 +53,15 @@ class MEDIA_EXPORT DecoderStream { DecoderStream( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, ScopedVector<Decoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb, const scoped_refptr<MediaLog>& media_log); virtual ~DecoderStream(); // Initializes the DecoderStream and returns the initialization result // through |init_cb|. Note that |init_cb| is always called asynchronously. void Initialize(DemuxerStream* stream, - const StatisticsCB& statistics_cb, - const InitCB& init_cb); + const InitCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, + const StatisticsCB& statistics_cb); // Reads a decoded Output and returns it via the |read_cb|. Note that // |read_cb| is always called asynchronously. This method should only be @@ -99,7 +99,7 @@ class MEDIA_EXPORT DecoderStream { } // Allows callers to register for notification of config changes; this is - // called immediately after recieving the 'kConfigChanged' status from the + // called immediately after receiving the 'kConfigChanged' status from the // DemuxerStream, before any action is taken to handle the config change. typedef base::Closure ConfigChangeObserverCB; void set_config_change_observer( diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc index 1a6d2d5..a568221 100644 --- a/media/filters/pipeline_integration_test.cc +++ b/media/filters/pipeline_integration_test.cc @@ -10,6 +10,7 @@ #include "base/strings/string_util.h" #include "build/build_config.h" #include "media/base/cdm_callback_promise.h" +#include "media/base/cdm_context.h" #include "media/base/decoder_buffer.h" #include "media/base/media_keys.h" #include "media/base/media_switches.h" @@ -145,11 +146,10 @@ class FakeEncryptedMedia { base::Unretained(this)), base::Bind(&FakeEncryptedMedia::OnSessionKeysChange, base::Unretained(this))), + cdm_context_(&decryptor_), app_(app) {} - AesDecryptor* decryptor() { - return &decryptor_; - } + CdmContext* GetCdmContext() { return &cdm_context_; } // Callbacks for firing session events. Delegate to |app_|. void OnSessionMessage(const std::string& web_session_id, @@ -181,7 +181,22 @@ class FakeEncryptedMedia { } private: + class TestCdmContext : public CdmContext { + public: + TestCdmContext(Decryptor* decryptor) : decryptor_(decryptor) {} + + Decryptor* GetDecryptor() final { return decryptor_; } + +#if defined(ENABLE_BROWSER_CDMS) + int GetCdmId() const final { return kInvalidCdmId; } +#endif + + private: + Decryptor* decryptor_; + }; + AesDecryptor decryptor_; + TestCdmContext cdm_context_; scoped_ptr<AppBase> app_; }; @@ -560,8 +575,7 @@ class PipelineIntegrationTest .Times(AtMost(1)); demuxer_ = source->GetDemuxer().Pass(); pipeline_->Start( - demuxer_.get(), - CreateRenderer(NULL), + demuxer_.get(), CreateRenderer(), base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)), base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)), QuitOnStatusCB(PIPELINE_OK), @@ -571,9 +585,8 @@ class PipelineIntegrationTest base::Unretained(this)), base::Bind(&PipelineIntegrationTest::OnVideoFramePaint, base::Unretained(this)), - base::Closure(), - base::Bind(&PipelineIntegrationTest::OnAddTextTrack, - base::Unretained(this))); + base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack, + base::Unretained(this))); message_loop_.Run(); } @@ -591,10 +604,16 @@ class PipelineIntegrationTest .WillRepeatedly(SaveArg<0>(&metadata_)); EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH)) .Times(AtMost(1)); + EXPECT_CALL(*this, DecryptorAttached(true)); + demuxer_ = source->GetDemuxer().Pass(); + + pipeline_->SetCdm(encrypted_media->GetCdmContext(), + base::Bind(&PipelineIntegrationTest::DecryptorAttached, + base::Unretained(this))); + pipeline_->Start( - demuxer_.get(), - CreateRenderer(encrypted_media->decryptor()), + demuxer_.get(), CreateRenderer(), base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)), base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)), QuitOnStatusCB(PIPELINE_OK), @@ -604,9 +623,8 @@ class PipelineIntegrationTest base::Unretained(this)), base::Bind(&PipelineIntegrationTest::OnVideoFramePaint, base::Unretained(this)), - base::Closure(), - base::Bind(&PipelineIntegrationTest::OnAddTextTrack, - base::Unretained(this))); + base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack, + base::Unretained(this))); source->set_need_key_cb(base::Bind(&FakeEncryptedMedia::NeedKey, base::Unretained(encrypted_media))); @@ -707,7 +725,7 @@ TEST_F(PipelineIntegrationTest, BasicPlaybackEncrypted) { base::Unretained(&encrypted_media))); ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-av_enc-av.webm"), - encrypted_media.decryptor())); + encrypted_media.GetCdmContext())); Play(); diff --git a/media/filters/pipeline_integration_test_base.cc b/media/filters/pipeline_integration_test_base.cc index 7b861f5..ca8176f 100644 --- a/media/filters/pipeline_integration_test_base.cc +++ b/media/filters/pipeline_integration_test_base.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/memory/scoped_vector.h" +#include "media/base/cdm_context.h" #include "media/base/media_log.h" #include "media/filters/audio_renderer_impl.h" #include "media/filters/chunk_demuxer.h" @@ -116,7 +117,7 @@ bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path, .Times(AtMost(1)); CreateDemuxer(file_path); pipeline_->Start( - demuxer_.get(), CreateRenderer(NULL), + demuxer_.get(), CreateRenderer(), base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)), base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)), QuitOnStatusCB(expected_status), @@ -145,17 +146,21 @@ bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path) { } bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path, - Decryptor* decryptor) { + CdmContext* cdm_context) { EXPECT_CALL(*this, OnMetadata(_)) .Times(AtMost(1)) .WillRepeatedly(SaveArg<0>(&metadata_)); EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH)) .Times(AtMost(1)); + EXPECT_CALL(*this, DecryptorAttached(true)); CreateDemuxer(file_path); + + pipeline_->SetCdm(cdm_context, + base::Bind(&PipelineIntegrationTestBase::DecryptorAttached, + base::Unretained(this))); pipeline_->Start( - demuxer_.get(), - CreateRenderer(decryptor), + demuxer_.get(), CreateRenderer(), base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)), base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)), base::Bind(&PipelineIntegrationTestBase::OnStatusCallback, @@ -166,9 +171,8 @@ bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path, base::Unretained(this)), base::Bind(&PipelineIntegrationTestBase::OnVideoFramePaint, base::Unretained(this)), - base::Closure(), - base::Bind(&PipelineIntegrationTestBase::OnAddTextTrack, - base::Unretained(this))); + base::Closure(), base::Bind(&PipelineIntegrationTestBase::OnAddTextTrack, + base::Unretained(this))); message_loop_.Run(); return (pipeline_status_ == PIPELINE_OK); } @@ -246,8 +250,7 @@ void PipelineIntegrationTestBase::CreateDemuxer( new MediaLog())); } -scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer( - Decryptor* decryptor) { +scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer() { ScopedVector<VideoDecoder> video_decoders; #if !defined(MEDIA_DISABLE_LIBVPX) video_decoders.push_back( @@ -257,14 +260,9 @@ scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer( new FFmpegVideoDecoder(message_loop_.message_loop_proxy())); // Disable frame dropping if hashing is enabled. - scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl( - message_loop_.message_loop_proxy(), - video_decoders.Pass(), - base::Bind(&PipelineIntegrationTestBase::SetDecryptor, - base::Unretained(this), - decryptor), - false, - new MediaLog())); + scoped_ptr<VideoRenderer> video_renderer( + new VideoRendererImpl(message_loop_.message_loop_proxy(), + video_decoders.Pass(), false, new MediaLog())); if (!clockless_playback_) { audio_sink_ = new NullAudioSink(message_loop_.message_loop_proxy()); @@ -290,12 +288,7 @@ scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer( (clockless_playback_) ? static_cast<AudioRendererSink*>(clockless_audio_sink_.get()) : audio_sink_.get(), - audio_decoders.Pass(), - base::Bind(&PipelineIntegrationTestBase::SetDecryptor, - base::Unretained(this), - decryptor), - hardware_config_, - new MediaLog())); + audio_decoders.Pass(), hardware_config_, new MediaLog())); if (hashing_enabled_) audio_sink_->StartAudioHashForTesting(); @@ -314,16 +307,6 @@ scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer( return renderer_impl.Pass(); } -void PipelineIntegrationTestBase::SetDecryptor( - Decryptor* decryptor, - const DecryptorReadyCB& decryptor_ready_cb) { - decryptor_ready_cb.Run( - decryptor, - base::Bind(&PipelineIntegrationTestBase::DecryptorAttached, - base::Unretained(this))); - EXPECT_CALL(*this, DecryptorAttached(true)); -} - void PipelineIntegrationTestBase::OnVideoFramePaint( const scoped_refptr<VideoFrame>& frame) { last_video_frame_format_ = frame->format(); diff --git a/media/filters/pipeline_integration_test_base.h b/media/filters/pipeline_integration_test_base.h index 3db6efa..d05a9ed 100644 --- a/media/filters/pipeline_integration_test_base.h +++ b/media/filters/pipeline_integration_test_base.h @@ -25,7 +25,7 @@ class FilePath; namespace media { -class Decryptor; +class CdmContext; // Empty MD5 hash string. Used to verify empty video tracks. extern const char kNullVideoHash[]; @@ -72,7 +72,7 @@ class PipelineIntegrationTestBase { // Initialize the pipeline and ignore any status updates. Useful for testing // invalid audio/video clips which don't have deterministic results. bool Start(const base::FilePath& file_path); - bool Start(const base::FilePath& file_path, Decryptor* decryptor); + bool Start(const base::FilePath& file_path, CdmContext* cdm_context); void Play(); void Pause(); @@ -132,10 +132,8 @@ class PipelineIntegrationTestBase { void CreateDemuxer(const base::FilePath& file_path); // Creates and returns a Renderer. - scoped_ptr<Renderer> CreateRenderer(Decryptor* decryptor); + scoped_ptr<Renderer> CreateRenderer(); - void SetDecryptor(Decryptor* decryptor, - const DecryptorReadyCB& decryptor_ready_cb); void OnVideoFramePaint(const scoped_refptr<VideoFrame>& frame); MOCK_METHOD1(OnMetadata, void(PipelineMetadata)); diff --git a/media/filters/renderer_impl.cc b/media/filters/renderer_impl.cc index f45007d..a5bda5a 100644 --- a/media/filters/renderer_impl.cc +++ b/media/filters/renderer_impl.cc @@ -32,6 +32,7 @@ RendererImpl::RendererImpl( video_buffering_state_(BUFFERING_HAVE_NOTHING), audio_ended_(false), video_ended_(false), + cdm_context_(nullptr), underflow_disabled_for_testing_(false), clockless_video_playback_enabled_for_testing_(false), weak_factory_(this), @@ -82,6 +83,23 @@ void RendererImpl::Initialize(DemuxerStreamProvider* demuxer_stream_provider, InitializeAudioRenderer(); } +void RendererImpl::SetCdm(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) { + DVLOG(1) << __FUNCTION__; + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(cdm_context); + + cdm_context_ = cdm_context; + + if (decryptor_ready_cb_.is_null()) { + cdm_attached_cb.Run(true); + return; + } + + base::ResetAndReturn(&decryptor_ready_cb_) + .Run(cdm_context->GetDecryptor(), cdm_attached_cb); +} + void RendererImpl::Flush(const base::Closure& flush_cb) { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); @@ -153,14 +171,6 @@ bool RendererImpl::HasVideo() { return video_renderer_ != NULL; } -void RendererImpl::SetCdm(MediaKeys* cdm) { - DVLOG(1) << __FUNCTION__; - DCHECK(task_runner_->BelongsToCurrentThread()); - // TODO(xhwang): Explore to possibility to move CDM setting from - // WebMediaPlayerImpl to this class. See http://crbug.com/401264 - NOTREACHED(); -} - void RendererImpl::DisableUnderflowForTesting() { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); @@ -191,6 +201,29 @@ base::TimeDelta RendererImpl::GetMediaTimeForSyncingVideo() { return time_source_->CurrentMediaTimeForSyncingVideo(); } +void RendererImpl::SetDecryptorReadyCallback( + const DecryptorReadyCB& decryptor_ready_cb) { + // Cancels the previous decryptor request. + if (decryptor_ready_cb.is_null()) { + if (!decryptor_ready_cb_.is_null()) { + base::ResetAndReturn(&decryptor_ready_cb_) + .Run(nullptr, base::Bind(IgnoreCdmAttached)); + } + return; + } + + // We initialize audio and video decoders in sequence. + DCHECK(decryptor_ready_cb_.is_null()); + + if (cdm_context_) { + decryptor_ready_cb.Run(cdm_context_->GetDecryptor(), + base::Bind(IgnoreCdmAttached)); + return; + } + + decryptor_ready_cb_ = decryptor_ready_cb; +} + void RendererImpl::InitializeAudioRenderer() { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); @@ -209,8 +242,8 @@ void RendererImpl::InitializeAudioRenderer() { // Note: After the initialization of a renderer, error events from it may // happen at any time and all future calls must guard against STATE_ERROR. audio_renderer_->Initialize( - demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), - done_cb, + demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), done_cb, + base::Bind(&RendererImpl::SetDecryptorReadyCallback, weak_this_), base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, &audio_buffering_state_), @@ -252,11 +285,10 @@ void RendererImpl::InitializeVideoRenderer() { } video_renderer_->Initialize( - demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), - done_cb, + demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), done_cb, + base::Bind(&RendererImpl::SetDecryptorReadyCallback, weak_this_), base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), - base::Bind(&RendererImpl::OnBufferingStateChanged, - weak_this_, + base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, &video_buffering_state_), base::ResetAndReturn(&paint_cb_), base::Bind(&RendererImpl::OnVideoRendererEnded, weak_this_), diff --git a/media/filters/renderer_impl.h b/media/filters/renderer_impl.h index 734113b..1000fa8 100644 --- a/media/filters/renderer_impl.h +++ b/media/filters/renderer_impl.h @@ -13,6 +13,7 @@ #include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "media/base/buffering_state.h" +#include "media/base/decryptor.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" #include "media/base/renderer.h" @@ -39,7 +40,7 @@ class MEDIA_EXPORT RendererImpl : public Renderer { scoped_ptr<AudioRenderer> audio_renderer, scoped_ptr<VideoRenderer> video_renderer); - ~RendererImpl() override; + ~RendererImpl() final; // Renderer implementation. void Initialize(DemuxerStreamProvider* demuxer_stream_provider, @@ -48,15 +49,16 @@ class MEDIA_EXPORT RendererImpl : public Renderer { const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, const base::Closure& ended_cb, - const PipelineStatusCB& error_cb) override; - void Flush(const base::Closure& flush_cb) override; - void StartPlayingFrom(base::TimeDelta time) override; - void SetPlaybackRate(float playback_rate) override; - void SetVolume(float volume) override; - base::TimeDelta GetMediaTime() override; - bool HasAudio() override; - bool HasVideo() override; - void SetCdm(MediaKeys* cdm) override; + const PipelineStatusCB& error_cb) final; + void SetCdm(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) final; + void Flush(const base::Closure& flush_cb) final; + void StartPlayingFrom(base::TimeDelta time) final; + void SetPlaybackRate(float playback_rate) final; + void SetVolume(float volume) final; + base::TimeDelta GetMediaTime() final; + bool HasAudio() final; + bool HasVideo() final; // Helper functions for testing purposes. Must be called before Initialize(). void DisableUnderflowForTesting(); @@ -73,6 +75,12 @@ class MEDIA_EXPORT RendererImpl : public Renderer { base::TimeDelta GetMediaTimeForSyncingVideo(); + // Requests that this object notifies when a decryptor is ready through the + // |decryptor_ready_cb| provided. + // If |decryptor_ready_cb| is null, the existing callback will be fired with + // nullptr immediately and reset. + void SetDecryptorReadyCallback(const DecryptorReadyCB& decryptor_ready_cb); + // Helper functions and callbacks for Initialize(). void InitializeAudioRenderer(); void OnAudioRendererInitializeDone(PipelineStatus status); @@ -150,6 +158,16 @@ class MEDIA_EXPORT RendererImpl : public Renderer { bool audio_ended_; bool video_ended_; + CdmContext* cdm_context_; + + // Callback registered by filters (decoder or demuxer) to be informed of a + // Decryptor. + // Note: We could have multiple filters registering this callback. One + // callback is okay because: + // 1, We always initialize filters in sequence. + // 2, Filter initialization will not finish until this callback is satisfied. + DecryptorReadyCB decryptor_ready_cb_; + bool underflow_disabled_for_testing_; bool clockless_video_playback_enabled_for_testing_; diff --git a/media/filters/renderer_impl_unittest.cc b/media/filters/renderer_impl_unittest.cc index 805b5c6..ec8e382 100644 --- a/media/filters/renderer_impl_unittest.cc +++ b/media/filters/renderer_impl_unittest.cc @@ -88,20 +88,18 @@ class RendererImplTest : public ::testing::Test { // Sets up expectations to allow the audio renderer to initialize. void SetAudioRendererInitializeExpectations(PipelineStatus status) { EXPECT_CALL(*audio_renderer_, - Initialize(audio_stream_.get(), _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<3>(&audio_buffering_state_cb_), - SaveArg<4>(&audio_ended_cb_), - SaveArg<5>(&audio_error_cb_), - RunCallback<1>(status))); + Initialize(audio_stream_.get(), _, _, _, _, _, _)) + .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_), + SaveArg<5>(&audio_ended_cb_), + SaveArg<6>(&audio_error_cb_), RunCallback<1>(status))); } // Sets up expectations to allow the video renderer to initialize. void SetVideoRendererInitializeExpectations(PipelineStatus status) { EXPECT_CALL(*video_renderer_, - Initialize(video_stream_.get(), _, _, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<3>(&video_buffering_state_cb_), - SaveArg<5>(&video_ended_cb_), - RunCallback<1>(status))); + Initialize(video_stream_.get(), _, _, _, _, _, _, _, _)) + .WillOnce(DoAll(SaveArg<4>(&video_buffering_state_cb_), + SaveArg<6>(&video_ended_cb_), RunCallback<1>(status))); } void InitializeAndExpect(PipelineStatus start_status) { @@ -438,10 +436,10 @@ TEST_F(RendererImplTest, ErrorDuringInitialize) { // Force an audio error to occur during video renderer initialization. EXPECT_CALL(*video_renderer_, - Initialize(video_stream_.get(), _, _, _, _, _, _, _)) + Initialize(video_stream_.get(), _, _, _, _, _, _, _, _)) .WillOnce(DoAll(AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE), - SaveArg<3>(&video_buffering_state_cb_), - SaveArg<5>(&video_ended_cb_), + SaveArg<4>(&video_buffering_state_cb_), + SaveArg<6>(&video_ended_cb_), RunCallback<1>(PIPELINE_OK))); InitializeAndExpect(PIPELINE_ERROR_DECODE); diff --git a/media/filters/video_decoder_selector_unittest.cc b/media/filters/video_decoder_selector_unittest.cc index a508aa9..f2dabdf 100644 --- a/media/filters/video_decoder_selector_unittest.cc +++ b/media/filters/video_decoder_selector_unittest.cc @@ -87,13 +87,6 @@ class VideoDecoderSelectorTest : public ::testing::Test { void InitializeDecoderSelector(DecryptorCapability decryptor_capability, int num_decoders) { - SetDecryptorReadyCB set_decryptor_ready_cb; - if (decryptor_capability != kNoDecryptor) { - set_decryptor_ready_cb = - base::Bind(&VideoDecoderSelectorTest::SetDecryptorReadyCallback, - base::Unretained(this)); - } - if (decryptor_capability == kDecryptOnly || decryptor_capability == kDecryptAndDecode) { EXPECT_CALL(*this, SetDecryptorReadyCallback(_)) @@ -116,6 +109,10 @@ class VideoDecoderSelectorTest : public ::testing::Test { // Set and cancel DecryptorReadyCB but the callback is never fired. EXPECT_CALL(*this, SetDecryptorReadyCallback(_)) .Times(2); + } else if (decryptor_capability == kNoDecryptor) { + EXPECT_CALL(*this, SetDecryptorReadyCallback(_)) + .WillRepeatedly( + RunCallback<0>(nullptr, base::Bind(&IgnoreCdmAttached))); } DCHECK_GE(all_decoders_.size(), static_cast<size_t>(num_decoders)); @@ -123,14 +120,14 @@ class VideoDecoderSelectorTest : public ::testing::Test { all_decoders_.begin() + num_decoders, all_decoders_.end()); decoder_selector_.reset(new VideoDecoderSelector( - message_loop_.message_loop_proxy(), - all_decoders_.Pass(), - set_decryptor_ready_cb)); + message_loop_.message_loop_proxy(), all_decoders_.Pass())); } void SelectDecoder() { decoder_selector_->SelectDecoder( demuxer_stream_.get(), + base::Bind(&VideoDecoderSelectorTest::SetDecryptorReadyCallback, + base::Unretained(this)), base::Bind(&VideoDecoderSelectorTest::MockOnDecoderSelected, base::Unretained(this)), base::Bind(&VideoDecoderSelectorTest::FrameReady, diff --git a/media/filters/video_frame_stream_unittest.cc b/media/filters/video_frame_stream_unittest.cc index 3791ed1..8b393af 100644 --- a/media/filters/video_frame_stream_unittest.cc +++ b/media/filters/video_frame_stream_unittest.cc @@ -79,11 +79,7 @@ class VideoFrameStreamTest decoders.push_back(decoder_); video_frame_stream_.reset(new VideoFrameStream( - message_loop_.message_loop_proxy(), - decoders.Pass(), - base::Bind(&VideoFrameStreamTest::SetDecryptorReadyCallback, - base::Unretained(this)), - new MediaLog())); + message_loop_.message_loop_proxy(), decoders.Pass(), new MediaLog())); // Decryptor can only decrypt (not decrypt-and-decode) so that // DecryptingDemuxerStream will be used. @@ -131,9 +127,11 @@ class VideoFrameStreamTest void InitializeVideoFrameStream() { pending_initialize_ = true; video_frame_stream_->Initialize( - demuxer_stream_.get(), - base::Bind(&VideoFrameStreamTest::OnStatistics, base::Unretained(this)), - base::Bind(&VideoFrameStreamTest::OnInitialized, + demuxer_stream_.get(), base::Bind(&VideoFrameStreamTest::OnInitialized, + base::Unretained(this)), + base::Bind(&VideoFrameStreamTest::SetDecryptorReadyCallback, + base::Unretained(this)), + base::Bind(&VideoFrameStreamTest::OnStatistics, base::Unretained(this))); message_loop_.RunUntilIdle(); } diff --git a/media/filters/video_renderer_impl.cc b/media/filters/video_renderer_impl.cc index 26f10cf..1ad10d3 100644 --- a/media/filters/video_renderer_impl.cc +++ b/media/filters/video_renderer_impl.cc @@ -22,14 +22,11 @@ namespace media { VideoRendererImpl::VideoRendererImpl( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, ScopedVector<VideoDecoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb, bool drop_frames, const scoped_refptr<MediaLog>& media_log) : task_runner_(task_runner), - video_frame_stream_(new VideoFrameStream(task_runner, - decoders.Pass(), - set_decryptor_ready_cb, - media_log)), + video_frame_stream_( + new VideoFrameStream(task_runner, decoders.Pass(), media_log)), low_delay_(false), received_end_of_stream_(false), rendered_end_of_stream_(false), @@ -103,14 +100,16 @@ void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { AttemptRead_Locked(); } -void VideoRendererImpl::Initialize(DemuxerStream* stream, - const PipelineStatusCB& init_cb, - const StatisticsCB& statistics_cb, - const BufferingStateCB& buffering_state_cb, - const PaintCB& paint_cb, - const base::Closure& ended_cb, - const PipelineStatusCB& error_cb, - const TimeDeltaCB& get_time_cb) { +void VideoRendererImpl::Initialize( + DemuxerStream* stream, + const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, + const StatisticsCB& statistics_cb, + const BufferingStateCB& buffering_state_cb, + const PaintCB& paint_cb, + const base::Closure& ended_cb, + const PipelineStatusCB& error_cb, + const TimeDeltaCB& get_time_cb) { DCHECK(task_runner_->BelongsToCurrentThread()); base::AutoLock auto_lock(lock_); DCHECK(stream); @@ -138,9 +137,9 @@ void VideoRendererImpl::Initialize(DemuxerStream* stream, state_ = kInitializing; video_frame_stream_->Initialize( - stream, statistics_cb, - base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized, - weak_factory_.GetWeakPtr())); + stream, base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized, + weak_factory_.GetWeakPtr()), + set_decryptor_ready_cb, statistics_cb); } void VideoRendererImpl::OnVideoFrameStreamInitialized(bool success) { diff --git a/media/filters/video_renderer_impl.h b/media/filters/video_renderer_impl.h index 20235e8..b003c4c 100644 --- a/media/filters/video_renderer_impl.h +++ b/media/filters/video_renderer_impl.h @@ -39,7 +39,6 @@ class MEDIA_EXPORT VideoRendererImpl public: // |decoders| contains the VideoDecoders to use when initializing. // - // // Implementors should avoid doing any sort of heavy work in this method and // instead post a task to a common/worker thread to handle rendering. Slowing // down the video thread may result in losing synchronization with audio. @@ -48,7 +47,6 @@ class MEDIA_EXPORT VideoRendererImpl VideoRendererImpl( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, ScopedVector<VideoDecoder> decoders, - const SetDecryptorReadyCB& set_decryptor_ready_cb, bool drop_frames, const scoped_refptr<MediaLog>& media_log); ~VideoRendererImpl() override; @@ -56,6 +54,7 @@ class MEDIA_EXPORT VideoRendererImpl // VideoRenderer implementation. void Initialize(DemuxerStream* stream, const PipelineStatusCB& init_cb, + const SetDecryptorReadyCB& set_decryptor_ready_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, diff --git a/media/filters/video_renderer_impl_unittest.cc b/media/filters/video_renderer_impl_unittest.cc index 6b34fe5..ec0c52e 100644 --- a/media/filters/video_renderer_impl_unittest.cc +++ b/media/filters/video_renderer_impl_unittest.cc @@ -50,12 +50,9 @@ class VideoRendererImplTest : public ::testing::Test { ScopedVector<VideoDecoder> decoders; decoders.push_back(decoder_); - renderer_.reset(new VideoRendererImpl( - message_loop_.message_loop_proxy(), - decoders.Pass(), - media::SetDecryptorReadyCB(), - true, - new MediaLog())); + renderer_.reset(new VideoRendererImpl(message_loop_.message_loop_proxy(), + decoders.Pass(), true, + new MediaLog())); demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal()); @@ -98,15 +95,13 @@ class VideoRendererImplTest : public ::testing::Test { EXPECT_CALL(*decoder_, Initialize(_, _, _, _)).WillOnce( DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(decoder_status))); renderer_->Initialize( - &demuxer_stream_, - status_cb, + &demuxer_stream_, status_cb, media::SetDecryptorReadyCB(), base::Bind(&VideoRendererImplTest::OnStatisticsUpdate, base::Unretained(this)), base::Bind(&StrictMock<MockCB>::BufferingStateChange, base::Unretained(&mock_cb_)), base::Bind(&StrictMock<MockCB>::Display, base::Unretained(&mock_cb_)), - ended_event_.GetClosure(), - error_event_.GetPipelineStatusCB(), + ended_event_.GetClosure(), error_event_.GetPipelineStatusCB(), base::Bind(&VideoRendererImplTest::GetTime, base::Unretained(this))); } diff --git a/media/mojo/services/mojo_renderer_impl.cc b/media/mojo/services/mojo_renderer_impl.cc index c51e6b4..4645bbd 100644 --- a/media/mojo/services/mojo_renderer_impl.cc +++ b/media/mojo/services/mojo_renderer_impl.cc @@ -80,6 +80,14 @@ void MojoRendererImpl::Initialize( weak_factory_.GetWeakPtr()))); } +void MojoRendererImpl::SetCdm(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) { + DVLOG(1) << __FUNCTION__; + DCHECK(task_runner_->BelongsToCurrentThread()); + NOTIMPLEMENTED(); + cdm_attached_cb.Run(false); +} + void MojoRendererImpl::Flush(const base::Closure& flush_cb) { DVLOG(2) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); @@ -129,12 +137,6 @@ bool MojoRendererImpl::HasVideo() { return !!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO); } -void MojoRendererImpl::SetCdm(MediaKeys* cdm) { - DVLOG(1) << __FUNCTION__; - DCHECK(task_runner_->BelongsToCurrentThread()); - NOTIMPLEMENTED(); -} - void MojoRendererImpl::OnTimeUpdate(int64_t time_usec, int64_t max_time_usec) { DVLOG(3) << __FUNCTION__ << ": " << time_usec << ", " << max_time_usec; diff --git a/media/mojo/services/mojo_renderer_impl.h b/media/mojo/services/mojo_renderer_impl.h index 7c0f9c6..6d24b6e 100644 --- a/media/mojo/services/mojo_renderer_impl.h +++ b/media/mojo/services/mojo_renderer_impl.h @@ -45,6 +45,8 @@ class MojoRendererImpl : public Renderer, public mojo::MediaRendererClient { const PaintCB& paint_cb, const base::Closure& ended_cb, const PipelineStatusCB& error_cb) override; + void SetCdm(CdmContext* cdm_context, + const CdmAttachedCB& cdm_attached_cb) override; void Flush(const base::Closure& flush_cb) override; void StartPlayingFrom(base::TimeDelta time) override; void SetPlaybackRate(float playback_rate) override; @@ -52,7 +54,6 @@ class MojoRendererImpl : public Renderer, public mojo::MediaRendererClient { base::TimeDelta GetMediaTime() override; bool HasAudio() override; bool HasVideo() override; - void SetCdm(MediaKeys* cdm) override; // mojo::MediaRendererClient implementation. void OnTimeUpdate(int64_t time_usec, int64_t max_time_usec) override; diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc index 25a812b..ee557dd 100644 --- a/media/mojo/services/mojo_renderer_service.cc +++ b/media/mojo/services/mojo_renderer_service.cc @@ -74,23 +74,18 @@ MojoRendererService::MojoRendererService() audio_renderer_sink_ = renderer_config->GetAudioRendererSink(); scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl( - task_runner, - audio_renderer_sink_.get(), + task_runner, audio_renderer_sink_.get(), renderer_config->GetAudioDecoders( task_runner, base::Bind(&LogMediaSourceError, media_log)).Pass(), - SetDecryptorReadyCB(), - renderer_config->GetAudioHardwareConfig(), - media_log)); + renderer_config->GetAudioHardwareConfig(), media_log)); scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl( task_runner, renderer_config->GetVideoDecoders( task_runner, base::Bind(&LogMediaSourceError, media_log)).Pass(), - SetDecryptorReadyCB(), - true, - media_log)); + true, media_log)); // Create renderer. renderer_.reset(new RendererImpl( diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index 9dfe601..f065387 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -116,12 +116,8 @@ void InitPipeline( bool /* enable_audio */) { ScopedVector<media::VideoDecoder> video_decoders; video_decoders.push_back(new media::FFmpegVideoDecoder(task_runner)); - scoped_ptr<media::VideoRenderer> video_renderer( - new media::VideoRendererImpl(task_runner, - video_decoders.Pass(), - media::SetDecryptorReadyCB(), - true, - new media::MediaLog())); + scoped_ptr<media::VideoRenderer> video_renderer(new media::VideoRendererImpl( + task_runner, video_decoders.Pass(), true, new media::MediaLog())); ScopedVector<media::AudioDecoder> audio_decoders; audio_decoders.push_back(new media::FFmpegAudioDecoder(task_runner, @@ -134,13 +130,9 @@ void InitPipeline( 512); media::AudioHardwareConfig hardware_config(out_params, out_params); - scoped_ptr<media::AudioRenderer> audio_renderer( - new media::AudioRendererImpl(task_runner, - new media::NullAudioSink(task_runner), - audio_decoders.Pass(), - media::SetDecryptorReadyCB(), - hardware_config, - new media::MediaLog())); + scoped_ptr<media::AudioRenderer> audio_renderer(new media::AudioRendererImpl( + task_runner, new media::NullAudioSink(task_runner), audio_decoders.Pass(), + hardware_config, new media::MediaLog())); scoped_ptr<media::Renderer> renderer(new media::RendererImpl( task_runner, audio_renderer.Pass(), video_renderer.Pass())); |