Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / rtc_video_decoder.cc
index dd043c2..ce1f24c 100644 (file)
 #include "base/metrics/histogram.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/task_runner_util.h"
 #include "content/child/child_thread.h"
 #include "content/renderer/media/native_handle_impl.h"
+#include "gpu/command_buffer/common/mailbox_holder.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/filters/gpu_video_accelerator_factories.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/webrtc/common_video/interface/texture_video_frame.h"
 #include "third_party/webrtc/system_wrappers/interface/ref_count.h"
 
@@ -85,28 +88,12 @@ RTCVideoDecoder::RTCVideoDecoder(
       weak_factory_(this) {
   DCHECK(!vda_task_runner_->BelongsToCurrentThread());
   weak_this_ = weak_factory_.GetWeakPtr();
-
-  base::WaitableEvent message_loop_async_waiter(false, false);
-  // Waiting here is safe. The media thread is stopped in the child thread and
-  // the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder
-  // runs.
-  vda_task_runner_->PostTask(FROM_HERE,
-                             base::Bind(&RTCVideoDecoder::Initialize,
-                                        base::Unretained(this),
-                                        &message_loop_async_waiter));
-  message_loop_async_waiter.Wait();
 }
 
 RTCVideoDecoder::~RTCVideoDecoder() {
   DVLOG(2) << "~RTCVideoDecoder";
-  // Destroy VDA and remove |this| from the observer if this is vda thread.
-  if (vda_task_runner_->BelongsToCurrentThread()) {
-    base::MessageLoop::current()->RemoveDestructionObserver(this);
-    DestroyVDA();
-  } else {
-    // VDA should have been destroyed in WillDestroyCurrentMessageLoop.
-    DCHECK(!vda_);
-  }
+  DCHECK(vda_task_runner_->BelongsToCurrentThread());
+  DestroyVDA();
 
   // Delete all shared memories.
   STLDeleteElements(&available_shm_segments_);
@@ -124,6 +111,7 @@ RTCVideoDecoder::~RTCVideoDecoder() {
   }
 }
 
+// static
 scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
     webrtc::VideoCodecType type,
     const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) {
@@ -139,9 +127,15 @@ scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
       return decoder.Pass();
   }
 
+  base::WaitableEvent waiter(true, false);
   decoder.reset(new RTCVideoDecoder(factories));
-  decoder->vda_ =
-      factories->CreateVideoDecodeAccelerator(profile, decoder.get()).Pass();
+  decoder->vda_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&RTCVideoDecoder::CreateVDA,
+                 base::Unretained(decoder.get()),
+                 profile,
+                 &waiter));
+  waiter.Wait();
   // vda can be NULL if VP8 is not supported.
   if (decoder->vda_ != NULL) {
     decoder->state_ = INITIALIZED;
@@ -406,6 +400,33 @@ void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
   }
 }
 
+static void ReadPixelsSyncInner(
+    const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
+    uint32 texture_id,
+    const gfx::Rect& visible_rect,
+    const SkBitmap& pixels,
+    base::WaitableEvent* event) {
+  factories->ReadPixels(texture_id, visible_rect, pixels);
+  event->Signal();
+}
+
+static void ReadPixelsSync(
+    const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
+    uint32 texture_id,
+    const gfx::Rect& visible_rect,
+    const SkBitmap& pixels) {
+  base::WaitableEvent event(true, false);
+  if (!factories->GetTaskRunner()->PostTask(FROM_HERE,
+                                            base::Bind(&ReadPixelsSyncInner,
+                                                       factories,
+                                                       texture_id,
+                                                       visible_rect,
+                                                       pixels,
+                                                       &event)))
+    return;
+  event.Wait();
+}
+
 scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
     const media::Picture& picture,
     const media::PictureBuffer& pb,
@@ -414,29 +435,21 @@ scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
     uint32_t height,
     size_t size) {
   gfx::Rect visible_rect(width, height);
-  gfx::Size natural_size(width, height);
   DCHECK(decoder_texture_target_);
   // Convert timestamp from 90KHz to ms.
   base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue(
       base::checked_cast<uint64_t>(timestamp) * 1000 / 90);
   return media::VideoFrame::WrapNativeTexture(
-      make_scoped_ptr(new media::VideoFrame::MailboxHolder(
-          pb.texture_mailbox(),
-          0,  // sync_point
-          media::BindToCurrentLoop(
-              base::Bind(&RTCVideoDecoder::ReusePictureBuffer,
-                         weak_this_,
-                         picture.picture_buffer_id())))),
-      decoder_texture_target_,
+      make_scoped_ptr(new gpu::MailboxHolder(
+          pb.texture_mailbox(), decoder_texture_target_, 0)),
+      media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer,
+                                          weak_this_,
+                                          picture.picture_buffer_id())),
       pb.size(),
       visible_rect,
-      natural_size,
+      visible_rect.size(),
       timestamp_ms,
-      base::Bind(&media::GpuVideoAcceleratorFactories::ReadPixels,
-                 factories_,
-                 pb.texture_id(),
-                 natural_size),
-      base::Closure());
+      base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect));
 }
 
 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
@@ -496,21 +509,6 @@ void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
   state_ = DECODE_ERROR;
 }
 
-void RTCVideoDecoder::WillDestroyCurrentMessageLoop() {
-  DVLOG(2) << "WillDestroyCurrentMessageLoop";
-  DCHECK(vda_task_runner_->BelongsToCurrentThread());
-  factories_->Abort();
-  weak_factory_.InvalidateWeakPtrs();
-  DestroyVDA();
-}
-
-void RTCVideoDecoder::Initialize(base::WaitableEvent* waiter) {
-  DVLOG(2) << "Initialize";
-  DCHECK(vda_task_runner_->BelongsToCurrentThread());
-  base::MessageLoop::current()->AddDestructionObserver(this);
-  waiter->Signal();
-}
-
 void RTCVideoDecoder::RequestBufferDecode() {
   DCHECK(vda_task_runner_->BelongsToCurrentThread());
   if (!vda_)
@@ -640,8 +638,9 @@ void RTCVideoDecoder::ResetInternal() {
     vda_->Reset();
 }
 
-void RTCVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id,
-                                         uint32 sync_point) {
+void RTCVideoDecoder::ReusePictureBuffer(
+    int64 picture_buffer_id,
+    scoped_ptr<gpu::MailboxHolder> mailbox_holder) {
   DCHECK(vda_task_runner_->BelongsToCurrentThread());
   DVLOG(3) << "ReusePictureBuffer. id=" << picture_buffer_id;
 
@@ -665,11 +664,18 @@ void RTCVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id,
     return;
   }
 
-  factories_->WaitSyncPoint(sync_point);
+  factories_->WaitSyncPoint(mailbox_holder->sync_point);
 
   vda_->ReusePictureBuffer(picture_buffer_id);
 }
 
+void RTCVideoDecoder::CreateVDA(media::VideoCodecProfile profile,
+                                base::WaitableEvent* waiter) {
+  DCHECK(vda_task_runner_->BelongsToCurrentThread());
+  vda_ = factories_->CreateVideoDecodeAccelerator(profile, this);
+  waiter->Signal();
+}
+
 void RTCVideoDecoder::DestroyTextures() {
   DCHECK(vda_task_runner_->BelongsToCurrentThread());
   std::map<int32, media::PictureBuffer>::iterator it;