| 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..0dbf69681c51d82ee185682a083b781f03a919e4 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()); | 
|  | 
|  |