Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / media / gpu_video_encode_accelerator.cc
index 9227847..3a6deec 100644 (file)
 #include "media/base/video_frame.h"
 
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
-#include "content/common/gpu/media/exynos_video_encode_accelerator.h"
+#include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
 #elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
 #include "content/common/gpu/media/android_video_encode_accelerator.h"
 #endif
 
 namespace content {
 
-GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(GpuChannel* gpu_channel,
-                                                     int32 route_id)
-    : weak_this_factory_(this),
-      channel_(gpu_channel),
-      route_id_(route_id),
+static bool MakeDecoderContextCurrent(
+    const base::WeakPtr<GpuCommandBufferStub> stub) {
+  if (!stub) {
+    DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
+    return false;
+  }
+
+  if (!stub->decoder()->MakeCurrent()) {
+    DLOG(ERROR) << "Failed to MakeCurrent()";
+    return false;
+  }
+
+  return true;
+}
+
+GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(int32 host_route_id,
+                                                     GpuCommandBufferStub* stub)
+    : host_route_id_(host_route_id),
+      stub_(stub),
       input_format_(media::VideoFrame::UNKNOWN),
-      output_buffer_size_(0) {}
+      output_buffer_size_(0),
+      weak_this_factory_(this) {
+  stub_->AddDestructionObserver(this);
+  make_context_current_ =
+      base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
+}
 
 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
-  if (encoder_)
-    encoder_.release()->Destroy();
+  // This class can only be self-deleted from OnWillDestroyStub(), which means
+  // the VEA has already been destroyed in there.
+  DCHECK(!encoder_);
+}
+
+void GpuVideoEncodeAccelerator::Initialize(
+    media::VideoFrame::Format input_format,
+    const gfx::Size& input_visible_size,
+    media::VideoCodecProfile output_profile,
+    uint32 initial_bitrate,
+    IPC::Message* init_done_msg) {
+  DVLOG(2) << "GpuVideoEncodeAccelerator::Initialize(): "
+              "input_format=" << input_format
+           << ", input_visible_size=" << input_visible_size.ToString()
+           << ", output_profile=" << output_profile
+           << ", initial_bitrate=" << initial_bitrate;
+  DCHECK(!encoder_);
+
+  if (!stub_->channel()->AddRoute(host_route_id_, this)) {
+    DLOG(ERROR) << "GpuVideoEncodeAccelerator::Initialize(): "
+                   "failed to add route";
+    SendCreateEncoderReply(init_done_msg, false);
+    return;
+  }
+
+  if (input_visible_size.width() > media::limits::kMaxDimension ||
+      input_visible_size.height() > media::limits::kMaxDimension ||
+      input_visible_size.GetArea() > media::limits::kMaxCanvas) {
+    DLOG(ERROR) << "GpuVideoEncodeAccelerator::Initialize(): "
+                   "input_visible_size " << input_visible_size.ToString()
+                << " too large";
+    SendCreateEncoderReply(init_done_msg, false);
+    return;
+  }
+
+  CreateEncoder();
+  if (!encoder_) {
+    DLOG(ERROR)
+        << "GpuVideoEncodeAccelerator::Initialize(): VEA creation failed";
+    SendCreateEncoderReply(init_done_msg, false);
+    return;
+  }
+  if (!encoder_->Initialize(input_format,
+                            input_visible_size,
+                            output_profile,
+                            initial_bitrate,
+                            this)) {
+    DLOG(ERROR)
+        << "GpuVideoEncodeAccelerator::Initialize(): VEA initialization failed";
+    SendCreateEncoderReply(init_done_msg, false);
+    return;
+  }
+  input_format_ = input_format;
+  input_visible_size_ = input_visible_size;
+  SendCreateEncoderReply(init_done_msg, true);
 }
 
 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Initialize, OnInitialize)
     IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode)
     IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
                         OnUseOutputBitstreamBuffer)
     IPC_MESSAGE_HANDLER(
         AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
         OnRequestEncodingParametersChange)
+    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
 }
 
-void GpuVideoEncodeAccelerator::OnChannelError() {
-  NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
-  if (channel_)
-    channel_ = NULL;
-}
-
-void GpuVideoEncodeAccelerator::NotifyInitializeDone() {
-  Send(new AcceleratedVideoEncoderHostMsg_NotifyInitializeDone(route_id_));
-}
-
 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers(
     unsigned int input_count,
     const gfx::Size& input_coded_size,
     size_t output_buffer_size) {
   Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
-      route_id_, input_count, input_coded_size, output_buffer_size));
+      host_route_id_, input_count, input_coded_size, output_buffer_size));
   input_coded_size_ = input_coded_size;
   output_buffer_size_ = output_buffer_size;
 }
