summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-12 00:36:15 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-12 00:36:15 +0000
commit62ed4d36e4357deaf863711bdfd1f00b367c426a (patch)
treeba8a618445d2751b6623b1726da8b4c137771c7c /media
parent7ef2985582f44c345638d06325541bdfc9ecdc87 (diff)
downloadchromium_src-62ed4d36e4357deaf863711bdfd1f00b367c426a.zip
chromium_src-62ed4d36e4357deaf863711bdfd1f00b367c426a.tar.gz
chromium_src-62ed4d36e4357deaf863711bdfd1f00b367c426a.tar.bz2
omx_test refactor to add encoder support. (only start)
1. add --dumpraw options 2. add --dumpyuv options to convert NV21 to IYUV 3. change StartUp() function to take input and output format. Reviewed: http://codereview.chromium.org/523044/show Submitted for: jiesun@chromium.org Review URL: http://codereview.chromium.org/542017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35976 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/filters/omx_video_decode_engine.cc8
-rw-r--r--media/omx/omx_codec.cc101
-rw-r--r--media/omx/omx_codec.h84
-rw-r--r--media/omx/omx_test.cc208
4 files changed, 316 insertions, 85 deletions
diff --git a/media/filters/omx_video_decode_engine.cc b/media/filters/omx_video_decode_engine.cc
index 3404f3f..2da3a56 100644
--- a/media/filters/omx_video_decode_engine.cc
+++ b/media/filters/omx_video_decode_engine.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -33,7 +33,11 @@ void OmxVideoDecodeEngine::Initialize(AVStream* stream, Task* done_cb) {
frame_bytes_ = (width_ * height_ * 3) / 2;
// TODO(ajwong): Find the right way to determine the Omx component name.
- omx_codec_->Setup("OMX.st.video_decoder.avc", OmxCodec::kCodecH264);
+ OmxCodec::OmxMediaFormat input_format;
+ input_format.codec = OmxCodec::kCodecH264;
+ OmxCodec::OmxMediaFormat output_format;
+ output_format.codec = OmxCodec::kCodecRaw;
+ omx_codec_->Setup("OMX.st.video_decoder.avc", input_format, output_format);
omx_codec_->SetErrorCallback(
NewCallback(this, &OmxVideoDecodeEngine::OnHardwareError));
omx_codec_->Start();
diff --git a/media/omx/omx_codec.cc b/media/omx/omx_codec.cc
index d67798d56..6a33a87 100644
--- a/media/omx/omx_codec.cc
+++ b/media/omx/omx_codec.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// Copyright (c) 2010 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.
@@ -26,10 +26,10 @@ OmxCodec::OmxCodec(MessageLoop* message_loop)
output_buffer_size_(0),
output_port_(0),
output_eos_(false),
- decoder_handle_(NULL),
state_(kEmpty),
next_state_(kEmpty),
- codec_(kCodecNone),
+ component_name_(NULL),
+ component_handle_(NULL),
message_loop_(message_loop) {
}
@@ -43,10 +43,16 @@ OmxCodec::~OmxCodec() {
DCHECK(output_queue_.empty());
}
-void OmxCodec::Setup(const char* component, Codec codec) {
+void OmxCodec::Setup(
+ const char* component_name,
+ const OmxCodec::OmxMediaFormat& input_format,
+ const OmxCodec::OmxMediaFormat& output_format) {
DCHECK_EQ(kEmpty, state_);
- component_ = component;
- codec_ = codec;
+ DCHECK_NE(input_format.codec, kCodecNone);
+ component_name_ = component_name;
+ input_format_ = input_format;
+ output_format_ = output_format;
+ encoder_ = input_format_.codec == kCodecRaw;
}
void OmxCodec::SetErrorCallback(Callback* callback) {
@@ -55,7 +61,7 @@ void OmxCodec::SetErrorCallback(Callback* callback) {
}
void OmxCodec::Start() {
- DCHECK_NE(kCodecNone, codec_);
+ DCHECK_NE(kCodecNone, input_format_.codec);
message_loop_->PostTask(
FROM_HERE,
@@ -177,7 +183,7 @@ bool OmxCodec::AllocateInputBuffers() {
for(int i = 0; i < input_buffer_count_; ++i) {
OMX_BUFFERHEADERTYPE* buffer;
OMX_ERRORTYPE error =
- OMX_AllocateBuffer(decoder_handle_, &buffer, input_port_,
+ OMX_AllocateBuffer(component_handle_, &buffer, input_port_,
NULL, input_buffer_size_);
if (error != OMX_ErrorNone)
return false;
@@ -197,7 +203,7 @@ bool OmxCodec::AllocateOutputBuffers() {
for(int i = 0; i < output_buffer_count_; ++i) {
OMX_BUFFERHEADERTYPE* buffer;
OMX_ERRORTYPE error =
- OMX_AllocateBuffer(decoder_handle_, &buffer, output_port_,
+ OMX_AllocateBuffer(component_handle_, &buffer, output_port_,
NULL, output_buffer_size_);
if (error != OMX_ErrorNone)
return false;
@@ -211,7 +217,7 @@ void OmxCodec::FreeInputBuffers() {
// Calls to OMX to free buffers.
for(size_t i = 0; i < input_buffers_.size(); ++i)
- OMX_FreeBuffer(decoder_handle_, input_port_, input_buffers_[i]);
+ OMX_FreeBuffer(component_handle_, input_port_, input_buffers_[i]);
input_buffers_.clear();
// Empty available buffer queue.
@@ -225,7 +231,7 @@ void OmxCodec::FreeOutputBuffers() {
// Calls to OMX to free buffers.
for(size_t i = 0; i < output_buffers_.size(); ++i)
- OMX_FreeBuffer(decoder_handle_, output_port_, output_buffers_[i]);
+ OMX_FreeBuffer(component_handle_, output_port_, output_buffers_[i]);
output_buffers_.clear();
// Empty available buffer queue.
@@ -288,10 +294,10 @@ void OmxCodec::Transition_EmptyToLoaded() {
// 2. Get the handle to the component. After OMX_GetHandle(),
// the component is in loaded state.
// TODO(hclam): We should have a list of componant names instead.
- OMX_STRING component = const_cast<OMX_STRING>(component_);
- OMX_HANDLETYPE handle = reinterpret_cast<OMX_HANDLETYPE>(decoder_handle_);
+ OMX_STRING component = const_cast<OMX_STRING>(component_name_);
+ OMX_HANDLETYPE handle = reinterpret_cast<OMX_HANDLETYPE>(component_handle_);
omxresult = OMX_GetHandle(&handle, component, this, &callback);
- decoder_handle_ = reinterpret_cast<OMX_COMPONENTTYPE*>(handle);
+ component_handle_ = reinterpret_cast<OMX_COMPONENTTYPE*>(handle);
if (omxresult != OMX_ErrorNone) {
LOG(ERROR) << "Failed to Load the component: " << component;
StateTransitionTask(kError);
@@ -302,7 +308,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
// number of ports and index of the first port.
OMX_PORT_PARAM_TYPE port_param;
ResetPortHeader(*this, &port_param);
- omxresult = OMX_GetParameter(decoder_handle_, OMX_IndexParamVideoInit,
+ omxresult = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit,
&port_param);
if (omxresult != OMX_ErrorNone) {
LOG(ERROR) << "ERROR - Failed to get Port Param";
@@ -326,7 +332,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
OMX_PARAM_PORTDEFINITIONTYPE port_format;
ResetPortHeader(*this, &port_format);
port_format.nPortIndex = input_port_;
- omxresult = OMX_GetParameter(decoder_handle_,
+ omxresult = OMX_GetParameter(component_handle_,
OMX_IndexParamPortDefinition,
&port_format);
if (omxresult != OMX_ErrorNone) {
@@ -339,21 +345,21 @@ void OmxCodec::Transition_EmptyToLoaded() {
StateTransitionTask(kError);
return;
}
- if (codec_ == kCodecH264)
+ if (input_format_.codec == kCodecH264)
port_format.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
- else if (codec_ == kCodecMpeg4)
+ else if (input_format_.codec == kCodecMpeg4)
port_format.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
- else if (codec_ == kCodecH263)
+ else if (input_format_.codec == kCodecH263)
port_format.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
- else if (codec_ == kCodecVc1)
+ else if (input_format_.codec == kCodecVc1)
port_format.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
else
- LOG(ERROR) << "Error: Unsupported codec " << codec_;
+ LOG(ERROR) << "Error: Unsupported codec " << input_format_.codec;
// Assume QCIF.
// TODO(ajwong): This MUST come from the client library somehow.
port_format.format.video.nFrameWidth = 720;
port_format.format.video.nFrameHeight = 480;
- omxresult = OMX_SetParameter(decoder_handle_,
+ omxresult = OMX_SetParameter(component_handle_,
OMX_IndexParamPortDefinition,
&port_format);
if (omxresult != OMX_ErrorNone) {
@@ -369,7 +375,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
// This will have the new mini buffer count in port_format.nBufferCountMin.
// Save this value to input_buf_count.
port_format.nPortIndex = port_param.nStartPortNumber;
- omxresult = OMX_GetParameter(decoder_handle_,
+ omxresult = OMX_GetParameter(component_handle_,
OMX_IndexParamPortDefinition,
&port_format);
if (omxresult != OMX_ErrorNone) {
@@ -388,7 +394,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
// 8. Obtain the information about the output port.
ResetPortHeader(*this, &port_format);
port_format.nPortIndex = output_port_;
- omxresult = OMX_GetParameter(decoder_handle_,
+ omxresult = OMX_GetParameter(component_handle_,
OMX_IndexParamPortDefinition,
&port_format);
if (omxresult != OMX_ErrorNone) {
@@ -407,10 +413,10 @@ void OmxCodec::Transition_EmptyToLoaded() {
// 9. Codec specific configurations.
// This sets the NAL length size. 0 means we are using a 3 byte start code.
// Other values specifies number of bytes of the NAL length.
- if (codec_ == kCodecH264) {
+ if (input_format_.codec == kCodecH264) {
OMX_VIDEO_CONFIG_NALSIZE naluSize;
naluSize.nNaluBytes = 0;
- omxresult = OMX_SetConfig(decoder_handle_,
+ omxresult = OMX_SetConfig(component_handle_,
OMX_IndexConfigVideoNalSize, (OMX_PTR)&naluSize);
if (omxresult != OMX_ErrorNone) {
LOG(ERROR) << "Error - SetConfig failed";
@@ -433,7 +439,7 @@ void OmxCodec::Transition_LoadedToIdle() {
DCHECK_EQ(kLoaded, GetState());
// 1. Sets decoder to idle state.
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandStateSet,
OMX_StateIdle, 0);
if (omxresult != OMX_ErrorNone) {
@@ -465,7 +471,7 @@ void OmxCodec::Transition_IdleToExecuting() {
DCHECK_EQ(kIdle, GetState());
// Transist to executing state.
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandStateSet,
OMX_StateExecuting, 0);
if (omxresult != OMX_ErrorNone) {
@@ -484,7 +490,7 @@ void OmxCodec::Transition_ExecutingToDisable() {
DCHECK_EQ(kExecuting, GetState());
// Send DISABLE command.
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandPortDisable,
output_port_, 0);
if (omxresult != OMX_ErrorNone) {
@@ -507,7 +513,7 @@ void OmxCodec::Transition_DisableToEnable() {
DCHECK_EQ(kPortSettingDisable, GetState());
// Send Enable command.
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandPortEnable,
output_port_, 0);
if (omxresult != OMX_ErrorNone) {
@@ -520,7 +526,7 @@ void OmxCodec::Transition_DisableToEnable() {
OMX_PARAM_PORTDEFINITIONTYPE port_format;
ResetPortHeader(*this, &port_format);
port_format.nPortIndex = output_port_;
- omxresult = OMX_GetParameter(decoder_handle_, OMX_IndexParamPortDefinition,
+ omxresult = OMX_GetParameter(component_handle_, OMX_IndexParamPortDefinition,
&port_format);
if (omxresult != OMX_ErrorNone) {
LOG(ERROR) << "Error - GetParameter failed";
@@ -550,7 +556,7 @@ void OmxCodec::Transition_DisableToIdle() {
DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(kPortSettingDisable, GetState());
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandStateSet,
OMX_StateIdle, 0);
if (omxresult != OMX_ErrorNone) {
@@ -575,7 +581,7 @@ void OmxCodec::Transition_EnableToIdle() {
DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(kPortSettingEnable, GetState());
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandStateSet,
OMX_StateIdle, 0);
if (omxresult != OMX_ErrorNone) {
@@ -592,7 +598,7 @@ void OmxCodec::Transition_ExecutingToIdle() {
DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(kExecuting, GetState());
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandStateSet,
OMX_StateIdle, 0);
if (omxresult != OMX_ErrorNone) {
@@ -611,7 +617,7 @@ void OmxCodec::Transition_IdleToLoaded() {
DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(kIdle, GetState());
- OMX_ERRORTYPE omxresult = OMX_SendCommand(decoder_handle_,
+ OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_,
OMX_CommandStateSet,
OMX_StateLoaded, 0);
if (omxresult != OMX_ErrorNone) {
@@ -633,11 +639,12 @@ void OmxCodec::Transition_LoadedToEmpty() {
DCHECK_EQ(kLoaded, GetState());
// Free the decoder handle.
- OMX_ERRORTYPE result = OMX_FreeHandle(decoder_handle_);
+ OMX_ERRORTYPE result = OMX_FreeHandle(component_handle_);
if (result != OMX_ErrorNone) {
- LOG(ERROR) << "Error - Terminate: OMX_FreeHandle error. Error code: " << result;
+ LOG(ERROR) << "Error - Terminate: OMX_FreeHandle error. "
+ "Error code: " << result;
}
- decoder_handle_ = NULL;
+ component_handle_ = NULL;
// Deinit OpenMAX
// TODO(hclam): move this out.
@@ -665,9 +672,9 @@ void OmxCodec::Transition_Error() {
// send a command to disable ports for us to free buffers.
if (old_state == kExecuting || old_state == kIdle ||
old_state == kPortSettingEnable || old_state == kPortSettingDisable) {
- DCHECK(decoder_handle_);
- OMX_SendCommand(decoder_handle_, OMX_CommandPortDisable, input_port_, 0);
- OMX_SendCommand(decoder_handle_, OMX_CommandPortDisable, output_port_, 0);
+ DCHECK(component_handle_);
+ OMX_SendCommand(component_handle_, OMX_CommandPortDisable, input_port_, 0);
+ OMX_SendCommand(component_handle_, OMX_CommandPortDisable, output_port_, 0);
}
// Free input and output buffers.
@@ -679,11 +686,11 @@ void OmxCodec::Transition_Error() {
FreeOutputQueue();
// Free decoder handle.
- if (decoder_handle_) {
- OMX_ERRORTYPE result = OMX_FreeHandle(decoder_handle_);
+ if (component_handle_) {
+ OMX_ERRORTYPE result = OMX_FreeHandle(component_handle_);
if (result != OMX_ErrorNone)
LOG(ERROR) << "Error - OMX_FreeHandle error. Error code: " << result;
- decoder_handle_ = NULL;
+ component_handle_ = NULL;
}
// Deinit OpenMAX.
@@ -917,7 +924,7 @@ void OmxCodec::EmptyBufferTask() {
omx_buffer->nFlags |= input_eos_ ? OMX_BUFFERFLAG_EOS : 0;
// Give this buffer to OMX.
- OMX_ERRORTYPE ret = OMX_EmptyThisBuffer(decoder_handle_, omx_buffer);
+ OMX_ERRORTYPE ret = OMX_EmptyThisBuffer(component_handle_, omx_buffer);
if (ret != OMX_ErrorNone) {
LOG(ERROR) << "ERROR - OMX_EmptyThisBuffer failed with result " << ret;
StateTransitionTask(kError);
@@ -967,7 +974,7 @@ void OmxCodec::FillBufferTask() {
omx_buffer->nOutputPortIndex = output_port_;
omx_buffer->pAppPrivate = this;
omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
- OMX_ERRORTYPE ret = OMX_FillThisBuffer(decoder_handle_, omx_buffer);
+ OMX_ERRORTYPE ret = OMX_FillThisBuffer(component_handle_, omx_buffer);
if (OMX_ErrorNone != ret) {
LOG(ERROR) << "Error - OMX_FillThisBuffer failed with result " << ret;
StateTransitionTask(kError);
@@ -1005,7 +1012,7 @@ void OmxCodec::InitialFillBuffer() {
omx_buffer->pAppPrivate = this;
// Need to clear the EOS flag.
omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
- OMX_ERRORTYPE ret = OMX_FillThisBuffer(decoder_handle_, omx_buffer);
+ OMX_ERRORTYPE ret = OMX_FillThisBuffer(component_handle_, omx_buffer);
if (OMX_ErrorNone != ret) {
LOG(ERROR) << "Error - OMX_FillThisBuffer failed with result " << ret;
diff --git a/media/omx/omx_codec.h b/media/omx/omx_codec.h
index 9a0804f..4aa69af 100644
--- a/media/omx/omx_codec.h
+++ b/media/omx/omx_codec.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// Copyright (c) 2010 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.
@@ -15,7 +15,10 @@
// // Initialization.
// MessageLoop message_loop;
// OmxCodec* decoder = new OmxCodec(&message_loop);
-// decoder->Setup(component_name, kCodecH264);
+// OmxCodec::OmxMediaFormat input_format, output_format;
+// input_format.codec = OmxCodec::kCodecH264;
+// output_format.codec = OmxCodec::kCodecRaw;
+// decoder->Setup(component_name, input_format, output_format);
// decoder->SetErrorCallback(NewCallback(this, &Client::ErrorCallback));
//
// // Start is asynchronous. But we don't need to wait for it to proceed.
@@ -106,14 +109,71 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
kCodecMpeg4,
kCodecH263,
kCodecVc1,
+ kCodecRaw,
+ };
+
+ // TODO(jiesun): figure out what other surface formats are.
+ enum OmxSurfaceFormat {
+ kOmxSurfaceFormatNV21,
+ kOmxSurfaceFormatNV21Tiled,
+ kOmxSurfaceFormatNV12,
+ };
+
+ struct OmxMediaFormatVideoHeader {
+ int width;
+ int height;
+ int stride; // n/a to compressed stream.
+ int frame_rate;
+ int bit_rate; // n/a to raw stream.
+ int profile; // n/a to raw stream.
+ int level; // n/a to raw stream.
+ int i_dist; // i frame distance; >0 if p frame is enabled.
+ int p_dist; // p frame distance; >0 if b frame is enabled.
+ };
+
+ struct OmxMediaFormatVideoRaw {
+ OmxMediaFormatVideoHeader h;
+ OmxSurfaceFormat color_space;
+ };
+
+ struct OmxMediaFormatVideoH264 {
+ OmxMediaFormatVideoHeader h;
+ int slice_enable;
+ int max_ref_frames;
+ int num_ref_l0, num_ref_l1;
+ int cabac_enable;
+ int cabac_init_idc;
+ int deblock_enable;
+ int frame_mbs_only_flags;
+ int mbaff_enable;
+ int bdirect_spatial_temporal;
+ };
+
+ struct OmxMediaFormatVideoMPEG4 {
+ OmxMediaFormatVideoHeader h;
+ int ac_pred_enable;
+ int time_inc_res;
+ int slice_enable;
+ };
+
+ struct OmxMediaFormat {
+ // TODO(jiesun): instead of codec type, we should have media format.
+ Codec codec;
+ union {
+ OmxMediaFormatVideoRaw raw;
+ OmxMediaFormatVideoH264 h264;
+ OmxMediaFormatVideoMPEG4 mpeg4;
+ };
};
OmxCodec(MessageLoop* message_loop);
virtual ~OmxCodec();
- // 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 component name and input/output media format.
+ // TODO(hclam): Remove |component|.
+ void Setup(const char* component_name,
+ const OmxMediaFormat& input_format,
+ const OmxMediaFormat& output_format);
// Set the error callback. In case of error the callback will be called.
void SetErrorCallback(Callback* callback);
@@ -138,8 +198,7 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
void Flush(Callback* callback);
// Getters for private members.
- OMX_COMPONENTTYPE* decoder_handle() { return decoder_handle_; }
- Codec codec() { return codec_; }
+ OMX_COMPONENTTYPE* component_handle() { return component_handle_; }
int input_port() { return input_port_; }
int output_port() { return output_port_; }
@@ -148,7 +207,7 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
protected:
// Returns the component name given the codec.
- virtual const char* GetComponentName(Codec codec) { return ""; }
+ virtual const char* GetComponentName(Codec codec) { return component_name_; }
// Inherit from subclass to allow device specific configurations.
virtual bool DeviceSpecificConfig() { return true; }
@@ -285,8 +344,6 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
int output_port_;
bool output_eos_;
- OMX_COMPONENTTYPE* decoder_handle_;
-
// |state_| records the current state. During state transition
// |next_state_| is the next state that this machine will transition
// to. After a state transition is completed and the state becomes
@@ -297,8 +354,11 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
State next_state_;
// TODO(hclam): We should keep a list of component names.
- const char* component_;
- Codec codec_;
+ const char* component_name_;
+ OMX_COMPONENTTYPE* component_handle_;
+ bool encoder_;
+ OmxMediaFormat input_format_;
+ OmxMediaFormat output_format_;
MessageLoop* message_loop_;
scoped_ptr<Callback> stop_callback_;
diff --git a/media/omx/omx_test.cc b/media/omx/omx_test.cc
index 0a44a70..08d91f0 100644
--- a/media/omx/omx_test.cc
+++ b/media/omx/omx_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// Copyright (c) 2010 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.
@@ -15,6 +15,7 @@
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
+#include "base/time.h"
#include "media/omx/input_buffer.h"
#include "media/omx/omx_codec.h"
@@ -23,15 +24,21 @@
// decoder.
class TestApp {
public:
- TestApp(const char* filename,
+ TestApp(const char* input_filename,
+ const char* output_filename,
const char* component,
- media::OmxCodec::Codec codec,
+ media::OmxCodec::OmxMediaFormat& input_format,
+ media::OmxCodec::OmxMediaFormat& output_format,
bool simulate_copy)
- : filename_(filename),
+ : input_filename_(input_filename),
+ output_filename_(output_filename),
component_(component),
- codec_(codec),
+ input_format_(input_format),
+ output_format_(output_format),
simulate_copy_(simulate_copy),
copy_buf_size_(0),
+ input_file_(NULL),
+ output_file_(NULL),
stopped_(false),
error_(false) {
}
@@ -82,36 +89,52 @@ class TestApp {
decoder_->Read(NewCallback(this, &TestApp::ReadCompleteCallback));
// Copy the output of the decoder to user memory.
- if (simulate_copy_) {
+ if (simulate_copy_ || output_file_) { // |output_file_| implies a copy.
if (size > copy_buf_size_) {
copy_buf_.reset(new uint8[size]);
copy_buf_size_ = size;
}
memcpy(copy_buf_.get(), buffer, size);
+ if (output_file_)
+ fwrite(copy_buf_.get(), sizeof(uint8), size, output_file_);
}
+
+ // could OMX IL return patial sample for decoder?
+ frame_count_++;
+ bit_count_ += size << 3;
}
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_);
+ int read = fread(data, 1, kSize, input_file_);
decoder_->Feed(new media::InputBuffer(data, read),
NewCallback(this, &TestApp::FeedCallback));
}
void Run() {
// Open the input file.
- file_ = file_util::OpenFile(filename_, "rb");
- if (!file_) {
- printf("Error - can't open file %s\n", filename_);
+ input_file_ = file_util::OpenFile(input_filename_, "rb");
+ if (!input_file_) {
+ printf("Error - can't open file %s\n", input_filename_);
return;
}
+ // Open the dump file.
+ if (strlen(output_filename_)) {
+ output_file_ = file_util::OpenFile(output_filename_, "wb");
+ if (!input_file_) {
+ fclose(input_file_);
+ printf("Error - can't open dump file %s\n", output_filename_);
+ return;
+ }
+ }
+
// Setup the decoder with the message loop of the current thread. Also
// setup component name, codec and callbacks.
decoder_ = new media::OmxCodec(&message_loop_);
- decoder_->Setup(component_, codec_);
+ decoder_->Setup(component_, input_format_, output_format_);
decoder_->SetErrorCallback(NewCallback(this, &TestApp::ErrorCallback));
// Start the decoder.
@@ -123,21 +146,100 @@ class TestApp {
// 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();
+
+ fclose(input_file_);
+ if (output_file_)
+ fclose(output_file_);
+ }
+
+ void StartProfiler() {
+ start_time_ = base::Time::Now();
+ frame_count_ = 0;
+ bit_count_ = 0;
+ }
+
+ void StopProfiler() {
+ base::Time stop_time = base::Time::Now();
+ base::TimeDelta duration = stop_time - start_time_;
+ int micro_sec = static_cast<int>(duration.InMicroseconds());
+ printf("\n<<< frame delivered : %d >>>", frame_count_);
+ printf("\n<<< time used(us) : %d >>>", micro_sec);
+ printf("\n<<< fps : %d >>>", frame_count_ * 1000000 / micro_sec);
+ // printf("\n<<< bitrate>>> : %I64d\n", bit_count_ * 1000000 / micro_sec);
+ printf("\n");
}
scoped_refptr<media::OmxCodec> decoder_;
MessageLoop message_loop_;
- const char* filename_;
+ const char* input_filename_;
+ const char* output_filename_;
const char* component_;
- media::OmxCodec::Codec codec_;
+ media::OmxCodec::OmxMediaFormat input_format_;
+ media::OmxCodec::OmxMediaFormat output_format_;
bool simulate_copy_;
scoped_array<uint8> copy_buf_;
int copy_buf_size_;
- FILE* file_;
+ FILE *input_file_, *output_file_;
bool stopped_;
bool error_;
+ base::Time start_time_;
+ int frame_count_;
+ int bit_count_;
};
+// Not intended to be used in production.
+void NV21toI420(uint8* nv21, uint8* i420, int width, int height) {
+ memcpy(i420, nv21, width * height * sizeof(uint8));
+ i420 += width * height;
+ nv21 += width * height;
+ uint8* u = i420;
+ uint8* v = i420 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *v++ = *nv21++;
+ *u++ = *nv21++;
+ }
+}
+
+void NV21toYV12(uint8* nv21, uint8* yv12, int width, int height) {
+ memcpy(yv12, nv21, width * height * sizeof(uint8));
+ yv12 += width * height;
+ nv21 += width * height;
+ uint8* v = yv12;
+ uint8* u = yv12 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *v++ = *nv21++;
+ *u++ = *nv21++;
+ }
+}
+
+void I420toNV21(uint8* i420, uint8* nv21, int width, int height) {
+ memcpy(nv21, i420, width * height * sizeof(uint8));
+ i420 += width * height;
+ nv21 += width * height;
+ uint8* u = i420;
+ uint8* v = i420 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *nv21++ = *v++;
+ *nv21++ = *u++;
+ }
+}
+
+void YV12toNV21(uint8* yv12, uint8* nv21, int width, int height) {
+ memcpy(nv21, yv12, width * height * sizeof(uint8));
+ yv12 += width * height;
+ nv21 += width * height;
+ uint8* v = yv12;
+ uint8* u = yv12 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *nv21++ = *v++;
+ *nv21++ = *u++;
+ }
+}
+
int main(int argc, char** argv) {
base::AtExitManager at_exit_manager;
@@ -145,40 +247,98 @@ int main(int argc, char** argv) {
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
if (argc < 2) {
- printf("Usage: omx_test --file=FILE --component=COMPONENT --codec=CODEC"
- " [--copy]\n");
+ printf("Usage: omx_test --input-file=FILE"
+ " --component=COMPONENT --codec=CODEC"
+ " [--output-file=FILE] [--enable-csc=FILE]"
+ " [--copy] [--measure-fps]\n");
printf(" COMPONENT: OpenMAX component name\n");
printf(" CODEC: h264/mpeg4/h263/vc1\n");
printf("\n");
printf("Optional Arguments\n");
- printf(" --copy Simulate a memcpy from the output of decoder.\n");
+ printf(" --output-file Dump raw OMX output to file.\n");
+ printf(" --enable-csc Dump the CSCed output to file.\n");
+ printf(" --copy Simulate a memcpy from the output of decoder.\n");
+ printf(" --measure-fps Measuring performance in fps\n");
return 1;
}
- std::string filename = cmd_line->GetSwitchValueASCII("file");
+ std::string input_filename = cmd_line->GetSwitchValueASCII("input-file");
+ std::string output_filename = cmd_line->GetSwitchValueASCII("output-file");
std::string component = cmd_line->GetSwitchValueASCII("component");
std::string codec = cmd_line->GetSwitchValueASCII("codec");
bool copy = cmd_line->HasSwitch("copy");
+ bool measure_fps = cmd_line->HasSwitch("measure-fps");
+
- media::OmxCodec::Codec codec_id = media::OmxCodec::kCodecNone;
+ media::OmxCodec::OmxMediaFormat input, output;
+ input.codec = media::OmxCodec::kCodecNone;
if (codec == "h264")
- codec_id = media::OmxCodec::kCodecH264;
+ input.codec = media::OmxCodec::kCodecH264;
else if (codec == "mpeg4")
- codec_id = media::OmxCodec::kCodecMpeg4;
+ input.codec = media::OmxCodec::kCodecMpeg4;
else if (codec == "h263")
- codec_id = media::OmxCodec::kCodecH263;
+ input.codec = media::OmxCodec::kCodecH263;
else if (codec == "vc1")
- codec_id = media::OmxCodec::kCodecVc1;
+ input.codec = media::OmxCodec::kCodecVc1;
else {
printf("Unknown codec.\n");
return 1;
}
+ output.codec = media::OmxCodec::kCodecRaw;
// Create a TestApp object and run the decoder.
- TestApp test(filename.c_str(), component.c_str(), codec_id, copy);
+ TestApp test(input_filename.c_str(),
+ output_filename.c_str(),
+ component.c_str(),
+ input,
+ output,
+ copy);
+
+
+ if (measure_fps)
+ test.StartProfiler();
// This call will run the decoder until EOS is reached or an error
// is encountered.
test.Run();
+
+ if (measure_fps)
+ test.StopProfiler();
+
+ // Color space conversion.
+ if (!output_filename.empty()) {
+ std::string dumpyuv_name = cmd_line->GetSwitchValueASCII("enable-csc");
+ if (!dumpyuv_name.empty()) {
+ // now assume the raw output is NV21;
+ // now assume decoder.
+ FILE* dump_raw = file_util::OpenFile(output_filename.c_str(), "rb");
+ FILE* dump_yuv = file_util::OpenFile(dumpyuv_name.c_str(), "wb");
+ if (!dump_raw || !dump_yuv) {
+ printf("Error - can't open file for color conversion %s\n",
+ dumpyuv_name.c_str());
+ } else {
+ // TODO(jiesun): get rid of hard coded value when Startup()
+ // call back function is ready.
+ int width = 352;
+ int height = 288;
+ int frame_size = width * height * 3 / 2; // assume 4:2:0 chroma format.
+ scoped_array<uint8> in_buffer(new uint8[frame_size]);
+ scoped_array<uint8> out_buffer(new uint8[frame_size]);
+ while (true) {
+ int read;
+ read = fread(in_buffer.get(), sizeof(uint8), frame_size, dump_raw);
+ if (read != frame_size)
+ break;
+ NV21toI420(in_buffer.get(), out_buffer.get(), width, height);
+ fwrite(out_buffer.get(), sizeof(uint8), frame_size, dump_yuv);
+ }
+ }
+ if (dump_raw)
+ fclose(dump_raw);
+ if (dump_yuv)
+ fclose(dump_yuv);
+ }
+ }
+
return 0;
}