diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-22 02:12:34 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-22 02:12:34 +0000 |
commit | e41dd82ca759c41fe121da6200278e9d174a1461 (patch) | |
tree | 4e49bd4b48a3b968ae2864897952632bb17a3286 /media/omx | |
parent | f060a159b265353593d0b1604af2ef12afe05dfe (diff) | |
download | chromium_src-e41dd82ca759c41fe121da6200278e9d174a1461.zip chromium_src-e41dd82ca759c41fe121da6200278e9d174a1461.tar.gz chromium_src-e41dd82ca759c41fe121da6200278e9d174a1461.tar.bz2 |
Unit tests for testing OpenMAX support
Added the following test cases:
1. GetComponentsByRole() now works with valid roles
2. GetHandle() / FreeHandle() pair on video decoder component
3. General configuration of video decoder component
TEST=omx_unittests
Review URL: http://codereview.chromium.org/550051
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36834 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/omx')
-rw-r--r-- | media/omx/omx_unittest.cc | 355 |
1 files changed, 331 insertions, 24 deletions
diff --git a/media/omx/omx_unittest.cc b/media/omx/omx_unittest.cc index 76d8f14..c2f7143 100644 --- a/media/omx/omx_unittest.cc +++ b/media/omx/omx_unittest.cc @@ -2,45 +2,352 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/command_line.h" +#include "base/condition_variable.h" #include "base/logging.h" +#include "base/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/openmax/il/OMX_Component.h" #include "third_party/openmax/il/OMX_Core.h" -namespace media { +namespace { + +// Defines the maximum number of buffers created for I/O ports. +const int kMaxBufferNum = 256; -TEST(OmxTest, SimpleInit) { - EXPECT_EQ(OMX_ErrorNone, OMX_Init()); - EXPECT_EQ(OMX_ErrorNone, OMX_Deinit()); +template <typename T> +static void ResetHeader(T* param) { + memset(param, 0, sizeof(T)); + // TODO(hclam): Make this version number configurable. + param->nVersion.nVersion = 0x00000101; + param->nSize = sizeof(T); } -TEST(OmxTest, GetComponentsOfRole) { - OMX_U32 roles = 0; - OMX_U8** component_names = NULL; - char role[] = "video_decoder"; - const int kSize = 256; +} // namespace + +namespace media { + +class OmxTest : public testing::Test { + public: + OmxTest() + : handle_(NULL), + event_(&lock_), + empty_buffer_(&lock_), + fill_buffer_(&lock_) { + memset(input_buffers_, 0, sizeof(input_buffers_)); + memset(output_buffers_, 0, sizeof(output_buffers_)); + } + + protected: + virtual void SetUp() { + // Initialize OpenMAX. + EXPECT_EQ(OMX_ErrorNone, OMX_Init()); + } + + virtual void TearDown() { + EXPECT_EQ(OMX_ErrorNone, OMX_Deinit()); + } + + void InitComponent(std::string component_name) { + OMX_CALLBACKTYPE callback = { &EventHandler, + &EmptyBufferCallback, + &FillBufferCallback }; + + OMX_ERRORTYPE omxresult = OMX_GetHandle( + (void**)&handle_, + const_cast<OMX_STRING>(component_name.c_str()), + this, &callback); + EXPECT_EQ(OMX_ErrorNone, omxresult); + CHECK(handle_); + } + + void DeinitComponent() { + if (handle_) + OMX_FreeHandle(handle_); + } + + void AllocateBuffers(int port) { + int count = 0; + int size = 0; + OMX_BUFFERHEADERTYPE** buffers = NULL; + if (port == input_port_) { + count = input_buffer_count_; + size = input_buffer_size_; + buffers = input_buffers_; + } else if (port == output_port_) { + count = output_buffer_count_; + size = output_buffer_size_; + buffers = output_buffers_; + } else { + NOTREACHED() << "Not a valid port"; + } + for (int i = 0; i < count; ++i) { + CHECK(!buffers[i]); + EXPECT_EQ(OMX_ErrorNone, + OMX_AllocateBuffer(handle_, buffers + i, + port, NULL, size)); + } + } + + void ReleaseBuffers(int port) { + int count = 0; + OMX_BUFFERHEADERTYPE** buffers = NULL; + if (port == input_port_) { + count = input_buffer_count_; + buffers = input_buffers_; + } else if (port == output_port_) { + count = output_buffer_count_; + buffers = output_buffers_; + } else { + NOTREACHED() << "Not a valid port"; + } + for (int i = 0; i < count; ++i) { + CHECK(buffers[i]); + EXPECT_EQ(OMX_ErrorNone, + OMX_FreeBuffer(handle_, port, buffers[i])); + buffers[i] = NULL; + } + } + + void TransitionToIdle() { + EXPECT_EQ(OMX_ErrorNone, + OMX_SendCommand(handle_, OMX_CommandStateSet, + OMX_StateIdle, 0)); + AllocateBuffers(input_port_); + AllocateBuffers(output_port_); + AutoLock auto_lock(lock_); + event_.Wait(); + } + + void TransitionToLoaded() { + EXPECT_EQ(OMX_ErrorNone, + OMX_SendCommand(handle_, OMX_CommandStateSet, + OMX_StateLoaded, 0)); + ReleaseBuffers(input_port_); + ReleaseBuffers(output_port_); + AutoLock auto_lock(lock_); + event_.Wait(); + } + + void GetComponentsOfRole(std::string role) { + OMX_U32 roles = 0; + OMX_U8** component_names = NULL; + const int kSize = 256; + + LOG(INFO) << "GetComponentsOfRole: " << role; + EXPECT_EQ(OMX_ErrorNone, OMX_GetComponentsOfRole( + const_cast<OMX_STRING>(role.c_str()), &roles, 0)); + + // TODO(hclam): Should assert the component number. + LOG(INFO) << "Components: " << roles; + + if (roles) { + component_names = new OMX_U8*[roles]; + for (size_t i = 0; i < roles; ++i) + component_names[i] = new OMX_U8[kSize]; + + OMX_U32 roles_backup = roles; + EXPECT_EQ(OMX_ErrorNone, + OMX_GetComponentsOfRole( + const_cast<OMX_STRING>(role.c_str()), + &roles, component_names)); + ASSERT_EQ(roles_backup, roles); + + for (size_t i = 0; i < roles; ++i) { + LOG(INFO) << "Component name: " << component_names[i]; + delete [] component_names[i]; + } + delete [] component_names; + } + } + + OMX_ERRORTYPE EventHandlerInternal( + OMX_HANDLETYPE component, OMX_EVENTTYPE event, + OMX_U32 data1, OMX_U32 data2, OMX_PTR event_data) { + AutoLock auto_lock(lock_); + // TODO(hclam): Save the parameters. + event_.Signal(); + return OMX_ErrorNone; + } + + OMX_ERRORTYPE EmptyBufferCallbackInternal( + OMX_HANDLETYPE component, OMX_BUFFERHEADERTYPE* buffer) { + // TODO(hclam): Add code here. + AutoLock auto_lock(lock_); + empty_buffer_.Signal(); + return OMX_ErrorNone; + } - EXPECT_EQ(OMX_ErrorNone, OMX_Init()); - EXPECT_EQ(OMX_ErrorNone, OMX_GetComponentsOfRole(role, &roles, 0)); + OMX_ERRORTYPE FillBufferCallbackInternal( + OMX_HANDLETYPE component, OMX_BUFFERHEADERTYPE* buffer) { + // TODO(hclam): Add code here. + AutoLock auto_lock(lock_); + fill_buffer_.Signal(); + return OMX_ErrorNone; + } + + // Static callback methods. + static OMX_ERRORTYPE EventHandler( + OMX_HANDLETYPE component, OMX_PTR priv_data, + OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2, + OMX_PTR event_data) { + return static_cast<OmxTest*>(priv_data) + ->EventHandlerInternal(component, + event, data1, data2, event_data); + } + + static OMX_ERRORTYPE EmptyBufferCallback( + OMX_HANDLETYPE component, OMX_PTR priv_data, + OMX_BUFFERHEADERTYPE* buffer) { + return static_cast<OmxTest*>(priv_data) + ->EmptyBufferCallbackInternal(component, buffer); + } + + static OMX_ERRORTYPE FillBufferCallback( + OMX_HANDLETYPE component, OMX_PTR priv_data, + OMX_BUFFERHEADERTYPE* buffer) { + return static_cast<OmxTest*>(priv_data) + ->FillBufferCallbackInternal(component, buffer); + } + + OMX_COMPONENTTYPE* handle_; + int input_port_; + int output_port_; + int input_buffer_count_; + int input_buffer_size_; + int output_buffer_count_; + int output_buffer_size_; + OMX_BUFFERHEADERTYPE* input_buffers_[kMaxBufferNum]; + OMX_BUFFERHEADERTYPE* output_buffers_[kMaxBufferNum]; + + Lock lock_; + ConditionVariable event_; + ConditionVariable empty_buffer_; + ConditionVariable fill_buffer_; +}; + +class OmxVideoDecoderTest : public OmxTest { + protected: + void Configure(OMX_VIDEO_CODINGTYPE codec, + int width, int height) { + // Obtain port IDs. + OMX_PORT_PARAM_TYPE port_param; + ResetHeader(&port_param); + EXPECT_EQ(OMX_ErrorNone, + OMX_GetParameter(handle_, + OMX_IndexParamVideoInit, + &port_param)); + + input_port_ = port_param.nStartPortNumber; + output_port_ = port_param.nStartPortNumber + 1; + LOG(INFO) << "Input port number: " << input_port_; + LOG(INFO) << "Output port number: " << output_port_; + + // Get and set parameters for input port. + LOG(INFO) << "Input port width: " << width; + LOG(INFO) << "Input port height: " << height; + LOG(INFO) << "Input port codec: " << codec; + OMX_PARAM_PORTDEFINITIONTYPE port_format; + ResetHeader(&port_format); + port_format.nPortIndex = input_port_; + EXPECT_EQ(OMX_ErrorNone, + OMX_GetParameter(handle_, + OMX_IndexParamPortDefinition, + &port_format)); + EXPECT_EQ(OMX_DirInput, port_format.eDir); + port_format.format.video.eCompressionFormat = codec; + port_format.format.video.nFrameWidth = width; + port_format.format.video.nFrameHeight = height; + EXPECT_EQ(OMX_ErrorNone, + OMX_SetParameter(handle_, + OMX_IndexParamPortDefinition, + &port_format)); - // TODO(hclam): Should assert the component number. - LOG(INFO) << "Video decoder components: " << roles; + // TODO(hclam): Add configurations to output port. - if (roles) { - component_names = new OMX_U8*[roles]; - for (size_t i = 0; i < roles; ++i) - component_names[i] = new OMX_U8[kSize]; + // Get Parameters for input port. + ResetHeader(&port_format); + port_format.nPortIndex = input_port_; + EXPECT_EQ(OMX_ErrorNone, + OMX_GetParameter(handle_, + OMX_IndexParamPortDefinition, + &port_format)); + EXPECT_EQ(OMX_DirInput, port_format.eDir); + input_buffer_count_ = port_format.nBufferCountMin; + input_buffer_size_ = port_format.nBufferSize; + CHECK(input_buffer_count_ < kMaxBufferNum); - OMX_U32 roles_backup = roles; + // Get parameters for output port. + ResetHeader(&port_format); + port_format.nPortIndex = output_port_; EXPECT_EQ(OMX_ErrorNone, - OMX_GetComponentsOfRole(role, &roles, component_names)); - ASSERT_EQ(roles_backup, roles); + OMX_GetParameter(handle_, + OMX_IndexParamPortDefinition, + &port_format)); + EXPECT_EQ(OMX_DirOutput, port_format.eDir); + output_buffer_count_ = port_format.nBufferCountMin; + output_buffer_size_ = port_format.nBufferSize; + CHECK(output_buffer_count_ < kMaxBufferNum); + + LOG(INFO) << "Input buffer count: " << input_buffer_count_; + LOG(INFO) << "Input buffer size: " << input_buffer_size_; + LOG(INFO) << "Output buffer count: " << output_buffer_count_; + LOG(INFO) << "Output buffer size: " << output_buffer_size_; + } + + std::string component() { + return CommandLine::ForCurrentProcess() + ->GetSwitchValueASCII("video-decoder-component"); + } - for (size_t i = 0; i < roles; ++i) - delete [] component_names[i]; - delete [] component_names; + OMX_VIDEO_CODINGTYPE codec() { + std::string codec = CommandLine::ForCurrentProcess() + ->GetSwitchValueASCII("video-decoder-codec"); + if (codec == "h264") + return OMX_VIDEO_CodingAVC; + return OMX_VIDEO_CodingAutoDetect; } - EXPECT_EQ(OMX_ErrorNone, OMX_Deinit()); +}; + +TEST_F(OmxTest, SimpleInit) { + // A empty test case will test basic init/deinit of OpenMAX library. +} + +TEST_F(OmxTest, GetComponentsOfRole) { + // Roles video decoders. + GetComponentsOfRole("video_decoder.avc"); + GetComponentsOfRole("video_decoder.mpeg4"); + GetComponentsOfRole("video_decoder.vc1"); + + // TODO(hclam): Add roles of encoders. +} + +TEST_F(OmxVideoDecoderTest, GetHandle) { + // TODO(hclam): Should use GetComponentsOfRole instead. + InitComponent(component()); + DeinitComponent(); +} + +TEST_F(OmxVideoDecoderTest, Configuration) { + InitComponent(component()); + // TODO(hclam): Make resolution configurable. + Configure(codec(), 1024, 768); + DeinitComponent(); +} + +TEST_F(OmxVideoDecoderTest, TransitionToIdle) { + InitComponent(component()); + Configure(codec(), 1024, 768); + TransitionToIdle(); + TransitionToLoaded(); + DeinitComponent(); +} + +TEST_F(OmxVideoDecoderTest, FreeHandleWhenIdle) { + InitComponent(component()); + Configure(codec(), 1024, 768); + TransitionToIdle(); + DeinitComponent(); } } // namespace media |