@@ -75,12 +137,23 @@ void GpuVideoEncodeAccelerator::BitstreamBufferReady(int32 bitstream_buffer_id,
                                                      size_t payload_size,
                                                      bool key_frame) {
   Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
-      route_id_, bitstream_buffer_id, payload_size, key_frame));
+      host_route_id_, bitstream_buffer_id, payload_size, key_frame));
 }
 
 void GpuVideoEncodeAccelerator::NotifyError(
     media::VideoEncodeAccelerator::Error error) {
-  Send(new AcceleratedVideoEncoderHostMsg_NotifyError(route_id_, error));
+  Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_, error));
+}
+
+void GpuVideoEncodeAccelerator::OnWillDestroyStub() {
+  DCHECK(stub_);
+  stub_->channel()->RemoveRoute(host_route_id_);
+  stub_->RemoveDestructionObserver(this);
+
+  if (encoder_)
+    encoder_.release()->Destroy();
+
+  delete this;
 }
 
 // static
@@ -89,7 +162,7 @@ GpuVideoEncodeAccelerator::GetSupportedProfiles() {
   std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
 
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
-  profiles = ExynosVideoEncodeAccelerator::GetSupportedProfiles();
+  profiles = V4L2VideoEncodeAccelerator::GetSupportedProfiles();
 #elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
   profiles = AndroidVideoEncodeAccelerator::GetSupportedProfiles();
 #endif
@@ -101,47 +174,16 @@ GpuVideoEncodeAccelerator::GetSupportedProfiles() {
 void GpuVideoEncodeAccelerator::CreateEncoder() {
   DCHECK(!encoder_);
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
-  encoder_.reset(new ExynosVideoEncodeAccelerator());
+  scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder);
+  if (!device.get())
+    return;
+
+  encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass()));
 #elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
   encoder_.reset(new AndroidVideoEncodeAccelerator());
 #endif
 }
 
-void GpuVideoEncodeAccelerator::OnInitialize(
-    media::VideoFrame::Format input_format,
-    const gfx::Size& input_visible_size,
-    media::VideoCodecProfile output_profile,
-    uint32 initial_bitrate) {
-  DVLOG(2) << "GpuVideoEncodeAccelerator::OnInitialize(): "
-              "input_format=" << input_format
-           << ", input_visible_size=" << input_visible_size.ToString()
-           << ", output_profile=" << output_profile
-           << ", initial_bitrate=" << initial_bitrate;
-  DCHECK(!encoder_);
-
-  if (input_visible_size.width() > media::limits::kMaxDimension ||
-      input_visible_size.height() > media::limits::kMaxDimension ||
-      input_visible_size.GetArea() > media::limits::kMaxCanvas) {
-    DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnInitialize(): "
-                   "input_visible_size " << input_visible_size.ToString()
-                << " too large";
-    NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
-    return;
-  }
-
-  CreateEncoder();
-  if (!encoder_) {
-    DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnInitialize(): VEA creation "
-                   "failed";
-    NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
-    return;
-  }
-  encoder_->Initialize(
-      input_format, input_visible_size, output_profile, initial_bitrate, this);
-  input_format_ = input_format;
-  input_visible_size_ = input_visible_size;
-}
-
 void GpuVideoEncodeAccelerator::OnEncode(int32 frame_id,
                                          base::SharedMemoryHandle buffer_handle,
                                          uint32 buffer_size,
@@ -222,6 +264,11 @@ void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
       media::BitstreamBuffer(buffer_id, buffer_handle, buffer_size));
 }
 
+void GpuVideoEncodeAccelerator::OnDestroy() {
+  DVLOG(2) << "GpuVideoEncodeAccelerator::OnDestroy()";
+  OnWillDestroyStub();
+}
+
 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
     uint32 bitrate,
     uint32 framerate) {
@@ -236,21 +283,19 @@ void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
 void GpuVideoEncodeAccelerator::EncodeFrameFinished(
     int32 frame_id,
     scoped_ptr<base::SharedMemory> shm) {
-  Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(route_id_, frame_id));
+  Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_,
+                                                          frame_id));
   // Just let shm fall out of scope.
 }
 
 void GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
-  if (!channel_) {
-    DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): no channel";
-    delete message;
-    return;
-  } else if (!channel_->Send(message)) {
-    DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): sending failed: "
-                   "message->type()=" << message->type();
-    NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
-    return;
-  }
+  stub_->channel()->Send(message);
+}
+
+void GpuVideoEncodeAccelerator::SendCreateEncoderReply(IPC::Message* message,
+                                                       bool succeeded) {
+  GpuCommandBufferMsg_CreateVideoEncoder::WriteReplyParams(message, succeeded);
+  Send(message);
 }
 
 }  // namespace content