diff options
-rw-r--r-- | media/filters/omx_video_decode_engine.cc | 4 | ||||
-rw-r--r-- | media/omx/omx_codec.cc | 114 | ||||
-rw-r--r-- | media/omx/omx_codec.h | 9 | ||||
-rw-r--r-- | media/omx/omx_test.cc | 15 |
4 files changed, 106 insertions, 36 deletions
diff --git a/media/filters/omx_video_decode_engine.cc b/media/filters/omx_video_decode_engine.cc index a263509..89e687f 100644 --- a/media/filters/omx_video_decode_engine.cc +++ b/media/filters/omx_video_decode_engine.cc @@ -32,10 +32,12 @@ void OmxVideoDecodeEngine::Initialize(AVStream* stream, Task* done_cb) { // TODO(ajwong): Find the right way to determine the Omx component name. OmxCodec::OmxMediaFormat input_format; + memset(&input_format, 0, sizeof(input_format)); input_format.codec = OmxCodec::kCodecH264; OmxCodec::OmxMediaFormat output_format; + memset(&output_format, 0, sizeof(output_format)); output_format.codec = OmxCodec::kCodecRaw; - omx_codec_->Setup("OMX.st.video_decoder.avc", input_format, output_format); + omx_codec_->Setup(input_format, output_format); omx_codec_->SetErrorCallback( NewCallback(this, &OmxVideoDecodeEngine::OnHardwareError)); omx_codec_->SetFormatCallback( diff --git a/media/omx/omx_codec.cc b/media/omx/omx_codec.cc index 55d02f5..b757a88 100644 --- a/media/omx/omx_codec.cc +++ b/media/omx/omx_codec.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/stl_util-inl.h" +#include "base/string_util.h" #include "media/omx/input_buffer.h" #include "media/omx/omx_codec.h" @@ -45,14 +46,14 @@ OmxCodec::~OmxCodec() { } void OmxCodec::Setup( - const std::string& component_name, const OmxCodec::OmxMediaFormat& input_format, const OmxCodec::OmxMediaFormat& output_format) { DCHECK_EQ(kEmpty, state_); DCHECK_NE(input_format.codec, kCodecNone); - component_name_ = component_name; input_format_ = input_format; output_format_ = output_format; + Codec codec = encoder() ? output_format_.codec : input_format_.codec; + role_name_ = SelectRole(codec, encoder()); } void OmxCodec::SetErrorCallback(Callback* callback) { @@ -273,21 +274,23 @@ void OmxCodec::FreeOutputQueue() { // Sequence of actions in this transition: // // 1. Initialize OMX (To be removed.) -// 2. Get handle of the OMX component -// 3. Get parameters about I/O ports. -// 4. Device specific configurations. -// 5. General configuration of input port. -// 6. General configuration of output port. -// 7. Get Parameters about input port. -// 8. Get Parameters about output port. -// 9. Codec specific configurations. +// 2. Map role name to component name. +// 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. void OmxCodec::Transition_EmptyToLoaded() { DCHECK_EQ(message_loop_, MessageLoop::current()); DCHECK_EQ(kEmpty, GetState()); - OMX_CALLBACKTYPE callback = { &EventHandler, - &EmptyBufferCallback, - &FillBufferCallback }; + static OMX_CALLBACKTYPE callback = { + &EventHandler, + &EmptyBufferCallback, + &FillBufferCallback + }; // 1. Initialize the OpenMAX Core. // TODO(hclam): move this out. @@ -298,9 +301,45 @@ void OmxCodec::Transition_EmptyToLoaded() { return; } - // 2. Get the handle to the component. After OMX_GetHandle(), + // 2. Map role name to component name. + OMX_U32 roles = 0; + omxresult = OMX_GetComponentsOfRole( + const_cast<OMX_STRING>(role_name_.c_str()), + &roles, 0); + if (omxresult != OMX_ErrorNone || roles == 0) { + LOG(ERROR) << "Unsupported Role: " << role_name_.c_str(); + StateTransitionTask(kError); + return; + } + const OMX_U32 kMaxRolePerComponent = 20; + CHECK(roles < kMaxRolePerComponent); + + OMX_U8** component_names = new OMX_U8*[roles]; + const int kMaxComponentNameLength = 256; + for (size_t i = 0; i < roles; ++i) + component_names[i] = new OMX_U8[kMaxComponentNameLength]; + + omxresult = OMX_GetComponentsOfRole( + const_cast<OMX_STRING>(role_name_.c_str()), + &roles, component_names); + + // Use first component only. Copy the name of the first component + // so that we could free the memory. + if (omxresult == OMX_ErrorNone) + component_name_ = reinterpret_cast<char*>(component_names[0]); + + for (size_t i = 0; i < roles; ++i) + delete [] component_names[i]; + delete [] component_names; + + if (omxresult != OMX_ErrorNone || roles == 0) { + LOG(ERROR) << "Unsupported Role: " << role_name_.c_str(); + StateTransitionTask(kError); + return; + } + + // 3. 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_name_.c_str()); OMX_HANDLETYPE handle = reinterpret_cast<OMX_HANDLETYPE>(component_handle_); omxresult = OMX_GetHandle(&handle, component, this, &callback); @@ -311,7 +350,7 @@ void OmxCodec::Transition_EmptyToLoaded() { return; } - // 3. Get the port information. This will obtain information about the + // 4. Get the port information. This will obtain information about the // number of ports and index of the first port. OMX_PORT_PARAM_TYPE port_param; ResetPortHeader(*this, &port_param); @@ -325,21 +364,38 @@ void OmxCodec::Transition_EmptyToLoaded() { input_port_ = port_param.nStartPortNumber; output_port_ = input_port_ + 1; - // 4. Device specific configurations. + // 5. Set role for the component because our component could + // have multiple roles. + OMX_PARAM_COMPONENTROLETYPE role_type; + ResetPortHeader(*this, &role_type); + base::strlcpy(reinterpret_cast<char*>(role_type.cRole), + role_name_.c_str(), + OMX_MAX_STRINGNAME_SIZE); + role_type.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; + omxresult = OMX_SetParameter(component_handle_, + OMX_IndexParamStandardComponentRole, + &role_type); + if (omxresult != OMX_ErrorNone) { + LOG(ERROR) << "Failed to Set Role"; + StateTransitionTask(kError); + return; + } + + // 6. Device specific configurations. if (!DeviceSpecificConfig()) { LOG(ERROR) << "Device specific configurations failed"; StateTransitionTask(kError); return; } - // 5. Input/output ports media format configuration. + // 7. Input/output ports media format configuration. if (!ConfigureIOPorts()) { LOG(ERROR) << "Media format configurations failed"; StateTransitionTask(kError); return; } - // 6. Obtain the information about the input port. + // 8. 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; @@ -361,7 +417,7 @@ void OmxCodec::Transition_EmptyToLoaded() { input_buffer_count_ = port_format.nBufferCountMin; input_buffer_size_ = port_format.nBufferSize; - // 7. Obtain the information about the output port. + // 9. Obtain the information about the output port. ResetPortHeader(*this, &port_format); port_format.nPortIndex = output_port_; omxresult = OMX_GetParameter(component_handle_, @@ -826,6 +882,24 @@ void OmxCodec::ReportFormatChange() { 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 ""; +} + bool OmxCodec::ConfigureIOPorts() { OMX_PARAM_PORTDEFINITIONTYPE input_port_def, output_port_def; OMX_ERRORTYPE omxresult = OMX_ErrorNone; diff --git a/media/omx/omx_codec.h b/media/omx/omx_codec.h index c198766..bb98a3d 100644 --- a/media/omx/omx_codec.h +++ b/media/omx/omx_codec.h @@ -18,7 +18,7 @@ // 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->Setup(input_format, output_format); // decoder->SetErrorCallback(NewCallback(this, &Client::ErrorCallback)); // decoder->SetFormatCallback(NewCallback(this, &Client::FormatCallback)); // @@ -174,8 +174,7 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> { // Set the component name and input/output media format. // TODO(hclam): Remove |component|. - void Setup(const std::string& component_name, - const OmxMediaFormat& input_format, + void Setup(const OmxMediaFormat& input_format, const OmxMediaFormat& output_format); // Set the error callback. In case of error the callback will be called. @@ -264,6 +263,9 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> { 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(); bool AllocateOutputBuffers(); @@ -375,6 +377,7 @@ class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> { 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_; diff --git a/media/omx/omx_test.cc b/media/omx/omx_test.cc index 34b98c3..a86f6a6 100644 --- a/media/omx/omx_test.cc +++ b/media/omx/omx_test.cc @@ -26,7 +26,6 @@ class TestApp { public: TestApp(const char* input_filename, const char* output_filename, - const std::string& component_name, media::OmxCodec::OmxMediaFormat& input_format, media::OmxCodec::OmxMediaFormat& output_format, bool simulate_copy, @@ -35,7 +34,6 @@ class TestApp { int loop_count) : input_filename_(input_filename), output_filename_(output_filename), - component_name_(component_name), input_format_(input_format), output_format_(output_format), simulate_copy_(simulate_copy), @@ -282,7 +280,7 @@ class TestApp { // Setup the |codec_| with the message loop of the current thread. Also // setup component name, codec format and callbacks. codec_ = new media::OmxCodec(&message_loop_); - codec_->Setup(component_name_, input_format_, output_format_); + codec_->Setup(input_format_, output_format_); codec_->SetErrorCallback(NewCallback(this, &TestApp::ErrorCallback)); codec_->SetFormatCallback(NewCallback(this, &TestApp::FormatCallback)); @@ -403,7 +401,6 @@ class TestApp { MessageLoop message_loop_; const char* input_filename_; const char* output_filename_; - std::string component_name_; media::OmxCodec::OmxMediaFormat input_format_; media::OmxCodec::OmxMediaFormat output_format_; bool simulate_copy_; @@ -434,11 +431,9 @@ int main(int argc, char** argv) { bool encoder = cmd_line->HasSwitch("encoder"); if (!encoder) { if (argc < 3) { - printf("Usage: omx_test --input-file=FILE" - " --component=COMPONENT --codec=CODEC" + printf("Usage: omx_test --input-file=FILE --codec=CODEC" " [--output-file=FILE] [--enable-csc]" " [--copy] [--measure-fps]\n"); - printf(" COMPONENT: OpenMAX component name\n"); printf(" CODEC: h264/mpeg4/h263/vc1\n"); printf("\n"); printf("Optional Arguments\n"); @@ -451,13 +446,11 @@ int main(int argc, char** argv) { } } else { if (argc < 7) { - printf("Usage: omx_test --input-file=FILE" - " --component=COMPONENT --codec=CODEC" + printf("Usage: omx_test --input-file=FILE --codec=CODEC" " --width=PIXEL_WIDTH --height=PIXEL_HEIGHT" " --bitrate=BIT_PER_SECOND --framerate=FRAME_PER_SECOND" " [--output-file=FILE] [--enable-csc]" " [--copy] [--measure-fps]\n"); - printf(" COMPONENT: OpenMAX component name\n"); printf(" CODEC: h264/mpeg4/h263/vc1\n"); printf("\n"); printf("Optional Arguments\n"); @@ -472,7 +465,6 @@ int main(int argc, char** argv) { std::string input_filename = cmd_line->GetSwitchValueASCII("input-file"); std::string output_filename = cmd_line->GetSwitchValueASCII("output-file"); - std::string component_name = 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"); @@ -522,7 +514,6 @@ int main(int argc, char** argv) { // Create a TestApp object and run the decoder. TestApp test(input_filename.c_str(), output_filename.c_str(), - component_name, input, output, copy, |