Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / media_stream_video_capturer_source.cc
index b4c254d..4bcab47 100644 (file)
@@ -5,9 +5,11 @@
 #include "content/renderer/media/media_stream_video_capturer_source.h"
 
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/location.h"
 #include "content/renderer/media/video_capture_impl_manager.h"
 #include "content/renderer/render_thread_impl.h"
+#include "media/base/bind_to_current_loop.h"
 #include "media/base/video_frame.h"
 
 namespace {
@@ -19,15 +21,13 @@ struct SourceVideoFormat {
 };
 
 // List of formats used if the source doesn't support capability enumeration.
-const SourceVideoFormat kVideoFormats[] = {
-    {1920, 1080, 30},
-    {1280, 720, 30},
-    {960, 720, 30},
-    {640, 480, 30},
-    {640, 360, 30},
-    {320, 240, 30},
-    {320, 180, 30}
-};
+const SourceVideoFormat kVideoFormats[] = {{1920, 1080, 30},
+                                           {1280, 720, 30},
+                                           {960, 720, 30},
+                                           {640, 480, 30},
+                                           {640, 360, 30},
+                                           {320, 240, 30},
+                                           {320, 180, 30}};
 
 }  // namespace
 
@@ -40,24 +40,26 @@ VideoCapturerDelegate::VideoCapturerDelegate(
                       device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE),
       got_first_frame_(false) {
   DVLOG(3) << "VideoCapturerDelegate::ctor";
-  // RenderThreadImpl::current() may be NULL in testing.
+
+  // NULL in unit test.
   if (RenderThreadImpl::current()) {
-    capture_engine_ = RenderThreadImpl::current()->video_capture_impl_manager()
-              ->UseDevice(device_info.session_id);
-    DCHECK(capture_engine_);
+    VideoCaptureImplManager* manager =
+        RenderThreadImpl::current()->video_capture_impl_manager();
+    if (manager)
+      release_device_cb_ = manager->UseDevice(session_id_);
   }
-  message_loop_proxy_ = base::MessageLoopProxy::current();
 }
 
 VideoCapturerDelegate::~VideoCapturerDelegate() {
   DVLOG(3) << "VideoCapturerDelegate::dtor";
-  DCHECK(new_frame_callback_.is_null());
+  if (!release_device_cb_.is_null())
+    release_device_cb_.Run();
 }
 
 void VideoCapturerDelegate::GetCurrentSupportedFormats(
     int max_requested_width,
     int max_requested_height,
-    const SupportedFormatsCallback& callback) {
+    const VideoCaptureDeviceFormatsCB& callback) {
   DVLOG(3) << "GetCurrentSupportedFormats("
            << " { max_requested_height = " << max_requested_height << "})"
            << " { max_requested_width = " << max_requested_width << "})";
@@ -77,116 +79,130 @@ void VideoCapturerDelegate::GetCurrentSupportedFormats(
     return;
   }
 
-  // This delegate implementation doesn't support capability enumeration.
-  // We need to guess what it supports.
-  media::VideoCaptureFormats formats;
-  for (size_t i = 0; i < arraysize(kVideoFormats); ++i) {
-    formats.push_back(
-        media::VideoCaptureFormat(
-            gfx::Size(kVideoFormats[i].width,
-                      kVideoFormats[i].height),
-            kVideoFormats[i].frame_rate,
-            media::PIXEL_FORMAT_I420));
-  }
-  callback.Run(formats);
+  // NULL in unit test.
+  if (!RenderThreadImpl::current())
+    return;
+  VideoCaptureImplManager* manager =
+      RenderThreadImpl::current()->video_capture_impl_manager();
+  if (!manager)
+    return;
+  DCHECK(source_formats_callback_.is_null());
+  source_formats_callback_ = callback;
+  manager->GetDeviceFormatsInUse(
+      session_id_,
+      media::BindToCurrentLoop(
+          base::Bind(
+              &VideoCapturerDelegate::OnDeviceFormatsInUseReceived, this)));
 }
 
