blob: c45cf69dd3e9680a950ea9be1affc2799c849a23 [file] [log] [blame]
/*
* Copyright (c) 2009 Wind River Systems, Inc.
*
* The right to copy, distribute, modify, or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <OMX_Core.h>
#include <cmodule.h>
#include <portvideo.h>
#include <componentbase.h>
#include <pv_omxcore.h>
#include "psb.h"
#define LOG_NDEBUG 0
#define LOG_TAG "mrst_psb"
#include <log.h>
/*
* constructor & destructor
*/
MrstPsbComponent::MrstPsbComponent()
{
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = void)\n", __func__, __LINE__);
}
MrstPsbComponent::~MrstPsbComponent()
{
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = void)\n", __func__, __LINE__);
}
/* end of constructor & destructor */
/* core methods & helpers */
OMX_ERRORTYPE MrstPsbComponent::ComponentAllocatePorts(void)
{
PortBase **ports;
OMX_U32 codec_port_index, raw_port_index;
OMX_DIRTYPE codec_port_dir, raw_port_dir;
OMX_PORT_PARAM_TYPE portparam;
const char *working_role;
OMX_ERRORTYPE ret = OMX_ErrorUndefined;
LOGV("%s(): enter\n", __func__);
ports = new PortBase *[NR_PORTS];
if (!ports)
return OMX_ErrorInsufficientResources;
this->nr_ports = NR_PORTS;
this->ports = ports;
/* video_[encoder/decoder].[avc/whatever] */
working_role = GetWorkingRole();
working_role = strpbrk(working_role, "_");
if (!strncmp(working_role, "_encoder", strlen("_encoder")))
isencoder = true;
else
isencoder = false;
working_role = strpbrk(working_role, ".");
if (!strcmp(working_role, ".avc"))
coding_type = OMX_VIDEO_CodingAVC;
if (isencoder) {
raw_port_index = INPORT_INDEX;
codec_port_index = OUTPORT_INDEX;
raw_port_dir = OMX_DirInput;
codec_port_dir = OMX_DirOutput;
}
else {
codec_port_index = INPORT_INDEX;
raw_port_index = OUTPORT_INDEX;
codec_port_dir = OMX_DirInput;
raw_port_dir = OMX_DirOutput;
}
if (coding_type == OMX_VIDEO_CodingAVC)
ret = __AllocateAvcPort(codec_port_index, codec_port_dir);
if (ret != OMX_ErrorNone)
goto free_ports;
ret = __AllocateRawPort(raw_port_index, raw_port_dir);
if (ret != OMX_ErrorNone)
goto free_codecport;
/* OMX_PORT_PARAM_TYPE */
memset(&portparam, 0, sizeof(portparam));
SetTypeHeader(&portparam, sizeof(portparam));
portparam.nPorts = NR_PORTS;
portparam.nStartPortNumber = INPORT_INDEX;
memcpy(&this->portparam, &portparam, sizeof(portparam));
/* end of OMX_PORT_PARAM_TYPE */
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, OMX_ErrorNone);
return OMX_ErrorNone;
free_codecport:
delete ports[codec_port_index];
ports[codec_port_index] = NULL;
free_ports:
coding_type = OMX_VIDEO_CodingUnused;
delete []ports;
ports = NULL;
this->ports = NULL;
this->nr_ports = 0;
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::__AllocateAvcPort(OMX_U32 port_index,
OMX_DIRTYPE dir)
{
PortAvc *avcport;
OMX_PARAM_PORTDEFINITIONTYPE avcportdefinition;
OMX_VIDEO_PARAM_AVCTYPE avcportparam;
LOGV("%s(): enter\n", __func__);
ports[port_index] = new PortAvc;
if (!ports[port_index]) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorInsufficientResources);
return OMX_ErrorInsufficientResources;
}
avcport = static_cast<PortAvc *>(this->ports[port_index]);
/* OMX_PARAM_PORTDEFINITIONTYPE */
memset(&avcportdefinition, 0, sizeof(avcportdefinition));
SetTypeHeader(&avcportdefinition, sizeof(avcportdefinition));
avcportdefinition.nPortIndex = port_index;
avcportdefinition.eDir = dir;
if (dir == OMX_DirInput) {
avcportdefinition.nBufferCountActual = INPORT_AVC_ACTUAL_BUFFER_COUNT;
avcportdefinition.nBufferCountMin = INPORT_AVC_MIN_BUFFER_COUNT;
avcportdefinition.nBufferSize = INPORT_AVC_BUFFER_SIZE;
}
else {
avcportdefinition.nBufferCountActual = OUTPORT_AVC_ACTUAL_BUFFER_COUNT;
avcportdefinition.nBufferCountMin = OUTPORT_AVC_MIN_BUFFER_COUNT;
avcportdefinition.nBufferSize = OUTPORT_AVC_BUFFER_SIZE;
}
avcportdefinition.bEnabled = OMX_TRUE;
avcportdefinition.bPopulated = OMX_FALSE;
avcportdefinition.eDomain = OMX_PortDomainVideo;
avcportdefinition.format.video.cMIMEType = (char *)"video/h264";
avcportdefinition.format.video.pNativeRender = NULL;
avcportdefinition.format.video.nFrameWidth = 176;
avcportdefinition.format.video.nFrameHeight = 144;
avcportdefinition.format.video.nStride = 0;
avcportdefinition.format.video.nSliceHeight = 0;
avcportdefinition.format.video.nBitrate = 64000;
avcportdefinition.format.video.xFramerate = 15 << 16;
avcportdefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
avcportdefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
avcportdefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
avcportdefinition.format.video.pNativeWindow = NULL;
avcportdefinition.bBuffersContiguous = OMX_FALSE;
avcportdefinition.nBufferAlignment = 0;
avcport->SetPortDefinition(&avcportdefinition, true);
/* end of OMX_PARAM_PORTDEFINITIONTYPE */
/* OMX_VIDEO_PARAM_AVCTYPE */
memset(&avcportparam, 0, sizeof(avcportparam));
SetTypeHeader(&avcportparam, sizeof(avcportparam));
avcportparam.nPortIndex = port_index;
avcportparam.eProfile = OMX_VIDEO_AVCProfileBaseline;
avcportparam.eLevel = OMX_VIDEO_AVCLevel1;
avcport->SetPortAvcParam(&avcportparam, true);
/* end of OMX_VIDEO_PARAM_AVCTYPE */
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, OMX_ErrorNone);
return OMX_ErrorNone;
}
OMX_ERRORTYPE MrstPsbComponent::__AllocateRawPort(OMX_U32 port_index,
OMX_DIRTYPE dir)
{
PortVideo *rawport;
OMX_PARAM_PORTDEFINITIONTYPE rawportdefinition;
OMX_VIDEO_PARAM_PORTFORMATTYPE rawvideoparam;
LOGV("%s(): enter\n", __func__);
ports[port_index] = new PortVideo;
if (!ports[port_index]) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorInsufficientResources);
return OMX_ErrorInsufficientResources;
}
rawport = static_cast<PortVideo *>(this->ports[port_index]);
/* OMX_PARAM_PORTDEFINITIONTYPE */
memset(&rawportdefinition, 0, sizeof(rawportdefinition));
SetTypeHeader(&rawportdefinition, sizeof(rawportdefinition));
rawportdefinition.nPortIndex = port_index;
rawportdefinition.eDir = dir;
if (dir == OMX_DirInput) {
rawportdefinition.nBufferCountActual = INPORT_RAW_ACTUAL_BUFFER_COUNT;
rawportdefinition.nBufferCountMin = INPORT_RAW_MIN_BUFFER_COUNT;
rawportdefinition.nBufferSize = INPORT_RAW_BUFFER_SIZE;
}
else {
rawportdefinition.nBufferCountActual = OUTPORT_RAW_ACTUAL_BUFFER_COUNT;
rawportdefinition.nBufferCountMin = OUTPORT_RAW_MIN_BUFFER_COUNT;
rawportdefinition.nBufferSize = OUTPORT_RAW_BUFFER_SIZE;
}
rawportdefinition.bEnabled = OMX_TRUE;
rawportdefinition.bPopulated = OMX_FALSE;
rawportdefinition.eDomain = OMX_PortDomainVideo;
rawportdefinition.format.video.cMIMEType = (char *)"video/raw";
rawportdefinition.format.video.pNativeRender = NULL;
rawportdefinition.format.video.nFrameWidth = 176;
rawportdefinition.format.video.nFrameHeight = 144;
rawportdefinition.format.video.nStride = 0;
rawportdefinition.format.video.nSliceHeight = 0;
rawportdefinition.format.video.nBitrate = 64000;
rawportdefinition.format.video.xFramerate = 15 << 16;
rawportdefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
rawportdefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
rawportdefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
rawportdefinition.format.video.pNativeWindow = NULL;
rawportdefinition.bBuffersContiguous = OMX_FALSE;
rawportdefinition.nBufferAlignment = 0;
rawport->SetPortDefinition(&rawportdefinition, true);
/* end of OMX_PARAM_PORTDEFINITIONTYPE */
/* OMX_VIDEO_PARAM_PORTFORMATTYPE */
rawvideoparam.nPortIndex = port_index;
rawvideoparam.nIndex = 0;
rawvideoparam.eCompressionFormat = OMX_VIDEO_CodingUnused;
rawvideoparam.eColorFormat = OMX_COLOR_FormatYUV420Planar;
rawport->SetPortVideoParam(&rawvideoparam, true);
/* end of OMX_VIDEO_PARAM_PORTFORMATTYPE */
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, OMX_ErrorNone);
return OMX_ErrorNone;
}
/* end of core methods & helpers */
/*
* component methods & helpers
*/
/* Get/SetParameter */
OMX_ERRORTYPE MrstPsbComponent::ComponentGetParameter(
OMX_INDEXTYPE nParamIndex,
OMX_PTR pComponentParameterStructure)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter (index = 0x%08x)\n", __func__, nParamIndex);
switch (nParamIndex) {
case OMX_IndexParamVideoPortFormat: {
OMX_VIDEO_PARAM_PORTFORMATTYPE *p =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure;
OMX_U32 index = p->nPortIndex;
PortVideo *port = NULL;
LOGV("%s(): port index : %lu\n", __func__, index);
ret = CheckTypeHeader(p, sizeof(*p));
if (ret != OMX_ErrorNone) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
if (index < nr_ports)
port = static_cast<PortVideo *>(ports[index]);
if (!port) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorBadPortIndex);
return OMX_ErrorBadPortIndex;
}
memcpy(p, port->GetPortVideoParam(), sizeof(*p));
break;
}
case OMX_IndexParamVideoAvc: {
OMX_VIDEO_PARAM_AVCTYPE *p =
(OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure;
OMX_U32 index = p->nPortIndex;
PortAvc *port = NULL;
if (strcmp(GetWorkingRole(), "video_decoder.avc")) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorUnsupportedIndex);
return OMX_ErrorUnsupportedIndex;
}
ret = CheckTypeHeader(p, sizeof(*p));
if (ret != OMX_ErrorNone) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
if (index < nr_ports)
port = static_cast<PortAvc *>(ports[index]);
if (!port) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorBadPortIndex);
return OMX_ErrorBadPortIndex;
}
memcpy(p, port->GetPortAvcParam(), sizeof(*p));
break;
}
case (OMX_INDEXTYPE) PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX: {
PV_OMXComponentCapabilityFlagsType *p =
(PV_OMXComponentCapabilityFlagsType *)pComponentParameterStructure;
p->iIsOMXComponentMultiThreaded = OMX_TRUE;
p->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
p->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE;
#ifdef PV_FULL_AVC_FRAME_MODE
p->iOMXComponentSupportsMovableInputBuffers = OMX_FALSE;
p->iOMXComponentUsesNALStartCodes = OMX_FALSE;
p->iOMXComponentSupportsPartialFrames = OMX_FALSE;
p->iOMXComponentCanHandleIncompleteFrames = OMX_TRUE;
p->iOMXComponentUsesFullAVCFrames = OMX_TRUE;
#else
p->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
p->iOMXComponentUsesNALStartCodes = OMX_FALSE;
p->iOMXComponentSupportsPartialFrames = OMX_TRUE;
p->iOMXComponentCanHandleIncompleteFrames = OMX_TRUE;
p->iOMXComponentUsesFullAVCFrames = OMX_FALSE;
#endif
break;
}
default:
ret = OMX_ErrorUnsupportedIndex;
} /* switch */
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::ComponentSetParameter(
OMX_INDEXTYPE nIndex,
OMX_PTR pComponentParameterStructure)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter (index = 0x%08x)\n", __func__, nIndex);
switch (nIndex) {
case OMX_IndexParamVideoPortFormat: {
OMX_VIDEO_PARAM_PORTFORMATTYPE *p =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure;
OMX_U32 index = p->nPortIndex;
PortVideo *port = NULL;
ret = CheckTypeHeader(p, sizeof(*p));
if (ret != OMX_ErrorNone) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
if (index < nr_ports)
port = static_cast<PortVideo *>(ports[index]);
if (!port) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorBadPortIndex);
return OMX_ErrorBadPortIndex;
}
if (port->IsEnabled()) {
OMX_STATETYPE state;
CBaseGetState((void *)GetComponentHandle(), &state);
if (state != OMX_StateLoaded &&
state != OMX_StateWaitForResources) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorIncorrectStateOperation);
return OMX_ErrorIncorrectStateOperation;
}
}
ret = port->SetPortVideoParam(p, false);
break;
}
case OMX_IndexParamVideoAvc: {
OMX_VIDEO_PARAM_AVCTYPE *p =
(OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure;
OMX_U32 index = p->nPortIndex;
PortAvc *port = NULL;
ret = CheckTypeHeader(p, sizeof(*p));
if (ret != OMX_ErrorNone) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
if (index < nr_ports)
port = static_cast<PortAvc *>(ports[index]);
if (!port) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorBadPortIndex);
return OMX_ErrorBadPortIndex;
}
if (port->IsEnabled()) {
OMX_STATETYPE state;
CBaseGetState((void *)GetComponentHandle(), &state);
if (state != OMX_StateLoaded &&
state != OMX_StateWaitForResources) {
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__,
OMX_ErrorIncorrectStateOperation);
return OMX_ErrorIncorrectStateOperation;
}
}
ret = port->SetPortAvcParam(p, false);
break;
}
default:
ret = OMX_ErrorUnsupportedIndex;
} /* switch */
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
/* Get/SetConfig */
OMX_ERRORTYPE MrstPsbComponent::ComponentGetConfig(
OMX_INDEXTYPE nIndex,
OMX_PTR pComponentConfigStructure)
{
OMX_ERRORTYPE ret = OMX_ErrorUnsupportedIndex;
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::ComponentSetConfig(
OMX_INDEXTYPE nParamIndex,
OMX_PTR pComponentConfigStructure)
{
OMX_ERRORTYPE ret = OMX_ErrorUnsupportedIndex;
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
/* implement ComponentBase::Processor[*] */
OMX_ERRORTYPE MrstPsbComponent::ProcessorInit(void)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter\n", __func__);
if (coding_type == OMX_VIDEO_CodingAVC) {
/*
* avc decoder specific code
*/
}
/* decoder */
if (!isencoder) {
/*
* decoder specific code
*/
}
/*
* common codes
*/
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::ProcessorDeinit(void)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::ProcessorStart(void)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::ProcessorStop(void)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::ProcessorPause(void)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
OMX_ERRORTYPE MrstPsbComponent::ProcessorResume(void)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
LOGV("%s(): enter\n", __func__);
LOGV("%s(),%d: exit (ret = 0x%08x)\n", __func__, __LINE__, ret);
return ret;
}
/* implement ComponentBase::ProcessorProcess */
void MrstPsbComponent::ProcessorProcess(
OMX_BUFFERHEADERTYPE **buffers,
bool *retain,
OMX_U32 nr_buffers)
{
OMX_U32 outfilledlen = 0;
OMX_S64 outtimestamp = 0;
LOGV("%s(): enter\n", __func__);
DumpBuffer(buffers[INPORT_INDEX]);
if (!buffers[INPORT_INDEX]->nFilledLen) {
LOGE("%s(),%d: exit, input buffer's nFilledLen is zero (ret = void)\n",
__func__, __LINE__);
return;
}
/* decoder */
if (!isencoder) {
if ((buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) &&
(buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
/*
* processing codec data
*/
retain[OUTPORT_INDEX] = true;
}
if (coding_type == OMX_VIDEO_CodingAVC) {
/*
* avc decoding specific code
*/
}
/*
* decoding common code
*/
outfilledlen = buffers[OUTPORT_INDEX]->nAllocLen;
outtimestamp = buffers[INPORT_INDEX]->nTimeStamp;
}
buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen;
buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp;
//if (!retain[OUTPORT_INDEX])
// DumpBuffer(buffers[OUTPORT_INDEX]);
LOGV("%s(),%d: exit (ret = void)\n", __func__, __LINE__);
}
/* end of implement ComponentBase::Processor[*] */
/* end of component methods & helpers */
/*
* CModule Interface
*/
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
static const char *g_name = (const char *)"OMX.Intel.Mrst.PSB";
static const char *g_roles[] =
{
(const char *)"video_decoder.avc",
};
OMX_ERRORTYPE wrs_omxil_cmodule_ops_instantiate(OMX_PTR *instance)
{
ComponentBase *cbase;
cbase = new MrstPsbComponent;
if (!cbase) {
*instance = NULL;
return OMX_ErrorInsufficientResources;
}
*instance = cbase;
return OMX_ErrorNone;
}
struct wrs_omxil_cmodule_ops_s cmodule_ops = {
instantiate: wrs_omxil_cmodule_ops_instantiate,
};
struct wrs_omxil_cmodule_s WRS_OMXIL_CMODULE_SYMBOL = {
name: g_name,
roles: &g_roles[0],
nr_roles: ARRAY_SIZE(g_roles),
ops: &cmodule_ops,
};