| Index: content/renderer/media/capture_video_decoder.cc
|
| diff --git a/content/renderer/media/capture_video_decoder.cc b/content/renderer/media/capture_video_decoder.cc
|
| index fadcac75a81275187ea6132785b6db2d7bc706db..4d1f683d8ad7083ed357291f5af5b33a7ba07212 100644
|
| --- a/content/renderer/media/capture_video_decoder.cc
|
| +++ b/content/renderer/media/capture_video_decoder.cc
|
| @@ -22,6 +22,7 @@ CaptureVideoDecoder::CaptureVideoDecoder(
|
| : message_loop_proxy_(message_loop_proxy),
|
| vc_manager_(vc_manager),
|
| capability_(capability),
|
| + natural_size_(capability.width, capability.height),
|
| state_(kUnInitialized),
|
| video_stream_id_(video_stream_id),
|
| capture_engine_(NULL) {
|
| @@ -41,16 +42,15 @@ void CaptureVideoDecoder::Initialize(
|
| filter_callback, stat_callback));
|
| }
|
|
|
| -void CaptureVideoDecoder::ProduceVideoFrame(
|
| - scoped_refptr<media::VideoFrame> video_frame) {
|
| +void CaptureVideoDecoder::Read(const ReadCB& callback) {
|
| message_loop_proxy_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&CaptureVideoDecoder::ProduceVideoFrameOnDecoderThread,
|
| - this, video_frame));
|
| + base::Bind(&CaptureVideoDecoder::ReadOnDecoderThread,
|
| + this, callback));
|
| }
|
|
|
| -gfx::Size CaptureVideoDecoder::natural_size() {
|
| - return gfx::Size(capability_.width, capability_.height);
|
| +const gfx::Size& CaptureVideoDecoder::natural_size() {
|
| + return natural_size_;
|
| }
|
|
|
| void CaptureVideoDecoder::Play(const base::Closure& callback) {
|
| @@ -131,17 +131,15 @@ void CaptureVideoDecoder::InitializeOnDecoderThread(
|
|
|
| capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this);
|
|
|
| - available_frames_.clear();
|
| -
|
| statistics_callback_ = stat_callback;
|
| filter_callback.Run();
|
| state_ = kNormal;
|
| }
|
|
|
| -void CaptureVideoDecoder::ProduceVideoFrameOnDecoderThread(
|
| - scoped_refptr<media::VideoFrame> video_frame) {
|
| +void CaptureVideoDecoder::ReadOnDecoderThread(const ReadCB& callback) {
|
| DCHECK(message_loop_proxy_->BelongsToCurrentThread());
|
| - available_frames_.push_back(video_frame);
|
| + CHECK(read_cb_.is_null());
|
| + read_cb_ = callback;
|
| }
|
|
|
| void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) {
|
| @@ -170,14 +168,6 @@ void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time,
|
| VLOG(1) << "SeekOnDecoderThread.";
|
| DCHECK(message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| - state_ = kSeeking;
|
| - // Create output buffer pool and pass the frames to renderer
|
| - // so that the renderer can complete the seeking
|
| - for (size_t i = 0; i < media::Limits::kMaxVideoFrames; ++i) {
|
| - VideoFrameReady(media::VideoFrame::CreateBlackFrame(capability_.width,
|
| - capability_.height));
|
| - }
|
| -
|
| cb.Run(media::PIPELINE_OK);
|
| state_ = kNormal;
|
| capture_engine_->StartCapture(this, capability_);
|
| @@ -197,34 +187,27 @@ void CaptureVideoDecoder::OnBufferReadyOnDecoderThread(
|
| scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) {
|
| DCHECK(message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| - if (available_frames_.size() == 0 || kNormal != state_) {
|
| + if (read_cb_.is_null() || kNormal != state_) {
|
| capture->FeedBuffer(buf);
|
| return;
|
| }
|
|
|
| - scoped_refptr<media::VideoFrame> video_frame = available_frames_.front();
|
| - available_frames_.pop_front();
|
| -
|
| if (buf->width != capability_.width || buf->height != capability_.height) {
|
| capability_.width = buf->width;
|
| capability_.height = buf->height;
|
| - host()->SetNaturalVideoSize(
|
| - gfx::Size(capability_.width, capability_.height));
|
| + natural_size_.SetSize(buf->width, buf->height);
|
| + host()->SetNaturalVideoSize(natural_size_);
|
| }
|
|
|
| - // Check if there's a size change.
|
| - if (static_cast<int>(video_frame->width()) != capability_.width ||
|
| - static_cast<int>(video_frame->height()) != capability_.height) {
|
| - // Allocate new buffer based on the new size.
|
| - video_frame = media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
|
| - capability_.width,
|
| - capability_.height,
|
| - media::kNoTimestamp,
|
| - media::kNoTimestamp);
|
| - }
|
| -
|
| - video_frame->SetTimestamp(buf->timestamp - start_time_);
|
| - video_frame->SetDuration(base::TimeDelta::FromMilliseconds(33));
|
| + // Always allocate a new frame.
|
| + //
|
| + // TODO(scherkus): migrate this to proper buffer recycling.
|
| + scoped_refptr<media::VideoFrame> video_frame =
|
| + media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
|
| + natural_size_.width(),
|
| + natural_size_.height(),
|
| + buf->timestamp - start_time_,
|
| + base::TimeDelta::FromMilliseconds(33));
|
|
|
| uint8* buffer = buf->memory_pointer;
|
|
|
| @@ -241,6 +224,14 @@ void CaptureVideoDecoder::OnBufferReadyOnDecoderThread(
|
| buffer += uv_width * uv_height;
|
| CopyVPlane(buffer, uv_width, uv_height, video_frame);
|
|
|
| - VideoFrameReady(video_frame);
|
| + DeliverFrame(video_frame);
|
| capture->FeedBuffer(buf);
|
| }
|
| +
|
| +void CaptureVideoDecoder::DeliverFrame(
|
| + const scoped_refptr<media::VideoFrame>& video_frame) {
|
| + // Reset the callback before running to protect against reentrancy.
|
| + ReadCB read_cb = read_cb_;
|
| + read_cb_.Reset();
|
| + read_cb.Run(video_frame);
|
| +}
|
|
|