#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 {
};
// 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
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 << "})";
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);
}
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