diff options
Diffstat (limited to 'content/renderer/media/video_capture_impl.cc')
-rw-r--r-- | content/renderer/media/video_capture_impl.cc | 198 |
1 files changed, 197 insertions, 1 deletions
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc index c6b7bf2..0dbf696 100644 --- a/content/renderer/media/video_capture_impl.cc +++ b/content/renderer/media/video_capture_impl.cc @@ -5,8 +5,10 @@ #include "content/renderer/media/video_capture_impl.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/stl_util.h" #include "content/child/child_process.h" +#include "content/common/media/encoded_video_capture_messages.h" #include "content/common/media/video_capture_messages.h" #include "media/base/limits.h" @@ -58,7 +60,9 @@ VideoCaptureImpl::VideoCaptureImpl( video_type_(media::VideoCaptureCapability::kI420), device_info_available_(false), suspended_(false), - state_(VIDEO_CAPTURE_STATE_STOPPED) { + state_(VIDEO_CAPTURE_STATE_STOPPED), + encoded_video_source_client_(NULL), + bitstream_open_(false) { DCHECK(filter); memset(¤t_params_, 0, sizeof(current_params_)); memset(&device_info_, 0, sizeof(device_info_)); @@ -101,6 +105,83 @@ void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { base::Unretained(this), handler)); } +void VideoCaptureImpl::RequestCapabilities( + const media::EncodedVideoSource::RequestCapabilitiesCallback& callback) { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&VideoCaptureImpl::DoRequestCapabilitiesOnCaptureThread, + base::Unretained(this), callback)); +} + +void VideoCaptureImpl::StartFetchCapabilities() { + Send(new EncodedVideoCaptureHostMsg_GetCapabilities( + device_id_, current_params_.session_id)); +} + +void VideoCaptureImpl::OpenBitstream( + media::EncodedVideoSource::Client* client, + const media::VideoEncodingParameters& params) { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&VideoCaptureImpl::DoOpenBitstreamOnCaptureThread, + base::Unretained(this), client, params)); +} + +void VideoCaptureImpl::CloseBitstream() { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&VideoCaptureImpl::DoCloseBitstreamOnCaptureThread, + base::Unretained(this))); +} + +void VideoCaptureImpl::ReturnBitstreamBuffer( + scoped_refptr<const media::EncodedBitstreamBuffer> buffer) { + Send(new EncodedVideoCaptureHostMsg_BitstreamBufferConsumed( + device_id_, buffer->buffer_id())); +} + +void VideoCaptureImpl::TrySetBitstreamConfig( + const media::RuntimeVideoEncodingParameters& params) { + Send(new EncodedVideoCaptureHostMsg_TryConfigureBitstream( + device_id_, params)); +} + +void VideoCaptureImpl::OnEncodingCapabilitiesAvailable( + const media::VideoEncodingCapabilities& capabilities) { + capture_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &VideoCaptureImpl::DoNotifyCapabilitiesAvailableOnCaptureThread, + base::Unretained(this), capabilities)); +} + +void VideoCaptureImpl::OnEncodedBitstreamOpened( + const media::VideoEncodingParameters& params, + const std::vector<base::SharedMemoryHandle>& buffers, + uint32 buffer_size) { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&VideoCaptureImpl::DoNotifyBitstreamOpenedOnCaptureThread, + base::Unretained(this), params, buffers, buffer_size)); +} + +void VideoCaptureImpl::OnEncodedBitstreamClosed() { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&VideoCaptureImpl::DoNotifyBitstreamClosedOnCaptureThread, + base::Unretained(this))); +} + +void VideoCaptureImpl::OnEncodingConfigChanged( + const media::RuntimeVideoEncodingParameters& params) { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind( + &VideoCaptureImpl::DoNotifyBitstreamConfigChangedOnCaptureThread, + base::Unretained(this), params)); +} + +void VideoCaptureImpl::OnEncodedBufferReady( + int buffer_id, + uint32 size, + const media::BufferEncodingMetadata& metadata) { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&VideoCaptureImpl::DoNotifyBitstreamBufferReadyOnCaptureThread, + base::Unretained(this), buffer_id, size, metadata)); +} + void VideoCaptureImpl::FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) { capture_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(&VideoCaptureImpl::DoFeedBufferOnCaptureThread, @@ -306,6 +387,9 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { switch (state) { case VIDEO_CAPTURE_STATE_STARTED: + if (!encoding_caps_callback_.is_null()) { + StartFetchCapabilities(); + } break; case VIDEO_CAPTURE_STATE_STOPPED: state_ = VIDEO_CAPTURE_STATE_STOPPED; @@ -380,6 +464,118 @@ void VideoCaptureImpl::DoSuspendCaptureOnCaptureThread(bool suspend) { suspended_ = suspend; } +void VideoCaptureImpl::DoRequestCapabilitiesOnCaptureThread( + const RequestCapabilitiesCallback& callback) { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + DCHECK(encoding_caps_callback_.is_null()); + encoding_caps_callback_ = callback; + + // Invoke callback immediately if capabilities are already available. + if (!encoding_caps_.empty()) + base::ResetAndReturn(&encoding_caps_callback_).Run(encoding_caps_); +} + +void VideoCaptureImpl::DoOpenBitstreamOnCaptureThread( + media::EncodedVideoSource::Client* client, + const media::VideoEncodingParameters& params) { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + DCHECK(!encoded_video_source_client_); + encoded_video_source_client_ = client; + Send(new EncodedVideoCaptureHostMsg_OpenBitstream( + device_id_, current_params_.session_id, params)); +} + +void VideoCaptureImpl::DoCloseBitstreamOnCaptureThread() { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + DCHECK(bitstream_open_); + + // Immediately clear EVS client pointer and release bitstream buffers if the + // client requests to close bitstream. Any further encoded capture messages + // from the browser process will be ignored. + bitstream_open_ = false; + for (size_t i = 0; i < bitstream_buffers_.size(); ++i) { + bitstream_buffers_[i]->Close(); + delete bitstream_buffers_[i]; + } + bitstream_buffers_.clear(); + encoded_video_source_client_ = NULL; + + Send(new EncodedVideoCaptureHostMsg_CloseBitstream(device_id_)); +} + +void VideoCaptureImpl::DoNotifyBitstreamOpenedOnCaptureThread( + const media::VideoEncodingParameters& params, + const std::vector<base::SharedMemoryHandle>& buffers, + uint32 buffer_size) { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + DCHECK(!bitstream_open_ && bitstream_buffers_.empty()); + if (!encoded_video_source_client_) + return; + bitstream_open_ = true; + for (size_t i = 0; i < buffers.size(); ++i) { + base::SharedMemory* shm = new base::SharedMemory(buffers[i], true); + CHECK(shm->Map(buffer_size)); + bitstream_buffers_.push_back(shm); + } + encoded_video_source_client_->OnOpened(params); +} + +void VideoCaptureImpl::DoNotifyBitstreamClosedOnCaptureThread() { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + + // Ignore the BitstreamClosed message if bitstream has already been closed + // by the EVS client. + if (!bitstream_open_) + return; + + // The bitstream may still be open when we receive BitstreamClosed message + // if the request to close bitstream comes from the browser process. + bitstream_open_ = false; + for (size_t i = 0; i < bitstream_buffers_.size(); ++i) { + bitstream_buffers_[i]->Close(); + delete bitstream_buffers_[i]; + } + bitstream_buffers_.clear(); + if (encoded_video_source_client_) { + encoded_video_source_client_->OnClosed(); + encoded_video_source_client_ = NULL; + } +} + +void VideoCaptureImpl::DoNotifyBitstreamConfigChangedOnCaptureThread( + const media::RuntimeVideoEncodingParameters& params) { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + if (!encoded_video_source_client_) + return; + encoded_video_source_client_->OnConfigChanged(params); +} + +void VideoCaptureImpl::DoNotifyBitstreamBufferReadyOnCaptureThread( + int buffer_id, + uint32 size, + const media::BufferEncodingMetadata& metadata) { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + if (!encoded_video_source_client_) + return; + if (buffer_id >= 0 && + static_cast<size_t>(buffer_id) < bitstream_buffers_.size()) { + base::SharedMemory* shm = bitstream_buffers_.at(buffer_id); + scoped_refptr<media::EncodedBitstreamBuffer> buffer = + new media::EncodedBitstreamBuffer( + buffer_id, (uint8*)shm->memory(), size, shm->handle(), + metadata, base::Bind(&base::DoNothing)); + encoded_video_source_client_->OnBufferReady(buffer); + } +} + +void VideoCaptureImpl::DoNotifyCapabilitiesAvailableOnCaptureThread( + const media::VideoEncodingCapabilities& capabilities) { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + encoding_caps_ = capabilities; + if (!encoding_caps_callback_.is_null()) + base::ResetAndReturn(&encoding_caps_callback_).Run(encoding_caps_); +} + void VideoCaptureImpl::StopDevice() { DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |