diff options
author | jiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-29 19:24:24 +0000 |
---|---|---|
committer | jiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-29 19:24:24 +0000 |
commit | 55683e21a68a2c0df23c126c4a002054bad5725d (patch) | |
tree | 787e82686dffceaac8d0f2b54a1d8a20fdb1510c | |
parent | ce4e83804af1a9f22ec3b23abae603ea3f759b52 (diff) | |
download | chromium_src-55683e21a68a2c0df23c126c4a002054bad5725d.zip chromium_src-55683e21a68a2c0df23c126c4a002054bad5725d.tar.gz chromium_src-55683e21a68a2c0df23c126c4a002054bad5725d.tar.bz2 |
media: OMX seek works for OMX_HEADBUFFERTYPE now.
1. Promote Stop() to engine interafce and make it Asynchronous.
2. Add Pause() and Flush() in engine interface.
3. Notify buffer return in ffmpeg engine so that future recycling could use it.
4. Add Pause logic in OMX decode engine.
to fully support seek in hardware path, some pipeline work and video render work is required. that will be in the next patch (maybe jia will write it).
1. some renderer hack is required for now. but current pause model of videoRenderBase is not suitable for hardware case. we need to resolve that.
2. Seek after EOS is not supported.
3. Seek for EGL image path is not yet tested, some code is required to return EGLImage buffer to allocator's side.
Review URL: http://codereview.chromium.org/2808022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51153 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/filters/decoder_base.h | 10 | ||||
-rw-r--r-- | media/filters/decoder_base_unittest.cc | 7 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decode_engine.cc | 11 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decode_engine.h | 3 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decoder.cc | 10 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decoder.h | 2 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decoder_unittest.cc | 4 | ||||
-rw-r--r-- | media/filters/omx_video_decode_engine.cc | 134 | ||||
-rw-r--r-- | media/filters/omx_video_decode_engine.h | 26 | ||||
-rw-r--r-- | media/filters/omx_video_decoder.cc | 30 | ||||
-rw-r--r-- | media/filters/omx_video_decoder.h | 7 | ||||
-rw-r--r-- | media/filters/video_decode_engine.h | 7 | ||||
-rw-r--r-- | media/omx/omx_codec_unittest.cc | 11 | ||||
-rw-r--r-- | media/tools/omx_test/omx_test.cc | 4 |
14 files changed, 231 insertions, 35 deletions
diff --git a/media/filters/decoder_base.h b/media/filters/decoder_base.h index 82f767e..8796464 100644 --- a/media/filters/decoder_base.h +++ b/media/filters/decoder_base.h @@ -99,9 +99,9 @@ class DecoderBase : public Decoder { // Method that may be implemented by the derived class if desired. It will // be called from within the MediaFilter::Stop() method prior to stopping the // base class. - // - // TODO(ajwong): Make this asynchronous. - virtual void DoStop() {} + virtual void DoStop(Task* done_cb) { + AutoTaskRunner done_runner(done_cb); + } // Derived class can implement this method and perform seeking logic prior // to the base class. @@ -150,8 +150,10 @@ class DecoderBase : public Decoder { DCHECK_EQ(MessageLoop::current(), this->message_loop()); // Delegate to the subclass first. - DoStop(); + DoStop(NewRunnableMethod(this, &DecoderBase::OnStopComplete, callback)); + } + void OnStopComplete(FilterCallback* callback) { // Throw away all buffers in all queues. result_queue_.clear(); state_ = kStopped; diff --git a/media/filters/decoder_base_unittest.cc b/media/filters/decoder_base_unittest.cc index 4bc0531..19ba820 100644 --- a/media/filters/decoder_base_unittest.cc +++ b/media/filters/decoder_base_unittest.cc @@ -5,6 +5,7 @@ #include <vector> #include "media/base/mock_filters.h" +#include "media/base/mock_task.h" #include "media/filters/decoder_base.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -12,6 +13,7 @@ using ::testing::_; using ::testing::NotNull; using ::testing::StrictMock; +using ::testing::WithArg; namespace media { @@ -69,7 +71,7 @@ class MockDecoderImpl : public media::DecoderBase< void(media::DemuxerStream* demuxer_stream, bool* success, Task* done_cb)); - MOCK_METHOD0(DoStop, void()); + MOCK_METHOD1(DoStop, void(Task* done_cb)); MOCK_METHOD2(DoSeek, void(base::TimeDelta time, Task* done_cb)); MOCK_METHOD1(DoDecode, void(media::Buffer* input)); @@ -152,7 +154,8 @@ TEST(DecoderBaseTest, FlowControl) { message_loop.RunAllPending(); // Stop. - EXPECT_CALL(*decoder, DoStop()); + EXPECT_CALL(*decoder, DoStop(_)) + .WillOnce(WithArg<0>(InvokeRunnable())); EXPECT_CALL(callback, OnFilterCallback()); EXPECT_CALL(callback, OnCallbackDestroyed()); decoder->Stop(callback.NewCallback()); diff --git a/media/filters/ffmpeg_video_decode_engine.cc b/media/filters/ffmpeg_video_decode_engine.cc index d84d56c..46e2de0 100644 --- a/media/filters/ffmpeg_video_decode_engine.cc +++ b/media/filters/ffmpeg_video_decode_engine.cc @@ -212,6 +212,17 @@ void FFmpegVideoDecodeEngine::DecodeFrame(scoped_refptr<Buffer> buffer) { fill_this_buffer_callback_->Run(video_frame); } +void FFmpegVideoDecodeEngine::Stop(Task* done_cb) { + // TODO(jiesun): Release buffers when we support buffer recycling. + AutoTaskRunner done_runner(done_cb); +} + +void FFmpegVideoDecodeEngine::Pause(Task* done_cb) { + // TODO(jiesun): Stop out-going buffer exchange when we support + // buffer recycling. + AutoTaskRunner done_runner(done_cb); +} + void FFmpegVideoDecodeEngine::Flush(Task* done_cb) { AutoTaskRunner done_runner(done_cb); diff --git a/media/filters/ffmpeg_video_decode_engine.h b/media/filters/ffmpeg_video_decode_engine.h index 9b0c186..3941c52 100644 --- a/media/filters/ffmpeg_video_decode_engine.h +++ b/media/filters/ffmpeg_video_decode_engine.h @@ -31,6 +31,9 @@ class FFmpegVideoDecodeEngine : public VideoDecodeEngine { FillThisBufferCallback* fill_buffer_callback, Task* done_cb); virtual void EmptyThisBuffer(scoped_refptr<Buffer> buffer); + virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame) {} + virtual void Stop(Task* done_cb); + virtual void Pause(Task* done_cb); virtual void Flush(Task* done_cb); virtual VideoFrame::Format GetSurfaceFormat() const; diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index 361e5f2..716c60d 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc @@ -85,6 +85,10 @@ void FFmpegVideoDecoder::OnInitializeComplete(bool* success, Task* done_cb) { } } +void FFmpegVideoDecoder::DoStop(Task* done_cb) { + decode_engine_->Stop(done_cb); +} + void FFmpegVideoDecoder::DoSeek(base::TimeDelta time, Task* done_cb) { // Everything in the presentation time queue is invalid, clear the queue. while (!pts_heap_.IsEmpty()) @@ -184,6 +188,12 @@ void FFmpegVideoDecoder::OnEmptyBufferDone(scoped_refptr<Buffer> buffer) { DecoderBase<VideoDecoder, VideoFrame>::OnDecodeComplete(); } +void FFmpegVideoDecoder::FillThisBuffer(scoped_refptr<VideoFrame> frame) { + DecoderBase<VideoDecoder, VideoFrame>::FillThisBuffer(frame); + // Notify decode engine the available of new frame. + decode_engine_->FillThisBuffer(frame); +} + void FFmpegVideoDecoder::EnqueueVideoFrame( const scoped_refptr<VideoFrame>& video_frame) { EnqueueResult(video_frame); diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h index 8350492..a66f5e5 100644 --- a/media/filters/ffmpeg_video_decoder.h +++ b/media/filters/ffmpeg_video_decoder.h @@ -29,11 +29,13 @@ class FFmpegVideoDecoder : public DecoderBase<VideoDecoder, VideoFrame> { protected: virtual void DoInitialize(DemuxerStream* demuxer_stream, bool* success, Task* done_cb); + virtual void DoStop(Task* done_cb); virtual void DoSeek(base::TimeDelta time, Task* done_cb); virtual void DoDecode(Buffer* input); protected: virtual void OnEmptyBufferDone(scoped_refptr<Buffer> buffer); + virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame); private: friend class FilterFactoryImpl1<FFmpegVideoDecoder, VideoDecodeEngine*>; diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index d564a73..33b7f5a 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -56,6 +56,8 @@ class MockVideoDecodeEngine : public VideoDecodeEngine { Task* done_cb)); MOCK_METHOD1(EmptyThisBuffer, void(scoped_refptr<Buffer> buffer)); MOCK_METHOD1(FillThisBuffer, void(scoped_refptr<VideoFrame> buffer)); + MOCK_METHOD1(Stop, void(Task* done_cb)); + MOCK_METHOD1(Pause, void(Task* done_cb)); MOCK_METHOD1(Flush, void(Task* done_cb)); MOCK_CONST_METHOD0(state, State()); MOCK_CONST_METHOD0(GetSurfaceFormat, VideoFrame::Format()); @@ -139,6 +141,8 @@ class FFmpegVideoDecoderTest : public testing::Test { // Call Stop() to shut down internal threads. EXPECT_CALL(callback_, OnFilterCallback()); EXPECT_CALL(callback_, OnCallbackDestroyed()); + EXPECT_CALL(*engine_, Stop(_)) + .WillOnce(WithArg<0>(InvokeRunnable())); decoder_->Stop(callback_.NewCallback()); // Finish up any remaining tasks. diff --git a/media/filters/omx_video_decode_engine.cc b/media/filters/omx_video_decode_engine.cc index cb42138..8110cd8 100644 --- a/media/filters/omx_video_decode_engine.cc +++ b/media/filters/omx_video_decode_engine.cc @@ -38,6 +38,7 @@ OmxVideoDecodeEngine::OmxVideoDecodeEngine() input_buffer_size_(0), input_port_(0), input_buffers_at_component_(0), + input_pending_request_(0), input_queue_has_eos_(false), input_has_fed_eos_(false), output_buffer_count_(0), @@ -116,6 +117,8 @@ void OmxVideoDecodeEngine::EmptyThisBuffer(scoped_refptr<Buffer> buffer) { DCHECK_EQ(message_loop_, MessageLoop::current()); DCHECK(!free_input_buffers_.empty()); + --input_pending_request_; + if (!CanAcceptInput()) { FinishEmptyBuffer(buffer); return; @@ -141,14 +144,115 @@ void OmxVideoDecodeEngine::EmptyThisBuffer(scoped_refptr<Buffer> buffer) { // Try to feed buffers into the decoder. EmptyBufferTask(); + + if (il_state_ == kIlPause && input_pending_request_ == 0) { + if (pause_callback_.get()) { + pause_callback_->Run(); + pause_callback_.reset(); + } + } +} + +void OmxVideoDecodeEngine::Pause(Task* done_cb) { + message_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &OmxVideoDecodeEngine::PauseTask, done_cb)); +} + +void OmxVideoDecodeEngine::PauseTask(Task* done_cb) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK_EQ(il_state_, kIlExecuting); + + pause_callback_.reset(done_cb); + + client_state_ = kClientFlushing; + + expected_il_state_ = kIlPause; + OnStateSetEventFunc = &OmxVideoDecodeEngine::PauseFromExecuting; + TransitionToState(OMX_StatePause); +} + +void OmxVideoDecodeEngine::PauseFromExecuting(OMX_STATETYPE state) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + + OnStateSetEventFunc = NULL; + il_state_ = kIlPause; + + if (input_pending_request_ == 0 ) { + if (pause_callback_.get()) { + pause_callback_->Run(); + pause_callback_.reset(NULL); + } + } } void OmxVideoDecodeEngine::Flush(Task* done_cb) { + message_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &OmxVideoDecodeEngine::FlushTask, done_cb)); +} + +void OmxVideoDecodeEngine::FlushTask(Task* done_cb) { DCHECK_EQ(message_loop_, MessageLoop::current()); - AutoTaskRunner done_cb_runner(done_cb); + if (client_state_ != kClientFlushing) { + // TODO(jiesun): how to prevent initial seek. + AutoTaskRunner done_runner(done_cb); + return; + } + + flush_callback_.reset(done_cb); + + // TODO(jiesun): return buffers to filter who allocate them. + while (!output_frames_ready_.empty()) + output_frames_ready_.pop(); + + while (!available_input_buffers_.empty()) + available_input_buffers_.pop(); + + input_port_flushed_ = false; + output_port_flushed_ = false; + OnFlushEventFunc = &OmxVideoDecodeEngine::PortFlushDone; + OMX_ERRORTYPE omxresult; + omxresult = OMX_SendCommand(component_handle_, + OMX_CommandFlush, + OMX_ALL, 0); +} + +bool OmxVideoDecodeEngine::InputPortFlushed() { + DCHECK_EQ(client_state_, kClientFlushing); + // Port flushed is defined by OpenMAX component had signal flush done and + // We had all buffers returned from demuxer and OpenMAX component. + int free_input_size = static_cast<int>(free_input_buffers_.size()); + return input_port_flushed_ && free_input_size == input_buffer_count_; +} - // TODO(wjia): to flush component +bool OmxVideoDecodeEngine::OutputPortFlushed() { + DCHECK_EQ(client_state_, kClientFlushing); + // Port flushed is defined by OpenMAX component had signal flush done and + // We had all buffers returned from renderer and OpenMAX component. + // TODO(jiesun): egl image path may use different value. + return output_port_flushed_ /*&& + available_output_frames_.size() == output_buffer_count_*/; +} + +void OmxVideoDecodeEngine::ComponentFlushDone() { + if (flush_callback_.get()) { + flush_callback_->Run(); + flush_callback_.reset(NULL); + + InitialReadBuffer(); + OnStateSetEventFunc = &OmxVideoDecodeEngine::DoneSetStateExecuting; + TransitionToState(OMX_StateExecuting); + } +} + +void OmxVideoDecodeEngine::PortFlushDone(int port) { + if (port == input_port_ || port == static_cast<int>(OMX_ALL)) + input_port_flushed_ = true; + if (port == output_port_ || port == static_cast<int>(OMX_ALL)) + output_port_flushed_ = true; + + if (InputPortFlushed() && OutputPortFlushed()) + ComponentFlushDone(); } VideoFrame::Format OmxVideoDecodeEngine::GetSurfaceFormat() const { @@ -181,7 +285,7 @@ VideoDecodeEngine::State OmxVideoDecodeEngine::state() const { return kError; } -void OmxVideoDecodeEngine::Stop(Callback0::Type* done_cb) { +void OmxVideoDecodeEngine::Stop(Task* done_cb) { // TODO(wjia): make this call in the thread. // DCHECK_EQ(message_loop_, MessageLoop::current()); @@ -203,8 +307,10 @@ void OmxVideoDecodeEngine::OnFormatChange( void OmxVideoDecodeEngine::FinishEmptyBuffer(scoped_refptr<Buffer> buffer) { DCHECK_EQ(message_loop_, MessageLoop::current()); - if (!input_queue_has_eos_) + if (!input_queue_has_eos_) { empty_this_buffer_callback_->Run(buffer); + ++input_pending_request_; + } } void OmxVideoDecodeEngine::FinishFillBuffer(OMX_BUFFERHEADERTYPE* buffer) { @@ -687,10 +793,10 @@ void OmxVideoDecodeEngine::OnPortEnableEventRun(int port) { } // Functions for stopping -void OmxVideoDecodeEngine::StopTask(Callback* callback) { +void OmxVideoDecodeEngine::StopTask(Task* task) { DCHECK_EQ(message_loop_, MessageLoop::current()); - stop_callback_.reset(callback); + stop_callback_.reset(task); if (client_state_ == kClientError) { OnStopDone(); @@ -1115,7 +1221,8 @@ void OmxVideoDecodeEngine::EmptyBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) { Buffer* stored_buffer = static_cast<Buffer*>(buffer->pAppPrivate); buffer->pAppPrivate = NULL; - FinishEmptyBuffer(stored_buffer); + if (client_state_ != kClientFlushing) + FinishEmptyBuffer(stored_buffer); stored_buffer->Release(); // Enqueue the available buffer because the decoder has consumed it. @@ -1127,6 +1234,10 @@ void OmxVideoDecodeEngine::EmptyBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) { // Try to feed more data into the decoder. EmptyBufferTask(); + + if (client_state_ == kClientFlushing && + InputPortFlushed() && OutputPortFlushed()) + ComponentFlushDone(); } void OmxVideoDecodeEngine::FillBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) { @@ -1142,10 +1253,17 @@ void OmxVideoDecodeEngine::FillBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) { output_eos_ = true; DLOG(INFO) << "Output has EOS"; } - output_frames_ready_.push(buffer); + + // TODO(jiesun): return this buffer to allocator? + if (client_state_ != kClientFlushing) + output_frames_ready_.push(buffer); // Try to fulfill one read request. FulfillOneRead(); + + if (client_state_ == kClientFlushing && + InputPortFlushed() && OutputPortFlushed()) + ComponentFlushDone(); } void OmxVideoDecodeEngine::EventHandlerCompleteTask(OMX_EVENTTYPE event, diff --git a/media/filters/omx_video_decode_engine.h b/media/filters/omx_video_decode_engine.h index 83480d0..24ee407 100644 --- a/media/filters/omx_video_decode_engine.h +++ b/media/filters/omx_video_decode_engine.h @@ -44,18 +44,13 @@ class OmxVideoDecodeEngine : Task* done_cb); virtual void EmptyThisBuffer(scoped_refptr<Buffer> buffer); virtual void FillThisBuffer(scoped_refptr<VideoFrame> video_frame); + virtual void Stop(Task* done_cb); + virtual void Pause(Task* done_cb); virtual void Flush(Task* done_cb); virtual VideoFrame::Format GetSurfaceFormat() const; virtual State state() const; - // Stops the engine. - // - // TODO(ajwong): Normalize this interface with Task like the others, and - // promote to the abstract interface. - // TODO(boliu): Should the callback type be FilterCallback*? - virtual void Stop(Callback0::Type* done_cb); - // Subclass can provide a different value. virtual int current_omx_spec_version() const { return 0x00000101; } @@ -102,7 +97,9 @@ class OmxVideoDecodeEngine : // Methods to be executed in |message_loop_|, they correspond to the // public methods. void InitializeTask(); - void StopTask(Callback* callback); + void StopTask(Task* task); + void PauseTask(Task* task); + void FlushTask(Task* task); // Transition method sequence for initialization bool CreateComponent(); @@ -117,6 +114,9 @@ class OmxVideoDecodeEngine : void DeinitFromExecuting(OMX_STATETYPE state); void DeinitFromIdle(OMX_STATETYPE state); void DeinitFromLoaded(OMX_STATETYPE state); + void PauseFromExecuting(OMX_STATETYPE state); + void PortFlushDone(int port); + void ComponentFlushDone(); void StopOnError(); @@ -140,6 +140,9 @@ class OmxVideoDecodeEngine : bool CanAcceptInput(); bool CanAcceptOutput(); + bool InputPortFlushed(); + bool OutputPortFlushed(); + // Method to send input buffers to component void EmptyBufferTask(); @@ -203,14 +206,17 @@ class OmxVideoDecodeEngine : int input_buffer_size_; int input_port_; int input_buffers_at_component_; + int input_pending_request_; bool input_queue_has_eos_; bool input_has_fed_eos_; + bool input_port_flushed_; std::vector<OMX_BUFFERHEADERTYPE*> output_buffers_; int output_buffer_count_; int output_buffer_size_; int output_port_; bool output_eos_; + bool output_port_flushed_; bool uses_egl_image_; base::TimeDelta last_pts_; @@ -228,7 +234,9 @@ class OmxVideoDecodeEngine : scoped_ptr<EmptyThisBufferCallback> empty_this_buffer_callback_; scoped_ptr<FillThisBufferCallback> fill_this_buffer_callback_; - scoped_ptr<Callback> stop_callback_; + scoped_ptr<Task> stop_callback_; + scoped_ptr<Task> flush_callback_; + scoped_ptr<Task> pause_callback_; // Free input OpenMAX buffers that can be used to take input bitstream from // demuxer. diff --git a/media/filters/omx_video_decoder.cc b/media/filters/omx_video_decoder.cc index eb9d598..ceabccc 100644 --- a/media/filters/omx_video_decoder.cc +++ b/media/filters/omx_video_decoder.cc @@ -6,6 +6,7 @@ #include "base/callback.h" #include "base/waitable_event.h" +#include "media/base/callback.h" #include "media/base/factory.h" #include "media/base/filter_host.h" #include "media/base/limits.h" @@ -73,7 +74,34 @@ void OmxVideoDecoder::FillThisBuffer(scoped_refptr<VideoFrame> frame) { } void OmxVideoDecoder::Stop(FilterCallback* callback) { - omx_engine_->Stop(callback); + omx_engine_->Stop( + NewRunnableMethod(this, + &OmxVideoDecoder::StopCompleteTask, callback)); +} + +void OmxVideoDecoder::StopCompleteTask(FilterCallback* callback) { + AutoCallbackRunner done_runner(callback); +} + +void OmxVideoDecoder::Pause(FilterCallback* callback) { + omx_engine_->Pause( + NewRunnableMethod(this, + &OmxVideoDecoder::PauseCompleteTask, callback)); +} + +void OmxVideoDecoder::PauseCompleteTask(FilterCallback* callback) { + AutoCallbackRunner done_runner(callback); +} + +void OmxVideoDecoder::Seek(base::TimeDelta time, + FilterCallback* callback) { + omx_engine_->Flush( + NewRunnableMethod(this, + &OmxVideoDecoder::SeekCompleteTask, callback)); +} + +void OmxVideoDecoder::SeekCompleteTask(FilterCallback* callback) { + AutoCallbackRunner done_runner(callback); } void OmxVideoDecoder::DoInitialize(DemuxerStream* demuxer_stream, diff --git a/media/filters/omx_video_decoder.h b/media/filters/omx_video_decoder.h index 236130b..5f747ad 100644 --- a/media/filters/omx_video_decoder.h +++ b/media/filters/omx_video_decoder.h @@ -29,6 +29,8 @@ class OmxVideoDecoder : public VideoDecoder { virtual void Initialize(DemuxerStream* stream, FilterCallback* callback); virtual void Stop(FilterCallback* callback); + virtual void Pause(FilterCallback* callback); + virtual void Seek(base::TimeDelta time, FilterCallback* callback); virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame); virtual const MediaFormat& media_format() { return media_format_; } @@ -42,6 +44,11 @@ class OmxVideoDecoder : public VideoDecoder { void EmptyBufferCallback(scoped_refptr<Buffer> buffer); void InitCompleteTask(FilterCallback* callback); + + void StopCompleteTask(FilterCallback* callback); + void PauseCompleteTask(FilterCallback* callback); + void SeekCompleteTask(FilterCallback* callback); + // TODO(hclam): This is very ugly that we keep reference instead of // scoped_refptr. void DemuxCompleteTask(Buffer* buffer); diff --git a/media/filters/video_decode_engine.h b/media/filters/video_decode_engine.h index f0ff923..8dc9d25 100644 --- a/media/filters/video_decode_engine.h +++ b/media/filters/video_decode_engine.h @@ -61,9 +61,10 @@ class VideoDecodeEngine { // engine through |FillThisBuffer|. Output buffers are returned to outside // by |FillThisBufferCallback|. virtual void EmptyThisBuffer(scoped_refptr<Buffer> buffer) = 0; - virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame) { - NOTREACHED(); - }; + virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame) = 0; + + virtual void Stop(Task* done_cb) = 0; + virtual void Pause(Task* done_cb) = 0; // Flushes the decode engine of any buffered input packets. virtual void Flush(Task* done_cb) = 0; diff --git a/media/omx/omx_codec_unittest.cc b/media/omx/omx_codec_unittest.cc index 71a9ca7..b1960b9 100644 --- a/media/omx/omx_codec_unittest.cc +++ b/media/omx/omx_codec_unittest.cc @@ -295,8 +295,7 @@ class OmxCodecTest : public testing::Test { } void ExpectStop() { - EXPECT_CALL(stop_callback_, OnFilterCallback()); - EXPECT_CALL(stop_callback_, OnCallbackDestroyed()); + EXPECT_CALL(stop_task_, Run()); ExpectToIdle(); ExpectIdleToLoaded(); ExpectToEmpty(); @@ -355,7 +354,7 @@ class OmxCodecTest : public testing::Test { VideoDecodeEngine::FillThisBufferCallback* decode_done_cb_; TaskMocker init_done_cb_task_; - MockFilterCallback stop_callback_; + TaskMocker stop_task_; private: DISALLOW_COPY_AND_ASSIGN(OmxCodecTest); @@ -375,7 +374,7 @@ TEST_F(OmxCodecTest, SimpleStartAndStop) { EXPECT_EQ(VideoDecodeEngine::kNormal, omx_engine_->state()); ExpectStop(); - omx_engine_->Stop(stop_callback_.NewCallback()); + omx_engine_->Stop(stop_task_.CreateTask()); message_loop_.RunAllPending(); } @@ -422,7 +421,7 @@ TEST_F(OmxCodecTest, NormalFlow) { // Shutdown. ExpectStop(); - omx_engine_->Stop(stop_callback_.NewCallback()); + omx_engine_->Stop(stop_task_.CreateTask()); message_loop_.RunAllPending(); } @@ -474,7 +473,7 @@ TEST_F(OmxCodecTest, RecycleInputBuffers) { // Shutdown. ExpectStop(); - omx_engine_->Stop(stop_callback_.NewCallback()); + omx_engine_->Stop(stop_task_.CreateTask()); message_loop_.RunAllPending(); } diff --git a/media/tools/omx_test/omx_test.cc b/media/tools/omx_test/omx_test.cc index 2b39fee..9a185e6 100644 --- a/media/tools/omx_test/omx_test.cc +++ b/media/tools/omx_test/omx_test.cc @@ -126,9 +126,9 @@ class TestApp : public base::RefCountedThreadSafe<TestApp> { if (!frame_count_) first_sample_delivered_time_ = base::TimeTicks::HighResNow(); - // If we are readding to the end, then stop. + // If we are reading to the end, then stop. if (frame->IsEndOfStream()) { - engine_->Stop(NewCallback(this, &TestApp::StopCallback)); + engine_->Stop(NewRunnableMethod(this, &TestApp::StopCallback)); return; } |