[MM]EME implementation using EncryptedMediaPlayerSupport.
authorsangdeug.kim <sangdeug.kim@samsung.com>
Wed, 21 Jan 2015 10:58:31 +0000 (19:58 +0900)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
SHA:aaaae22e commit is included to fix crash issue.
(Refactor MediaSourceDelegate destruction.)
https://codereview.chromium.org/605013002

Together with: I0e3d41130d1b66e32e248a2ac6495c5d52cd9e8f

Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=8682
Reviewed by: Min-Soo Koo, SeungSeop Park, Venugopal S M

Change-Id: I9c065ae4a9b442bf5141011e66aa7f4135cc8b65
Signed-off-by: sangdeug.kim <sangdeug.kim@samsung.com>
tizen_src/impl/content/renderer/media/tizen/media_source_delegate_tizen.cc
tizen_src/impl/content/renderer/media/tizen/media_source_delegate_tizen.h
tizen_src/impl/media/base/tizen/webmediaplayer_tizen.cc
tizen_src/impl/media/base/tizen/webmediaplayer_tizen.h

index 914d0ae..8a14751 100644 (file)
@@ -57,15 +57,21 @@ MediaSourceDelegateTizen::~MediaSourceDelegateTizen() {
   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;
 
@@ -95,8 +101,11 @@ void MediaSourceDelegateTizen::InitializeDemuxer() {
 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() {
@@ -113,11 +122,6 @@ void MediaSourceDelegateTizen::OnDemuxerError(
     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());
@@ -128,21 +132,84 @@ void MediaSourceDelegateTizen::OnDemuxerInitDone(
   }
   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_) {
@@ -194,14 +261,13 @@ void MediaSourceDelegateTizen::OnReadFromDemuxer(
   }
 }
 
-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;
   }
 
@@ -219,10 +285,11 @@ void MediaSourceDelegateTizen::Destroy() {
   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_);
 
@@ -230,6 +297,8 @@ void MediaSourceDelegateTizen::StopDemuxer() {
   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());
@@ -237,18 +306,7 @@ void MediaSourceDelegateTizen::StopDemuxer() {
   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() {
@@ -404,6 +462,36 @@ void MediaSourceDelegateTizen::OnDemuxerSeekDone(
     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) {
index 1caf259..8727771 100644 (file)
@@ -10,6 +10,7 @@
 #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 {
@@ -23,14 +24,6 @@ public:
       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,
@@ -61,14 +54,16 @@ public:
 
   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.
@@ -97,10 +92,10 @@ public:
   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(
@@ -109,6 +104,19 @@ public:
       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_;
@@ -129,6 +137,11 @@ public:
   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_;
index 76f7b62..a6faa8b 100644 (file)
@@ -50,9 +50,10 @@ GURL GetCleanURL(std::string url) {
 
 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),
@@ -85,8 +86,11 @@ WebMediaPlayerTizen::WebMediaPlayerTizen(
       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.
@@ -116,6 +120,16 @@ WebMediaPlayerTizen::~WebMediaPlayerTizen() {
   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,
@@ -134,9 +148,15 @@ 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,
@@ -166,6 +186,52 @@ void WebMediaPlayerTizen::load(LoadType load_type,
                        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);
index f404ae1..cb1a12a 100644 (file)
 #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 {
@@ -45,9 +46,10 @@ class WebMediaPlayerTizen
   // |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();
 
@@ -110,6 +112,30 @@ class 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);
 
@@ -146,7 +172,7 @@ class WebMediaPlayerTizen
   // 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_;
@@ -177,8 +203,7 @@ class WebMediaPlayerTizen
   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_|.
@@ -211,6 +236,7 @@ class WebMediaPlayerTizen
 
   // 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);