-void VideoCapturerDelegate::StartDeliver(
+void VideoCapturerDelegate::StartCapture(
     const media::VideoCaptureParams& params,
-    const NewFrameCallback& new_frame_callback,
+    const VideoCaptureDeliverFrameCB& new_frame_callback,
     const StartedCallback& started_callback) {
   DCHECK(params.requested_format.IsValid());
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  new_frame_callback_ = new_frame_callback;
+  DCHECK(thread_checker_.CalledOnValidThread());
   started_callback_ = started_callback;
   got_first_frame_ = false;
 
-  // Increase the reference count to ensure the object is not deleted until
-  // it is unregistered in VideoCapturerDelegate::OnRemoved.
-  AddRef();
-  capture_engine_->StartCapture(this, params);
+  // NULL in unit test.
+  if (!RenderThreadImpl::current())
+    return;
+  VideoCaptureImplManager* manager =
+      RenderThreadImpl::current()->video_capture_impl_manager();
+  if (!manager)
+    return;
+  stop_capture_cb_ =
+      manager->StartCapture(
+          session_id_,
+          params,
+          media::BindToCurrentLoop(base::Bind(
+              &VideoCapturerDelegate::OnStateUpdateOnRenderThread, this)),
+          new_frame_callback);
 }
 
-void VideoCapturerDelegate::StopDeliver() {
+void VideoCapturerDelegate::StopCapture() {
   // Immediately make sure we don't provide more frames.
   DVLOG(3) << "VideoCapturerDelegate::StopCapture()";
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  capture_engine_->StopCapture(this);
-  new_frame_callback_.Reset();
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!stop_capture_cb_.is_null()) {
+    base::ResetAndReturn(&stop_capture_cb_).Run();
+  }
   started_callback_.Reset();
+  source_formats_callback_.Reset();
 }
 
-void VideoCapturerDelegate::OnStarted(media::VideoCapture* capture) {
-  DVLOG(3) << "VideoCapturerDelegate::OnStarted";
-  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
-}
-
-void VideoCapturerDelegate::OnStopped(media::VideoCapture* capture) {
-  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
-}
-
-void VideoCapturerDelegate::OnPaused(media::VideoCapture* capture) {
-  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
-}
-
-void VideoCapturerDelegate::OnError(media::VideoCapture* capture,
-                                    int error_code) {
-  DVLOG(3) << "VideoCapturerDelegate::OnError";
-  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
-  message_loop_proxy_->PostTask(
-      FROM_HERE,
-      base::Bind(&VideoCapturerDelegate::OnErrorOnRenderThread, this, capture));
-}
-
-void VideoCapturerDelegate::OnRemoved(media::VideoCapture* capture) {
-  DVLOG(3) << " MediaStreamVideoCapturerSource::OnRemoved";
-  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
-
-  // Balance the AddRef in StartDeliver.
-  // This means we are no longer registered as an event handler and can safely
-  // be deleted.
-  Release();
-}
-
-void VideoCapturerDelegate::OnFrameReady(
-    media::VideoCapture* capture,
-    const scoped_refptr<media::VideoFrame>& frame) {
-  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
-  message_loop_proxy_->PostTask(
-      FROM_HERE,
-      base::Bind(&VideoCapturerDelegate::OnFrameReadyOnRenderThread,
-                 this,
-                 capture,
-                 frame));
+void VideoCapturerDelegate::OnStateUpdateOnRenderThread(
+    VideoCaptureState state) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DVLOG(3) << "OnStateUpdateOnRenderThread state = " << state;
+  if (state > VIDEO_CAPTURE_STATE_STARTING && !started_callback_.is_null()) {
+    base::ResetAndReturn(&started_callback_).Run(
+        state == VIDEO_CAPTURE_STATE_STARTED);
+  }
 }
 
-void VideoCapturerDelegate::OnFrameReadyOnRenderThread(
-    media::VideoCapture* capture,
-    const scoped_refptr<media::VideoFrame>& frame) {
-  if (!got_first_frame_) {
-    got_first_frame_ = true;
-    if (!started_callback_.is_null())
-      started_callback_.Run(true);
+void VideoCapturerDelegate::OnDeviceFormatsInUseReceived(
+    const media::VideoCaptureFormats& formats_in_use) {
+  DVLOG(3) << "OnDeviceFormatsInUseReceived: " << formats_in_use.size();
+  DCHECK(thread_checker_.CalledOnValidThread());
+  // StopCapture() might have destroyed |source_formats_callback_| before
+  // arriving here.
+  if (source_formats_callback_.is_null())
+    return;
+  // If there are no formats in use, try to retrieve the whole list of
+  // supported form.
+  if (!formats_in_use.empty()) {
+    source_formats_callback_.Run(formats_in_use);
+    source_formats_callback_.Reset();
+    return;
   }
 
-  if (!new_frame_callback_.is_null()) {
-    new_frame_callback_.Run(frame);
+  // NULL in unit test.
+  if (!RenderThreadImpl::current())
+    return;
+  VideoCaptureImplManager* manager =
+      RenderThreadImpl::current()->video_capture_impl_manager();
+  if (!manager)
+    return;
+  manager->GetDeviceSupportedFormats(
+      session_id_,
+      media::BindToCurrentLoop(
+          base::Bind(
+              &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated,
+              this)));
+}
+
+void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated(
+    const media::VideoCaptureFormats& formats) {
+  DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size()
+           << " received";
+  DCHECK(thread_checker_.CalledOnValidThread());
+  // StopCapture() might have destroyed |source_formats_callback_| before
+  // arriving here.
+  if (source_formats_callback_.is_null())
+    return;
+  if (formats.size()) {
+    source_formats_callback_.Run(formats);
+  } else {
+    // The capture device doesn't seem to support capability enumeration,
+    // compose a fallback list of capabilities.
+    media::VideoCaptureFormats default_formats;
+    for (size_t i = 0; i < arraysize(kVideoFormats); ++i) {
+      default_formats.push_back(media::VideoCaptureFormat(
+          gfx::Size(kVideoFormats[i].width, kVideoFormats[i].height),
+          kVideoFormats[i].frame_rate,
+          media::PIXEL_FORMAT_I420));
+    }
+    source_formats_callback_.Run(default_formats);
   }
-}
-
-void VideoCapturerDelegate::OnErrorOnRenderThread(
-    media::VideoCapture* capture) {
-  if (!started_callback_.is_null())
-    started_callback_.Run(false);
+  source_formats_callback_.Reset();
 }
 
 MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
     const StreamDeviceInfo& device_info,
     const SourceStoppedCallback& stop_callback,
-    const scoped_refptr<VideoCapturerDelegate>& delegate,
-    MediaStreamDependencyFactory* factory)
-    : MediaStreamVideoSource(factory),
-      delegate_(delegate) {
+    const scoped_refptr<VideoCapturerDelegate>& delegate)
+    : delegate_(delegate) {
   SetDeviceInfo(device_info);
   SetStopCallback(stop_callback);
 }
@@ -196,31 +212,31 @@ MediaStreamVideoCapturerSource::~MediaStreamVideoCapturerSource() {
 
 void MediaStreamVideoCapturerSource::GetCurrentSupportedFormats(
     int max_requested_width,
-    int max_requested_height) {
+    int max_requested_height,
+    const VideoCaptureDeviceFormatsCB& callback) {
   delegate_->GetCurrentSupportedFormats(
       max_requested_width,
       max_requested_height,
-      base::Bind(&MediaStreamVideoCapturerSource::OnSupportedFormats,
-                 base::Unretained(this)));
+      callback);
 }
 
 void MediaStreamVideoCapturerSource::StartSourceImpl(
-    const media::VideoCaptureParams& params) {
+    const media::VideoCaptureParams& params,
+    const VideoCaptureDeliverFrameCB& frame_callback) {
   media::VideoCaptureParams new_params(params);
   if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE ||
       device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
     new_params.allow_resolution_change = true;
   }
-  delegate_->StartDeliver(
+  delegate_->StartCapture(
       new_params,
-      base::Bind(&MediaStreamVideoCapturerSource::DeliverVideoFrame,
-                 base::Unretained(this)),
+      frame_callback,
       base::Bind(&MediaStreamVideoCapturerSource::OnStartDone,
                  base::Unretained(this)));
 }
 
 void MediaStreamVideoCapturerSource::StopSourceImpl() {
-  delegate_->StopDeliver();
+  delegate_->StopCapture();
 }
 
 }  // namespace content