DCHECK(!chunk_demuxer_);
DCHECK(!audio_stream_);
DCHECK(!video_stream_);
+ DCHECK(!audio_decrypting_demuxer_stream_);
+ DCHECK(!video_decrypting_demuxer_stream_);
}
void MediaSourceDelegateTizen::InitializeMediaSource(
const MediaSourceOpenedCB& media_source_opened_cb,
+ const media::Demuxer::NeedKeyCB& need_key_cb,
+ const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
const UpdateNetworkStateCB& update_network_state_cb,
const DurationChangeCB& duration_change_cb) {
DCHECK(main_loop_->BelongsToCurrentThread());
DCHECK(!media_source_opened_cb.is_null());
media_source_opened_cb_ = media_source_opened_cb;
+ need_key_cb_ = need_key_cb;
+ set_decryptor_ready_cb_ = set_decryptor_ready_cb;
update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb);
duration_change_cb_ = duration_change_cb;
void MediaSourceDelegateTizen::OnNeedKey(
const std::string& type,
const std::vector<uint8>& init_data) {
- // FIXME: Need to check the functionality of this method.
- NOTIMPLEMENTED();
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ if (need_key_cb_.is_null()) {
+ return;
+ }
+ need_key_cb_.Run(type, init_data);
}
void MediaSourceDelegateTizen::OnDemuxerOpened() {
update_network_state_cb_.Run(PipelineErrorToNetworkState(status));
}
-bool MediaSourceDelegateTizen::CanNotifyDemuxerReady() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- return is_demuxer_ready_;
-}
-
void MediaSourceDelegateTizen::OnDemuxerInitDone(
media::PipelineStatus status) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
}
audio_stream_ = chunk_demuxer_->GetStream(media::DemuxerStream::AUDIO);
video_stream_ = chunk_demuxer_->GetStream(media::DemuxerStream::VIDEO);
- if ((audio_stream_ && audio_stream_->audio_decoder_config().is_encrypted())
- || (video_stream_ && video_stream_->video_decoder_config().is_encrypted()
- )) {
- OnDemuxerError(media::PIPELINE_ERROR_DECODE);
+ if (audio_stream_ && audio_stream_->audio_decoder_config().is_encrypted() &&
+ !set_decryptor_ready_cb_.is_null()) {
+ InitAudioDecryptingDemuxerStream();
+ return;
+ }
+ if (video_stream_ && video_stream_->video_decoder_config().is_encrypted() &&
+ !set_decryptor_ready_cb_.is_null()) {
+ InitVideoDecryptingDemuxerStream();
return;
}
-
// Notify demuxer ready when both streams are not encrypted.
is_demuxer_ready_ = true;
NotifyDemuxerReady();
}
+void MediaSourceDelegateTizen::InitAudioDecryptingDemuxerStream() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
+ media_task_runner_, set_decryptor_ready_cb_));
+
+ audio_decrypting_demuxer_stream_->Initialize(
+ audio_stream_,
+ base::Bind(&MediaSourceDelegateTizen::OnAudioDecryptingDemuxerStreamInitDone,
+ media_weak_factory_.GetWeakPtr()));
+}
+
+void MediaSourceDelegateTizen::InitVideoDecryptingDemuxerStream() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
+ media_task_runner_, set_decryptor_ready_cb_));
+
+ video_decrypting_demuxer_stream_->Initialize(
+ video_stream_,
+ base::Bind(&MediaSourceDelegateTizen::OnVideoDecryptingDemuxerStreamInitDone,
+ media_weak_factory_.GetWeakPtr()));
+}
+
+
+void MediaSourceDelegateTizen::OnAudioDecryptingDemuxerStreamInitDone(
+ media::PipelineStatus status) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(chunk_demuxer_);
+
+ if (status != media::PIPELINE_OK)
+ audio_decrypting_demuxer_stream_.reset();
+ else
+ audio_stream_ = audio_decrypting_demuxer_stream_.get();
+
+ if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) {
+ InitVideoDecryptingDemuxerStream();
+ return;
+ }
+
+ // Try to notify demuxer ready when audio DDS initialization finished and
+ // video is not encrypted.
+ is_demuxer_ready_ = true;
+ NotifyDemuxerReady();
+}
+
+void MediaSourceDelegateTizen::OnVideoDecryptingDemuxerStreamInitDone(
+ media::PipelineStatus status) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(chunk_demuxer_);
+
+ if (status != media::PIPELINE_OK)
+ video_decrypting_demuxer_stream_.reset();
+ else
+ video_stream_ = video_decrypting_demuxer_stream_.get();
+
+ // Try to notify demuxer ready when video DDS initialization finished.
+ is_demuxer_ready_ = true;
+ NotifyDemuxerReady();
+}
+
void MediaSourceDelegateTizen::NotifyDemuxerReady() {
DCHECK(media_task_runner_->BelongsToCurrentThread());
- DCHECK(CanNotifyDemuxerReady());
+ DCHECK(is_demuxer_ready_);
scoped_ptr<media::DemuxerConfigs> configs(new media::DemuxerConfigs());
if (audio_stream_) {
}
}
-void MediaSourceDelegateTizen::Destroy() {
+void MediaSourceDelegateTizen::Stop(const base::Closure& stop_cb) {
DCHECK(main_loop_->BelongsToCurrentThread());
VLOG(1) << "MediaSourceDelegateTizen::" << __FUNCTION__
<< ": Demuxer Client Id = " << demuxer_client_id_;
if (!chunk_demuxer_) {
DCHECK(!demuxer_client_);
- delete this;
return;
}
media_task_runner_->PostTask(
FROM_HERE,
base::Bind(&MediaSourceDelegateTizen::StopDemuxer,
- base::Unretained(this)));
+ base::Unretained(this),
+ stop_cb));
}
-void MediaSourceDelegateTizen::StopDemuxer() {
+void MediaSourceDelegateTizen::StopDemuxer(const base::Closure& stop_cb) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
DCHECK(chunk_demuxer_);
demuxer_client_ = NULL;
audio_stream_ = NULL;
video_stream_ = NULL;
+ audio_decrypting_demuxer_stream_.reset();
+ video_decrypting_demuxer_stream_.reset();
media_weak_factory_.InvalidateWeakPtrs();
DCHECK(!media_weak_factory_.HasWeakPtrs());
chunk_demuxer_->Stop();
chunk_demuxer_.reset();
- main_loop_->PostTask(
- FROM_HERE,
- base::Bind(&MediaSourceDelegateTizen::DeleteSelf,
- base::Unretained(this)));
-}
-
-void MediaSourceDelegateTizen::DeleteSelf() {
- DCHECK(main_loop_->BelongsToCurrentThread());
- VLOG(1) << "MediaSourceDelegateTizen::" << __FUNCTION__
- << ": Demuxer Client Id = " << demuxer_client_id_;
- chunk_demuxer_.reset();
- delete this;
+ stop_cb.Run();
}
void MediaSourceDelegateTizen::OnMediaConfigRequest() {
is_demuxer_seek_done_ = true;
demuxer_client_->DemuxerSeekDone(demuxer_client_id_, seek_time_);
}
+ ResetAudioDecryptingDemuxerStream();
+}
+
+void MediaSourceDelegateTizen::ResetAudioDecryptingDemuxerStream() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ if (audio_decrypting_demuxer_stream_) {
+ audio_decrypting_demuxer_stream_->Reset(
+ base::Bind(&MediaSourceDelegateTizen::ResetVideoDecryptingDemuxerStream,
+ media_weak_factory_.GetWeakPtr()));
+ return;
+ }
+ ResetVideoDecryptingDemuxerStream();
+}
+
+void MediaSourceDelegateTizen::ResetVideoDecryptingDemuxerStream() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ if (video_decrypting_demuxer_stream_) {
+ video_decrypting_demuxer_stream_->Reset(base::Bind(
+ &MediaSourceDelegateTizen::FinishResettingDecryptingDemuxerStreams,
+ media_weak_factory_.GetWeakPtr()));
+ return;
+ }
+ FinishResettingDecryptingDemuxerStreams();
+}
+
+void MediaSourceDelegateTizen::FinishResettingDecryptingDemuxerStreams() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(is_seeking_);
+ is_seeking_ = false;
+ demuxer_client_->DemuxerSeekDone(demuxer_client_id_, seek_time_);
}
void MediaSourceDelegateTizen::SetDuration(base::TimeDelta duration) {
#include "media/base/demuxer_stream.h"
#include "media/base/media_keys.h"
#include "media/filters/chunk_demuxer.h"
+#include "media/filters/decrypting_demuxer_stream.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
namespace content {
UpdateNetworkStateCB;
typedef base::Callback<void(double)> DurationChangeCB;
- class Destroyer {
- public:
- inline void operator()(void* media_source_delegate) const {
- static_cast<MediaSourceDelegateTizen*>(
- media_source_delegate)->Destroy();
- }
- };
-
MediaSourceDelegateTizen(
RendererDemuxerTizen* demuxer_client,
int demuxer_client_id,
void InitializeMediaSource(
const MediaSourceOpenedCB& media_source_opened_cb,
+ const media::Demuxer::NeedKeyCB& need_key_cb,
+ const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
const UpdateNetworkStateCB& update_network_state_cb,
const DurationChangeCB& duration_change_cb);
// Called when DemuxerStreamPlayer needs to read data from ChunkDemuxer.
void OnReadFromDemuxer(media::DemuxerStream::Type type);
- // Called by the Destroyer to destroy an instance of this object.
- void Destroy();
+ // Must be called explicitly before |this| can be destroyed.
+ void Stop(const base::Closure& stop_cb);
// In MSE case, calls ChunkDemuxer::StartWaitingForSeek(), sets the
// expectation that a regular seek will be arriving.
void OnDemuxerOpened();
void InitializeDemuxer();
void OnDemuxerInitDone(media::PipelineStatus status);
- void StopDemuxer();
- void DeleteSelf();
- bool CanNotifyDemuxerReady();
+ // Stops and clears objects on the media thread.
+ void StopDemuxer(const base::Closure& stop_cb);
+
void NotifyDemuxerReady();
void OnDurationChanged(const base::TimeDelta& duration);
void OnBufferReady(
const scoped_refptr<media::DecoderBuffer>& buffer);
void SeekInternal(const base::TimeDelta& seek_time);
+ // Initializes DecryptingDemuxerStreams if audio/video stream is encrypted.
+ void InitAudioDecryptingDemuxerStream();
+ void InitVideoDecryptingDemuxerStream();
+
+ // Callbacks for DecryptingDemuxerStream::Initialize().
+ void OnAudioDecryptingDemuxerStreamInitDone(media::PipelineStatus status);
+ void OnVideoDecryptingDemuxerStreamInitDone(media::PipelineStatus status);
+
+ // Runs on the media thread.
+ void ResetAudioDecryptingDemuxerStream();
+ void ResetVideoDecryptingDemuxerStream();
+ void FinishResettingDecryptingDemuxerStreams();
+
// Message loop for main renderer thread and corresponding weak pointer.
const scoped_refptr<base::MessageLoopProxy> main_loop_;
base::WeakPtrFactory<MediaSourceDelegateTizen> main_weak_factory_;
media::DemuxerStream* audio_stream_;
media::DemuxerStream* video_stream_;
+ media::SetDecryptorReadyCB set_decryptor_ready_cb_;
+ media::Demuxer::NeedKeyCB need_key_cb_;
+ scoped_ptr<media::DecryptingDemuxerStream> audio_decrypting_demuxer_stream_;
+ scoped_ptr<media::DecryptingDemuxerStream> video_decrypting_demuxer_stream_;
+
base::TimeDelta seek_time_;
bool pending_seek_;
bool is_seeking_;
WebMediaPlayerTizen::WebMediaPlayerTizen(
content::RendererMediaPlayerManagerTizen* manager,
- blink::WebFrame* frame,
+ blink::WebLocalFrame* frame,
blink::WebMediaPlayerClient* client,
base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
+ const WebMediaPlayerParams& params,
content::WrtUrlParseBase* wrt_url_parse)
: frame_(frame),
network_state_(blink::WebMediaPlayer::NetworkStateEmpty),
did_loading_progress_(false),
volume_(0),
gpu_factories_(content::RenderThreadImpl::current()->GetGpuFactories()),
+ encrypted_media_support_(
+ params.CreateEncryptedMediaPlayerSupport(client)),
wrt_url_parse_(wrt_url_parse) {
DCHECK(manager_);
+ DCHECK(encrypted_media_support_);
VLOG(1) << "WebMediaPlayerTizen::" << __FUNCTION__;
FrameAvailable_ = false;
// We want to be notified of |main_loop_| destruction.
if (base::MessageLoop::current())
base::MessageLoop::current()->RemoveDestructionObserver(this);
compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
+ if (media_source_delegate_) {
+ // Part of |media_source_delegate_| needs to be stopped
+ // on the media thread.
+ // Wait until |media_source_delegate_| is fully stopped
+ // before tearing down other objects.
+ base::WaitableEvent waiter(false, false);
+ media_source_delegate_->Stop(
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
+ waiter.Wait();
+ }
}
void WebMediaPlayerTizen::load(LoadType load_type,
demuxer_client_id = demuxer->GetNextDemuxerClientID();
media_source_delegate_.reset(new content::MediaSourceDelegateTizen(
demuxer, demuxer_client_id, media_task_runner_, media_log_.get()));
+ SetDecryptorReadyCB set_decryptor_ready_cb =
+ encrypted_media_support_->CreateSetDecryptorReadyCB();
+ Demuxer::NeedKeyCB need_key_cb =
+ encrypted_media_support_->CreateNeedKeyCB();
media_source_delegate_->InitializeMediaSource(
base::Bind(&WebMediaPlayerTizen::OnMediaSourceOpened,
weak_factory_.GetWeakPtr()),
+ need_key_cb,
+ set_decryptor_ready_cb,
base::Bind(&WebMediaPlayerTizen::SetNetworkState,
weak_factory_.GetWeakPtr()),
base::Bind(&WebMediaPlayerTizen::OnDurationChange,
demuxer_client_id);
}
+blink::WebMediaPlayer::MediaKeyException
+WebMediaPlayerTizen::generateKeyRequest(const blink::WebString& key_system,
+ const unsigned char* init_data,
+ unsigned init_data_length) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+
+ return encrypted_media_support_->GenerateKeyRequest(
+ frame_, key_system, init_data, init_data_length);
+}
+
+blink::WebMediaPlayer::MediaKeyException WebMediaPlayerTizen::addKey(
+ const blink::WebString& key_system,
+ const unsigned char* key,
+ unsigned key_length,
+ const unsigned char* init_data,
+ unsigned init_data_length,
+ const blink::WebString& session_id) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+
+ return encrypted_media_support_->AddKey(
+ key_system, key, key_length, init_data, init_data_length, session_id);
+}
+
+blink::WebMediaPlayer::MediaKeyException WebMediaPlayerTizen::cancelKeyRequest(
+ const blink::WebString& key_system,
+ const blink::WebString& session_id) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+
+ return encrypted_media_support_->CancelKeyRequest(key_system, session_id);
+}
+
+void WebMediaPlayerTizen::setContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+
+ encrypted_media_support_->SetContentDecryptionModule(cdm);
+}
+
+void WebMediaPlayerTizen::setContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm,
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+
+ encrypted_media_support_->SetContentDecryptionModule(cdm, result);
+}
+
void WebMediaPlayerTizen::OnMediaSourceOpened(
blink::WebMediaSource* web_media_source) {
client_->mediaSourceOpened(web_media_source);
#include "content/renderer/media/tizen/media_source_delegate_tizen.h"
#include "content/renderer/media/tizen/renderer_media_player_manager_tizen.h"
#include "media/blink/video_frame_compositor.h"
+#include "media/blink/webmediaplayer_params.h"
#include "media/filters/skcanvas_video_renderer.h"
namespace blink {
-class WebFrame;
+class WebLocalFrame;
}
namespace cc_blink {
// |proxy|.
WebMediaPlayerTizen(
content::RendererMediaPlayerManagerTizen* manager,
- blink::WebFrame* frame,
+ blink::WebLocalFrame* frame,
blink::WebMediaPlayerClient* client,
base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
+ const WebMediaPlayerParams& params,
content::WrtUrlParseBase* wrt_url_parse);
virtual ~WebMediaPlayerTizen();
// Method inherited from DestructionObserver.
virtual void WillDestroyCurrentMessageLoop() override {};
+ virtual MediaKeyException generateKeyRequest(
+ const blink::WebString& key_system,
+ const unsigned char* init_data,
+ unsigned init_data_length);
+
+ virtual MediaKeyException addKey(const blink::WebString& key_system,
+ const unsigned char* key,
+ unsigned key_length,
+ const unsigned char* init_data,
+ unsigned init_data_length,
+ const blink::WebString& session_id);
+
+ virtual MediaKeyException cancelKeyRequest(
+ 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);
+
void SetReadyState(WebMediaPlayer::ReadyState state);
void SetNetworkState(WebMediaPlayer::NetworkState state);
// Called whenever there is new frame to be painted.
void FrameReady(const scoped_refptr<media::VideoFrame>& frame);
- blink::WebFrame* frame_;
+ blink::WebLocalFrame* frame_;
blink::WebMediaPlayer::NetworkState network_state_;
blink::WebMediaPlayer::ReadyState ready_state_;
media::SkCanvasVideoRenderer skcanvas_video_renderer_;
base::WeakPtrFactory<WebMediaPlayerTizen> weak_factory_;
- scoped_ptr<content::MediaSourceDelegateTizen,
- content::MediaSourceDelegateTizen::Destroyer> media_source_delegate_;
+ scoped_ptr<content::MediaSourceDelegateTizen> media_source_delegate_;
MediaPlayerHostMsg_Initialize_Type player_type_;
// Player ID assigned by the |manager_|.
// Factories for supporting video accelerators. May be null.
scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
+ scoped_ptr<EncryptedMediaPlayerSupport> encrypted_media_support_;
content::WrtUrlParseBase* wrt_url_parse_;
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerTizen);