summaryrefslogtreecommitdiffstats
path: root/media/omx
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-06 19:05:56 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-06 19:05:56 +0000
commit1c04bd1673c858b357ff97a98c3cdb3363a20d76 (patch)
tree28cb612e08c366c96ae7162f235b9b97d9b614c8 /media/omx
parent52bbcd935cdabd999b6ea5237ddeab860689092a (diff)
downloadchromium_src-1c04bd1673c858b357ff97a98c3cdb3363a20d76.zip
chromium_src-1c04bd1673c858b357ff97a98c3cdb3363a20d76.tar.gz
chromium_src-1c04bd1673c858b357ff97a98c3cdb3363a20d76.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. Submitted=jiesun@google.com Reviewed=hclam@google.com Review=http://codereview.chromium.org/523044 BUG=NONE Review URL: http://codereview.chromium.org/525053 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35639 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/omx')
-rw-r--r--media/omx/omx_codec.cc95
-rw-r--r--media/omx/omx_codec.h82
-rw-r--r--media/omx/omx_test.cc207
3 files changed, 305 insertions, 79 deletions
diff --git a/media/omx/omx_codec.cc b/media/omx/omx_codec.cc
index d67798d56..bea1d5b 100644
--- a/media/omx/omx_codec.cc
+++ b/media/omx/omx_codec.cc
@@ -26,10 +26,9 @@ 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_handle_(NULL),
message_loop_(message_loop) {
}
@@ -43,10 +42,16 @@ OmxCodec::~OmxCodec() {
DCHECK(output_queue_.empty());
}
-void OmxCodec::Setup(const char* component, Codec codec) {
+void OmxCodec::Setup(
+ const char* component,
+ const OmxCodec::OmxMediaFormat& input_format,
+ const OmxCodec::OmxMediaFormat& output_format) {
DCHECK_EQ(kEmpty, state_);
- component_ = component;
- codec_ = codec;
+ DCHECK(input_format.codec != kCodecNone);
+ component_name_ = component;
+ input_format_ = input_format;
+ output_format_ = output_format;
+ encoder_ = input_format_.codec == kCodecRaw;
}
void OmxCodec::SetErrorCallback(Callback* callback) {
@@ -55,7 +60,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 +182,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 +202,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 +216,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 +230,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 +293,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 +307,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 +331,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 +344,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 +374,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 +393,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 +412,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 +438,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 +470,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 +489,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 +512,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 +525,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 +555,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 +580,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 +597,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 +616,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 +638,11 @@ 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;
}
- decoder_handle_ = NULL;
+ component_handle_ = NULL;
// Deinit OpenMAX
// TODO(hclam): move this out.
@@ -665,9 +670,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 +684,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 +922,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 +972,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 +1010,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..9abe7aa 100644
--- a/media/omx/omx_codec.h
+++ b/media/omx/omx_codec.h
@@ -15,7 +15,10 @@
// // Initialization.
// MessageLoop message_loop;
// OmxCodec* decoder = new OmxCodec(&message_loop);
-// decoder->Setup(component_name, kCodecH264);
+// media::OmxCodec::OmxMediaFormat input_format, output_format;
+// input_format.codec = kCodecH264;
+// output_format.codec = 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, // hacky.
};
+ // TODO(jiesun) figure out what surface format Samsung support.
+ enum OmxSurfaceFormat {
+ kOmxSurfaceFormatNV21,
+ kOmxSurfaceFormatNV21Tiled,
+ kOmxSurfaceFormatNV12,
+ };
+
+ typedef struct {
+ 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
+ } OmxMediaFormatVideoHeader;
+
+ typedef struct {
+ OmxMediaFormatVideoHeader h;
+ OmxSurfaceFormat color_space;
+ } OmxMediaFormatVideoRaw;
+
+ typedef struct {
+ 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;
+ } OmxMediaFormatVideoH264;
+
+ typedef struct {
+ OmxMediaFormatVideoHeader h;
+ int ac_pred_enable;
+ int time_inc_res;
+ int slice_enable;
+ } OmxMediaFormatVideoMPEG4;
+
+ typedef struct {
+ // hTODO(jiesun) should change Coded to something format.
+ Codec codec;
+ union {
+ OmxMediaFormatVideoRaw raw;
+ OmxMediaFormatVideoH264 h264;
+ OmxMediaFormatVideoMPEG4 mpeg4;
+ };
+ } OmxMediaFormat;
+
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,
+ const OmxMediaFormat& Input,
+ const OmxMediaFormat& Output);
// 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..1e450e8 100644
--- a/media/omx/omx_test.cc
+++ b/media/omx/omx_test.cc
@@ -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_;
+ int64 micro_sec = duration.InMicroseconds();
+ printf("\n<<< frame delivered : %lld >>>", frame_count_);
+ printf("\n<<< time used(us) : %lld >>>", micro_sec);
+ printf("\n<<< fps : %lld >>>", frame_count_ * 1000000 / micro_sec);
+ // printf("\n<<< bitrate>>> : %lld\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_;
+ int64 frame_count_;
+ int64 bit_count_;
};
+// Not intend 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,99 @@ 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
+ uint8* in_buffer = new uint8[frame_size];
+ uint8* out_buffer = new uint8[frame_size];
+ while (true) {
+ int read = fread(in_buffer, sizeof(uint8), frame_size, dump_raw);
+ if (read != frame_size)
+ break;
+ NV21toI420(in_buffer, out_buffer, width, height);
+ fwrite(out_buffer, sizeof(uint8), frame_size, dump_yuv);
+ }
+ delete [] in_buffer;
+ delete [] out_buffer;
+ }
+ if (dump_raw)
+ fclose(dump_raw);
+ if (dump_yuv)
+ fclose(dump_yuv);
+ }
+ }
+
return 0;
}