summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/base/audio_renderer.h5
-rw-r--r--media/base/cdm_context.cc3
-rw-r--r--media/base/cdm_context.h8
-rw-r--r--media/base/mock_filters.h36
-rw-r--r--media/base/pipeline.cc25
-rw-r--r--media/base/pipeline.h15
-rw-r--r--media/base/renderer.h10
-rw-r--r--media/base/video_renderer.h5
-rw-r--r--media/blink/cdm_session_adapter.cc10
-rw-r--r--media/blink/cdm_session_adapter.h12
-rw-r--r--media/blink/encrypted_media_player_support.cc108
-rw-r--r--media/blink/encrypted_media_player_support.h37
-rw-r--r--media/blink/webcontentdecryptionmodule_impl.cc10
-rw-r--r--media/blink/webcontentdecryptionmodule_impl.h20
-rw-r--r--media/blink/webmediaplayer_impl.cc61
-rw-r--r--media/blink/webmediaplayer_impl.h10
-rw-r--r--media/cdm/proxy_decryptor.cc10
-rw-r--r--media/cdm/proxy_decryptor.h15
-rw-r--r--media/filters/audio_decoder_selector_unittest.cc17
-rw-r--r--media/filters/audio_renderer_impl.cc27
-rw-r--r--media/filters/audio_renderer_impl.h5
-rw-r--r--media/filters/audio_renderer_impl_unittest.cc10
-rw-r--r--media/filters/decoder_selector.cc12
-rw-r--r--media/filters/decoder_selector.h13
-rw-r--r--media/filters/decoder_stream.cc18
-rw-r--r--media/filters/decoder_stream.h8
-rw-r--r--media/filters/pipeline_integration_test.cc46
-rw-r--r--media/filters/pipeline_integration_test_base.cc49
-rw-r--r--media/filters/pipeline_integration_test_base.h8
-rw-r--r--media/filters/renderer_impl.cc60
-rw-r--r--media/filters/renderer_impl.h38
-rw-r--r--media/filters/renderer_impl_unittest.cc22
-rw-r--r--media/filters/video_decoder_selector_unittest.cc17
-rw-r--r--media/filters/video_frame_stream_unittest.cc14
-rw-r--r--media/filters/video_renderer_impl.cc31
-rw-r--r--media/filters/video_renderer_impl.h3
-rw-r--r--media/filters/video_renderer_impl_unittest.cc15
-rw-r--r--media/mojo/services/mojo_renderer_impl.cc14
-rw-r--r--media/mojo/services/mojo_renderer_impl.h3
-rw-r--r--media/mojo/services/mojo_renderer_service.cc11
-rw-r--r--media/tools/player_x11/player_x11.cc18
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()));