/* * Copyright (c) 2008-2016 Allwinner Technology Co. Ltd. * All rights reserved. * * File : omx_adec.c * Description : * History : * Author : AL3 * Date : 2013/05/05 * Comment : init the design code */ /*============================================================================ O p e n M A X w r a p p e r s O p e n M A X C o r e *//** @file omx_adec.cpp This module contains the implementation of the OpenMAX core & component. *//*========================================================================*/ ////////////////////////////////////////////////////////////////////////////// // Include Files ////////////////////////////////////////////////////////////////////////////// // http://www.mime-type.net/ #include "log.h" #include #include #include #include #include #include #include "omx_adec.h" #include #include "AWOMX_VideoIndexExtension.h" #include "memoryAdapter.h" #include "adecoder.h" #include #include #define debug logi("LINE %d, FUNCTION %s", __LINE__, __FUNCTION__); #define OPEN_STATISTICS (0) #ifdef __ANDROID__ using namespace android; #endif #define OMX_ADEC_RESULT_OK (0) #define OMX_ADEC_RESULT_ERROR (-1) #define OMX_ADEC_RESULT_EXIT (1) #define OMX_ADEC_RESULT_CONTINUE (2) /* * M A C R O S */ /* * Initializes a data structure using a pointer to the structure. * The initialization of OMX structures always sets up the nSize and nVersion fields * of the structure. */ #define OMX_CONF_INIT_STRUCT_PTR(_variable_, _struct_name_) \ memset((_variable_), 0x0, sizeof(_struct_name_)); \ (_variable_)->nSize = sizeof(_struct_name_); \ (_variable_)->nVersion.s.nVersionMajor = 0x1; \ (_variable_)->nVersion.s.nVersionMinor = 0x1; \ (_variable_)->nVersion.s.nRevision = 0x0; \ (_variable_)->nVersion.s.nStep = 0x0 static AUDIO_CUSTOM_PARAM sAudioDecCustomParams[] = { {VIDDEC_CUSTOMPARAM_ENABLE_ANDROID_NATIVE_BUFFER, (OMX_INDEXTYPE)AWOMX_IndexParamVideoEnableAndroidNativeBuffers}, {VIDDEC_CUSTOMPARAM_GET_ANDROID_NATIVE_BUFFER_USAGE, (OMX_INDEXTYPE)AWOMX_IndexParamVideoGetAndroidNativeBufferUsage}, {VIDDEC_CUSTOMPARAM_USE_ANDROID_NATIVE_BUFFER2, (OMX_INDEXTYPE)AWOMX_IndexParamVideoUseAndroidNativeBuffer2} }; static void* ComponentThread(void* pThreadData); //* factory function executed by the core to create instances void *get_omx_component_factory_fn(void) { CEDARC_UNUSE(get_omx_component_factory_fn); return (new omx_adec); } omx_adec::omx_adec() { logd("(f:%s, l:%d) ", __FUNCTION__, __LINE__); m_state = OMX_StateLoaded; m_cRole[0] = 0; m_cName[0] = 0; m_eCompressionFormat = OMX_AUDIO_CodingPCM;//OMX_AUDIO_CodingUnused; m_pAppData = NULL; m_thread_id = 0; m_cmdpipe[0] = 0; m_cmdpipe[1] = 0; m_cmddatapipe[0] = 0; m_cmddatapipe[1] = 0; m_channel = 0; m_sampleRate = 0; m_channels = 0; m_codec_tag = 0; m_blockalign = 0; m_bitspersample = 0; m_bitRate = 0; m_decoder = NULL; mEosFlag = OMX_FALSE; pMarkData = NULL; hMarkTargetComponent = NULL; port_setting_match = OMX_TRUE; pMarkBuf = NULL; memset(&m_Callbacks, 0, sizeof(m_Callbacks)); memset(&m_sInPortDef, 0, sizeof(m_sInPortDef)); memset(&m_sOutPortDef, 0, sizeof(m_sOutPortDef)); memset(&m_sInPortFormat, 0, sizeof(m_sInPortFormat)); memset(&m_sOutPortFormat, 0, sizeof(m_sOutPortFormat)); memset(&m_sPriorityMgmt, 0, sizeof(m_sPriorityMgmt)); memset(&m_sInBufSupplier, 0, sizeof(m_sInBufSupplier)); memset(&m_sOutBufSupplier, 0, sizeof(m_sOutBufSupplier)); memset(&m_sInBufList, 0, sizeof(m_sInBufList)); memset(&m_sOutBufList, 0, sizeof(m_sOutBufList)); memset(&m_streamInfo, 0, sizeof(m_streamInfo)); m_useAndroidBuffer = OMX_FALSE; m_nInportPrevTimeStamp = 0; m_JumpFlag = OMX_FALSE; mFirstInputDataFlag = OMX_TRUE; pthread_mutex_init(&m_inBufMutex, NULL); pthread_mutex_init(&m_outBufMutex, NULL); } omx_adec::~omx_adec() { OMX_S32 nIndex; // In case the client crashes, check for nAllocSize parameter. // If this is greater than zero, there are elements in the list that are not free'd. // In that case, free the elements. logi("(f:%s, l:%d) ", __FUNCTION__, __LINE__); pthread_mutex_lock(&m_inBufMutex); for(nIndex=0; nIndex("audio/wma"); } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.aac", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.aac", OMX_MAX_STRINGNAME_SIZE); //OMX_AUDIO_CodingAAC;//OMX_AUDIO_CodingPCM; m_eCompressionFormat = OMX_AUDIO_CodingAAC; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_MPEG_AAC_LC; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/aac"); } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.mp3", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.mp3", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingMP3; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_MP3; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/mp3"); } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.amrnb", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.amrnb", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingAMR; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_AMR; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/3gpp"); m_sampleRate = 8000; m_channel = 1; m_streamInfo.eSubCodecFormat = AMR_FORMAT_NARROWBAND; m_codec_tag = AMR_FORMAT_NARROWBAND; } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.amrwb", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.amrwb", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingAMR; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_AMR; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/amr-wb"); m_sampleRate = 16000; m_channel = 1; m_streamInfo.eSubCodecFormat = AMR_FORMAT_WIDEBAND; m_codec_tag = AMR_FORMAT_WIDEBAND; } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.g711.alaw", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.g711alaw", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingG711; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_LPCM_A; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/g711-alaw"); m_streamInfo.eSubCodecFormat = WAVE_FORMAT_ALAW; m_codec_tag = WAVE_FORMAT_ALAW; m_bitspersample = 8; } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.g711.mlaw", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.g711mlaw", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingG711; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_LPCM_V; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/g711-mlaw"); m_streamInfo.eSubCodecFormat = WAVE_FORMAT_MULAW; m_codec_tag = WAVE_FORMAT_MULAW; m_bitspersample = 8; } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.adpcm", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.adpcm", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingADPCM; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_ADPCM; //("audio/x-adpcm-ms"); m_sInPortDef.format.audio.cMIMEType = const_cast("audio/x-adpcm-dvi-ima"); m_streamInfo.eSubCodecFormat = WAVE_FORMAT_DVI_ADPCM; m_codec_tag = WAVE_FORMAT_DVI_ADPCM; } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.vorbis", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.ogg", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingVORBIS; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_OGG; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/ogg"); } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.ape", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.ape", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingAPE; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_APE; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/ape"); } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.dts", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.dts", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingDTS; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_DTS; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/dts"); } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.raw", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.raw", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingPCM; m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_PCM; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/raw"); m_streamInfo.eSubCodecFormat = WAVE_FORMAT_PCM; m_codec_tag = WAVE_FORMAT_PCM; } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.flac", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char *)m_cRole, "audio_decoder.flac", OMX_MAX_STRINGNAME_SIZE); m_eCompressionFormat = OMX_AUDIO_CodingFLAC;//FLAC??????? m_streamInfo.eCodecFormat = AUDIO_CODEC_FORMAT_FLAC; m_sInPortDef.format.audio.cMIMEType = const_cast("audio/flac"); } else { logi("\nERROR:Unknown Component\n"); eRet = OMX_ErrorInvalidComponentName; return eRet; } // Initialize component data structures to default values OMX_CONF_INIT_STRUCT_PTR(&m_sPortParam, OMX_PORT_PARAM_TYPE); m_sPortParam.nPorts = 0x2; m_sPortParam.nStartPortNumber = 0x0; // Initialize the audio parameters for input port OMX_CONF_INIT_STRUCT_PTR(&m_sInPortDef, OMX_PARAM_PORTDEFINITIONTYPE); m_sInPortDef.nPortIndex = 0; m_sInPortDef.eDir = OMX_DirInput; m_sInPortDef.nBufferCountMin = NUM_IN_BUFFERS; m_sInPortDef.nBufferCountActual = m_sInPortDef.nBufferCountMin; m_sInPortDef.nBufferSize = OMX_VIDEO_DEC_INPUT_BUFFER_SIZE; m_sInPortDef.bEnabled = OMX_TRUE; m_sInPortDef.bPopulated = OMX_FALSE; m_sInPortDef.eDomain = OMX_PortDomainAudio; m_sInPortDef.bBuffersContiguous = OMX_FALSE; m_sInPortDef.nBufferAlignment = 1; //m_sInPortDef.format.audio.cMIMEType = const_cast("audio/aac"); m_sInPortDef.format.audio.pNativeRender = NULL; m_sInPortDef.format.audio.bFlagErrorConcealment = OMX_FALSE; m_sInPortDef.format.audio.eEncoding = m_eCompressionFormat; // Initialize the audio parameters for output port OMX_CONF_INIT_STRUCT_PTR(&m_sOutPortDef, OMX_PARAM_PORTDEFINITIONTYPE); m_sOutPortDef.nPortIndex = 1; m_sOutPortDef.eDir = OMX_DirOutput; m_sOutPortDef.nBufferCountMin = NUM_OUT_BUFFERS; m_sOutPortDef.nBufferCountActual = m_sOutPortDef.nBufferCountMin; m_sOutPortDef.nBufferSize = OMX_VIDEO_DEC_OUTPUT_BUFFER_SIZE; m_sOutPortDef.bEnabled = OMX_TRUE; m_sOutPortDef.bPopulated = OMX_FALSE; m_sOutPortDef.eDomain = OMX_PortDomainAudio; m_sOutPortDef.bBuffersContiguous = OMX_FALSE; m_sOutPortDef.nBufferAlignment = 2; m_sOutPortDef.format.audio.cMIMEType = const_cast("audio/raw"); m_sOutPortDef.format.audio.pNativeRender = NULL; m_sOutPortDef.format.audio.bFlagErrorConcealment = OMX_FALSE; m_sOutPortDef.format.audio.eEncoding = OMX_AUDIO_CodingPCM; // Initialize the audio compression format for input port OMX_CONF_INIT_STRUCT_PTR(&m_sInPortFormat, OMX_AUDIO_PARAM_PORTFORMATTYPE); m_sInPortFormat.nPortIndex = 0x0; m_sInPortFormat.nIndex = 0x0; m_sInPortFormat.eEncoding = m_eCompressionFormat; // Initialize the compression format for output port OMX_CONF_INIT_STRUCT_PTR(&m_sOutPortFormat, OMX_AUDIO_PARAM_PORTFORMATTYPE); m_sOutPortFormat.nPortIndex = 0x1; m_sOutPortFormat.nIndex = 0x0; m_sOutPortFormat.eEncoding = OMX_AUDIO_CodingPCM; OMX_CONF_INIT_STRUCT_PTR(&m_sPriorityMgmt, OMX_PRIORITYMGMTTYPE); OMX_CONF_INIT_STRUCT_PTR(&m_sInBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE ); m_sInBufSupplier.nPortIndex = 0x0; OMX_CONF_INIT_STRUCT_PTR(&m_sOutBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE ); m_sOutBufSupplier.nPortIndex = 0x1; // Initialize the input buffer list memset(&(m_sInBufList), 0x0, sizeof(BufferList)); m_sInBufList.pBufArr = (OMX_BUFFERHEADERTYPE*)malloc(sizeof(OMX_BUFFERHEADERTYPE) * m_sInPortDef.nBufferCountActual); if(m_sInBufList.pBufArr == NULL) { eRet = OMX_ErrorInsufficientResources; goto EXIT; } memset(m_sInBufList.pBufArr, 0, sizeof(OMX_BUFFERHEADERTYPE) * m_sInPortDef.nBufferCountActual); for (nIndex = 0; nIndex < m_sInPortDef.nBufferCountActual; nIndex++) { OMX_CONF_INIT_STRUCT_PTR (&m_sInBufList.pBufArr[nIndex], OMX_BUFFERHEADERTYPE); } m_sInBufList.pBufHdrList = (OMX_BUFFERHEADERTYPE**)malloc(sizeof(OMX_BUFFERHEADERTYPE*) * m_sInPortDef.nBufferCountActual); if(m_sInBufList.pBufHdrList == NULL) { eRet = OMX_ErrorInsufficientResources; goto EXIT; } m_sInBufList.nSizeOfList = 0; m_sInBufList.nAllocSize = 0; m_sInBufList.nWritePos = 0; m_sInBufList.nReadPos = 0; m_sInBufList.nAllocBySelfFlags = 0; m_sInBufList.nBufArrSize = m_sInPortDef.nBufferCountActual; m_sInBufList.eDir = OMX_DirInput; // Initialize the output buffer list memset(&m_sOutBufList, 0x0, sizeof(BufferList)); m_sOutBufList.pBufArr = (OMX_BUFFERHEADERTYPE*)malloc(sizeof(OMX_BUFFERHEADERTYPE) * m_sOutPortDef.nBufferCountActual); if(m_sOutBufList.pBufArr == NULL) { eRet = OMX_ErrorInsufficientResources; goto EXIT; } memset(m_sOutBufList.pBufArr, 0, sizeof(OMX_BUFFERHEADERTYPE) * m_sOutPortDef.nBufferCountActual); for (nIndex = 0; nIndex < m_sOutPortDef.nBufferCountActual; nIndex++) { OMX_CONF_INIT_STRUCT_PTR(&m_sOutBufList.pBufArr[nIndex], OMX_BUFFERHEADERTYPE); } m_sOutBufList.pBufHdrList = (OMX_BUFFERHEADERTYPE**)malloc(sizeof(OMX_BUFFERHEADERTYPE*) * m_sOutPortDef.nBufferCountActual); if(m_sOutBufList.pBufHdrList == NULL) { eRet = OMX_ErrorInsufficientResources; goto EXIT; } m_sOutBufList.nSizeOfList = 0; m_sOutBufList.nAllocSize = 0; m_sOutBufList.nWritePos = 0; m_sOutBufList.nReadPos = 0; m_sOutBufList.nAllocBySelfFlags = 0; m_sOutBufList.nBufArrSize = m_sOutPortDef.nBufferCountActual; m_sOutBufList.eDir = OMX_DirOutput; // Create the pipe used to send commands to the thread err = pipe(m_cmdpipe); if (err) { eRet = OMX_ErrorInsufficientResources; goto EXIT; } // if (ve_mutex_init(&m_cedarv_req_ctx, CEDARV_DECODE) < 0) { // ALOGE("cedarv_req_ctx init fail!!"); // eRet = OMX_ErrorInsufficientResources; // goto EXIT; // } // Create the pipe used to send command data to the thread err = pipe(m_cmddatapipe); if (err) { eRet = OMX_ErrorInsufficientResources; goto EXIT; } //* create a decoder. // m_decoder = CreateAudioDecoder(); // if(m_decoder == NULL) // { // logi(" can not create audio decoder."); // eRet = OMX_ErrorInsufficientResources; // goto EXIT; // } //*set omx cts flag to flush the last frame in h264 //m_decoder->ioctrl(m_decoder, CEDARV_COMMAND_SET_OMXCTS_DECODER, 1); // Create the component thread err = pthread_create(&m_thread_id, NULL, ComponentThread, this); if( err || !m_thread_id ) { eRet = OMX_ErrorInsufficientResources; goto EXIT; } EXIT: return eRet; } OMX_ERRORTYPE omx_adec::get_component_version(OMX_IN OMX_HANDLETYPE pHComp, OMX_OUT OMX_STRING pComponentName, OMX_OUT OMX_VERSIONTYPE* pComponentVersion, OMX_OUT OMX_VERSIONTYPE* pSpecVersion, OMX_OUT OMX_UUIDTYPE* pComponentUUID) { logi("(f:%s, l:%d) ", __FUNCTION__, __LINE__); CEDARC_UNUSE(pComponentUUID); if (!pHComp || !pComponentName || !pComponentVersion || !pSpecVersion) { return OMX_ErrorBadParameter; } strcpy((char*)pComponentName, (char*)m_cName); pComponentVersion->s.nVersionMajor = 1; pComponentVersion->s.nVersionMinor = 1; pComponentVersion->s.nRevision = 0; pComponentVersion->s.nStep = 0; pSpecVersion->s.nVersionMajor = 1; pSpecVersion->s.nVersionMinor = 1; pSpecVersion->s.nRevision = 0; pSpecVersion->s.nStep = 0; return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::send_command(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_COMMANDTYPE eCmd, OMX_IN OMX_U32 uParam1, OMX_IN OMX_PTR pCmdData) { ThrCmdType eCmdNative; OMX_ERRORTYPE eError = OMX_ErrorNone; logi("(f:%s, l:%d) ", __FUNCTION__, __LINE__); CEDARC_UNUSE(pHComp); if(m_state == OMX_StateInvalid) { logd("ERROR: Send Command in Invalid State\n"); return OMX_ErrorInvalidState; } if (eCmd == OMX_CommandMarkBuffer && pCmdData == NULL) { logd("ERROR: Send OMX_CommandMarkBuffer command but pCmdData invalid."); return OMX_ErrorBadParameter; } switch (eCmd) { case OMX_CommandStateSet: logi(" COMPONENT_SEND_COMMAND: OMX_CommandStateSet"); eCmdNative = SetState; break; case OMX_CommandFlush: logi(" COMPONENT_SEND_COMMAND: OMX_CommandFlush"); eCmdNative = Flush; if ((int)uParam1 > 1 && (int)uParam1 != -1) { logd("Error: Send OMX_CommandFlush command but uParam1 invalid."); return OMX_ErrorBadPortIndex; } break; case OMX_CommandPortDisable: logi(" COMPONENT_SEND_COMMAND: OMX_CommandPortDisable"); eCmdNative = StopPort; break; case OMX_CommandPortEnable: logi(" COMPONENT_SEND_COMMAND: OMX_CommandPortEnable"); eCmdNative = RestartPort; eCmdNative; case OMX_CommandMarkBuffer: logi(" COMPONENT_SEND_COMMAND: OMX_CommandMarkBuffer"); eCmdNative = MarkBuf; if (uParam1 > 0) { logd("Error: Send OMX_CommandMarkBuffer command but uParam1 invalid."); return OMX_ErrorBadPortIndex; } break; default: break; } write(m_cmdpipe[1], &eCmdNative, sizeof(eCmdNative)); // In case of MarkBuf, the pCmdData parameter is used to carry the data. // In other cases, the nParam1 parameter carries the data. if(eCmdNative == MarkBuf) { write(m_cmddatapipe[1], &pCmdData, sizeof(OMX_PTR)); } else { write(m_cmddatapipe[1], &uParam1, sizeof(uParam1)); } return eError; } OMX_ERRORTYPE omx_adec::get_parameter(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_INDEXTYPE eParamIndex, OMX_INOUT OMX_PTR pParamData) { OMX_ERRORTYPE eError = OMX_ErrorNone; CEDARC_UNUSE(pHComp); logd("(f:%s, l:%d) eParamIndex = 0x%x", __FUNCTION__, __LINE__, eParamIndex); if(m_state == OMX_StateInvalid) { logi("Get Param in Invalid State\n"); return OMX_ErrorInvalidState; } if(pParamData == NULL) { logi("Get Param in Invalid pParamData \n"); return OMX_ErrorBadParameter; } switch(eParamIndex) { case OMX_IndexParamVideoInit: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoInit"); memcpy(pParamData, &m_sPortParam, sizeof(OMX_PORT_PARAM_TYPE)); break; } case OMX_IndexParamPortDefinition: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamPortDefinition"); if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nPortIndex == m_sInPortDef.nPortIndex) { memcpy(pParamData, &m_sInPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); logd("****eDomain:%d,eEncoding:%d", m_sInPortDef.eDomain,m_sInPortDef.format.audio.eEncoding); logd(" get_OMX_IndexParamPortDefinition: m_sInPortDef.nPortIndex[%d]", (int)m_sInPortDef.nPortIndex); } else if (((OMX_PARAM_PORTDEFINITIONTYPE*)(pParamData))->nPortIndex == m_sOutPortDef.nPortIndex) { memcpy(pParamData, &m_sOutPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); logd("****eDomain:%d,eEncoding:%d", m_sOutPortDef.eDomain,m_sOutPortDef.format.audio.eEncoding); logd("(omx_adec, f:%s, l:%d) OMX_IndexParamPortDefinition, nPortIndex[%d], \ nBufferCountActual[%d], nBufferCountMin[%d], nBufferSize[%d]", __FUNCTION__, __LINE__, (int)m_sOutPortDef.nPortIndex, (int)m_sOutPortDef.nBufferCountActual, (int)m_sOutPortDef.nBufferCountMin, (int)m_sOutPortDef.nBufferSize); } else { eError = OMX_ErrorBadPortIndex; logd(" get_OMX_IndexParamPortDefinition: error. pParamData->nPortIndex=[%d]", (int)((OMX_PARAM_PORTDEFINITIONTYPE*)(pParamData))->nPortIndex); } break; } case OMX_IndexParamAudioPortFormat: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioPortFormat"); if (((OMX_AUDIO_PARAM_PORTFORMATTYPE *)(pParamData))->nPortIndex == m_sInPortFormat.nPortIndex) { if (((OMX_AUDIO_PARAM_PORTFORMATTYPE*)(pParamData))->nIndex > m_sInPortFormat.nIndex) { eError = OMX_ErrorNoMore; } else { memcpy(pParamData, &m_sInPortFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); } } else if (((OMX_AUDIO_PARAM_PORTFORMATTYPE*)(pParamData))->nPortIndex == m_sOutPortFormat.nPortIndex) { if (((OMX_AUDIO_PARAM_PORTFORMATTYPE*)(pParamData))->nIndex > m_sOutPortFormat.nIndex) { eError = OMX_ErrorNoMore; } else { memcpy(pParamData, &m_sOutPortFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); } } else { eError = OMX_ErrorBadPortIndex; } logi("OMX_IndexParamAudioPortFormat, eError[0x%x]", eError); break; } case OMX_IndexParamStandardComponentRole: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamStandardComponentRole"); OMX_PARAM_COMPONENTROLETYPE* comp_role; comp_role = (OMX_PARAM_COMPONENTROLETYPE *) pParamData; comp_role->nVersion.nVersion = OMX_SPEC_VERSION; comp_role->nSize = sizeof(*comp_role); strncpy((char*)comp_role->cRole, (const char*)m_cRole, OMX_MAX_STRINGNAME_SIZE); break; } case OMX_IndexParamPriorityMgmt: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamPriorityMgmt"); memcpy(pParamData, &m_sPriorityMgmt, sizeof(OMX_PRIORITYMGMTTYPE)); break; } case OMX_IndexParamCompBufferSupplier: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamCompBufferSupplier"); OMX_PARAM_BUFFERSUPPLIERTYPE* pBuffSupplierParam = (OMX_PARAM_BUFFERSUPPLIERTYPE*)pParamData; if (pBuffSupplierParam->nPortIndex == 1) { pBuffSupplierParam->eBufferSupplier = m_sOutBufSupplier.eBufferSupplier; } else if (pBuffSupplierParam->nPortIndex == 0) { pBuffSupplierParam->eBufferSupplier = m_sInBufSupplier.eBufferSupplier; } else { eError = OMX_ErrorBadPortIndex; } break; } case OMX_IndexParamAudioInit: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioInit"); OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) pParamData; audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); audioPortParamType->nPorts = 0; audioPortParamType->nStartPortNumber = 0; break; } case OMX_IndexParamImageInit: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamImageInit"); OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) pParamData; imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); imagePortParamType->nPorts = 0; imagePortParamType->nStartPortNumber = 0; break; } case OMX_IndexParamOtherInit: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamOtherInit"); OMX_PORT_PARAM_TYPE *otherPortParamType = (OMX_PORT_PARAM_TYPE *) pParamData; otherPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; otherPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); otherPortParamType->nPorts = 0; otherPortParamType->nStartPortNumber = 0; break; } case OMX_IndexParamAudioWma: { logi(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioWma"); logi("get_parameter: OMX_IndexParamAudioWma, do nothing.\n"); break; } case OMX_IndexParamAudioAac: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioAac"); logd("get_parameter: OMX_IndexParamAudioAac, do nothing.\n"); break; } case OMX_IndexParamAudioMp3: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioMp3"); logd("get_parameter: OMX_IndexParamAudioMp3, do nothing.\n"); break; } case OMX_IndexParamAudioAmr: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioAmr"); logd("get_parameter: OMX_IndexParamAudioAmr, do nothing.\n"); break; } case OMX_IndexParamAudioVorbis: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioOgg"); logd("get_parameter: OMX_IndexParamAudioOgg, do nothing.\n"); break; } case OMX_IndexParamAudioApe: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioApe"); logd("get_parameter: OMX_IndexParamAudioApe, do nothing.\n"); break; } case OMX_IndexParamAudioAc3: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioAc3"); logd("get_parameter: OMX_IndexParamAudioAc3, do nothing.\n"); break; } case OMX_IndexParamAudioDts: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioDts"); logd("get_parameter: OMX_IndexParamAudioDts, do nothing.\n"); break; } case OMX_IndexParamAudioFlac://FLAC { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioFlac"); logd("get_parameter: OMX_IndexParamAudioFlac, do nothing.\n"); break; } case OMX_IndexParamAudioAdpcm: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioADPCM"); logd("get_parameter: OMX_IndexParamAudioADPCM, do nothing.\n"); break; } case OMX_IndexParamAudioPcm: { logd(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioPcm"); OMX_AUDIO_PARAM_PCMMODETYPE* params = (OMX_AUDIO_PARAM_PCMMODETYPE*)pParamData; params->eNumData = OMX_NumericalDataSigned; params->nBitPerSample = 16; params->ePCMMode = OMX_AUDIO_PCMModeLinear; if(m_channel) { params->nChannels = m_channel; } else { m_channel = 2; params->nChannels = 2; } if(m_sampleRate) { params->nSamplingRate = m_sampleRate; } else { m_sampleRate = 44100; params->nSamplingRate = 44100; } logd("eNumData[%d],nChannels[%d],m_streamInfo[%d],nSamplingRate[%d],m_streamInfo[%d]", params->eNumData,(int)params->nChannels,m_channel, (int)params->nSamplingRate,m_sampleRate); break; } default: { if((AW_VIDEO_EXTENSIONS_INDEXTYPE)eParamIndex == AWOMX_IndexParamVideoGetAndroidNativeBufferUsage) { logi(" COMPONENT_GET_PARAMETER: AWOMX_IndexParamVideoGetAndroidNativeBufferUsage"); break; } else { logi("get_parameter: unknown param %08x\n", eParamIndex); eError =OMX_ErrorUnsupportedIndex; break; } } } return eError; } OMX_ERRORTYPE omx_adec::set_parameter(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_INDEXTYPE eParamIndex, OMX_IN OMX_PTR pParamData) { OMX_ERRORTYPE eError = OMX_ErrorNone; logd("(f:%s, l:%d) eParamIndex = 0x%x", __FUNCTION__, __LINE__, eParamIndex); CEDARC_UNUSE(pHComp); if(m_state == OMX_StateInvalid) { logd("Set Param in Invalid State\n"); return OMX_ErrorInvalidState; } if(pParamData == NULL) { logd("Get Param in Invalid pParamData \n"); return OMX_ErrorBadParameter; } switch(eParamIndex) { case OMX_IndexParamPortDefinition: { logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamPortDefinition"); if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nPortIndex == m_sInPortDef.nPortIndex) { logd("set_OMX_IndexParamPortDefinition, m_sInPortDef.nPortIndex=%d", (int)m_sInPortDef.nPortIndex); if(((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual != m_sInPortDef.nBufferCountActual) { int nBufCnt; int nIndex; pthread_mutex_lock(&m_inBufMutex); if(m_sInBufList.pBufArr != NULL) { free(m_sInBufList.pBufArr); } if(m_sInBufList.pBufHdrList != NULL) { free(m_sInBufList.pBufHdrList); } nBufCnt = ((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual; logi("x allocate %d buffers.", nBufCnt); m_sInBufList.pBufArr = (OMX_BUFFERHEADERTYPE*)malloc(sizeof(OMX_BUFFERHEADERTYPE)* nBufCnt); m_sInBufList.pBufHdrList = (OMX_BUFFERHEADERTYPE**)malloc(sizeof(OMX_BUFFERHEADERTYPE*)* nBufCnt); for (nIndex = 0; nIndex < nBufCnt; nIndex++) { OMX_CONF_INIT_STRUCT_PTR (&m_sInBufList.pBufArr[nIndex], OMX_BUFFERHEADERTYPE); } m_sInBufList.nSizeOfList = 0; m_sInBufList.nAllocSize = 0; m_sInBufList.nWritePos = 0; m_sInBufList.nReadPos = 0; m_sInBufList.nAllocBySelfFlags = 0; m_sInBufList.nBufArrSize = nBufCnt; m_sInBufList.eDir = OMX_DirInput; pthread_mutex_unlock(&m_inBufMutex); } memcpy(&m_sInPortDef, pParamData, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); } else if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nPortIndex == m_sOutPortDef.nPortIndex) { logd("set_OMX_IndexParamPortDefinition, m_sOutPortDef.nPortIndex=%d", (int)m_sOutPortDef.nPortIndex); if(((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual != m_sOutPortDef.nBufferCountActual) { int nBufCnt; int nIndex; pthread_mutex_lock(&m_outBufMutex); if(m_sOutBufList.pBufArr != NULL) { free(m_sOutBufList.pBufArr); } if(m_sOutBufList.pBufHdrList != NULL) { free(m_sOutBufList.pBufHdrList); } nBufCnt = ((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual; logi("x allocate %d buffers.", nBufCnt); //*Initialize the output buffer list m_sOutBufList.pBufArr = (OMX_BUFFERHEADERTYPE*) malloc(sizeof(OMX_BUFFERHEADERTYPE) * nBufCnt); m_sOutBufList.pBufHdrList = (OMX_BUFFERHEADERTYPE**) malloc(sizeof(OMX_BUFFERHEADERTYPE*) * nBufCnt); for (nIndex = 0; nIndex < nBufCnt; nIndex++) { OMX_CONF_INIT_STRUCT_PTR (&m_sOutBufList.pBufArr[nIndex], OMX_BUFFERHEADERTYPE); } m_sOutBufList.nSizeOfList = 0; m_sOutBufList.nAllocSize = 0; m_sOutBufList.nWritePos = 0; m_sOutBufList.nReadPos = 0; m_sOutBufList.nAllocBySelfFlags = 0; m_sOutBufList.nBufArrSize = nBufCnt; m_sOutBufList.eDir = OMX_DirOutput; pthread_mutex_unlock(&m_outBufMutex); } memcpy(&m_sOutPortDef, pParamData, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); } else { logw("set_OMX_IndexParamPortDefinition, error, paramPortIndex=%d", (int)((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nPortIndex); eError = OMX_ErrorBadPortIndex; } break; } case OMX_IndexParamAudioPortFormat: { logi(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioPortFormat"); if (((OMX_AUDIO_PARAM_PORTFORMATTYPE *)(pParamData))->nPortIndex == m_sInPortFormat.nPortIndex) { if (((OMX_AUDIO_PARAM_PORTFORMATTYPE *)(pParamData))->nIndex > m_sInPortFormat.nIndex) { eError = OMX_ErrorNoMore; } else { memcpy(&m_sInPortFormat, pParamData, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); } } else if (((OMX_AUDIO_PARAM_PORTFORMATTYPE*)(pParamData))->nPortIndex == m_sOutPortFormat.nPortIndex) { if (((OMX_AUDIO_PARAM_PORTFORMATTYPE*)(pParamData))->nIndex > m_sOutPortFormat.nIndex) { eError = OMX_ErrorNoMore; } else { memcpy(&m_sOutPortFormat, pParamData, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); } } else { eError = OMX_ErrorBadPortIndex; } break; } case OMX_IndexParamStandardComponentRole: { logi(" COMPONENT_SET_PARAMETER: OMX_IndexParamStandardComponentRole"); OMX_PARAM_COMPONENTROLETYPE *comp_role; comp_role = (OMX_PARAM_COMPONENTROLETYPE *) pParamData; logi("set_parameter: OMX_IndexParamStandardComponentRole %s\n", comp_role->cRole); if(m_state == OMX_StateLoaded) { logi("Set Parameter called in valid state"); } else { logi("Set Parameter called in Invalid State\n"); return OMX_ErrorIncorrectStateOperation; } if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.wma", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.wma", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.wma",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.aac", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.aac", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.aac",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.mp3", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.mp3", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.mp3",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.amrnb", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.amrnb", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.amrnb",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.amrwb", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.amrwb", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.amrwb",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.g711.alaw", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.g711alaw", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.g711alaw",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.g711.mlaw", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.g711mlaw", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.g711mlaw",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.adpcm", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.adpcm", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.adpcm",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.vorbis", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.ogg", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.ogg",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.ape", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.ape", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.ape",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.dts", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.dts", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.dts",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.raw", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.raw", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.raw",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else if(!strncmp((char*)m_cName, "OMX.allwinner.audio.decoder.flac", OMX_MAX_STRINGNAME_SIZE)) { if(!strncmp((const char*)comp_role->cRole,"audio_decoder.flac", OMX_MAX_STRINGNAME_SIZE)) { strncpy((char*)m_cRole,"audio_decoder.flac",OMX_MAX_STRINGNAME_SIZE); } else { logi("Setparameter: unknown uIndex %s\n", comp_role->cRole); eError =OMX_ErrorUnsupportedSetting; } } else { logi("Setparameter: unknown param %s\n", m_cName); eError = OMX_ErrorInvalidComponentName; } break; } case OMX_IndexParamPriorityMgmt: { logi(" COMPONENT_SET_PARAMETER: OMX_IndexParamPriorityMgmt"); if(m_state != OMX_StateLoaded) { logi("Set Parameter called in Invalid State\n"); return OMX_ErrorIncorrectStateOperation; } OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) pParamData; m_sPriorityMgmt.nGroupID = priorityMgmtype->nGroupID; m_sPriorityMgmt.nGroupPriority = priorityMgmtype->nGroupPriority; break; } case OMX_IndexParamCompBufferSupplier: { logi(" COMPONENT_SET_PARAMETER: OMX_IndexParamCompBufferSupplier"); OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) pParamData; logi("set_parameter: OMX_IndexParamCompBufferSupplier %d\n", bufferSupplierType->eBufferSupplier); if(bufferSupplierType->nPortIndex == 0) { m_sInBufSupplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; } else if(bufferSupplierType->nPortIndex == 1) { m_sOutBufSupplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; } else { eError = OMX_ErrorBadPortIndex; } break; } case OMX_IndexParamAudioWma: { OMX_AUDIO_PARAM_WMATYPE* params = (OMX_AUDIO_PARAM_WMATYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioWma"); logd("nChannels[%d],nSamplingRate[%d],bitrate:%d", (int)params->nChannels,(int)params->nSamplingRate,(int)params->nBitRate); m_channel = params->nChannels>2? 2:params->nChannels; m_sampleRate = params->nSamplingRate; m_channels = params->nChannels ; m_codec_tag = params->nEncodeOptions; m_bitRate = params->nBitRate; m_blockalign = params->nBlockAlign; m_bitspersample = params->nSuperBlockAlign; break; } case OMX_IndexParamAudioAac: { OMX_AUDIO_PARAM_AACPROFILETYPE* params = (OMX_AUDIO_PARAM_AACPROFILETYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioAac"); logd("nChannels[%d],nSamplingRate[%d]", (int)params->nChannels,(int)params->nSampleRate); m_channels = params->nChannels ; if(params->nChannels) { m_channel = params->nChannels>2? 2:params->nChannels; } if(params->nSampleRate) { m_sampleRate = params->nSampleRate; } break; } case OMX_IndexParamAudioMp3: { OMX_AUDIO_PARAM_MP3TYPE* params = (OMX_AUDIO_PARAM_MP3TYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioMp3"); logd("nChannels[%d],nSamplingRate[%d]", (int)params->nChannels,(int)params->nSampleRate); m_channels = params->nChannels ; if(params->nChannels) { m_channel = params->nChannels>2? 2:params->nChannels; } if(params->nSampleRate) { m_sampleRate = params->nSampleRate; } break; } case OMX_IndexParamAudioAmr: { OMX_AUDIO_PARAM_AMRTYPE* params = (OMX_AUDIO_PARAM_AMRTYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioAmr"); logd("nChannels[%d],eAMRBandMode[%d]", (int)params->nChannels,(int)params->eAMRBandMode); m_channel = 1; m_channels = 1 ; //if(params->nSampleRate) if((params->eAMRBandMode>OMX_AUDIO_AMRBandModeUnused) &&(params->eAMRBandModenSampleRate; } else { m_sampleRate = 16000; } break; } case OMX_IndexParamAudioVorbis: { OMX_AUDIO_PARAM_VORBISTYPE* params = (OMX_AUDIO_PARAM_VORBISTYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioOgg"); logd("nChannels[%d],nSamplingRate[%d]", (int)params->nChannels,(int)params->nSampleRate); m_channels = params->nChannels ; if(params->nChannels) { m_channel = params->nChannels>2? 2:params->nChannels; } if(params->nSampleRate) { m_sampleRate = params->nSampleRate; } break; } case OMX_IndexParamAudioApe: { OMX_AUDIO_PARAM_PCMMODETYPE* params = (OMX_AUDIO_PARAM_PCMMODETYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioApe"); logd("nChannels[%d],nSamplingRate[%d],nBitPerSample:%d", (int)params->nChannels,(int)params->nSamplingRate,(int)params->nBitPerSample); m_channels = params->nChannels ; m_channel = params->nChannels>2? 2:params->nChannels; m_sampleRate = params->nSamplingRate; m_channels = params->nChannels ; m_bitspersample = params->nBitPerSample; break; } case OMX_IndexParamAudioAc3: { OMX_AUDIO_PARAM_PCMMODETYPE* params = (OMX_AUDIO_PARAM_PCMMODETYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioAc3"); logd("nChannels[%d],nSamplingRate[%d],nBitPerSample:%d", (int)params->nChannels,(int)params->nSamplingRate,(int)params->nBitPerSample); m_channels = params->nChannels ; m_channel = params->nChannels>2? 2:params->nChannels; m_sampleRate = params->nSamplingRate; m_channels = params->nChannels ; m_bitspersample = params->nBitPerSample; break; } case OMX_IndexParamAudioDts: { OMX_AUDIO_PARAM_PCMMODETYPE* params = (OMX_AUDIO_PARAM_PCMMODETYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioDts"); logd("nChannels[%d],nSamplingRate[%d],nBitPerSample:%d", (int)params->nChannels,(int)params->nSamplingRate,(int)params->nBitPerSample); m_channels = params->nChannels ; m_channel = params->nChannels>2? 2:params->nChannels; m_sampleRate = params->nSamplingRate; m_channels = params->nChannels ; m_bitspersample = params->nBitPerSample; break; } case OMX_IndexParamAudioFlac: { OMX_AUDIO_PARAM_FLACTYPE* params = (OMX_AUDIO_PARAM_FLACTYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioFlac"); logd("nChannels[%d],nSamplingRate[%d]", (int)params->nChannels,(int)params->nSampleRate); m_channels = params->nChannels ; if(params->nChannels) { m_channel = params->nChannels>2? 2:params->nChannels; } if(params->nSampleRate) { m_sampleRate = params->nSampleRate; } break; } case OMX_IndexParamAudioAdpcm: { OMX_AUDIO_PARAM_ADPCMTYPE* params = (OMX_AUDIO_PARAM_ADPCMTYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioADPCM"); logd("nChannels[%d],nSamplingRate[%d],nBitsPerSample[%d]", (int)params->nChannels,(int)params->nSampleRate,(int)params->nBitsPerSample); m_channels = params->nChannels ; if(params->nChannels) { m_channel = params->nChannels>2? 2:params->nChannels; } if(params->nSampleRate) { m_sampleRate = params->nSampleRate; } m_bitspersample = params->nBitsPerSample; break; } case OMX_IndexParamAudioPcm: { OMX_AUDIO_PARAM_PCMMODETYPE* params = (OMX_AUDIO_PARAM_PCMMODETYPE*)pParamData; logd(" COMPONENT_SET_PARAMETER: OMX_IndexParamAudioPcm"); logd("set_parameter: OMX_IndexParamAudioPcm, do nothing.\n"); logd("nChannels[%d],nSamplingRate[%d]", (int)params->nChannels,(int)params->nSamplingRate); m_channels = params->nChannels ; if(params->nChannels) { m_channel = params->nChannels>2? 2:params->nChannels; } if(params->nSamplingRate) { m_sampleRate = params->nSamplingRate; } if(!m_bitspersample) { m_bitspersample = params->nBitPerSample; } break; } default: { if((AW_VIDEO_EXTENSIONS_INDEXTYPE)eParamIndex == AWOMX_IndexParamVideoUseAndroidNativeBuffer2) { logi(" COMPONENT_SET_PARAMETER: AWOMX_IndexParamVideoUseAndroidNativeBuffer2"); logi("set_parameter: AWOMX_IndexParamVideoUseAndroidNativeBuffer2, do nothing.\n"); m_useAndroidBuffer = OMX_TRUE; break; } else if((AW_VIDEO_EXTENSIONS_INDEXTYPE)eParamIndex == AWOMX_IndexParamVideoEnableAndroidNativeBuffers) { logi(" COMPONENT_SET_PARAMETER: AWOMX_IndexParamVideoEnableAndroidNativeBuffers"); logi("set_parameter: AWOMX_IndexParamVideoEnableAndroidNativeBuffers, \ set m_useAndroidBuffer to OMX_TRUE\n"); m_useAndroidBuffer = OMX_TRUE; break; } else { logi("Setparameter: unknown param %d\n", eParamIndex); eError = OMX_ErrorUnsupportedIndex; break; } } } logd("err:%d",eError); return eError; } OMX_ERRORTYPE omx_adec::get_config(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_INDEXTYPE eConfigIndex, OMX_INOUT OMX_PTR pConfigData) { OMX_ERRORTYPE eError = OMX_ErrorNone; logi("(f:%s, l:%d) uIndex = %d", __FUNCTION__, __LINE__, eConfigIndex); CEDARC_UNUSE(pHComp); CEDARC_UNUSE(pConfigData); if (m_state == OMX_StateInvalid) { logi("get_config in Invalid State\n"); return OMX_ErrorInvalidState; } switch (eConfigIndex) { default: { logi("get_config: unknown param %d\n",eConfigIndex); eError = OMX_ErrorUnsupportedIndex; } } return eError; } OMX_ERRORTYPE omx_adec::set_config(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_INDEXTYPE eConfigIndex, OMX_IN OMX_PTR pConfigData) { logi("(f:%s, l:%d) uIndex = %d", __FUNCTION__, __LINE__, eConfigIndex); CEDARC_UNUSE(pHComp); CEDARC_UNUSE(pConfigData); if(m_state == OMX_StateInvalid) { logi("set_config in Invalid State\n"); return OMX_ErrorInvalidState; } OMX_ERRORTYPE eError = OMX_ErrorNone; if (m_state == OMX_StateExecuting) { logi("set_config: Ignore in Executing state\n"); return eError; } switch(eConfigIndex) { default: { eError = OMX_ErrorUnsupportedIndex; } } return eError; } OMX_ERRORTYPE omx_adec::get_extension_index(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_STRING pParamName, OMX_OUT OMX_INDEXTYPE* pIndexType) { unsigned int nIndex; OMX_ERRORTYPE eError = OMX_ErrorUndefined; logi("(f:%s, l:%d) param name = %s", __FUNCTION__, __LINE__, pParamName); if(m_state == OMX_StateInvalid) { logi("Get Extension uIndex in Invalid State\n"); return OMX_ErrorInvalidState; } if(pHComp == NULL) { return OMX_ErrorBadParameter; } for(nIndex = 0; nIndex < sizeof(sAudioDecCustomParams)/sizeof(AUDIO_CUSTOM_PARAM); nIndex++) { if(strcmp((char *)pParamName, (char *)&(sAudioDecCustomParams[nIndex].cCustomParamName)) == 0) { *pIndexType = sAudioDecCustomParams[nIndex].nCustomParamIndex; eError = OMX_ErrorNone; break; } } return eError; } OMX_ERRORTYPE omx_adec::get_state(OMX_IN OMX_HANDLETYPE pHComp, OMX_OUT OMX_STATETYPE* pState) { logi("(f:%s, l:%d) ", __FUNCTION__, __LINE__); if(pHComp == NULL || pState == NULL) { return OMX_ErrorBadParameter; } *pState = m_state; logi("COMPONENT_GET_STATE, state[0x%x]", m_state); return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::component_tunnel_request(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_U32 uPort, OMX_IN OMX_HANDLETYPE pPeerComponent, OMX_IN OMX_U32 uPeerPort, OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) { logi(" COMPONENT_TUNNEL_REQUEST"); CEDARC_UNUSE(pHComp); CEDARC_UNUSE(uPort); CEDARC_UNUSE(pPeerComponent); CEDARC_UNUSE(uPeerPort); CEDARC_UNUSE(pTunnelSetup); logw("Error: component_tunnel_request Not Implemented\n"); return OMX_ErrorNotImplemented; } OMX_ERRORTYPE omx_adec::use_buffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes, OMX_IN OMX_U8* pBuffer) { OMX_PARAM_PORTDEFINITIONTYPE* pPortDef; OMX_U32 nIndex = 0x0; if(hComponent == NULL || ppBufferHdr == NULL || pBuffer == NULL) { return OMX_ErrorBadParameter; } if (nPortIndex == m_sInPortDef.nPortIndex) { pPortDef = &m_sInPortDef; } else if (nPortIndex == m_sOutPortDef.nPortIndex) { pPortDef = &m_sOutPortDef; } else { return OMX_ErrorBadParameter; } if (m_state!=OMX_StateLoaded && m_state!=OMX_StateWaitForResources && pPortDef->bEnabled!=OMX_FALSE) { logd("pPortDef[%d]->bEnabled=%d, m_state=0x%x, Can't use_buffer!", (int)nPortIndex, pPortDef->bEnabled, m_state); return OMX_ErrorIncorrectStateOperation; } logi("pPortDef[%d]->bEnabled=%d, m_state=0x%x, can use_buffer.", (int)nPortIndex, pPortDef->bEnabled, m_state); if (nSizeBytes != pPortDef->nBufferSize || pPortDef->bPopulated) { return OMX_ErrorBadParameter; } // Find an empty position in the BufferList and allocate memory for the buffer header. // Use the buffer passed by the client to initialize the actual buffer // inside the buffer header. if (nPortIndex == m_sInPortDef.nPortIndex) { logi("use_buffer, m_sInPortDef.nPortIndex=[%d]", (int)m_sInPortDef.nPortIndex); pthread_mutex_lock(&m_inBufMutex); if((OMX_S32)m_sInBufList.nAllocSize >= m_sInBufList.nBufArrSize) { pthread_mutex_unlock(&m_inBufMutex); return OMX_ErrorInsufficientResources; } nIndex = m_sInBufList.nAllocSize; m_sInBufList.nAllocSize++; m_sInBufList.pBufArr[nIndex].pBuffer = pBuffer; m_sInBufList.pBufArr[nIndex].nAllocLen = nSizeBytes; m_sInBufList.pBufArr[nIndex].pAppPrivate = pAppPrivate; m_sInBufList.pBufArr[nIndex].nInputPortIndex = nPortIndex; m_sInBufList.pBufArr[nIndex].nOutputPortIndex = 0xFFFFFFFE; *ppBufferHdr = &m_sInBufList.pBufArr[nIndex]; if (m_sInBufList.nAllocSize == pPortDef->nBufferCountActual) { pPortDef->bPopulated = OMX_TRUE; } pthread_mutex_unlock(&m_inBufMutex); } else { logi("use_buffer, m_sOutPortDef.nPortIndex=[%d]", (int)m_sOutPortDef.nPortIndex); pthread_mutex_lock(&m_outBufMutex); if((OMX_S32)m_sOutBufList.nAllocSize >= m_sOutBufList.nBufArrSize) { pthread_mutex_unlock(&m_outBufMutex); return OMX_ErrorInsufficientResources; } nIndex = m_sOutBufList.nAllocSize; m_sOutBufList.nAllocSize++; m_sOutBufList.pBufArr[nIndex].pBuffer = pBuffer; m_sOutBufList.pBufArr[nIndex].nAllocLen = nSizeBytes; m_sOutBufList.pBufArr[nIndex].pAppPrivate = pAppPrivate; m_sOutBufList.pBufArr[nIndex].nInputPortIndex = 0xFFFFFFFE; m_sOutBufList.pBufArr[nIndex].nOutputPortIndex = nPortIndex; *ppBufferHdr = &m_sOutBufList.pBufArr[nIndex]; if (m_sOutBufList.nAllocSize == pPortDef->nBufferCountActual) { pPortDef->bPopulated = OMX_TRUE; } pthread_mutex_unlock(&m_outBufMutex); } return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes) { OMX_S8 nIndex = 0x0; OMX_PARAM_PORTDEFINITIONTYPE* pPortDef; //logi(" COMPONENT_ALLOCATE_BUFFER"); logd("(f:%s, l:%d) nPortIndex[%d], nSizeBytes[%d]", __FUNCTION__, __LINE__, (int)nPortIndex, (int)nSizeBytes); if(hComponent == NULL || ppBufferHdr == NULL) { return OMX_ErrorBadParameter; } if (nPortIndex == m_sInPortDef.nPortIndex) { pPortDef = &m_sInPortDef; } else { if (nPortIndex == m_sOutPortDef.nPortIndex) { pPortDef = &m_sOutPortDef; } else { return OMX_ErrorBadParameter; } } // if (!pPortDef->bEnabled) // return OMX_ErrorIncorrectStateOperation; if (m_state!=OMX_StateLoaded && m_state!=OMX_StateWaitForResources && pPortDef->bEnabled!=OMX_FALSE) { logw("pPortDef[%d]->bEnabled=%d, m_state=0x%x, Can't allocate_buffer!", (int)nPortIndex, pPortDef->bEnabled, m_state); return OMX_ErrorIncorrectStateOperation; } logi("pPortDef[%d]->bEnabled=%d, m_state=0x%x, can allocate_buffer.", (int)nPortIndex, pPortDef->bEnabled, m_state); if (nSizeBytes != pPortDef->nBufferSize || pPortDef->bPopulated) { return OMX_ErrorBadParameter; } // Find an empty position in the BufferList and allocate memory for the buffer header // and the actual buffer if (nPortIndex == m_sInPortDef.nPortIndex) { logi("allocate_buffer, m_sInPortDef.nPortIndex[%d]", (int)m_sInPortDef.nPortIndex); pthread_mutex_lock(&m_inBufMutex); if((OMX_S32)m_sInBufList.nAllocSize >= m_sInBufList.nBufArrSize) { pthread_mutex_unlock(&m_inBufMutex); return OMX_ErrorInsufficientResources; } nIndex = m_sInBufList.nAllocSize; logd("malloc m_sInBufList.pBufArr[nIndex[%d]].pBuffer:",(int)m_sInBufList.nAllocSize); m_sInBufList.pBufArr[nIndex].pBuffer = (OMX_U8*)malloc(nSizeBytes); if (!m_sInBufList.pBufArr[nIndex].pBuffer) { pthread_mutex_unlock(&m_inBufMutex); return OMX_ErrorInsufficientResources; } m_sInBufList.nAllocBySelfFlags |= (1<nBufferCountActual) { pPortDef->bPopulated = OMX_TRUE; } pthread_mutex_unlock(&m_inBufMutex); } else { logi("allocate_buffer, m_sOutPortDef.nPortIndex[%d]", (int)m_sOutPortDef.nPortIndex); pthread_mutex_lock(&m_outBufMutex); if((OMX_S32)m_sOutBufList.nAllocSize >= m_sOutBufList.nBufArrSize) { pthread_mutex_unlock(&m_outBufMutex); return OMX_ErrorInsufficientResources; } nIndex = m_sOutBufList.nAllocSize; logd("malloc m_sOutBufList.pBufArr[nIndex[%d]].pBuffer:",(int)m_sInBufList.nAllocSize); m_sOutBufList.pBufArr[nIndex].pBuffer = (OMX_U8*)malloc(nSizeBytes); if (!m_sOutBufList.pBufArr[nIndex].pBuffer) { pthread_mutex_unlock(&m_outBufMutex); return OMX_ErrorInsufficientResources; } m_sOutBufList.nAllocBySelfFlags |= (1<nBufferCountActual) { pPortDef->bPopulated = OMX_TRUE; } pthread_mutex_unlock(&m_outBufMutex); } return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::free_buffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) { OMX_PARAM_PORTDEFINITIONTYPE* pPortDef; OMX_S32 nIndex; logd("(f:%s, l:%d) nPortIndex = %d, pBufferHdr = %p, m_state=0x%x", __FUNCTION__, __LINE__, (int)nPortIndex, pBufferHdr, m_state); if(hComponent == NULL || pBufferHdr == NULL) { return OMX_ErrorBadParameter; } // Match the pBufferHdr to the appropriate entry in the BufferList // and free the allocated memory if (nPortIndex == m_sInPortDef.nPortIndex) { pPortDef = &m_sInPortDef; pthread_mutex_lock(&m_inBufMutex); for(nIndex = 0; nIndex < m_sInBufList.nBufArrSize; nIndex++) { if(pBufferHdr == &m_sInBufList.pBufArr[nIndex]) break; } if(nIndex == m_sInBufList.nBufArrSize) { pthread_mutex_unlock(&m_inBufMutex); return OMX_ErrorBadParameter; } if(m_sInBufList.nAllocBySelfFlags & (1<bPopulated = OMX_FALSE; } pthread_mutex_unlock(&m_inBufMutex); } else if (nPortIndex == m_sOutPortDef.nPortIndex) { pPortDef = &m_sOutPortDef; pthread_mutex_lock(&m_outBufMutex); for(nIndex = 0; nIndex < m_sOutBufList.nBufArrSize; nIndex++) { logi("pBufferHdr = %p, &m_sOutBufList.pBufArr[%d] = %p", pBufferHdr, (int)nIndex, &m_sOutBufList.pBufArr[nIndex]); if(pBufferHdr == &m_sOutBufList.pBufArr[nIndex]) { break; } } logi("uIndex = %d", (int)nIndex); if(nIndex == m_sOutBufList.nBufArrSize) { pthread_mutex_unlock(&m_outBufMutex); return OMX_ErrorBadParameter; } if(m_sOutBufList.nAllocBySelfFlags & (1<bPopulated = OMX_FALSE; } pthread_mutex_unlock(&m_outBufMutex); } else { return OMX_ErrorBadParameter; } return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) { logd("***emptyThisBuffer: pts = %lld , audioFormat = %d", pBufferHdr->nTimeStamp, m_eCompressionFormat); ThrCmdType eCmd = EmptyBuf; if(hComponent == NULL || pBufferHdr == NULL) { return OMX_ErrorBadParameter; } if (!m_sInPortDef.bEnabled) { return OMX_ErrorIncorrectStateOperation; } if (pBufferHdr->nInputPortIndex != 0x0 || pBufferHdr->nOutputPortIndex != OMX_NOPORT) { return OMX_ErrorBadPortIndex; } if (m_state != OMX_StateExecuting && m_state != OMX_StatePause) { return OMX_ErrorIncorrectStateOperation; } //fwrite(pBufferHdr->pBuffer, 1, pBufferHdr->nFilledLen, ph264File); //DBG_WARNING("BHF[0x%x],len[%d]", pBufferHdr->nFlags, pBufferHdr->nFilledLen); // Put the command and data in the pipe write(m_cmdpipe[1], &eCmd, sizeof(eCmd)); write(m_cmddatapipe[1], &pBufferHdr, sizeof(OMX_BUFFERHEADERTYPE*)); return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) { ThrCmdType eCmd = FillBuf; // logd("(f:%s, l:%d) ", __FUNCTION__, __LINE__); if(hComponent == NULL || pBufferHdr == NULL) { return OMX_ErrorBadParameter; } if (!m_sOutPortDef.bEnabled) { return OMX_ErrorIncorrectStateOperation; } if (pBufferHdr->nOutputPortIndex != 0x1 || pBufferHdr->nInputPortIndex != OMX_NOPORT) { return OMX_ErrorBadPortIndex; } if (m_state != OMX_StateExecuting && m_state != OMX_StatePause) { return OMX_ErrorIncorrectStateOperation; } // Put the command and data in the pipe write(m_cmdpipe[1], &eCmd, sizeof(eCmd)); write(m_cmddatapipe[1], &pBufferHdr, sizeof(OMX_BUFFERHEADERTYPE*)); return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::set_callbacks(OMX_IN OMX_HANDLETYPE pHComp, OMX_IN OMX_CALLBACKTYPE* pCallbacks, OMX_IN OMX_PTR appData) { logi("(f:%s, l:%d) ", __FUNCTION__, __LINE__); if(pHComp == NULL || pCallbacks == NULL || appData == NULL) { return OMX_ErrorBadParameter; } memcpy(&m_Callbacks, pCallbacks, sizeof(OMX_CALLBACKTYPE)); m_pAppData = appData; return OMX_ErrorNone; } OMX_ERRORTYPE omx_adec::component_deinit(OMX_IN OMX_HANDLETYPE pHComp) { //logi(" COMPONENT_DEINIT"); logi("(f:%s, l:%d) ", __FUNCTION__, __LINE__); OMX_ERRORTYPE eError = OMX_ErrorNone; ThrCmdType eCmd = Stop; OMX_S32 nIndex = 0; CEDARC_UNUSE(pHComp); // In case the client crashes, check for nAllocSize parameter. // If this is greater than zero, there are elements in the list that are not free'd. // In that case, free the elements. if (m_sInBufList.nAllocSize > 0) { for(nIndex=0; nIndex 0) { for(nIndex=0; nIndexm_state == OMX_StateIdle || pSelf->m_state == OMX_StateWaitForResources) { OMX_U32 nTimeout = 0x0; while (1) { //*Transition happens only when the ports are unpopulated if (!pSelf->m_sInPortDef.bPopulated && !pSelf->m_sOutPortDef.bPopulated) { pSelf->m_state = OMX_StateLoaded; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandStateSet, pSelf->m_state, NULL); //* close decoder //* TODO. break; } else if (nTimeout++ > OMX_MAX_TIMEOUTS) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorInsufficientResources, 0 , NULL); logw("Transition to loaded failed\n"); break; } usleep(OMX_TIMEOUT*1000);logd("wait OMX_TIMEOUT ms"); } if(pSelf->m_decoder != NULL) { DestroyAudioDecoder(pSelf->m_decoder); pSelf->m_decoder = NULL; pSelf->mFirstInputDataFlag = OMX_TRUE;logd("****mFirstInputDataFlag = OMX_TRUE"); } logd("(f:%s, l:%d) DestroyAudioDecoder", __FUNCTION__, __LINE__); } else { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorIncorrectStateTransition, 0 , NULL); } return ; } static inline void setStateIdle(omx_adec* pSelf) { if (pSelf->m_state == OMX_StateInvalid) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorIncorrectStateTransition, 0 , NULL); } else { //*Return buffers if currently in pause and executing if (pSelf->m_state == OMX_StatePause || pSelf->m_state == OMX_StateExecuting) { pthread_mutex_lock(&pSelf->m_inBufMutex); while (pSelf->m_sInBufList.nSizeOfList > 0) { pSelf->m_sInBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sInBufList.nSizeOfList); pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos++]); if (pSelf->m_sInBufList.nReadPos >= pSelf->m_sInBufList.nBufArrSize) { pSelf->m_sInBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_inBufMutex); pthread_mutex_lock(&pSelf->m_outBufMutex); while (pSelf->m_sOutBufList.nSizeOfList > 0) { pSelf->m_sOutBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sOutBufList.nSizeOfList); pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++]); if (pSelf->m_sOutBufList.nReadPos >= pSelf->m_sOutBufList.nBufArrSize) { pSelf->m_sOutBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_outBufMutex); } else { ; } OMX_U32 nTimeout = 0x0; while (1) { //*Ports have to be populated before transition completes if ((!pSelf->m_sInPortDef.bEnabled && !pSelf->m_sOutPortDef.bEnabled) || (pSelf->m_sInPortDef.bPopulated && pSelf->m_sOutPortDef.bPopulated)) { pSelf->m_state = OMX_StateIdle; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandStateSet, pSelf->m_state, NULL); //* Open decoder //* TODO. break; } else if (nTimeout++ > OMX_MAX_TIMEOUTS) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorInsufficientResources, 0 , NULL); logw("Idle transition failed\n"); break; } usleep(OMX_TIMEOUT*1000);logd("wait OMX_TIMEOUT ms"); } } return ; } static inline void setStateExecuting(omx_adec* pSelf) { //*Transition can only happen from pause or idle state if (pSelf->m_state == OMX_StateIdle || pSelf->m_state == OMX_StatePause) { //*Return buffers if currently in pause if (pSelf->m_state == OMX_StatePause) { pthread_mutex_lock(&pSelf->m_inBufMutex); while (pSelf->m_sInBufList.nSizeOfList > 0) { pSelf->m_sInBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sInBufList.nSizeOfList); pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos++]); if (pSelf->m_sInBufList.nReadPos >= pSelf->m_sInBufList.nBufArrSize) { pSelf->m_sInBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_inBufMutex); pthread_mutex_lock(&pSelf->m_outBufMutex); while (pSelf->m_sOutBufList.nSizeOfList > 0) { pSelf->m_sOutBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sOutBufList.nSizeOfList); pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++]); if (pSelf->m_sOutBufList.nReadPos >= pSelf->m_sOutBufList.nBufArrSize) { pSelf->m_sOutBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_outBufMutex); } pSelf->m_state = OMX_StateExecuting; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandStateSet, pSelf->m_state, NULL); } else { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorIncorrectStateTransition, 0 , NULL); } pSelf->mEosFlag = OMX_FALSE; pSelf->pMarkData = NULL; pSelf->hMarkTargetComponent = NULL; return ; } static inline void controlSetState(omx_adec* pSelf, OMX_U32 cmddata) { //*If the parameter states a transition to the same state // raise a same state transition error. if (pSelf->m_state == (OMX_STATETYPE)(cmddata)) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorSameState, 0 , NULL); } else { //*transitions/callbacks made based on state transition table // cmddata contains the target state switch ((OMX_STATETYPE)(cmddata)) { case OMX_StateInvalid: pSelf->m_state = OMX_StateInvalid; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorInvalidState, 0 , NULL); pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandStateSet, pSelf->m_state, NULL); break; case OMX_StateLoaded: setStateLoaded(pSelf); break; case OMX_StateIdle: setStateIdle(pSelf); break; case OMX_StateExecuting: setStateExecuting(pSelf); break; case OMX_StatePause: // Transition can only happen from idle or executing state if (pSelf->m_state == OMX_StateIdle || pSelf->m_state == OMX_StateExecuting) { pSelf->m_state = OMX_StatePause; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandStateSet, pSelf->m_state, NULL); } else { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorIncorrectStateTransition, 0 , NULL); } break; case OMX_StateWaitForResources: if (pSelf->m_state == OMX_StateLoaded) { pSelf->m_state = OMX_StateWaitForResources; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandStateSet, pSelf->m_state, NULL); } else { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorIncorrectStateTransition, 0 , NULL); } break; default: pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorIncorrectStateTransition, 0 , NULL); break; } } } static inline void controlStopPort(omx_adec* pSelf, OMX_U32 cmddata) { logd(" stop port command, cmddata = %d.", (int)cmddata); //*Stop Port(s) // cmddata contains the port index to be stopped. // It is assumed that 0 is input and 1 is output port for this component // The cmddata value -1 means that both input and output ports will be stopped. if (cmddata == 0x0 || (OMX_S32)cmddata == -1) { //*Return all input buffers pthread_mutex_lock(&pSelf->m_inBufMutex); while (pSelf->m_sInBufList.nSizeOfList > 0) { pSelf->m_sInBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sInBufList.nSizeOfList); pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos++]); if (pSelf->m_sInBufList.nReadPos >= pSelf->m_sInBufList.nBufArrSize) { pSelf->m_sInBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_inBufMutex); //*Disable port pSelf->m_sInPortDef.bEnabled = OMX_FALSE; } if (cmddata == 0x1 || (OMX_S32)cmddata == -1) { //*Return all output buffers pthread_mutex_lock(&pSelf->m_outBufMutex); while (pSelf->m_sOutBufList.nSizeOfList > 0) { pSelf->m_sOutBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sOutBufList.nSizeOfList); pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++]); if (pSelf->m_sOutBufList.nReadPos >= pSelf->m_sOutBufList.nBufArrSize) { pSelf->m_sOutBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_outBufMutex); // Disable port pSelf->m_sOutPortDef.bEnabled = OMX_FALSE; } // Wait for all buffers to be freed OMX_U32 nTimeout = 0x0; while (1) { if (cmddata == 0x0 && !pSelf->m_sInPortDef.bPopulated) { //*Return cmdcomplete event if input unpopulated pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortDisable, 0x0, NULL); break; } if (cmddata == 0x1 && !pSelf->m_sOutPortDef.bPopulated) { //*Return cmdcomplete event if output unpopulated pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortDisable, 0x1, NULL); break; } if ((OMX_S32)cmddata == -1 && !pSelf->m_sInPortDef.bPopulated && !pSelf->m_sOutPortDef.bPopulated) { //*Return cmdcomplete event if inout & output unpopulated pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortDisable, 0x0, NULL); pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortDisable, 0x1, NULL); break; } if (nTimeout++ > OMX_MAX_TIMEOUTS) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorPortUnresponsiveDuringDeallocation, 0 , NULL); break; } usleep(OMX_TIMEOUT*1000);logd("wait OMX_TIMEOUT ms"); } return ; } static inline void controlRestartPort(omx_adec* pSelf, OMX_U32 cmddata) { logd(" restart port command.pSelf->m_state[%d]", pSelf->m_state); //*Restart Port(s) // cmddata contains the port index to be restarted. // It is assumed that 0 is input and 1 is output port for this component. // The cmddata value -1 means both input and output ports will be restarted. /* if (cmddata == 0x0 || (OMX_S32)cmddata == -1) pSelf->m_sInPortDef.bEnabled = OMX_TRUE; if (cmddata == 0x1 || (OMX_S32)cmddata == -1) pSelf->m_sOutPortDef.bEnabled = OMX_TRUE; */ // Wait for port to be populated OMX_U32 nTimeout = 0x0; while (1) { // Return cmdcomplete event if input port populated if (cmddata == 0x0 && (pSelf->m_state == OMX_StateLoaded || pSelf->m_sInPortDef.bPopulated)) { pSelf->m_sInPortDef.bEnabled = OMX_TRUE; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortEnable, 0x0, NULL); break; } // Return cmdcomplete event if output port populated else if (cmddata == 0x1 && (pSelf->m_state == OMX_StateLoaded || pSelf->m_sOutPortDef.bPopulated)) { pSelf->m_sOutPortDef.bEnabled = OMX_TRUE; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortEnable, 0x1, NULL); break; } // Return cmdcomplete event if input and output ports populated else if ((OMX_S32)cmddata == -1 && (pSelf->m_state == OMX_StateLoaded || (pSelf->m_sInPortDef.bPopulated && pSelf->m_sOutPortDef.bPopulated))) { pSelf->m_sInPortDef.bEnabled = OMX_TRUE; pSelf->m_sOutPortDef.bEnabled = OMX_TRUE; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortEnable, 0x0, NULL); pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandPortEnable, 0x1, NULL); break; } else if (nTimeout++ > OMX_MAX_TIMEOUTS) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorPortUnresponsiveDuringAllocation, 0, NULL); break; } usleep(OMX_TIMEOUT*1000);logd("wait OMX_TIMEOUT ms"); } if(pSelf->port_setting_match == OMX_FALSE) { pSelf->port_setting_match = OMX_TRUE; } } static inline void controlFlush(omx_adec* pSelf, OMX_U32 cmddata) { logd(" flush command."); //*Flush port(s) // cmddata contains the port index to be flushed. // It is assumed that 0 is input and 1 is output port for this component // The cmddata value -1 means that both input and output ports will be flushed. //if request flush input and output port, we reset decoder! if(cmddata == OMX_ALL || cmddata == 0x1 || (OMX_S32)cmddata == -1) { logd(" flush all port! we reset decoder!"); if(pSelf->m_decoder) { ResetAudioDecoder(pSelf->m_decoder,0); } else { logw(" fatal error, m_decoder is not malloc when flush all ports!"); } } if (cmddata == 0x0 || (OMX_S32)cmddata == -1) { // Return all input buffers and send cmdcomplete pthread_mutex_lock(&pSelf->m_inBufMutex); while (pSelf->m_sInBufList.nSizeOfList > 0) { pSelf->m_sInBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sInBufList.nSizeOfList); pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos++]); if (pSelf->m_sInBufList.nReadPos >= pSelf->m_sInBufList.nBufArrSize) { pSelf->m_sInBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_inBufMutex); pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandFlush, 0x0, NULL); } if (cmddata == 0x1 || (OMX_S32)cmddata == -1) { // Return all output buffers and send cmdcomplete pthread_mutex_lock(&pSelf->m_outBufMutex); while (pSelf->m_sOutBufList.nSizeOfList > 0) { pSelf->m_sOutBufList.nSizeOfList--; logd("*****nSizeOfList:%d",(int)pSelf->m_sOutBufList.nSizeOfList); pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++]); if (pSelf->m_sOutBufList.nReadPos >= pSelf->m_sOutBufList.nBufArrSize) { pSelf->m_sOutBufList.nReadPos = 0; } } pthread_mutex_unlock(&pSelf->m_outBufMutex); pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventCmdComplete, OMX_CommandFlush, 0x1, NULL); } return ; } static inline void controlFillBuf(omx_adec* pSelf, OMX_U32 cmddata) { //*Fill buffer logd("****cmd = FillBuf,pSelf->m_sOutBufList.nSizeOfList:%d,nAllocSize:%d", (int)pSelf->m_sOutBufList.nSizeOfList,(int)pSelf->m_sOutBufList.nAllocSize); pthread_mutex_lock(&pSelf->m_outBufMutex); if (pSelf->m_sOutBufList.nSizeOfList < pSelf->m_sOutBufList.nAllocSize) { pSelf->m_sOutBufList.nSizeOfList++; pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nWritePos++] = ((OMX_BUFFERHEADERTYPE*) cmddata); if (pSelf->m_sOutBufList.nWritePos >= (OMX_S32)pSelf->m_sOutBufList.nAllocSize) { pSelf->m_sOutBufList.nWritePos = 0; } } pthread_mutex_unlock(&pSelf->m_outBufMutex); return ; } static inline int controlEmptyBuf(omx_adec* pSelf, OMX_U32 cmddata) { OMX_BUFFERHEADERTYPE* pTmpInBufHeader = (OMX_BUFFERHEADERTYPE*) cmddata; OMX_TICKS nInterval; OMX_BUFFERHEADERTYPE* pInBufHdr = NULL; logd("****cmd = EmptyBuf,pSelf->m_sInBufList.nSizeOfList:%d,nAllocSize:%d", (int)pSelf->m_sInBufList.nSizeOfList,(int)pSelf->m_sInBufList.nAllocSize); //*Empty buffer pthread_mutex_lock(&pSelf->m_inBufMutex); if(pSelf->m_nInportPrevTimeStamp) { //compare pts to decide if jump nInterval = pTmpInBufHeader->nTimeStamp - pSelf->m_nInportPrevTimeStamp; if(nInterval < -AWOMX_PTS_JUMP_THRESH || nInterval > AWOMX_PTS_JUMP_THRESH) { logd("pts jump [%lld]us, prev[%lld],cur[%lld],need reset vdeclib", nInterval, pSelf->m_nInportPrevTimeStamp, pTmpInBufHeader->nTimeStamp); pSelf->m_JumpFlag = OMX_TRUE; } pSelf->m_nInportPrevTimeStamp = pTmpInBufHeader->nTimeStamp; } else //first InBuf data { pSelf->m_nInportPrevTimeStamp = pTmpInBufHeader->nTimeStamp; } if (pSelf->m_sInBufList.nSizeOfList < pSelf->m_sInBufList.nAllocSize) { pSelf->m_sInBufList.nSizeOfList++; pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nWritePos++] = ((OMX_BUFFERHEADERTYPE*) cmddata); if (pSelf->m_sInBufList.nWritePos >= (OMX_S32)pSelf->m_sInBufList.nAllocSize) { pSelf->m_sInBufList.nWritePos = 0; } } logd("(omx_adec, f:%s, l:%d) nTimeStamp[%lld], nAllocLen[%d], nFilledLen[%d],\ nOffset[%d], nFlags[0x%x], nOutputPortIndex[%d], nInputPortIndex[%d],nSizeOfList[%d]", __FUNCTION__, __LINE__, pTmpInBufHeader->nTimeStamp, (int)pTmpInBufHeader->nAllocLen, (int)pTmpInBufHeader->nFilledLen, (int)pTmpInBufHeader->nOffset, (int)pTmpInBufHeader->nFlags, (int)pTmpInBufHeader->nOutputPortIndex, (int)pTmpInBufHeader->nInputPortIndex, (int)pSelf->m_sInBufList.nSizeOfList); pthread_mutex_unlock(&pSelf->m_inBufMutex); logd("****mFirstInputDataFlag:%d",pSelf->mFirstInputDataFlag); if(pSelf->mFirstInputDataFlag==OMX_TRUE && pSelf->m_sInBufList.nSizeOfList>0) { pInBufHdr = pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos]; if(pInBufHdr != NULL) { int ret = -1; pSelf->mFirstInputDataFlag = OMX_FALSE; logd("*** the first pInBufHdr->nFlags = 0x%x",(int)pInBufHdr->nFlags); pSelf->m_streamInfo.eSubCodecFormat = pSelf->m_codec_tag; pSelf->m_streamInfo.nChannelNum = pSelf->m_channels; pSelf->m_streamInfo.nSampleRate = pSelf->m_sampleRate; pSelf->m_streamInfo.nAvgBitrate = pSelf->m_bitRate; pSelf->m_streamInfo.nBlockAlign = pSelf->m_blockalign; pSelf->m_streamInfo.nBitsPerSample = pSelf->m_bitspersample; if (pInBufHdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { int i =0; logd("***nFilledLen %d",(int)pInBufHdr->nFilledLen); for(i=0;i<(int)pInBufHdr->nFilledLen;i++) { logd("***pCodecSpecificData[0x%02x] 0x%02x",i,pInBufHdr->pBuffer[i]); } if(pSelf->m_streamInfo.pCodecSpecificData) { free(pSelf->m_streamInfo.pCodecSpecificData); } pSelf->m_streamInfo.nCodecSpecificDataLen = pInBufHdr->nFilledLen; pSelf->m_streamInfo.pCodecSpecificData = (char*)malloc(pSelf->m_streamInfo.nCodecSpecificDataLen); memset(pSelf->m_streamInfo.pCodecSpecificData,0, pSelf->m_streamInfo.nCodecSpecificDataLen); memcpy(pSelf->m_streamInfo.pCodecSpecificData, pInBufHdr->pBuffer,pSelf->m_streamInfo.nCodecSpecificDataLen); if (pSelf->m_state != OMX_StateExecuting) { logd("fatal error! when vdrv OMX_AdrvCommand_PrepareAdecLib,\ m_state[0x%x] should be OMX_StateLoaded", pSelf->m_state); } //*if mdecoder had closed before, we should create it if(pSelf->m_decoder==NULL) { pSelf->m_decoder = CreateAudioDecoder(); BsInFor m_audioConfig; memset(&m_audioConfig,0,sizeof(BsInFor)); ret = InitializeAudioDecoder(pSelf->m_decoder, &(pSelf->m_streamInfo),&m_audioConfig); if(ret != 0) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorHardware, 0 , NULL); logd("Idle transition failed, set_vstream_info() return fail.\n"); return OMX_ADEC_RESULT_EXIT; } } else { logd("CreateAudioDecoder again"); } pSelf->m_sInBufList.nSizeOfList--; pSelf->m_sInBufList.nReadPos++; logd("*****nSizeOfList:%d",(int)pSelf->m_sInBufList.nSizeOfList); if (pSelf->m_sInBufList.nReadPos >= (OMX_S32)pSelf->m_sInBufList.nAllocSize) { pSelf->m_sInBufList.nReadPos = 0; } pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pInBufHdr); } else { if (pSelf->m_state != OMX_StateExecuting) { logw("fatal error! when vdrv OMX_AdrvCommand_PrepareAdecLib, \ m_state[0x%x] should be OMX_StateLoaded", pSelf->m_state); } //*if mdecoder had closed before, we should create it if(pSelf->m_decoder==NULL) { pSelf->m_decoder = CreateAudioDecoder(); BsInFor m_audioConfig; memset(&m_audioConfig,0,sizeof(BsInFor)); ret = InitializeAudioDecoder(pSelf->m_decoder, &(pSelf->m_streamInfo),&m_audioConfig); if(ret != 0) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError, OMX_ErrorHardware, 0 , NULL); logd("Idle transition failed, set_vstream_info() return fail.\n"); return OMX_ADEC_RESULT_EXIT; } } else { logd("CreateAudioDecoder again"); } } pInBufHdr = NULL; } } //*Mark current buffer if there is outstanding command if (pSelf->pMarkBuf) { ((OMX_BUFFERHEADERTYPE *)(cmddata))->hMarkTargetComponent = &pSelf->mOmxCmp; ((OMX_BUFFERHEADERTYPE *)(cmddata))->pMarkData = pSelf->pMarkBuf->pMarkData; pSelf->pMarkBuf = NULL; } return OMX_ADEC_RESULT_OK; } static inline int processThreadCommand(omx_adec* pSelf, ThrCmdType cmd, OMX_U32 cmddata) { logd(" set state command, cmd = %d, cmddata = %d.", (int)cmd, (int)cmddata); int ret = OMX_ADEC_RESULT_OK; //*State transition command if (cmd == SetState) { controlSetState(pSelf, cmddata); } else if (cmd == StopPort) { controlStopPort(pSelf, cmddata); } else if (cmd == RestartPort) { controlRestartPort(pSelf, cmddata); } else if (cmd == Flush) { controlFlush(pSelf, cmddata); } else if (cmd == Stop) { logd(" stop command."); // Kill thread ret = OMX_ADEC_RESULT_EXIT; } else if (cmd == FillBuf) { controlFillBuf(pSelf, cmddata); } else if (cmd == EmptyBuf) { ret = controlEmptyBuf(pSelf, cmddata); } else if (cmd == MarkBuf) { if (!pSelf->pMarkBuf) pSelf->pMarkBuf = (OMX_MARKTYPE *)(cmddata); } return ret; } static inline int sendStreamDataToDecoder(omx_adec * pSelf) { OMX_U8* pBuf0; OMX_U8* pBuf1; int size0; int size1; OMX_U8* pData; OMX_BUFFERHEADERTYPE* pInBufHdr = NULL; int nOffset = 0; pInBufHdr = NULL; //* check if there is a input bit stream. pthread_mutex_lock(&pSelf->m_inBufMutex); if(pSelf->m_sInBufList.nSizeOfList > 0) { pSelf->m_sInBufList.nSizeOfList; pInBufHdr = pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos]; } pthread_mutex_unlock(&pSelf->m_inBufMutex); logd("****inputnum:%d,ptr:%p",(int)pSelf->m_sInBufList.nSizeOfList,pInBufHdr); logd("****line:%d,nOffset:%d",__LINE__,nOffset); //* add stream to decoder. if(pInBufHdr) { int require_size = pInBufHdr->nFilledLen; logd("****line:%d,nOffset:%d",__LINE__,nOffset); //DBG_WARNING("vbs data size[%d]", require_size); int ret = ParserRequestBsBuffer(pSelf->m_decoder, require_size, &pBuf0, &size0, &pBuf1, &size1,&nOffset); if(ret != 0) { ALOGD("req vbs fail!"); return OMX_ADEC_RESULT_CONTINUE; } logd("****line:%d,nOffset:%d",__LINE__,nOffset); if(require_size <= size0) { pData = pInBufHdr->pBuffer + pInBufHdr->nOffset; memcpy(pBuf0, pData, require_size); } else { pData = pInBufHdr->pBuffer + pInBufHdr->nOffset; memcpy(pBuf0, pData, size0); pData += size0; memcpy(pBuf1, pData, require_size - size0); } logd("****line:%d,nOffset:%d",__LINE__,nOffset); ParserUpdateBsBuffer(pSelf->m_decoder, pInBufHdr->nFilledLen, pInBufHdr->nTimeStamp, nOffset);logd("****line:%d,nOffset:%d",__LINE__,nOffset); //DBG_WARNING("EmptyBufferDone is called"); pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pInBufHdr); pSelf->m_sInBufList.nSizeOfList--; pSelf->m_sInBufList.nReadPos++; if (pSelf->m_sInBufList.nReadPos >= (OMX_S32)pSelf->m_sInBufList.nAllocSize) { pSelf->m_sInBufList.nReadPos = 0; } if (pInBufHdr->nFlags & OMX_BUFFERFLAG_EOS) { // Copy flag to output buffer header pSelf->mEosFlag = OMX_TRUE; ALOGD(" set up eos flag."); // Trigger event handler pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventBufferFlag, 0x1, pInBufHdr->nFlags, NULL); // Clear flag pInBufHdr->nFlags = 0; } // Check for mark buffers if (pInBufHdr->pMarkData) { // Copy mark to output buffer header if (pSelf->pMarkData == NULL && pSelf->hMarkTargetComponent == NULL) { pSelf->pMarkData = pInBufHdr->pMarkData; // Copy handle to output buffer header pSelf->hMarkTargetComponent = pInBufHdr->hMarkTargetComponent; } } // Trigger event handler if (pInBufHdr->hMarkTargetComponent == &pSelf->mOmxCmp && pInBufHdr->pMarkData) { pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventMark, 0, 0, pInBufHdr->pMarkData); } //pInBufHdr = NULL; } return OMX_ADEC_RESULT_OK; } /* * Component Thread * The ComponentThread function is exeuted in a separate pThread and * is used to implement the actual component functions. */ /*****************************************************************************/ static void* ComponentThread(void* pThreadData) { int decodeResult; // VideoPicture* picture; int i; int fd1; fd_set rfds; OMX_U32 cmddata; ThrCmdType cmd; // Variables related to decoder buffer handling OMX_BUFFERHEADERTYPE* pInBufHdr = NULL; OMX_BUFFERHEADERTYPE* pOutBufHdr = NULL; OMX_U8* pInBuf = NULL; OMX_U32 nInBufSize; // Variables related to decoder timeouts OMX_U32 nTimeout; struct timeval timeout; int readRet = 0; // Recover the pointer to my component specific data omx_adec* pSelf = static_cast(pThreadData); while (1) { fd1 = pSelf->m_cmdpipe[0]; FD_ZERO(&rfds); FD_SET(fd1, &rfds); //*Check for new command timeout.tv_sec = 0; timeout.tv_usec = 0; i = select(pSelf->m_cmdpipe[0]+1, &rfds, NULL, NULL, &timeout); //logd("*****************"); if (FD_ISSET(pSelf->m_cmdpipe[0], &rfds)) { //*retrieve command and data from pipe //logd("*****************"); readRet = read(pSelf->m_cmdpipe[0], &cmd, sizeof(cmd)); if(readRet<0) { logd("error: read pipe data failed!,ret = %d",(int)readRet); goto EXIT; } readRet = read(pSelf->m_cmddatapipe[0], &cmddata, sizeof(cmddata)); if(readRet<0) { logd("error: read pipe data failed!,ret = %d",(int)readRet); goto EXIT; } logd(" set state command, cmd = %d, cmddata = %d.", (int)cmd, (int)cmddata);//test if(processThreadCommand(pSelf, cmd, cmddata) == OMX_ADEC_RESULT_EXIT) goto EXIT; } if (pSelf->m_state == OMX_StateExecuting && pSelf->m_sInPortDef.bEnabled && pSelf->m_sOutPortDef.bEnabled && pSelf->port_setting_match == OMX_TRUE) { if(OMX_TRUE == pSelf->m_JumpFlag) { logd("reset vdeclib for jump!"); pSelf->m_JumpFlag = OMX_FALSE; } pthread_mutex_lock(&pSelf->m_outBufMutex); if(pSelf->m_sOutBufList.nSizeOfList > 0) { pSelf->m_sOutBufList.nSizeOfList; pOutBufHdr = pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos]; } else { pOutBufHdr = NULL; } pthread_mutex_unlock(&pSelf->m_outBufMutex); //* if no output buffer, wait for some time. if(pOutBufHdr == NULL) { continue; } if(pSelf->mFirstInputDataFlag==OMX_TRUE) { logd("mFirstInputDataFlag init no ok"); continue; } int vbv = 0; int ValidPercent = 0; BsQueryQuality(pSelf->m_decoder,&ValidPercent,&vbv); if((pSelf->mEosFlag)&&(vbv==0)) { //set eof flag, MediaCodec use this flag //to determine whether a playback is finished. pthread_mutex_lock(&pSelf->m_outBufMutex); while(pSelf->m_sOutBufList.nSizeOfList > 0) { pSelf->m_sOutBufList.nSizeOfList--; pOutBufHdr = pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++]; if (pSelf->m_sOutBufList.nReadPos >= (OMX_S32)pSelf->m_sOutBufList.nAllocSize) { pSelf->m_sOutBufList.nReadPos = 0; } // CHECK(pOutBufHdr != NULL); if(pSelf->m_sOutBufList.nSizeOfList == 0) { logd("(f:%s, l:%d), EOS msg send with FillBufferDone", __FUNCTION__, __LINE__); pOutBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; } pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pOutBufHdr); pOutBufHdr = NULL; } pthread_mutex_unlock(&pSelf->m_outBufMutex); logd("end file!!!!!!!"); break; } if((pSelf->m_sInBufList.nSizeOfList==0)&&(vbv==0)) { logd("pInBufHdr = 0,no bs data"); continue; } logd("****list:%d,vbv:%d",(int)pSelf->m_sInBufList.nSizeOfList,vbv); if((pSelf->m_sInBufList.nSizeOfList>0)&&(vbv<4)) { if(sendStreamDataToDecoder(pSelf) == OMX_ADEC_RESULT_CONTINUE) continue ; } pOutBufHdr->nOffset = 0; decodeResult = DecodeAudioStream(pSelf->m_decoder,&(pSelf->m_streamInfo), (char*)(pOutBufHdr->pBuffer + pOutBufHdr->nOffset), (int*)(&pOutBufHdr->nFilledLen)); pOutBufHdr->nTimeStamp = PlybkRequestPcmPts(pSelf->m_decoder); logd("***decodeResult = %d",decodeResult); if((decodeResult==ERR_AUDIO_DEC_NONE) &&((pSelf->m_channel != pSelf->m_streamInfo.nChannelNum) ||(pSelf->m_sampleRate != pSelf->m_streamInfo.nSampleRate))) { logd("****fs:%d,m_fs:%d,ch:%d,m_ch:%d", pSelf->m_streamInfo.nSampleRate,pSelf->m_sampleRate, pSelf->m_streamInfo.nChannelNum,pSelf->m_channel); pSelf->m_channel = pSelf->m_streamInfo.nChannelNum; pSelf->m_sampleRate = pSelf->m_streamInfo.nSampleRate; pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventPortSettingsChanged, 0x01, OMX_IndexConfigCommonOutputCrop, NULL); } if(pOutBufHdr->nFilledLen) { pSelf->m_sOutBufList.nSizeOfList--; pSelf->m_sOutBufList.nReadPos++; logd("*****nSizeOfList:%d",(int)pSelf->m_sOutBufList.nSizeOfList); if (pSelf->m_sOutBufList.nReadPos >= (OMX_S32)pSelf->m_sOutBufList.nAllocSize) { pSelf->m_sOutBufList.nReadPos = 0; } pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData, pOutBufHdr); pOutBufHdr = NULL; } if(decodeResult == ERR_AUDIO_DEC_NONE || decodeResult == ERR_AUDIO_DEC_FFREVRETURN || decodeResult == ERR_AUDIO_DEC_VIDEOJUMP) { continue; } else if(decodeResult == ERR_AUDIO_DEC_NO_BITSTREAM ) { continue; } else if(decodeResult < 0) { logd("decode fatal error[%d]", decodeResult); continue; } } } EXIT: if(pSelf->m_decoder != NULL) { DestroyAudioDecoder(pSelf->m_decoder); pSelf->m_decoder = NULL; pSelf->mFirstInputDataFlag = OMX_TRUE; logd("DestroyAudioDecoder"); logd("*****mFirstInputDataFlag = OMX_TRUE"); } return (void*)OMX_ErrorNone; }