| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "media/filters/video_frame_generator.h" |
| |
| #include "base/bind.h" |
| #include "base/message_loop.h" |
| #include "media/base/demuxer_stream.h" |
| #include "media/base/video_frame.h" |
| |
| namespace media { |
| |
| VideoFrameGenerator::VideoFrameGenerator( |
| const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, |
| const gfx::Size& size, |
| const base::TimeDelta& frame_duration) |
| : message_loop_proxy_(message_loop_proxy), |
| size_(size), |
| stopped_(true), |
| frame_duration_(frame_duration) { |
| } |
| |
| void VideoFrameGenerator::Initialize( |
| const scoped_refptr<DemuxerStream>& stream, |
| const PipelineStatusCB& status_cb, |
| const StatisticsCB& statistics_cb) { |
| message_loop_proxy_->PostTask( |
| FROM_HERE, |
| base::Bind(&VideoFrameGenerator::InitializeOnDecoderThread, |
| this, stream, status_cb, statistics_cb)); |
| } |
| |
| void VideoFrameGenerator::Read(const ReadCB& read_cb) { |
| message_loop_proxy_->PostTask( |
| FROM_HERE, |
| base::Bind(&VideoFrameGenerator::ReadOnDecoderThread, this, read_cb)); |
| } |
| |
| void VideoFrameGenerator::Reset(const base::Closure& closure) { |
| message_loop_proxy_->PostTask( |
| FROM_HERE, |
| base::Bind(&VideoFrameGenerator::ResetOnDecoderThread, this, closure)); |
| } |
| |
| void VideoFrameGenerator::Stop(const base::Closure& closure) { |
| message_loop_proxy_->PostTask( |
| FROM_HERE, |
| base::Bind(&VideoFrameGenerator::StopOnDecoderThread, this, closure)); |
| } |
| |
| VideoFrameGenerator::~VideoFrameGenerator() {} |
| |
| void VideoFrameGenerator::InitializeOnDecoderThread( |
| const scoped_refptr<DemuxerStream>& /* stream */, |
| const PipelineStatusCB& status_cb, |
| const StatisticsCB& statistics_cb) { |
| DVLOG(1) << "InitializeOnDecoderThread"; |
| DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| |
| status_cb.Run(PIPELINE_OK); |
| stopped_ = false; |
| } |
| |
| void VideoFrameGenerator::ReadOnDecoderThread(const ReadCB& read_cb) { |
| DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| CHECK(!read_cb.is_null()); |
| if (stopped_) |
| return; |
| |
| // Always allocate a new frame. |
| // |
| // TODO(scherkus): migrate this to proper buffer recycling. |
| scoped_refptr<VideoFrame> video_frame = |
| VideoFrame::CreateFrame(VideoFrame::YV12, size_, gfx::Rect(size_), size_, |
| current_time_); |
| current_time_ += frame_duration_; |
| |
| // TODO(wjia): set pixel data to pre-defined patterns if it's desired to |
| // verify frame content. |
| |
| read_cb.Run(kOk, video_frame); |
| } |
| |
| void VideoFrameGenerator::ResetOnDecoderThread(const base::Closure& closure) { |
| DVLOG(1) << "ResetOnDecoderThread"; |
| DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| current_time_ = base::TimeDelta(); |
| closure.Run(); |
| } |
| |
| void VideoFrameGenerator::StopOnDecoderThread(const base::Closure& closure) { |
| DVLOG(1) << "StopOnDecoderThread"; |
| DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| stopped_ = true; |
| current_time_ = base::TimeDelta(); |
| closure.Run(); |
| } |
| |
| } // namespace media |