summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/filters/omx_video_decoder.cc111
-rw-r--r--media/filters/omx_video_decoder.h42
-rw-r--r--media/filters/video_decode_engine.h6
3 files changed, 141 insertions, 18 deletions
diff --git a/media/filters/omx_video_decoder.cc b/media/filters/omx_video_decoder.cc
index 8f9a992..f3fd0c2 100644
--- a/media/filters/omx_video_decoder.cc
+++ b/media/filters/omx_video_decoder.cc
@@ -6,7 +6,10 @@
#include "base/callback.h"
#include "base/waitable_event.h"
+#include "media/base/factory.h"
+#include "media/base/filter_host.h"
#include "media/ffmpeg/ffmpeg_common.h"
+#include "media/filters/ffmpeg_interfaces.h"
#include "media/filters/omx_video_decode_engine.h"
namespace media {
@@ -37,26 +40,35 @@ bool OmxVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) {
}
OmxVideoDecoder::OmxVideoDecoder(OmxVideoDecodeEngine* engine)
- : VideoDecoderImpl(engine),
- omx_engine_(engine) {
+ : omx_engine_(engine) {
#if defined(ENABLE_EGLIMAGE)
supports_egl_image_ = true;
#else
supports_egl_image_ = false;
#endif
+ DCHECK(omx_engine_.get());
}
OmxVideoDecoder::~OmxVideoDecoder() {
+ // TODO(hclam): Make sure OmxVideoDecodeEngine is stopped.
}
-void OmxVideoDecoder::DoInitialize(DemuxerStream* demuxer_stream,
- bool* success,
- Task* done_cb) {
- if (supports_egl_image_)
- media_format_.SetAsString(MediaFormat::kMimeType,
- mime_type::kUncompressedVideoEglImage);
+void OmxVideoDecoder::Initialize(DemuxerStream* stream,
+ FilterCallback* callback) {
+ message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &OmxVideoDecoder::DoInitialize,
+ stream,
+ callback));
+}
- VideoDecoderImpl::DoInitialize(demuxer_stream, success, done_cb);
+void OmxVideoDecoder::FillThisBuffer(scoped_refptr<VideoFrame> frame) {
+ DCHECK(omx_engine_.get());
+ message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(omx_engine_.get(),
+ &OmxVideoDecodeEngine::FillThisBuffer, frame));
}
void OmxVideoDecoder::Stop() {
@@ -66,4 +78,85 @@ void OmxVideoDecoder::Stop() {
event.Wait();
}
+void OmxVideoDecoder::DoInitialize(DemuxerStream* demuxer_stream,
+ FilterCallback* callback) {
+ DCHECK_EQ(message_loop(), MessageLoop::current());
+
+ // Sets the output format.
+ if (supports_egl_image_) {
+ media_format_.SetAsString(MediaFormat::kMimeType,
+ mime_type::kUncompressedVideoEglImage);
+ }
+
+ // Savs the demuxer stream.
+ demuxer_stream_ = demuxer_stream;
+
+ // Get the AVStream by querying for the provider interface.
+ AVStreamProvider* av_stream_provider;
+ if (!demuxer_stream->QueryInterface(&av_stream_provider))
+ return;
+ AVStream* av_stream = av_stream_provider->GetAVStream();
+
+ // Initialize the decode engine.
+ omx_engine_->Initialize(
+ message_loop(),
+ av_stream,
+ NewCallback(this, &OmxVideoDecoder::EmptyBufferCallback),
+ NewCallback(this, &OmxVideoDecoder::FillBufferCallback),
+ NewRunnableMethod(this, &OmxVideoDecoder::InitCompleteTask, callback));
+}
+
+void OmxVideoDecoder::FillBufferCallback(scoped_refptr<VideoFrame> frame) {
+ DCHECK_EQ(message_loop(), MessageLoop::current());
+
+ // Invoke the FillBufferDoneCallback with the frame.
+ DCHECK(fill_buffer_done_callback());
+ fill_buffer_done_callback()->Run(frame);
+}
+
+void OmxVideoDecoder::EmptyBufferCallback(scoped_refptr<Buffer> buffer) {
+ DCHECK_EQ(message_loop(), MessageLoop::current());
+
+ // Issue more demux.
+ demuxer_stream_->Read(NewCallback(this, &OmxVideoDecoder::DemuxCompleteTask));
+}
+
+void OmxVideoDecoder::InitCompleteTask(FilterCallback* callback) {
+ DCHECK_EQ(message_loop(), MessageLoop::current());
+
+ // Check the status of the decode engine.
+ if (omx_engine_->state() == VideoDecodeEngine::kError)
+ host()->SetError(PIPELINE_ERROR_DECODE);
+ else
+ InitialDemux();
+
+ callback->Run();
+ delete callback;
+}
+
+void OmxVideoDecoder::DemuxCompleteTask(Buffer* buffer) {
+ // We simply delicate the buffer to the right message loop.
+ scoped_refptr<Buffer> ref_buffer = buffer;
+ DCHECK(omx_engine_.get());
+ message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(omx_engine_.get(),
+ &OmxVideoDecodeEngine::EmptyThisBuffer, ref_buffer));
+}
+
+void OmxVideoDecoder::InitialDemux() {
+ DCHECK_EQ(message_loop(), MessageLoop::current());
+
+ // This is the right time to issue read to the demuxer. The first thing we
+ // need to do here is to determine how many we should read from the
+ // demuxer.
+ // TODO(hclam): Query this number from |omx_engine_|.
+ const int kDemuxPackets = 2;
+ DCHECK(demuxer_stream_);
+ for (int i = 0; i < kDemuxPackets; ++i) {
+ demuxer_stream_->Read(
+ NewCallback(this, &OmxVideoDecoder::DemuxCompleteTask));
+ }
+}
+
} // namespace media
diff --git a/media/filters/omx_video_decoder.h b/media/filters/omx_video_decoder.h
index 22aa56a..c406095 100644
--- a/media/filters/omx_video_decoder.h
+++ b/media/filters/omx_video_decoder.h
@@ -5,33 +5,59 @@
#ifndef MEDIA_FILTERS_OMX_VIDEO_DECODER_H_
#define MEDIA_FILTERS_OMX_VIDEO_DECODER_H_
-#include "media/filters/video_decoder_impl.h"
+#include <queue>
+
+#include "media/base/filters.h"
+#include "media/base/media_format.h"
class MessageLoop;
namespace media {
+class Buffer;
class FilterFactory;
-class MediaFormat;
class OmxVideoDecodeEngine;
+class VideoFrame;
-class OmxVideoDecoder : public VideoDecoderImpl {
+class OmxVideoDecoder : public VideoDecoder {
public:
+ typedef Callback1<VideoFrame*>::Type ReadCallback;
+
static FilterFactory* CreateFactory();
static bool IsMediaFormatSupported(const MediaFormat& media_format);
OmxVideoDecoder(OmxVideoDecodeEngine* engine);
virtual ~OmxVideoDecoder();
+ virtual void Initialize(DemuxerStream* stream, FilterCallback* callback);
virtual void Stop();
-
- protected:
- void DoInitialize(DemuxerStream* demuxer_stream, bool* success,
- Task* done_cb);
+ virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame);
+ virtual const MediaFormat& media_format() { return media_format_; }
private:
+ virtual void DoInitialize(DemuxerStream* stream, FilterCallback* callback);
+
+ // Called after the decode engine has successfully decoded something.
+ void FillBufferCallback(scoped_refptr<VideoFrame> frame);
+
+ // Called after the decode engine has consumed an input buffer.
+ void EmptyBufferCallback(scoped_refptr<Buffer> buffer);
+
+ void InitCompleteTask(FilterCallback* callback);
+ // TODO(hclam): This is very ugly that we keep reference instead of
+ // scoped_refptr.
+ void DemuxCompleteTask(Buffer* buffer);
+
+ // Calls |omx_engine_|'s EmptyThisBuffer() method on the right thread.
+ void EmptyBufferTask(scoped_refptr<Buffer> buffer);
+
+ // Helper method to do the initial demuxing.
+ void InitialDemux();
+
+ DemuxerStream* demuxer_stream_;
bool supports_egl_image_;
- OmxVideoDecodeEngine* omx_engine_;
+ scoped_refptr<OmxVideoDecodeEngine> omx_engine_;
+ MediaFormat media_format_;
DISALLOW_COPY_AND_ASSIGN(OmxVideoDecoder);
};
diff --git a/media/filters/video_decode_engine.h b/media/filters/video_decode_engine.h
index 2cc767a..f0ff923 100644
--- a/media/filters/video_decode_engine.h
+++ b/media/filters/video_decode_engine.h
@@ -32,7 +32,12 @@ class VideoDecodeEngine {
VideoDecodeEngine() {}
virtual ~VideoDecodeEngine() {}
+ // This calback is called by the decode engine to notify that the decode
+ // engine has consumed an input bufer in response to a EmptyThisBuffer() call.
typedef Callback1<scoped_refptr<Buffer> >::Type EmptyThisBufferCallback;
+
+ // This callback is called by the decode engine to notify that a video
+ // frame is ready to be consumed in reaponse to a FillThisBuffer() call.
typedef Callback1<scoped_refptr<VideoFrame> >::Type FillThisBufferCallback;
// Initialized the engine. On successful Initialization, state() should
@@ -55,7 +60,6 @@ class VideoDecodeEngine {
// 2. Output buffers are provided from outside the engine, and feed into
// 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();