blob: 780665d1c70cade200c85ea451639fe96426b631 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* 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.
* -------------------------------------------------------------------
*/
#include "pvmf_omx_videodec_node.h"
#include "pvlogger.h"
#include "oscl_error_codes.h"
#include "pvmf_omx_basedec_port.h"
#include "pv_mime_string_utils.h"
#include "oscl_snprintf.h"
#include "pvmf_media_cmd.h"
#include "pvmf_media_msg_format_ids.h"
#include "pvmi_kvp_util.h"
// needed for capability and config
#include "pv_omx_config_parser.h"
#include "OMX_Core.h"
#include "pvmf_omx_basedec_callbacks.h" //used for thin AO in Decoder's callbacks
#include "pv_omxcore.h"
#include "OMX_Video.h"
#include "utils/Log.h"
#undef LOG_TAG
#define LOG_TAG "PVOMXVidDecNode"
#define CONFIG_SIZE_AND_VERSION(param) \
param.nSize=sizeof(param); \
param.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; \
param.nVersion.s.nVersionMinor = SPECVERSIONMINOR; \
param.nVersion.s.nRevision = SPECREVISION; \
param.nVersion.s.nStep = SPECSTEP;
#define PVOMXVIDEODEC_EXTRA_YUVBUFFER_POOLNUM 3
#define PVOMXVIDEODEC_MEDIADATA_POOLNUM (PVOMXVIDEODECMAXNUMDPBFRAMESPLUS1 + PVOMXVIDEODEC_EXTRA_YUVBUFFER_POOLNUM)
// Node default settings
#define PVOMXVIDEODECNODE_CONFIG_POSTPROCENABLE_DEF false
#define PVOMXVIDEODECNODE_CONFIG_POSTPROCTYPE_DEF 0 // 0 (nopostproc),1(deblock),3(deblock&&dering)
#define PVOMXVIDEODECNODE_CONFIG_DROPFRAMEENABLE_DEF false
// H263 default settings
#define PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_DEF 40000
#define PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_MIN 20000
#define PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_MAX 120000
#define PVOMXVIDEODECNODE_CONFIG_H263MAXWIDTH_DEF 352
#define PVOMXVIDEODECNODE_CONFIG_H263MAXHEIGHT_DEF 288
#define PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MIN 4
#define PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MAX 352
// M4v default settings
#define PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_DEF 40000
#define PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_MIN 20000
#define PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_MAX 120000
#define PVOMXVIDEODECNODE_CONFIG_M4VMAXWIDTH_DEF 352
#define PVOMXVIDEODECNODE_CONFIG_M4VMAXHEIGHT_DEF 288
#define PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MIN 4
#define PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MAX 352
// AVC default settings
#define PVOMXVIDEODECNODE_CONFIG_AVCMAXBITSTREAMFRAMESIZE_DEF 20000
#define PVOMXVIDEODECNODE_CONFIG_AVCMAXBITSTREAMFRAMESIZE_MIN 20000
#define PVOMXVIDEODECNODE_CONFIG_AVCMAXBITSTREAMFRAMESIZE_MAX 120000
#define PVOMXVIDEODECNODE_CONFIG_AVCMAXWIDTH_DEF 352
#define PVOMXVIDEODECNODE_CONFIG_AVCMAXHEIGHT_DEF 288
#define PVOMXVIDEODECNODE_CONFIG_AVCMAXDIMENSION_MIN 4
#define PVOMXVIDEODECNODE_CONFIG_AVCMAXDIMENSION_MAX 352
/* WMV default settings */
#define PVOMXVIDEODECNODE_CONFIG_WMVMAXWIDTH_DEF 352
#define PVOMXVIDEODECNODE_CONFIG_WMVMAXHEIGHT_DEF 288
#define PVMF_OMXVIDEODEC_NUM_METADATA_VALUES 6
// Constant character strings for metadata keys
static const char PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY[] = "codec-info/video/format";
static const char PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY[] = "codec-info/video/width";
static const char PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY[] = "codec-info/video/height";
static const char PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY[] = "codec-info/video/profile";
static const char PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY[] = "codec-info/video/level";
static const char PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY[] = "codec-info/video/avgbitrate";//(bits per sec)
static const char PVOMXVIDEODECMETADATA_SEMICOLON[] = ";";
/////////////////////////////////////////////////////////////////////////////
// Class Destructor
/////////////////////////////////////////////////////////////////////////////
PVMFOMXVideoDecNode::~PVMFOMXVideoDecNode()
{
ReleaseAllPorts();
}
/////////////////////////////////////////////////////////////////////////////
// Add AO to the scheduler
/////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXVideoDecNode::ThreadLogon()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXVideoDecNode:ThreadLogon"));
switch (iInterfaceState)
{
case EPVMFNodeCreated:
if (!IsAdded())
{
AddToScheduler();
iIsAdded = true;
}
iLogger = PVLogger::GetLoggerObject("PVMFOMXVideoDecNode");
iRunlLogger = PVLogger::GetLoggerObject("Run.PVMFOMXVideoDecNode");
iDataPathLogger = PVLogger::GetLoggerObject("datapath");
iClockLogger = PVLogger::GetLoggerObject("clock");
iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.decnode.OMXVideoDecnode");
SetState(EPVMFNodeIdle);
return PVMFSuccess;
default:
return PVMFErrInvalidState;
}
}
/////////////////////
// Private Section //
/////////////////////
/////////////////////////////////////////////////////////////////////////////
// Class Constructor
/////////////////////////////////////////////////////////////////////////////
PVMFOMXVideoDecNode::PVMFOMXVideoDecNode(int32 aPriority, bool aHwAccelerated) :
PVMFOMXBaseDecNode(aPriority, "PVMFOMXVideoDecNode", aHwAccelerated),
iH263MaxBitstreamFrameSize(PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_DEF),
iH263MaxWidth(PVOMXVIDEODECNODE_CONFIG_H263MAXWIDTH_DEF),
iH263MaxHeight(PVOMXVIDEODECNODE_CONFIG_H263MAXHEIGHT_DEF),
iM4VMaxBitstreamFrameSize(PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_DEF),
iM4VMaxWidth(PVOMXVIDEODECNODE_CONFIG_M4VMAXWIDTH_DEF),
iM4VMaxHeight(PVOMXVIDEODECNODE_CONFIG_M4VMAXHEIGHT_DEF),
iNewWidth(0),
iNewHeight(0)
{
iInterfaceState = EPVMFNodeCreated;
iNodeConfig.iPostProcessingEnable = PVOMXVIDEODECNODE_CONFIG_POSTPROCENABLE_DEF;
iNodeConfig.iPostProcessingMode = PVOMXVIDEODECNODE_CONFIG_POSTPROCTYPE_DEF;
iNodeConfig.iDropFrame = PVOMXVIDEODECNODE_CONFIG_DROPFRAMEENABLE_DEF;
iNodeConfig.iMimeType = PVMF_MIME_FORMAT_UNKNOWN;
int32 err;
OSCL_TRY(err,
//Create the input command queue. Use a reserve to avoid lots of
//dynamic memory allocation.
iInputCommands.Construct(PVMF_OMXBASEDEC_NODE_COMMAND_ID_START, PVMF_OMXBASEDEC_NODE_COMMAND_VECTOR_RESERVE);
//Create the "current command" queue. It will only contain one
//command at a time, so use a reserve of 1.
iCurrentCommand.Construct(0, 1);
//Set the node capability data.
//This node can support an unlimited number of ports.
iCapability.iCanSupportMultipleInputPorts = false;
iCapability.iCanSupportMultipleOutputPorts = false;
iCapability.iHasMaxNumberOfPorts = true;
iCapability.iMaxNumberOfPorts = 2;
iCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_MP4);
iCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_RAW);
iCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO);
iCapability.iInputFormatCapability.push_back(PVMF_MIME_M4V);
iCapability.iInputFormatCapability.push_back(PVMF_MIME_H2631998);
iCapability.iInputFormatCapability.push_back(PVMF_MIME_H2632000);
iCapability.iInputFormatCapability.push_back(PVMF_MIME_WMV);
iCapability.iOutputFormatCapability.push_back(PVMF_MIME_YUV420);
iAvailableMetadataKeys.reserve(PVMF_OMXVIDEODEC_NUM_METADATA_VALUES);
iAvailableMetadataKeys.clear();
);
// need to init this allocator since verifyParameterSync (using the buffers) may be called through
// port interface before anything else happens.
OSCL_TRY(err, iFsiFragmentAlloc.size(PVOMXVIDEODEC_MEDIADATA_POOLNUM, sizeof(PVMFYuvFormatSpecificInfo0)));
OSCL_TRY(err, iPrivateDataFsiFragmentAlloc.size(PVOMXVIDEODEC_MEDIADATA_POOLNUM, sizeof(OsclAny *)));
iLastYUVWidth = 0;
iLastYUVHeight = 0;
iStride = 0;
iSliceHeight = 0;
}
/////////////////////////////////////////////////////////////////////////////
// This routine will handle the PortReEnable state
/////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXVideoDecNode::HandlePortReEnable()
{
// set the port index so that we get parameters for the proper port
iParamPort.nPortIndex = iPortIndexForDynamicReconfig;
CONFIG_SIZE_AND_VERSION(iParamPort);
// get new parameters of the port
OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
// send command for port re-enabling (for this to happen, we must first recreate the buffers)
OMX_SendCommand(iOMXDecoder, OMX_CommandPortEnable, iPortIndexForDynamicReconfig, NULL);
// is this output port?
if (iPortIndexForDynamicReconfig == iOutputPortIndex)
{
// set the new width / height
iYUVWidth = iParamPort.format.video.nFrameWidth;
iYUVHeight = iParamPort.format.video.nFrameHeight;
iOMXComponentOutputBufferSize = iParamPort.nBufferSize;
// do we need to increase the number of buffers?
if (iNumOutputBuffers < iParamPort.nBufferCountMin)
iNumOutputBuffers = iParamPort.nBufferCountMin;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() new output buffers %d, size %d", iNumOutputBuffers, iOMXComponentOutputBufferSize));
iStride = OSCL_ABS(iParamPort.format.video.nStride);
iSliceHeight = iParamPort.format.video.nSliceHeight;
// This should not happen. If it does, it is a bug in the OMX component.
OSCL_ASSERT( (iStride < iParamPort.format.video.nFrameWidth) || (iSliceHeight < iParamPort.format.video.nFrameHeight) );
if (iStride < iParamPort.format.video.nFrameWidth)
{
iStride = iParamPort.format.video.nFrameWidth;
}
if (iSliceHeight < iParamPort.format.video.nFrameHeight)
{
iSliceHeight = iParamPort.format.video.nFrameHeight;
}
// Before allocating new set of output buffers, re-send Video FSI to
// media output node in case of dynamic port reconfiguration
sendFsi = true;
iCompactFSISettingSucceeded = false;
iLastYUVWidth = iYUVWidth ;
iLastYUVHeight = iYUVHeight;
// Check if Fsi configuration need to be sent
if (sendFsi)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable - Re-sending YUV FSI after Dynamic port reconfiguration"));
int fsiErrorCode = 0;
OsclRefCounterMemFrag yuvFsiMemfrag;
OSCL_TRY(fsiErrorCode, yuvFsiMemfrag = iFsiFragmentAlloc.get(););
OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() Failed to allocate memory for FSI")));
if (fsiErrorCode == 0)
{
PVMFYuvFormatSpecificInfo0* fsiInfo = OSCL_PLACEMENT_NEW(yuvFsiMemfrag.getMemFragPtr(), PVMFYuvFormatSpecificInfo0());
if (fsiInfo != NULL)
{
fsiInfo->uid = PVMFYuvFormatSpecificInfo0_UID;
fsiInfo->video_format = iYUVFormat;
fsiInfo->display_width = iYUVWidth;
fsiInfo->display_height = iYUVHeight;
fsiInfo->num_buffers = iNumOutputBuffers;
fsiInfo->buffer_size = iOMXComponentOutputBufferSize;
fsiInfo->width = iStride;
fsiInfo->height = iSliceHeight;
OsclMemAllocator alloc;
int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY_YUV) + 1;
PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength);
if (NULL == KvpKey)
{
return false;
}
oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY_YUV, KeyLength);
int32 err;
OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(yuvFsiMemfrag, KvpKey););
if (err != OsclErrNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable - Problem to set FSI"));
}
else
{
sendFsi = false;
iCompactFSISettingSucceeded = true;
}
alloc.deallocate((OsclAny*)(KvpKey));
fsiInfo->video_format.~PVMFFormatType();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable - Problem allocating Output FSI"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return false; // this is going to make everything go out of scope
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable - Problem allocating Output FSI"));
return false; // this is going to make everything go out of scope
}
}
//Buffer allocation has to be done again in case we landed to port reconfiguration
PvmiKvp* kvp = NULL;
int numKvp = 0;
PvmiKeyType aIdentifier = (PvmiKeyType)PVMF_BUFFER_ALLOCATOR_KEY;
int32 err, err1;
ipExternalOutputBufferAllocatorInterface = NULL;
OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aIdentifier, kvp, numKvp););
if ((err == OsclErrNone) && (NULL != kvp))
{
ipExternalOutputBufferAllocatorInterface = (PVInterface*) kvp->value.key_specific_value;
if (ipExternalOutputBufferAllocatorInterface)
{
PVInterface* pTempPVInterfacePtr = NULL;
OSCL_TRY(err, ipExternalOutputBufferAllocatorInterface->queryInterface(PVMFFixedSizeBufferAllocUUID, pTempPVInterfacePtr););
OSCL_TRY(err1, ((PVMFOMXDecPort*)iOutPort)->releaseParametersSync(kvp, numKvp););
if (err1 != OsclErrNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable - Unable to Release Parameters"));
}
if ((err == OsclErrNone) && (NULL != pTempPVInterfacePtr))
{
ipFixedSizeBufferAlloc = OSCL_STATIC_CAST(PVMFFixedSizeBufferAlloc*, pTempPVInterfacePtr);
uint32 iNumBuffers, iBufferSize;
iNumBuffers = ipFixedSizeBufferAlloc->getNumBuffers();
iBufferSize = ipFixedSizeBufferAlloc->getBufferSize();
if ((iNumBuffers < iParamPort.nBufferCountMin) || (iBufferSize < iOMXComponentOutputBufferSize))
{
ipExternalOutputBufferAllocatorInterface->removeRef();
ipExternalOutputBufferAllocatorInterface = NULL;
}
else
{
iNumOutputBuffers = iNumBuffers;
iOMXComponentOutputBufferSize = iBufferSize;
}
}
else
{
ipExternalOutputBufferAllocatorInterface->removeRef();
ipExternalOutputBufferAllocatorInterface = NULL;
}
}
}
/* Allocate output buffers */
if (!CreateOutMemPool(iNumOutputBuffers))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot allocate output buffers "));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
if (out_ctrl_struct_ptr == NULL)
{
out_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *));
if (out_ctrl_struct_ptr == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() out_ctrl_struct_ptr == NULL"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
}
if (out_buff_hdr_ptr == NULL)
{
out_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *));
if (out_buff_hdr_ptr == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() out_buff_hdr_ptr == NULL"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
}
if (!ProvideBuffersToComponent(iOutBufMemoryPool, // allocator
iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer)
iNumOutputBuffers, // number of buffers
iOMXComponentOutputBufferSize, // actual buffer size
iOutputPortIndex, // port idx
iOMXComponentSupportsExternalOutputBufferAlloc, // can component use OMX_UseBuffer
false // this is not input
))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot provide output buffers to component"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
// do not drop output any more, i.e. enable output to be sent downstream
iDoNotSendOutputBuffersDownstreamFlag = false;
}
else
{
// this is input port
iOMXComponentInputBufferSize = iParamPort.nBufferSize;
// do we need to increase the number of buffers?
if (iNumInputBuffers < iParamPort.nBufferCountMin)
iNumInputBuffers = iParamPort.nBufferCountMin;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() new buffers %d, size %d", iNumInputBuffers, iOMXComponentInputBufferSize));
/* Allocate input buffers */
if (!CreateInputMemPool(iNumInputBuffers))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot allocate new input buffers to component"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
if (in_ctrl_struct_ptr == NULL)
{
in_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *));
if (in_ctrl_struct_ptr == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() in_ctrl_struct_ptr == NULL"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
}
if (in_buff_hdr_ptr == NULL)
{
in_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *));
if (in_buff_hdr_ptr == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() in_buff_hdr_ptr == NULL"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
}
if (!ProvideBuffersToComponent(iInBufMemoryPool, // allocator
iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer)
iNumInputBuffers, // number of buffers
iOMXComponentInputBufferSize, // actual buffer size
iInputPortIndex, // port idx
iOMXComponentSupportsExternalInputBufferAlloc, // can component use OMX_UseBuffer
true // this is input
))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot provide new input buffers to component"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return PVMFErrNoMemory;
}
// do not drop partially consumed input
iDoNotSaveInputBuffersFlag = false;
}
// if the callback that the port was re-enabled has not arrived yet, wait for it
// if it has arrived, it will set the state to either PortReconfig or to ReadyToDecode
if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_PortReconfig &&
iProcessingState != EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode)
iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForPortEnable;
return PVMFSuccess; // allow rescheduling of the node
}
////////////////////////////////////////////////////////////////////////////////
bool PVMFOMXVideoDecNode::NegotiateComponentParameters(OMX_PTR aOutputParameters)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() In"));
OMX_ERRORTYPE Err;
// first get the number of ports and port indices
OMX_PORT_PARAM_TYPE VideoPortParameters;
uint32 NumPorts;
uint32 ii;
//set version and size;
CONFIG_SIZE_AND_VERSION(VideoPortParameters);
// get starting number
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamVideoInit, &VideoPortParameters);
NumPorts = VideoPortParameters.nPorts; // must be at least 2 of them (in&out)
if (Err != OMX_ErrorNone || NumPorts < 2)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() There is insuffucient (%d) ports", NumPorts));
return false;
}
// loop through video ports starting from the starting index to find index of the first input port
for (ii = VideoPortParameters.nStartPortNumber ; ii < VideoPortParameters.nStartPortNumber + NumPorts; ii++)
{
// get port parameters, and determine if it is input or output
// if there are more than 2 ports, the first one we encounter that has input direction is picked
CONFIG_SIZE_AND_VERSION(iParamPort);
//port
iParamPort.nPortIndex = ii; // iInputPortIndex; //OMF_MC_H264D_PORT_INDEX_OF_STREAM;
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem negotiating with port %d ", ii));
return false;
}
if (iParamPort.eDir == OMX_DirInput)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Found Input port index %d ", ii));
iInputPortIndex = ii;
break;
}
}
if (ii == VideoPortParameters.nStartPortNumber + NumPorts)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Cannot find any input port "));
return false;
}
// loop through video ports starting from the starting index to find index of the first output port
for (ii = VideoPortParameters.nStartPortNumber ; ii < VideoPortParameters.nStartPortNumber + NumPorts; ii++)
{
// get port parameters, and determine if it is input or output
// if there are more than 2 ports, the first one we encounter that has output direction is picked
CONFIG_SIZE_AND_VERSION(iParamPort);
//port
iParamPort.nPortIndex = ii;
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem negotiating with port %d ", ii));
return false;
}
if (iParamPort.eDir == OMX_DirOutput)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Found Output port index %d ", ii));
iOutputPortIndex = ii;
break;
}
}
if (ii == VideoPortParameters.nStartPortNumber + NumPorts)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Cannot find any output port "));
return false;
}
// now get input parameters
CONFIG_SIZE_AND_VERSION(iParamPort);
//Input port
iParamPort.nPortIndex = iInputPortIndex;
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem negotiating with input port %d ", iInputPortIndex));
return false;
}
// preset the number of input buffers
//iNumInputBuffers = NUMBER_INPUT_BUFFER;
iNumInputBuffers = iParamPort.nBufferCountActual; // use the value provided by component
// do we need to increase the number of buffers?
if (iNumInputBuffers < iParamPort.nBufferCountMin)
iNumInputBuffers = iParamPort.nBufferCountMin;
iOMXComponentInputBufferSize = iParamPort.nBufferSize;
iParamPort.nBufferCountActual = iNumInputBuffers;
// set the number of actual input buffers
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Inport buffers %d,size %d", iNumInputBuffers, iOMXComponentInputBufferSize));
VideoOMXConfigParserOutputs *pOutputParameters;
pOutputParameters = (VideoOMXConfigParserOutputs *)aOutputParameters;
// set the width/height on INPUT port parameters (this may change during port reconfig)
if ((pOutputParameters->width != 0) && (pOutputParameters->height != 0))
{
iParamPort.format.video.nFrameWidth = pOutputParameters->width;
iParamPort.format.video.nFrameHeight = pOutputParameters->height;
}
CONFIG_SIZE_AND_VERSION(iParamPort);
Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting parameters in input port %d ", iInputPortIndex));
return false;
}
//Port 1 for output port
iParamPort.nPortIndex = iOutputPortIndex;
CONFIG_SIZE_AND_VERSION(iParamPort);
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem negotiating with output port %d ", iOutputPortIndex));
return false;
}
// check if params are OK. In case of H263, width/height cannot be obtained until
// 1st frame is decoded, so read them from the output port.
// otherwise, used Width/Height from the config parser utility
// set the width/height based on port parameters (this may change during port reconfig)
if ((pOutputParameters->width != 0) && (pOutputParameters->height != 0) && iInPort && (((PVMFOMXDecPort*)iInPort)->iFormat != PVMF_MIME_H2631998 || ((PVMFOMXDecPort*)iInPort)->iFormat != PVMF_MIME_H2632000))
{
// set width and height obtained from config parser in the output port as well
iParamPort.format.video.nFrameWidth = pOutputParameters->width;
iParamPort.format.video.nFrameHeight = pOutputParameters->height;
iYUVWidth = pOutputParameters->width;
iYUVHeight = pOutputParameters->height;
}
else
{
iYUVWidth = iParamPort.format.video.nFrameWidth;
iYUVHeight = iParamPort.format.video.nFrameHeight;
}
// Send the parameters right away to allow the OMX component to re-calculate the buffer size
// based on the new width and height that was just provided
CONFIG_SIZE_AND_VERSION(iParamPort);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Outport buffers %d,size %d", iNumOutputBuffers, iOMXComponentOutputBufferSize));
Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting parameters in output port %d ", iOutputPortIndex));
return false;
}
// Now - read the same parameters back again with potentially new buffer sizes
iParamPort.nPortIndex = iOutputPortIndex;
CONFIG_SIZE_AND_VERSION(iParamPort);
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem negotiating with output port %d ", iOutputPortIndex));
return false;
}
//iNumOutputBuffers = NUMBER_OUTPUT_BUFFER;
iNumOutputBuffers = iParamPort.nBufferCountActual;
if (iNumOutputBuffers > NUMBER_OUTPUT_BUFFER)
iNumOutputBuffers = NUMBER_OUTPUT_BUFFER; // make sure number of output buffers is not larger than port queue size
iOMXComponentOutputBufferSize = iParamPort.nBufferSize;
if (iNumOutputBuffers < iParamPort.nBufferCountMin)
iNumOutputBuffers = iParamPort.nBufferCountMin;
iStride = OSCL_ABS(iParamPort.format.video.nStride);
iSliceHeight = iParamPort.format.video.nSliceHeight;
// This should not happen. If it does, it is a bug in the OMX component.
OSCL_ASSERT( (iStride < iParamPort.format.video.nFrameWidth) || (iSliceHeight < iParamPort.format.video.nFrameHeight) );
if (iStride < iParamPort.format.video.nFrameWidth)
{
iStride = iParamPort.format.video.nFrameWidth;
}
if(iSliceHeight < iParamPort.format.video.nFrameHeight)
{
iSliceHeight = iParamPort.format.video.nFrameHeight;
}
//Send the FSI information to media output node here, before setting output
//port parameters to the omx component
if (iLastYUVWidth != iYUVWidth || iYUVHeight != iLastYUVHeight)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters - Sending YUV FSI"));
// set a flag to send Fsi configuration
sendFsi = true;
iCompactFSISettingSucceeded = false;
//store new values for reference
iLastYUVWidth = iYUVWidth ;
iLastYUVHeight = iYUVHeight;
}
{
// Get video color format
OMX_VIDEO_PARAM_PORTFORMATTYPE VideoPortFormat;
// init to unknown
iOMXVideoColorFormat = OMX_COLOR_FormatUnused;
CONFIG_SIZE_AND_VERSION(VideoPortFormat);
VideoPortFormat.nPortIndex = iOutputPortIndex;
VideoPortFormat.nIndex = 0; // read the preferred format - first
// doing this in a while loop while incrementing nIndex will get all supported formats
// until component says OMX_ErrorNoMore
// For now, we just use the preferred one (with nIndex=0) assuming it is supported at MIO
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamVideoPortFormat, &VideoPortFormat);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem getting video port format"));
return false;
}
// check if color format is valid and set DeBlocking
if (VideoPortFormat.eCompressionFormat == OMX_VIDEO_CodingUnused)
{
// color format is valid, so read it
iOMXVideoColorFormat = VideoPortFormat.eColorFormat;
// Now set the format to confirm parameters
CONFIG_SIZE_AND_VERSION(VideoPortFormat);
Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamVideoPortFormat, &VideoPortFormat);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting video port format"));
return false;
}
}
// now that we have the color format, interpret it
if (iOMXVideoColorFormat == OMX_COLOR_Format8bitRGB332)
{
iYUVFormat = PVMF_MIME_RGB8;
}
else if (iOMXVideoColorFormat == OMX_COLOR_Format12bitRGB444)
{
iYUVFormat = PVMF_MIME_RGB12;
}
else if (iOMXVideoColorFormat >= OMX_COLOR_Format16bitARGB4444 && iOMXVideoColorFormat <= OMX_COLOR_Format16bitBGR565)
{
iYUVFormat = PVMF_MIME_RGB16;
}
else if (iOMXVideoColorFormat >= OMX_COLOR_Format24bitRGB888 && iOMXVideoColorFormat <= OMX_COLOR_Format24bitARGB1887)
{
iYUVFormat = PVMF_MIME_RGB24;
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV420Planar)
{
iYUVFormat = PVMF_MIME_YUV420_PLANAR; // Y, U, V are separate - entire planes
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV420PackedPlanar)
{
iYUVFormat = PVMF_MIME_YUV420_PACKEDPLANAR; // each slice contains Y,U,V separate
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)
{
iYUVFormat = PVMF_MIME_YUV420_SEMIPLANAR; // Y and UV interleaved - entire planes
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar)
{
iYUVFormat = PVMF_MIME_YUV420_PACKEDSEMIPLANAR; // Y and UV interleaved - sliced
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV422Planar)
{
iYUVFormat = PVMF_MIME_YUV422_PLANAR; // Y, U, V are separate - entire planes
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV422PackedPlanar)
{
iYUVFormat = PVMF_MIME_YUV422_PACKEDPLANAR; // each slice contains Y,U,V separate
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV422SemiPlanar)
{
iYUVFormat = PVMF_MIME_YUV422_SEMIPLANAR; // Y and UV interleaved - entire planes
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatYUV422PackedSemiPlanar)
{
iYUVFormat = PVMF_MIME_YUV422_PACKEDSEMIPLANAR; // Y and UV interleaved - sliced
}
else if (iOMXVideoColorFormat == OMX_COLOR_FormatCbYCrY)
{
iYUVFormat = PVMF_MIME_YUV422_INTERLEAVED_UYVY; // Y, U, V interleaved
}
else if (iOMXVideoColorFormat == 0x7FA30C00) // SPECIAL VALUE
{
iYUVFormat = PVMF_MIME_YUV420_SEMIPLANAR_YVU; // semiplanar with Y and VU interleaved
}
else
{
iYUVFormat = PVMF_MIME_FORMAT_UNKNOWN;
return false;
}
}
// Check if Fsi configuration need to be sent
if (sendFsi)
{
int fsiErrorCode = 0;
OsclRefCounterMemFrag yuvFsiMemfrag;
OSCL_TRY(fsiErrorCode, yuvFsiMemfrag = iFsiFragmentAlloc.get(););
OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Failed to allocate memory for FSI")));
if (fsiErrorCode == 0)
{
PVMFYuvFormatSpecificInfo0* fsiInfo = OSCL_PLACEMENT_NEW(yuvFsiMemfrag.getMemFragPtr(), PVMFYuvFormatSpecificInfo0());
if (fsiInfo != NULL)
{
fsiInfo->uid = PVMFYuvFormatSpecificInfo0_UID;
fsiInfo->video_format = iYUVFormat;
fsiInfo->display_width = iYUVWidth;
fsiInfo->display_height = iYUVHeight;
fsiInfo->num_buffers = iNumOutputBuffers;
fsiInfo->buffer_size = iOMXComponentOutputBufferSize;
fsiInfo->width = iStride;
fsiInfo->height = iSliceHeight;
OsclMemAllocator alloc;
int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY_YUV) + 1;
PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength);
if (NULL == KvpKey)
{
return false;
}
oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY_YUV, KeyLength);
int32 err;
OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(yuvFsiMemfrag, KvpKey););
if (err != OsclErrNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters - Problem to set FSI"));
}
else
{
iCompactFSISettingSucceeded = true;
sendFsi = false;
}
alloc.deallocate((OsclAny*)(KvpKey));
fsiInfo->video_format.~PVMFFormatType();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters - Problem allocating Output FSI"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return false; // this is going to make everything go out of scope
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters - Problem allocating Output FSI"));
return false; // this is going to make everything go out of scope
}
}
//Try querying the buffer allocator KVP for output buffer allocation outside the node
PvmiKvp* kvp = NULL;
int numKvp = 0;
PvmiKeyType aIdentifier = (PvmiKeyType)PVMF_BUFFER_ALLOCATOR_KEY;
int32 err, err1;
ipExternalOutputBufferAllocatorInterface = NULL;
OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aIdentifier, kvp, numKvp););
if ((err == OsclErrNone) && (NULL != kvp))
{
ipExternalOutputBufferAllocatorInterface = (PVInterface*) kvp->value.key_specific_value;
if (ipExternalOutputBufferAllocatorInterface)
{
PVInterface* pTempPVInterfacePtr = NULL;
OSCL_TRY(err, ipExternalOutputBufferAllocatorInterface->queryInterface(PVMFFixedSizeBufferAllocUUID, pTempPVInterfacePtr););
OSCL_TRY(err1, ((PVMFOMXDecPort*)iOutPort)->releaseParametersSync(kvp, numKvp););
if (err1 != OsclErrNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters - Unable to Release Parameters"));
}
if ((err == OsclErrNone) && (NULL != pTempPVInterfacePtr))
{
ipFixedSizeBufferAlloc = OSCL_STATIC_CAST(PVMFFixedSizeBufferAlloc*, pTempPVInterfacePtr);
uint32 iNumBuffers, iBufferSize;
iNumBuffers = ipFixedSizeBufferAlloc->getNumBuffers();
iBufferSize = ipFixedSizeBufferAlloc->getBufferSize();
if ((iNumBuffers < iParamPort.nBufferCountMin) || (iBufferSize < iOMXComponentOutputBufferSize))
{
ipExternalOutputBufferAllocatorInterface->removeRef();
ipExternalOutputBufferAllocatorInterface = NULL;
}
else
{
iNumOutputBuffers = iNumBuffers;
iOMXComponentOutputBufferSize = iBufferSize;
}
}
else
{
ipExternalOutputBufferAllocatorInterface->removeRef();
ipExternalOutputBufferAllocatorInterface = NULL;
}
}
}
iParamPort.nBufferCountActual = iNumOutputBuffers;
CONFIG_SIZE_AND_VERSION(iParamPort);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Outport buffers %d,size %d", iNumOutputBuffers, iOMXComponentOutputBufferSize));
Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting parameters in output port %d ", iOutputPortIndex));
return false;
}
//Set input video format
//This is need it since a single component could handle differents roles
// Init to desire format
PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN;
if (iInPort != NULL)
{
Format = ((PVMFOMXDecPort*)iInPort)->iFormat;
}
if (Format == PVMF_MIME_H264_VIDEO ||
Format == PVMF_MIME_H264_VIDEO_MP4 ||
Format == PVMF_MIME_H264_VIDEO_RAW)
{
iOMXVideoCompressionFormat = OMX_VIDEO_CodingAVC;
}
else if (Format == PVMF_MIME_M4V)
{
iOMXVideoCompressionFormat = OMX_VIDEO_CodingMPEG4;
}
else if (Format == PVMF_MIME_H2631998 ||
Format == PVMF_MIME_H2632000)
{
iOMXVideoCompressionFormat = OMX_VIDEO_CodingH263;
}
else if (Format == PVMF_MIME_WMV)
{
iOMXVideoCompressionFormat = OMX_VIDEO_CodingWMV;
}
else
{
// Illegal codec specified.
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting video compression format"));
return false;
}
if ((iOMXVideoCompressionFormat == OMX_VIDEO_CodingMPEG4) ||
(iOMXVideoCompressionFormat == OMX_VIDEO_CodingH263))
{
// Enable deblocking for these two video types
OMX_PARAM_DEBLOCKINGTYPE DeBlock;
CONFIG_SIZE_AND_VERSION(DeBlock);
DeBlock.nPortIndex = iOutputPortIndex;
DeBlock.bDeblocking = OMX_TRUE;
Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamCommonDeblocking, &DeBlock);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting deblocking flag"));
// Dont return false in this case. If enabling DeBlocking fails, just continue.
}
}
OMX_VIDEO_PARAM_PORTFORMATTYPE VideoPortFormat;
CONFIG_SIZE_AND_VERSION(VideoPortFormat);
VideoPortFormat.nPortIndex = iInputPortIndex;
// Search the proper format index and set it.
// Since we already know that the component has the role we need, search until finding the proper nIndex
// if component does not find the format will return OMX_ErrorNoMore
for (ii = 0;; ii++)
{
VideoPortFormat.nIndex = ii;
Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamVideoPortFormat, &VideoPortFormat);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting video compression format"));
return false;
}
if (iOMXVideoCompressionFormat == VideoPortFormat.eCompressionFormat)
{
break;
}
}
// Now set the format to confirm parameters
Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamVideoPortFormat, &VideoPortFormat);
if (Err != OMX_ErrorNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::NegotiateComponentParameters() Problem setting video compression format"));
return false;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
bool PVMFOMXVideoDecNode::InitDecoder(PVMFSharedMediaDataPtr& DataIn)
{
OSCL_UNUSED_ARG(DataIn);
uint16 length = 0, size = 0;
uint8 *tmp_ptr;
PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN;
OsclRefCounterMemFrag DataFrag;
OsclRefCounterMemFrag refCtrMemFragOut;
// NOTE: the component may not start decoding without providing the Output buffer to it,
// here, we're sending input/config buffers.
// Then, we'll go to ReadyToDecode state and send output as well
if (iInPort != NULL)
{
Format = ((PVMFOMXDecPort*)iInPort)->iFormat;
}
if (Format == PVMF_MIME_H264_VIDEO ||
Format == PVMF_MIME_H264_VIDEO_MP4)
{
uint8* initbuffer = ((PVMFOMXDecPort*)iInPort)->getTrackConfig();
int32 initbufsize = (int32)((PVMFOMXDecPort*)iInPort)->getTrackConfigSize();
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::InitDecoder() for H264 Decoder. Initialization data Size %d.", initbufsize));
if (initbufsize > 0)
{
// there may be more than 1 NAL in config info in format specific data memfragment (SPS, PPS)
tmp_ptr = initbuffer;
do
{
length = (uint16)(tmp_ptr[1] << 8) | tmp_ptr[0];
size += (length + 2);
if (size > initbufsize)
break;
tmp_ptr += 2;
if (!SendConfigBufferToOMXComponent(tmp_ptr, length))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::InitDecoder() Error in processing config buffer"));
return false;
}
tmp_ptr += length;
}
while (size < initbufsize);
}
}
else if (Format == PVMF_MIME_M4V ||
Format == PVMF_MIME_H2631998 ||
Format == PVMF_MIME_H2632000)
{
uint8* initbuffer = ((PVMFOMXDecPort*)iInPort)->getTrackConfig();
int32 initbufsize = (int32)((PVMFOMXDecPort*)iInPort)->getTrackConfigSize();
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::InitDecoder() for H263 Decoder. Initialization data Size %d.", initbufsize));
// for H263, the initbufsize is 0, and initbuf= NULL. Config is done after 1st frame of data
if (initbufsize > 0)
{
if (!SendConfigBufferToOMXComponent(initbuffer, initbufsize))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::InitDecoder() Error in processing config buffer"));
return false;
}
}
}
else if (Format == PVMF_MIME_WMV)
{
uint8* initbuffer = ((PVMFOMXDecPort*)iInPort)->getTrackConfig();
int32 initbufsize = (int32)((PVMFOMXDecPort*)iInPort)->getTrackConfigSize();
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::InitDecoder() for WMV Decoder. Initialization data Size %d.", initbufsize));
if (initbufsize > 0)
{
if (!SendConfigBufferToOMXComponent(initbuffer, initbufsize))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::InitDecoder() Error in processing config buffer"));
return false;
}
}
}
else
{
// Unknown codec type
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::InitDecoder() Unknown codec type"));
return false;
}
//Varibles initialization
//sendFsi = true;
return true;
}
/////////////////////////////////////////////////////////////////////////////
////////////////////// CALLBACK PROCESSING FOR EVENT HANDLER
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE PVMFOMXVideoDecNode::EventHandlerProcessing(OMX_OUT OMX_HANDLETYPE aComponent,
OMX_OUT OMX_PTR aAppData,
OMX_OUT OMX_EVENTTYPE aEvent,
OMX_OUT OMX_U32 aData1,
OMX_OUT OMX_U32 aData2,
OMX_OUT OMX_PTR aEventData)
{
OSCL_UNUSED_ARG(aComponent);
OSCL_UNUSED_ARG(aAppData);
OSCL_UNUSED_ARG(aEventData);
switch (aEvent)
{
case OMX_EventCmdComplete:
{
switch (aData1)
{
case OMX_CommandStateSet:
{
HandleComponentStateChange(aData2);
break;
}
case OMX_CommandFlush:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_CommandFlush - completed on port %d", aData2));
if (iIsRepositioningRequestSentToComponent)
{
if (aData2 == iOutputPortIndex)
{
iIsOutputPortFlushed = true;
}
else if (aData2 == iInputPortIndex)
{
iIsInputPortFlushed = true;
}
if (iIsOutputPortFlushed && iIsInputPortFlushed)
{
iIsRepositionDoneReceivedFromComponent = true;
}
}
if (IsAdded())
RunIfNotReady();
}
break;
case OMX_CommandPortDisable:
{
// if port disable command is done, we can re-allocate the buffers and re-enable the port
iProcessingState = EPVMFOMXBaseDecNodeProcessingState_PortReEnable;
iPortIndexForDynamicReconfig = aData2;
RunIfNotReady();
break;
}
case OMX_CommandPortEnable:
// port enable command is done. Check if the other port also reported change.
// If not, we can start data flow. Otherwise, must start dynamic reconfig procedure for
// the other port as well.
{
if (iSecondPortReportedChange)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_CommandPortEnable - completed on port %d, dynamic reconfiguration needed on port %d", aData2, iSecondPortToReconfig));
iProcessingState = EPVMFOMXBaseDecNodeProcessingState_PortReconfig;
iPortIndexForDynamicReconfig = iSecondPortToReconfig;
iSecondPortReportedChange = false;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_CommandPortEnable - completed on port %d, resuming normal data flow", aData2));
iProcessingState = EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode;
iDynamicReconfigInProgress = false;
// in case pause or stop command was sent to component
// change processing state (because the node might otherwise
// start sending buffers to component before pause/stop is processed)
if (iPauseCommandWasSentToComponent)
{
iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Pausing;
}
if (iStopCommandWasSentToComponent)
{
iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Stopping;
}
}
RunIfNotReady();
break;
}
case OMX_CommandMarkBuffer:
// nothing to do here yet;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_CommandMarkBuffer - completed - no action taken"));
break;
default:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: Unsupported event"));
break;
}
}//end of switch (aData1)
break;
}//end of case OMX_EventCmdComplete
case OMX_EventError:
{
LOGE("Ln %d OMX_EventError nData1 %d nData2 %d", __LINE__, aData1, aData2);
if (aData1 == (OMX_U32) OMX_ErrorStreamCorrupt)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventError - Bitstream corrupt error"));
// Errors from corrupt bitstream are reported as info events
ReportInfoEvent(PVMFInfoProcessingFailure, NULL);
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventError"));
// for now, any error from the component will be reported as error
ReportErrorEvent(PVMFErrProcessing, NULL, NULL);
SetState(EPVMFNodeError);
}
break;
}
case OMX_EventBufferFlag:
{
// the component is reporting it encountered end of stream flag
// we'll send eos when we get the actual last buffer with marked eos
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventBufferFlag (EOS) flag returned from OMX component"));
RunIfNotReady();
break;
}//end of case OMX_EventBufferFlag
case OMX_EventMark:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventMark returned from OMX component - no action taken"));
RunIfNotReady();
break;
}//end of case OMX_EventMark
case OMX_EventPortSettingsChanged:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventPortSettingsChanged returned from OMX component"));
// first check if dynamic reconfiguration is already in progress,
// if so, wait until this is completed, and then initiate the 2nd reconfiguration
if (iDynamicReconfigInProgress)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d, dynamic reconfig already in progress", aData1));
iSecondPortToReconfig = aData1;
iSecondPortReportedChange = true;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d", aData1));
iProcessingState = EPVMFOMXBaseDecNodeProcessingState_PortReconfig;
iPortIndexForDynamicReconfig = aData1;
iDynamicReconfigInProgress = true;
}
RunIfNotReady();
break;
}//end of case OMX_PortSettingsChanged
case OMX_EventResourcesAcquired: //not supported
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: OMX_EventResourcesAcquired returned from OMX component - no action taken"));
RunIfNotReady();
break;
}
default:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::EventHandlerProcessing: Unknown Event returned from OMX component - no action taken"));
break;
}
}//end of switch (eEvent)
return OMX_ErrorNone;
}
////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Put output buffer in outgoing queue //////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
bool PVMFOMXVideoDecNode::QueueOutputBuffer(OsclSharedPtr<PVMFMediaDataImpl> &mediadataimplout, uint32 aDataLen)
{
bool status = true;
PVMFSharedMediaDataPtr mediaDataOut;
int32 leavecode = OsclErrNone;
// NOTE: ASSUMPTION IS THAT OUTGOING QUEUE IS BIG ENOUGH TO QUEUE ALL THE OUTPUT BUFFERS
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame: In"));
// First check if we can put outgoing msg. into the queue
if (iOutPort->IsOutgoingQueueBusy())
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame() OutgoingQueue is busy"));
return false;
}
OSCL_TRY(leavecode,
mediaDataOut = PVMFMediaData::createMediaData(mediadataimplout, iMediaDataMemPool););
if (OsclErrNone == leavecode)
{
// Update the filled length of the fragment
mediaDataOut->setMediaFragFilledLen(0, aDataLen);
// Set timestamp
mediaDataOut->setTimestamp(iOutTimeStamp);
// Set Streamid
mediaDataOut->setStreamID(iStreamID);
// Set sequence number
mediaDataOut->setSeqNum(iSeqNum++);
PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iDataPathLogger, PVLOGMSG_INFO, (0, ":PVMFOMXVideoDecNode::QueueOutputFrame(): - SeqNum=%d, TS=%d", iSeqNum, iOutTimeStamp));
int fsiErrorCode = 0;
// Check if Fsi configuration need to be sent
if (sendFsi && !iCompactFSISettingSucceeded)
{
OsclRefCounterMemFrag yuvFsiMemfrag;
OSCL_TRY(fsiErrorCode, yuvFsiMemfrag = iFsiFragmentAlloc.get(););
OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::RemoveOutputFrame() Failed to allocate memory for FSI")));
if (fsiErrorCode == 0)
{
PVMFYuvFormatSpecificInfo0* fsiInfo = OSCL_PLACEMENT_NEW(yuvFsiMemfrag.getMemFragPtr(), PVMFYuvFormatSpecificInfo0());
if (fsiInfo != NULL)
{
fsiInfo->uid = PVMFYuvFormatSpecificInfo0_UID;
fsiInfo->video_format = iYUVFormat;
fsiInfo->display_width = iYUVWidth;
fsiInfo->display_height = iYUVHeight;
fsiInfo->width = iStride;
fsiInfo->height = iSliceHeight;
fsiInfo->buffer_size = iOMXComponentOutputBufferSize;
OsclMemAllocator alloc;
int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY) + 1;
PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength);
if (NULL == KvpKey)
{
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return false;
}
oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY, KeyLength);
int32 err;
OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(yuvFsiMemfrag, KvpKey););
if (err != OsclErrNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::HandlePortReEnable - Problem to set FSI"));
}
alloc.deallocate((OsclAny*)(KvpKey));
fsiInfo->video_format.~PVMFFormatType();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame - Problem allocating Output FSI"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return false; // this is going to make everything go out of scope
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame - Problem allocating Output FSI"));
return false; // this is going to make everything go out of scope
}
// Reset the flag
sendFsi = false;
}
// in case of special YVU format, attach fsi to every outgoing message containing ptr to private data
if (iYUVFormat == PVMF_MIME_YUV420_SEMIPLANAR_YVU)
{
OsclRefCounterMemFrag privatedataFsiMemFrag;
OSCL_TRY(fsiErrorCode, privatedataFsiMemFrag = iPrivateDataFsiFragmentAlloc.get(););
OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::RemoveOutputFrame() Failed to allocate memory for FSI for private data")));
if (fsiErrorCode == 0)
{
uint8 *fsiptr = (uint8*) privatedataFsiMemFrag.getMemFragPtr();
privatedataFsiMemFrag.getMemFrag().len = sizeof(OsclAny*);
oscl_memcpy(fsiptr, &ipPrivateData, sizeof(OsclAny *)); // store ptr data into fsi
mediaDataOut->setFormatSpecificInfo(privatedataFsiMemFrag);
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame - Problem allocating Output FSI for private data"));
SetState(EPVMFNodeError);
ReportErrorEvent(PVMFErrNoMemory);
return false; // this is going to make everything go out of scope
}
}
if (fsiErrorCode == 0)
{
// Send frame to downstream node
PVMFSharedMediaMsgPtr mediaMsgOut;
convertToPVMFMediaMsg(mediaMsgOut, mediaDataOut);
if (iOutPort && (iOutPort->QueueOutgoingMsg(mediaMsgOut) == PVMFSuccess))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame(): Queued frame OK "));
}
else
{
// we should not get here because we always check for whether queue is busy or not
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame(): Send frame failed"));
return false;
}
}
}//end of if (leavecode==0)
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::QueueOutputFrame() call PVMFMediaData::createMediaData is failed"));
return false;
}
return status;
}
/////////////////////////////////////////////////////////////////////////////
void PVMFOMXVideoDecNode::DoRequestPort(PVMFOMXBaseDecNodeCommand& aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::DoRequestPort() In"));
//This node supports port request from any state
//retrieve port tag.
int32 tag;
OSCL_String* portconfig;
aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(tag, portconfig);
PVMFPortInterface* port = NULL;
int32 leavecode = OsclErrNone;
//validate the tag...
switch (tag)
{
case PVMF_OMX_DEC_NODE_PORT_TYPE_INPUT:
if (iInPort)
{
CommandComplete(iInputCommands, aCmd, PVMFFailure);
break;
}
OSCL_TRY(leavecode, iInPort = OSCL_NEW(PVMFOMXDecPort, ((int32)tag, this, PVMF_OMX_VIDEO_DEC_INPUT_PORT_NAME)););
if (leavecode || iInPort == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::DoRequestPort: Error - Input port instantiation failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
return;
}
port = iInPort;
break;
case PVMF_OMX_DEC_NODE_PORT_TYPE_OUTPUT:
if (iOutPort)
{
CommandComplete(iInputCommands, aCmd, PVMFFailure);
break;
}
OSCL_TRY(leavecode, iOutPort = OSCL_NEW(PVMFOMXDecPort, ((int32)tag, this, PVMF_OMX_VIDEO_DEC_OUTPUT_PORT_NAME)));
if (leavecode || iOutPort == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::DoRequestPort: Error - Output port instantiation failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
return;
}
port = iOutPort;
break;
default:
//bad port tag
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFOMXVideoDecNode::DoRequestPort: Error - Invalid port tag"));
CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
return;
}
//Return the port pointer to the caller.
CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port);
}
/////////////////////////////////////////////////////////////////////////////
void PVMFOMXVideoDecNode::DoReleasePort(PVMFOMXBaseDecNodeCommand& aCmd)
{
PVMFPortInterface* p = NULL;
aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(p);
PVMFOMXDecPort* port = (PVMFOMXDecPort*)p;
if (port != NULL && (port == iInPort || port == iOutPort))
{
if (port == iInPort)
{
OSCL_DELETE(((PVMFOMXDecPort*)iInPort));
iInPort = NULL;
}
else
{
OSCL_DELETE(((PVMFOMXDecPort*)iOutPort));
iOutPort = NULL;
}
//delete the port.
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
else
{
//port not found.
CommandComplete(iInputCommands, aCmd, PVMFFailure);
}
}
/////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXVideoDecNode::DoGetNodeMetadataKey(PVMFOMXBaseDecNodeCommand& aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFOMXVideoDecNode::DoGetNodeMetadataKey() In"));
PVMFMetadataList* keylistptr = NULL;
uint32 starting_index;
int32 max_entries;
char* query_key;
aCmd.PVMFOMXBaseDecNodeCommand::Parse(keylistptr, starting_index, max_entries, query_key);
// Check parameters
if (keylistptr == NULL)
{
// The list pointer is invalid
return PVMFErrArgument;
}
// Update the available metadata keys
iAvailableMetadataKeys.clear();
int32 leavecode = OsclErrNone;
leavecode = PushKVPKey(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY, iAvailableMetadataKeys);
if (OsclErrNone != leavecode)
{
return PVMFErrNoMemory;
}
if (iYUVWidth > 0 && iYUVHeight > 0)
{
leavecode = OsclErrNone;
leavecode = PushKVPKey(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY, iAvailableMetadataKeys);
if (OsclErrNone != leavecode)
{
return PVMFErrNoMemory;
}
leavecode = OsclErrNone;
leavecode = PushKVPKey(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY, iAvailableMetadataKeys);
if (OsclErrNone != leavecode)
{
return PVMFErrNoMemory;
}
}
// add the profile, level and avgbitrate
PVMF_MPEGVideoProfileType aProfile;
PVMF_MPEGVideoLevelType aLevel;
if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
{
// For H263 this metadata will be available only after first frame decoding
leavecode = OsclErrNone;
leavecode = PushKVPKey(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY, iAvailableMetadataKeys);
if (leavecode != OsclErrNone)
{
return PVMFErrNoMemory;
}
leavecode = OsclErrNone;
leavecode = PushKVPKey(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY, iAvailableMetadataKeys);
if (OsclErrNone != leavecode)
{
return PVMFErrNoMemory;
}
}
leavecode = OsclErrNone;
leavecode = PushKVPKey(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY, iAvailableMetadataKeys);
if (OsclErrNone != leavecode)
{
return PVMFErrNoMemory;
}
if ((starting_index > (iAvailableMetadataKeys.size() - 1)) || max_entries == 0)
{
// Invalid starting index and/or max entries
return PVMFErrArgument;
}
// Copy the requested keys
uint32 num_entries = 0;
int32 num_added = 0;
for (uint32 lcv = 0; lcv < iAvailableMetadataKeys.size(); lcv++)
{
if (query_key == NULL)
{
// No query key so this key is counted
++num_entries;
if (num_entries > starting_index)
{
// Past the starting index so copy the key
leavecode = OsclErrNone;
leavecode = PushKVPKey(iAvailableMetadataKeys[lcv] , keylistptr);
if (OsclErrNone != leavecode)
{
return PVMFErrNoMemory;
}
num_added++;
}
}
else
{
// Check if the key matche the query key
if (pv_mime_strcmp(iAvailableMetadataKeys[lcv].get_cstr(), query_key) >= 0)
{
// This key is counted
++num_entries;
if (num_entries > starting_index)
{
// Past the starting index so copy the key
leavecode = OsclErrNone;
leavecode = PushKVPKey(iAvailableMetadataKeys[lcv] , keylistptr);
if (OsclErrNone != leavecode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetNodeMetadataKey() Memory allocation failure when copying metadata key"));
return PVMFErrNoMemory;
}
num_added++;
}
}
}
// Check if max number of entries have been copied
if (max_entries > 0 && num_added >= max_entries)
{
break;
}
}
return PVMFSuccess;
}
/////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXVideoDecNode::DoGetNodeMetadataValue(PVMFOMXBaseDecNodeCommand& aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoGetNodeMetadataValue() In"));
PVMFMetadataList* keylistptr = NULL;
Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL;
uint32 starting_index;
int32 max_entries;
aCmd.PVMFOMXBaseDecNodeCommand::Parse(keylistptr, valuelistptr, starting_index, max_entries);
// Check the parameters
if (keylistptr == NULL || valuelistptr == NULL)
{
return PVMFErrArgument;
}
uint32 numkeys = keylistptr->size();
if (starting_index > (numkeys - 1) || numkeys <= 0 || max_entries == 0)
{
// Don't do anything
return PVMFErrArgument;
}
uint32 numvalentries = 0;
int32 numentriesadded = 0;
for (uint32 lcv = 0; lcv < numkeys; lcv++)
{
int32 leavecode = OsclErrNone;
int32 leavecode1 = OsclErrNone;
PvmiKvp KeyVal;
KeyVal.key = NULL;
uint32 KeyLen = 0;
if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY) == 0) &&
iYUVWidth > 0)
{
// Video width
// Increment the counter for the number of values found so far
++numvalentries;
// Create a value entry if past the starting index
if (numvalentries > starting_index)
{
KeyLen = oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY) + 1; // for "codec-info/video/width;"
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
// Allocate memory for the string
leavecode = OsclErrNone;
KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
if (OsclErrNone == leavecode)
{
// Copy the key string
oscl_strncpy(KeyVal.key, PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY, oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY) + 1);
oscl_strncat(KeyVal.key, PVOMXVIDEODECMETADATA_SEMICOLON, oscl_strlen(PVOMXVIDEODECMETADATA_SEMICOLON));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
// Copy the value
KeyVal.value.uint32_value = iYUVWidth;
// Set the length and capacity
KeyVal.length = 1;
KeyVal.capacity = 1;
}
else
{
// Memory allocation failed
KeyVal.key = NULL;
break;
}
}
}
else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) == 0) &&
iYUVHeight > 0)
{
// Video height
// Increment the counter for the number of values found so far
++numvalentries;
// Create a value entry if past the starting index
if (numvalentries > starting_index)
{
KeyLen = oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) + 1; // for "codec-info/video/height;"
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
// Allocate memory for the string
leavecode = OsclErrNone;
KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
if (OsclErrNone == leavecode)
{
// Copy the key string
oscl_strncpy(KeyVal.key, PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY, oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) + 1);
oscl_strncat(KeyVal.key, PVOMXVIDEODECMETADATA_SEMICOLON, oscl_strlen(PVOMXVIDEODECMETADATA_SEMICOLON));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
// Copy the value
KeyVal.value.uint32_value = iYUVHeight;
// Set the length and capacity
KeyVal.length = 1;
KeyVal.capacity = 1;
}
else
{
// Memory allocation failed
KeyVal.key = NULL;
break;
}
}
}
else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY) == 0))
{
// Video profile
// Increment the counter for the number of values found so far
++numvalentries;
// Create a value entry if past the starting index
if (numvalentries > starting_index)
{
KeyLen = oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY) + 1; // for "codec-info/video/profile;"
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
// Allocate memory for the string
leavecode = OsclErrNone;
KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
if (OsclErrNone == leavecode)
{
PVMF_MPEGVideoProfileType aProfile;
PVMF_MPEGVideoLevelType aLevel;
if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
{
// Copy the key string
oscl_strncpy(KeyVal.key, PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY, oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY) + 1);
oscl_strncat(KeyVal.key, PVOMXVIDEODECMETADATA_SEMICOLON, oscl_strlen(PVOMXVIDEODECMETADATA_SEMICOLON));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
// Copy the value
KeyVal.value.uint32_value = (uint32)aProfile; // This is to be decided, who will interpret these value
// Set the length and capacity
KeyVal.length = 1;
KeyVal.capacity = 1;
}
else
{
// Memory allocation failed
KeyVal.key = NULL;
break;
}
}
else
{
// Memory allocation failed
KeyVal.key = NULL;
break;
}
}
}
else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY) == 0))
{
// Video level
// Increment the counter for the number of values found so far
++numvalentries;
// Create a value entry if past the starting index
if (numvalentries > starting_index)
{
KeyLen = oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY) + 1; // for "codec-info/video/level;"
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
// Allocate memory for the string
leavecode = OsclErrNone;
KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
if (OsclErrNone == leavecode)
{
PVMF_MPEGVideoProfileType aProfile;
PVMF_MPEGVideoLevelType aLevel;
if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
{
// Copy the key string
oscl_strncpy(KeyVal.key, PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY, oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY) + 1);
oscl_strncat(KeyVal.key, PVOMXVIDEODECMETADATA_SEMICOLON, oscl_strlen(PVOMXVIDEODECMETADATA_SEMICOLON));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
// Copy the value
KeyVal.value.uint32_value = (uint32)aLevel; // This is to be decided, who will interpret these value
// Set the length and capacity
KeyVal.length = 1;
KeyVal.capacity = 1;
}
else
{
// Memory allocation failed
KeyVal.key = NULL;
break;
}
}
else
{
// Memory allocation failed
KeyVal.key = NULL;
break;
}
}
}
else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) == 0) &&
(iAvgBitrateValue > 0))
{
// Video average bitrate
// Increment the counter for the number of values found so far
++numvalentries;
// Create a value entry if past the starting index
if (numvalentries > starting_index)
{
KeyLen = oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) + 1; // for "codec-info/video/avgbitrate;"
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
// Allocate memory for the string
leavecode = OsclErrNone;
KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
if (OsclErrNone == leavecode)
{
// Copy the key string
oscl_strncpy(KeyVal.key, PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY, oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) + 1);
oscl_strncat(KeyVal.key, PVOMXVIDEODECMETADATA_SEMICOLON, oscl_strlen(PVOMXVIDEODECMETADATA_SEMICOLON));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
// Copy the value
KeyVal.value.uint32_value = iAvgBitrateValue;
// Set the length and capacity
KeyVal.length = 1;
KeyVal.capacity = 1;
}
else
{
// Memory allocation failed
KeyVal.key = NULL;
break;
}
}
}
else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY) == 0) &&
(((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2631998 || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2632000 ||
((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_M4V ||
((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4 ||
((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMV))
{
// Format
// Increment the counter for the number of values found so far
++numvalentries;
// Create a value entry if past the starting index
if (numvalentries > starting_index)
{
KeyLen = oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY) + 1; // for "codec-info/video/format;"
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
KeyLen += oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR) + 1; // for "char*" and NULL terminator
uint32 valuelen = 0;
if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO)
{
valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO)) + 1; // Value string plus one for NULL terminator
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4)
{
valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO_MP4)) + 1; // Value string plus one for NULL terminator
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW)
{
valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO_RAW)) + 1; // Value string plus one for NULL terminator
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_M4V)
{
valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_M4V)) + 1; // Value string plus one for NULL terminator
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2631998)
{
valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H2631998)) + 1; // Value string plus one for NULL terminator
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2632000)
{
valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H2632000)) + 1; // Value string plus one for NULL terminator
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMV)
{
valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_WMV)) + 1; // Value string plus one for NULL terminator
}
else
{
// Should not enter here
OSCL_ASSERT(false);
valuelen = 1;
}
// Allocate memory for the strings
leavecode = OsclErrNone;
KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
if (OsclErrNone == leavecode)
{
KeyVal.value.pChar_value = (char*) AllocateKVPKeyArray(leavecode1, PVMI_KVPVALTYPE_CHARPTR, valuelen);
}
if (OsclErrNone == leavecode && OsclErrNone == leavecode1)
{
// Copy the key string
oscl_strncpy(KeyVal.key, PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY, oscl_strlen(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY) + 1);
oscl_strncat(KeyVal.key, PVOMXVIDEODECMETADATA_SEMICOLON, oscl_strlen(PVOMXVIDEODECMETADATA_SEMICOLON));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR));
KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
// Copy the value
if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO)
{
oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO), valuelen);
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4)
{
oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO_MP4), valuelen);
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW)
{
oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO_RAW), valuelen);
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_M4V)
{
oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_M4V), valuelen);
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2631998)
{
oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2631998), valuelen);
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2632000)
{
oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2632000), valuelen);
}
else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMV)
{
oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_WMV), valuelen);
}
else
{
// Should not enter here
OSCL_ASSERT(false);
}
KeyVal.value.pChar_value[valuelen-1] = NULL_TERM_CHAR;
// Set the length and capacity
KeyVal.length = valuelen;
KeyVal.capacity = valuelen;
}
else
{
// Memory allocation failed so clean up
if (KeyVal.key)
{
OSCL_ARRAY_DELETE(KeyVal.key);
KeyVal.key = NULL;
}
if (KeyVal.value.pChar_value)
{
OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
}
break;
}
}
}
if (KeyVal.key != NULL)
{
leavecode = OsclErrNone;
leavecode = PushKVP(KeyVal, *valuelistptr);
if (OsclErrNone != leavecode)
{
switch (GetValTypeFromKeyString(KeyVal.key))
{
case PVMI_KVPVALTYPE_CHARPTR:
if (KeyVal.value.pChar_value != NULL)
{
OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
KeyVal.value.pChar_value = NULL;
}
break;
default:
// Add more case statements if other value types are returned
break;
}
OSCL_ARRAY_DELETE(KeyVal.key);
KeyVal.key = NULL;
}
else
{
// Increment the counter for number of value entries added to the list
++numentriesadded;
}
// Check if the max number of value entries were added
if (max_entries > 0 && numentriesadded >= max_entries)
{
break;
}
}
}
return PVMFSuccess;
}
/////////////////////////////////////////////////////////////////////////////
bool PVMFOMXVideoDecNode::ReleaseAllPorts()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::ReleaseAllPorts() In"));
if (iInPort)
{
iInPort->ClearMsgQueues();
iInPort->Disconnect();
OSCL_DELETE(((PVMFOMXDecPort*)iInPort));
iInPort = NULL;
}
if (iOutPort)
{
iOutPort->ClearMsgQueues();
iOutPort->Disconnect();
OSCL_DELETE(((PVMFOMXDecPort*)iOutPort));
iOutPort = NULL;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
void PVMFOMXVideoDecNode::DoQueryUuid(PVMFOMXBaseDecNodeCommand& aCmd)
{
//This node supports Query UUID from any state
OSCL_String* mimetype;
Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
bool exactmatch;
aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
//Try to match the input mimetype against any of
//the custom interfaces for this node
//Match against custom interface1...
if (*mimetype == PVMF_OMX_BASE_DEC_NODE_CUSTOM1_MIMETYPE
//also match against base mimetypes for custom interface1,
//unless exactmatch is set.
|| (!exactmatch && *mimetype == PVMF_OMX_VIDEO_DEC_NODE_MIMETYPE)
|| (!exactmatch && *mimetype == PVMF_BASEMIMETYPE))
{
PVUuid uuid(PVMF_OMX_BASE_DEC_NODE_CUSTOM1_UUID);
uuidvec->push_back(uuid);
}
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
/////////////////////////////////////////////////////////////////////////////
uint32 PVMFOMXVideoDecNode::GetNumMetadataKeys(char* aQueryKeyString)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::GetNumMetadataKeys() called"));
// Update the available metadata keys
iAvailableMetadataKeys.clear();
int32 errcode = OsclErrNone;
OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY));
if (iYUVWidth > 0 && iYUVHeight > 0)
{
errcode = OsclErrNone;
OSCL_TRY(errcode,
iAvailableMetadataKeys.push_back(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY);
iAvailableMetadataKeys.push_back(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY));
}
// add the profile, level and avgbitrate
PVMF_MPEGVideoProfileType aProfile;
PVMF_MPEGVideoLevelType aLevel;
if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
{
// For H263 this metadata will be available only after first frame decoding
errcode = OsclErrNone;
OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY));
errcode = OsclErrNone;
OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY));
}
errcode = OsclErrNone;
OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY));
uint32 num_entries = 0;
if (aQueryKeyString == NULL)
{
num_entries = iAvailableMetadataKeys.size();
}
else
{
for (uint32 i = 0; i < iAvailableMetadataKeys.size(); i++)
{
if (pv_mime_strcmp(iAvailableMetadataKeys[i].get_cstr(), aQueryKeyString) >= 0)
{
num_entries++;
}
}
}
return num_entries; // Number of elements
}
/////////////////////////////////////////////////////////////////////////////
uint32 PVMFOMXVideoDecNode::GetNumMetadataValues(PVMFMetadataList& aKeyList)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::GetNumMetadataValues() called"));
uint32 numkeys = aKeyList.size();
if (numkeys <= 0)
{
// Don't do anything
return 0;
}
// Count the number of value entries for the provided key list
uint32 numvalentries = 0;
PVMF_MPEGVideoProfileType aProfile;
PVMF_MPEGVideoLevelType aLevel;
for (uint32 lcv = 0; lcv < numkeys; lcv++)
{
if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_WIDTH_KEY) == 0) &&
iYUVWidth > 0)
{
// Video width
++numvalentries;
}
else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) == 0) &&
iYUVHeight > 0)
{
// Video height
++numvalentries;
}
else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_PROFILE_KEY) == 0) &&
(GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess))
{
// Video profile
++numvalentries;
}
else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_LEVEL_KEY) == 0) &&
(GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess))
{
// Video level
++numvalentries;
}
else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) == 0) &&
(iAvgBitrateValue > 0))
{
// Video average bitrate
if (iAvgBitrateValue > 0)
++numvalentries;
}
else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXVIDEODECMETADATA_CODECINFO_VIDEO_FORMAT_KEY) == 0) &&
(((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMV || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_M4V || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2631998 || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H2632000 || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4 || ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW))
{
// Format
++numvalentries;
}
}
return numvalentries;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// CAPABILITY CONFIG PRIVATE
PVMFStatus PVMFOMXVideoDecNode::DoCapConfigGetParametersSync(PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() In"));
OSCL_UNUSED_ARG(aContext);
// Initialize the output parameters
aNumParamElements = 0;
aParameters = NULL;
// Count the number of components and parameters in the key
int compcount = pv_mime_string_compcnt(aIdentifier);
// Retrieve the first component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(0, aIdentifier, compstr);
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/decoder")) < 0) || compcount < 3)
{
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/render")) < 0) || compcount != 3)
{
// First 3 component should be "x-pvmf/video/decoder" and there must
// be at least three components
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigReleaseParameters() Unsupported key"));
return PVMFErrArgument;
}
}
if (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/render")) >= 0)
{
aParameters = (PvmiKvp*)oscl_malloc(PVOMXVIDEODECNODECONFIG_RENDER_NUMKEYS * sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, PVOMXVIDEODECNODECONFIG_RENDER_NUMKEYS*sizeof(PvmiKvp));
// Allocate memory for the key strings in each KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXVIDEODECNODECONFIG_RENDER_NUMKEYS * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, PVOMXVIDEODECNODECONFIG_RENDER_NUMKEYS*PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to each KVP
int32 j;
for (j = 0; j < PVOMXVIDEODECNODECONFIG_RENDER_NUMKEYS; ++j)
{
aParameters[j].key = memblock + (j * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE);
}
// Copy the requested info
for (j = 0; j < PVOMXVIDEODECNODECONFIG_RENDER_NUMKEYS; ++j)
{
oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/video/render/"), 20);
oscl_strncat(aParameters[j].key, PVOMXVideoDecNodeConfigRenderKeys[j].iString, oscl_strlen(PVOMXVideoDecNodeConfigRenderKeys[j].iString));
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";valtype=uint32_value"), 21);
aParameters[j].key[PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE-1] = 0;
// Copy the requested info
switch (j)
{
case 0: // "width"
// Return current value
aParameters[j].value.uint32_value = iNewWidth;
break;
case 1: // "height"
aParameters[j].value.uint32_value = iNewHeight;
break;
default:
break;
}
}
aNumParamElements = PVOMXVIDEODECNODECONFIG_RENDER_NUMKEYS;
}
else if (compcount == 3)
{
// Since key is "x-pvmf/video/decoder" return all
// nodes available at this level. Ignore attribute
// since capability is only allowed
// Allocate memory for the KVP list
aParameters = (PvmiKvp*)oscl_malloc(PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS * sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS*sizeof(PvmiKvp));
// Allocate memory for the key strings in each KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS*PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to each KVP
int32 j;
for (j = 0; j < PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS; ++j)
{
aParameters[j].key = memblock + (j * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE);
}
// Copy the requested info
for (j = 0; j < PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS; ++j)
{
oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/video/decoder/"), 21);
oscl_strncat(aParameters[j].key, PVOMXVideoDecNodeConfigBaseKeys[j].iString, oscl_strlen(PVOMXVideoDecNodeConfigBaseKeys[j].iString));
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";type="), 6);
switch (PVOMXVideoDecNodeConfigBaseKeys[j].iType)
{
case PVMI_KVPTYPE_AGGREGATE:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_AGGREGATE_STRING), oscl_strlen(PVMI_KVPTYPE_AGGREGATE_STRING));
break;
case PVMI_KVPTYPE_POINTER:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_POINTER_STRING), oscl_strlen(PVMI_KVPTYPE_POINTER_STRING));
break;
case PVMI_KVPTYPE_VALUE:
default:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_VALUE_STRING), oscl_strlen(PVMI_KVPTYPE_VALUE_STRING));
// Now append the valtype param
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";valtype="), 9);
switch (PVOMXVideoDecNodeConfigBaseKeys[j].iValueType)
{
case PVMI_KVPVALTYPE_BITARRAY32:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BITARRAY32_STRING), oscl_strlen(PVMI_KVPVALTYPE_BITARRAY32_STRING));
break;
case PVMI_KVPVALTYPE_UINT32:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
break;
case PVMI_KVPVALTYPE_BOOL:
default:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING));
break;
}
break;
}
aParameters[j].key[PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE-1] = 0;
}
aNumParamElements = PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS;
}
else
{
// Retrieve the fourth component from the key string
pv_mime_string_extract_type(3, aIdentifier, compstr);
for (int32 vdeccomp4ind = 0; vdeccomp4ind < PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS; ++vdeccomp4ind)
{
// Go through each video dec component string at 4th level
if (pv_mime_strcmp(compstr, (char*)(PVOMXVideoDecNodeConfigBaseKeys[vdeccomp4ind].iString)) >= 0)
{
if (vdeccomp4ind == 3)
{
// "x-pvmf/video/decoder/h263"
if (compcount == 4)
{
// Return list of H263 settings. Ignore the
// attribute since capability is only allowed
// Allocate memory for the KVP list
aParameters = (PvmiKvp*)oscl_malloc(PVOMXVIDEODECNODECONFIG_H263_NUMKEYS * sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, PVOMXVIDEODECNODECONFIG_H263_NUMKEYS*sizeof(PvmiKvp));
// Allocate memory for the key strings in each KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXVIDEODECNODECONFIG_H263_NUMKEYS * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, PVOMXVIDEODECNODECONFIG_H263_NUMKEYS*PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to each KVP
int32 j;
for (j = 0; j < PVOMXVIDEODECNODECONFIG_H263_NUMKEYS; ++j)
{
aParameters[j].key = memblock + (j * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE);
}
// Copy the requested info
for (j = 0; j < PVOMXVIDEODECNODECONFIG_H263_NUMKEYS; ++j)
{
oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/video/decoder/h263/"), 26);
oscl_strncat(aParameters[j].key, PVOMXVideoDecNodeConfigH263Keys[j].iString, oscl_strlen(PVOMXVideoDecNodeConfigH263Keys[j].iString));
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";type=value;valtype="), 20);
switch (PVOMXVideoDecNodeConfigH263Keys[j].iValueType)
{
case PVMI_KVPVALTYPE_RANGE_UINT32:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
break;
case PVMI_KVPVALTYPE_UINT32:
default:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
break;
}
aParameters[j].key[PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE-1] = 0;
}
aNumParamElements = PVOMXVIDEODECNODECONFIG_H263_NUMKEYS;
}
else if (compcount > 4)
{
// Retrieve the fifth component from the key string
pv_mime_string_extract_type(4, aIdentifier, compstr);
for (int32 vdeccomp5ind = 0; vdeccomp5ind < PVOMXVIDEODECNODECONFIG_H263_NUMKEYS; ++vdeccomp5ind)
{
if (pv_mime_strcmp(compstr, (char*)(PVOMXVideoDecNodeConfigH263Keys[vdeccomp5ind].iString)) >= 0)
{
// Determine what is requested
PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier);
if (reqattr == PVMI_KVPATTR_UNKNOWN)
{
// Default is current setting
reqattr = PVMI_KVPATTR_CUR;
}
// Return the requested info
PVMFStatus retval = DoGetH263DecoderParameter(aParameters, aNumParamElements, vdeccomp5ind, reqattr);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Retrieving H.263 parameter failed"));
return retval;
}
// Break out of the for(vdeccomp5ind) loop
break;
}
}
}
else
{
// Right now video dec node doesn't support more than 5 components
// for the key sub-string so error out
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Unsupported key"));
return PVMFErrArgument;
}
}
else if (vdeccomp4ind == 4)
{
// "x-pvmf/video/decoder/m4v"
if (compcount == 4)
{
// Return list of M4v settings. Ignore the
// attribute since capability is only allowed
// Allocate memory for the KVP list
aParameters = (PvmiKvp*)oscl_malloc(PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS * sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS*sizeof(PvmiKvp));
// Allocate memory for the key strings in each KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS*PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to each KVP
int32 j;
for (j = 0; j < PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS; ++j)
{
aParameters[j].key = memblock + (j * PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE);
}
// Copy the requested info
for (j = 0; j < PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS; ++j)
{
oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/video/decoder/m4v/"), 25);
oscl_strncat(aParameters[j].key, PVOMXVideoDecNodeConfigM4VKeys[j].iString, oscl_strlen(PVOMXVideoDecNodeConfigM4VKeys[j].iString));
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";type=value;valtype="), 20);
switch (PVOMXVideoDecNodeConfigM4VKeys[j].iValueType)
{
case PVMI_KVPVALTYPE_RANGE_UINT32:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
break;
case PVMI_KVPVALTYPE_UINT32:
default:
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
break;
}
aParameters[j].key[PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE-1] = 0;
}
aNumParamElements = PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS;
}
else if (compcount > 4)
{
// Retrieve the fifth component from the key string
pv_mime_string_extract_type(4, aIdentifier, compstr);
for (int32 vdeccomp5ind = 0; vdeccomp5ind < PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS; ++vdeccomp5ind)
{
if (pv_mime_strcmp(compstr, (char*)(PVOMXVideoDecNodeConfigM4VKeys[vdeccomp5ind].iString)) >= 0)
{
// Determine what is requested
PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier);
if (reqattr == PVMI_KVPATTR_UNKNOWN)
{
// Default is current setting
reqattr = PVMI_KVPATTR_CUR;
}
// Return the requested info
PVMFStatus retval = DoGetM4VDecoderParameter(aParameters, aNumParamElements, vdeccomp5ind, reqattr);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Retrieving M4v parameter failed"));
return retval;
}
// Break out of the for(vdeccomp5ind) loop
break;
}
}
}
else
{
// Right now video dec node doesn't support more than 5 components
// for the key sub-string so error out
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Unsupported key"));
return PVMFErrArgument;
}
}
else if ((vdeccomp4ind == 0) || // "postproc_enable",
(vdeccomp4ind == 1) || // "postproc_type"
(vdeccomp4ind == 2) || // "dropframe_enable"
(vdeccomp4ind == 5) // "format_type"
)
{
if (compcount == 4)
{
// Determine what is requested
PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier);
if (reqattr == PVMI_KVPATTR_UNKNOWN)
{
reqattr = PVMI_KVPATTR_CUR;
}
// Return the requested info
PVMFStatus retval = DoGetVideoDecNodeParameter(aParameters, aNumParamElements, vdeccomp4ind, reqattr);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Retrieving video dec node parameter failed"));
return retval;
}
}
else
{
// Right now videodec node doesn't support more than 4 components
// for this sub-key string so error out
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Unsupported key"));
return PVMFErrArgument;
}
}
// Breakout of the for(vdeccomp4ind) loop
break;
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Out"));
if (aNumParamElements == 0)
{
// If no one could get the parameter, return error
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Unsupported key"));
return PVMFFailure;
}
else
{
return PVMFSuccess;
}
}
PVMFStatus PVMFOMXVideoDecNode::DoCapConfigReleaseParameters(PvmiKvp* aParameters, int aNumElements)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigReleaseParameters() In"));
if (aParameters == NULL || aNumElements < 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigReleaseParameters() KVP list is NULL or number of elements is 0"));
return PVMFErrArgument;
}
// Count the number of components and parameters in the key
int compcount = pv_mime_string_compcnt(aParameters[0].key);
// Retrieve the first component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(0, aParameters[0].key, compstr);
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/decoder")) < 0) || compcount < 3)
{
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/render")) < 0) || compcount != 4)
{
// First 3 component should be "x-pvmf/video/decoder" and there must
// be at least three components
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigReleaseParameters() Unsupported key"));
return PVMFErrArgument;
}
}
if (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/decoder")) >= 0)
{
// Retrieve the third component from the key string
pv_mime_string_extract_type(2, aParameters[0].key, compstr);
// Go through each KVP and release memory for value if allocated from heap
for (int32 i = 0; i < aNumElements; ++i)
{
// Next check if it is a value type that allocated memory
PvmiKvpType kvptype = GetTypeFromKeyString(aParameters[i].key);
if (kvptype == PVMI_KVPTYPE_VALUE || kvptype == PVMI_KVPTYPE_UNKNOWN)
{
PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameters[i].key);
if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigReleaseParameters() Valtype not specified in key string"));
return PVMFErrArgument;
}
if (keyvaltype == PVMI_KVPVALTYPE_CHARPTR && aParameters[i].value.pChar_value != NULL)
{
oscl_free(aParameters[i].value.pChar_value);
aParameters[i].value.pChar_value = NULL;
}
else if (keyvaltype == PVMI_KVPVALTYPE_KSV && aParameters[i].value.key_specific_value != NULL)
{
oscl_free(aParameters[i].value.key_specific_value);
aParameters[i].value.key_specific_value = NULL;
}
else if (keyvaltype == PVMI_KVPVALTYPE_RANGE_UINT32 && aParameters[i].value.key_specific_value != NULL)
{
range_uint32* rui32 = (range_uint32*)aParameters[i].value.key_specific_value;
aParameters[i].value.key_specific_value = NULL;
oscl_free(rui32);
}
}
}
}
// Video dec node allocated its key strings in one chunk so just free the first key string ptr
oscl_free(aParameters[0].key);
// Free memory for the parameter list
oscl_free(aParameters);
aParameters = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigReleaseParameters() Out"));
return PVMFSuccess;
}
void PVMFOMXVideoDecNode::DoCapConfigSetParameters(PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() In"));
if (aParameters == NULL || aNumElements < 1)
{
if (aParameters)
{
aRetKVP = aParameters;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Passed in parameter invalid"));
return;
}
// Go through each parameter
for (int32 paramind = 0; paramind < aNumElements; ++paramind)
{
// Count the number of components and parameters in the key
int compcount = pv_mime_string_compcnt(aParameters[paramind].key);
// Retrieve the first component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(0, aParameters[paramind].key, compstr);
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/decoder")) < 0) || compcount < 4)
{
// First 3 components should be "x-pvmf/video/decoder" and there must
// be at least four components
aRetKVP = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Unsupported key"));
return;
}
if (compcount == 4)
{
// Verify and set the passed-in video dec node setting
PVMFStatus retval = DoVerifyAndSetVideoDecNodeParameter(aParameters[paramind], true);
if (retval != PVMFSuccess)
{
aRetKVP = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Setting parameter %d failed", paramind));
return;
}
}
else if (compcount == 5)
{
// Determine the 4th level component
pv_mime_string_extract_type(3, aParameters[paramind].key, compstr);
if (pv_mime_strcmp(compstr, _STRLIT_CHAR("h263")) >= 0)
{
// Verify and set the passed-in H.263 decoder setting
PVMFStatus retval = DoVerifyAndSetH263DecoderParameter(aParameters[paramind], true);
if (retval != PVMFSuccess)
{
aRetKVP = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Setting parameter %d failed", paramind));
return;
}
}
else if (pv_mime_strcmp(compstr, _STRLIT_CHAR("m4v")) >= 0)
{
// Verify and set the passed-in M4v decoder setting
PVMFStatus retval = DoVerifyAndSetM4VDecoderParameter(aParameters[paramind], true);
if (retval != PVMFSuccess)
{
aRetKVP = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Setting parameter %d failed", paramind));
return;
}
}
else
{
// Unknown key sub-string
aRetKVP = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Unsupported key"));
return;
}
}
else
{
// Do not support more than 5 components right now
aRetKVP = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Unsupported key"));
return;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigSetParameters() Out"));
}
/* This function finds a nal from the SC's, moves the bitstream pointer to the beginning of the NAL unit, returns the
size of the NAL, and at the same time, updates the remaining size in the bitstream buffer that is passed in */
int32 PVMFOMXVideoDecNode::GetNAL_OMXNode(uint8** bitstream, int* size)
{
int i = 0;
int j;
uint8* nal_unit = *bitstream;
int count = 0;
/* find SC at the beginning of the NAL */
while (nal_unit[i++] == 0 && i < *size)
{
}
if (nal_unit[i-1] == 1)
{
*bitstream = nal_unit + i;
}
else
{
j = *size;
*size = 0;
return j; // no SC at the beginning, not supposed to happen
}
j = i;
/* found the SC at the beginning of the NAL, now find the SC at the beginning of the next NAL */
while (i < *size)
{
if (count == 2 && nal_unit[i] == 0x01)
{
i -= 2;
break;
}
if (nal_unit[i])
count = 0;
else
count++;
i++;
}
*size -= i;
return (i - j);
}
PVMFStatus PVMFOMXVideoDecNode::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() In"));
if (aParameters == NULL || aNumElements < 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Passed in parameter invalid"));
return PVMFErrArgument;
}
// Go through each parameter
for (int32 paramind = 0; paramind < aNumElements; ++paramind)
{
// Count the number of components and parameters in the key
int compcount = pv_mime_string_compcnt(aParameters[paramind].key);
// Retrieve the first component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(0, aParameters[paramind].key, compstr);
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/video/decoder")) < 0) || compcount < 4)
{
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/media/format_specific_info")) < 0) || compcount < 3)
{
// First 3 components should be "x-pvmf/media/format_specific_info" and there must
// be at least three components
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Unsupported key"));
return PVMFErrArgument;
}
else
{
pvVideoConfigParserInputs aInputs;
OMXConfigParserInputs aInputParameters;
VideoOMXConfigParserOutputs aOutputParameters;
aInputs.inPtr = (uint8*)(aParameters->value.key_specific_value);
aInputs.inBytes = (int32)aParameters->capacity;
aInputs.iMimeType = iNodeConfig.iMimeType;
aInputParameters.inBytes = aInputs.inBytes;
aInputParameters.inPtr = aInputs.inPtr;
if (aInputs.iMimeType == PVMF_MIME_H264_VIDEO ||
aInputs.iMimeType == PVMF_MIME_H264_VIDEO_MP4 ||
aInputs.iMimeType == PVMF_MIME_H264_VIDEO_RAW)
{
aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.avc";
}
else if (aInputs.iMimeType == PVMF_MIME_M4V)
{
aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.mpeg4";
}
else if (aInputs.iMimeType == PVMF_MIME_H2631998 ||
aInputs.iMimeType == PVMF_MIME_H2632000)
{
aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.h263";
}
else if (aInputs.iMimeType == PVMF_MIME_WMV)
{
aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.wmv";
}
else
{
// Illegal codec specified.
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Input port format other then codec type", iName.Str()));
}
OMX_BOOL status = OMX_FALSE;
OMX_U32 num_comps = 0;
OMX_STRING *CompOfRole;
OMX_U32 ii;
// call once to find out the number of components that can fit the role
OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, NULL);
if (num_comps > 0)
{
CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING));
for (ii = 0; ii < num_comps; ii++)
CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
// call 2nd time to get the component names
OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, (OMX_U8 **)CompOfRole);
for (ii = 0; ii < num_comps; ii++)
{
aInputParameters.cComponentName = CompOfRole[ii];
status = OMX_MasterConfigParser(&aInputParameters, &aOutputParameters);
if (status == OMX_TRUE)
{
break;
}
else
{
status = OMX_FALSE;
}
}
// whether successful or not, need to free CompOfRoles
for (ii = 0; ii < num_comps; ii++)
{
oscl_free(CompOfRole[ii]);
CompOfRole[ii] = NULL;
}
oscl_free(CompOfRole);
}
else
{
// if no component supports the role, nothing else to do
return PVMFErrNotSupported;
}
if (status == OMX_FALSE)
{
return PVMFErrNotSupported;
}
iNewWidth = aOutputParameters.width;
iNewHeight = aOutputParameters.height;
return PVMFSuccess;
}
}
else
{
if (compcount == 4)
{
// Verify and set the passed-in video dec node setting
PVMFStatus retval = DoVerifyAndSetVideoDecNodeParameter(aParameters[paramind], false);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Setting parameter %d failed", paramind));
return retval;
}
}
else if (compcount == 5)
{
// Determine the 4th level component
pv_mime_string_extract_type(3, aParameters[paramind].key, compstr);
if (pv_mime_strcmp(compstr, _STRLIT_CHAR("h263")) >= 0)
{
// Verify and set the passed-in H.263 decoder setting
PVMFStatus retval = DoVerifyAndSetH263DecoderParameter(aParameters[paramind], false);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Setting parameter %d failed", paramind));
return retval;
}
}
else if (pv_mime_strcmp(compstr, _STRLIT_CHAR("m4v")) >= 0)
{
// Verify and set the passed-in M4v decoder setting
PVMFStatus retval = DoVerifyAndSetM4VDecoderParameter(aParameters[paramind], false);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Setting parameter %d failed", paramind));
return retval;
}
}
else
{
// Unknown key sub-string
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Unsupported key"));
return PVMFErrArgument;
}
}
else
{
// Do not support more than 5 components right now
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Unsupported key"));
return PVMFErrArgument;
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigVerifyParameters() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFOMXVideoDecNode::DoGetVideoDecNodeParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr reqattr)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoGetVideoDecNodeParameter() In"));
aNumParamElements = 0;
// Allocate memory for the KVP
aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetVideoDecNodeParameter() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, sizeof(PvmiKvp));
// Allocate memory for the key string in KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetVideoDecNodeParameter() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to KVP
aParameters[0].key = memblock;
// Copy the key string
oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/video/decoder/"), 21);
oscl_strncat(aParameters[0].key, PVOMXVideoDecNodeConfigBaseKeys[aIndex].iString, oscl_strlen(PVOMXVideoDecNodeConfigBaseKeys[aIndex].iString));
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20);
switch (PVOMXVideoDecNodeConfigBaseKeys[aIndex].iValueType)
{
case PVMI_KVPVALTYPE_BITARRAY32:
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BITARRAY32_STRING), oscl_strlen(PVMI_KVPVALTYPE_BITARRAY32_STRING));
break;
case PVMI_KVPVALTYPE_KSV:
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_KSV_STRING), oscl_strlen(PVMI_KVPVALTYPE_KSV_STRING));
break;
case PVMI_KVPVALTYPE_BOOL:
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING));
break;
case PVMI_KVPVALTYPE_UINT32:
default:
if (reqattr == PVMI_KVPATTR_CAP)
{
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
}
else
{
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
}
break;
}
aParameters[0].key[PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE-1] = 0;
// Copy the requested info
switch (aIndex)
{
case 0: // "postproc_enable"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.bool_value = iNodeConfig.iPostProcessingEnable;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.bool_value = PVOMXVIDEODECNODE_CONFIG_POSTPROCENABLE_DEF;
}
break;
case 1: // "postproc_type"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.uint32_value = iNodeConfig.iPostProcessingMode;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = PVOMXVIDEODECNODE_CONFIG_POSTPROCTYPE_DEF;
}
break;
case 2: // "dropframe_enable"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.bool_value = iNodeConfig.iDropFrame;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.bool_value = PVOMXVIDEODECNODE_CONFIG_DROPFRAMEENABLE_DEF;
}
break;
case 5: //"format-type"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.pChar_value = (char*)iNodeConfig.iMimeType.getMIMEStrPtr();
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.pChar_value = (char*)PVMF_MIME_FORMAT_UNKNOWN;
}
break;
default:
// Invalid index
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetVideoDecNodeParameter() Invalid index to video dec node parameter"));
return PVMFErrArgument;
}
aNumParamElements = 1;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoGetVideoDecNodeParameter() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFOMXVideoDecNode::DoGetH263DecoderParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr reqattr)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoGetH263DecoderParameter() In"));
aNumParamElements = 0;
// Allocate memory for the KVP
aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetH263DecoderParameter() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, sizeof(PvmiKvp));
// Allocate memory for the key string in KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetH263DecoderParameter() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to KVP
aParameters[0].key = memblock;
// Copy the key string
oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/video/decoder/h263/"), 26);
oscl_strncat(aParameters[0].key, PVOMXVideoDecNodeConfigH263Keys[aIndex].iString, oscl_strlen(PVOMXVideoDecNodeConfigH263Keys[aIndex].iString));
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20);
switch (PVOMXVideoDecNodeConfigH263Keys[aIndex].iValueType)
{
case PVMI_KVPVALTYPE_RANGE_UINT32:
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
break;
case PVMI_KVPVALTYPE_UINT32:
default:
if (reqattr == PVMI_KVPATTR_CAP)
{
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
}
else
{
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
}
break;
}
aParameters[0].key[PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE-1] = 0;
// Copy the requested info
switch (aIndex)
{
case 0: // "maxbitstreamframesize"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.uint32_value = iH263MaxBitstreamFrameSize;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_DEF;
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetH263DecoderParameter() Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_MIN;
rui32->max = PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_MAX;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case 1: // "maxdimension"
{
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetH263DecoderParameter() Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
rui32->min = iH263MaxWidth;
rui32->max = iH263MaxHeight;
aParameters[0].value.key_specific_value = (void*)rui32;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
rui32->min = PVOMXVIDEODECNODE_CONFIG_H263MAXWIDTH_DEF;
rui32->max = PVOMXVIDEODECNODE_CONFIG_H263MAXHEIGHT_DEF;
aParameters[0].value.key_specific_value = (void*)rui32;
}
else
{
// Return capability
rui32->min = PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MIN;
rui32->max = PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MAX;
aParameters[0].value.key_specific_value = (void*)rui32;
}
}
break;
default:
// Invalid index
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetH263DecoderParameter() Invalid index to H.263 decoder parameter"));
return PVMFErrArgument;
}
aNumParamElements = 1;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoGetH263DecoderParameter() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFOMXVideoDecNode::DoGetM4VDecoderParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr reqattr)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoGetM4VDecoderParameter() In"));
aNumParamElements = 0;
// Allocate memory for the KVP
aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetM4VDecoderParameter() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, sizeof(PvmiKvp));
// Allocate memory for the key string in KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetM4VDecoderParameter() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to KVP
aParameters[0].key = memblock;
// Copy the key string
oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/video/decoder/m4v/"), 25);
oscl_strncat(aParameters[0].key, PVOMXVideoDecNodeConfigM4VKeys[aIndex].iString, oscl_strlen(PVOMXVideoDecNodeConfigM4VKeys[aIndex].iString));
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20);
switch (PVOMXVideoDecNodeConfigM4VKeys[aIndex].iValueType)
{
case PVMI_KVPVALTYPE_RANGE_UINT32:
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
break;
case PVMI_KVPVALTYPE_UINT32:
default:
if (reqattr == PVMI_KVPATTR_CAP)
{
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
}
else
{
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
}
break;
}
aParameters[0].key[PVOMXVIDEODECNODECONFIG_KEYSTRING_SIZE-1] = 0;
// Copy the requested info
switch (aIndex)
{
case 0: // "maxbitstreamframesize"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.uint32_value = iM4VMaxBitstreamFrameSize;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_DEF;
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetM4VDecoderParameter() Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_MIN;
rui32->max = PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_MAX;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case 1: // "maxdimension"
{
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetM4VDecoderParameter() Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
rui32->min = iM4VMaxWidth;
rui32->max = iM4VMaxHeight;
aParameters[0].value.key_specific_value = (void*)rui32;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
rui32->min = PVOMXVIDEODECNODE_CONFIG_M4VMAXWIDTH_DEF;
rui32->max = PVOMXVIDEODECNODE_CONFIG_M4VMAXHEIGHT_DEF;
aParameters[0].value.key_specific_value = (void*)rui32;
}
else
{
// Return capability
rui32->min = PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MIN;
rui32->max = PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MAX;
aParameters[0].value.key_specific_value = (void*)rui32;
}
}
break;
default:
// Invalid index
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoGetM4VDecoderParameter() Invalid index to H.263 decoder parameter"));
return PVMFErrArgument;
}
aNumParamElements = 1;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoGetM4VDecoderParameter() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter(PvmiKvp& aParameter, bool aSetParam)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() In"));
// Determine the valtype
PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key);
if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Valtype in key string unknown"));
return PVMFErrArgument;
}
// Retrieve the fourth component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(3, aParameter.key, compstr);
int32 vdeccomp4ind = 0;
for (vdeccomp4ind = 0; vdeccomp4ind < PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS; ++vdeccomp4ind)
{
// Go through each component string at 4th level
if (pv_mime_strcmp(compstr, (char*)(PVOMXVideoDecNodeConfigBaseKeys[vdeccomp4ind].iString)) >= 0)
{
// Break out of the for loop
break;
}
}
if (vdeccomp4ind == PVOMXVIDEODECNODECONFIG_BASE_NUMKEYS || vdeccomp4ind == 3 || vdeccomp4ind == 4)
{
// Match couldn't be found or non-leaf node specified
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Unsupported key or non-leaf node"));
return PVMFErrArgument;
}
// Verify the valtype
if (keyvaltype != PVOMXVideoDecNodeConfigBaseKeys[vdeccomp4ind].iValueType)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Valtype does not match for key"));
return PVMFErrArgument;
}
switch (vdeccomp4ind)
{
case 0: // "postproc_enable"
// Nothing to validate since it is boolean
// Change the config if to set
if (aSetParam)
{
iNodeConfig.iPostProcessingEnable = aParameter.value.bool_value;
}
break;
case 1: // "postproc_type"
// Nothing to validate since it is bitarray32
// Change the config if to set
if (aSetParam)
{
iNodeConfig.iPostProcessingMode = aParameter.value.uint32_value;
if (iNodeConfig.iPostProcessingEnable && iOMXDecoder)
{
// Don't do anything yet: Need to communicate post-processing to decoder
//iVideoDecoder->SetPostProcType(iNodeConfig.iPostProcessingMode);
}
}
break;
case 2: // "dropframe_enable"
// Nothing to validate since it is boolean
// Change the config if to set
if (aSetParam)
{
if (iInterfaceState == EPVMFNodeStarted || iInterfaceState == EPVMFNodePaused)
{
// This setting cannot be changed when decoder has been initialized
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Setting cannot be changed while started or paused"));
return PVMFErrInvalidState;
}
iNodeConfig.iDropFrame = aParameter.value.bool_value;
}
break;
case 5: // "format-type"
// Nothing to validate since it is boolean
// Change the config if to set
if (aSetParam)
{
if (iInterfaceState == EPVMFNodeStarted || iInterfaceState == EPVMFNodePaused)
{
// This setting cannot be changed when decoder has been initialized
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Setting cannot be changed while started or paused"));
return PVMFErrInvalidState;
}
iNodeConfig.iMimeType = aParameter.value.pChar_value;
}
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Invalid index for video dec node parameter"));
return PVMFErrArgument;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter(PvmiKvp& aParameter, bool aSetParam)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() In"));
// Determine the valtype
PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key);
if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() Valtype in key string unknown"));
return PVMFErrArgument;
}
// Retrieve the fifth component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(4, aParameter.key, compstr);
int32 vdeccomp5ind = 0;
for (vdeccomp5ind = 0; vdeccomp5ind < PVOMXVIDEODECNODECONFIG_H263_NUMKEYS; ++vdeccomp5ind)
{
// Go through each component string at 5th level
if (pv_mime_strcmp(compstr, (char*)(PVOMXVideoDecNodeConfigH263Keys[vdeccomp5ind].iString)) >= 0)
{
// Break out of the for loop
break;
}
}
if (vdeccomp5ind == PVOMXVIDEODECNODECONFIG_H263_NUMKEYS)
{
// Match couldn't be found or non-leaf node specified
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() Unsupported key or non-leaf node"));
return PVMFErrArgument;
}
// Verify the valtype
if (keyvaltype != PVOMXVideoDecNodeConfigH263Keys[vdeccomp5ind].iValueType)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() Valtype does not match for key"));
return PVMFErrArgument;
}
switch (vdeccomp5ind)
{
case 0: // "maxbitstreamframesize"
// Check if within range
if (aParameter.value.uint32_value < PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_MIN ||
aParameter.value.uint32_value > PVOMXVIDEODECNODE_CONFIG_H263MAXBITSTREAMFRAMESIZE_MAX)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() Invalid value for maxbitstreamframesize"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
if (iInterfaceState == EPVMFNodeStarted || iInterfaceState == EPVMFNodePaused)
{
// This setting cannot be changed when decoder has been initialized
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Setting cannot be changed while started or paused"));
return PVMFErrInvalidState;
}
iH263MaxBitstreamFrameSize = aParameter.value.uint32_value;
}
break;
case 1: // "maxdimension"
{
range_uint32* rui32 = (range_uint32*)aParameter.value.key_specific_value;
if (rui32 == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() ksv for maxdimension is NULL"));
return PVMFErrArgument;
}
// Check if within range
if (rui32->min < PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MIN ||
rui32->min > PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MAX ||
rui32->max < PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MIN ||
rui32->max > PVOMXVIDEODECNODE_CONFIG_H263MAXDIMENSION_MAX)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() Invalid range for maxdimension"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
if (iInterfaceState == EPVMFNodeStarted || iInterfaceState == EPVMFNodePaused)
{
// This setting cannot be changed when decoder has been initialized
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Setting cannot be changed while started or paused"));
return PVMFErrInvalidState;
}
iH263MaxWidth = rui32->min;
iH263MaxHeight = rui32->max;
}
}
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() Invalid index for H.263 decoder parameter"));
return PVMFErrArgument;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetH263DecoderParameter() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter(PvmiKvp& aParameter, bool aSetParam)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() In"));
// Determine the valtype
PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key);
if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() Valtype in key string unknown"));
return PVMFErrArgument;
}
// Retrieve the fifth component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(4, aParameter.key, compstr);
int32 vdeccomp5ind = 0;
for (vdeccomp5ind = 0; vdeccomp5ind < PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS; ++vdeccomp5ind)
{
// Go through each component string at 5th level
if (pv_mime_strcmp(compstr, (char*)(PVOMXVideoDecNodeConfigM4VKeys[vdeccomp5ind].iString)) >= 0)
{
// Break out of the for loop
break;
}
}
if (vdeccomp5ind == PVOMXVIDEODECNODECONFIG_M4V_NUMKEYS)
{
// Match couldn't be found or non-leaf node specified
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() Unsupported key or non-leaf node"));
return PVMFErrArgument;
}
// Verify the valtype
if (keyvaltype != PVOMXVideoDecNodeConfigM4VKeys[vdeccomp5ind].iValueType)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() Valtype does not match for key"));
return PVMFErrArgument;
}
switch (vdeccomp5ind)
{
case 0: // "maxbitstreamframesize"
// Check if within range
if (aParameter.value.uint32_value < PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_MIN ||
aParameter.value.uint32_value > PVOMXVIDEODECNODE_CONFIG_M4VMAXBITSTREAMFRAMESIZE_MAX)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() Invalid value for maxbitstreamframesize"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
if (iInterfaceState == EPVMFNodeStarted || iInterfaceState == EPVMFNodePaused)
{
// This setting cannot be changed when decoder has been initialized
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Setting cannot be changed while started or paused"));
return PVMFErrInvalidState;
}
iM4VMaxBitstreamFrameSize = aParameter.value.uint32_value;
}
break;
case 1: // "maxdimension"
{
range_uint32* rui32 = (range_uint32*)aParameter.value.key_specific_value;
if (rui32 == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() ksv for maxdimension is NULL"));
return PVMFErrArgument;
}
// Check if within range
if (rui32->min < PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MIN ||
rui32->min > PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MAX ||
rui32->max < PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MIN ||
rui32->max > PVOMXVIDEODECNODE_CONFIG_M4VMAXDIMENSION_MAX)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() Invalid range for maxdimension"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
if (iInterfaceState == EPVMFNodeStarted || iInterfaceState == EPVMFNodePaused)
{
// This setting cannot be changed when decoder has been initialized
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetVideoDecNodeParameter() Setting cannot be changed while started or paused"));
return PVMFErrInvalidState;
}
iM4VMaxWidth = rui32->min;
iM4VMaxHeight = rui32->max;
}
}
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() Invalid index for M4v decoder parameter"));
return PVMFErrArgument;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoVerifyAndSetM4VDecoderParameter() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFOMXVideoDecNode::GetProfileAndLevel(PVMF_MPEGVideoProfileType& aProfile, PVMF_MPEGVideoLevelType& aLevel)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::GetProfileAndLevel() In"));
if (NULL == iOMXDecoder)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::GetProfileAndLevel() iVideoDecoder is Null"));
aProfile = PV_MPEG_VIDEO_RESERVED_PROFILE;
aLevel = PV_MPEG_VIDEO_LEVEL_UNKNOWN;
return PVMFFailure;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::GetProfileAndLevel() iVideoDecoder is Null"));
aProfile = PV_MPEG_VIDEO_RESERVED_PROFILE;
aLevel = PV_MPEG_VIDEO_LEVEL_UNKNOWN;
// FOR NOW, JUST RETURN FAILURE, WE DON'T SUPPORT THIS FEATURE YET
return PVMFFailure;
}
// DEFINITIONS for parsing the config information & sequence header for WMV
#define GetUnalignedDword( pb, dw ) \
(dw) = ((uint32) *(pb + 3) << 24) + \
((uint32) *(pb + 2) << 16) + \
((uint16) *(pb + 1) << 8) + *pb;
#define GetUnalignedDwordEx( pb, dw ) GetUnalignedDword( pb, dw ); (pb) += sizeof(uint32);
#define LoadDWORD( dw, p ) GetUnalignedDwordEx( p, dw )
#ifndef MAKEFOURCC_WMC
#define MAKEFOURCC_WMC(ch0, ch1, ch2, ch3) \
((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \
((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
#define mmioFOURCC_WMC(ch0, ch1, ch2, ch3) MAKEFOURCC_WMC(ch0, ch1, ch2, ch3)
#endif
#define FOURCC_WMV3 mmioFOURCC_WMC('W','M','V','3')
#define FOURCC_WMV2 mmioFOURCC_WMC('W','M','V','2')
#define FOURCC_WMVA mmioFOURCC_WMC('W','M','V','A')
//For WMV3
enum { NOT_WMV3 = -1, WMV3_SIMPLE_PROFILE, WMV3_MAIN_PROFILE, WMV3_PC_PROFILE, WMV3_SCREEN };
//For WMVA
#define ASFBINDING_SIZE 1 // size of ASFBINDING is 1 byte
#define SC_SEQ 0x0F
#define SC_ENTRY 0x0E
bool PVMFOMXVideoDecNode::VerifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
{
// unused parameters
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(num_elements);
// call this in case of WMV format
if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMV)
{
//verify bitrate
if (pv_mime_strcmp(aParameters->key, PVMF_BITRATE_VALUE_KEY) == 0)
{
if (((PVMFOMXDecPort*)iOutPort)->verifyConnectedPortParametersSync(PVMF_BITRATE_VALUE_KEY, &(aParameters->value.uint32_value)) != PVMFSuccess)
{
return false;
}
return true;
}
else if (pv_mime_strcmp(aParameters->key, PVMF_FRAMERATE_VALUE_KEY) == 0)
{
if (((PVMFOMXDecPort*)iOutPort)->verifyConnectedPortParametersSync(PVMF_FRAMERATE_VALUE_KEY, &(aParameters->value.uint32_value)) != PVMFSuccess)
{
return false;
}
return true;
}
else if (pv_mime_strcmp(aParameters->key, PVMF_FORMAT_SPECIFIC_INFO_KEY) < 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::VerifyParametersSync() - Unsupported Key"));
return true;
}
// pConfig points to format specific info and sequence header.
uint8 *pConfig = (uint8*)(aParameters->value.key_specific_value);
uint8 *pData;
uint32 dwdat;
uint32 NewCompression;
uint32 NewSeqHeader;
uint32 NewProfile, NewFrameRate, NewBitRate;
// We are interested in the following (and will extract it)
// 1. Version (WMV9 or WMV8 etc.) (from format specific info)
// 2. picture dimensions // from format specific info
// 3. interlaced YUV411 /sprite content is not supported (from sequence header)
// 4. framerate / bitrate information (from sequence header)
pData = pConfig + 15; // position ptr to Width & Height
LoadDWORD(dwdat, pData);
iNewWidth = dwdat;
LoadDWORD(dwdat, pData);
iNewHeight = dwdat;
if (((iNewWidth != (uint32)iYUVWidth) || (iNewHeight != (uint32)iYUVHeight)) && iOutPort != NULL)
{
// see if downstream node can handle the re-sizing
int32 errcode = OsclErrNone;
OsclRefCounterMemFrag yuvFsiMemfrag;
OSCL_TRY(errcode, yuvFsiMemfrag = iFsiFragmentAlloc.get());
OSCL_FIRST_CATCH_ANY(errcode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::VerifyParametersSync() Failed to allocate memory for verifyParametersSync FSI")));
if (OsclErrNone == errcode)
{
PVMFYuvFormatSpecificInfo0* fsiInfo = OSCL_PLACEMENT_NEW(yuvFsiMemfrag.getMemFragPtr(), PVMFYuvFormatSpecificInfo0());
if (fsiInfo != NULL)
{
fsiInfo->video_format = PVMF_MIME_YUV420;
fsiInfo->uid = PVMFYuvFormatSpecificInfo0_UID;
fsiInfo->display_width = iNewWidth;
fsiInfo->display_height = iNewHeight;
fsiInfo->width = (iNewWidth + 3) & -4;
fsiInfo->height = iNewHeight;
if (((PVMFOMXDecPort*)iOutPort)->verifyConnectedPortParametersSync(PVMF_FORMAT_SPECIFIC_INFO_KEY, &yuvFsiMemfrag) != PVMFSuccess)
{
fsiInfo->video_format.~PVMFFormatType();
return false;
}
fsiInfo->video_format.~PVMFFormatType();
}
else
{
return false;
}
}
else
{
return false;
}
}
pData += 4; //position ptr to Compression type
LoadDWORD(dwdat, pData);
NewCompression = dwdat;
if (NewCompression != FOURCC_WMV2 &&
NewCompression != FOURCC_WMV3 &&
NewCompression != FOURCC_WMVA)
return false;
// Check sequence header
switch (NewCompression)
{
case FOURCC_WMV3:
{
pData = pConfig + 11 + 40; //sizeof(BITMAPINFOHEADER); // position to sequence header
LoadDWORD(dwdat, pData);
NewSeqHeader = dwdat; // this is little endian read sequence header
uint32 YUV411flag, Spriteflag;
// For FOURCC_WMV3
uint32 YUV411;
uint32 SpriteMode;
uint32 LoopFilter;
uint32 Xintra8Switch;
uint32 MultiresEnabled;
uint32 X16bitXform;
uint32 UVHpelBilinear;
uint32 ExtendedMvMode;
uint32 DQuantCodingOn;
uint32 XformSwitch;
uint32 DCTTable_MB_ENABLED;
uint32 SequenceOverlap;
uint32 StartCode;
uint32 PreProcRange;
uint32 NumBFrames;
uint32 ExplicitSeqQuantizer;
uint32 Use3QPDZQuantizer = 0;
uint32 ExplicitFrameQuantizer = 0;
bool bValidProfile = true;
NewProfile = (NewSeqHeader & 0xC0) >> 6; // 0 - simple , 1- main, 3 - complex, 2-forbidden
if (NewProfile == WMV3_PC_PROFILE)
return false;
YUV411flag = (NewSeqHeader & 0x20) >> 5;
Spriteflag = (NewSeqHeader & 0x10) >> 4;
if ((YUV411flag != 0) || (Spriteflag != 0))
return false;
YUV411 = (uint32)YUV411flag;
SpriteMode = (uint32)Spriteflag;
LoopFilter = (NewSeqHeader & 0x800) >> 11;
Xintra8Switch = (NewSeqHeader & 0x400) >> 10;
MultiresEnabled = (NewSeqHeader & 0x200) >> 9;
X16bitXform = (NewSeqHeader & 0x100) >> 8;
UVHpelBilinear = (NewSeqHeader & 0x800000) >> 23;
ExtendedMvMode = (NewSeqHeader & 0x400000) >> 22;
DQuantCodingOn = (NewSeqHeader & 0x300000) >> 20;
XformSwitch = (NewSeqHeader & 0x80000) >> 19;
DCTTable_MB_ENABLED = (NewSeqHeader & 0x40000) >> 18;
SequenceOverlap = (NewSeqHeader & 0x20000) >> 17;
StartCode = (NewSeqHeader & 0x10000) >> 16;
PreProcRange = (NewSeqHeader & 0x80000000) >> 31;
NumBFrames = (NewSeqHeader & 0x70000000) >> 28;
ExplicitSeqQuantizer = (NewSeqHeader & 0x8000000) >> 27;
if (ExplicitSeqQuantizer)
Use3QPDZQuantizer = (NewSeqHeader & 0x4000000) >> 26;
else
ExplicitFrameQuantizer = (NewSeqHeader & 0x4000000) >> 26;
NewFrameRate = (NewSeqHeader & 0x0E) >> 1 ; // from 2 to 30 fps (in steps of 4)
NewFrameRate = 4 * NewFrameRate + 2; // (in fps)
NewBitRate = (((NewSeqHeader & 0xF000) >> 24) | ((NewSeqHeader & 0x01) << 8)); // from 32 to 2016 kbps in steps of 64kbps
NewBitRate = 64 * NewBitRate + 32; // (in kbps)
// Verify Profile
if (!SpriteMode)
{
if (NewProfile == WMV3_SIMPLE_PROFILE)
{
bValidProfile = (Xintra8Switch == 0) &&
(X16bitXform == 1) &&
(UVHpelBilinear == 1) &&
(StartCode == 0) &&
(LoopFilter == 0) &&
(YUV411 == 0) &&
(MultiresEnabled == 0) &&
(DQuantCodingOn == 0) &&
(NumBFrames == 0) &&
(PreProcRange == 0);
}
else if (NewProfile == WMV3_MAIN_PROFILE)
{
bValidProfile = (Xintra8Switch == 0) &&
(X16bitXform == 1);
}
else if (NewProfile == WMV3_PC_PROFILE)
{
// no feature restrictions for complex profile.
}
if (!bValidProfile)
{
return false;
}
}
else
{
if (!Xintra8Switch &&
!DCTTable_MB_ENABLED &&
!YUV411 &&
!LoopFilter &&
!ExtendedMvMode &&
!MultiresEnabled &&
!UVHpelBilinear &&
!DQuantCodingOn &&
!XformSwitch &&
!StartCode &&
!PreProcRange &&
!ExplicitSeqQuantizer &&
!Use3QPDZQuantizer &&
!ExplicitFrameQuantizer)
return true;
else
return false;
}
}
break;
case FOURCC_WMVA:
{
pData = pConfig + 11 + 40 + ASFBINDING_SIZE; //sizeof(BITMAPINFOHEADER); // position to sequence header
LoadDWORD(dwdat, pData);
NewSeqHeader = dwdat; // this is little endian read sequence header
int32 iPrefix;
//ignore start code prefix
iPrefix = NewSeqHeader & 0xFF;
if (iPrefix != 0) return false;
iPrefix = (NewSeqHeader & 0xFF00) >> 8;
if (iPrefix != 0) return false;
iPrefix = (NewSeqHeader & 0xFF0000) >> 16;
if (iPrefix != 1) return false;
iPrefix = (NewSeqHeader & 0xFF000000) >> 24;
if (iPrefix != SC_SEQ) return false;
LoadDWORD(dwdat, pData);
NewSeqHeader = dwdat;
NewProfile = (NewSeqHeader & 0xC0) >> 6;
if (NewProfile != 3)
return false;
pData += 3;
LoadDWORD(dwdat, pData);
NewSeqHeader = dwdat;
//ignore start code prefix
iPrefix = NewSeqHeader & 0xFF;
if (iPrefix != 0) return false;
iPrefix = (NewSeqHeader & 0xFF00) >> 8;
if (iPrefix != 0) return false;
iPrefix = (NewSeqHeader & 0xFF0000) >> 16;
if (iPrefix != 1) return false;
iPrefix = (NewSeqHeader & 0xFF000000) >> 24;
if (iPrefix != SC_ENTRY) return false;
}
break;
case FOURCC_WMV2:
break;
default:
return false;
}
} // end of if(format == PVMF_MIME_WMV)
return true;
}