Index: media/tools/omx_test/omx_test.cc |
diff --git a/media/tools/omx_test/omx_test.cc b/media/tools/omx_test/omx_test.cc |
index f12db14517e6fe6a8b5fbe65e94c74e601b3d8d6..560e6d6b9b5229444fec1d13c001bb87584edf26 100644 |
--- a/media/tools/omx_test/omx_test.cc |
+++ b/media/tools/omx_test/omx_test.cc |
@@ -14,37 +14,42 @@ |
#include "base/message_loop.h" |
#include "base/scoped_ptr.h" |
#include "base/time.h" |
+#include "media/base/data_buffer.h" |
#include "media/base/media.h" |
+#include "media/base/video_frame.h" |
#include "media/ffmpeg/ffmpeg_common.h" |
#include "media/ffmpeg/file_protocol.h" |
#include "media/filters/bitstream_converter.h" |
-#include "media/omx/omx_codec.h" |
-#include "media/base/data_buffer.h" |
+#include "media/filters/omx_video_decode_engine.h" |
#include "media/tools/omx_test/color_space_util.h" |
#include "media/tools/omx_test/file_reader_util.h" |
#include "media/tools/omx_test/file_sink.h" |
using media::BlockFileReader; |
+using media::Buffer; |
+using media::DataBuffer; |
using media::FFmpegFileReader; |
using media::FileReader; |
using media::FileSink; |
using media::H264FileReader; |
-using media::OmxCodec; |
using media::OmxConfigurator; |
using media::OmxDecoderConfigurator; |
using media::OmxEncoderConfigurator; |
+using media::OmxVideoDecodeEngine; |
+using media::VideoFrame; |
using media::YuvFileReader; |
-using media::Buffer; |
-using media::DataBuffer; |
// This is the driver object to feed the decoder with data from a file. |
// It also provides callbacks for the decoder to receive events from the |
// decoder. |
-class TestApp { |
+// TODO(wjia): AVStream should be replaced with a new structure which is |
+// neutral to any video decoder. Also change media.gyp correspondingly. |
+class TestApp : public base::RefCountedThreadSafe<TestApp> { |
public: |
- TestApp(OmxConfigurator* configurator, FileSink* file_sink, |
+ TestApp(AVStream* av_stream, |
+ FileSink* file_sink, |
FileReader* file_reader) |
- : configurator_(configurator), |
+ : av_stream_(av_stream), |
file_reader_(file_reader), |
file_sink_(file_sink), |
stopped_(false), |
@@ -65,6 +70,9 @@ class TestApp { |
return true; |
} |
+ void InitializeDoneCallback() { |
+ } |
+ |
void StopCallback() { |
// If this callback is received, mark the |stopped_| flag so that we don't |
// feed more buffers into the decoder. |
@@ -98,7 +106,7 @@ class TestApp { |
input_format.video_header.height); |
} |
- void FeedCompleteCallback(scoped_refptr<Buffer> buffer) { |
+ void FeedDoneCallback(scoped_refptr<Buffer> buffer) { |
// We receive this callback when the decoder has consumed an input buffer. |
// In this case, delete the previous buffer and enqueue a new one. |
// There are some conditions we don't want to enqueue, for example when |
@@ -109,9 +117,9 @@ class TestApp { |
FeedInputBuffer(); |
} |
- void ReadCompleteCallback(OMX_BUFFERHEADERTYPE* buffer) { |
+ void DecodeDoneCallback(scoped_refptr<VideoFrame> frame) { |
// This callback is received when the decoder has completed a decoding |
- // task and given us some output data. The buffer is owned by the decoder. |
+ // task and given us some output data. The frame is owned by the decoder. |
if (stopped_ || error_) |
return; |
@@ -119,13 +127,18 @@ class TestApp { |
first_sample_delivered_time_ = base::TimeTicks::HighResNow(); |
// If we are readding to the end, then stop. |
- if (buffer == NULL) { |
- codec_->Stop(NewCallback(this, &TestApp::StopCallback)); |
+ if (frame.get() == NULL) { |
+ engine_->Stop(NewCallback(this, &TestApp::StopCallback)); |
return; |
} |
- if (file_sink_.get()) |
- file_sink_->BufferReady(buffer->nFilledLen, buffer->pBuffer); |
+ if (file_sink_.get()) { |
+ for (size_t i = 0; i < frame->planes(); i++) { |
+ int plane_size = frame->width() * frame->height(); |
+ if (i > 0) plane_size >>= 2; |
+ file_sink_->BufferReady(plane_size, frame->data(i)); |
+ } |
+ } |
// could OMX IL return patial sample for decoder? |
frame_count_++; |
@@ -135,23 +148,22 @@ class TestApp { |
uint8* data; |
int read; |
file_reader_->Read(&data, &read); |
- codec_->Feed(new DataBuffer(data, read)); |
+ engine_->EmptyThisBuffer(new DataBuffer(data, read)); |
} |
void Run() { |
StartProfiler(); |
- // Setup the |codec_| with the message loop of the current thread. Also |
- // setup component name, codec format and callbacks. |
- codec_ = new OmxCodec(&message_loop_); |
- codec_->Setup(configurator_.get(), |
- NewCallback(this, &TestApp::FeedCompleteCallback), |
- NewCallback(this, &TestApp::ReadCompleteCallback)); |
- codec_->SetErrorCallback(NewCallback(this, &TestApp::ErrorCallback)); |
- codec_->SetFormatCallback(NewCallback(this, &TestApp::FormatCallback)); |
- |
- // Start the |codec_|. |
- codec_->Start(); |
+ // Setup the |engine_| with the message loop of the current thread. Also |
+ // setup codec format and callbacks. |
+ engine_ = new OmxVideoDecodeEngine(); |
+ engine_->Initialize(&message_loop_, |
+ av_stream_.get(), |
+ NewCallback(this, &TestApp::FeedDoneCallback), |
+ NewCallback(this, &TestApp::DecodeDoneCallback), |
+ NewRunnableMethod(this, |
+ &TestApp::InitializeDoneCallback)); |
+ |
for (int i = 0; i < 20; ++i) |
FeedInputBuffer(); |
@@ -184,9 +196,9 @@ class TestApp { |
printf("\n"); |
} |
- scoped_refptr<OmxCodec> codec_; |
+ scoped_refptr<OmxVideoDecodeEngine> engine_; |
MessageLoop message_loop_; |
- scoped_ptr<OmxConfigurator> configurator_; |
+ scoped_ptr<AVStream> av_stream_; |
scoped_ptr<FileReader> file_reader_; |
scoped_ptr<FileSink> file_sink_; |
@@ -214,43 +226,48 @@ static int GetIntSwitch(const char* name) { |
return 0; |
} |
-static bool PrepareDecodeFormats(OmxConfigurator::MediaFormat* input, |
- OmxConfigurator::MediaFormat* output) { |
+static bool PrepareDecodeFormats(AVStream *av_stream) { |
std::string codec = GetStringSwitch("codec"); |
- input->codec = OmxConfigurator::kCodecNone; |
+ av_stream->codec->codec_id = CODEC_ID_NONE; |
if (codec == "h264") { |
- input->codec = OmxConfigurator::kCodecH264; |
+ av_stream->codec->codec_id = CODEC_ID_H264; |
} else if (codec == "mpeg4") { |
- input->codec = OmxConfigurator::kCodecMpeg4; |
+ av_stream->codec->codec_id = CODEC_ID_MPEG4; |
} else if (codec == "h263") { |
- input->codec = OmxConfigurator::kCodecH263; |
+ av_stream->codec->codec_id = CODEC_ID_H263; |
} else if (codec == "vc1") { |
- input->codec = OmxConfigurator::kCodecVc1; |
+ av_stream->codec->codec_id = CODEC_ID_VC1; |
} else { |
LOG(ERROR) << "Unknown codec."; |
return false; |
} |
- output->codec = OmxConfigurator::kCodecRaw; |
return true; |
} |
-static bool PrepareEncodeFormats(OmxConfigurator::MediaFormat* input, |
- OmxConfigurator::MediaFormat* output) { |
- input->codec = OmxConfigurator::kCodecRaw; |
- input->video_header.width = GetIntSwitch("width"); |
- input->video_header.height = GetIntSwitch("height"); |
- input->video_header.frame_rate = GetIntSwitch("framerate"); |
- // TODO(jiesun): make other format available. |
- output->codec = OmxConfigurator::kCodecMpeg4; |
- output->video_header.width = GetIntSwitch("width"); |
- output->video_header.height = GetIntSwitch("height"); |
- output->video_header.frame_rate = GetIntSwitch("framerate"); |
+static bool PrepareEncodeFormats(AVStream *av_stream) { |
+ av_stream->codec->width = GetIntSwitch("width"); |
+ av_stream->codec->height = GetIntSwitch("height"); |
+ av_stream->avg_frame_rate.num = GetIntSwitch("framerate"); |
+ av_stream->avg_frame_rate.den = 1; |
+ |
+ std::string codec = GetStringSwitch("codec"); |
+ av_stream->codec->codec_id = CODEC_ID_NONE; |
+ if (codec == "h264") { |
+ av_stream->codec->codec_id = CODEC_ID_H264; |
+ } else if (codec == "mpeg4") { |
+ av_stream->codec->codec_id = CODEC_ID_MPEG4; |
+ } else if (codec == "h263") { |
+ av_stream->codec->codec_id = CODEC_ID_H263; |
+ } else if (codec == "vc1") { |
+ av_stream->codec->codec_id = CODEC_ID_VC1; |
+ } else { |
+ LOG(ERROR) << "Unknown codec."; |
+ return false; |
+ } |
// TODO(jiesun): assume constant bitrate now. |
- output->video_header.bit_rate = GetIntSwitch("bitrate"); |
- // TODO(jiesun): one I frame per second now. make it configurable. |
- output->video_header.i_dist = output->video_header.frame_rate; |
- // TODO(jiesun): disable B frame now. does they support it? |
- output->video_header.p_dist = 0; |
+ av_stream->codec->bit_rate = GetIntSwitch("bitrate"); |
+ |
+ // TODO(wjia): add more configurations needed by encoder |
return true; |
} |
@@ -328,21 +345,26 @@ int main(int argc, char** argv) { |
return -1; |
} |
- // Set the media formats for I/O. |
- OmxConfigurator::MediaFormat input, output; |
- memset(&input, 0, sizeof(input)); |
- memset(&output, 0, sizeof(output)); |
+ // Create AVStream |
+ AVStream *av_stream = new AVStream; |
+ AVCodecContext *av_codec_context = new AVCodecContext; |
+ memset(av_stream, 0, sizeof(AVStream)); |
+ memset(av_codec_context, 0, sizeof(AVCodecContext)); |
+ scoped_ptr<AVCodecContext> av_codec_context_deleter(av_codec_context); |
+ av_stream->codec = av_codec_context; |
+ av_codec_context->width = 320; |
+ av_codec_context->height = 240; |
if (encoder) |
- PrepareEncodeFormats(&input, &output); |
+ PrepareEncodeFormats(av_stream); |
else |
- PrepareDecodeFormats(&input, &output); |
+ PrepareDecodeFormats(av_stream); |
// Creates the FileReader to read input file. |
FileReader* file_reader; |
if (encoder) { |
file_reader = new YuvFileReader( |
- input_filename.c_str(), input.video_header.width, |
- input.video_header.height, loop_count, enable_csc); |
+ input_filename.c_str(), av_stream->codec->width, |
+ av_stream->codec->height, loop_count, enable_csc); |
} else if (use_ffmpeg) { |
// Use ffmepg for reading. |
file_reader = new FFmpegFileReader(input_filename.c_str()); |
@@ -354,25 +376,18 @@ int main(int argc, char** argv) { |
file_reader = new BlockFileReader(input_filename.c_str(), kReadSize); |
} |
- // Create the configurator. |
- OmxConfigurator* configurator; |
- if (encoder) |
- configurator = new OmxEncoderConfigurator(input, output); |
- else |
- configurator = new OmxDecoderConfigurator(input, output); |
- |
// Create a file sink. |
FileSink* file_sink = new FileSink(output_filename, copy, enable_csc); |
// Create a test app object and initialize it. |
- TestApp test(configurator, file_sink, file_reader); |
- if (!test.Initialize()) { |
+ scoped_refptr<TestApp> test = new TestApp(av_stream, file_sink, file_reader); |
+ if (!test->Initialize()) { |
LOG(ERROR) << "can't initialize this application"; |
return -1; |
} |
// This will run the decoder until EOS is reached or an error |
// is encountered. |
- test.Run(); |
+ test->Run(); |
return 0; |
} |