Chromium Code Reviews| Index: content/renderer/media/video_capture_impl.cc |
| diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc |
| index c6b7bf27cd5a4f8bfe7599368b14f54211c8952f..d8ac4282f23f4bde2be950dd5be2196d46bb0741 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()) { |
|
palmer
2013/06/19 20:24:08
As written this looks OK, but it strongly suggests
hshi1
2013/06/19 21:16:25
I'd opt for using std::vector::at.
|
| + base::SharedMemory* shm = bitstream_buffers_[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()); |