diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-03 16:15:28 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-03 16:15:28 +0000 |
commit | edda6f2964eb176cd35741df9719b275f3d2a622 (patch) | |
tree | fe2f94e8e5dbd14b6ed9512594b7aa09d00ad9bf /media | |
parent | e79e7c7f129f85625cb050f153a4b022a8b88de3 (diff) | |
download | chromium_src-edda6f2964eb176cd35741df9719b275f3d2a622.zip chromium_src-edda6f2964eb176cd35741df9719b275f3d2a622.tar.gz chromium_src-edda6f2964eb176cd35741df9719b275f3d2a622.tar.bz2 |
Removing defunct OpenMAX code.
All of this code hasn't been used in over a year and has been replaced by VideoDecodeAccelerator and it's corresponding OpenMAX implementation OmxVideoDecodeAccelerator.
BUG=none
TEST=the world still compiles
Review URL: http://codereview.chromium.org/7066071
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87790 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
23 files changed, 5 insertions, 4615 deletions
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index c93727e..54e83b5 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc @@ -19,10 +19,6 @@ const char kEnableAcceleratedDecoding[] = "enable-accelerated-decoding"; // Enable x-adaptive URL scheme. const char kEnableAdaptive[] = "enable-adaptive"; -// Enable hardware decoding using OpenMax API. -// In practice this is for ChromeOS ARM. -const char kEnableOpenMax[] = "enable-openmax"; - // Set number of threads to use for video decoding. const char kVideoThreads[] = "video-threads"; diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 904f9bc..b84fcda 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h @@ -18,10 +18,8 @@ extern const char kAlsaInputDevice[]; extern const char kEnableAcceleratedDecoding[]; extern const char kEnableAdaptive[]; -extern const char kEnableOpenMax[]; extern const char kVideoThreads[]; - } // namespace switches #endif // MEDIA_BASE_MEDIA_SWITCHES_H_ diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index 53d28a2..449b6aa 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc @@ -88,7 +88,6 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, } void FFmpegVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { - // TODO(scherkus): Dedup this from OmxVideoDecoder::OnInitializeComplete. DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(initialize_callback_.get()); diff --git a/media/filters/omx_video_decoder.cc b/media/filters/omx_video_decoder.cc deleted file mode 100644 index b58e1c6..0000000 --- a/media/filters/omx_video_decoder.cc +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright (c) 2011 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/filters/omx_video_decoder.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/message_loop.h" -#include "media/base/callback.h" -#include "media/base/filter_host.h" -#include "media/base/limits.h" -#include "media/ffmpeg/ffmpeg_common.h" -#include "media/video/omx_video_decode_engine.h" - -namespace media { - -OmxVideoDecoder::OmxVideoDecoder( - MessageLoop* message_loop, - VideoDecodeContext* context) - : message_loop_(message_loop), - decode_engine_(new OmxVideoDecodeEngine()), - decode_context_(context) { - DCHECK(decode_engine_.get()); - memset(&info_, 0, sizeof(info_)); -} - -OmxVideoDecoder::~OmxVideoDecoder() { - // TODO(hclam): Make sure OmxVideoDecodeEngine is stopped. -} - -void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream, - FilterCallback* callback, - StatisticsCallback* stats_callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, - &OmxVideoDecoder::Initialize, - make_scoped_refptr(demuxer_stream), - callback, stats_callback)); - return; - } - - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK(!demuxer_stream_); - DCHECK(!initialize_callback_.get()); - - initialize_callback_.reset(callback); - statistics_callback_.reset(stats_callback); - demuxer_stream_ = demuxer_stream; - - // We require bit stream converter for openmax hardware decoder. - demuxer_stream->EnableBitstreamConverter(); - - AVStream* av_stream = demuxer_stream->GetAVStream(); - if (!av_stream) { - VideoCodecInfo info = {0}; - OnInitializeComplete(info); - return; - } - - pts_stream_.Initialize(GetFrameDuration(av_stream)); - - int width = av_stream->codec->coded_width; - int height = av_stream->codec->coded_height; - - int surface_width = GetSurfaceWidth(av_stream); - int surface_height = GetSurfaceHeight(av_stream); - - if (surface_width > Limits::kMaxDimension || - surface_height > Limits::kMaxDimension || - (surface_width * surface_height) > Limits::kMaxCanvas) { - VideoCodecInfo info = {0}; - OnInitializeComplete(info); - return; - } - - VideoDecoderConfig config(CodecIDToVideoCodec(av_stream->codec->codec_id), - width, height, - surface_width, surface_height, - av_stream->r_frame_rate.num, - av_stream->r_frame_rate.den, - av_stream->codec->extradata, - av_stream->codec->extradata_size); - decode_engine_->Initialize(message_loop_, this, NULL, config); -} - -void OmxVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { - // TODO(scherkus): Dedup this from FFmpegVideoDecoder::OnInitializeComplete. - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(initialize_callback_.get()); - - info_ = info; - AutoCallbackRunner done_runner(initialize_callback_.release()); - - if (info.success) { - media_format_.SetAsInteger(MediaFormat::kWidth, - info.stream_info.surface_width); - media_format_.SetAsInteger(MediaFormat::kHeight, - info.stream_info.surface_height); - media_format_.SetAsInteger( - MediaFormat::kSurfaceType, - static_cast<int>(info.stream_info.surface_type)); - media_format_.SetAsInteger( - MediaFormat::kSurfaceFormat, - static_cast<int>(info.stream_info.surface_format)); - } else { - host()->SetError(PIPELINE_ERROR_DECODE); - } -} - -void OmxVideoDecoder::Stop(FilterCallback* callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, - &OmxVideoDecoder::Stop, - callback)); - return; - } - - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(!uninitialize_callback_.get()); - - uninitialize_callback_.reset(callback); - decode_engine_->Uninitialize(); -} - -void OmxVideoDecoder::OnUninitializeComplete() { - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(uninitialize_callback_.get()); - - AutoCallbackRunner done_runner(uninitialize_callback_.release()); - - // TODO(jiesun): Destroy the decoder context. -} - -void OmxVideoDecoder::Flush(FilterCallback* callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, - &OmxVideoDecoder::Flush, - callback)); - return; - } - - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(!flush_callback_.get()); - - flush_callback_.reset(callback); - - decode_engine_->Flush(); -} - - -void OmxVideoDecoder::OnFlushComplete() { - DCHECK(flush_callback_.get()); - - AutoCallbackRunner done_runner(flush_callback_.release()); - - pts_stream_.Flush(); -} - -void OmxVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, - &OmxVideoDecoder::Seek, - time, - cb)); - return; - } - - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(seek_cb_.is_null()); - - pts_stream_.Seek(time); - seek_cb_ = cb; - decode_engine_->Seek(); -} - -void OmxVideoDecoder::OnSeekComplete() { - DCHECK_EQ(MessageLoop::current(), message_loop_); - DCHECK(!seek_cb_.is_null()); - - ResetAndRunCB(&seek_cb_, PIPELINE_OK); -} - -void OmxVideoDecoder::OnError() { - NOTIMPLEMENTED(); -} -void OmxVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { - NOTIMPLEMENTED(); -} - -void OmxVideoDecoder::ProduceVideoSample(scoped_refptr<Buffer> buffer) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - // Issue more demux. - demuxer_stream_->Read(base::Bind(&OmxVideoDecoder::DemuxCompleteTask, this)); -} - -void OmxVideoDecoder::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame, - const PipelineStatistics& statistics) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - statistics_callback_->Run(statistics); - - if (frame.get()) { - pts_stream_.UpdatePtsAndDuration(frame.get()); - - frame->SetTimestamp(pts_stream_.current_pts()); - frame->SetDuration(pts_stream_.current_duration()); - } - - VideoFrameReady(frame); -} - -void OmxVideoDecoder::ProduceVideoFrame(scoped_refptr<VideoFrame> frame) { - DCHECK(decode_engine_.get()); - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(decode_engine_.get(), - &VideoDecodeEngine::ProduceVideoFrame, frame)); -} - -bool OmxVideoDecoder::ProvidesBuffer() { - DCHECK(info_.success); - return info_.provides_buffers; -} - -const MediaFormat& OmxVideoDecoder::media_format() { - return media_format_; -} - -void OmxVideoDecoder::DemuxCompleteTask(Buffer* buffer) { - // We simply delicate the buffer to the right message loop. - scoped_refptr<Buffer> ref_buffer = buffer; - DCHECK(decode_engine_.get()); - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, - &OmxVideoDecoder::ConsumeVideoSample, ref_buffer)); -} - -void OmxVideoDecoder::ConsumeVideoSample(scoped_refptr<Buffer> buffer) { - if (buffer.get()) - pts_stream_.EnqueuePts(buffer.get()); - decode_engine_->ConsumeVideoSample(buffer); -} - -} // namespace media - -// Disable refcounting for the decode engine because it only lives on the -// video decoder thread. -DISABLE_RUNNABLE_METHOD_REFCOUNT(media::VideoDecodeEngine); diff --git a/media/filters/omx_video_decoder.h b/media/filters/omx_video_decoder.h deleted file mode 100644 index 40bf721..0000000 --- a/media/filters/omx_video_decoder.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 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_FILTERS_OMX_VIDEO_DECODER_H_ -#define MEDIA_FILTERS_OMX_VIDEO_DECODER_H_ - -#include <queue> - -#include "media/base/filters.h" -#include "media/base/media_format.h" -#include "media/base/pts_stream.h" -#include "media/video/video_decode_context.h" -#include "media/video/video_decode_engine.h" - -class MessageLoop; - -namespace media { - -class Buffer; -class OmxVideoDecodeEngine; -class VideoFrame; - -class OmxVideoDecoder : public VideoDecoder, - public VideoDecodeEngine::EventHandler { - public: - OmxVideoDecoder(MessageLoop* message_loop, - VideoDecodeContext* decode_context); - virtual ~OmxVideoDecoder(); - - // Filter implementations. - virtual void Initialize(DemuxerStream* stream, - FilterCallback* callback, - StatisticsCallback* stats_callback); - virtual void Stop(FilterCallback* callback); - virtual void Flush(FilterCallback* callback); - virtual void Seek(base::TimeDelta time, const FilterStatusCB& cb); - virtual void ProduceVideoFrame(scoped_refptr<VideoFrame> frame); - virtual bool ProvidesBuffer(); - virtual const MediaFormat& media_format(); - - private: - // VideoDecodeEngine::EventHandler interface. - virtual void OnInitializeComplete(const VideoCodecInfo& info); - virtual void OnUninitializeComplete(); - virtual void OnFlushComplete(); - virtual void OnSeekComplete(); - virtual void OnError(); - virtual void OnFormatChange(VideoStreamInfo stream_info); - virtual void ProduceVideoSample(scoped_refptr<Buffer> buffer); - virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame, - const PipelineStatistics& statistics); - - // TODO(hclam): This is very ugly that we keep reference instead of - // scoped_refptr. - void DemuxCompleteTask(Buffer* buffer); - void ConsumeVideoSample(scoped_refptr<Buffer> buffer); - - MessageLoop* message_loop_; - - // Pointer to the demuxer stream that will feed us compressed buffers. - scoped_refptr<DemuxerStream> demuxer_stream_; - scoped_ptr<VideoDecodeEngine> decode_engine_; - scoped_ptr<VideoDecodeContext> decode_context_; - MediaFormat media_format_; - - scoped_ptr<FilterCallback> initialize_callback_; - scoped_ptr<FilterCallback> uninitialize_callback_; - scoped_ptr<FilterCallback> flush_callback_; - FilterStatusCB seek_cb_; - scoped_ptr<StatisticsCallback> statistics_callback_; - - VideoCodecInfo info_; - - PtsStream pts_stream_; // Stream of presentation timestamps. - - DISALLOW_COPY_AND_ASSIGN(OmxVideoDecoder); -}; - -} // namespace media - -#endif // MEDIA_FILTERS_OMX_VIDEO_DECODER_H_ diff --git a/media/media.gyp b/media/media.gyp index b7560c1..846297d 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -15,8 +15,9 @@ 'yuv_convert', '../base/base.gyp:base', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', - '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', '../build/temp_gyp/googleurl.gyp:googleurl', + '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', + '../third_party/openmax/openmax.gyp:il', ], 'include_dirs': [ '..', @@ -224,15 +225,6 @@ ], }], ['os_posix == 1 and OS != "mac"', { - 'sources': [ - 'filters/omx_video_decoder.cc', - 'filters/omx_video_decoder.h', - ], - 'dependencies': [ - 'omx_wrapper', - ] - }], - ['os_posix == 1 and OS != "mac"', { 'sources!': [ 'video/capture/video_capture_device_dummy.cc', 'video/capture/video_capture_device_dummy.h', @@ -376,10 +368,6 @@ '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', - '../third_party/openmax/openmax.gyp:il', - ], - 'sources!': [ - '../third_party/openmax/omx_stub.cc', ], 'sources': [ 'audio/audio_input_controller_unittest.cc', @@ -425,31 +413,8 @@ 'filters/file_data_source_unittest.cc', 'filters/rtc_video_decoder_unittest.cc', 'filters/video_renderer_base_unittest.cc', - 'omx/mock_omx.cc', - 'omx/mock_omx.h', 'video/ffmpeg_video_decode_engine_unittest.cc', ], - 'conditions': [ - ['toolkit_uses_gtk == 1', { - 'dependencies': [ - # Needed for the following #include chain: - # base/run_all_unittests.cc - # ../base/test_suite.h - # gtk/gtk.h - '../build/linux/system.gyp:gtk', - ], - 'sources': [ - 'omx/omx_codec_unittest.cc', - ], - 'conditions': [ - ['linux_use_tcmalloc==1', { - 'dependencies': [ - '../base/allocator/allocator.gyp:allocator', - ], - }], - ], - }], - ], }, { 'target_name': 'media_test_support', @@ -676,67 +641,6 @@ ['os_posix == 1 and OS != "mac"', { 'targets': [ { - 'target_name': 'omx_test', - 'type': 'executable', - 'dependencies': [ - 'media', - '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', - '../third_party/openmax/openmax.gyp:il', - ], - 'sources': [ - 'tools/omx_test/color_space_util.cc', - 'tools/omx_test/color_space_util.h', - 'tools/omx_test/file_reader_util.cc', - 'tools/omx_test/file_reader_util.h', - 'tools/omx_test/file_sink.cc', - 'tools/omx_test/file_sink.h', - 'tools/omx_test/omx_test.cc', - ], - }, - { - 'target_name': 'omx_unittests', - 'type': 'executable', - 'dependencies': [ - 'media', - 'omx_wrapper', - '../base/base.gyp:base', - '../base/base.gyp:base_i18n', - '../base/base.gyp:test_support_base', - '../testing/gtest.gyp:gtest', - ], - 'conditions': [ - ['toolkit_uses_gtk == 1', { - 'dependencies': [ - '../build/linux/system.gyp:gtk', - ], - }], - ], - 'sources': [ - 'omx/omx_unittest.cc', - 'omx/run_all_unittests.cc', - ], - }, - { - 'target_name': 'omx_wrapper', - 'type': 'static_library', - 'dependencies': [ - '../base/base.gyp:base', - '../third_party/openmax/openmax.gyp:il', - # TODO(wjia): remove ffmpeg - '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', - ], - 'sources': [ - 'omx/omx_configurator.cc', - 'omx/omx_configurator.h', - 'video/omx_video_decode_engine.cc', - 'video/omx_video_decode_engine.cc', - ], - 'hard_dependency': 1, - 'export_dependent_settings': [ - '../third_party/openmax/openmax.gyp:il', - ], - }, - { 'target_name': 'player_x11', 'type': 'executable', 'dependencies': [ diff --git a/media/omx/mock_omx.cc b/media/omx/mock_omx.cc deleted file mode 100644 index 79d8dc2..0000000 --- a/media/omx/mock_omx.cc +++ /dev/null @@ -1,159 +0,0 @@ -// 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/mock_omx.h" - -#include "base/logging.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { - -MockOmx* MockOmx::instance_ = NULL; - -// Static stub methods. They redirect method calls back to the mock object. -static OMX_ERRORTYPE MockSendCommand(OMX_HANDLETYPE component, - OMX_COMMANDTYPE command, - OMX_U32 param1, - OMX_PTR command_data) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->SendCommand(command, param1, command_data); -} - -static OMX_ERRORTYPE MockGetParameter(OMX_HANDLETYPE component, - OMX_INDEXTYPE param_index, - OMX_PTR structure) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->GetParameter(param_index, structure); -} - -static OMX_ERRORTYPE MockSetParameter(OMX_HANDLETYPE component, - OMX_INDEXTYPE param_index, - OMX_PTR structure) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->SetParameter(param_index, structure); -} - -static OMX_ERRORTYPE MockGetConfig(OMX_HANDLETYPE component, - OMX_INDEXTYPE index, - OMX_PTR structure) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->GetConfig(index, structure); -} - -static OMX_ERRORTYPE MockSetConfig(OMX_HANDLETYPE component, - OMX_INDEXTYPE index, - OMX_PTR structure) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->SetConfig(index, structure); -} - -static OMX_ERRORTYPE MockAllocateBuffer(OMX_HANDLETYPE component, - OMX_BUFFERHEADERTYPE** buffer, - OMX_U32 port_index, - OMX_PTR app_private, - OMX_U32 size_bytes) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->AllocateBuffer(buffer, port_index, app_private, - size_bytes); -} - -static OMX_ERRORTYPE MockUseBuffer(OMX_HANDLETYPE component, - OMX_BUFFERHEADERTYPE** buffer, - OMX_U32 port_index, - OMX_PTR app_private, - OMX_U32 size_bytes, - OMX_U8* pBuffer) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->UseBuffer(buffer, port_index, app_private, - size_bytes, pBuffer); -} - -static OMX_ERRORTYPE MockFreeBuffer(OMX_HANDLETYPE component, - OMX_U32 port_index, - OMX_BUFFERHEADERTYPE* buffer) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->FreeBuffer(port_index, buffer); -} - -static OMX_ERRORTYPE MockEmptyThisBuffer(OMX_HANDLETYPE component, - OMX_BUFFERHEADERTYPE* buffer) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->EmptyThisBuffer(buffer); -} - -static OMX_ERRORTYPE MockFillThisBuffer(OMX_HANDLETYPE component, - OMX_BUFFERHEADERTYPE* buffer) { - CHECK(MockOmx::get()->component() == - reinterpret_cast<OMX_COMPONENTTYPE*>(component)); - return MockOmx::get()->FillThisBuffer(buffer); -} - -// Stub methods to export symbols used for OpenMAX. -extern "C" { -OMX_ERRORTYPE OMX_Init() { - return MockOmx::get()->Init(); -} - -OMX_ERRORTYPE OMX_Deinit() { - return MockOmx::get()->Deinit(); -} - -OMX_ERRORTYPE OMX_GetHandle( - OMX_HANDLETYPE* handle, OMX_STRING name, OMX_PTR app_private, - OMX_CALLBACKTYPE* callbacks) { - return MockOmx::get()->GetHandle(handle, name, app_private, callbacks); -} - -OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE handle) { - return MockOmx::get()->FreeHandle(handle); -} - -OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_STRING name, OMX_U32* roles, - OMX_U8** component_names) { - return MockOmx::get()->GetComponentsOfRole(name, roles, component_names); -} -} // extern "C" - -MockOmx::MockOmx() { - memset(&callbacks_, 0, sizeof(callbacks_)); - memset(&component_, 0, sizeof(component_)); - - // Setup the function pointers to the static methods. They will redirect back - // to this mock object. - component_.SendCommand = &MockSendCommand; - component_.GetParameter = &MockGetParameter; - component_.SetParameter = &MockSetParameter; - component_.GetConfig = &MockGetConfig; - component_.SetConfig = &MockSetConfig; - component_.AllocateBuffer = &MockAllocateBuffer; - component_.UseBuffer = &MockUseBuffer; - component_.FreeBuffer = &MockFreeBuffer; - component_.EmptyThisBuffer = &MockEmptyThisBuffer; - component_.FillThisBuffer = &MockFillThisBuffer; - - // Save this instance to static member. - CHECK(!instance_); - instance_ = this; -} - -MockOmx::~MockOmx() { - CHECK(instance_); - instance_ = NULL; -} - -// static -MockOmx* MockOmx::get() { - return instance_; -} - -} // namespace media diff --git a/media/omx/mock_omx.h b/media/omx/mock_omx.h deleted file mode 100644 index af328fd..0000000 --- a/media/omx/mock_omx.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2011 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_MOCK_OMX_H_ -#define MEDIA_OMX_MOCK_OMX_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/openmax/il/OMX_Component.h" -#include "third_party/openmax/il/OMX_Core.h" - -namespace media { - -class MockOmx { - public: - MockOmx(); - virtual ~MockOmx(); - - // The following mock methods are component specific. - MOCK_METHOD3(SendCommand, OMX_ERRORTYPE( - OMX_COMMANDTYPE command, - OMX_U32 param1, - OMX_PTR command_data)); - - MOCK_METHOD2(GetParameter, OMX_ERRORTYPE( - OMX_INDEXTYPE param_index, - OMX_PTR structure)); - - MOCK_METHOD2(SetParameter, OMX_ERRORTYPE( - OMX_INDEXTYPE param_index, - OMX_PTR structure)); - - MOCK_METHOD2(GetConfig, OMX_ERRORTYPE( - OMX_INDEXTYPE index, - OMX_PTR structure)); - - MOCK_METHOD2(SetConfig, OMX_ERRORTYPE( - OMX_INDEXTYPE index, - OMX_PTR structure)); - - MOCK_METHOD4(AllocateBuffer, OMX_ERRORTYPE( - OMX_BUFFERHEADERTYPE** buffer, - OMX_U32 port_index, - OMX_PTR app_private, - OMX_U32 size_bytes)); - - MOCK_METHOD5(UseBuffer, OMX_ERRORTYPE( - OMX_BUFFERHEADERTYPE** buffer, - OMX_U32 port_index, - OMX_PTR app_private, - OMX_U32 size_bytes, - OMX_U8* pBuffer)); - - MOCK_METHOD2(FreeBuffer, OMX_ERRORTYPE( - OMX_U32 port_index, - OMX_BUFFERHEADERTYPE* buffer)); - - MOCK_METHOD1(EmptyThisBuffer, OMX_ERRORTYPE( - OMX_BUFFERHEADERTYPE* buffer)); - - MOCK_METHOD1(FillThisBuffer, OMX_ERRORTYPE( - OMX_BUFFERHEADERTYPE* buffer)); - - // The following mock methods are defined global. - MOCK_METHOD0(Init, OMX_ERRORTYPE()); - MOCK_METHOD0(Deinit, OMX_ERRORTYPE()); - - MOCK_METHOD4(GetHandle, OMX_ERRORTYPE( - OMX_HANDLETYPE* handle, - OMX_STRING name, - OMX_PTR app_private, - OMX_CALLBACKTYPE* callbacks)); - - MOCK_METHOD1(FreeHandle, OMX_ERRORTYPE( - OMX_HANDLETYPE handle)); - - MOCK_METHOD3(GetComponentsOfRole, OMX_ERRORTYPE( - OMX_STRING name, - OMX_U32* roles, - OMX_U8** component_names)); - - OMX_CALLBACKTYPE* callbacks() { return &callbacks_; } - OMX_COMPONENTTYPE* component() { return &component_; } - - // Getter for the global instance of MockOmx. - static MockOmx* get(); - - private: - static MockOmx* instance_; - - OMX_CALLBACKTYPE callbacks_; - OMX_COMPONENTTYPE component_; - - DISALLOW_COPY_AND_ASSIGN(MockOmx); -}; - -} // namespace media - -#endif // MEDIA_OMX_MOCK_OMX_H_ diff --git a/media/omx/omx_codec_unittest.cc b/media/omx/omx_codec_unittest.cc deleted file mode 100644 index 06fa31e..0000000 --- a/media/omx/omx_codec_unittest.cc +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright (c) 2011 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. - -#define _CRT_SECURE_NO_WARNINGS - -#if 0 -#include <deque> - -#include "base/callback.h" -#include "base/message_loop.h" -#include "base/task.h" -#include "media/base/buffers.h" -#include "media/base/mock_filters.h" -#include "media/base/mock_task.h" -#include "media/ffmpeg/ffmpeg_common.h" -#include "media/video/omx_video_decode_engine.h" -#include "media/video/video_decode_engine.h" -#include "media/omx/mock_omx.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; -using ::testing::DoAll; -using ::testing::InSequence; -using ::testing::IsNull; -using ::testing::NotNull; -using ::testing::Return; -using ::testing::SaveArg; -using ::testing::SetArgumentPointee; -using ::testing::StrEq; -using ::testing::StrictMock; - -namespace media { - -static const int kBufferCount = 3; -static const int kBufferSize = 4096; -static const char* kComponentName = "OMX.google.video_decoder.avc"; - -ACTION(ReturnComponentName) { - strcpy(((char**)arg2)[0], kComponentName); -} - -ACTION(GetHandle) { - *arg0 = MockOmx::get()->component(); - MockOmx::get()->component()->pApplicationPrivate = arg2; - memcpy(MockOmx::get()->callbacks(), arg3, sizeof(OMX_CALLBACKTYPE)); -} - -ACTION(GetParameterVideoInit) { - ((OMX_PORT_PARAM_TYPE*)arg1)->nStartPortNumber = 0; -} - -ACTION(GetParameterPortDefinition) { - OMX_PARAM_PORTDEFINITIONTYPE* port_format = - (OMX_PARAM_PORTDEFINITIONTYPE*)arg1; - CHECK(port_format->nPortIndex == 0 || port_format->nPortIndex == 1); - if (port_format->nPortIndex == 0) - port_format->eDir = OMX_DirInput; - else - port_format->eDir = OMX_DirOutput; - port_format->nBufferCountMin = kBufferCount; - port_format->nBufferCountActual = kBufferCount; - port_format->nBufferSize = kBufferSize; -} - -ACTION(AllocateBuffer) { - *arg0 = new OMX_BUFFERHEADERTYPE(); - memset(*arg0, 0, sizeof(OMX_BUFFERHEADERTYPE)); - (*arg0)->nAllocLen = arg3; - (*arg0)->pBuffer = new uint8[arg3]; - (*arg0)->nOutputPortIndex = 1; - (*arg0)->nInputPortIndex = OMX_ALL; -} - -ACTION(UseBuffer) { - *arg0 = new OMX_BUFFERHEADERTYPE(); - memset(*arg0, 0, sizeof(OMX_BUFFERHEADERTYPE)); - (*arg0)->nOutputPortIndex = OMX_ALL; - (*arg0)->nInputPortIndex = 0; -} - -ACTION(FreeBuffer) { - if (1 == arg1->nOutputPortIndex) - delete [] arg1->pBuffer; - delete arg1; -} - -ACTION_P3(SendEvent, event, data1, data2) { - (*MockOmx::get()->callbacks()->EventHandler)( - MockOmx::get()->component(), - MockOmx::get()->component()->pApplicationPrivate, - event, static_cast<OMX_U32>(data1), static_cast<OMX_U32>(data2), NULL); -} - -ACTION_P(EmptyBufferDone, output_pool_ptr) { - (*MockOmx::get()->callbacks()->EmptyBufferDone)( - MockOmx::get()->component(), - MockOmx::get()->component()->pApplicationPrivate, - arg0); - OMX_BUFFERHEADERTYPE* out_buffer = output_pool_ptr->front(); - output_pool_ptr->pop_front(); - if (arg0->nFlags & OMX_BUFFERFLAG_EOS) - out_buffer->nFlags |= OMX_BUFFERFLAG_EOS; - out_buffer->nFilledLen = kBufferSize; - (*MockOmx::get()->callbacks()->FillBufferDone)( - MockOmx::get()->component(), - MockOmx::get()->component()->pApplicationPrivate, - out_buffer); -} - -ACTION_P(EnqueueOutputBuffer, output_pool_ptr) { - output_pool_ptr->push_back(arg0); -} - -ACTION(FillEosBuffer) { - arg0->nFlags = OMX_BUFFERFLAG_EOS; - arg0->nFilledLen = 0; - (*MockOmx::get()->callbacks()->FillBufferDone)( - MockOmx::get()->component(), - MockOmx::get()->component()->pApplicationPrivate, - arg0); -} - -class TestBuffer : public media::Buffer { - public: - TestBuffer() : size_(0), data_(NULL) { } - explicit TestBuffer(int size) : size_(size) { - if (size) - data_.reset(new uint8[size]); - else - data_.reset(NULL); - } - virtual const uint8* GetData() const { - return data_.get(); - } - virtual size_t GetDataSize() const { - return size_; - } - private: - virtual ~TestBuffer() { } - - int size_; - scoped_array<uint8> data_; - DISALLOW_COPY_AND_ASSIGN(TestBuffer); -}; - -class OmxCodecTest : public testing::Test { - public: - OmxCodecTest () - : input_buffer_count_(0), - got_eos_(false), - omx_engine_(new OmxVideoDecodeEngine()) { - av_stream_.codec = &av_codec_context_; - av_codec_context_.width = 16; - av_codec_context_.height = 16; - feed_done_cb_ = - NewCallback(this, &OmxCodecTest::EmptyBufferDoneCallback); - decode_done_cb_ = - NewCallback(this, &OmxCodecTest::FillBufferDoneCallback); - } - - ~OmxCodecTest() { - } - - protected: - void ExpectSettings() { - // Return the component name. - EXPECT_CALL(*MockOmx::get(), GetComponentsOfRole(_, _, IsNull())) - .WillOnce(DoAll(SetArgumentPointee<1>(1), - Return(OMX_ErrorNone))); - EXPECT_CALL(*MockOmx::get(), GetComponentsOfRole(_, _, NotNull())) - .WillOnce(DoAll(SetArgumentPointee<1>(1), - ReturnComponentName(), - Return(OMX_ErrorNone))); - - // Handle get parameter calls. - EXPECT_CALL(*MockOmx::get(), - GetParameter(OMX_IndexParamVideoInit, NotNull())) - .WillRepeatedly(DoAll(GetParameterVideoInit(), Return(OMX_ErrorNone))); - EXPECT_CALL(*MockOmx::get(), - GetParameter(OMX_IndexParamPortDefinition, NotNull())) - .WillRepeatedly(DoAll(GetParameterPortDefinition(), - Return(OMX_ErrorNone))); - - // Ignore all set parameter calls. - EXPECT_CALL(*MockOmx::get(), SetParameter(_, _)) - .WillRepeatedly(Return(OMX_ErrorNone)); - } - - void ExpectToLoaded() { - InSequence s; - - // Expect initialization. - EXPECT_CALL(*MockOmx::get(), Init()) - .WillOnce(Return(OMX_ErrorNone)); - - // Return the handle. - EXPECT_CALL(*MockOmx::get(), - GetHandle(NotNull(), StrEq(kComponentName), - NotNull(), NotNull())) - .WillOnce(DoAll(GetHandle(), - Return(OMX_ErrorNone))); - } - - void ExpectLoadedToIdle() { - InSequence s; - - // Expect transition to idle. - EXPECT_CALL(*MockOmx::get(), - SendCommand(OMX_CommandStateSet, OMX_StateIdle, _)) - .WillOnce( - DoAll( - SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, - OMX_StateIdle), - Return(OMX_ErrorNone))); - - // Expect allocation of buffers. - EXPECT_CALL(*MockOmx::get(), - UseBuffer(NotNull(), 0, NotNull(), kBufferSize, _)) - .Times(kBufferCount) - .WillRepeatedly(DoAll(UseBuffer(), Return(OMX_ErrorNone))); - - // Expect allocation of output buffers and send command complete. - EXPECT_CALL(*MockOmx::get(), - AllocateBuffer(NotNull(), 1, IsNull(), kBufferSize)) - .Times(kBufferCount) - .WillRepeatedly(DoAll(AllocateBuffer(), Return(OMX_ErrorNone))); - } - - void ExpectToExecuting() { - InSequence s; - - // Expect transition to executing. - EXPECT_CALL(*MockOmx::get(), - SendCommand(OMX_CommandStateSet, OMX_StateExecuting, _)) - .WillOnce(DoAll( - SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, - OMX_StateExecuting), - Return(OMX_ErrorNone))); - - // Expect initial FillThisBuffer() calls. - EXPECT_CALL(*MockOmx::get(), FillThisBuffer(NotNull())) - .Times(kBufferCount) - .WillRepeatedly(DoAll(EnqueueOutputBuffer(&output_pool_), - Return(OMX_ErrorNone))); - } - - void ExpectToIdle() { - // Expect going to idle - EXPECT_CALL(*MockOmx::get(), - SendCommand(OMX_CommandStateSet, OMX_StateIdle, _)) - .WillOnce(DoAll( - SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateIdle), - Return(OMX_ErrorNone))); - } - - void ExpectIdleToLoaded() { - InSequence s; - - // Expect transition to loaded. - EXPECT_CALL(*MockOmx::get(), - SendCommand(OMX_CommandStateSet, OMX_StateLoaded, _)) - .WillOnce(DoAll( - SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, - OMX_StateLoaded), - Return(OMX_ErrorNone))); - - // Expect free buffer for input port. - EXPECT_CALL(*MockOmx::get(), FreeBuffer(0, NotNull())) - .Times(kBufferCount) - .WillRepeatedly(DoAll(FreeBuffer(), Return(OMX_ErrorNone))); - - EXPECT_CALL(*MockOmx::get(), FreeBuffer(1, NotNull())) - .Times(kBufferCount) - .WillRepeatedly(DoAll(FreeBuffer(), Return(OMX_ErrorNone))); - } - - void ExpectToEmpty() { - InSequence s; - - EXPECT_CALL(*MockOmx::get(), FreeHandle(MockOmx::get()->component())) - .WillOnce(Return(OMX_ErrorNone)); - EXPECT_CALL(*MockOmx::get(), Deinit()) - .WillOnce(Return(OMX_ErrorNone)); - } - - // TODO(hclam): Make a more generic about when to stop. - void ExpectStart() { - ExpectToLoaded(); - ExpectLoadedToIdle(); - ExpectToExecuting(); - EXPECT_CALL(init_done_cb_task_, Run()); - } - - void ExpectStop() { - EXPECT_CALL(stop_task_, Run()); - ExpectToIdle(); - ExpectIdleToLoaded(); - ExpectToEmpty(); - } - - void EmptyBufferDoneCallback(scoped_refptr<Buffer> buffer) { - if (buffer.get()) { - input_units_.push_back(buffer); - } else { - input_buffer_count_++; - scoped_refptr<Buffer> buffer_ref = new TestBuffer(input_buffer_count_); - input_units_.push_back(buffer_ref); - } - } - - void FillBufferDoneCallback(scoped_refptr<VideoFrame> frame) { - output_units_.push_back(frame); - if (frame->IsEndOfStream()) - got_eos_ = true; - } - - void MakeEmptyBufferRequest() { - scoped_refptr<Buffer> buffer = input_units_.front(); - input_units_.pop_front(); - omx_engine_->EmptyThisBuffer(buffer); - } - - void SendEOSInputBuffer() { - input_units_.pop_front(); - scoped_refptr<Buffer> buffer_ref = new TestBuffer(); - input_units_.push_front(buffer_ref); - EXPECT_CALL(*MockOmx::get(), EmptyThisBuffer(NotNull())) - .WillOnce(DoAll(EmptyBufferDone(&output_pool_), Return(OMX_ErrorNone))) - .RetiresOnSaturation(); - MakeEmptyBufferRequest(); - message_loop_.RunAllPending(); - } - - int input_buffer_count_; - - std::deque<scoped_refptr<Buffer> > input_units_; - std::deque<scoped_refptr<VideoFrame> > output_units_; - std::deque<OMX_BUFFERHEADERTYPE*> fill_this_buffer_received_; - std::deque<OMX_BUFFERHEADERTYPE*> output_pool_; - - MockOmx mock_omx_; - - bool got_eos_; - MessageLoop message_loop_; - scoped_refptr<OmxVideoDecodeEngine> omx_engine_; - - AVStream av_stream_; - AVCodecContext av_codec_context_; - - VideoDecodeEngine::ProduceVideoSampleCallback* feed_done_cb_; - VideoDecodeEngine::ConsumeVideoFrameCallback* decode_done_cb_; - TaskMocker init_done_cb_task_; - - TaskMocker stop_task_; - - private: - DISALLOW_COPY_AND_ASSIGN(OmxCodecTest); -}; - -TEST_F(OmxCodecTest, SimpleStartAndStop) { - ExpectSettings(); - ExpectStart(); - omx_engine_->Initialize(&message_loop_, - &av_stream_, - feed_done_cb_, - decode_done_cb_, - init_done_cb_task_.CreateTask()); - message_loop_.RunAllPending(); - - EXPECT_EQ(kBufferCount, input_buffer_count_); - EXPECT_EQ(VideoDecodeEngine::kNormal, omx_engine_->state()); - - ExpectStop(); - omx_engine_->Stop(stop_task_.CreateTask()); - message_loop_.RunAllPending(); -} - -TEST_F(OmxCodecTest, NormalFlow) { - ExpectSettings(); - ExpectStart(); - omx_engine_->Initialize(&message_loop_, - &av_stream_, - feed_done_cb_, - decode_done_cb_, - init_done_cb_task_.CreateTask()); - message_loop_.RunAllPending(); - - EXPECT_EQ(kBufferCount, input_buffer_count_); - EXPECT_EQ(VideoDecodeEngine::kNormal, omx_engine_->state()); - - // Make emptybuffer requests. - EXPECT_EQ(0u, output_units_.size()); - int count = output_pool_.size(); - for (int i = 0; i < kBufferCount; ++i) { - // Give input buffers to OmxVideoDecodeEngine. OmxVideoDecodeEngine will - // make a new FillThisBuffer() call for each read. - EXPECT_CALL(*MockOmx::get(), EmptyThisBuffer(NotNull())) - .WillOnce(DoAll(EmptyBufferDone(&output_pool_), Return(OMX_ErrorNone))) - .RetiresOnSaturation(); - EXPECT_CALL(*MockOmx::get(), FillThisBuffer(NotNull())) - .WillOnce(DoAll(EnqueueOutputBuffer(&output_pool_), - Return(OMX_ErrorNone))) - .RetiresOnSaturation(); - MakeEmptyBufferRequest(); - } - message_loop_.RunAllPending(); - EXPECT_EQ(kBufferCount, static_cast<int>(input_units_.size())); - EXPECT_EQ(kBufferCount, static_cast<int>(output_units_.size())); - EXPECT_EQ(count, static_cast<int>(output_pool_.size())); - output_units_.clear(); - - // Send EndOfStream, expect eos flag. - SendEOSInputBuffer(); - EXPECT_EQ(kBufferCount - 1, static_cast<int>(input_units_.size())); - EXPECT_EQ(1, static_cast<int>(output_units_.size())); - EXPECT_EQ(count - 1, static_cast<int>(output_pool_.size())); - EXPECT_TRUE(got_eos_); - - // Shutdown. - ExpectStop(); - omx_engine_->Stop(stop_task_.CreateTask()); - message_loop_.RunAllPending(); -} - -TEST_F(OmxCodecTest, RecycleInputBuffers) { - ExpectSettings(); - ExpectStart(); - omx_engine_->Initialize(&message_loop_, - &av_stream_, - feed_done_cb_, - decode_done_cb_, - init_done_cb_task_.CreateTask()); - message_loop_.RunAllPending(); - - EXPECT_EQ(kBufferCount, input_buffer_count_); - EXPECT_EQ(VideoDecodeEngine::kNormal, omx_engine_->state()); - - // Make emptybuffer requests, also recycle input buffers - EXPECT_EQ(0u, output_units_.size()); - int count = output_pool_.size(); - int repeat_count = kBufferCount * 2; - for (int i = 0; i < repeat_count; ++i) { - // Give input buffers to OmxVideoDecodeEngine. OmxVideoDecodeEngine will - // make a new FillThisBuffer() call for each read. - EXPECT_CALL(*MockOmx::get(), EmptyThisBuffer(NotNull())) - .WillOnce(DoAll(EmptyBufferDone(&output_pool_), Return(OMX_ErrorNone))) - .RetiresOnSaturation(); - EXPECT_CALL(*MockOmx::get(), FillThisBuffer(NotNull())) - .WillOnce(DoAll(EnqueueOutputBuffer(&output_pool_), - Return(OMX_ErrorNone))) - .RetiresOnSaturation(); - MakeEmptyBufferRequest(); - message_loop_.RunAllPending(); - CHECK(kBufferCount == static_cast<int>(input_units_.size())); - CHECK(((i % kBufferCount) + 1) == - static_cast<int>(input_units_.back()->GetDataSize())); - } - message_loop_.RunAllPending(); - EXPECT_EQ(kBufferCount, static_cast<int>(input_units_.size())); - EXPECT_EQ(repeat_count, static_cast<int>(output_units_.size())); - EXPECT_EQ(count, static_cast<int>(output_pool_.size())); - output_units_.clear(); - - // Send EndOfStream, expect eos flag. - SendEOSInputBuffer(); - EXPECT_EQ(kBufferCount - 1, static_cast<int>(input_units_.size())); - EXPECT_EQ(1, static_cast<int>(output_units_.size())); - EXPECT_EQ(count - 1, static_cast<int>(output_pool_.size())); - EXPECT_TRUE(got_eos_); - - // Shutdown. - ExpectStop(); - omx_engine_->Stop(stop_task_.CreateTask()); - message_loop_.RunAllPending(); -} - -// TODO(hclam): Add test case for dynamic port config. -// TODO(hclam): Create a more complicated test case so that read -// requests and reply from FillThisBuffer() arrives out of order. - -} // namespace media -#endif diff --git a/media/omx/omx_configurator.cc b/media/omx/omx_configurator.cc deleted file mode 100644 index 821cd2d..0000000 --- a/media/omx/omx_configurator.cc +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2011 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 media { - -static std::string GetCodecName(OmxConfigurator::Codec codec) { - switch (codec) { - case OmxConfigurator::kCodecH264: - return "avc"; - case OmxConfigurator::kCodecH263: - return "h263"; - case OmxConfigurator::kCodecMpeg4: - return "mpeg4"; - case OmxConfigurator::kCodecVc1: - return "vc1"; - default: - break; - } - NOTREACHED(); - return ""; -} - -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 deleted file mode 100644 index 6d50b33..0000000 --- a/media/omx/omx_configurator.h +++ /dev/null @@ -1,154 +0,0 @@ -// 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_ diff --git a/media/omx/omx_unittest.cc b/media/omx/omx_unittest.cc deleted file mode 100644 index a60e21a..0000000 --- a/media/omx/omx_unittest.cc +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright (c) 2011 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 "base/command_line.h" -#include "base/logging.h" -#include "base/synchronization/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 { - -// Defines the maximum number of buffers created for I/O ports. -static const int kMaxBufferNum = 256; - -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); -} - -class OmxTest : public testing::Test { - public: - OmxTest() - : handle_(NULL), - event_(false, false), - empty_buffer_(false, false), - fill_buffer_(false, false), - last_event_type_(OMX_EventMax), - last_event_data1_(0), - last_event_data2_(0) { - 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) { - // TODO(hclam): Remove static when bug in driver is fixed. - static 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) { - 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 TransitionLoadedToIdle() { - EXPECT_EQ(OMX_ErrorNone, - OMX_SendCommand(handle_, OMX_CommandStateSet, - OMX_StateIdle, 0)); - AllocateBuffers(input_port_); - AllocateBuffers(output_port_); - event_.Wait(); - EXPECT_EQ(OMX_EventCmdComplete, last_event_type_); - EXPECT_EQ(OMX_CommandStateSet, last_event_data1_); - EXPECT_EQ(OMX_StateIdle, last_event_data2_); - } - - void TransitionIdleToLoaded() { - EXPECT_EQ(OMX_ErrorNone, - OMX_SendCommand(handle_, OMX_CommandStateSet, - OMX_StateLoaded, 0)); - ReleaseBuffers(input_port_); - ReleaseBuffers(output_port_); - event_.Wait(); - EXPECT_EQ(OMX_EventCmdComplete, last_event_type_); - EXPECT_EQ(OMX_CommandStateSet, last_event_data1_); - EXPECT_EQ(OMX_StateLoaded, last_event_data2_); - } - - void TransitionIdleToExecuting() { - EXPECT_EQ(OMX_ErrorNone, - OMX_SendCommand(handle_, OMX_CommandStateSet, - OMX_StateExecuting, 0)); - event_.Wait(); - EXPECT_EQ(OMX_EventCmdComplete, last_event_type_); - EXPECT_EQ(OMX_CommandStateSet, last_event_data1_); - EXPECT_EQ(OMX_StateExecuting, last_event_data2_); - } - - void TransitionExecutingToIdle() { - EXPECT_EQ(OMX_ErrorNone, - OMX_SendCommand(handle_, OMX_CommandStateSet, - OMX_StateIdle, 0)); - event_.Wait(); - EXPECT_EQ(OMX_EventCmdComplete, last_event_type_); - EXPECT_EQ(OMX_CommandStateSet, last_event_data1_); - EXPECT_EQ(OMX_StateIdle, last_event_data2_); - } - - 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) { - last_event_type_ = event; - last_event_data1_ = static_cast<int>(data1); - last_event_data2_ = static_cast<int>(data2); - // TODO(hclam): Save |event_data|. - event_.Signal(); - return OMX_ErrorNone; - } - - OMX_ERRORTYPE EmptyBufferCallbackInternal( - OMX_HANDLETYPE component, OMX_BUFFERHEADERTYPE* buffer) { - // TODO(hclam): Add code here. - empty_buffer_.Signal(); - return OMX_ErrorNone; - } - - OMX_ERRORTYPE FillBufferCallbackInternal( - OMX_HANDLETYPE component, OMX_BUFFERHEADERTYPE* buffer) { - // TODO(hclam): Add code here. - 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]; - - base::WaitableEvent event_; - base::WaitableEvent empty_buffer_; - base::WaitableEvent fill_buffer_; - - OMX_EVENTTYPE last_event_type_; - int last_event_data1_; - int last_event_data2_; -}; - -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): Add configurations to output port. - - // 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); - - // Get parameters for output port. - ResetHeader(&port_format); - port_format.nPortIndex = output_port_; - EXPECT_EQ(OMX_ErrorNone, - 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"); - } - - OMX_VIDEO_CODINGTYPE codec() { - std::string codec = CommandLine::ForCurrentProcess() - ->GetSwitchValueASCII("video-decoder-codec"); - if (codec == "h264") - return OMX_VIDEO_CodingAVC; - return OMX_VIDEO_CodingAutoDetect; - } -}; - -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); - TransitionLoadedToIdle(); - TransitionIdleToLoaded(); - DeinitComponent(); -} - -TEST_F(OmxVideoDecoderTest, FreeHandleWhenIdle) { - InitComponent(component()); - Configure(codec(), 1024, 768); - TransitionLoadedToIdle(); - DeinitComponent(); -} - -TEST_F(OmxVideoDecoderTest, TransitionToExecuting) { - InitComponent(component()); - Configure(codec(), 1024, 768); - TransitionLoadedToIdle(); - TransitionIdleToExecuting(); - TransitionExecutingToIdle(); - TransitionIdleToLoaded(); - DeinitComponent(); -} - -TEST_F(OmxVideoDecoderTest, FreeHandleWhenExecuting) { - InitComponent(component()); - Configure(codec(), 1024, 768); - TransitionLoadedToIdle(); - TransitionIdleToExecuting(); - DeinitComponent(); -} - -TEST_F(OmxVideoDecoderTest, CallbacksAreCopied) { - // Allocate a callback struct on stack and clear it with zero. - // This make sure OpenMAX library will copy the content of the - // struct. - OMX_CALLBACKTYPE callback = { &EventHandler, - &EmptyBufferCallback, - &FillBufferCallback }; - - OMX_ERRORTYPE omxresult = OMX_GetHandle( - (void**)&handle_, - const_cast<OMX_STRING>(component().c_str()), - this, &callback); - EXPECT_EQ(OMX_ErrorNone, omxresult); - CHECK(handle_); - memset(&callback, 0, sizeof(callback)); - - // Then configure the component as usual. - Configure(codec(), 1024, 768); - TransitionLoadedToIdle(); - TransitionIdleToExecuting(); - TransitionExecutingToIdle(); - TransitionIdleToLoaded(); - DeinitComponent(); -} - -} // namespace media diff --git a/media/omx/run_all_unittests.cc b/media/omx/run_all_unittests.cc deleted file mode 100644 index b28ef94..0000000 --- a/media/omx/run_all_unittests.cc +++ /dev/null @@ -1,17 +0,0 @@ -// 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 "base/file_path.h" -#include "base/logging.h" -#include "base/test/test_suite.h" -#include "media/base/media.h" - -int main(int argc, char** argv) { - // Load the OpenMAX library. - if (!media::InitializeOpenMaxLibrary(FilePath())) { - LOG(ERROR) << "Unable to initialize OpenMAX library."; - return -1; - } - return base::TestSuite(argc, argv).Run(); -} diff --git a/media/tools/omx_test/color_space_util.cc b/media/tools/omx_test/color_space_util.cc deleted file mode 100644 index 87a7bba..0000000 --- a/media/tools/omx_test/color_space_util.cc +++ /dev/null @@ -1,61 +0,0 @@ -// 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/tools/omx_test/color_space_util.h" - -namespace media { - -void NV21toIYUV(const uint8* nv21, uint8* iyuv, int width, int height) { - memcpy(iyuv, nv21, width * height); - iyuv += width * height; - nv21 += width * height; - uint8* u = iyuv; - uint8* v = iyuv + width * height / 4; - - for (int i = 0; i < width * height / 4; ++i) { - *v++ = *nv21++; - *u++ = *nv21++; - } -} - -void NV21toYV12(const uint8* nv21, uint8* yv12, int width, int height) { - memcpy(yv12, nv21, width * height); - 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 IYUVtoNV21(const uint8* iyuv, uint8* nv21, int width, int height) { - memcpy(nv21, iyuv, width * height); - iyuv += width * height; - nv21 += width * height; - const uint8* u = iyuv; - const uint8* v = iyuv + width * height / 4; - - for (int i = 0; i < width * height / 4; ++i) { - *nv21++ = *v++; - *nv21++ = *u++; - } -} - -void YV12toNV21(const uint8* yv12, uint8* nv21, int width, int height) { - memcpy(nv21, yv12, width * height); - yv12 += width * height; - nv21 += width * height; - const uint8* v = yv12; - const uint8* u = yv12 + width * height / 4; - - for (int i = 0; i < width * height / 4; ++i) { - *nv21++ = *v++; - *nv21++ = *u++; - } -} - -} // namespace media diff --git a/media/tools/omx_test/color_space_util.h b/media/tools/omx_test/color_space_util.h deleted file mode 100644 index 1969485d..0000000 --- a/media/tools/omx_test/color_space_util.h +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -// Color space conversion methods, they are for testing purpose and are -// not optimized for production use. - -#ifndef MEDIA_TOOLS_OMX_TEST_COLOR_SPACE_UTIL_H_ -#define MEDIA_TOOLS_OMX_TEST_COLOR_SPACE_UTIL_H_ - -#include "base/basictypes.h" - -namespace media { - -// First parameter is the input buffer, second parameter is the output -// buffer. -void NV21toIYUV(const uint8* nv21, uint8* iyuv, int width, int height); -void NV21toYV12(const uint8* nv21, uint8* yv12, int width, int height); -void IYUVtoNV21(const uint8* iyuv, uint8* nv21, int width, int height); -void YV12toNV21(const uint8* yv12, uint8* nv21, int width, int height); - -} // namespace media - -#endif // MEDIA_TOOLS_OMX_TEST_COLOR_SPACE_UTIL_H_ diff --git a/media/tools/omx_test/file_reader_util.cc b/media/tools/omx_test/file_reader_util.cc deleted file mode 100644 index a599d2f..0000000 --- a/media/tools/omx_test/file_reader_util.cc +++ /dev/null @@ -1,296 +0,0 @@ -// 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/tools/omx_test/file_reader_util.h" - -#include <stdio.h> -#include <string> - -#include "base/file_util.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "media/ffmpeg/ffmpeg_common.h" -#include "media/ffmpeg/file_protocol.h" -#include "media/filters/bitstream_converter.h" -#include "media/tools/omx_test/color_space_util.h" - -namespace media { - -////////////////////////////////////////////////////////////////////////////// -// BasicFileReader -BasicFileReader::BasicFileReader(const FilePath& path) - : path_(path), - file_(NULL) { -} - -bool BasicFileReader::Initialize() { - file_.Set(file_util::OpenFile(path_, "rb")); - if (!file_.get()) { - LOG(ERROR) << "unable to open " << path_.value(); - } - return file_.get() != NULL; -} - -////////////////////////////////////////////////////////////////////////////// -// YuvFileReader -YuvFileReader::YuvFileReader(const FilePath& path, - int width, - int height, - int loop_count, - bool enable_csc) - : BasicFileReader(path), - width_(width), - height_(height), - loop_count_(loop_count), - output_nv21_(enable_csc) { -} - -YuvFileReader::~YuvFileReader() {} - -void YuvFileReader::Read(uint8** output, int* size) { - if (!file()) { - *size = 0; - *output = NULL; - return; - } - - while (true) { - scoped_array<uint8> data; - int bytes_read = 0; - - // OMX require encoder input are delivered in frames (or planes). - // Assume the input file is I420 YUV file. - const int kFrameSize = width_ * height_ * 3 / 2; - data.reset(new uint8[kFrameSize]); - - if (output_nv21_) { - if (!csc_buf_.get()) - csc_buf_.reset(new uint8[kFrameSize]); - bytes_read = fread(csc_buf_.get(), 1, kFrameSize, file()); - - // We do not convert partial frames. - if (bytes_read == kFrameSize) - IYUVtoNV21(csc_buf_.get(), data.get(), width_, height_); - else - bytes_read = 0; // force cleanup or loop around. - } else { - bytes_read = fread(data.get(), 1, kFrameSize, file()); - } - - if (bytes_read) { - *size = bytes_read; - *output = data.release(); - break; - } - - // Encounter the end of file. - if (loop_count_ == 1) { - // Signal end of stream. - *size = 0; - *output = data.release(); - } - - --loop_count_; - fseek(file(), 0, SEEK_SET); - } -} - -////////////////////////////////////////////////////////////////////////////// -// BlockFileReader -BlockFileReader::BlockFileReader(const FilePath& path, - int block_size) - : BasicFileReader(path), - block_size_(block_size) { -} - -void BlockFileReader::Read(uint8** output, int* size) { - CHECK(file()); - *output = new uint8[block_size_]; - *size = fread(*output, 1, block_size_, file()); -} - -////////////////////////////////////////////////////////////////////////////// -// FFmpegFileReader -FFmpegFileReader::FFmpegFileReader(const FilePath& path) - : path_(path), - format_context_(NULL), - codec_context_(NULL), - target_stream_(-1), - converter_(NULL) { -} - -FFmpegFileReader::~FFmpegFileReader() { - if (format_context_) - av_close_input_file(format_context_); -} - -bool FFmpegFileReader::Initialize() { - // av_open_input_file wants a char*, which can't work with wide paths. - // So we assume ASCII on Windows. On other platforms we can pass the - // path bytes through verbatim. -#if defined(OS_WIN) - std::string string_path = WideToASCII(path_.value()); -#else - const std::string& string_path = path_.value(); -#endif - int result = av_open_input_file(&format_context_, string_path.c_str(), - NULL, 0, NULL); - if (result < 0) { - switch (result) { - case AVERROR_NOFMT: - LOG(ERROR) << "Error: File format not supported " - << path_.value() << std::endl; - break; - default: - LOG(ERROR) << "Error: Could not open input for " - << path_.value() << std::endl; - break; - } - return false; - } - if (av_find_stream_info(format_context_) < 0) { - LOG(ERROR) << "can't use FFmpeg to parse stream info"; - return false; - } - - for (size_t i = 0; i < format_context_->nb_streams; ++i) { - codec_context_ = format_context_->streams[i]->codec; - - // Find the video stream. - if (codec_context_->codec_type == CODEC_TYPE_VIDEO) { - target_stream_ = i; - break; - } - } - if (target_stream_ == -1) { - LOG(ERROR) << "no video in the stream"; - return false; - } - - // Initialize the bitstream filter if needed. - // TODO(hclam): find a better way to identify mp4 container. - if (codec_context_->codec_id == CODEC_ID_H264) { - converter_.reset(new media::FFmpegBitstreamConverter( - "h264_mp4toannexb", codec_context_)); - } else if (codec_context_->codec_id == CODEC_ID_MPEG4) { - converter_.reset(new media::FFmpegBitstreamConverter( - "mpeg4video_es", codec_context_)); - } else if (codec_context_->codec_id == CODEC_ID_WMV3) { - converter_.reset(new media::FFmpegBitstreamConverter( - "vc1_asftorcv", codec_context_)); - } else if (codec_context_->codec_id == CODEC_ID_VC1) { - converter_.reset(new media::FFmpegBitstreamConverter( - "vc1_asftoannexg", codec_context_)); - } - - if (converter_.get() && !converter_->Initialize()) { - converter_.reset(); - LOG(ERROR) << "failed to initialize h264_mp4toannexb filter"; - return false; - } - return true; -} - -void FFmpegFileReader::Read(uint8** output, int* size) { - if (!format_context_ || !codec_context_ || target_stream_ == -1) { - *size = 0; - *output = NULL; - return; - } - - AVPacket packet; - bool found = false; - while (!found) { - int result = av_read_frame(format_context_, &packet); - if (result < 0) { - *output = NULL; - *size = 0; - return; - } - if (packet.stream_index == target_stream_) { - if (converter_.get() && !converter_->ConvertPacket(&packet)) { - LOG(ERROR) << "failed to convert AVPacket"; - } - *output = new uint8[packet.size]; - *size = packet.size; - memcpy(*output, packet.data, packet.size); - found = true; - } - av_free_packet(&packet); - } -} - -////////////////////////////////////////////////////////////////////////////// -// H264FileReader -const int kH264ReadSize = 1024 * 1024; - -H264FileReader::H264FileReader(const FilePath& path) - : BasicFileReader(path), - read_buf_(new uint8[kH264ReadSize]), - current_(0), - used_(0) { -} - -H264FileReader::~H264FileReader() {} - -void H264FileReader::Read(uint8** output, int *size) { - // Fill the buffer when it's less than half full. - int read = 0; - if (used_ < kH264ReadSize / 2) { - read = fread(read_buf_.get(), 1, kH264ReadSize - used_, file()); - CHECK(read >= 0); - used_ += read; - } - - // If we failed to read. - if (current_ == used_) { - *output = NULL; - *size = 0; - return; - } - - // Try to find start code of 0x00, 0x00, 0x01. - bool found = false; - int pos = current_ + 3; - for (; pos < used_ - 2; ++pos) { - if (read_buf_[pos] == 0 && - read_buf_[pos+1] == 0 && - read_buf_[pos+2] == 1) { - found = true; - break; - } - } - - // If next NALU is found. - if (found) { - CHECK(pos > current_); - *size = pos - current_; - *output = new uint8[*size]; - memcpy(*output, read_buf_.get() + current_, *size); - current_ = pos; - - // If we have used_ more than half of the available buffer. - // Then move the unused_ buffer to the front to give space - // for more incoming output. - if (current_ > used_ / 2) { - CHECK(used_ > current_); - memcpy(read_buf_.get(), - read_buf_.get() + current_, - used_ - current_); - used_ = used_ - current_; - current_ = 0; - } - return; - } - - // If next NALU is not found, assume the remaining data is a NALU - // and return the data. - CHECK(used_ > current_); - *size = used_ - current_; - *output = new uint8[*size]; - memcpy(*output, read_buf_.get() + current_, *size); - current_ = used_; -} - -} // namespace media diff --git a/media/tools/omx_test/file_reader_util.h b/media/tools/omx_test/file_reader_util.h deleted file mode 100644 index ae4076d..0000000 --- a/media/tools/omx_test/file_reader_util.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2011 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_TOOLS_OMX_TEST_FILE_READER_UTIL_H_ -#define MEDIA_TOOLS_OMX_TEST_FILE_READER_UTIL_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/file_path.h" -#include "base/memory/scoped_handle.h" -#include "base/memory/scoped_ptr.h" - -struct AVCodecContext; -struct AVFormatContext; - -namespace media { - -class BitstreamConverter; - -// A class to help reading and parsing input file for use in omx_test. -class FileReader { - public: - virtual ~FileReader() {} - - // Initialize FileReader object, returns true if successful. - virtual bool Initialize() = 0; - - // Read the file into |output|, and output the number of bytes read to - // |size|. - virtual void Read(uint8** output, int* size) = 0; -}; - -class BasicFileReader : public FileReader { - public: - explicit BasicFileReader(const FilePath& path); - virtual bool Initialize(); - virtual void Read(uint8** output, int* size) = 0; - - protected: - FILE* file() const { return file_.get(); } - - private: - FilePath path_; - ScopedStdioHandle file_; - - DISALLOW_COPY_AND_ASSIGN(BasicFileReader); -}; - -class YuvFileReader : public BasicFileReader { - public: - // Construct a YUV file reader with looping and color space conversion - // ability. |loop_count| specifies the number of times the input file - // is read. If |enable_csc| is true, input in YV420 is converted to - // NV21. - // TODO(jiesun): Make color space more generic not a hard coded color - // space conversion. - YuvFileReader(const FilePath& path, - int width, - int height, - int loop_count, - bool output_nv21); - virtual ~YuvFileReader(); - - virtual void Read(uint8** output, int* size); - - private: - int width_; - int height_; - int loop_count_; - bool output_nv21_; - scoped_array<uint8> csc_buf_; - - DISALLOW_COPY_AND_ASSIGN(YuvFileReader); -}; - -class BlockFileReader : public BasicFileReader { - public: - BlockFileReader(const FilePath& path, - int block_size); - virtual void Read(uint8** output, int* size); - - private: - int block_size_; - - DISALLOW_COPY_AND_ASSIGN(BlockFileReader); -}; - -class FFmpegFileReader : public FileReader { - public: - explicit FFmpegFileReader(const FilePath& path); - virtual ~FFmpegFileReader(); - virtual bool Initialize(); - virtual void Read(uint8** output, int* size); - - private: - FilePath path_; - AVFormatContext* format_context_; - AVCodecContext* codec_context_; - int target_stream_; - scoped_ptr<media::BitstreamConverter> converter_; - - DISALLOW_COPY_AND_ASSIGN(FFmpegFileReader); -}; - -class H264FileReader : public BasicFileReader { - public: - explicit H264FileReader(const FilePath& path); - virtual ~H264FileReader(); - virtual void Read(uint8** output, int* size); - - private: - scoped_array<uint8> read_buf_; - int current_; - int used_; - - DISALLOW_COPY_AND_ASSIGN(H264FileReader); -}; - -} // namespace media - -#endif // MEDIA_TOOLS_OMX_TEST_FILE_READER_UTIL_H_ diff --git a/media/tools/omx_test/file_sink.cc b/media/tools/omx_test/file_sink.cc deleted file mode 100644 index 5e92b02..0000000 --- a/media/tools/omx_test/file_sink.cc +++ /dev/null @@ -1,69 +0,0 @@ -// 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/tools/omx_test/file_sink.h" - -#include "base/file_util.h" -#include "base/logging.h" -#include "media/tools/omx_test/color_space_util.h" - -namespace media { - -FileSink::FileSink(const FilePath& output_path, - bool simulate_copy, - bool enable_csc) - : output_path_(output_path), - simulate_copy_(simulate_copy), - enable_csc_(enable_csc), - width_(0), - height_(0), - copy_buf_size_(0), - csc_buf_size_(0) { -} - -FileSink::~FileSink() {} - -void FileSink::BufferReady(int size, uint8* buffer) { - if (size > copy_buf_size_) { - copy_buf_.reset(new uint8[size]); - copy_buf_size_ = size; - } - if (size > csc_buf_size_) { - csc_buf_.reset(new uint8[size]); - csc_buf_size_ = size; - } - - // Copy the output of the decoder to user memory. - if (simulate_copy_ || output_file_.get()) // Implies a copy. - memcpy(copy_buf_.get(), buffer, size); - - uint8* out_buffer = copy_buf_.get(); - if (enable_csc_) { - // Now assume the raw output is NV21. - media::NV21toIYUV(copy_buf_.get(), csc_buf_.get(), width_, height_); - out_buffer = csc_buf_.get(); - } - - if (output_file_.get()) - fwrite(out_buffer, sizeof(uint8), size, output_file_.get()); -} - -bool FileSink::Initialize() { - // Opens the output file for writing. - if (!output_path_.empty()) { - output_file_.Set(file_util::OpenFile(output_path_, "wb")); - if (!output_file_.get()) { - LOG(ERROR) << "can't open dump file %s" << output_path_.value(); - return false; - } - } - return true; -} - -void FileSink::UpdateSize(int width, int height) { - width_ = width; - height_ = height; -} - -} // namespace media diff --git a/media/tools/omx_test/file_sink.h b/media/tools/omx_test/file_sink.h deleted file mode 100644 index 8ee0576..0000000 --- a/media/tools/omx_test/file_sink.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2011 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_TOOLS_OMX_TEST_FILE_SINK_H_ -#define MEDIA_TOOLS_OMX_TEST_FILE_SINK_H_ - -#include <map> -#include <string> - -#include "base/basictypes.h" -#include "base/file_path.h" -#include "base/memory/scoped_handle.h" -#include "base/memory/scoped_ptr.h" - -namespace media { - -// This class writes output of a frame decoded by OmxCodec and save it to -// a file. -class FileSink { - public: - FileSink(const FilePath& output_path, - bool simulate_copy, - bool enable_csc); - - virtual ~FileSink(); - - virtual void BufferReady(int size, uint8* buffer); - - // Initialize this object. Returns true if successful. - bool Initialize(); - - // Update the output frame size. - void UpdateSize(int wdith, int height); - - // Write the frame buffer reference by |buffer|. - void Write(uint8* buffer, int size); - - private: - FilePath output_path_; - bool simulate_copy_; - bool enable_csc_; - ScopedStdioHandle output_file_; - - // Image properties. - int width_; - int height_; - - // Buffers for copying and color space conversion. - scoped_array<uint8> copy_buf_; - int copy_buf_size_; - scoped_array<uint8> csc_buf_; - int csc_buf_size_; - - DISALLOW_COPY_AND_ASSIGN(FileSink); -}; - -} // namespace media - -#endif // MEDIA_TOOLS_OMX_TEST_FILE_SINK_H_ diff --git a/media/tools/omx_test/omx_test.cc b/media/tools/omx_test/omx_test.cc deleted file mode 100644 index a5f6591..0000000 --- a/media/tools/omx_test/omx_test.cc +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright (c) 2011 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. - -// A test program that drives an OpenMAX video decoder module. This program -// will take video in elementary stream and read into the decoder. -// -// Run the following command to see usage: -// ./omx_test - -#include "base/at_exit.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop.h" -#include "base/string_number_conversions.h" -#include "base/time.h" -#include "base/utf_string_conversions.h" -#include "media/base/data_buffer.h" -#include "media/base/media.h" -#include "media/base/video_frame.h" -#include "media/ffmpeg/ffmpeg_common.h" -#include "media/ffmpeg/file_protocol.h" -#include "media/filters/bitstream_converter.h" -#include "media/tools/omx_test/color_space_util.h" -#include "media/tools/omx_test/file_reader_util.h" -#include "media/tools/omx_test/file_sink.h" -#include "media/video/omx_video_decode_engine.h" - -using media::BlockFileReader; -using media::Buffer; -using media::DataBuffer; -using media::FFmpegFileReader; -using media::FileReader; -using media::FileSink; -using media::H264FileReader; -using media::OmxConfigurator; -using media::OmxDecoderConfigurator; -using media::OmxEncoderConfigurator; -using media::OmxVideoDecodeEngine; -using media::PipelineStatistics; -using media::VideoFrame; -using media::YuvFileReader; - -// This is the driver object to feed the decoder with data from a file. -// It also provides callbacks for the decoder to receive events from the -// decoder. -// TODO(wjia): AVStream should be replaced with a new structure which is -// neutral to any video decoder. Also change media.gyp correspondingly. -class TestApp : public base::RefCountedThreadSafe<TestApp>, - public media::VideoDecodeEngine::EventHandler { - public: - TestApp(AVStream* av_stream, - FileSink* file_sink, - FileReader* file_reader) - : av_stream_(av_stream), - file_reader_(file_reader), - file_sink_(file_sink), - stopped_(false), - error_(false) { - } - - bool Initialize() { - if (!file_reader_->Initialize()) { - file_reader_.reset(); - LOG(ERROR) << "can't initialize file reader"; - return false;; - } - - if (!file_sink_->Initialize()) { - LOG(ERROR) << "can't initialize output writer"; - return false; - } - return true; - } - - virtual void OnInitializeComplete(const media::VideoCodecInfo& info) {} - - virtual void OnUninitializeComplete() { - // If this callback is received, mark the |stopped_| flag so that we don't - // feed more buffers into the decoder. - // We need to exit the current message loop because we have no more work - // to do on the message loop. This is done by calling - // message_loop_.Quit(). - stopped_ = true; - message_loop_.Quit(); - } - - virtual void OnError() { - // In case of error, this method is called. Mark the error flag and - // exit the message loop because we have no more work to do. - LOG(ERROR) << "Error callback received!"; - error_ = true; - message_loop_.Quit(); - } - - virtual void OnFlushComplete() { - NOTIMPLEMENTED(); - } - - virtual void OnSeekComplete() { - NOTIMPLEMENTED(); - } - - virtual void OnFormatChange(media::VideoStreamInfo stream_info) { - NOTIMPLEMENTED(); - } - - void FormatCallback( - const OmxConfigurator::MediaFormat& input_format, - const OmxConfigurator::MediaFormat& output_format) { - // This callback will be called when port reconfiguration is done. - // Input format and output format will be used in the codec. - - DCHECK_EQ(input_format.video_header.width, - output_format.video_header.width); - DCHECK_EQ(input_format.video_header.height, - output_format.video_header.height); - - file_sink_->UpdateSize(input_format.video_header.width, - input_format.video_header.height); - } - - virtual void ProduceVideoSample(scoped_refptr<Buffer> buffer) { - // We receive this callback when the decoder has consumed an input buffer. - // In this case, delete the previous buffer and enqueue a new one. - // There are some conditions we don't want to enqueue, for example when - // the last buffer is an end-of-stream buffer, when we have stopped, and - // when we have received an error. - bool eos = buffer.get() && buffer->IsEndOfStream(); - if (!eos && !stopped_ && !error_) - FeedInputBuffer(); - } - - virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame, - const PipelineStatistics& statistics) { - // This callback is received when the decoder has completed a decoding - // task and given us some output data. The frame is owned by the decoder. - if (stopped_ || error_) - return; - - if (!frame_count_) - first_sample_delivered_time_ = base::TimeTicks::HighResNow(); - - // If we are reading to the end, then stop. - if (frame->IsEndOfStream()) { - engine_->Uninitialize(); - return; - } - - if (file_sink_.get()) { - for (size_t i = 0; i < frame->planes(); i++) { - int plane_size = frame->width() * frame->height(); - if (i > 0) plane_size >>= 2; - file_sink_->BufferReady(plane_size, frame->data(i)); - } - } - - // could OMX IL return patial sample for decoder? - frame_count_++; - } - - void FeedInputBuffer() { - uint8* data; - int read; - file_reader_->Read(&data, &read); - engine_->ConsumeVideoSample(new DataBuffer(data, read)); - } - - void Run() { - StartProfiler(); - - media::VideoDecoderConfig config( - media::CodecIDToVideoCodec(av_stream_->codec->codec_id), - av_stream_->codec->coded_width, - av_stream_->codec->coded_height, - media::GetSurfaceWidth(av_stream_.get()), - media::GetSurfaceHeight(av_stream_.get()), - av_stream_->r_frame_rate.num, - av_stream_->r_frame_rate.den, - av_stream_->codec->extradata, - av_stream_->codec->extradata_size); - - engine_.reset(new OmxVideoDecodeEngine()); - engine_->Initialize(&message_loop_, this, NULL, config); - - // 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(); - - StopProfiler(); - } - - void StartProfiler() { - start_time_ = base::TimeTicks::HighResNow(); - frame_count_ = 0; - } - - void StopProfiler() { - base::TimeDelta duration = base::TimeTicks::HighResNow() - start_time_; - int64 duration_ms = duration.InMilliseconds(); - int64 fps = 0; - if (duration_ms) { - fps = (static_cast<int64>(frame_count_) * - base::Time::kMillisecondsPerSecond) / duration_ms; - } - base::TimeDelta delay = first_sample_delivered_time_ - start_time_; - printf("\n<<< frame delivered : %d >>>", frame_count_); - printf("\n<<< time used(ms) : %d >>>", static_cast<int>(duration_ms)); - printf("\n<<< fps : %d >>>", static_cast<int>(fps)); - printf("\n<<< initial delay used(us): %d >>>", - static_cast<int>(delay.InMicroseconds())); - printf("\n"); - } - - scoped_ptr<OmxVideoDecodeEngine> engine_; - MessageLoop message_loop_; - scoped_ptr<AVStream> av_stream_; - scoped_ptr<FileReader> file_reader_; - scoped_ptr<FileSink> file_sink_; - - // Internal states for execution. - bool stopped_; - bool error_; - - // Counters for performance. - base::TimeTicks start_time_; - base::TimeTicks first_sample_delivered_time_; - int frame_count_; -}; - -static std::string GetStringSwitch(const char* name) { - return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name); -} - -static bool HasSwitch(const char* name) { - return CommandLine::ForCurrentProcess()->HasSwitch(name); -} - -static int GetIntSwitch(const char* name) { - if (HasSwitch(name)) { - int val; - base::StringToInt(GetStringSwitch(name), &val); - return val; - } - return 0; -} - -static bool PrepareDecodeFormats(AVStream *av_stream) { - std::string codec = GetStringSwitch("codec"); - av_stream->codec->codec_id = CODEC_ID_NONE; - if (codec == "h264") { - av_stream->codec->codec_id = CODEC_ID_H264; - } else if (codec == "mpeg4") { - av_stream->codec->codec_id = CODEC_ID_MPEG4; - } else if (codec == "h263") { - av_stream->codec->codec_id = CODEC_ID_H263; - } else if (codec == "vc1") { - av_stream->codec->codec_id = CODEC_ID_VC1; - } else { - LOG(ERROR) << "Unknown codec."; - return false; - } - return true; -} - -static bool PrepareEncodeFormats(AVStream *av_stream) { - av_stream->codec->width = GetIntSwitch("width"); - av_stream->codec->height = GetIntSwitch("height"); - av_stream->avg_frame_rate.num = GetIntSwitch("framerate"); - av_stream->avg_frame_rate.den = 1; - - std::string codec = GetStringSwitch("codec"); - av_stream->codec->codec_id = CODEC_ID_NONE; - if (codec == "h264") { - av_stream->codec->codec_id = CODEC_ID_H264; - } else if (codec == "mpeg4") { - av_stream->codec->codec_id = CODEC_ID_MPEG4; - } else if (codec == "h263") { - av_stream->codec->codec_id = CODEC_ID_H263; - } else if (codec == "vc1") { - av_stream->codec->codec_id = CODEC_ID_VC1; - } else { - LOG(ERROR) << "Unknown codec."; - return false; - } - // TODO(jiesun): assume constant bitrate now. - av_stream->codec->bit_rate = GetIntSwitch("bitrate"); - - // TODO(wjia): add more configurations needed by encoder - return true; -} - -static bool InitFFmpeg() { - if (!media::InitializeMediaLibrary(FilePath())) - return false; - avcodec_init(); - av_register_all(); - av_register_protocol2(&kFFmpegFileProtocol, sizeof(kFFmpegFileProtocol)); - return true; -} - -static void PrintHelp() { - printf("Using for decoding...\n"); - printf("\n"); - printf("Usage: omx_test --input-file=FILE --codec=CODEC" - " [--output-file=FILE] [--enable-csc]" - " [--copy] [--use-ffmpeg]\n"); - printf(" CODEC: h264/mpeg4/h263/vc1\n"); - printf("\n"); - printf("Optional Arguments\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.\n"); - printf(" --use-ffmpeg Use ffmpeg demuxer\n"); - printf("\n"); - printf("Using for encoding...\n"); - printf("\n"); - printf("Usage: omx_test --encoder --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]\n"); - printf(" CODEC: h264/mpeg4/h263/vc1\n"); - printf("\n"); - printf("Optional Arguments\n"); - printf(" --output-file Dump raw OMX output to file.\n"); - printf(" --enable-csc Dump the CSCed input from file.\n"); - printf(" --copy Simulate a memcpy from the output.\n"); - printf(" --loop=COUNT loop input streams\n"); -} - -int main(int argc, char** argv) { - base::AtExitManager at_exit_manager; - CommandLine::Init(argc, argv); - - // Print help if there is not enough arguments. - if (argc == 1) { - PrintHelp(); - return -1; - } - - const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); - // Read a bunch of parameters. - FilePath input_path = cmd_line.GetSwitchValuePath("input-file"); - FilePath output_path = cmd_line.GetSwitchValuePath("output-file"); - bool encoder = HasSwitch("encoder"); - bool copy = HasSwitch("copy"); - bool enable_csc = HasSwitch("enable-csc"); - bool use_ffmpeg = HasSwitch("use-ffmpeg"); - int loop_count = GetIntSwitch("loop"); - if (loop_count == 0) - loop_count = 1; - DCHECK_GE(loop_count, 1); - - // Initialize OpenMAX. - if (!media::InitializeOpenMaxLibrary(FilePath())) { - LOG(ERROR) << "Unable to initialize OpenMAX library."; - return false; - } - - // If FFmpeg should be used for demuxing load the library here and do - // the initialization. - if (use_ffmpeg && !InitFFmpeg()) { - LOG(ERROR) << "Unable to initialize the media library."; - return -1; - } - - // Create AVStream - AVStream *av_stream = new AVStream; - AVCodecContext *av_codec_context = new AVCodecContext; - memset(av_stream, 0, sizeof(AVStream)); - memset(av_codec_context, 0, sizeof(AVCodecContext)); - scoped_ptr<AVCodecContext> av_codec_context_deleter(av_codec_context); - av_stream->codec = av_codec_context; - av_codec_context->width = 320; - av_codec_context->height = 240; - if (encoder) - PrepareEncodeFormats(av_stream); - else - PrepareDecodeFormats(av_stream); - - // Creates the FileReader to read input file. - FileReader* file_reader; - if (encoder) { - file_reader = new YuvFileReader( - input_path, av_stream->codec->width, - av_stream->codec->height, loop_count, enable_csc); - } else if (use_ffmpeg) { - // Use ffmepg for reading. - file_reader = new FFmpegFileReader(input_path); - } else if (input_path.Extension() == FILE_PATH_LITERAL(".264")) { - file_reader = new H264FileReader(input_path); - } else { - // Creates a reader that reads in blocks of 32KB. - const int kReadSize = 32768; - file_reader = new BlockFileReader(input_path, kReadSize); - } - - // Create a file sink. - FileSink* file_sink = new FileSink(output_path, copy, enable_csc); - - // Create a test app object and initialize it. - scoped_refptr<TestApp> test = new TestApp(av_stream, file_sink, file_reader); - if (!test->Initialize()) { - LOG(ERROR) << "can't initialize this application"; - return -1; - } - - // This will run the decoder until EOS is reached or an error - // is encountered. - test->Run(); - return 0; -} diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index 42b30438..590306b 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -26,7 +26,6 @@ #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/file_data_source_factory.h" #include "media/filters/null_audio_renderer.h" -#include "media/filters/omx_video_decoder.h" // TODO(jiesun): implement different video decode contexts according to // these flags. e.g. @@ -95,14 +94,6 @@ bool InitPipeline(MessageLoop* message_loop, scoped_refptr<media::PipelineImpl>* pipeline, MessageLoop* paint_message_loop, media::MessageLoopFactory* message_loop_factory) { - // Initialize OpenMAX. - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableOpenMax) && - !media::InitializeOpenMaxLibrary(FilePath())) { - std::cout << "Unable to initialize OpenMAX library."<< std::endl; - return false; - } - // Load media libraries. if (!media::InitializeMediaLibrary(FilePath())) { std::cout << "Unable to initialize the media library." << std::endl; @@ -118,16 +109,9 @@ bool InitPipeline(MessageLoop* message_loop, new media::FileDataSourceFactory(), message_loop))); collection->AddAudioDecoder(new media::FFmpegAudioDecoder( message_loop_factory->GetMessageLoop("AudioDecoderThread"))); - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableOpenMax)) { - collection->AddVideoDecoder(new media::OmxVideoDecoder( - message_loop_factory->GetMessageLoop("VideoDecoderThread"), - NULL)); - } else { - collection->AddVideoDecoder(new media::FFmpegVideoDecoder( - message_loop_factory->GetMessageLoop("VideoDecoderThread"), - NULL)); - } + collection->AddVideoDecoder(new media::FFmpegVideoDecoder( + message_loop_factory->GetMessageLoop("VideoDecoderThread"), + NULL)); collection->AddVideoRenderer(new Renderer(g_display, g_window, paint_message_loop)); @@ -234,7 +218,6 @@ int main(int argc, char** argv) { std::cout << "Usage: " << argv[0] << " --file=FILE" << std::endl << std::endl << "Optional arguments:" << std::endl - << " [--enable-openmax]" << " [--audio]" << " [--alsa-device=DEVICE]" << std::endl << " Press [ESC] to stop" << std::endl diff --git a/media/video/omx_video_decode_engine.cc b/media/video/omx_video_decode_engine.cc deleted file mode 100644 index d799ecd..0000000 --- a/media/video/omx_video_decode_engine.cc +++ /dev/null @@ -1,1357 +0,0 @@ -// Copyright (c) 2011 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. - -// This class interacts with OmxCodec and the VideoDecoderImpl -// in the media pipeline. -// -// THREADING SEMANTICS -// -// This class is created by OmxVideoDecoder and lives on the thread -// that it lives. This class is given the message loop -// for the above thread. The OMX callbacks are guaranteed to be -// executed on the hosting message loop. Because of that there's no need -// for locking anywhere. - -#include "media/video/omx_video_decode_engine.h" - -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/string_util.h" -#include "media/base/buffers.h" -#include "media/base/pipeline.h" - -namespace media { - -OmxVideoDecodeEngine::OmxVideoDecodeEngine() - : width_(16), - height_(16), - message_loop_(NULL), - input_buffer_count_(0), - input_buffer_size_(0), - input_port_(0), - input_buffers_at_component_(0), - input_pending_request_(0), - input_queue_has_eos_(false), - input_has_fed_eos_(false), - input_port_flushed_(false), - output_buffer_count_(0), - output_buffer_size_(0), - output_port_(0), - output_buffers_at_component_(0), - output_pending_request_(0), - output_eos_(false), - output_port_flushed_(false), - il_state_(kIlNone), - expected_il_state_(kIlNone), - client_state_(kClientNotInitialized), - component_handle_(NULL), - need_free_input_buffers_(false), - need_free_output_buffers_(false), - flush_pending_(false), - output_frames_allocated_(false), - need_setup_output_port_(false) { - // TODO(wjia): change uses_egl_image_ to runtime setup -#if ENABLE_EGLIMAGE == 1 - uses_egl_image_ = true; - DLOG(INFO) << "Uses egl image for output"; -#else - uses_egl_image_ = false; - DLOG(INFO) << "Uses system memory for output"; -#endif -} - -OmxVideoDecodeEngine::~OmxVideoDecodeEngine() { - DCHECK(client_state_ == kClientNotInitialized || - client_state_ == kClientStopped); - DCHECK_EQ(il_state_, kIlNone); - DCHECK_EQ(0u, input_buffers_.size()); - DCHECK(free_input_buffers_.empty()); - DCHECK(available_input_buffers_.empty()); - DCHECK_EQ(0, input_buffers_at_component_); - DCHECK_EQ(0, output_buffers_at_component_); - DCHECK(output_frames_.empty()); -} - -template <typename T> -static void ResetParamHeader(const OmxVideoDecodeEngine& dec, T* param) { - memset(param, 0, sizeof(T)); - param->nVersion.nVersion = dec.current_omx_spec_version(); - param->nSize = sizeof(T); -} - -void OmxVideoDecodeEngine::Initialize( - MessageLoop* message_loop, - VideoDecodeEngine::EventHandler* event_handler, - VideoDecodeContext* context, - const VideoDecoderConfig& config) { - DCHECK_EQ(message_loop, MessageLoop::current()); - - message_loop_ = message_loop; - event_handler_ = event_handler; - - width_ = config.width(); - height_ = config.height(); - - // TODO(wjia): Find the right way to determine the codec type. - OmxConfigurator::MediaFormat input_format, output_format; - memset(&input_format, 0, sizeof(input_format)); - memset(&output_format, 0, sizeof(output_format)); - input_format.codec = OmxConfigurator::kCodecH264; - output_format.codec = OmxConfigurator::kCodecRaw; - configurator_.reset( - new OmxDecoderConfigurator(input_format, output_format)); - - // TODO(jiesun): We already ensure Initialize() is called in thread context, - // We should try to merge the following function into this function. - client_state_ = kClientInitializing; - InitializeTask(); - - VideoCodecInfo info; - // TODO(jiesun): ridiculous, we never fail initialization? - info.success = true; - info.provides_buffers = !uses_egl_image_; - info.stream_info.surface_type = - uses_egl_image_ ? VideoFrame::TYPE_GL_TEXTURE - : VideoFrame::TYPE_SYSTEM_MEMORY; - info.stream_info.surface_format = GetSurfaceFormat(); - info.stream_info.surface_width = config.width(); - info.stream_info.surface_height = config.height(); - event_handler_->OnInitializeComplete(info); -} - -// This method handles only input buffer, without coupling with output -void OmxVideoDecodeEngine::ConsumeVideoSample(scoped_refptr<Buffer> buffer) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK(!free_input_buffers_.empty()); - DCHECK_GT(input_pending_request_, 0); - - --input_pending_request_; - - if (!CanAcceptInput()) { - FinishEmptyBuffer(buffer); - return; - } - - if (buffer->IsEndOfStream()) { - DLOG(INFO) << "Input queue has EOS"; - input_queue_has_eos_ = true; - } - - OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); - free_input_buffers_.pop(); - - // setup |omx_buffer|. - omx_buffer->pBuffer = const_cast<OMX_U8*>(buffer->GetData()); - omx_buffer->nFilledLen = buffer->GetDataSize(); - omx_buffer->nAllocLen = omx_buffer->nFilledLen; - if (input_queue_has_eos_) - omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; - else - omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; - omx_buffer->nTimeStamp = buffer->GetTimestamp().InMicroseconds(); - omx_buffer->pAppPrivate = buffer.get(); - buffer->AddRef(); - available_input_buffers_.push(omx_buffer); - - // Try to feed buffers into the decoder. - EmptyBufferTask(); - - if (flush_pending_ && input_pending_request_ == 0) - StartFlush(); -} - -void OmxVideoDecodeEngine::Flush() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(il_state_, kIlExecuting); - - if (il_state_ != kIlExecuting) { - event_handler_->OnFlushComplete(); - return; - } - - client_state_ = kClientFlushing; - expected_il_state_ = kIlPause; - OnStateSetEventFunc = &OmxVideoDecodeEngine::PauseFromExecuting; - TransitionToState(OMX_StatePause); -} - -void OmxVideoDecodeEngine::PauseFromExecuting(OMX_STATETYPE state) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - OnStateSetEventFunc = NULL; - il_state_ = kIlPause; - - if (input_pending_request_ == 0) - StartFlush(); - else - flush_pending_ = true; -} - -void OmxVideoDecodeEngine::StartFlush() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(input_pending_request_, 0); - DLOG(INFO) << "StartFlush"; - - while (!available_input_buffers_.empty()) - available_input_buffers_.pop(); - - flush_pending_ = false; - - // Flush input port first. - OnFlushEventFunc = &OmxVideoDecodeEngine::PortFlushDone; - OMX_ERRORTYPE omxresult; - omxresult = OMX_SendCommand(component_handle_, - OMX_CommandFlush, - input_port_, 0); -} - -bool OmxVideoDecodeEngine::InputPortFlushed() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(client_state_, kClientFlushing); - // Port flushed is defined by OpenMAX component had signal flush done and - // We had all buffers returned from demuxer and OpenMAX component. - int free_input_size = static_cast<int>(free_input_buffers_.size()); - return input_port_flushed_ && free_input_size == input_buffer_count_; -} - -bool OmxVideoDecodeEngine::OutputPortFlushed() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(client_state_, kClientFlushing); - // Port flushed is defined by OpenMAX component had signal flush done and - // We had all buffers returned from renderer and OpenMAX component. - return output_port_flushed_ && output_pending_request_ == 0; -} - -void OmxVideoDecodeEngine::ComponentFlushDone() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DLOG(INFO) << "Component had been flushed!"; - - if (input_port_flushed_ && output_port_flushed_) { - event_handler_->OnFlushComplete(); - input_port_flushed_ = false; - output_port_flushed_ = false; - } -} - -void OmxVideoDecodeEngine::PortFlushDone(int port) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_NE(port, static_cast<int>(OMX_ALL)); - - if (port == input_port_) { - DLOG(INFO) << "Input Port had been flushed"; - DCHECK_EQ(input_buffers_at_component_, 0); - input_port_flushed_ = true; - // Flush output port next. - OMX_ERRORTYPE omxresult; - omxresult = OMX_SendCommand(component_handle_, - OMX_CommandFlush, - output_port_, 0); - return; - } - - if (port == output_port_) { - DLOG(INFO) << "Output Port had been flushed"; - DCHECK_EQ(output_buffers_at_component_, 0); - - output_port_flushed_ = true; - } - - if (kClientFlushing == client_state_ && - InputPortFlushed() && OutputPortFlushed()) - ComponentFlushDone(); -} - -void OmxVideoDecodeEngine::Seek() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - DCHECK(client_state_ == kClientFlushing || // After a flush - client_state_ == kClientInitializing); // After an initialize. - - if (client_state_ == kClientFlushing) { - InitialReadBuffer(); - OnStateSetEventFunc = &OmxVideoDecodeEngine::DoneSetStateExecuting; - TransitionToState(OMX_StateExecuting); - } - - event_handler_->OnSeekComplete(); -} - -int OmxVideoDecodeEngine::current_omx_spec_version() const { - return 0x00000101; -} - -VideoFrame::Format OmxVideoDecodeEngine::GetSurfaceFormat() const { - // TODO(jiesun): Both OmxHeaderType and EGLImage surface type could have - // different surface formats. - return uses_egl_image_ ? VideoFrame::RGBA : VideoFrame::YV12; -} - -void OmxVideoDecodeEngine::Uninitialize() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - if (client_state_ == kClientError) { - OnStopDone(); - return; - } - - // TODO(wjia): add more state checking - if (kClientRunning == client_state_ || kClientFlushing == client_state_) { - client_state_ = kClientStopping; - DeinitFromExecuting(OMX_StateExecuting); - } - - // TODO(wjia): When FillThisBuffer() is added, engine state should be - // kStopping here. engine state should be set to kStopped in OnStopDone(); - // client_state_ = kClientStopping; -} - -void OmxVideoDecodeEngine::FinishEmptyBuffer(scoped_refptr<Buffer> buffer) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - if (!input_queue_has_eos_) { - event_handler_->ProduceVideoSample(buffer); - ++input_pending_request_; - } -} - -void OmxVideoDecodeEngine::FinishFillBuffer(OMX_BUFFERHEADERTYPE* buffer) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK(buffer); - - scoped_refptr<VideoFrame> frame; - frame = static_cast<VideoFrame*>(buffer->pAppPrivate); - - // We should not flush buffer to renderer during decoder flushing if decoder - // provides the buffer allocator. - if (kClientFlushing == client_state_ && !uses_egl_image_) return; - - PipelineStatistics statistics; - statistics.video_bytes_decoded = buffer->nFilledLen; - - frame->SetTimestamp(base::TimeDelta::FromMicroseconds(buffer->nTimeStamp)); - frame->SetDuration(frame->GetTimestamp() - last_pts_); - last_pts_ = frame->GetTimestamp(); - event_handler_->ConsumeVideoFrame(frame, statistics); - output_pending_request_--; -} - -void OmxVideoDecodeEngine::OnStopDone() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - event_handler_->OnUninitializeComplete(); -} - -// Function sequence for initializing -void OmxVideoDecodeEngine::InitializeTask() { - DCHECK_EQ(il_state_, kIlNone); - - il_state_ = kIlNone; - expected_il_state_ = kIlLoaded; - output_port_state_ = kPortEnabled; - if (!CreateComponent()) { - StopOnError(); - return; - } - il_state_ = kIlLoaded; - - // TODO(wjia): Disabling output port is to work around racing condition - // due to bug in some vendor's driver. But it hits another bug. - // So temporarily fall back to enabling output port. Still keep the code - // disabling output port here. - // No need to respond to this PortDisable event - // OnPortDisableEventFunc = NULL; - // ChangePort(OMX_CommandPortDisable, output_port_); - // if (kClientError == client_state_) { - // StopOnError(); - // return; - // } - // output_port_state_ = kPortDisabled; - - // Transition component to Idle state - OnStateSetEventFunc = &OmxVideoDecodeEngine::DoneSetStateIdle; - if (!TransitionToState(OMX_StateIdle)) { - StopOnError(); - return; - } - expected_il_state_ = kIlIdle; - - if (!AllocateInputBuffers()) { - LOG(ERROR) << "OMX_AllocateBuffer() Input buffer error"; - client_state_ = kClientError; - StopOnError(); - return; - } - if (!AllocateOutputBuffers()) { - LOG(ERROR) << "OMX_AllocateBuffer() Output buffer error"; - client_state_ = kClientError; - return; - } -} - -// Sequence of actions in this transition: -// -// 1. Initialize OMX (To be removed.) -// 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. Input/output ports media format configuration. -// 7. Obtain the information about the input port. -// 8. Obtain the information about the output port. -bool OmxVideoDecodeEngine::CreateComponent() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - static OMX_CALLBACKTYPE callback = { - &OmxVideoDecodeEngine::EventHandler, - &OmxVideoDecodeEngine::EmptyBufferCallback, - &OmxVideoDecodeEngine::FillBufferCallback - }; - - // 1. Initialize the OpenMAX Core. - // TODO(hclam): move this out. - OMX_ERRORTYPE omxresult = OMX_Init(); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "Failed to init OpenMAX core"; - client_state_ = kClientError; - return false; - } - - // 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()), - &roles, 0); - if (omxresult != OMX_ErrorNone || roles == 0) { - LOG(ERROR) << "Unsupported Role: " << role_name.c_str(); - client_state_ = kClientError; - return false; - } - 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. - std::string component_name; - 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(); - client_state_ = kClientError; - return false; - } - - // 3. Get the handle to the component. After OMX_GetHandle(), - // the component is in loaded state. - OMX_STRING component = const_cast<OMX_STRING>(component_name.c_str()); - omxresult = OMX_GetHandle(&component_handle_, component, this, &callback); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "Failed to Load the component: " << component; - client_state_ = kClientError; - return false; - } - - // 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; - ResetParamHeader(*this, &port_param); - omxresult = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit, - &port_param); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "Failed to get Port Param"; - client_state_ = kClientError; - return false; - } - input_port_ = port_param.nStartPortNumber; - output_port_ = input_port_ + 1; - - // 5. Set role for the component because our component could - // have multiple roles. - OMX_PARAM_COMPONENTROLETYPE role_type; - ResetParamHeader(*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"; - client_state_ = kClientError; - return false; - } - - // 6. Input/output ports media format configuration. - if (!ConfigureIOPorts()) { - LOG(ERROR) << "Media format configurations failed"; - client_state_ = kClientError; - return false; - } - - // 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; - ResetParamHeader(*this, &port_format); - port_format.nPortIndex = input_port_; - omxresult = OMX_GetParameter(component_handle_, - OMX_IndexParamPortDefinition, - &port_format); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "GetParameter(OMX_IndexParamPortDefinition) failed"; - client_state_ = kClientError; - return false; - } - if (OMX_DirInput != port_format.eDir) { - LOG(ERROR) << "Expected input port"; - client_state_ = kClientError; - return false; - } - input_buffer_count_ = port_format.nBufferCountActual; - input_buffer_size_ = port_format.nBufferSize; - - // 8. Obtain the information about the output port. - ResetParamHeader(*this, &port_format); - port_format.nPortIndex = output_port_; - omxresult = OMX_GetParameter(component_handle_, - OMX_IndexParamPortDefinition, - &port_format); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "GetParameter(OMX_IndexParamPortDefinition) failed"; - client_state_ = kClientError; - return false; - } - if (OMX_DirOutput != port_format.eDir) { - LOG(ERROR) << "Expect Output Port"; - client_state_ = kClientError; - return false; - } - - // TODO(wjia): use same buffer recycling for EGLImage and system memory. - // Override buffer count when EGLImage is used. - if (uses_egl_image_) { - // TODO(wjia): remove hard-coded value - port_format.nBufferCountActual = port_format.nBufferCountMin = - output_buffer_count_ = 4; - - omxresult = OMX_SetParameter(component_handle_, - OMX_IndexParamPortDefinition, - &port_format); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "SetParameter(OMX_IndexParamPortDefinition) failed"; - client_state_ = kClientError; - return false; - } - } else { - output_buffer_count_ = port_format.nBufferCountActual; - } - output_buffer_size_ = port_format.nBufferSize; - - return true; -} - -// Event callback during initialization to handle DoneStateSet to idle -void OmxVideoDecodeEngine::DoneSetStateIdle(OMX_STATETYPE state) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(client_state_, kClientInitializing); - DCHECK_EQ(OMX_StateIdle, state); - DLOG(INFO) << "OMX video decode engine is in Idle"; - - il_state_ = kIlIdle; - - // start reading bit stream - InitialReadBuffer(); - OnStateSetEventFunc = &OmxVideoDecodeEngine::DoneSetStateExecuting; - if (!TransitionToState(OMX_StateExecuting)) { - StopOnError(); - return; - } - expected_il_state_ = kIlExecuting; -} - -// Event callback during initialization to handle DoneStateSet to executing -void OmxVideoDecodeEngine::DoneSetStateExecuting(OMX_STATETYPE state) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK(client_state_ == kClientInitializing || - client_state_ == kClientFlushing); - DCHECK_EQ(OMX_StateExecuting, state); - DLOG(INFO) << "OMX video decode engine is in Executing"; - - il_state_ = kIlExecuting; - client_state_ = kClientRunning; - OnStateSetEventFunc = NULL; - EmptyBufferTask(); - InitialFillBuffer(); - if (kClientError == client_state_) { - StopOnError(); - return; - } -} - -// Function for receiving output buffers. Hookup for buffer recycling -// and outside allocator. -void OmxVideoDecodeEngine::ProduceVideoFrame( - scoped_refptr<VideoFrame> video_frame) { - DCHECK(video_frame.get() && !video_frame->IsEndOfStream()); - output_pending_request_++; - - PipelineStatistics statistics; - - if (!CanAcceptOutput()) { - if (uses_egl_image_) { // return it to owner. - output_pending_request_--; - event_handler_->ConsumeVideoFrame(video_frame, statistics); - } - return; - } - - OMX_BUFFERHEADERTYPE* omx_buffer = FindOmxBuffer(video_frame); - if (omx_buffer) { - statistics.video_bytes_decoded = omx_buffer->nFilledLen; - - if (kClientRunning == client_state_) { - SendOutputBufferToComponent(omx_buffer); - } else if (kClientFlushing == client_state_) { - if (uses_egl_image_) { // return it to owner. - output_pending_request_--; - event_handler_->ConsumeVideoFrame(video_frame, statistics); - } - if (InputPortFlushed() && OutputPortFlushed()) - ComponentFlushDone(); - } - } else { - DCHECK(!output_frames_allocated_); - DCHECK(uses_egl_image_); - output_frames_.push_back(std::make_pair(video_frame, - static_cast<OMX_BUFFERHEADERTYPE*>(NULL))); - } - - DCHECK(static_cast<int>(output_frames_.size()) <= output_buffer_count_); - - if ((!output_frames_allocated_) && - static_cast<int>(output_frames_.size()) == output_buffer_count_) { - output_frames_allocated_ = true; - - if (need_setup_output_port_) { - SetupOutputPort(); - } - } - - if (kClientError == client_state_) { - StopOnError(); - return; - } -} - -// Reconfigure port -void OmxVideoDecodeEngine::OnPortSettingsChangedRun(int port, - OMX_INDEXTYPE index) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(client_state_, kClientRunning); - DCHECK_EQ(port, output_port_); - - // TODO(wjia): add buffer negotiation between decoder and renderer. - if (uses_egl_image_) { - DLOG(INFO) << "Port settings are changed"; - return; - } - - // TODO(wjia): remove this checking when all vendors observe same spec. - if (index > OMX_IndexComponentStartUnused) { - if (index != OMX_IndexParamPortDefinition) - return; - } - - OMX_PARAM_PORTDEFINITIONTYPE port_format; - ResetParamHeader(*this, &port_format); - port_format.nPortIndex = output_port_; - OMX_ERRORTYPE omxresult; - omxresult = OMX_GetParameter(component_handle_, - OMX_IndexParamPortDefinition, - &port_format); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "GetParameter(OMX_IndexParamPortDefinition) failed"; - client_state_ = kClientError; - StopOnError(); - return; - } - if (OMX_DirOutput != port_format.eDir) { - LOG(ERROR) << "Expected Output Port"; - client_state_ = kClientError; - StopOnError(); - return; - } - - // Update the output format. - OmxConfigurator::MediaFormat 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; - output_buffer_count_ = port_format.nBufferCountActual; - output_buffer_size_ = port_format.nBufferSize; - - if (kPortEnabled == output_port_state_) { - output_port_state_ = kPortDisabling; - OnPortDisableEventFunc = &OmxVideoDecodeEngine::OnPortDisableEventRun; - ChangePort(OMX_CommandPortDisable, output_port_); - if (kClientError == client_state_) { - StopOnError(); - return; - } - FreeOutputBuffers(); - } else { - OnPortDisableEventRun(output_port_); - } -} - -// Post output port disabling -void OmxVideoDecodeEngine::OnPortDisableEventRun(int port) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(client_state_, kClientRunning); - DCHECK_EQ(port, output_port_); - - output_port_state_ = kPortDisabled; - - // make sure all eglimages are available before enabling output port - if (output_frames_allocated_ || !uses_egl_image_) { - SetupOutputPort(); - if (kClientError == client_state_) { - StopOnError(); - return; - } - } else { - need_setup_output_port_ = true; - } -} - -// Enable output port and allocate buffers correspondingly -void OmxVideoDecodeEngine::SetupOutputPort() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - need_setup_output_port_ = false; - - // Enable output port when necessary since the port could be waiting for - // buffers, instead of port reconfiguration. - if (kPortEnabled != output_port_state_) { - output_port_state_ = kPortEnabling; - OnPortEnableEventFunc = &OmxVideoDecodeEngine::OnPortEnableEventRun; - ChangePort(OMX_CommandPortEnable, output_port_); - if (kClientError == client_state_) { - return; - } - } - - // TODO(wjia): add state checking - // Update the ports in buffer if necessary - if (!AllocateOutputBuffers()) { - LOG(ERROR) << "OMX_AllocateBuffer() Output buffer error"; - client_state_ = kClientError; - return; - } -} - -// Post output port enabling -void OmxVideoDecodeEngine::OnPortEnableEventRun(int port) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(port, output_port_); - DCHECK_EQ(client_state_, kClientRunning); - - output_port_state_ = kPortEnabled; - last_pts_ = base::TimeDelta::FromMilliseconds(0); - OnPortEnableEventFunc = NULL; - InitialFillBuffer(); - if (kClientError == client_state_) { - StopOnError(); - return; - } -} - -void OmxVideoDecodeEngine::DeinitFromExecuting(OMX_STATETYPE state) { - DCHECK_EQ(state, OMX_StateExecuting); - - DLOG(INFO) << "Deinit from Executing"; - OnStateSetEventFunc = &OmxVideoDecodeEngine::DeinitFromIdle; - TransitionToState(OMX_StateIdle); - expected_il_state_ = kIlIdle; -} - -void OmxVideoDecodeEngine::DeinitFromIdle(OMX_STATETYPE state) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(state, OMX_StateIdle); - - DLOG(INFO) << "Deinit from Idle"; - il_state_ = kIlIdle; - OnStateSetEventFunc = &OmxVideoDecodeEngine::DeinitFromLoaded; - TransitionToState(OMX_StateLoaded); - expected_il_state_ = kIlLoaded; - - if (!input_buffers_at_component_) - FreeInputBuffers(); - else - need_free_input_buffers_ = true; - - if (!output_buffers_at_component_) - FreeOutputBuffers(); - else - need_free_output_buffers_ = true; -} - -void OmxVideoDecodeEngine::DeinitFromLoaded(OMX_STATETYPE state) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_EQ(state, OMX_StateLoaded); - - DLOG(INFO) << "Deinit from Loaded"; - il_state_ = kIlLoaded; - if (component_handle_) { - OMX_ERRORTYPE result = OMX_FreeHandle(component_handle_); - if (result != OMX_ErrorNone) - LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; - component_handle_ = NULL; - } - il_state_ = expected_il_state_ = kIlNone; - - // kClientStopped is different from kClientNotInitialized. The former can't - // accept output buffers, while the latter can. - client_state_ = kClientStopped; - - OMX_Deinit(); - - OnStopDone(); -} - -void OmxVideoDecodeEngine::StopOnError() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - client_state_ = kClientStopping; - - if (kIlExecuting == expected_il_state_) { - DeinitFromExecuting(OMX_StateExecuting); - } else if (kIlIdle == expected_il_state_) { - DeinitFromIdle(OMX_StateIdle); - } else if (kIlLoaded == expected_il_state_) { - DeinitFromLoaded(OMX_StateLoaded); - } else if (kIlPause == expected_il_state_) { - // TODO(jiesun): Make sure this works. - DeinitFromExecuting(OMX_StateExecuting); - } else { - NOTREACHED(); - } -} - -// Call OMX_UseBuffer() to avoid buffer copying when -// OMX_EmptyThisBuffer() is called -bool OmxVideoDecodeEngine::AllocateInputBuffers() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - uint8* data = new uint8[input_buffer_size_]; - scoped_array<uint8> data_deleter(data); - - for (int i = 0; i < input_buffer_count_; ++i) { - OMX_BUFFERHEADERTYPE* buffer; - OMX_ERRORTYPE error = - OMX_UseBuffer(component_handle_, &buffer, input_port_, - this, input_buffer_size_, data); - if (error != OMX_ErrorNone) - return false; - buffer->nInputPortIndex = input_port_; - buffer->nOffset = 0; - buffer->nFlags = 0; - input_buffers_.push_back(buffer); - free_input_buffers_.push(buffer); - } - return true; -} - -// This method handles EGLImage and internal buffer cases. Any external -// allocation case is similar to EGLImage -bool OmxVideoDecodeEngine::AllocateOutputBuffers() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - if (uses_egl_image_ && !output_frames_allocated_) { - DLOG(INFO) << "Output frames are not allocated yet"; - need_setup_output_port_ = true; - return true; - } - - for (int i = 0; i < output_buffer_count_; ++i) { - OMX_BUFFERHEADERTYPE* buffer; - scoped_refptr<VideoFrame> video_frame; - OMX_ERRORTYPE error; - if (uses_egl_image_) { - OutputFrame output_frame = output_frames_[i]; - video_frame = output_frame.first; - DCHECK(!output_frame.second); - error = OMX_UseEGLImage(component_handle_, &buffer, output_port_, - video_frame.get(), video_frame->private_buffer()); - if (error != OMX_ErrorNone) - return false; - output_frames_[i].second = buffer; - } else { - error = OMX_AllocateBuffer(component_handle_, &buffer, output_port_, - NULL, output_buffer_size_); - if (error != OMX_ErrorNone) - return false; - video_frame = CreateOmxBufferVideoFrame(buffer); - output_frames_.push_back(std::make_pair(video_frame, buffer)); - buffer->pAppPrivate = video_frame.get(); - } - } - - return true; -} - -scoped_refptr<VideoFrame> OmxVideoDecodeEngine::CreateOmxBufferVideoFrame( - OMX_BUFFERHEADERTYPE* omx_buffer) { - scoped_refptr<VideoFrame> video_frame; - uint8* data[VideoFrame::kMaxPlanes]; - int32 strides[VideoFrame::kMaxPlanes]; - - memset(data, 0, sizeof(data)); - memset(strides, 0, sizeof(strides)); - // TODO(jiesun): chroma format 4:2:0 only and 3 planes. - data[0] = omx_buffer->pBuffer; - data[1] = data[0] + width_ * height_; - data[2] = data[1] + width_ * height_ / 4; - strides[0] = width_; - strides[1] = strides[2] = width_ >> 1; - - VideoFrame::CreateFrameExternal( - VideoFrame::TYPE_SYSTEM_MEMORY, - VideoFrame::YV12, - width_, height_, 3, - data, strides, - kNoTimestamp, - kNoTimestamp, - omx_buffer, - &video_frame); - - return video_frame; -} - -void OmxVideoDecodeEngine::FreeInputBuffers() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - // Empty available buffer queue. - while (!free_input_buffers_.empty()) { - free_input_buffers_.pop(); - } - - while (!available_input_buffers_.empty()) { - OMX_BUFFERHEADERTYPE* omx_buffer = available_input_buffers_.front(); - available_input_buffers_.pop(); - Buffer* stored_buffer = static_cast<Buffer*>(omx_buffer->pAppPrivate); - FinishEmptyBuffer(stored_buffer); - stored_buffer->Release(); - } - - // Calls to OMX to free buffers. - for (size_t i = 0; i < input_buffers_.size(); ++i) - OMX_FreeBuffer(component_handle_, input_port_, input_buffers_[i]); - input_buffers_.clear(); - - need_free_input_buffers_ = false; -} - -void OmxVideoDecodeEngine::FreeOutputBuffers() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - // Calls to OMX to free buffers. - for (size_t i = 0; i < output_frames_.size(); ++i) { - OMX_BUFFERHEADERTYPE* omx_buffer = output_frames_[i].second; - CHECK(omx_buffer); - OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); - } - output_frames_.clear(); - output_frames_allocated_ = false; - - need_free_output_buffers_ = false; -} - -bool OmxVideoDecodeEngine::ConfigureIOPorts() { - OMX_PARAM_PORTDEFINITIONTYPE input_port_def, output_port_def; - OMX_ERRORTYPE omxresult = OMX_ErrorNone; - // Get default input port definition. - ResetParamHeader(*this, &input_port_def); - input_port_def.nPortIndex = input_port_; - omxresult = OMX_GetParameter(component_handle_, - OMX_IndexParamPortDefinition, - &input_port_def); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "GetParameter(OMX_IndexParamPortDefinition) " - << "for input port failed"; - return false; - } - if (OMX_DirInput != input_port_def.eDir) { - LOG(ERROR) << "Expected Input Port"; - return false; - } - - // Get default output port definition. - ResetParamHeader(*this, &output_port_def); - output_port_def.nPortIndex = output_port_; - omxresult = OMX_GetParameter(component_handle_, - OMX_IndexParamPortDefinition, - &output_port_def); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "GetParameter(OMX_IndexParamPortDefinition) " - << "for output port failed"; - return false; - } - if (OMX_DirOutput != output_port_def.eDir) { - LOG(ERROR) << "Expected Output Port"; - return false; - } - - return configurator_->ConfigureIOPorts( - static_cast<OMX_COMPONENTTYPE*>(component_handle_), - &input_port_def, &output_port_def); -} - -bool OmxVideoDecodeEngine::CanEmptyBuffer() { - // We can call empty buffer while we are in executing and EOS has - // not been sent - return (il_state_ == kIlExecuting && - !input_has_fed_eos_); -} - -bool OmxVideoDecodeEngine::CanFillBuffer() { - // Make sure component is in the executing state and end-of-stream - // has not been reached. - return (il_state_ == kIlExecuting && - !output_eos_ && - (output_port_state_ == kPortEnabled || - output_port_state_ == kPortEnabling)); -} - -bool OmxVideoDecodeEngine::CanAcceptInput() { - // We can't take input buffer when in error state. - return (kClientError != client_state_ && - kClientStopping != client_state_ && - kClientStopped != client_state_ && - !input_queue_has_eos_); -} - -bool OmxVideoDecodeEngine::CanAcceptOutput() { - return (kClientError != client_state_ && - kClientStopping != client_state_ && - kClientStopped != client_state_ && - output_port_state_ == kPortEnabled && - !output_eos_); -} - -// TODO(wjia): There are several things need to be done here: -// 1. Merge this method into EmptyThisBuffer(); -// 2. Get rid of the while loop, this is not needed because when we call -// OMX_EmptyThisBuffer we assume we *always* have an input buffer. -void OmxVideoDecodeEngine::EmptyBufferTask() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - if (!CanEmptyBuffer()) - return; - - // Loop for all available input data and input buffer for the - // decoder. When input has reached EOS we need to stop. - while (!available_input_buffers_.empty() && - !input_has_fed_eos_) { - OMX_BUFFERHEADERTYPE* omx_buffer = available_input_buffers_.front(); - available_input_buffers_.pop(); - - input_has_fed_eos_ = omx_buffer->nFlags & OMX_BUFFERFLAG_EOS; - if (input_has_fed_eos_) { - DLOG(INFO) << "Input has fed EOS"; - } - - // Give this buffer to OMX. - input_buffers_at_component_++; - OMX_ERRORTYPE ret = OMX_EmptyThisBuffer(component_handle_, omx_buffer); - if (ret != OMX_ErrorNone) { - LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << ret; - client_state_ = kClientError; - return; - } - } -} - -void OmxVideoDecodeEngine::InitialReadBuffer() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - input_queue_has_eos_ = false; - input_has_fed_eos_ = false; - output_eos_ = false; - - DLOG(INFO) << "OmxVideoDecodeEngine::InitialReadBuffer"; - for (size_t i = 0; i < free_input_buffers_.size(); i++) - FinishEmptyBuffer(NULL); -} - -void OmxVideoDecodeEngine::InitialFillBuffer() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - // DCHECK(output_frames_allocated_); - - if (!CanFillBuffer()) - return; - - DLOG(INFO) << "OmxVideoDecodeEngine::InitialFillBuffer"; - - // Ask the decoder to fill the output buffers. - for (uint32 i = 0; i < output_frames_.size(); ++i) { - OMX_BUFFERHEADERTYPE* omx_buffer = output_frames_[i].second; - SendOutputBufferToComponent(omx_buffer); - } -} - -// helper functions -// Send command to disable/enable port. -void OmxVideoDecodeEngine::ChangePort(OMX_COMMANDTYPE cmd, int port_index) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_, - cmd, port_index, 0); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "SendCommand(OMX_CommandPortDisable) failed"; - client_state_ = kClientError; - return; - } -} - -// Find if omx_buffer exists corresponding to video_frame -OMX_BUFFERHEADERTYPE* OmxVideoDecodeEngine::FindOmxBuffer( - scoped_refptr<VideoFrame> video_frame) { - for (size_t i = 0; i < output_frames_.size(); ++i) { - if (video_frame == output_frames_[i].first) - return output_frames_[i].second; - } - return NULL; -} - -OMX_STATETYPE OmxVideoDecodeEngine::GetComponentState() { - OMX_STATETYPE eState; - OMX_ERRORTYPE eError; - - eError = OMX_GetState(component_handle_, &eState); - if (OMX_ErrorNone != eError) { - LOG(ERROR) << "OMX_GetState failed"; - StopOnError(); - } - - return eState; -} - -// send one output buffer to component -void OmxVideoDecodeEngine::SendOutputBufferToComponent( - OMX_BUFFERHEADERTYPE *omx_buffer) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - if (!CanFillBuffer()) - return; - - // clear EOS flag. - omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; - omx_buffer->nOutputPortIndex = output_port_; - output_buffers_at_component_++; - OMX_ERRORTYPE ret = OMX_FillThisBuffer(component_handle_, omx_buffer); - - if (OMX_ErrorNone != ret) { - LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << ret; - client_state_ = kClientError; - return; - } -} - -// Send state transition command to component. -bool OmxVideoDecodeEngine::TransitionToState(OMX_STATETYPE new_state) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - OMX_ERRORTYPE omxresult = OMX_SendCommand(component_handle_, - OMX_CommandStateSet, - new_state, 0); - if (omxresult != OMX_ErrorNone) { - LOG(ERROR) << "SendCommand(OMX_CommandStateSet) failed"; - client_state_ = kClientError; - return false; - } - - return true; -} - -void OmxVideoDecodeEngine::EmptyBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_GT(input_buffers_at_component_, 0); - - Buffer* stored_buffer = static_cast<Buffer*>(buffer->pAppPrivate); - buffer->pAppPrivate = NULL; - if (client_state_ != kClientFlushing) - FinishEmptyBuffer(stored_buffer); - stored_buffer->Release(); - - // Enqueue the available buffer because the decoder has consumed it. - free_input_buffers_.push(buffer); - input_buffers_at_component_--; - - if (need_free_input_buffers_ && !input_buffers_at_component_) { - FreeInputBuffers(); - return; - } - - // Try to feed more data into the decoder. - EmptyBufferTask(); - - if (client_state_ == kClientFlushing && - InputPortFlushed() && OutputPortFlushed()) - ComponentFlushDone(); -} - -void OmxVideoDecodeEngine::FillBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK_GT(output_buffers_at_component_, 0); - - output_buffers_at_component_--; - - if (need_free_output_buffers_ && !output_buffers_at_component_) { - FreeOutputBuffers(); - return; - } - - PipelineStatistics statistics; - statistics.video_bytes_decoded = buffer->nFilledLen; - - if (!CanAcceptOutput()) { - if (uses_egl_image_) { - scoped_refptr<VideoFrame> frame; - frame = static_cast<VideoFrame*>(buffer->pAppPrivate); - event_handler_->ConsumeVideoFrame(frame, statistics); - output_pending_request_--; - } - return; - } - - // This buffer is received with decoded frame. Enqueue it and make it - // ready to be consumed by reads. - - if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { - output_eos_ = true; - DLOG(INFO) << "Output has EOS"; - } - - FinishFillBuffer(buffer); - - if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { - // Singal end of stream. - scoped_refptr<VideoFrame> frame; - VideoFrame::CreateEmptyFrame(&frame); - event_handler_->ConsumeVideoFrame(frame, statistics); - } - - if (client_state_ == kClientFlushing && - InputPortFlushed() && OutputPortFlushed()) - ComponentFlushDone(); -} - -void OmxVideoDecodeEngine::EventHandlerCompleteTask(OMX_EVENTTYPE event, - OMX_U32 data1, - OMX_U32 data2) { - switch (event) { - case OMX_EventCmdComplete: { - // If the last command was successful, we have completed - // a state transition. So notify that we have done it - // accordingly. - OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(data1); - if (cmd == OMX_CommandPortDisable) { - if (OnPortDisableEventFunc) - (this->*OnPortDisableEventFunc)(static_cast<int>(data2)); - } else if (cmd == OMX_CommandPortEnable) { - if (OnPortEnableEventFunc) - (this->*OnPortEnableEventFunc)(static_cast<int>(data2)); - } else if (cmd == OMX_CommandStateSet) { - (this->*OnStateSetEventFunc)(static_cast<OMX_STATETYPE>(data2)); - } else if (cmd == OMX_CommandFlush) { - (this->*OnFlushEventFunc)(data2); - } else { - LOG(ERROR) << "Unknown command completed\n" << data1; - } - break; - } - case OMX_EventError: - if (OMX_ErrorInvalidState == (OMX_ERRORTYPE)data1) { - // TODO(hclam): what to do here? - } - StopOnError(); - break; - case OMX_EventPortSettingsChanged: - // TODO(wjia): remove this hack when all vendors observe same spec. - if (data1 < OMX_IndexComponentStartUnused) - OnPortSettingsChangedRun(static_cast<int>(data1), - static_cast<OMX_INDEXTYPE>(data2)); - else - OnPortSettingsChangedRun(static_cast<int>(data2), - static_cast<OMX_INDEXTYPE>(data1)); - break; - default: - LOG(ERROR) << "Warning - Unknown event received\n"; - break; - } -} - -// static -OMX_ERRORTYPE OmxVideoDecodeEngine::EventHandler(OMX_HANDLETYPE component, - OMX_PTR priv_data, - OMX_EVENTTYPE event, - OMX_U32 data1, - OMX_U32 data2, - OMX_PTR event_data) { - OmxVideoDecodeEngine* decoder = static_cast<OmxVideoDecodeEngine*>(priv_data); - DCHECK_EQ(component, decoder->component_handle_); - decoder->message_loop_->PostTask(FROM_HERE, - NewRunnableMethod(decoder, - &OmxVideoDecodeEngine::EventHandlerCompleteTask, - event, data1, data2)); - return OMX_ErrorNone; -} - -// static -OMX_ERRORTYPE OmxVideoDecodeEngine::EmptyBufferCallback( - OMX_HANDLETYPE component, - OMX_PTR priv_data, - OMX_BUFFERHEADERTYPE* buffer) { - OmxVideoDecodeEngine* decoder = static_cast<OmxVideoDecodeEngine*>(priv_data); - DCHECK_EQ(component, decoder->component_handle_); - decoder->message_loop_->PostTask(FROM_HERE, - NewRunnableMethod(decoder, - &OmxVideoDecodeEngine::EmptyBufferDoneTask, buffer)); - return OMX_ErrorNone; -} - -// static -OMX_ERRORTYPE OmxVideoDecodeEngine::FillBufferCallback( - OMX_HANDLETYPE component, - OMX_PTR priv_data, - OMX_BUFFERHEADERTYPE* buffer) { - OmxVideoDecodeEngine* decoder = static_cast<OmxVideoDecodeEngine*>(priv_data); - DCHECK_EQ(component, decoder->component_handle_); - decoder->message_loop_->PostTask(FROM_HERE, - NewRunnableMethod(decoder, - &OmxVideoDecodeEngine::FillBufferDoneTask, buffer)); - return OMX_ErrorNone; -} - -} // namespace media - -// Disable refcounting for this object because this object only lives -// on the video decoder thread and there's no need to refcount it. -DISABLE_RUNNABLE_METHOD_REFCOUNT(media::OmxVideoDecodeEngine); diff --git a/media/video/omx_video_decode_engine.h b/media/video/omx_video_decode_engine.h deleted file mode 100644 index e9cc756..0000000 --- a/media/video/omx_video_decode_engine.h +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright (c) 2011 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_VIDEO_OMX_VIDEO_DECODE_ENGINE_H_ -#define MEDIA_VIDEO_OMX_VIDEO_DECODE_ENGINE_H_ - -#include <queue> -#include <utility> -#include <vector> - -#include "base/callback_old.h" -#include "base/memory/scoped_ptr.h" -#include "media/omx/omx_configurator.h" -#include "media/video/video_decode_engine.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 OmxVideoDecodeEngine : public VideoDecodeEngine { - public: - OmxVideoDecodeEngine(); - virtual ~OmxVideoDecodeEngine(); - - // Implementation of the VideoDecodeEngine Interface. - virtual void Initialize(MessageLoop* message_loop, - VideoDecodeEngine::EventHandler* event_handler, - VideoDecodeContext* context, - const VideoDecoderConfig& config); - virtual void ConsumeVideoSample(scoped_refptr<Buffer> buffer); - virtual void ProduceVideoFrame(scoped_refptr<VideoFrame> frame); - virtual void Uninitialize(); - virtual void Flush(); - virtual void Seek(); - - // Subclass can provide a different value. - virtual int current_omx_spec_version() const; - - private: - enum OmxIlState { - kIlNone, - kIlLoaded, - kIlIdle, - kIlExecuting, - kIlPause, - kIlInvalid, - kIlUnknown, - }; - - enum OmxIlClientState { - kClientNotInitialized, - kClientInitializing, - kClientRunning, - kClientStopping, - kClientStopped, - kClientPausing, - kClientFlushing, - kClientError, - }; - - enum OmxIlPortState { - kPortDisabled, - kPortEnabling, - kPortEnabled, - kPortDisabling, - }; - - typedef Callback0::Type Callback; - - // calls into other classes - void FinishEmptyBuffer(scoped_refptr<Buffer> buffer); - void FinishFillBuffer(OMX_BUFFERHEADERTYPE* buffer); - // Helper method to perform tasks when this object is stopped. - void OnStopDone(); - - // Transition method sequence for initialization - bool CreateComponent(); - void DoneSetStateIdle(OMX_STATETYPE state); - void DoneSetStateExecuting(OMX_STATETYPE state); - void OnPortSettingsChangedRun(int port, OMX_INDEXTYPE index); - void OnPortDisableEventRun(int port); - void SetupOutputPort(); - void OnPortEnableEventRun(int port); - - // Transition methods for shutdown - void DeinitFromExecuting(OMX_STATETYPE state); - void DeinitFromIdle(OMX_STATETYPE state); - void DeinitFromLoaded(OMX_STATETYPE state); - void PauseFromExecuting(OMX_STATETYPE state); - void StartFlush(); - void PortFlushDone(int port); - void ComponentFlushDone(); - - void StopOnError(); - - void InitializeTask(); - - // Methods to free input and output buffers. - bool AllocateInputBuffers(); - bool AllocateOutputBuffers(); - void FreeInputBuffers(); - void FreeOutputBuffers(); - void FreeInputQueue(); - - // Helper method to configure port format at LOADED state. - bool ConfigureIOPorts(); - - // Determine whether we can issue fill buffer or empty buffer - // to the decoder based on the current state and port state. - bool CanEmptyBuffer(); - bool CanFillBuffer(); - - // Determine whether we can use |input_queue_| and |output_queue_| - // based on the current state. - bool CanAcceptInput(); - bool CanAcceptOutput(); - - bool InputPortFlushed(); - bool OutputPortFlushed(); - - // Method to send input buffers to component - void EmptyBufferTask(); - - // Method doing initial reads to get bit stream from demuxer. - void InitialReadBuffer(); - - // Method doing initial fills to kick start the decoding process. - void InitialFillBuffer(); - - // helper functions - void ChangePort(OMX_COMMANDTYPE cmd, int port_index); - OMX_BUFFERHEADERTYPE* FindOmxBuffer(scoped_refptr<VideoFrame> video_frame); - OMX_STATETYPE GetComponentState(); - void SendOutputBufferToComponent(OMX_BUFFERHEADERTYPE *omx_buffer); - bool TransitionToState(OMX_STATETYPE new_state); - virtual VideoFrame::Format GetSurfaceFormat() const; - - // Method to handle events - void EventHandlerCompleteTask(OMX_EVENTTYPE event, - OMX_U32 data1, - OMX_U32 data2); - - // Method to receive buffers from component's input port - void EmptyBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer); - - // Method to receive buffers from component's output port - void FillBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer); - - // The following three methods are static callback methods - // for the OMX component. When these callbacks are received, the - // call is delegated to the three internal methods above. - static OMX_ERRORTYPE EventHandler(OMX_HANDLETYPE component, - OMX_PTR priv_data, - OMX_EVENTTYPE event, - OMX_U32 data1, OMX_U32 data2, - OMX_PTR event_data); - - static OMX_ERRORTYPE EmptyBufferCallback(OMX_HANDLETYPE component, - OMX_PTR priv_data, - OMX_BUFFERHEADERTYPE* buffer); - - static OMX_ERRORTYPE FillBufferCallback(OMX_HANDLETYPE component, - OMX_PTR priv_data, - OMX_BUFFERHEADERTYPE* buffer); - - // Member function pointers to respond to events - void (OmxVideoDecodeEngine::*OnPortDisableEventFunc)(int port); - void (OmxVideoDecodeEngine::*OnPortEnableEventFunc)(int port); - void (OmxVideoDecodeEngine::*OnStateSetEventFunc)(OMX_STATETYPE state); - void (OmxVideoDecodeEngine::*OnFlushEventFunc)(int port); - - // Helper function - scoped_refptr<VideoFrame> CreateOmxBufferVideoFrame( - OMX_BUFFERHEADERTYPE* omx_buffer); - - int width_; - int height_; - - MessageLoop* message_loop_; - - std::vector<OMX_BUFFERHEADERTYPE*> input_buffers_; - int input_buffer_count_; - int input_buffer_size_; - int input_port_; - int input_buffers_at_component_; - int input_pending_request_; - bool input_queue_has_eos_; - bool input_has_fed_eos_; - bool input_port_flushed_; - - int output_buffer_count_; - int output_buffer_size_; - int output_port_; - int output_buffers_at_component_; - int output_pending_request_; - bool output_eos_; - bool output_port_flushed_; - bool uses_egl_image_; - base::TimeDelta last_pts_; - - // |il_state_| records the current component state. During state transition - // |expected_il_state_| is the next state that the component will transition - // to. After a state transition is completed, |il_state_| equals - // |expected_il_state_|. Inequality can be used to detect a state transition. - // These two members are read and written only on |message_loop_|. - OmxIlState il_state_; - OmxIlState expected_il_state_; - OmxIlClientState client_state_; - - OMX_HANDLETYPE component_handle_; - scoped_ptr<media::OmxConfigurator> configurator_; - - // Free input OpenMAX buffers that can be used to take input bitstream from - // demuxer. - std::queue<OMX_BUFFERHEADERTYPE*> free_input_buffers_; - - // Available input OpenMAX buffers that we can use to issue - // OMX_EmptyThisBuffer() call. - std::queue<OMX_BUFFERHEADERTYPE*> available_input_buffers_; - - // flag for freeing input/output buffers - bool need_free_input_buffers_; - bool need_free_output_buffers_; - - // for calling flush callback only once. - bool flush_pending_; - - // For output buffer recycling cases. - typedef std::pair<scoped_refptr<VideoFrame>, - OMX_BUFFERHEADERTYPE*> OutputFrame; - std::vector<OutputFrame> output_frames_; - bool output_frames_allocated_; - - // port related - bool need_setup_output_port_; - OmxIlPortState output_port_state_; - VideoDecodeEngine::EventHandler* event_handler_; - - DISALLOW_COPY_AND_ASSIGN(OmxVideoDecodeEngine); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_OMX_VIDEO_DECODE_ENGINE_H_ |