blob: 08a3d42641933694914ae6e4f0299ded9c12fc60 [file] [log] [blame]
/*
* Copyright (C) 2013 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 "SoftVideoDecoderOMXComponent"
#include <utils/Log.h>
#include "include/SoftVideoDecoderOMXComponent.h"
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaDefs.h>
namespace android {
template<class T>
static void InitOMXParams(T *params) {
params->nSize = sizeof(T);
params->nVersion.s.nVersionMajor = 1;
params->nVersion.s.nVersionMinor = 0;
params->nVersion.s.nRevision = 0;
params->nVersion.s.nStep = 0;
}
SoftVideoDecoderOMXComponent::SoftVideoDecoderOMXComponent(
const char *name,
const char *componentRole,
OMX_VIDEO_CODINGTYPE codingType,
const CodecProfileLevel *profileLevels,
size_t numProfileLevels,
int32_t width,
int32_t height,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component)
: SimpleSoftOMXComponent(name, callbacks, appData, component),
mWidth(width),
mHeight(height),
mCropLeft(0),
mCropTop(0),
mCropWidth(width),
mCropHeight(height),
mOutputPortSettingsChange(NONE),
mComponentRole(componentRole),
mCodingType(codingType),
mProfileLevels(profileLevels),
mNumProfileLevels(numProfileLevels) {
}
void SoftVideoDecoderOMXComponent::initPorts(
OMX_U32 numInputBuffers,
OMX_U32 inputBufferSize,
OMX_U32 numOutputBuffers,
const char *mimeType) {
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = kInputPortIndex;
def.eDir = OMX_DirInput;
def.nBufferCountMin = numInputBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = inputBufferSize;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainVideo;
def.bBuffersContiguous = OMX_FALSE;
def.nBufferAlignment = 1;
def.format.video.cMIMEType = const_cast<char *>(mimeType);
def.format.video.pNativeRender = NULL;
/* size is initialized in updatePortDefinitions() */
def.format.video.nBitrate = 0;
def.format.video.xFramerate = 0;
def.format.video.bFlagErrorConcealment = OMX_FALSE;
def.format.video.eCompressionFormat = mCodingType;
def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
def.format.video.pNativeWindow = NULL;
addPort(def);
def.nPortIndex = kOutputPortIndex;
def.eDir = OMX_DirOutput;
def.nBufferCountMin = numOutputBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainVideo;
def.bBuffersContiguous = OMX_FALSE;
def.nBufferAlignment = 2;
def.format.video.cMIMEType = const_cast<char *>("video/raw");
def.format.video.pNativeRender = NULL;
/* size is initialized in updatePortDefinitions() */
def.format.video.nBitrate = 0;
def.format.video.xFramerate = 0;
def.format.video.bFlagErrorConcealment = OMX_FALSE;
def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
def.format.video.pNativeWindow = NULL;
addPort(def);
updatePortDefinitions();
}
void SoftVideoDecoderOMXComponent::updatePortDefinitions() {
OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
def->format.video.nFrameWidth = mWidth;
def->format.video.nFrameHeight = mHeight;
def->format.video.nStride = def->format.video.nFrameWidth;
def->format.video.nSliceHeight = def->format.video.nFrameHeight;
def = &editPortInfo(kOutputPortIndex)->mDef;
def->format.video.nFrameWidth = mWidth;
def->format.video.nFrameHeight = mHeight;
def->format.video.nStride = def->format.video.nFrameWidth;
def->format.video.nSliceHeight = def->format.video.nFrameHeight;
def->nBufferSize =
(def->format.video.nFrameWidth *
def->format.video.nFrameHeight * 3) / 2;
mCropLeft = 0;
mCropTop = 0;
mCropWidth = mWidth;
mCropHeight = mHeight;
}
OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter(
OMX_INDEXTYPE index, OMX_PTR params) {
switch (index) {
case OMX_IndexParamVideoPortFormat:
{
OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
if (formatParams->nPortIndex > kMaxPortIndex) {
return OMX_ErrorUndefined;
}
if (formatParams->nIndex != 0) {
return OMX_ErrorNoMore;
}
if (formatParams->nPortIndex == kInputPortIndex) {
formatParams->eCompressionFormat = mCodingType;
formatParams->eColorFormat = OMX_COLOR_FormatUnused;
formatParams->xFramerate = 0;
} else {
CHECK_EQ(formatParams->nPortIndex, 1u);
formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
formatParams->xFramerate = 0;
}
return OMX_ErrorNone;
}
case OMX_IndexParamVideoProfileLevelQuerySupported:
{
OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
(OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
if (profileLevel->nPortIndex != kInputPortIndex) {
ALOGE("Invalid port index: %ld", profileLevel->nPortIndex);
return OMX_ErrorUnsupportedIndex;
}
if (index >= mNumProfileLevels) {
return OMX_ErrorNoMore;
}
profileLevel->eProfile = mProfileLevels[index].mProfile;
profileLevel->eLevel = mProfileLevels[index].mLevel;
return OMX_ErrorNone;
}
default:
return SimpleSoftOMXComponent::internalGetParameter(index, params);
}
}
OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
OMX_INDEXTYPE index, const OMX_PTR params) {
switch (index) {
case OMX_IndexParamStandardComponentRole:
{
const OMX_PARAM_COMPONENTROLETYPE *roleParams =
(const OMX_PARAM_COMPONENTROLETYPE *)params;
if (strncmp((const char *)roleParams->cRole,
mComponentRole,
OMX_MAX_STRINGNAME_SIZE - 1)) {
return OMX_ErrorUndefined;
}
return OMX_ErrorNone;
}
case OMX_IndexParamVideoPortFormat:
{
OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
if (formatParams->nPortIndex > kMaxPortIndex) {
return OMX_ErrorUndefined;
}
if (formatParams->nIndex != 0) {
return OMX_ErrorNoMore;
}
return OMX_ErrorNone;
}
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}
}
OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig(
OMX_INDEXTYPE index, OMX_PTR params) {
switch (index) {
case OMX_IndexConfigCommonOutputCrop:
{
OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
if (rectParams->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUndefined;
}
rectParams->nLeft = mCropLeft;
rectParams->nTop = mCropTop;
rectParams->nWidth = mCropWidth;
rectParams->nHeight = mCropHeight;
return OMX_ErrorNone;
}
default:
return OMX_ErrorUnsupportedIndex;
}
}
void SoftVideoDecoderOMXComponent::onReset() {
mOutputPortSettingsChange = NONE;
}
void SoftVideoDecoderOMXComponent::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
if (portIndex != kOutputPortIndex) {
return;
}
switch (mOutputPortSettingsChange) {
case NONE:
break;
case AWAITING_DISABLED:
{
CHECK(!enabled);
mOutputPortSettingsChange = AWAITING_ENABLED;
break;
}
default:
{
CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
CHECK(enabled);
mOutputPortSettingsChange = NONE;
break;
}
}
}
} // namespace android