Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Unified Diff: content/common/gpu/media/omx_video_decode_accelerator.cc

Issue 21584002: Delete dead code: OmxVideoDecodeAccelerator is unused. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Re-removing both OWNERS & README Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/media/omx_video_decode_accelerator.cc
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.cc b/content/common/gpu/media/omx_video_decode_accelerator.cc
deleted file mode 100644
index b110b7fbc3072fd17a7d81ea506c000bb235ef79..0000000000000000000000000000000000000000
--- a/content/common/gpu/media/omx_video_decode_accelerator.cc
+++ /dev/null
@@ -1,1259 +0,0 @@
-// Copyright (c) 2012 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 "content/common/gpu/media/omx_video_decode_accelerator.h"
-
-#include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h"
-#include "media/base/bitstream_buffer.h"
-#include "media/video/picture.h"
-
-namespace content {
-
-// Helper typedef for input buffers. This is used as the pAppPrivate field of
-// OMX_BUFFERHEADERTYPEs of input buffers, to point to the data associated with
-// them.
-typedef std::pair<scoped_ptr<base::SharedMemory>, int32> SharedMemoryAndId;
-
-enum { kNumPictureBuffers = 8 };
-
-// Delay between polling for texture sync status. 5ms feels like a good
-// compromise, allowing some decoding ahead (up to 3 frames/vsync) to compensate
-// for more difficult frames.
-enum { kSyncPollDelayMs = 5 };
-
-void* omx_handle = NULL;
-
-typedef OMX_ERRORTYPE (*OMXInit)();
-typedef OMX_ERRORTYPE (*OMXGetHandle)(
- OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*);
-typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**);
-typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE);
-typedef OMX_ERRORTYPE (*OMXDeinit)();
-
-OMXInit omx_init = NULL;
-OMXGetHandle omx_gethandle = NULL;
-OMXGetComponentsOfRole omx_get_components_of_role = NULL;
-OMXFreeHandle omx_free_handle = NULL;
-OMXDeinit omx_deinit = NULL;
-
-// Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values.
-static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) {
- switch (profile) {
- case media::H264PROFILE_BASELINE:
- return OMX_VIDEO_AVCProfileBaseline;
- case media::H264PROFILE_MAIN:
- return OMX_VIDEO_AVCProfileMain;
- case media::H264PROFILE_EXTENDED:
- return OMX_VIDEO_AVCProfileExtended;
- case media::H264PROFILE_HIGH:
- return OMX_VIDEO_AVCProfileHigh;
- case media::H264PROFILE_HIGH10PROFILE:
- return OMX_VIDEO_AVCProfileHigh10;
- case media::H264PROFILE_HIGH422PROFILE:
- return OMX_VIDEO_AVCProfileHigh422;
- case media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
- return OMX_VIDEO_AVCProfileHigh444;
- // Below enums don't have equivalent enum in Openmax.
- case media::H264PROFILE_SCALABLEBASELINE:
- case media::H264PROFILE_SCALABLEHIGH:
- case media::H264PROFILE_STEREOHIGH:
- case media::H264PROFILE_MULTIVIEWHIGH:
- // Nvidia OMX video decoder requires the same resources (as that of the
- // High profile) in every profile higher to the Main profile.
- return OMX_VIDEO_AVCProfileHigh444;
- default:
- NOTREACHED();
- return OMX_VIDEO_AVCProfileMax;
- }
-}
-
-// Helper macros for dealing with failure. If |result| evaluates false, emit
-// |log| to ERROR, register |error| with the decoder, and return |ret_val|
-// (which may be omitted for functions that return void).
-#define RETURN_ON_FAILURE(result, log, error, ret_val) \
- do { \
- if (!(result)) { \
- DLOG(ERROR) << log; \
- StopOnError(error); \
- return ret_val; \
- } \
- } while (0)
-
-// OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone.
-#define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \
- RETURN_ON_FAILURE( \
- ((omx_result) == OMX_ErrorNone), \
- log << ", OMX result: 0x" << std::hex << omx_result, \
- error, ret_val)
-
-// static
-bool OmxVideoDecodeAccelerator::pre_sandbox_init_done_ = false;
-
-class OmxVideoDecodeAccelerator::PictureSyncObject {
- public:
- // Create a sync object and insert into the GPU command stream.
- PictureSyncObject(EGLDisplay egl_display);
- ~PictureSyncObject();
-
- bool IsSynced();
-
- private:
- EGLSyncKHR egl_sync_obj_;
- EGLDisplay egl_display_;
-};
-
-OmxVideoDecodeAccelerator::PictureSyncObject::PictureSyncObject(
- EGLDisplay egl_display)
- : egl_display_(egl_display) {
- DCHECK(egl_display_ != EGL_NO_DISPLAY);
-
- egl_sync_obj_ = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL);
- DCHECK_NE(egl_sync_obj_, EGL_NO_SYNC_KHR);
-}
-
-OmxVideoDecodeAccelerator::PictureSyncObject::~PictureSyncObject() {
- eglDestroySyncKHR(egl_display_, egl_sync_obj_);
-}
-
-bool OmxVideoDecodeAccelerator::PictureSyncObject::IsSynced() {
- EGLint value = EGL_UNSIGNALED_KHR;
- EGLBoolean ret = eglGetSyncAttribKHR(
- egl_display_, egl_sync_obj_, EGL_SYNC_STATUS_KHR, &value);
- DCHECK(ret) << "Failed getting sync object state.";
-
- return value == EGL_SIGNALED_KHR;
-}
-
-OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
- EGLDisplay egl_display, EGLContext egl_context,
- media::VideoDecodeAccelerator::Client* client,
- const base::Callback<bool(void)>& make_context_current)
- : message_loop_(base::MessageLoop::current()),
- component_handle_(NULL),
- weak_this_(base::AsWeakPtr(this)),
- init_begun_(false),
- client_state_(OMX_StateMax),
- current_state_change_(NO_TRANSITION),
- input_buffer_count_(0),
- input_buffer_size_(0),
- input_port_(0),
- input_buffers_at_component_(0),
- output_port_(0),
- output_buffers_at_component_(0),
- egl_display_(egl_display),
- egl_context_(egl_context),
- make_context_current_(make_context_current),
- client_ptr_factory_(client),
- client_(client_ptr_factory_.GetWeakPtr()),
- codec_(UNKNOWN),
- h264_profile_(OMX_VIDEO_AVCProfileMax),
- component_name_is_nvidia_(false) {
- static bool omx_functions_initialized = PostSandboxInitialization();
- RETURN_ON_FAILURE(omx_functions_initialized,
- "Failed to load openmax library", PLATFORM_FAILURE,);
- RETURN_ON_OMX_FAILURE(omx_init(), "Failed to init OpenMAX core",
- PLATFORM_FAILURE,);
-}
-
-OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK(free_input_buffers_.empty());
- DCHECK_EQ(0, input_buffers_at_component_);
- DCHECK_EQ(0, output_buffers_at_component_);
- DCHECK(pictures_.empty());
-}
-
-// This is to initialize the OMX data structures to default values.
-template <typename T>
-static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) {
- memset(param, 0, sizeof(T));
- param->nVersion.nVersion = 0x00000101;
- param->nSize = sizeof(T);
-}
-
-bool OmxVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) {
- codec_ = H264;
- h264_profile_ = MapH264ProfileToOMXAVCProfile(profile);
- RETURN_ON_FAILURE(h264_profile_ != OMX_VIDEO_AVCProfileMax,
- "Unexpected profile", INVALID_ARGUMENT, false);
- } else if (profile == media::VP8PROFILE_MAIN) {
- codec_ = VP8;
- } else {
- RETURN_ON_FAILURE(false, "Unsupported profile: " << profile,
- INVALID_ARGUMENT, false);
- }
-
- // We need the context to be initialized to query extensions.
- RETURN_ON_FAILURE(make_context_current_.Run(),
- "Failed make context current",
- PLATFORM_FAILURE,
- false);
- RETURN_ON_FAILURE(gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync,
- "Platform does not support EGL_KHR_fence_sync",
- PLATFORM_FAILURE,
- false);
-
- if (!CreateComponent()) // Does its own RETURN_ON_FAILURE dances.
- return false;
-
- DCHECK_EQ(current_state_change_, NO_TRANSITION);
- current_state_change_ = INITIALIZING;
- BeginTransitionToState(OMX_StateIdle);
-
- if (!AllocateInputBuffers()) // Does its own RETURN_ON_FAILURE dances.
- return false;
- if (!AllocateFakeOutputBuffers()) // Does its own RETURN_ON_FAILURE dances.
- return false;
-
- init_begun_ = true;
- return true;
-}
-
-bool OmxVideoDecodeAccelerator::CreateComponent() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- OMX_CALLBACKTYPE omx_accelerator_callbacks = {
- &OmxVideoDecodeAccelerator::EventHandler,
- &OmxVideoDecodeAccelerator::EmptyBufferCallback,
- &OmxVideoDecodeAccelerator::FillBufferCallback
- };
-
- // TODO(vhiremath@nvidia.com) Get this role_name from the configs
- // For now hard-coding.
- OMX_STRING role_name = codec_ == H264 ?
- const_cast<OMX_STRING>("video_decoder.avc") :
- const_cast<OMX_STRING>("video_decoder.vpx");
- // Get the first component for this role and set the role on it.
- OMX_U32 num_components = 1;
- std::string component(OMX_MAX_STRINGNAME_SIZE, '\0');
- char* component_as_array = string_as_array(&component);
- OMX_ERRORTYPE result = omx_get_components_of_role(
- role_name, &num_components,
- reinterpret_cast<OMX_U8**>(&component_as_array));
- RETURN_ON_OMX_FAILURE(result, "Unsupported role: " << role_name,
- PLATFORM_FAILURE, false);
- RETURN_ON_FAILURE(num_components == 1, "No components for: " << role_name,
- PLATFORM_FAILURE, false);
- component_name_is_nvidia_ = StartsWithASCII(
- component, "OMX.Nvidia", true);
-
- // Get the handle to the component.
- result = omx_gethandle(
- &component_handle_,
- reinterpret_cast<OMX_STRING>(string_as_array(&component)),
- this, &omx_accelerator_callbacks);
- RETURN_ON_OMX_FAILURE(result,
- "Failed to OMX_GetHandle on: " << component,
- PLATFORM_FAILURE, false);
- client_state_ = OMX_StateLoaded;
-
- texture_to_egl_image_translator_.reset(new Gles2TextureToEglImageTranslator(
- StartsWithASCII(component, "OMX.SEC.", true)));
-
- // 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;
- InitParam(*this, &port_param);
- result = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit,
- &port_param);
- RETURN_ON_FAILURE(result == OMX_ErrorNone && port_param.nPorts == 2,
- "Failed to get Port Param: " << result << ", "
- << port_param.nPorts,
- PLATFORM_FAILURE, false);
- input_port_ = port_param.nStartPortNumber;
- output_port_ = input_port_ + 1;
-
- // Set role for the component because components can have multiple roles.
- OMX_PARAM_COMPONENTROLETYPE role_type;
- InitParam(*this, &role_type);
- base::strlcpy(reinterpret_cast<char*>(role_type.cRole),
- role_name,
- OMX_MAX_STRINGNAME_SIZE);
-
- result = OMX_SetParameter(component_handle_,
- OMX_IndexParamStandardComponentRole,
- &role_type);
- RETURN_ON_OMX_FAILURE(result, "Failed to Set Role",
- PLATFORM_FAILURE, false);
-
- // Populate input-buffer-related members based on input port data.
- OMX_PARAM_PORTDEFINITIONTYPE port_format;
- InitParam(*this, &port_format);
- port_format.nPortIndex = input_port_;
- result = OMX_GetParameter(component_handle_,
- OMX_IndexParamPortDefinition,
- &port_format);
- RETURN_ON_OMX_FAILURE(result,
- "GetParameter(OMX_IndexParamPortDefinition) failed",
- PLATFORM_FAILURE, false);
- RETURN_ON_FAILURE(OMX_DirInput == port_format.eDir, "Expected input port",
- PLATFORM_FAILURE, false);
-
- input_buffer_count_ = port_format.nBufferCountActual;
- input_buffer_size_ = port_format.nBufferSize;
-
- // Verify output port conforms to our expectations.
- InitParam(*this, &port_format);
- port_format.nPortIndex = output_port_;
- result = OMX_GetParameter(component_handle_,
- OMX_IndexParamPortDefinition,
- &port_format);
- RETURN_ON_OMX_FAILURE(result,
- "GetParameter(OMX_IndexParamPortDefinition) failed",
- PLATFORM_FAILURE, false);
- RETURN_ON_FAILURE(OMX_DirOutput == port_format.eDir, "Expect Output Port",
- PLATFORM_FAILURE, false);
-
- // Set output port parameters.
- port_format.nBufferCountActual = kNumPictureBuffers;
- // Force an OMX_EventPortSettingsChanged event to be sent once we know the
- // stream's real dimensions (which can only happen once some Decode() work has
- // been done).
- port_format.format.video.nFrameWidth = -1;
- port_format.format.video.nFrameHeight = -1;
- result = OMX_SetParameter(component_handle_,
- OMX_IndexParamPortDefinition,
- &port_format);
- RETURN_ON_OMX_FAILURE(result,
- "SetParameter(OMX_IndexParamPortDefinition) failed",
- PLATFORM_FAILURE, false);
- return true;
-}
-
-void OmxVideoDecodeAccelerator::Decode(
- const media::BitstreamBuffer& bitstream_buffer) {
- TRACE_EVENT1("Video Decoder", "OVDA::Decode",
- "Buffer id", bitstream_buffer.id());
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- if (current_state_change_ == RESETTING ||
- !queued_bitstream_buffers_.empty() ||
- free_input_buffers_.empty()) {
- queued_bitstream_buffers_.push_back(bitstream_buffer);
- return;
- }
-
- RETURN_ON_FAILURE((current_state_change_ == NO_TRANSITION ||
- current_state_change_ == FLUSHING) &&
- (client_state_ == OMX_StateIdle ||
- client_state_ == OMX_StateExecuting),
- "Call to Decode() during invalid state or transition: "
- << current_state_change_ << ", " << client_state_,
- ILLEGAL_STATE,);
-
- OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front();
- free_input_buffers_.pop();
-
- if (bitstream_buffer.id() == -1 && bitstream_buffer.size() == 0) {
- // Cook up an empty buffer w/ EOS set and feed it to OMX.
- omx_buffer->nFilledLen = 0;
- omx_buffer->nAllocLen = omx_buffer->nFilledLen;
- omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;
- omx_buffer->nTimeStamp = -2;
- OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer);
- RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed",
- PLATFORM_FAILURE,);
- input_buffers_at_component_++;
- return;
- }
-
- // Setup |omx_buffer|.
- scoped_ptr<base::SharedMemory> shm(
- new base::SharedMemory(bitstream_buffer.handle(), true));
- RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()),
- "Failed to SharedMemory::Map()", UNREADABLE_INPUT,);
-
- SharedMemoryAndId* input_buffer_details = new SharedMemoryAndId();
- input_buffer_details->first.reset(shm.release());
- input_buffer_details->second = bitstream_buffer.id();
- DCHECK(!omx_buffer->pAppPrivate);
- omx_buffer->pAppPrivate = input_buffer_details;
- omx_buffer->pBuffer =
- static_cast<OMX_U8*>(input_buffer_details->first->memory());
- omx_buffer->nFilledLen = bitstream_buffer.size();
- omx_buffer->nAllocLen = omx_buffer->nFilledLen;
- omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
- // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to
- // the output buffer's nTimeStamp field, so we can report it back to the
- // client in PictureReady().
- omx_buffer->nTimeStamp = bitstream_buffer.id();
-
- // Give this buffer to OMX.
- OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer);
- RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed",
- PLATFORM_FAILURE,);
- input_buffers_at_component_++;
-}
-
-void OmxVideoDecodeAccelerator::AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- // If we are resetting/destroying/erroring, don't bother, as
- // OMX_FillThisBuffer will fail anyway. In case we're in the middle of
- // closing, this will put the Accelerator in ERRORING mode, which has the
- // unwanted side effect of not going through the OMX_FreeBuffers path and
- // leaks memory.
- if (current_state_change_ == RESETTING ||
- current_state_change_ == DESTROYING ||
- current_state_change_ == ERRORING)
- return;
-
- RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,);
- RETURN_ON_FAILURE((kNumPictureBuffers == buffers.size()),
- "Failed to provide requested picture buffers. (Got " << buffers.size() <<
- ", requested " << kNumPictureBuffers << ")", INVALID_ARGUMENT,);
-
- DCHECK_EQ(output_buffers_at_component_, 0);
- DCHECK_EQ(fake_output_buffers_.size(), 0U);
- DCHECK_EQ(pictures_.size(), 0U);
-
- if (!make_context_current_.Run())
- return;
-
- for (size_t i = 0; i < buffers.size(); ++i) {
- EGLImageKHR egl_image =
- texture_to_egl_image_translator_->TranslateToEglImage(
- egl_display_, egl_context_,
- buffers[i].texture_id(),
- last_requested_picture_buffer_dimensions_);
- CHECK(pictures_.insert(std::make_pair(
- buffers[i].id(), OutputPicture(buffers[i], NULL, egl_image))).second);
- }
-
- // These do their own RETURN_ON_FAILURE dances.
- if (!AllocateOutputBuffers())
- return;
- if (!SendCommandToPort(OMX_CommandPortEnable, output_port_))
- return;
-}
-
-void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer",
- "Picture id", picture_buffer_id);
- scoped_ptr<PictureSyncObject> egl_sync_obj(
- new PictureSyncObject(egl_display_));
-
- // Start checking sync status periodically.
- CheckPictureStatus(picture_buffer_id, egl_sync_obj.Pass());
-}
-
-void OmxVideoDecodeAccelerator::CheckPictureStatus(
- int32 picture_buffer_id,
- scoped_ptr<PictureSyncObject> egl_sync_obj) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- // It's possible for this task to never run if the message loop is
- // stopped. In that case we may never call QueuePictureBuffer().
- // This is fine though, because all pictures, irrespective of their state,
- // are in pictures_ map and that's what will be used to do the clean up.
- if (!egl_sync_obj->IsSynced()) {
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::CheckPictureStatus, weak_this_,
- picture_buffer_id, base::Passed(&egl_sync_obj)),
- base::TimeDelta::FromMilliseconds(kSyncPollDelayMs));
- return;
- }
-
- // Synced successfully. Queue the buffer for reuse.
- QueuePictureBuffer(picture_buffer_id);
-}
-
-void OmxVideoDecodeAccelerator::QueuePictureBuffer(int32 picture_buffer_id) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- // During port-flushing, do not call OMX FillThisBuffer.
- if (current_state_change_ == RESETTING) {
- queued_picture_buffer_ids_.push_back(picture_buffer_id);
- return;
- }
-
- // We might have started destroying while waiting for the picture. It's safe
- // to drop it here, because we will free all the pictures regardless of their
- // state using the pictures_ map.
- if (!CanFillBuffer())
- return;
-
- OutputPictureById::iterator it = pictures_.find(picture_buffer_id);
- RETURN_ON_FAILURE(it != pictures_.end(),
- "Missing picture buffer id: " << picture_buffer_id,
- INVALID_ARGUMENT,);
- OutputPicture& output_picture = it->second;
-
- ++output_buffers_at_component_;
- OMX_ERRORTYPE result =
- OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header);
- RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed",
- PLATFORM_FAILURE,);
-}
-
-void OmxVideoDecodeAccelerator::Flush() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK_EQ(current_state_change_, NO_TRANSITION);
- DCHECK_EQ(client_state_, OMX_StateExecuting);
- current_state_change_ = FLUSHING;
-
- Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0));
-}
-
-void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK_EQ(client_state_, OMX_StateExecuting);
- current_state_change_ = NO_TRANSITION;
- if (client_)
- client_->NotifyFlushDone();
-}
-
-void OmxVideoDecodeAccelerator::FlushIOPorts() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- // Flush input port first.
- if (!SendCommandToPort(OMX_CommandFlush, input_port_))
- return;
-}
-
-void OmxVideoDecodeAccelerator::InputPortFlushDone() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK_EQ(input_buffers_at_component_, 0);
- if (!SendCommandToPort(OMX_CommandFlush, output_port_))
- return;
-}
-
-void OmxVideoDecodeAccelerator::OutputPortFlushDone() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK_EQ(output_buffers_at_component_, 0);
- BeginTransitionToState(OMX_StateExecuting);
-}
-
-void OmxVideoDecodeAccelerator::Reset() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK_EQ(current_state_change_, NO_TRANSITION);
- DCHECK_EQ(client_state_, OMX_StateExecuting);
- current_state_change_ = RESETTING;
- BeginTransitionToState(OMX_StatePause);
-}
-
-void OmxVideoDecodeAccelerator::Destroy() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- scoped_ptr<OmxVideoDecodeAccelerator> deleter(this);
- client_ptr_factory_.InvalidateWeakPtrs();
-
- if (current_state_change_ == ERRORING ||
- current_state_change_ == DESTROYING) {
- return;
- }
-
- DCHECK(current_state_change_ == NO_TRANSITION ||
- current_state_change_ == FLUSHING ||
- current_state_change_ == RESETTING) << current_state_change_;
-
- // If we were never initializeed there's no teardown to do.
- if (client_state_ == OMX_StateMax)
- return;
- // If we can already call OMX_FreeHandle, simply do so.
- if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) {
- ShutdownComponent();
- return;
- }
- DCHECK(client_state_ == OMX_StateExecuting ||
- client_state_ == OMX_StateIdle ||
- client_state_ == OMX_StatePause);
- current_state_change_ = DESTROYING;
- BeginTransitionToState(OMX_StateIdle);
- BusyLoopInDestroying(deleter.Pass());
-}
-
-void OmxVideoDecodeAccelerator::BeginTransitionToState(
- OMX_STATETYPE new_state) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- if (new_state != OMX_StateInvalid)
- DCHECK_NE(current_state_change_, NO_TRANSITION);
- if (current_state_change_ == ERRORING)
- return;
- OMX_ERRORTYPE result = OMX_SendCommand(
- component_handle_, OMX_CommandStateSet, new_state, 0);
- RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed",
- PLATFORM_FAILURE,);
-}
-
-void OmxVideoDecodeAccelerator::OnReachedIdleInInitializing() {
- DCHECK_EQ(client_state_, OMX_StateLoaded);
- client_state_ = OMX_StateIdle;
- // Query the resources with the component.
- if (component_name_is_nvidia_) {
- OMX_INDEXTYPE extension_index;
- OMX_ERRORTYPE result = OMX_GetExtensionIndex(
- component_handle_,
- const_cast<char*>("OMX.Nvidia.index.config.checkresources"),
- &extension_index);
- RETURN_ON_OMX_FAILURE(result,
- "Failed to get the extension",
- PLATFORM_FAILURE,);
- OMX_VIDEO_PARAM_PROFILELEVELTYPE video_profile_level;
- InitParam(*this, &video_profile_level);
- DCHECK_EQ(codec_, H264);
- video_profile_level.eProfile = h264_profile_;
- result = OMX_SetConfig(component_handle_, extension_index,
- &video_profile_level);
- RETURN_ON_OMX_FAILURE(result,
- "Resource Allocation failed",
- PLATFORM_FAILURE,);
-
- // The OMX spec doesn't say whether (0,0) is bottom-left or top-left, but
- // NVIDIA OMX implementation used with this class chooses the opposite
- // of other APIs used for HW decode (DXVA, OS/X, VAAPI). So we request
- // a mirror here to avoid having to track Y-orientation throughout the
- // stack (particularly unattractive because this is exposed to ppapi
- // plugin authors and NaCl programs).
- OMX_CONFIG_MIRRORTYPE mirror_config;
- InitParam(*this, &mirror_config);
- result = OMX_GetConfig(component_handle_,
- OMX_IndexConfigCommonMirror, &mirror_config);
- RETURN_ON_OMX_FAILURE(result, "Failed to get mirror", PLATFORM_FAILURE,);
- mirror_config.eMirror = OMX_MirrorVertical;
- result = OMX_SetConfig(component_handle_,
- OMX_IndexConfigCommonMirror, &mirror_config);
- RETURN_ON_OMX_FAILURE(result, "Failed to set mirror", PLATFORM_FAILURE,);
- }
- BeginTransitionToState(OMX_StateExecuting);
-}
-
-void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() {
- DCHECK_EQ(client_state_, OMX_StateIdle);
- client_state_ = OMX_StateExecuting;
- current_state_change_ = NO_TRANSITION;
-
- // Request filling of our fake buffers to trigger decode processing. In
- // reality as soon as any data is decoded these will get dismissed due to
- // dimension mismatch.
- for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it =
- fake_output_buffers_.begin();
- it != fake_output_buffers_.end(); ++it) {
- OMX_BUFFERHEADERTYPE* buffer = *it;
- OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer);
- RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer()", PLATFORM_FAILURE,);
- ++output_buffers_at_component_;
- }
-
- if (client_)
- client_->NotifyInitializeDone();
-}
-
-void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() {
- DCHECK_EQ(client_state_, OMX_StateExecuting);
- client_state_ = OMX_StatePause;
- FlushIOPorts();
-}
-
-void OmxVideoDecodeAccelerator::DecodeQueuedBitstreamBuffers() {
- BitstreamBufferList buffers;
- buffers.swap(queued_bitstream_buffers_);
- if (current_state_change_ == DESTROYING ||
- current_state_change_ == ERRORING) {
- return;
- }
- for (size_t i = 0; i < buffers.size(); ++i)
- Decode(buffers[i]);
-}
-
-void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() {
- DCHECK_EQ(client_state_, OMX_StatePause);
- client_state_ = OMX_StateExecuting;
- current_state_change_ = NO_TRANSITION;
- if (!client_)
- return;
-
- // Drain queues of input & output buffers held during the reset.
- DecodeQueuedBitstreamBuffers();
- for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i)
- ReusePictureBuffer(queued_picture_buffer_ids_[i]);
- queued_picture_buffer_ids_.clear();
-
- client_->NotifyResetDone();
-}
-
-// Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients
-// enjoy the fire-and-forget nature of a synchronous Destroy() call that
-// ensures no further callbacks are made. Since the interface between OMX
-// callbacks and this class is a MessageLoop, we need to ensure the loop
-// outlives the shutdown dance, even during process shutdown. We do this by
-// repeatedly enqueuing a no-op task until shutdown is complete, since
-// MessageLoop's shutdown drains pending tasks.
-void OmxVideoDecodeAccelerator::BusyLoopInDestroying(
- scoped_ptr<OmxVideoDecodeAccelerator> self) {
- if (!component_handle_) return;
- // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed
- // tasks. Instead we sleep for 5ms. Really.
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
- base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::BusyLoopInDestroying,
- base::Unretained(this), base::Passed(&self)));
-}
-
-void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() {
- DCHECK(client_state_ == OMX_StateExecuting ||
- client_state_ == OMX_StateIdle ||
- client_state_ == OMX_StatePause);
- client_state_ = OMX_StateIdle;
-
- // Note that during the Executing -> Idle transition, the OMX spec guarantees
- // buffers have been returned to the client, so we don't need to do an
- // explicit FlushIOPorts().
-
- BeginTransitionToState(OMX_StateLoaded);
-
- FreeOMXBuffers();
-}
-
-void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() {
- DCHECK_EQ(client_state_, OMX_StateIdle);
- client_state_ = OMX_StateLoaded;
- current_state_change_ = NO_TRANSITION;
- ShutdownComponent();
-}
-
-void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() {
- client_state_ = OMX_StateInvalid;
- FreeOMXBuffers();
- ShutdownComponent();
-}
-
-void OmxVideoDecodeAccelerator::ShutdownComponent() {
- OMX_ERRORTYPE result = omx_free_handle(component_handle_);
- if (result != OMX_ErrorNone)
- DLOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result;
- client_state_ = OMX_StateMax;
- omx_deinit();
- // Allow BusyLoopInDestroying to exit and delete |this|.
- component_handle_ = NULL;
-}
-
-void OmxVideoDecodeAccelerator::StopOnError(
- media::VideoDecodeAccelerator::Error error) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- if (current_state_change_ == ERRORING)
- return;
-
- if (client_ && init_begun_)
- client_->NotifyError(error);
- client_ptr_factory_.InvalidateWeakPtrs();
-
- if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax)
- return;
-
- BeginTransitionToState(OMX_StateInvalid);
- current_state_change_ = ERRORING;
-}
-
-bool OmxVideoDecodeAccelerator::AllocateInputBuffers() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- for (int i = 0; i < input_buffer_count_; ++i) {
- OMX_BUFFERHEADERTYPE* buffer;
- // While registering the buffer header we use fake buffer information
- // (length 0, at memory address 0x1) to fake out the "safety" check in
- // OMX_UseBuffer. When it comes time to actually use this header in Decode
- // we set these fields to their real values (for the duration of that
- // Decode).
- OMX_ERRORTYPE result =
- OMX_UseBuffer(component_handle_, &buffer, input_port_,
- NULL, /* pAppPrivate gets set in Decode(). */
- 0, reinterpret_cast<OMX_U8*>(0x1));
- RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer() Input buffer error",
- PLATFORM_FAILURE, false);
- buffer->nInputPortIndex = input_port_;
- buffer->nOffset = 0;
- buffer->nFlags = 0;
- free_input_buffers_.push(buffer);
- }
- return true;
-}
-
-bool OmxVideoDecodeAccelerator::AllocateFakeOutputBuffers() {
- // Fill the component with fake output buffers.
- for (unsigned int i = 0; i < kNumPictureBuffers; ++i) {
- OMX_BUFFERHEADERTYPE* buffer;
- OMX_ERRORTYPE result;
- result = OMX_AllocateBuffer(component_handle_, &buffer, output_port_,
- NULL, 0);
- RETURN_ON_OMX_FAILURE(result, "OMX_AllocateBuffer failed",
- PLATFORM_FAILURE, false);
- buffer->pAppPrivate = NULL;
- buffer->nTimeStamp = -1;
- buffer->nOutputPortIndex = output_port_;
- CHECK(fake_output_buffers_.insert(buffer).second);
- }
- return true;
-}
-
-bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- DCHECK(!pictures_.empty());
- for (OutputPictureById::iterator it = pictures_.begin();
- it != pictures_.end(); ++it) {
- media::PictureBuffer& picture_buffer = it->second.picture_buffer;
- OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header;
- DCHECK(!*omx_buffer);
- OMX_ERRORTYPE result = OMX_UseEGLImage(
- component_handle_, omx_buffer, output_port_, &picture_buffer,
- it->second.egl_image);
- RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage", PLATFORM_FAILURE, false);
- // Here we set a garbage bitstream buffer id, and then overwrite it before
- // passing to PictureReady.
- int garbage_bitstream_buffer_id = -1;
- (*omx_buffer)->pAppPrivate =
- new media::Picture(picture_buffer.id(), garbage_bitstream_buffer_id);
- }
- return true;
-}
-
-void OmxVideoDecodeAccelerator::FreeOMXBuffers() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- bool failure_seen = false;
- while (!free_input_buffers_.empty()) {
- OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front();
- free_input_buffers_.pop();
- OMX_ERRORTYPE result =
- OMX_FreeBuffer(component_handle_, input_port_, omx_buffer);
- if (result != OMX_ErrorNone) {
- DLOG(ERROR) << "OMX_FreeBuffer failed: 0x" << std::hex << result;
- failure_seen = true;
- }
- }
- for (OutputPictureById::iterator it = pictures_.begin();
- it != pictures_.end(); ++it) {
- OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header;
- DCHECK(omx_buffer);
- delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate);
- OMX_ERRORTYPE result =
- OMX_FreeBuffer(component_handle_, output_port_, omx_buffer);
- if (result != OMX_ErrorNone) {
- DLOG(ERROR) << "OMX_FreeBuffer failed: 0x" << std::hex << result;
- failure_seen = true;
- }
- texture_to_egl_image_translator_->DestroyEglImage(egl_display_,
- it->second.egl_image);
- if (client_)
- client_->DismissPictureBuffer(it->first);
- }
- pictures_.clear();
-
- // Delete pending fake_output_buffers_
- for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it =
- fake_output_buffers_.begin();
- it != fake_output_buffers_.end(); ++it) {
- OMX_BUFFERHEADERTYPE* buffer = *it;
- OMX_ERRORTYPE result =
- OMX_FreeBuffer(component_handle_, output_port_, buffer);
- if (result != OMX_ErrorNone) {
- DLOG(ERROR) << "OMX_FreeBuffer failed: 0x" << std::hex << result;
- failure_seen = true;
- }
- }
- fake_output_buffers_.clear();
-
- // Dequeue pending queued_picture_buffer_ids_
- if (client_) {
- for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i)
- client_->DismissPictureBuffer(queued_picture_buffer_ids_[i]);
- }
- queued_picture_buffer_ids_.clear();
-
- RETURN_ON_FAILURE(!failure_seen, "OMX_FreeBuffer", PLATFORM_FAILURE,);
-}
-
-void OmxVideoDecodeAccelerator::OnOutputPortDisabled() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- OMX_PARAM_PORTDEFINITIONTYPE port_format;
- InitParam(*this, &port_format);
- port_format.nPortIndex = output_port_;
- OMX_ERRORTYPE result = OMX_GetParameter(
- component_handle_, OMX_IndexParamPortDefinition, &port_format);
- RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", PLATFORM_FAILURE,);
- DCHECK_LE(port_format.nBufferCountMin, kNumPictureBuffers);
-
- // TODO(fischman): to support mid-stream resize, need to free/dismiss any
- // |pictures_| we already have. Make sure that the shutdown-path agrees with
- // this (there's already freeing logic there, which should not be duplicated).
-
- // Request picture buffers to be handed to the component.
- // ProvidePictureBuffers() will trigger AssignPictureBuffers, which ultimately
- // assigns the textures to the component and re-enables the port.
- const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video;
- last_requested_picture_buffer_dimensions_.SetSize(vformat.nFrameWidth,
- vformat.nFrameHeight);
- if (client_) {
- client_->ProvidePictureBuffers(
- kNumPictureBuffers,
- gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight),
- GL_TEXTURE_2D);
- }
-}
-
-void OmxVideoDecodeAccelerator::OnOutputPortEnabled() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- if (current_state_change_ == RESETTING) {
- for (OutputPictureById::iterator it = pictures_.begin();
- it != pictures_.end(); ++it) {
- queued_picture_buffer_ids_.push_back(it->first);
- }
- return;
- }
-
- if (!CanFillBuffer()) {
- StopOnError(ILLEGAL_STATE);
- return;
- }
-
- // Provide output buffers to decoder.
- for (OutputPictureById::iterator it = pictures_.begin();
- it != pictures_.end(); ++it) {
- OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header;
- DCHECK(omx_buffer);
- // Clear EOS flag.
- omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
- omx_buffer->nOutputPortIndex = output_port_;
- ++output_buffers_at_component_;
- OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer);
- RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed",
- PLATFORM_FAILURE,);
- }
-}
-
-void OmxVideoDecodeAccelerator::FillBufferDoneTask(
- OMX_BUFFERHEADERTYPE* buffer) {
-
- media::Picture* picture =
- reinterpret_cast<media::Picture*>(buffer->pAppPrivate);
- int picture_buffer_id = picture ? picture->picture_buffer_id() : -1;
- TRACE_EVENT2("Video Decoder", "OVDA::FillBufferDoneTask",
- "Buffer id", buffer->nTimeStamp,
- "Picture id", picture_buffer_id);
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK_GT(output_buffers_at_component_, 0);
- --output_buffers_at_component_;
-
- // If we are destroying and then get a fillbuffer callback, calling into any
- // openmax function will put us in error mode, so bail now. In the RESETTING
- // case we still need to enqueue the picture ids but have to avoid giving
- // them to the client (this is handled below).
- if (current_state_change_ == DESTROYING ||
- current_state_change_ == ERRORING)
- return;
-
- if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) {
- size_t erased = fake_output_buffers_.erase(buffer);
- DCHECK_EQ(erased, 1U);
- OMX_ERRORTYPE result =
- OMX_FreeBuffer(component_handle_, output_port_, buffer);
- RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed", PLATFORM_FAILURE,);
- return;
- }
- DCHECK(!fake_output_buffers_.size());
-
- // When the EOS picture is delivered back to us, notify the client and reuse
- // the underlying picturebuffer.
- if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
- buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
- OnReachedEOSInFlushing();
- ReusePictureBuffer(picture_buffer_id);
- return;
- }
-
- // During the transition from Executing to Idle, and during port-flushing, all
- // pictures are sent back through here. Avoid giving them to the client.
- if (current_state_change_ == RESETTING) {
- queued_picture_buffer_ids_.push_back(picture_buffer_id);
- return;
- }
-
- DCHECK(picture);
- // See Decode() for an explanation of this abuse of nTimeStamp.
- picture->set_bitstream_buffer_id(buffer->nTimeStamp);
- if (client_)
- client_->PictureReady(*picture);
-}
-
-void OmxVideoDecodeAccelerator::EmptyBufferDoneTask(
- OMX_BUFFERHEADERTYPE* buffer) {
- TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferDoneTask",
- "Buffer id", buffer->nTimeStamp);
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- DCHECK_GT(input_buffers_at_component_, 0);
- free_input_buffers_.push(buffer);
- input_buffers_at_component_--;
- if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
- return;
-
- // Retrieve the corresponding BitstreamBuffer's id and notify the client of
- // its completion.
- SharedMemoryAndId* input_buffer_details =
- reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate);
- DCHECK(input_buffer_details);
- buffer->pAppPrivate = NULL;
- if (client_)
- client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second);
- delete input_buffer_details;
-
- DecodeQueuedBitstreamBuffers();
-}
-
-void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- switch (current_state_change_) {
- case INITIALIZING:
- switch (reached) {
- case OMX_StateIdle:
- OnReachedIdleInInitializing();
- return;
- case OMX_StateExecuting:
- OnReachedExecutingInInitializing();
- return;
- default:
- NOTREACHED() << "Unexpected state in INITIALIZING: " << reached;
- return;
- }
- case RESETTING:
- switch (reached) {
- case OMX_StatePause:
- OnReachedPauseInResetting();
- return;
- case OMX_StateExecuting:
- OnReachedExecutingInResetting();
- return;
- default:
- NOTREACHED() << "Unexpected state in RESETTING: " << reached;
- return;
- }
- case DESTROYING:
- switch (reached) {
- case OMX_StatePause:
- case OMX_StateExecuting:
- // Because Destroy() can interrupt an in-progress Reset(),
- // we might arrive at these states after current_state_change_ was
- // overwritten with DESTROYING. That's fine though - we already have
- // the state transition for Destroy() queued up at the component, so
- // we treat this as a no-op.
- return;
- case OMX_StateIdle:
- OnReachedIdleInDestroying();
- return;
- case OMX_StateLoaded:
- OnReachedLoadedInDestroying();
- return;
- default:
- NOTREACHED() << "Unexpected state in DESTROYING: " << reached;
- return;
- }
- case ERRORING:
- switch (reached) {
- case OMX_StateInvalid:
- OnReachedInvalidInErroring();
- return;
- default:
- NOTREACHED() << "Unexpected state in ERRORING: " << reached;
- return;
- }
- default:
- NOTREACHED() << "Unexpected state in " << current_state_change_
- << ": " << reached;
- }
-}
-
-void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event,
- OMX_U32 data1,
- OMX_U32 data2) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- switch (event) {
- case OMX_EventCmdComplete:
- switch (data1) {
- case OMX_CommandPortDisable:
- DCHECK_EQ(data2, output_port_);
- OnOutputPortDisabled();
- return;
- case OMX_CommandPortEnable:
- DCHECK_EQ(data2, output_port_);
- OnOutputPortEnabled();
- return;
- case OMX_CommandStateSet:
- DispatchStateReached(static_cast<OMX_STATETYPE>(data2));
- return;
- case OMX_CommandFlush:
- if (current_state_change_ == DESTROYING ||
- current_state_change_ == ERRORING) {
- return;
- }
- DCHECK_EQ(current_state_change_, RESETTING);
- if (data2 == input_port_)
- InputPortFlushDone();
- else if (data2 == output_port_)
- OutputPortFlushDone();
- else
- NOTREACHED() << "Unexpected port flushed: " << data2;
- return;
- default:
- RETURN_ON_FAILURE(false, "Unknown command completed: " << data1,
- PLATFORM_FAILURE,);
- }
- return;
- case OMX_EventError:
- if (current_state_change_ != DESTROYING &&
- current_state_change_ != ERRORING) {
- RETURN_ON_FAILURE(false, "EventError: 0x" << std::hex << data1,
- PLATFORM_FAILURE,);
- }
- return;
- case OMX_EventPortSettingsChanged:
- if ((data2 == OMX_IndexParamPortDefinition) || // Tegra2/3
- (data2 == 0)) { // Exynos SEC-OMX; http://crosbug.com/p/11665
- DCHECK_EQ(data1, output_port_);
- // This event is only used for output resize; kick off handling that by
- // pausing the output port.
- SendCommandToPort(OMX_CommandPortDisable, output_port_);
- } else if (data1 == output_port_ &&
- data2 == OMX_IndexConfigCommonOutputCrop) {
- // TODO(vjain): Handle video crop rect.
- } else if (data1 == output_port_ &&
- data2 == OMX_IndexConfigCommonScale) {
- // TODO(ashokm@nvidia.com): Handle video SAR change.
- } else {
- RETURN_ON_FAILURE(false,
- "Unexpected EventPortSettingsChanged: "
- << data1 << ", " << data2,
- PLATFORM_FAILURE,);
- }
- return;
- case OMX_EventBufferFlag:
- if (data1 == output_port_) {
- // In case of Destroy() interrupting Flush().
- if (current_state_change_ == DESTROYING)
- return;
- DCHECK_EQ(current_state_change_, FLUSHING);
- // Do nothing; rely on the EOS picture delivery to notify the client.
- } else {
- RETURN_ON_FAILURE(false,
- "Unexpected OMX_EventBufferFlag: "
- << data1 << ", " << data2,
- PLATFORM_FAILURE,);
- }
- return;
- default:
- RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event,
- PLATFORM_FAILURE,);
- }
-}
-
-// static
-void OmxVideoDecodeAccelerator::PreSandboxInitialization() {
- DCHECK(!pre_sandbox_init_done_);
- omx_handle = dlopen("libOmxCore.so", RTLD_NOW);
- pre_sandbox_init_done_ = omx_handle != NULL;
-}
-
-// static
-bool OmxVideoDecodeAccelerator::PostSandboxInitialization() {
- if (!pre_sandbox_init_done_)
- return false;
-
- omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init"));
- omx_gethandle =
- reinterpret_cast<OMXGetHandle>(dlsym(omx_handle, "OMX_GetHandle"));
- omx_get_components_of_role =
- reinterpret_cast<OMXGetComponentsOfRole>(
- dlsym(omx_handle, "OMX_GetComponentsOfRole"));
- omx_free_handle =
- reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle"));
- omx_deinit =
- reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit"));
-
- return (omx_init && omx_gethandle && omx_get_components_of_role &&
- omx_free_handle && omx_deinit);
-}
-
-// static
-OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
- OMX_PTR priv_data,
- OMX_EVENTTYPE event,
- OMX_U32 data1,
- OMX_U32 data2,
- OMX_PTR event_data) {
- // Called on the OMX thread.
- OmxVideoDecodeAccelerator* decoder =
- static_cast<OmxVideoDecodeAccelerator*>(priv_data);
- DCHECK_EQ(component, decoder->component_handle_);
- decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::EventHandlerCompleteTask,
- decoder->weak_this(), event, data1, data2));
- return OMX_ErrorNone;
-}
-
-// static
-OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback(
- OMX_HANDLETYPE component,
- OMX_PTR priv_data,
- OMX_BUFFERHEADERTYPE* buffer) {
- TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferCallback",
- "Buffer id", buffer->nTimeStamp);
- // Called on the OMX thread.
- OmxVideoDecodeAccelerator* decoder =
- static_cast<OmxVideoDecodeAccelerator*>(priv_data);
- DCHECK_EQ(component, decoder->component_handle_);
- decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::EmptyBufferDoneTask, decoder->weak_this(),
- buffer));
- return OMX_ErrorNone;
-}
-
-// static
-OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback(
- OMX_HANDLETYPE component,
- OMX_PTR priv_data,
- OMX_BUFFERHEADERTYPE* buffer) {
- media::Picture* picture =
- reinterpret_cast<media::Picture*>(buffer->pAppPrivate);
- int picture_buffer_id = picture ? picture->picture_buffer_id() : -1;
- TRACE_EVENT2("Video Decoder", "OVDA::FillBufferCallback",
- "Buffer id", buffer->nTimeStamp,
- "Picture id", picture_buffer_id);
- // Called on the OMX thread.
- OmxVideoDecodeAccelerator* decoder =
- static_cast<OmxVideoDecodeAccelerator*>(priv_data);
- DCHECK_EQ(component, decoder->component_handle_);
- decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::FillBufferDoneTask, decoder->weak_this(),
- buffer));
- return OMX_ErrorNone;
-}
-
-bool OmxVideoDecodeAccelerator::CanFillBuffer() {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- const CurrentStateChange csc = current_state_change_;
- const OMX_STATETYPE cs = client_state_;
- return (csc != DESTROYING && csc != ERRORING && csc != RESETTING) &&
- (cs == OMX_StateIdle || cs == OMX_StateExecuting || cs == OMX_StatePause);
-}
-
-bool OmxVideoDecodeAccelerator::SendCommandToPort(
- OMX_COMMANDTYPE cmd, int port_index) {
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
- cmd, port_index, 0);
- RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
- PLATFORM_FAILURE, false);
- return true;
-}
-
-} // namespace content
« no previous file with comments | « content/common/gpu/media/omx_video_decode_accelerator.h ('k') | content/common/gpu/media/video_decode_accelerator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698