diff options
author | jiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-26 21:37:54 +0000 |
---|---|---|
committer | jiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-26 21:37:54 +0000 |
commit | 5c84b7e13f3525b84f7928e946727b5b8b77899b (patch) | |
tree | 44bb458aeb239c69a85a5c505916d1516b5b526e /media | |
parent | 00ae7a50fe5aa9b15046dff5e805d8cbb1bb4906 (diff) | |
download | chromium_src-5c84b7e13f3525b84f7928e946727b5b8b77899b.zip chromium_src-5c84b7e13f3525b84f7928e946727b5b8b77899b.tar.gz chromium_src-5c84b7e13f3525b84f7928e946727b5b8b77899b.tar.bz2 |
refactoring decoder interface
1. install permanent buffer exchange callback.
2. render provide buffer in read=>fillthisbuffer.
3. for ffmpeg path, the provided buffer is just dummy. it had no relation to decoded buffer. so as to keep the code almost same.
Review URL: http://codereview.chromium.org/2101022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48328 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/filters.h | 44 | ||||
-rw-r--r-- | media/base/mock_filters.h | 10 | ||||
-rw-r--r-- | media/filters/audio_renderer_base.cc | 10 | ||||
-rw-r--r-- | media/filters/audio_renderer_base.h | 4 | ||||
-rw-r--r-- | media/filters/audio_renderer_base_unittest.cc | 48 | ||||
-rw-r--r-- | media/filters/decoder_base.h | 37 | ||||
-rw-r--r-- | media/filters/decoder_base_unittest.cc | 46 | ||||
-rw-r--r-- | media/filters/video_renderer_base.cc | 10 | ||||
-rw-r--r-- | media/filters/video_renderer_base.h | 5 | ||||
-rw-r--r-- | media/filters/video_renderer_base_unittest.cc | 15 |
10 files changed, 136 insertions, 93 deletions
diff --git a/media/base/filters.h b/media/base/filters.h index 980e700..c4da5d9 100644 --- a/media/base/filters.h +++ b/media/base/filters.h @@ -265,10 +265,24 @@ class VideoDecoder : public MediaFilter { // Returns the MediaFormat for this filter. virtual const MediaFormat& media_format() = 0; - // Schedules a read. Decoder takes ownership of the callback. - // - // TODO(scherkus): switch Read() callback to scoped_refptr<>. - virtual void Read(Callback1<VideoFrame*>::Type* read_callback) = 0; + // |set_fill_buffer_done_callback| install permanent callback from downstream + // filter (i.e. Renderer). The callback is used to deliver video frames at + // runtime to downstream filter + typedef Callback1<scoped_refptr<VideoFrame> >::Type FillBufferDoneCallback; + void set_fill_buffer_done_callback(FillBufferDoneCallback* callback) { + fill_buffer_done_callback_.reset(callback); + } + FillBufferDoneCallback* fill_buffer_done_callback() { + return fill_buffer_done_callback_.get(); + } + + // Render provides an output buffer for Decoder to write to. These buffers + // will be recycled to renderer by fill_buffer_done_callback_; + // We could also pass empty pointer here to let decoder provide buffers pool. + virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame) = 0; + + private: + scoped_ptr<FillBufferDoneCallback> fill_buffer_done_callback_; }; @@ -289,10 +303,24 @@ class AudioDecoder : public MediaFilter { // Returns the MediaFormat for this filter. virtual const MediaFormat& media_format() = 0; - // Schedules a read. Decoder takes ownership of the callback. - // - // TODO(scherkus): switch Read() callback to scoped_refptr<>. - virtual void Read(Callback1<Buffer*>::Type* read_callback) = 0; + // |set_fill_buffer_done_callback| install permanent callback from downstream + // filter (i.e. Renderer). The callback is used to deliver buffers at + // runtime to downstream filter. + typedef Callback1<scoped_refptr<Buffer> >::Type FillBufferDoneCallback; + void set_fill_buffer_done_callback(FillBufferDoneCallback* callback) { + fill_buffer_done_callback_.reset(callback); + } + FillBufferDoneCallback* fill_buffer_done_callback() { + return fill_buffer_done_callback_.get(); + } + + // Render provides an output buffer for Decoder to write to. These buffers + // will be recycled to renderer by fill_buffer_done_callback_; + // We could also pass empty pointer here to let decoder provide buffers pool. + virtual void FillThisBuffer(scoped_refptr<Buffer> buffer) = 0; + + private: + scoped_ptr<FillBufferDoneCallback> fill_buffer_done_callback_; }; diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 7f49fcf..9aeaeec 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -18,6 +18,7 @@ #include "base/callback.h" #include "media/base/factory.h" #include "media/base/filters.h" +#include "media/base/video_frame.h" #include "testing/gmock/include/gmock/gmock.h" namespace media { @@ -170,7 +171,7 @@ class MockVideoDecoder : public VideoDecoder { MOCK_METHOD2(Initialize, void(DemuxerStream* stream, FilterCallback* callback)); MOCK_METHOD0(media_format, const MediaFormat&()); - MOCK_METHOD1(Read, void(Callback1<VideoFrame*>::Type* read_callback)); + MOCK_METHOD1(FillThisBuffer, void(scoped_refptr<VideoFrame>)); protected: virtual ~MockVideoDecoder() {} @@ -193,7 +194,12 @@ class MockAudioDecoder : public AudioDecoder { MOCK_METHOD2(Initialize, void(DemuxerStream* stream, FilterCallback* callback)); MOCK_METHOD0(media_format, const MediaFormat&()); - MOCK_METHOD1(Read, void(Callback1<Buffer*>::Type* read_callback)); + MOCK_METHOD1(FillThisBuffer, void(scoped_refptr<Buffer>)); + + // change to public to allow unittest for access; + FillBufferDoneCallback* fill_buffer_done_callback() { + return AudioDecoder::fill_buffer_done_callback(); + } protected: virtual ~MockAudioDecoder() {} diff --git a/media/filters/audio_renderer_base.cc b/media/filters/audio_renderer_base.cc index f07a4c2..7e530a8 100644 --- a/media/filters/audio_renderer_base.cc +++ b/media/filters/audio_renderer_base.cc @@ -79,6 +79,8 @@ void AudioRendererBase::Initialize(AudioDecoder* decoder, scoped_ptr<FilterCallback> c(callback); decoder_ = decoder; + decoder_->set_fill_buffer_done_callback( + NewCallback(this, &AudioRendererBase::OnFillBufferDone)); // Get the media properties to initialize our algorithms. int channels = 0; int sample_rate = 0; @@ -126,7 +128,7 @@ bool AudioRendererBase::HasEnded() { return recieved_end_of_stream_ && rendered_end_of_stream_; } -void AudioRendererBase::OnReadComplete(Buffer* buffer_in) { +void AudioRendererBase::OnFillBufferDone(scoped_refptr<Buffer> buffer_in) { AutoLock auto_lock(lock_); DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying); DCHECK_GT(pending_reads_, 0u); @@ -229,7 +231,11 @@ uint32 AudioRendererBase::FillBuffer(uint8* dest, void AudioRendererBase::ScheduleRead_Locked() { lock_.AssertAcquired(); ++pending_reads_; - decoder_->Read(NewCallback(this, &AudioRendererBase::OnReadComplete)); + // TODO(jiesun): We use dummy buffer to feed decoder to let decoder to + // provide buffer pools. In the future, we may want to implement real + // buffer pool to recycle buffers. + scoped_refptr<Buffer> buffer; + decoder_->FillThisBuffer(buffer); } // static diff --git a/media/filters/audio_renderer_base.h b/media/filters/audio_renderer_base.h index 3b3b593..3762679 100644 --- a/media/filters/audio_renderer_base.h +++ b/media/filters/audio_renderer_base.h @@ -55,9 +55,9 @@ class AudioRendererBase : public AudioRenderer { // this time, such as stopping any running threads. virtual void OnStop() = 0; - // Called when a AudioDecoder::Read() completes and decrements + // Called when a AudioDecoder completes decoding and decrements // |pending_reads_|. - virtual void OnReadComplete(Buffer* buffer_in); + virtual void OnFillBufferDone(scoped_refptr<Buffer> buffer_in); // Fills the given buffer with audio data by delegating to its |algorithm_|. // FillBuffer() also takes care of updating the clock. Returns the number of diff --git a/media/filters/audio_renderer_base_unittest.cc b/media/filters/audio_renderer_base_unittest.cc index 62889d0..064f7a6 100644 --- a/media/filters/audio_renderer_base_unittest.cc +++ b/media/filters/audio_renderer_base_unittest.cc @@ -49,11 +49,12 @@ class AudioRendererBaseTest : public ::testing::Test { // Give the decoder some non-garbage media properties. AudioRendererBaseTest() : renderer_(new MockAudioRendererBase()), - decoder_(new MockAudioDecoder()) { + decoder_(new MockAudioDecoder()), + pending_reads_(0) { renderer_->set_host(&host_); // Queue all reads from the decoder. - EXPECT_CALL(*decoder_, Read(NotNull())) + EXPECT_CALL(*decoder_, FillThisBuffer(_)) .WillRepeatedly(Invoke(this, &AudioRendererBaseTest::EnqueueCallback)); // Sets the essential media format keys for this decoder. @@ -67,8 +68,6 @@ class AudioRendererBaseTest : public ::testing::Test { } virtual ~AudioRendererBaseTest() { - STLDeleteElements(&read_queue_); - // Expect a call into the subclass. EXPECT_CALL(*renderer_, OnStop()); renderer_->Stop(); @@ -84,12 +83,12 @@ class AudioRendererBaseTest : public ::testing::Test { StrictMock<MockFilterCallback> callback_; MediaFormat decoder_media_format_; - // Receives asynchronous read requests sent to |decoder_|. - std::deque<Callback1<Buffer*>::Type*> read_queue_; + // Number of asynchronous read requests sent to |decoder_|. + size_t pending_reads_; private: - void EnqueueCallback(Callback1<Buffer*>::Type* callback) { - read_queue_.push_back(callback); + void EnqueueCallback(scoped_refptr<Buffer> buffer) { + ++pending_reads_; } DISALLOW_COPY_AND_ASSIGN(AudioRendererBaseTest); @@ -113,7 +112,7 @@ TEST_F(AudioRendererBaseTest, Initialize_Failed) { // Initialize, we expect to have no reads. renderer_->Initialize(decoder_, callback_.NewCallback()); - EXPECT_EQ(0u, read_queue_.size()); + EXPECT_EQ(0u, pending_reads_); } TEST_F(AudioRendererBaseTest, Initialize_Successful) { @@ -136,23 +135,22 @@ TEST_F(AudioRendererBaseTest, Initialize_Successful) { // Initialize, we shouldn't have any reads. renderer_->Initialize(decoder_, callback_.NewCallback()); - EXPECT_EQ(0u, read_queue_.size()); + EXPECT_EQ(0u, pending_reads_); // Now seek to trigger prerolling. renderer_->Seek(base::TimeDelta(), seek_callback.NewCallback()); - EXPECT_EQ(kMaxQueueSize, read_queue_.size()); + EXPECT_EQ(kMaxQueueSize, pending_reads_); // Verify our seek callback hasn't been executed yet. renderer_->CheckPoint(0); // Now satisfy the read requests. Our callback should be executed after // exiting this loop. - while (!read_queue_.empty()) { + while (pending_reads_) { scoped_refptr<DataBuffer> buffer = new DataBuffer(1024); buffer->SetDataSize(1024); - read_queue_.front()->Run(buffer); - delete read_queue_.front(); - read_queue_.pop_front(); + --pending_reads_; + decoder_->fill_buffer_done_callback()->Run(buffer); } } @@ -176,11 +174,11 @@ TEST_F(AudioRendererBaseTest, OneCompleteReadCycle) { // Initialize, we shouldn't have any reads. renderer_->Initialize(decoder_, callback_.NewCallback()); - EXPECT_EQ(0u, read_queue_.size()); + EXPECT_EQ(0u, pending_reads_); // Now seek to trigger prerolling. renderer_->Seek(base::TimeDelta(), seek_callback.NewCallback()); - EXPECT_EQ(kMaxQueueSize, read_queue_.size()); + EXPECT_EQ(kMaxQueueSize, pending_reads_); // Verify our seek callback hasn't been executed yet. renderer_->CheckPoint(0); @@ -189,12 +187,11 @@ TEST_F(AudioRendererBaseTest, OneCompleteReadCycle) { // exiting this loop. const uint32 kDataSize = 1024; uint32 bytes_buffered = 0; - while (!read_queue_.empty()) { + while (pending_reads_) { scoped_refptr<DataBuffer> buffer = new DataBuffer(kDataSize); buffer->SetDataSize(kDataSize); - read_queue_.front()->Run(buffer); - delete read_queue_.front(); - read_queue_.pop_front(); + decoder_->fill_buffer_done_callback()->Run(buffer); + --pending_reads_; bytes_buffered += kDataSize; } @@ -216,19 +213,18 @@ TEST_F(AudioRendererBaseTest, OneCompleteReadCycle) { } // Make sure the read request queue is full. - EXPECT_EQ(kMaxQueueSize, read_queue_.size()); + EXPECT_EQ(kMaxQueueSize, pending_reads_); // Fulfill the read with an end-of-stream packet. scoped_refptr<DataBuffer> last_buffer = new DataBuffer(0); - read_queue_.front()->Run(last_buffer); - delete read_queue_.front(); - read_queue_.pop_front(); + decoder_->fill_buffer_done_callback()->Run(last_buffer); + --pending_reads_; // We shouldn't report ended until all data has been flushed out. EXPECT_FALSE(renderer_->HasEnded()); // We should have one less read request in the queue. - EXPECT_EQ(kMaxQueueSize - 1, read_queue_.size()); + EXPECT_EQ(kMaxQueueSize - 1, pending_reads_); // Flush the entire internal buffer and verify NotifyEnded() isn't called // right away. diff --git a/media/filters/decoder_base.h b/media/filters/decoder_base.h index 5642651..cc0e3cb 100644 --- a/media/filters/decoder_base.h +++ b/media/filters/decoder_base.h @@ -52,14 +52,15 @@ class DecoderBase : public Decoder { virtual const MediaFormat& media_format() { return media_format_; } // Audio or video decoder. - virtual void Read(ReadCallback* read_callback) { + virtual void FillThisBuffer(scoped_refptr<Output> output) { this->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &DecoderBase::ReadTask, read_callback)); + NewRunnableMethod(this, &DecoderBase::ReadTask, output)); } protected: DecoderBase() : pending_reads_(0), + pending_requests_(0), expecting_discontinuous_(false), state_(kUninitialized) { } @@ -67,7 +68,6 @@ class DecoderBase : public Decoder { virtual ~DecoderBase() { DCHECK(state_ == kUninitialized || state_ == kStopped); DCHECK(result_queue_.empty()); - DCHECK(read_queue_.empty()); } // This method is called by the derived class from within the OnDecode method. @@ -124,9 +124,9 @@ class DecoderBase : public Decoder { // Note that it's possible for us to decode but not produce a frame, in // which case |pending_reads_| will remain less than |read_queue_| so we // need to schedule an additional read. - DCHECK_LE(pending_reads_, read_queue_.size()); + DCHECK_LE(pending_reads_, pending_requests_); if (!fulfilled) { - DCHECK_LT(pending_reads_, read_queue_.size()); + DCHECK_LT(pending_reads_, pending_requests_); demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); ++pending_reads_; } @@ -154,14 +154,13 @@ class DecoderBase : public Decoder { // Throw away all buffers in all queues. result_queue_.clear(); - STLDeleteElements(&read_queue_); state_ = kStopped; } void SeekTask(base::TimeDelta time, FilterCallback* callback) { DCHECK_EQ(MessageLoop::current(), this->message_loop()); DCHECK_EQ(0u, pending_reads_) << "Pending reads should have completed"; - DCHECK(read_queue_.empty()) << "Read requests should be empty"; + DCHECK_EQ(0u, pending_requests_) << "Pending requests should be empty"; // Delegate to the subclass first. // @@ -215,17 +214,16 @@ class DecoderBase : public Decoder { } } - void ReadTask(ReadCallback* read_callback) { + void ReadTask(scoped_refptr<Output> output) { DCHECK_EQ(MessageLoop::current(), this->message_loop()); // TODO(scherkus): should reply with a null operation (empty buffer). - if (IsStopped()) { - delete read_callback; + if (IsStopped()) return; - } - // Enqueue the callback and attempt to fulfill it immediately. - read_queue_.push_back(read_callback); + ++pending_requests_; + + // Try to fulfill it immediately. if (FulfillPendingRead()) return; @@ -260,24 +258,25 @@ class DecoderBase : public Decoder { // Return true if one read request is fulfilled. bool FulfillPendingRead() { DCHECK_EQ(MessageLoop::current(), this->message_loop()); - if (read_queue_.empty() || result_queue_.empty()) { + if (!pending_requests_ || result_queue_.empty()) { return false; } // Dequeue a frame and read callback pair. scoped_refptr<Output> output = result_queue_.front(); - scoped_ptr<ReadCallback> read_callback(read_queue_.front()); result_queue_.pop_front(); - read_queue_.pop_front(); // Execute the callback! - read_callback->Run(output); + --pending_requests_; + Decoder::fill_buffer_done_callback()->Run(output); return true; } // Tracks the number of asynchronous reads issued to |demuxer_stream_|. // Using size_t since it is always compared against deque::size(). size_t pending_reads_; + // Tracks the number of asynchronous reads issued from renderer. + size_t pending_requests_; // A flag used for debugging that we expect our next read to be discontinuous. bool expecting_discontinuous_; @@ -296,10 +295,6 @@ class DecoderBase : public Decoder { typedef std::deque<scoped_refptr<Output> > ResultQueue; ResultQueue result_queue_; - // Queue of callbacks supplied by the renderer through the Read() method. - typedef std::deque<ReadCallback*> ReadQueue; - ReadQueue read_queue_; - // Pause callback. scoped_ptr<FilterCallback> pause_callback_; diff --git a/media/filters/decoder_base_unittest.cc b/media/filters/decoder_base_unittest.cc index 5468602..e771989 100644 --- a/media/filters/decoder_base_unittest.cc +++ b/media/filters/decoder_base_unittest.cc @@ -9,6 +9,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; using ::testing::NotNull; using ::testing::StrictMock; @@ -25,8 +26,6 @@ class MockDecoderOutput : public media::StreamSample { MOCK_CONST_METHOD0(IsEndOfStream, bool()); }; -class MockDecoder : public media::MediaFilter {}; - class MockBuffer : public media::Buffer { public: MockBuffer() {} @@ -38,6 +37,24 @@ class MockBuffer : public media::Buffer { DISALLOW_COPY_AND_ASSIGN(MockBuffer); }; +class MockDecoder : public media::MediaFilter { + public: + typedef Callback1<scoped_refptr<MockDecoderOutput> >::Type + FillBufferDoneCallback; + void set_fill_buffer_done_callback_(FillBufferDoneCallback* callback) { + fill_buffer_done_callback_.reset(callback); + } + FillBufferDoneCallback* fill_buffer_done_callback() { + return fill_buffer_done_callback_.get(); + } + scoped_ptr<FillBufferDoneCallback> fill_buffer_done_callback_; +}; + +class MockDecoderCallback { + public: + MOCK_METHOD1(OnReadComplete, void(scoped_refptr<MockDecoderOutput> output)); +}; + class MockDecoderImpl : public media::DecoderBase< MockDecoder, MockDecoderOutput> { public: @@ -62,16 +79,6 @@ class MockDecoderImpl : public media::DecoderBase< DISALLOW_COPY_AND_ASSIGN(MockDecoderImpl); }; -class MockDecoderReadCallback { - public: - MockDecoderReadCallback() {} - virtual ~MockDecoderReadCallback() {} - MOCK_METHOD1(ReadCallback, void(MockDecoderOutput* output)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockDecoderReadCallback); -}; - } // namespace namespace media { @@ -107,6 +114,9 @@ ACTION(CompleteDemuxRequest) { TEST(DecoderBaseTest, FlowControl) { MessageLoop message_loop; scoped_refptr<MockDecoderImpl> decoder = new MockDecoderImpl(); + MockDecoderCallback read_callback; + decoder->set_fill_buffer_done_callback_( + NewCallback(&read_callback, &MockDecoderCallback::OnReadComplete)); scoped_refptr<MockDemuxerStream> demuxer_stream = new MockDemuxerStream(); StrictMock<MockFilterCallback> callback; decoder->set_message_loop(&message_loop); @@ -120,7 +130,6 @@ TEST(DecoderBaseTest, FlowControl) { message_loop.RunAllPending(); // Read. - StrictMock<MockDecoderReadCallback> read_callback; std::vector<scoped_refptr<Buffer> > decode_requests; EXPECT_CALL(*demuxer_stream, Read(NotNull())) .Times(2) @@ -128,16 +137,13 @@ TEST(DecoderBaseTest, FlowControl) { EXPECT_CALL(*decoder, DoDecode(NotNull())) .Times(2) .WillRepeatedly(SaveDecodeRequest(&decode_requests)); - decoder->Read( - NewCallback(reinterpret_cast<MockDecoderReadCallback*>(&read_callback), - &MockDecoderReadCallback::ReadCallback)); - decoder->Read( - NewCallback(reinterpret_cast<MockDecoderReadCallback*>(&read_callback), - &MockDecoderReadCallback::ReadCallback)); + scoped_refptr<MockDecoderOutput> output; + decoder->FillThisBuffer(output); + decoder->FillThisBuffer(output); message_loop.RunAllPending(); // Fulfill the decode request. - EXPECT_CALL(read_callback, ReadCallback(NotNull())).Times(2); + EXPECT_CALL(read_callback, OnReadComplete(_)).Times(2); for (size_t i = 0; i < decode_requests.size(); ++i) { decoder->EnqueueResult(new MockDecoderOutput()); decoder->OnDecodeComplete(); diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc index 683a170..4833d34 100644 --- a/media/filters/video_renderer_base.cc +++ b/media/filters/video_renderer_base.cc @@ -146,6 +146,8 @@ void VideoRendererBase::Initialize(VideoDecoder* decoder, decoder_ = decoder; scoped_ptr<FilterCallback> c(callback); + decoder_->set_fill_buffer_done_callback( + NewCallback(this, &VideoRendererBase::OnFillBufferDone)); // Notify the pipeline of the video dimensions. if (!ParseMediaFormat(decoder->media_format(), &width_, &height_, &uses_egl_image_)) { @@ -312,7 +314,7 @@ void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { *frame_out = current_frame_; } -void VideoRendererBase::OnReadComplete(VideoFrame* frame) { +void VideoRendererBase::OnFillBufferDone(scoped_refptr<VideoFrame> frame) { AutoLock auto_lock(lock_); // TODO(ajwong): Work around cause we don't synchronize on stop. Correct @@ -367,7 +369,11 @@ void VideoRendererBase::ScheduleRead_Locked() { DCHECK_NE(kEnded, state_); DCHECK_LT(pending_reads_, kMaxFrames); ++pending_reads_; - decoder_->Read(NewCallback(this, &VideoRendererBase::OnReadComplete)); + // TODO(jiesun): We use dummy buffer to feed decoder to let decoder to + // provide buffer pools. In the future, we may want to implement real + // buffer pool to recycle buffers. + scoped_refptr<VideoFrame> video_frame; + decoder_->FillThisBuffer(video_frame); } base::TimeDelta VideoRendererBase::CalculateSleepDuration( diff --git a/media/filters/video_renderer_base.h b/media/filters/video_renderer_base.h index 24e914d..f66d1cd 100644 --- a/media/filters/video_renderer_base.h +++ b/media/filters/video_renderer_base.h @@ -82,8 +82,9 @@ class VideoRendererBase : public VideoRenderer, virtual void OnFrameAvailable() = 0; private: - // Read complete callback from video decoder and decrements |pending_reads_|. - void OnReadComplete(VideoFrame* frame); + // Callback from video decoder to deliver decoded video frames and decrements + // |pending_reads_|. + void OnFillBufferDone(scoped_refptr<VideoFrame> frame); // Helper method that schedules an asynchronous read from the decoder and // increments |pending_reads_|. diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc index 2cdde22..111df56 100644 --- a/media/filters/video_renderer_base_unittest.cc +++ b/media/filters/video_renderer_base_unittest.cc @@ -48,7 +48,7 @@ class VideoRendererBaseTest : public ::testing::Test { renderer_->set_host(&host_); // Queue all reads from the decoder. - EXPECT_CALL(*decoder_, Read(NotNull())) + EXPECT_CALL(*decoder_, FillThisBuffer(_)) .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::EnqueueCallback)); // Sets the essential media format keys for this decoder. @@ -61,7 +61,7 @@ class VideoRendererBaseTest : public ::testing::Test { } virtual ~VideoRendererBaseTest() { - STLDeleteElements(&read_queue_); + read_queue_.clear(); // Expect a call into the subclass. EXPECT_CALL(*renderer_, OnStop()); @@ -79,12 +79,12 @@ class VideoRendererBaseTest : public ::testing::Test { StrictMock<MockFilterCallback> callback_; MediaFormat decoder_media_format_; - // Receives asynchronous read requests sent to |decoder_|. - std::deque<Callback1<VideoFrame*>::Type*> read_queue_; + // Receives all the buffers that renderer had provided to |decoder_|. + std::deque<scoped_refptr<VideoFrame> > read_queue_; private: - void EnqueueCallback(Callback1<VideoFrame*>::Type* callback) { - read_queue_.push_back(callback); + void EnqueueCallback(scoped_refptr<VideoFrame> frame) { + read_queue_.push_back(frame); } DISALLOW_COPY_AND_ASSIGN(VideoRendererBaseTest); @@ -191,8 +191,7 @@ TEST_F(VideoRendererBaseTest, Initialize_Successful) { scoped_refptr<VideoFrame> frame; VideoFrame::CreateFrame(VideoFrame::RGB32, kWidth, kHeight, kZero, kZero, &frame); - read_queue_.front()->Run(frame); - delete read_queue_.front(); + decoder_->fill_buffer_done_callback()->Run(frame); read_queue_.pop_front(); } } |