summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-13 22:21:01 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-13 22:21:01 +0000
commit95ff808aa05c3de690fed32e92a940a6877cd3ed (patch)
tree0fd037078b5b8b50c253bb68c11d3cabd93b2432 /media
parent108a96fe15de05d91fe9a0a2eb39c3edd287c123 (diff)
downloadchromium_src-95ff808aa05c3de690fed32e92a940a6877cd3ed.zip
chromium_src-95ff808aa05c3de690fed32e92a940a6877cd3ed.tar.gz
chromium_src-95ff808aa05c3de690fed32e92a940a6877cd3ed.tar.bz2
Test program for OpenMAX video decoding
Including gyp file for openmax and the test application. The test application will link against libOmxCore.so which is provided by the target system. Review URL: http://codereview.chromium.org/391030 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31957 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/omx/omx_test.cc163
-rw-r--r--media/omx/omx_test.gyp30
-rw-r--r--media/omx/omx_video_decoder.cc10
-rw-r--r--media/omx/omx_video_decoder.h10
4 files changed, 205 insertions, 8 deletions
diff --git a/media/omx/omx_test.cc b/media/omx/omx_test.cc
new file mode 100644
index 0000000..306a2fd
--- /dev/null
+++ b/media/omx/omx_test.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2009 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.
+
+// A test program that drives an OpenMAX video decoder module. This program
+// will take video in elementary stream and read into the decoder.
+// Usage of this program:
+// ./omx_test --file=<file> --component=<component> --codec=<codec>
+// <file> = Input file name
+// <component> = Name of the OpenMAX component
+// <codec> = Codec to be used, available codecs: h264, vc1, mpeg4, h263.
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "media/omx/input_buffer.h"
+#include "media/omx/omx_video_decoder.h"
+
+// 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 {
+ public:
+ TestApp(const char* filename,
+ const char* component,
+ media::OmxVideoDecoder::Codec codec)
+ : filename_(filename),
+ component_(component),
+ codec_(codec),
+ stopped_(false),
+ error_(false) {
+ }
+
+ void StopCallback() {
+ // If this callback is received, mark the |stopped_| flag so that we don't
+ // feed more buffers into the decoder.
+ // We need to exit the current message loop because we have no more work
+ // to do on the message loop. This is done by calling
+ // message_loop_.Quit().
+ stopped_ = true;
+ message_loop_.Quit();
+ }
+
+ void ErrorCallback() {
+ // In case of error, this method is called. Mark the error flag and
+ // exit the message loop because we have no more work to do.
+ printf("Error callback received!\n");
+ error_ = true;
+ message_loop_.Quit();
+ }
+
+ void FeedCallback(media::InputBuffer* 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
+ // the last buffer is an end-of-stream buffer, when we have stopped, and
+ // when we have received an error.
+ bool eos = buffer->Eos();
+ delete buffer;
+ if (!eos && !stopped_ && !error_)
+ FeedDecoder();
+ }
+
+ void ReadCompleteCallback(uint8* buffer, int size) {
+ // 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.
+ if (stopped_ || error_)
+ return;
+
+ // If we are readding to the end, then stop.
+ if (!size) {
+ decoder_->Stop(NewCallback(this, &TestApp::StopCallback));
+ return;
+ }
+
+ // Read one more from the decoder.
+ decoder_->Read(NewCallback(this, &TestApp::ReadCompleteCallback));
+ }
+
+ void FeedDecoder() {
+ // This method feeds the decoder with 32KB of input data.
+ const int kSize = 32768;
+ uint8* data = new uint8[kSize];
+ int read = fread(data, 1, kSize, file_);
+ decoder_->Feed(new media::InputBuffer(data, read),
+ NewCallback(this, &TestApp::FeedCallback));
+ }
+
+ void Run() {
+ // Open the input file.
+ file_ = fopen(filename_, "rb");
+ if (!file_) {
+ printf("Error - can't open file %s\n", filename_);
+ return;
+ }
+
+ // Setup the decoder with the message loop of the current thread. Also
+ // setup component name, codec and callbacks.
+ decoder_ = new media::OmxVideoDecoder(&message_loop_);
+ decoder_->Setup(component_, codec_);
+ decoder_->SetErrorCallback(NewCallback(this, &TestApp::ErrorCallback));
+
+ // Start the decoder.
+ decoder_->Start();
+ for (int i = 0; i < 20; ++i)
+ FeedDecoder();
+ decoder_->Read(NewCallback(this, &TestApp::ReadCompleteCallback));
+
+ // Execute the message loop so that we can run tasks on it. This call
+ // will return when we call message_loop_.Quit().
+ message_loop_.Run();
+ }
+
+ scoped_refptr<media::OmxVideoDecoder> decoder_;
+ MessageLoop message_loop_;
+ const char* filename_;
+ const char* component_;
+ media::OmxVideoDecoder::Codec codec_;
+ FILE* file_;
+ bool stopped_;
+ bool error_;
+};
+
+int main(int argc, char** argv) {
+ base::AtExitManager at_exit_manager;
+
+ CommandLine::Init(argc, argv);
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+
+ if (argc < 2) {
+ printf("Usage: omx_test --file=FILE --component=COMPONENT --codec=CODEC\n");
+ printf(" COMPONENT: OpenMAX component name\n");
+ printf(" CODEC: h264/mpeg4/h263/vc1\n");
+ return 1;
+ }
+
+ std::string filename = cmd_line->GetSwitchValueASCII("file");
+ std::string component = cmd_line->GetSwitchValueASCII("component");
+ std::string codec = cmd_line->GetSwitchValueASCII("codec");
+
+ media::OmxVideoDecoder::Codec codec_id = media::OmxVideoDecoder::kCodecNone;
+ if (codec == "h264")
+ codec_id = media::OmxVideoDecoder::kCodecH264;
+ else if (codec == "mpeg4")
+ codec_id = media::OmxVideoDecoder::kCodecMpeg4;
+ else if (codec == "h263")
+ codec_id = media::OmxVideoDecoder::kCodecH263;
+ else if (codec == "vc1")
+ codec_id = media::OmxVideoDecoder::kCodecVc1;
+ else {
+ printf("Unknown codec.\n");
+ return 1;
+ }
+
+ // Create a TestApp object and run the decoder.
+ TestApp test(filename.c_str(), component.c_str(), codec_id);
+
+ // This call will run the decoder until EOS is reached or an error
+ // is encountered.
+ test.Run();
+ return 0;
+}
diff --git a/media/omx/omx_test.gyp b/media/omx/omx_test.gyp
new file mode 100644
index 0000000..0e2fcaa
--- /dev/null
+++ b/media/omx/omx_test.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2009 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'conditions': [
+ ['OS=="linux"', {
+ 'targets' : [
+ {
+ 'target_name': 'omx_test',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../third_party/openmax/openmax.gyp:il',
+ ],
+ 'sources': [
+ 'input_buffer.cc',
+ 'input_buffer.h',
+ 'omx_test.cc',
+ 'omx_video_decoder.cc',
+ 'omx_video_decoder.h',
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/media/omx/omx_video_decoder.cc b/media/omx/omx_video_decoder.cc
index 4142ab8..1b2f416 100644
--- a/media/omx/omx_video_decoder.cc
+++ b/media/omx/omx_video_decoder.cc
@@ -35,13 +35,14 @@ OmxVideoDecoder::~OmxVideoDecoder() {
DCHECK(output_queue_.empty());
}
-void OmxVideoDecoder::Setup(Codec codec) {
- DCHECK_EQ(kEmpty, GetState());
+void OmxVideoDecoder::Setup(const char* component, Codec codec) {
+ DCHECK_EQ(kEmpty, state_);
+ component_ = component;
codec_ = codec;
}
void OmxVideoDecoder::SetErrorCallback(Callback* callback) {
- DCHECK_EQ(kEmpty, GetState());
+ DCHECK_EQ(kEmpty, state_);
error_callback_.reset(callback);
}
@@ -278,7 +279,8 @@ void OmxVideoDecoder::Transition_EmptyToLoaded() {
// 2. Get the handle to the component. After OMX_GetHandle(),
// the component is in loaded state.
- component = GetComponentName(codec_);
+ // TODO(hclam): We should have a list of componant names instead.
+ component = component_;
omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&decoder_handle_),
(OMX_STRING)component, this, &callback);
if (omxresult != OMX_ErrorNone) {
diff --git a/media/omx/omx_video_decoder.h b/media/omx/omx_video_decoder.h
index 3da80b9..baf3c51 100644
--- a/media/omx/omx_video_decoder.h
+++ b/media/omx/omx_video_decoder.h
@@ -11,7 +11,7 @@
// // Initialization.
// MessageLoop message_loop;
// OmxVideoDecoder* decoder = new OmxVideoDecoder(&message_loop);
-// decoder->Setup(kCodecH264);
+// decoder->Setup(component_name, kCodecH264);
// decoder->SetErrorCallback(NewCallback(this, &Client::ErrorCallback));
//
// // Start is asynchronous. But we don't need to wait for it to proceed.
@@ -104,9 +104,9 @@ class OmxVideoDecoder : public base::RefCountedThreadSafe<OmxVideoDecoder> {
OmxVideoDecoder(MessageLoop* message_loop);
virtual ~OmxVideoDecoder();
- // Set the input codec format.
- // TODO(hclam): Add input format and output format.
- void Setup(Codec codec);
+ // Set the component name and input codec format.
+ // TODO(hclam): Add input format and output format. Also remove |component|.
+ void Setup(const char* component, Codec codec);
// Set the error callback. In case of error the callback will be called.
void SetErrorCallback(Callback* callback);
@@ -289,6 +289,8 @@ class OmxVideoDecoder : public base::RefCountedThreadSafe<OmxVideoDecoder> {
State state_;
State next_state_;
+ // TODO(hclam): We should keep a list of component names.
+ const char* component_;
Codec codec_;
MessageLoop* message_loop_;