summaryrefslogtreecommitdiffstats
path: root/media/omx
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-04 19:31:20 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-04 19:31:20 +0000
commitb2e3a43dcd39459cf1417bbb7d791a8ddb8ea900 (patch)
treeef6a0658f0ddce2061bb04eef0b13a1dcc5a077c /media/omx
parenta3046083f16194a4e5d783e5933b26f7bddb4a8c (diff)
downloadchromium_src-b2e3a43dcd39459cf1417bbb7d791a8ddb8ea900.zip
chromium_src-b2e3a43dcd39459cf1417bbb7d791a8ddb8ea900.tar.gz
chromium_src-b2e3a43dcd39459cf1417bbb7d791a8ddb8ea900.tar.bz2
Refactoring of media::OmxCodec to split configuration of IO ports
Split encoder/decoder configuration of media::OmxCodec into strategy classes. This will help OmxCodec free from any codec specific bits. Also included the refactoring of omx_test to split the file output part to a separate class. Review URL: http://codereview.chromium.org/566036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38121 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/omx')
-rw-r--r--media/omx/omx_codec.cc253
-rw-r--r--media/omx/omx_codec.h117
-rw-r--r--media/omx/omx_configurator.cc172
-rw-r--r--media/omx/omx_configurator.h154
4 files changed, 381 insertions, 315 deletions
diff --git a/media/omx/omx_codec.cc b/media/omx/omx_codec.cc
index b757a88..71387d1 100644
--- a/media/omx/omx_codec.cc
+++ b/media/omx/omx_codec.cc
@@ -45,15 +45,11 @@ OmxCodec::~OmxCodec() {
DCHECK(output_queue_.empty());
}
-void OmxCodec::Setup(
- const OmxCodec::OmxMediaFormat& input_format,
- const OmxCodec::OmxMediaFormat& output_format) {
+void OmxCodec::Setup(OmxConfigurator* configurator) {
DCHECK_EQ(kEmpty, state_);
- DCHECK_NE(input_format.codec, kCodecNone);
- input_format_ = input_format;
- output_format_ = output_format;
- Codec codec = encoder() ? output_format_.codec : input_format_.codec;
- role_name_ = SelectRole(codec, encoder());
+
+ CHECK(configurator);
+ configurator_.reset(configurator);
}
void OmxCodec::SetErrorCallback(Callback* callback) {
@@ -67,7 +63,7 @@ void OmxCodec::SetFormatCallback(FormatCallback* callback) {
}
void OmxCodec::Start() {
- DCHECK_NE(kCodecNone, input_format_.codec);
+ CHECK(configurator_.get());
message_loop_->PostTask(
FROM_HERE,
@@ -116,8 +112,6 @@ void OmxCodec::SetNextState(State state) {
void OmxCodec::StartTask() {
DCHECK_EQ(message_loop_, MessageLoop::current());
- next_sample_timestamp_ = 0;
-
StateTransitionTask(kLoaded);
}
@@ -278,10 +272,9 @@ void OmxCodec::FreeOutputQueue() {
// 3. Get handle of the OMX component
// 4. Get the port information.
// 5. Set role for the component.
-// 6. Device specific configurations.
-// 7. Input/output ports media format configuration.
-// 8. Obtain the information about the input port.
-// 9. Obtain the information about the output port.
+// 6. Input/output ports media format configuration.
+// 7. Obtain the information about the input port.
+// 8. Obtain the information about the output port.
void OmxCodec::Transition_EmptyToLoaded() {
DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(kEmpty, GetState());
@@ -302,12 +295,13 @@ void OmxCodec::Transition_EmptyToLoaded() {
}
// 2. Map role name to component name.
+ std::string role_name = configurator_->GetRoleName();
OMX_U32 roles = 0;
omxresult = OMX_GetComponentsOfRole(
- const_cast<OMX_STRING>(role_name_.c_str()),
+ const_cast<OMX_STRING>(role_name.c_str()),
&roles, 0);
if (omxresult != OMX_ErrorNone || roles == 0) {
- LOG(ERROR) << "Unsupported Role: " << role_name_.c_str();
+ LOG(ERROR) << "Unsupported Role: " << role_name.c_str();
StateTransitionTask(kError);
return;
}
@@ -320,7 +314,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
component_names[i] = new OMX_U8[kMaxComponentNameLength];
omxresult = OMX_GetComponentsOfRole(
- const_cast<OMX_STRING>(role_name_.c_str()),
+ const_cast<OMX_STRING>(role_name.c_str()),
&roles, component_names);
// Use first component only. Copy the name of the first component
@@ -333,7 +327,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
delete [] component_names;
if (omxresult != OMX_ErrorNone || roles == 0) {
- LOG(ERROR) << "Unsupported Role: " << role_name_.c_str();
+ LOG(ERROR) << "Unsupported Role: " << role_name.c_str();
StateTransitionTask(kError);
return;
}
@@ -369,7 +363,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
OMX_PARAM_COMPONENTROLETYPE role_type;
ResetPortHeader(*this, &role_type);
base::strlcpy(reinterpret_cast<char*>(role_type.cRole),
- role_name_.c_str(),
+ role_name.c_str(),
OMX_MAX_STRINGNAME_SIZE);
role_type.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
omxresult = OMX_SetParameter(component_handle_,
@@ -381,21 +375,14 @@ void OmxCodec::Transition_EmptyToLoaded() {
return;
}
- // 6. Device specific configurations.
- if (!DeviceSpecificConfig()) {
- LOG(ERROR) << "Device specific configurations failed";
- StateTransitionTask(kError);
- return;
- }
-
- // 7. Input/output ports media format configuration.
+ // 6. Input/output ports media format configuration.
if (!ConfigureIOPorts()) {
LOG(ERROR) << "Media format configurations failed";
StateTransitionTask(kError);
return;
}
- // 8. Obtain the information about the input port.
+ // 7. Obtain the information about the input port.
// This will have the new mini buffer count in |port_format.nBufferCountMin|.
// Save this value to input_buf_count.
OMX_PARAM_PORTDEFINITIONTYPE port_format;
@@ -417,7 +404,7 @@ void OmxCodec::Transition_EmptyToLoaded() {
input_buffer_count_ = port_format.nBufferCountMin;
input_buffer_size_ = port_format.nBufferSize;
- // 9. Obtain the information about the output port.
+ // 8. Obtain the information about the output port.
ResetPortHeader(*this, &port_format);
port_format.nPortIndex = output_port_;
omxresult = OMX_GetParameter(component_handle_,
@@ -490,6 +477,10 @@ void OmxCodec::Transition_IdleToExecuting() {
StateTransitionTask(kError);
return;
}
+
+ // Simulate a format change.
+ ReportFormatChange(configurator_->input_format(),
+ configurator_->output_format());
}
// Sequence of actions in this transition:
@@ -553,13 +544,14 @@ void OmxCodec::Transition_DisableToEnable() {
// Update the output format.
// TODO(jiesun): check if the format really change. ( we had omit some
// information such as frame rate / bit rate / vbv buffer info now. )
- output_format_.video_header.height = port_format.format.video.nFrameHeight;
- output_format_.video_header.width = port_format.format.video.nFrameWidth;
- output_format_.video_header.stride = port_format.format.video.nStride;
- input_format_.video_header.height = output_format_.video_header.height;
- input_format_.video_header.width = output_format_.video_header.width;
- input_format_.video_header.stride = output_format_.video_header.stride;
- ReportFormatChange();
+ OmxConfigurator::MediaFormat input_format, output_format;
+ output_format.video_header.height = port_format.format.video.nFrameHeight;
+ output_format.video_header.width = port_format.format.video.nFrameWidth;
+ output_format.video_header.stride = port_format.format.video.nStride;
+ input_format.video_header.height = output_format.video_header.height;
+ input_format.video_header.width = output_format.video_header.width;
+ input_format.video_header.stride = output_format.video_header.stride;
+ ReportFormatChange(input_format, output_format);
// Update the ports in buffer.
output_buffer_count_ = port_format.nBufferCountActual;
@@ -838,9 +830,8 @@ void OmxCodec::DoneStateTransitionTask() {
StateTransitionTask(kPortSettingEnable);
else if (old_state == kPortSettingDisable && GetState() == kPortSettingEnable)
StateTransitionTask(kExecuting);
- else if (old_state == kPortSettingEnable && GetState() == kExecuting) {
+ else if (old_state == kPortSettingEnable && GetState() == kExecuting)
InitialFillBuffer();
- }
else if (old_state == kPortSettingDisable && GetState() == kIdle)
StateTransitionTask(kLoaded);
else if (old_state == kPortSettingEnable && GetState() == kIdle)
@@ -874,30 +865,14 @@ void OmxCodec::ReportError() {
error_callback_.reset();
}
-void OmxCodec::ReportFormatChange() {
+void OmxCodec::ReportFormatChange(
+ const OmxConfigurator::MediaFormat& input_format,
+ const OmxConfigurator::MediaFormat& output_format) {
DCHECK_EQ(message_loop_, MessageLoop::current());
if (!format_callback_.get())
return;
- format_callback_->Run(&input_format_, &output_format_);
-}
-
-std::string OmxCodec::SelectRole(Codec codec, bool encoder) {
- std::string role_name = encoder ? "video_encoder." : "video_decoder.";
- switch (codec) {
- case kCodecH264:
- return role_name + "avc";
- case kCodecH263:
- return role_name + "h263";
- case kCodecMpeg4:
- return role_name + "mpeg4";
- case kCodecVc1:
- return role_name + "vc1";
- default:
- break;
- }
- NOTREACHED();
- return "";
+ format_callback_->Run(input_format, output_format);
}
bool OmxCodec::ConfigureIOPorts() {
@@ -935,158 +910,8 @@ bool OmxCodec::ConfigureIOPorts() {
return false;
}
- return encoder() ?
- ConfigureAsEncoder(&input_port_def, &output_port_def) :
- ConfigureAsDecoder(&input_port_def, &output_port_def);
-}
-
-bool OmxCodec::ConfigureAsEncoder(
- OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
- OMX_PARAM_PORTDEFINITIONTYPE* output_port_def) {
- // TODO(jiesun): Add support for other format than MPEG4.
- DCHECK_EQ(kCodecMpeg4, output_format_.codec);
- // Configure the input port.
- input_port_def->format.video.nFrameWidth =
- input_format_.video_header.width;
- input_port_def->format.video.nFrameHeight =
- input_format_.video_header.height;
- OMX_ERRORTYPE omxresult = OMX_ErrorNone;
- omxresult = OMX_SetParameter(component_handle_,
- OMX_IndexParamPortDefinition,
- input_port_def);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "SetParameter(OMX_IndexParamPortDefinition) "
- "for input port failed";
- return false;
- }
-
- // Configure the output port
- output_port_def->format.video.nFrameWidth =
- input_format_.video_header.width;
- output_port_def->format.video.nFrameHeight =
- input_format_.video_header.height;
- omxresult = OMX_SetParameter(component_handle_,
- OMX_IndexParamPortDefinition,
- output_port_def);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "SetParameter(OMX_IndexParamPortDefinition) "
- "for output port failed";
- return false;
- }
-
- if (output_format_.codec == kCodecMpeg4) {
- OMX_VIDEO_PARAM_MPEG4TYPE mp4_type;
- omxresult = OMX_GetParameter(component_handle_,
- OMX_IndexParamVideoMpeg4,
- &mp4_type);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "GetParameter(OMX_IndexParamVideoMpeg4) failed";
- return false;
- }
- // TODO(jiesun): verify if other vendors had the same definition.
- // Specify the frame rate.
- mp4_type.nTimeIncRes = output_format_.video_header.frame_rate * 2;
- // Specify how many P frames between adjacent intra frames.
- mp4_type.nPFrames = output_format_.video_header.i_dist - 1;
- omxresult = OMX_SetParameter(component_handle_,
- OMX_IndexParamVideoMpeg4,
- &mp4_type);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "SetParameter(OMX_IndexParamVideoMpeg4) failed";
- return false;
- }
- }
-
- OMX_VIDEO_PARAM_BITRATETYPE bitrate;
- omxresult = OMX_GetParameter(component_handle_,
- OMX_IndexParamVideoBitrate,
- &bitrate);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "GetParameter(OMX_IndexParamVideoBitrate) failed";
- return false;
- }
- // TODO(jiesun): expose other rate control method that matters.
- bitrate.eControlRate = OMX_Video_ControlRateConstant;
- bitrate.nTargetBitrate = output_format_.video_header.bit_rate;
- omxresult = OMX_SetParameter(component_handle_,
- OMX_IndexParamVideoBitrate,
- &bitrate);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "SetParameter(OMX_IndexParamVideoBitrate) failed";
- return false;
- }
-
- OMX_CONFIG_FRAMERATETYPE framerate;
- omxresult = OMX_GetConfig(component_handle_,
- OMX_IndexConfigVideoFramerate,
- &framerate);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "GetParameter(OMX_IndexConfigVideoFramerate) failed";
- return false;
- }
-
- framerate.xEncodeFramerate =
- output_format_.video_header.frame_rate << 16; // Q16 format.
- omxresult = OMX_SetConfig(component_handle_,
- OMX_IndexConfigVideoFramerate,
- &framerate);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "SetParameter(OMX_IndexConfigVideoFramerate) failed";
- return false;
- }
-
- // Emulate a format change to conform with decoder case.
- ReportFormatChange();
- return true;
-}
-
-bool OmxCodec::ConfigureAsDecoder(
- OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
- OMX_PARAM_PORTDEFINITIONTYPE* output_port_def) {
- // Configure the input port.
- if (input_format_.codec == kCodecNone) {
- LOG(ERROR) << "Unsupported codec " << input_format_.codec;
- return false;
- }
- if (input_format_.codec == kCodecH264)
- input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
- else if (input_format_.codec == kCodecMpeg4)
- input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
- else if (input_format_.codec == kCodecH263)
- input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
- else if (input_format_.codec == kCodecVc1)
- input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
- // Assume QCIF.
- // TODO(ajwong): This MUST come from the client library somehow.
- input_port_def->format.video.nFrameWidth = 720;
- input_port_def->format.video.nFrameHeight = 480;
- OMX_ERRORTYPE omxresult = OMX_ErrorNone;
- omxresult = OMX_SetParameter(component_handle_,
- OMX_IndexParamPortDefinition,
- input_port_def);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "SetParameter(OMX_IndexParamPortDefinition) "
- "for input port failed";
- return false;
- }
-
- // 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 (input_format_.codec == kCodecH264) {
- OMX_VIDEO_CONFIG_NALSIZE naluSize;
- ResetPortHeader(*this, &naluSize);
- naluSize.nPortIndex = input_port_;
- naluSize.nNaluBytes = 0;
- omxresult = OMX_SetConfig(component_handle_,
- OMX_IndexConfigVideoNalSize,
- (OMX_PTR)&naluSize);
- if (omxresult != OMX_ErrorNone) {
- LOG(ERROR) << "SetConfig(OMX_IndexConfigVideoNalSize) failed";
- return false;
- }
- }
- return true;
+ return configurator_->ConfigureIOPorts(component_handle_,
+ &input_port_def, &output_port_def);
}
bool OmxCodec::CanEmptyBuffer() {
@@ -1159,11 +984,7 @@ void OmxCodec::EmptyBufferTask() {
omx_buffer->nFilledLen = filled;
omx_buffer->pAppPrivate = this;
omx_buffer->nFlags |= input_eos_ ? OMX_BUFFERFLAG_EOS : 0;
- if (encoder()) {
- next_sample_timestamp_ += base::Time::kMicrosecondsPerSecond /
- output_format_.video_header.frame_rate;
- omx_buffer->nTimeStamp = next_sample_timestamp_;
- }
+ // TODO(hclam): Get timestamp from the input buffer and fill in here.
// Give this buffer to OMX.
OMX_ERRORTYPE ret = OMX_EmptyThisBuffer(component_handle_, omx_buffer);
diff --git a/media/omx/omx_codec.h b/media/omx/omx_codec.h
index e49fb4f..fac10c6 100644
--- a/media/omx/omx_codec.h
+++ b/media/omx/omx_codec.h
@@ -82,14 +82,15 @@
// to another. When an error is received, this object will transition to
// the error state.
-#ifndef MEDIA_OMX_CODEC_H_
-#define MEDIA_OMX_CODEC_H_
+#ifndef MEDIA_OMX_OMX_CODEC_H_
+#define MEDIA_OMX_OMX_CODEC_H_
#include <queue>
#include <vector>
#include "base/scoped_ptr.h"
#include "base/task.h"
+#include "media/omx/omx_configurator.h"
#include "third_party/openmax/il/OMX_Component.h"
#include "third_party/openmax/il/OMX_Core.h"
#include "third_party/openmax/il/OMX_Video.h"
@@ -101,83 +102,22 @@ namespace media {
class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
public:
- struct OmxMediaFormat; // forward declaration.
// TODO(jiesun): remove callback parameters.
- typedef Callback2<OmxMediaFormat*, OmxMediaFormat*>::Type FormatCallback;
+ typedef Callback2<
+ const OmxConfigurator::MediaFormat&,
+ const OmxConfigurator::MediaFormat&>::Type FormatCallback;
typedef Callback1<InputBuffer*>::Type FeedCallback;
typedef Callback2<uint8*, int>::Type ReadCallback;
typedef Callback0::Type Callback;
- enum Codec {
- kCodecNone,
- kCodecH264,
- 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 {
- OmxSurfaceFormat color_space;
- };
-
- struct OmxMediaFormatVideoH264 {
- 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 {
- 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;
- OmxMediaFormatVideoHeader video_header;
- union {
- OmxMediaFormatVideoRaw raw;
- OmxMediaFormatVideoH264 h264;
- OmxMediaFormatVideoMPEG4 mpeg4;
- };
- };
-
// Initialize an OmxCodec object that runs on |message_loop|. It is
// guaranteed that callbacks are executed on this message loop.
explicit OmxCodec(MessageLoop* message_loop);
virtual ~OmxCodec();
- // Set the component name and input/output media format.
- // TODO(hclam): Remove |component|.
- void Setup(const OmxMediaFormat& input_format,
- const OmxMediaFormat& output_format);
+ // Setup OmxCodec using |configurator|. Ownership of |configurator|
+ // is passed to this class. It is then used for configuration.
+ void Setup(OmxConfigurator* configurator);
// Set the error callback. In case of error the callback will be called.
void SetErrorCallback(Callback* callback);
@@ -204,24 +144,9 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
// Flush the decoder and reset its end-of-stream state.
void Flush(Callback* callback);
- // Getters for private members.
- OMX_COMPONENTTYPE* component_handle() { return component_handle_; }
- int input_port() { return input_port_; }
- int output_port() { return output_port_; }
- bool encoder() const { return input_format_.codec == kCodecRaw; }
-
// Subclass can provide a different value.
virtual int current_omx_spec_version() const { return 0x00000101; }
- protected:
- // Returns the component name given the codec.
- virtual const char* GetComponentName(Codec codec) {
- return component_name_.c_str();
- }
-
- // Inherit from subclass to allow device specific configurations.
- virtual bool DeviceSpecificConfig() { return true; }
-
private:
enum State {
kEmpty,
@@ -253,20 +178,15 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
// state is done.
void ReportError();
- // Helper method to call |start_callback_| after a foramt change.
+ // Helper method to call |format_callback_| after a format change.
// used when decoder output port had done with port reconfigure and
// return to enabled state.
- void ReportFormatChange();
+ void ReportFormatChange(
+ const OmxConfigurator::MediaFormat& input_format,
+ const OmxConfigurator::MediaFormat& output_format);
// Helper method to configure port format at LOADED state.
bool ConfigureIOPorts();
- bool ConfigureAsDecoder(OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
- OMX_PARAM_PORTDEFINITIONTYPE* output_port_def);
- bool ConfigureAsEncoder(OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
- OMX_PARAM_PORTDEFINITIONTYPE* output_port_def);
-
- // Helper to return predefined OpenMAX role name for specific codec type.
- static std::string SelectRole(Codec codec, bool encoder);
// Methods and free input and output buffers.
bool AllocateInputBuffers();
@@ -378,14 +298,10 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
State state_;
State next_state_;
- // TODO(hclam): We should keep a list of component names.
std::string role_name_;
std::string component_name_;
OMX_COMPONENTTYPE* component_handle_;
- bool encoder_;
- int64 next_sample_timestamp_;
- OmxMediaFormat input_format_;
- OmxMediaFormat output_format_;
+ scoped_ptr<OmxConfigurator> configurator_;
MessageLoop* message_loop_;
scoped_ptr<FormatCallback> format_callback_;
@@ -400,8 +316,11 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
// Input and output buffers that we can use to feed the decoder.
std::queue<OMX_BUFFERHEADERTYPE*> available_input_buffers_;
std::queue<OMX_BUFFERHEADERTYPE*> available_output_buffers_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OmxCodec);
};
} // namespace media
-#endif // MEDIA_OMX_CODEC_H_
+#endif // MEDIA_OMX_OMX_CODEC_H_
diff --git a/media/omx/omx_configurator.cc b/media/omx/omx_configurator.cc
new file mode 100644
index 0000000..6f9c2ad
--- /dev/null
+++ b/media/omx/omx_configurator.cc
@@ -0,0 +1,172 @@
+// 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.
+
+#include "media/omx/omx_configurator.h"
+
+#include "base/logging.h"
+
+namespace {
+
+std::string GetCodecName(media::OmxConfigurator::Codec codec) {
+ switch (codec) {
+ case media::OmxConfigurator::kCodecH264:
+ return "avc";
+ case media::OmxConfigurator::kCodecH263:
+ return "h263";
+ case media::OmxConfigurator::kCodecMpeg4:
+ return "mpeg4";
+ case media::OmxConfigurator::kCodecVc1:
+ return "vc1";
+ default:
+ break;
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace
+
+namespace media {
+
+std::string OmxDecoderConfigurator::GetRoleName() const {
+ return "video_decoder." + GetCodecName(input_format().codec);
+}
+
+bool OmxDecoderConfigurator::ConfigureIOPorts(
+ OMX_COMPONENTTYPE* component,
+ OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
+ OMX_PARAM_PORTDEFINITIONTYPE* output_port_def) const {
+ // Configure the input port.
+ if (input_format().codec == kCodecNone) {
+ LOG(ERROR) << "Unsupported codec " << input_format().codec;
+ return false;
+ }
+ if (input_format().codec == kCodecH264)
+ input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ else if (input_format().codec == kCodecMpeg4)
+ input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ else if (input_format().codec == kCodecH263)
+ input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
+ else if (input_format().codec == kCodecVc1)
+ input_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
+
+ // Assumes 480P.
+ input_port_def->format.video.nFrameWidth = 720;
+ input_port_def->format.video.nFrameHeight = 480;
+ OMX_ERRORTYPE omxresult = OMX_ErrorNone;
+ omxresult = OMX_SetParameter(component,
+ OMX_IndexParamPortDefinition,
+ input_port_def);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "SetParameter(OMX_IndexParamPortDefinition) "
+ "for input port failed";
+ return false;
+ }
+ return true;
+}
+
+std::string OmxEncoderConfigurator::GetRoleName() const {
+ return "video_encoder." + GetCodecName(output_format().codec);
+}
+
+bool OmxEncoderConfigurator::ConfigureIOPorts(
+ OMX_COMPONENTTYPE* component,
+ OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
+ OMX_PARAM_PORTDEFINITIONTYPE* output_port_def) const {
+ // TODO(jiesun): Add support for other format than MPEG4.
+ DCHECK_EQ(kCodecMpeg4, output_format().codec);
+ // Configure the input port.
+ input_port_def->format.video.nFrameWidth =
+ input_format().video_header.width;
+ input_port_def->format.video.nFrameHeight =
+ input_format().video_header.height;
+ OMX_ERRORTYPE omxresult = OMX_ErrorNone;
+ omxresult = OMX_SetParameter(component,
+ OMX_IndexParamPortDefinition,
+ input_port_def);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "SetParameter(OMX_IndexParamPortDefinition) "
+ "for input port failed";
+ return false;
+ }
+
+ // Configure the output port.
+ output_port_def->format.video.nFrameWidth =
+ input_format().video_header.width;
+ output_port_def->format.video.nFrameHeight =
+ input_format().video_header.height;
+ omxresult = OMX_SetParameter(component,
+ OMX_IndexParamPortDefinition,
+ output_port_def);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "SetParameter(OMX_IndexParamPortDefinition) "
+ "for output port failed";
+ return false;
+ }
+
+ if (output_format().codec == kCodecMpeg4) {
+ OMX_VIDEO_PARAM_MPEG4TYPE mp4_type;
+ omxresult = OMX_GetParameter(component,
+ OMX_IndexParamVideoMpeg4,
+ &mp4_type);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "GetParameter(OMX_IndexParamVideoMpeg4) failed";
+ return false;
+ }
+ // TODO(jiesun): verify if other vendors had the same definition.
+ // Specify the frame rate.
+ mp4_type.nTimeIncRes = output_format().video_header.frame_rate * 2;
+ // Specify how many P frames between adjacent intra frames.
+ mp4_type.nPFrames = output_format().video_header.i_dist - 1;
+ omxresult = OMX_SetParameter(component,
+ OMX_IndexParamVideoMpeg4,
+ &mp4_type);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "SetParameter(OMX_IndexParamVideoMpeg4) failed";
+ return false;
+ }
+ }
+
+ OMX_VIDEO_PARAM_BITRATETYPE bitrate;
+ omxresult = OMX_GetParameter(component,
+ OMX_IndexParamVideoBitrate,
+ &bitrate);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "GetParameter(OMX_IndexParamVideoBitrate) failed";
+ return false;
+ }
+
+ // TODO(jiesun): expose other rate control method that matters.
+ bitrate.eControlRate = OMX_Video_ControlRateConstant;
+ bitrate.nTargetBitrate = output_format().video_header.bit_rate;
+ omxresult = OMX_SetParameter(component,
+ OMX_IndexParamVideoBitrate,
+ &bitrate);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "SetParameter(OMX_IndexParamVideoBitrate) failed";
+ return false;
+ }
+
+ OMX_CONFIG_FRAMERATETYPE framerate;
+ omxresult = OMX_GetConfig(component,
+ OMX_IndexConfigVideoFramerate,
+ &framerate);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "GetParameter(OMX_IndexConfigVideoFramerate) failed";
+ return false;
+ }
+
+ framerate.xEncodeFramerate =
+ output_format().video_header.frame_rate << 16; // Q16 format.
+ omxresult = OMX_SetConfig(component,
+ OMX_IndexConfigVideoFramerate,
+ &framerate);
+ if (omxresult != OMX_ErrorNone) {
+ LOG(ERROR) << "SetParameter(OMX_IndexConfigVideoFramerate) failed";
+ return false;
+ }
+ return true;
+}
+
+} // namespace media
diff --git a/media/omx/omx_configurator.h b/media/omx/omx_configurator.h
new file mode 100644
index 0000000..6d50b33
--- /dev/null
+++ b/media/omx/omx_configurator.h
@@ -0,0 +1,154 @@
+// 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.
+
+#ifndef MEDIA_OMX_OMX_CONFIGURATOR_H_
+#define MEDIA_OMX_OMX_CONFIGURATOR_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "third_party/openmax/il/OMX_Component.h"
+#include "third_party/openmax/il/OMX_Core.h"
+#include "third_party/openmax/il/OMX_Video.h"
+
+namespace media {
+
+class OmxConfigurator {
+ public:
+ enum Codec {
+ kCodecNone,
+ kCodecH264,
+ kCodecMpeg4,
+ kCodecH263,
+ kCodecVc1,
+ kCodecRaw,
+ };
+
+ // TODO(jiesun): figure out what other surface formats are.
+ enum SurfaceFormat {
+ kSurfaceFormatNV21,
+ kSurfaceFormatNV21Tiled,
+ kSurfaceFormatNV12,
+ };
+
+ struct MediaFormatVideoHeader {
+ 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 MediaFormatVideoRaw {
+ SurfaceFormat color_space;
+ };
+
+ struct MediaFormatVideoH264 {
+ 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 MediaFormatVideoMPEG4 {
+ int ac_pred_enable;
+ int time_inc_res;
+ int slice_enable;
+ };
+
+ struct MediaFormat {
+ // TODO(jiesun): instead of codec type, we should have media format.
+ Codec codec;
+ MediaFormatVideoHeader video_header;
+ union {
+ MediaFormatVideoRaw raw;
+ MediaFormatVideoH264 h264;
+ MediaFormatVideoMPEG4 mpeg4;
+ };
+ };
+
+ OmxConfigurator(const MediaFormat& input,
+ const MediaFormat& output)
+ : input_format_(input),
+ output_format_(output) {
+ }
+
+ virtual ~OmxConfigurator() {}
+
+ // Returns the role name for this configuration.
+ virtual std::string GetRoleName() const = 0;
+
+ // Called by OmxCodec on the message loop given to it during
+ // transition to idle state.
+ // OmxCodec reads the current IO port definitions and pass it to this
+ // method.
+ // Returns true if configuration has completed successfully.
+ virtual bool ConfigureIOPorts(
+ OMX_COMPONENTTYPE* component,
+ OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
+ OMX_PARAM_PORTDEFINITIONTYPE* output_port_def) const = 0;
+
+ const MediaFormat& input_format() const { return input_format_; }
+ const MediaFormat& output_format() const { return output_format_; }
+
+ private:
+ MediaFormat input_format_;
+ MediaFormat output_format_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OmxConfigurator);
+};
+
+class OmxDecoderConfigurator : public OmxConfigurator {
+ public:
+ OmxDecoderConfigurator(const MediaFormat& input,
+ const MediaFormat& output)
+ : OmxConfigurator(input, output) {
+ }
+
+ virtual ~OmxDecoderConfigurator() {}
+
+ virtual std::string GetRoleName() const;
+
+ virtual bool ConfigureIOPorts(
+ OMX_COMPONENTTYPE* component,
+ OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
+ OMX_PARAM_PORTDEFINITIONTYPE* output_port_def) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OmxDecoderConfigurator);
+};
+
+class OmxEncoderConfigurator : public OmxConfigurator {
+ public:
+ OmxEncoderConfigurator(const MediaFormat& input,
+ const MediaFormat& output)
+ : OmxConfigurator(input, output) {
+ }
+
+ virtual ~OmxEncoderConfigurator() {}
+
+ virtual std::string GetRoleName() const;
+
+ virtual bool ConfigureIOPorts(
+ OMX_COMPONENTTYPE* component,
+ OMX_PARAM_PORTDEFINITIONTYPE* input_port_def,
+ OMX_PARAM_PORTDEFINITIONTYPE* output_port_def) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OmxEncoderConfigurator);
+};
+
+} // namespace media
+
+#endif // MEDIA_OMX_OMX_CONFIGURATOR_H_