OMX init
This commit is contained in:
757
SimpleRedroidOMXComponent.cpp
Normal file
757
SimpleRedroidOMXComponent.cpp
Normal file
@@ -0,0 +1,757 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "SimpleRedroidOMXComponent"
|
||||
#include <utils/Log.h>
|
||||
#include <OMX_Core.h>
|
||||
#include <OMX_Audio.h>
|
||||
#include <OMX_IndexExt.h>
|
||||
#include <OMX_AudioExt.h>
|
||||
|
||||
#include <media/stagefright/omx/SimpleRedroidOMXComponent.h>
|
||||
#include <media/stagefright/foundation/ADebug.h>
|
||||
#include <media/stagefright/foundation/ALooper.h>
|
||||
#include <media/stagefright/foundation/AMessage.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
SimpleRedroidOMXComponent::SimpleRedroidOMXComponent(
|
||||
const char *name,
|
||||
const OMX_CALLBACKTYPE *callbacks,
|
||||
OMX_PTR appData,
|
||||
OMX_COMPONENTTYPE **component)
|
||||
: RedroidOMXComponent(name, callbacks, appData, component),
|
||||
mLooper(new ALooper),
|
||||
mHandler(new AHandlerReflector<SimpleRedroidOMXComponent>(this)),
|
||||
mState(OMX_StateLoaded),
|
||||
mTargetState(OMX_StateLoaded),
|
||||
mFrameConfig(false) {
|
||||
mLooper->setName(name);
|
||||
mLooper->registerHandler(mHandler);
|
||||
|
||||
mLooper->start(
|
||||
false, // runOnCallingThread
|
||||
false, // canCallJava
|
||||
ANDROID_PRIORITY_VIDEO);
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::prepareForDestruction() {
|
||||
// The looper's queue may still contain messages referencing this
|
||||
// object. Make sure those are flushed before returning so that
|
||||
// a subsequent dlunload() does not pull out the rug from under us.
|
||||
|
||||
mLooper->unregisterHandler(mHandler->id());
|
||||
mLooper->stop();
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::sendCommand(
|
||||
OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) {
|
||||
CHECK(data == NULL);
|
||||
|
||||
sp<AMessage> msg = new AMessage(kWhatSendCommand, mHandler);
|
||||
msg->setInt32("cmd", cmd);
|
||||
msg->setInt32("param", param);
|
||||
msg->post();
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
bool SimpleRedroidOMXComponent::isSetParameterAllowed(
|
||||
OMX_INDEXTYPE index, const OMX_PTR params) const {
|
||||
if (mState == OMX_StateLoaded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
OMX_U32 portIndex;
|
||||
|
||||
switch ((int)index) {
|
||||
case OMX_IndexParamPortDefinition:
|
||||
{
|
||||
const OMX_PARAM_PORTDEFINITIONTYPE *portDefs =
|
||||
(const OMX_PARAM_PORTDEFINITIONTYPE *) params;
|
||||
if (!isValidOMXParam(portDefs)) {
|
||||
return false;
|
||||
}
|
||||
portIndex = portDefs->nPortIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
case OMX_IndexParamAudioPcm:
|
||||
{
|
||||
const OMX_AUDIO_PARAM_PCMMODETYPE *pcmMode =
|
||||
(const OMX_AUDIO_PARAM_PCMMODETYPE *) params;
|
||||
if (!isValidOMXParam(pcmMode)) {
|
||||
return false;
|
||||
}
|
||||
portIndex = pcmMode->nPortIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
case OMX_IndexParamAudioAac:
|
||||
{
|
||||
const OMX_AUDIO_PARAM_AACPROFILETYPE *aacMode =
|
||||
(const OMX_AUDIO_PARAM_AACPROFILETYPE *) params;
|
||||
if (!isValidOMXParam(aacMode)) {
|
||||
return false;
|
||||
}
|
||||
portIndex = aacMode->nPortIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
case OMX_IndexParamAudioAndroidAacDrcPresentation:
|
||||
{
|
||||
if (mState == OMX_StateInvalid) {
|
||||
return false;
|
||||
}
|
||||
const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *aacPresParams =
|
||||
(const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *)params;
|
||||
if (!isValidOMXParam(aacPresParams)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK(portIndex < mPorts.size());
|
||||
|
||||
return !mPorts.itemAt(portIndex).mDef.bEnabled;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::getParameter(
|
||||
OMX_INDEXTYPE index, OMX_PTR params) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
return internalGetParameter(index, params);
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::setParameter(
|
||||
OMX_INDEXTYPE index, const OMX_PTR params) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
CHECK(isSetParameterAllowed(index, params));
|
||||
|
||||
return internalSetParameter(index, params);
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::internalGetParameter(
|
||||
OMX_INDEXTYPE index, OMX_PTR params) {
|
||||
switch (index) {
|
||||
case OMX_IndexParamPortDefinition:
|
||||
{
|
||||
OMX_PARAM_PORTDEFINITIONTYPE *defParams =
|
||||
(OMX_PARAM_PORTDEFINITIONTYPE *)params;
|
||||
|
||||
if (!isValidOMXParam(defParams)) {
|
||||
return OMX_ErrorBadParameter;
|
||||
}
|
||||
|
||||
if (defParams->nPortIndex >= mPorts.size()
|
||||
|| defParams->nSize
|
||||
!= sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
|
||||
return OMX_ErrorUndefined;
|
||||
}
|
||||
|
||||
const PortInfo *port =
|
||||
&mPorts.itemAt(defParams->nPortIndex);
|
||||
|
||||
memcpy(defParams, &port->mDef, sizeof(port->mDef));
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
default:
|
||||
return OMX_ErrorUnsupportedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::internalSetParameter(
|
||||
OMX_INDEXTYPE index, const OMX_PTR params) {
|
||||
switch (index) {
|
||||
case OMX_IndexParamPortDefinition:
|
||||
{
|
||||
OMX_PARAM_PORTDEFINITIONTYPE *defParams =
|
||||
(OMX_PARAM_PORTDEFINITIONTYPE *)params;
|
||||
|
||||
if (!isValidOMXParam(defParams)) {
|
||||
return OMX_ErrorBadParameter;
|
||||
}
|
||||
|
||||
if (defParams->nPortIndex >= mPorts.size()) {
|
||||
return OMX_ErrorBadPortIndex;
|
||||
}
|
||||
if (defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
|
||||
return OMX_ErrorUnsupportedSetting;
|
||||
}
|
||||
|
||||
PortInfo *port =
|
||||
&mPorts.editItemAt(defParams->nPortIndex);
|
||||
|
||||
// default behavior is that we only allow buffer size to increase
|
||||
if (defParams->nBufferSize > port->mDef.nBufferSize) {
|
||||
port->mDef.nBufferSize = defParams->nBufferSize;
|
||||
}
|
||||
|
||||
if (defParams->nBufferCountActual < port->mDef.nBufferCountMin) {
|
||||
ALOGW("component requires at least %u buffers (%u requested)",
|
||||
port->mDef.nBufferCountMin, defParams->nBufferCountActual);
|
||||
return OMX_ErrorUnsupportedSetting;
|
||||
}
|
||||
|
||||
port->mDef.nBufferCountActual = defParams->nBufferCountActual;
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
default:
|
||||
return OMX_ErrorUnsupportedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::internalSetConfig(
|
||||
OMX_INDEXTYPE index, const OMX_PTR params, bool *frameConfig) {
|
||||
return OMX_ErrorUndefined;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::setConfig(
|
||||
OMX_INDEXTYPE index, const OMX_PTR params) {
|
||||
bool frameConfig = mFrameConfig;
|
||||
OMX_ERRORTYPE err = internalSetConfig(index, params, &frameConfig);
|
||||
if (err == OMX_ErrorNone) {
|
||||
mFrameConfig = frameConfig;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::useBuffer(
|
||||
OMX_BUFFERHEADERTYPE **header,
|
||||
OMX_U32 portIndex,
|
||||
OMX_PTR appPrivate,
|
||||
OMX_U32 size,
|
||||
OMX_U8 *ptr) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
CHECK_LT(portIndex, mPorts.size());
|
||||
|
||||
PortInfo *port = &mPorts.editItemAt(portIndex);
|
||||
if (size < port->mDef.nBufferSize) {
|
||||
ALOGE("b/63522430, Buffer size is too small.");
|
||||
android_errorWriteLog(0x534e4554, "63522430");
|
||||
return OMX_ErrorBadParameter;
|
||||
}
|
||||
|
||||
*header = new OMX_BUFFERHEADERTYPE;
|
||||
(*header)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
|
||||
(*header)->nVersion.s.nVersionMajor = 1;
|
||||
(*header)->nVersion.s.nVersionMinor = 0;
|
||||
(*header)->nVersion.s.nRevision = 0;
|
||||
(*header)->nVersion.s.nStep = 0;
|
||||
(*header)->pBuffer = ptr;
|
||||
(*header)->nAllocLen = size;
|
||||
(*header)->nFilledLen = 0;
|
||||
(*header)->nOffset = 0;
|
||||
(*header)->pAppPrivate = appPrivate;
|
||||
(*header)->pPlatformPrivate = NULL;
|
||||
(*header)->pInputPortPrivate = NULL;
|
||||
(*header)->pOutputPortPrivate = NULL;
|
||||
(*header)->hMarkTargetComponent = NULL;
|
||||
(*header)->pMarkData = NULL;
|
||||
(*header)->nTickCount = 0;
|
||||
(*header)->nTimeStamp = 0;
|
||||
(*header)->nFlags = 0;
|
||||
(*header)->nOutputPortIndex = portIndex;
|
||||
(*header)->nInputPortIndex = portIndex;
|
||||
|
||||
CHECK(mState == OMX_StateLoaded || port->mDef.bEnabled == OMX_FALSE);
|
||||
|
||||
CHECK_LT(port->mBuffers.size(), port->mDef.nBufferCountActual);
|
||||
|
||||
port->mBuffers.push();
|
||||
|
||||
BufferInfo *buffer =
|
||||
&port->mBuffers.editItemAt(port->mBuffers.size() - 1);
|
||||
|
||||
buffer->mHeader = *header;
|
||||
buffer->mOwnedByUs = false;
|
||||
|
||||
if (port->mBuffers.size() == port->mDef.nBufferCountActual) {
|
||||
port->mDef.bPopulated = OMX_TRUE;
|
||||
checkTransitions();
|
||||
}
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::allocateBuffer(
|
||||
OMX_BUFFERHEADERTYPE **header,
|
||||
OMX_U32 portIndex,
|
||||
OMX_PTR appPrivate,
|
||||
OMX_U32 size) {
|
||||
OMX_U8 *ptr = new OMX_U8[size];
|
||||
|
||||
OMX_ERRORTYPE err =
|
||||
useBuffer(header, portIndex, appPrivate, size, ptr);
|
||||
|
||||
if (err != OMX_ErrorNone) {
|
||||
delete[] ptr;
|
||||
ptr = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
CHECK((*header)->pPlatformPrivate == NULL);
|
||||
(*header)->pPlatformPrivate = ptr;
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::freeBuffer(
|
||||
OMX_U32 portIndex,
|
||||
OMX_BUFFERHEADERTYPE *header) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
CHECK_LT(portIndex, mPorts.size());
|
||||
|
||||
PortInfo *port = &mPorts.editItemAt(portIndex);
|
||||
|
||||
#if 0 // XXX
|
||||
CHECK((mState == OMX_StateIdle && mTargetState == OMX_StateLoaded)
|
||||
|| port->mDef.bEnabled == OMX_FALSE);
|
||||
#endif
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < port->mBuffers.size(); ++i) {
|
||||
BufferInfo *buffer = &port->mBuffers.editItemAt(i);
|
||||
|
||||
if (buffer->mHeader == header) {
|
||||
CHECK(!buffer->mOwnedByUs);
|
||||
|
||||
if (header->pPlatformPrivate != NULL) {
|
||||
// This buffer's data was allocated by us.
|
||||
CHECK(header->pPlatformPrivate == header->pBuffer);
|
||||
|
||||
delete[] header->pBuffer;
|
||||
header->pBuffer = NULL;
|
||||
}
|
||||
|
||||
delete header;
|
||||
header = NULL;
|
||||
|
||||
port->mBuffers.removeAt(i);
|
||||
port->mDef.bPopulated = OMX_FALSE;
|
||||
|
||||
checkTransitions();
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(found);
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::emptyThisBuffer(
|
||||
OMX_BUFFERHEADERTYPE *buffer) {
|
||||
sp<AMessage> msg = new AMessage(kWhatEmptyThisBuffer, mHandler);
|
||||
msg->setPointer("header", buffer);
|
||||
if (mFrameConfig) {
|
||||
msg->setInt32("frame-config", mFrameConfig);
|
||||
mFrameConfig = false;
|
||||
}
|
||||
msg->post();
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::fillThisBuffer(
|
||||
OMX_BUFFERHEADERTYPE *buffer) {
|
||||
sp<AMessage> msg = new AMessage(kWhatFillThisBuffer, mHandler);
|
||||
msg->setPointer("header", buffer);
|
||||
msg->post();
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE SimpleRedroidOMXComponent::getState(OMX_STATETYPE *state) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
*state = mState;
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onMessageReceived(const sp<AMessage> &msg) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
uint32_t msgType = msg->what();
|
||||
ALOGV("msgType = %d", msgType);
|
||||
switch (msgType) {
|
||||
case kWhatSendCommand:
|
||||
{
|
||||
int32_t cmd, param;
|
||||
CHECK(msg->findInt32("cmd", &cmd));
|
||||
CHECK(msg->findInt32("param", ¶m));
|
||||
|
||||
onSendCommand((OMX_COMMANDTYPE)cmd, (OMX_U32)param);
|
||||
break;
|
||||
}
|
||||
|
||||
case kWhatEmptyThisBuffer:
|
||||
case kWhatFillThisBuffer:
|
||||
{
|
||||
OMX_BUFFERHEADERTYPE *header;
|
||||
CHECK(msg->findPointer("header", (void **)&header));
|
||||
int32_t frameConfig;
|
||||
if (!msg->findInt32("frame-config", &frameConfig)) {
|
||||
frameConfig = 0;
|
||||
}
|
||||
|
||||
CHECK(mState == OMX_StateExecuting && mTargetState == mState);
|
||||
|
||||
bool found = false;
|
||||
size_t portIndex = (kWhatEmptyThisBuffer == msgType)?
|
||||
header->nInputPortIndex: header->nOutputPortIndex;
|
||||
PortInfo *port = &mPorts.editItemAt(portIndex);
|
||||
|
||||
for (size_t j = 0; j < port->mBuffers.size(); ++j) {
|
||||
BufferInfo *buffer = &port->mBuffers.editItemAt(j);
|
||||
|
||||
if (buffer->mHeader == header) {
|
||||
CHECK(!buffer->mOwnedByUs);
|
||||
|
||||
buffer->mOwnedByUs = true;
|
||||
buffer->mFrameConfig = (bool)frameConfig;
|
||||
|
||||
CHECK((msgType == kWhatEmptyThisBuffer
|
||||
&& port->mDef.eDir == OMX_DirInput)
|
||||
|| (port->mDef.eDir == OMX_DirOutput));
|
||||
|
||||
port->mQueue.push_back(buffer);
|
||||
onQueueFilled(portIndex);
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(found);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRESPASS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onSendCommand(
|
||||
OMX_COMMANDTYPE cmd, OMX_U32 param) {
|
||||
switch (cmd) {
|
||||
case OMX_CommandStateSet:
|
||||
{
|
||||
onChangeState((OMX_STATETYPE)param);
|
||||
break;
|
||||
}
|
||||
|
||||
case OMX_CommandPortEnable:
|
||||
case OMX_CommandPortDisable:
|
||||
{
|
||||
onPortEnable(param, cmd == OMX_CommandPortEnable);
|
||||
break;
|
||||
}
|
||||
|
||||
case OMX_CommandFlush:
|
||||
{
|
||||
onPortFlush(param, true /* sendFlushComplete */);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRESPASS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onChangeState(OMX_STATETYPE state) {
|
||||
ALOGV("%p requesting change from %d to %d", this, mState, state);
|
||||
// We shouldn't be in a state transition already.
|
||||
|
||||
if (mState == OMX_StateLoaded
|
||||
&& mTargetState == OMX_StateIdle
|
||||
&& state == OMX_StateLoaded) {
|
||||
// OMX specifically allows "canceling" a state transition from loaded
|
||||
// to idle. Pretend we made it to idle, and go back to loaded
|
||||
ALOGV("load->idle canceled");
|
||||
mState = mTargetState = OMX_StateIdle;
|
||||
state = OMX_StateLoaded;
|
||||
}
|
||||
|
||||
if (mState != mTargetState) {
|
||||
ALOGE("State change to state %d requested while still transitioning from state %d to %d",
|
||||
state, mState, mTargetState);
|
||||
notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mState) {
|
||||
case OMX_StateLoaded:
|
||||
CHECK_EQ((int)state, (int)OMX_StateIdle);
|
||||
break;
|
||||
case OMX_StateIdle:
|
||||
CHECK(state == OMX_StateLoaded || state == OMX_StateExecuting);
|
||||
break;
|
||||
case OMX_StateExecuting:
|
||||
{
|
||||
CHECK_EQ((int)state, (int)OMX_StateIdle);
|
||||
|
||||
for (size_t i = 0; i < mPorts.size(); ++i) {
|
||||
onPortFlush(i, false /* sendFlushComplete */);
|
||||
}
|
||||
|
||||
mState = OMX_StateIdle;
|
||||
notify(OMX_EventCmdComplete, OMX_CommandStateSet, state, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRESPASS();
|
||||
}
|
||||
|
||||
mTargetState = state;
|
||||
|
||||
checkTransitions();
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onReset() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onPortEnable(OMX_U32 portIndex, bool enable) {
|
||||
CHECK_LT(portIndex, mPorts.size());
|
||||
|
||||
PortInfo *port = &mPorts.editItemAt(portIndex);
|
||||
CHECK_EQ((int)port->mTransition, (int)PortInfo::NONE);
|
||||
CHECK(port->mDef.bEnabled == !enable);
|
||||
|
||||
if (port->mDef.eDir != OMX_DirOutput) {
|
||||
ALOGE("Port enable/disable allowed only on output ports.");
|
||||
notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
|
||||
android_errorWriteLog(0x534e4554, "29421804");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enable) {
|
||||
port->mDef.bEnabled = OMX_FALSE;
|
||||
port->mTransition = PortInfo::DISABLING;
|
||||
|
||||
for (size_t i = 0; i < port->mBuffers.size(); ++i) {
|
||||
BufferInfo *buffer = &port->mBuffers.editItemAt(i);
|
||||
|
||||
if (buffer->mOwnedByUs) {
|
||||
buffer->mOwnedByUs = false;
|
||||
|
||||
if (port->mDef.eDir == OMX_DirInput) {
|
||||
notifyEmptyBufferDone(buffer->mHeader);
|
||||
} else {
|
||||
CHECK_EQ(port->mDef.eDir, OMX_DirOutput);
|
||||
notifyFillBufferDone(buffer->mHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
port->mQueue.clear();
|
||||
} else {
|
||||
port->mTransition = PortInfo::ENABLING;
|
||||
}
|
||||
|
||||
checkTransitions();
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onPortFlush(
|
||||
OMX_U32 portIndex, bool sendFlushComplete) {
|
||||
if (portIndex == OMX_ALL) {
|
||||
for (size_t i = 0; i < mPorts.size(); ++i) {
|
||||
onPortFlush(i, sendFlushComplete);
|
||||
}
|
||||
|
||||
if (sendFlushComplete) {
|
||||
notify(OMX_EventCmdComplete, OMX_CommandFlush, OMX_ALL, NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK_LT(portIndex, mPorts.size());
|
||||
|
||||
PortInfo *port = &mPorts.editItemAt(portIndex);
|
||||
// Ideally, the port should not in transitioning state when flushing.
|
||||
// However, in error handling case, e.g., the client can't allocate buffers
|
||||
// when it tries to re-enable the port, the port will be stuck in ENABLING.
|
||||
// The client will then transition the component from Executing to Idle,
|
||||
// which leads to flushing ports. At this time, it should be ok to notify
|
||||
// the client of the error and still clear all buffers on the port.
|
||||
if (port->mTransition != PortInfo::NONE) {
|
||||
notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < port->mBuffers.size(); ++i) {
|
||||
BufferInfo *buffer = &port->mBuffers.editItemAt(i);
|
||||
|
||||
if (!buffer->mOwnedByUs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buffer->mHeader->nFilledLen = 0;
|
||||
buffer->mHeader->nOffset = 0;
|
||||
buffer->mHeader->nFlags = 0;
|
||||
|
||||
buffer->mOwnedByUs = false;
|
||||
|
||||
if (port->mDef.eDir == OMX_DirInput) {
|
||||
notifyEmptyBufferDone(buffer->mHeader);
|
||||
} else {
|
||||
CHECK_EQ(port->mDef.eDir, OMX_DirOutput);
|
||||
|
||||
notifyFillBufferDone(buffer->mHeader);
|
||||
}
|
||||
}
|
||||
|
||||
port->mQueue.clear();
|
||||
|
||||
if (sendFlushComplete) {
|
||||
notify(OMX_EventCmdComplete, OMX_CommandFlush, portIndex, NULL);
|
||||
|
||||
onPortFlushCompleted(portIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::checkTransitions() {
|
||||
if (mState != mTargetState) {
|
||||
bool transitionComplete = true;
|
||||
|
||||
if (mState == OMX_StateLoaded) {
|
||||
CHECK_EQ((int)mTargetState, (int)OMX_StateIdle);
|
||||
|
||||
for (size_t i = 0; i < mPorts.size(); ++i) {
|
||||
const PortInfo &port = mPorts.itemAt(i);
|
||||
if (port.mDef.bEnabled == OMX_FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (port.mDef.bPopulated == OMX_FALSE) {
|
||||
transitionComplete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (mTargetState == OMX_StateLoaded) {
|
||||
CHECK_EQ((int)mState, (int)OMX_StateIdle);
|
||||
|
||||
for (size_t i = 0; i < mPorts.size(); ++i) {
|
||||
const PortInfo &port = mPorts.itemAt(i);
|
||||
if (port.mDef.bEnabled == OMX_FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t n = port.mBuffers.size();
|
||||
|
||||
if (n > 0) {
|
||||
CHECK_LE(n, port.mDef.nBufferCountActual);
|
||||
|
||||
if (n == port.mDef.nBufferCountActual) {
|
||||
CHECK_EQ((int)port.mDef.bPopulated, (int)OMX_TRUE);
|
||||
} else {
|
||||
CHECK_EQ((int)port.mDef.bPopulated, (int)OMX_FALSE);
|
||||
}
|
||||
|
||||
transitionComplete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (transitionComplete) {
|
||||
ALOGV("state transition from %d to %d complete", mState, mTargetState);
|
||||
mState = mTargetState;
|
||||
|
||||
if (mState == OMX_StateLoaded) {
|
||||
onReset();
|
||||
}
|
||||
|
||||
notify(OMX_EventCmdComplete, OMX_CommandStateSet, mState, NULL);
|
||||
} else {
|
||||
ALOGV("state transition from %d to %d not yet complete", mState, mTargetState);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mPorts.size(); ++i) {
|
||||
PortInfo *port = &mPorts.editItemAt(i);
|
||||
|
||||
if (port->mTransition == PortInfo::DISABLING) {
|
||||
if (port->mBuffers.empty()) {
|
||||
ALOGV("Port %zu now disabled.", i);
|
||||
|
||||
port->mTransition = PortInfo::NONE;
|
||||
notify(OMX_EventCmdComplete, OMX_CommandPortDisable, i, NULL);
|
||||
|
||||
onPortEnableCompleted(i, false /* enabled */);
|
||||
}
|
||||
} else if (port->mTransition == PortInfo::ENABLING) {
|
||||
if (port->mDef.bPopulated == OMX_TRUE) {
|
||||
ALOGV("Port %zu now enabled.", i);
|
||||
|
||||
port->mTransition = PortInfo::NONE;
|
||||
port->mDef.bEnabled = OMX_TRUE;
|
||||
notify(OMX_EventCmdComplete, OMX_CommandPortEnable, i, NULL);
|
||||
|
||||
onPortEnableCompleted(i, true /* enabled */);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::addPort(const OMX_PARAM_PORTDEFINITIONTYPE &def) {
|
||||
CHECK_EQ(def.nPortIndex, mPorts.size());
|
||||
|
||||
mPorts.push();
|
||||
PortInfo *info = &mPorts.editItemAt(mPorts.size() - 1);
|
||||
info->mDef = def;
|
||||
info->mTransition = PortInfo::NONE;
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onQueueFilled(OMX_U32 portIndex __unused) {
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onPortFlushCompleted(OMX_U32 portIndex __unused) {
|
||||
}
|
||||
|
||||
void SimpleRedroidOMXComponent::onPortEnableCompleted(
|
||||
OMX_U32 portIndex __unused, bool enabled __unused) {
|
||||
}
|
||||
|
||||
List<SimpleRedroidOMXComponent::BufferInfo *> &
|
||||
SimpleRedroidOMXComponent::getPortQueue(OMX_U32 portIndex) {
|
||||
CHECK_LT(portIndex, mPorts.size());
|
||||
return mPorts.editItemAt(portIndex).mQueue;
|
||||
}
|
||||
|
||||
SimpleRedroidOMXComponent::PortInfo *SimpleRedroidOMXComponent::editPortInfo(
|
||||
OMX_U32 portIndex) {
|
||||
CHECK_LT(portIndex, mPorts.size());
|
||||
return &mPorts.editItemAt(portIndex);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
Reference in New Issue
Block a user