sdk-hwV1.3/external/eyesee-mpp/middleware/sun8iw21/media/component/Demux_Component.c

3323 lines
124 KiB
C
Executable File

/******************************************************************************
Copyright (C), 2001-2016, Allwinner Tech. Co., Ltd.
******************************************************************************
File Name : Demux_Component.c
Version : Initial Draft
Author : Allwinner BU3-PD2 Team
Created : 2016/08/05
Last Modified :
Description : mpp component implement
Function List :
History :
******************************************************************************/
//#define LOG_NDEBUG 0
#define LOG_TAG "Demux_Component"
#include <utils/plat_log.h>
//ref platform headers
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/prctl.h>
#include "plat_type.h"
#include "plat_errno.h"
#include "plat_defines.h"
#include "plat_math.h"
#include "cdx_list.h"
//media api headers to app
#include "SystemBase.h"
#include "mm_common.h"
#include "mm_comm_demux.h"
#include "mpi_demux.h"
//media internal common headers.
#include "media_common.h"
#include "mm_component.h"
#include "ComponentCommon.h"
#include "tmessage.h"
#include "tsemaphore.h"
#include <DemuxTypeMap.h>
#include "Demux_Component.h"
#include <CDX_ErrorType.h>
#define DEBUG_SAVE_VIDEO_STREAM (0)
#if DEBUG_SAVE_VIDEO_STREAM
static const char* fpVideoStreamPath = "/tmp/DmxVideo.dat"; //"/data/camera/1011.dat";
static FILE* fpVideoStream = NULL;
#endif
#define MAX_USE_BUFFER_NUM (4)
#define PER_BLOCK_SIZE (1024*64)
typedef struct _BUFFER_MNG
{
int mPktListNodeCnt;
struct list_head idlePktList; //DMXPKT_NODE_T
struct list_head fillingPktList;
struct list_head readyPktList;
struct list_head usingPktList;
pthread_mutex_t mPktlistMutex;
BOOL mWaitReadyPktFlag;
BOOL mWaitIdlePktFlag;
pthread_cond_t mWaitIdleCondition;
pthread_cond_t mWaitReadyCondition;
}BUFFER_MNG;
typedef struct _DEMUXDATATYPE
{
COMP_STATETYPE state;
pthread_mutex_t mStateLock;
COMP_CALLBACKTYPE *pCallbacks;
void* pAppData;
COMP_HANDLETYPE hSelf;
char mThreadName[32];
COMP_PORT_PARAM_TYPE sPortParam;
COMP_PARAM_PORTDEFINITIONTYPE sPortDef[DEMUX_MAX_PORT_COUNT];
COMP_PARAM_PORTEXTRADEFINITIONTYPE sPortExtraDef[DEMUX_MAX_PORT_COUNT];
COMP_INTERNAL_TUNNELINFOTYPE sPortTunnelInfo[DEMUX_MAX_PORT_COUNT];
COMP_PARAM_BUFFERSUPPLIERTYPE sPortBufSupplier[DEMUX_MAX_PORT_COUNT];
BOOL mInputPortTunnelFlag;
BOOL mOutputPortTunnelFlag[DEMUX_MAX_PORT_COUNT]; //TRUE: tunnel mode; FALSE: non-tunnel mode.
MPP_CHN_S mMppChnInfo; // do not know what to do -> keep nChnId
DEMUX_CHN_ATTR_S mDemuxChnAttr; // keep sourcedata info
pthread_t thread_id;
CompInternalMsgType eTCmd;
message_queue_t cmd_queue;
int demux_type; //CDX_MEDIA_FILE_FORMAT, mp4/ts
int disable_track; //cdx_player set it to disable audio/video/subtitle track. DEMUX_DISABLE_AUDIO_TRACK
// below 2 may not be used
//int disable_media_type; //cdx_player set it.CDX_MEDIA_TYPE_DISABLE_AVI, CDX_CODEC_TYPE_DISABLE_MPEG2
int disable_proprity_track; //cdx_player set it to disable proprietary media type(audio ac3/dts\), 1 or 0.
int mFd; //record fd of setDataSource().
CEDARX_SOURCETYPE mSourceType; //* url or fd or IStreamSource.
CdxDataSourceT datasrc_desc; //CedarXDataSourceDesc
CedarXDemuxerAPI *cdx_epdk_dmx;
CdxMediaInfoT cdx_mediainfo; //CedarXMediainfo, some pointer is malloc by parserLib, so if parserLib is close, these pointers will become wild pointer.
CdxPacketT cdx_pkt; //CedarXPacket
CedarXSeekPara seek_para;
int mCurVideoStreamIndex;
int mCurAudioStreamIndex; //from 0
int mCurSubtitleStreamIndex; //from 0
BOOL mSwitchAudioFlag;
int video_port_idx;
int audio_port_idx;
int subtitle_port_idx;
int clock_port_idx;
int64_t max_send_packet_time_video; //unit:us
int64_t max_send_packet_time_audio; //unit:us
int64_t max_send_packet_time_subtitle;
int demux_init_end;
int dmx_eof;
int dmx_eof_send;
int dmx_seek_flag;
int sub_disable;
unsigned int prefetch_done;
unsigned int playBDFileTag; ////1:bd, 0:common file. same as CedarXPlayerContext->play_bd_file
int force_exit;
int switching_state;
BOOL mAllocBufFlag;
BUFFER_MNG mBufferMng[DEMUX_MAX_PORT_COUNT];
BOOL mWaitVideoBufFlag;
BOOL mWaitAudioBufFlag;
BOOL mWaitSubtitleBufFlag;
} DEMUXDATATYPE;
static void* ComponentThread(void* pThreadData);
static int CB_EventHandler(void* cookie, int event, void *data);
static int map_PacketType_To_MediaType(cdx_int32 pkt_type)
{
int media_type = CDX_PacketUnkown;
if (pkt_type == CDX_MEDIA_VIDEO)
{
media_type = CDX_PacketVideo;
}
else if (pkt_type == CDX_MEDIA_AUDIO)
{
media_type = CDX_PacketAudio;
}
else if (pkt_type == CDX_MEDIA_SUBTITLE)
{
media_type = CDX_PacketSubtitle;
}
else
{
aloge("fatal error! Unknown packet type (%d) detected", pkt_type);
}
return media_type;
}
static void allocDmxOutputBuf(DEMUXDATATYPE *pDemuxData)
{
DMXPKT_NODE_T *pEntry, *pTmp;
ERRORTYPE eError = SUCCESS;
COMP_PARAM_PORTDEFINITIONTYPE* pPortDef = NULL;
COMP_INTERNAL_TUNNELINFOTYPE* pTunnelInfo = NULL;
COMP_PARAM_BUFFERSUPPLIERTYPE* pBufSupplier = NULL;
BUFFER_MNG* pBufMng = NULL;
if (pDemuxData->mAllocBufFlag)
{
alogw("buffer has alloc, never alloc again");
return;
}
// find all ports
int valid_ports[DEMUX_MAX_PORT_COUNT];
int valid_port_num = 0;
if (pDemuxData->video_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->video_port_idx;
valid_port_num++;
}
if (pDemuxData->audio_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->audio_port_idx;
valid_port_num++;
}
if (pDemuxData->subtitle_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->subtitle_port_idx;
valid_port_num++;
}
for (int i = 0; i < valid_port_num; i++)
{
int cnt = 0;
int port_idx = valid_ports[i];
pPortDef = &pDemuxData->sPortDef[port_idx];
pTunnelInfo = &pDemuxData->sPortTunnelInfo[port_idx];
pBufSupplier = &pDemuxData->sPortBufSupplier[port_idx];
pBufMng = &pDemuxData->mBufferMng[port_idx];
if ( pDemuxData->mOutputPortTunnelFlag[port_idx]
&& pBufSupplier->eBufferSupplier == COMP_BufferSupplyInput
)
{// audio/video/muxer supply buffer, no need to alloc
continue;
}
pthread_mutex_lock(&pBufMng->mPktlistMutex);
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->idlePktList, mList)
{
pEntry->stEncodedStream.nBufferLen = PER_BLOCK_SIZE;
pEntry->stEncodedStream.pBuffer = (unsigned char *)malloc(PER_BLOCK_SIZE);
if (pEntry->stEncodedStream.pBuffer == NULL)
{
pEntry->stEncodedStream.nBufferLen = 0;
break;
}
memset(pEntry->stEncodedStream.pBuffer, 0, pEntry->stEncodedStream.nBufferLen);
pEntry->stEncodedStream.pBufferExtra = NULL;
pEntry->stEncodedStream.nBufferExtraLen = 0;
cnt++;
}
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->idlePktList, mList)
{
if (pEntry->stEncodedStream.pBuffer == NULL) //free no alloc buf node
{
list_del(&pEntry->mList);
free(pEntry);
pBufMng->mPktListNodeCnt--;
}
}
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
if (pBufMng->mPktListNodeCnt != cnt)
{
aloge("[%d]node alloc buf, but there is[%d] we marked, not compitible", pBufMng->mPktListNodeCnt, cnt);
}
alogd("port_idx[%d] alloc_buf, cnt = %d", port_idx, pBufMng->mPktListNodeCnt);
}
pDemuxData->mAllocBufFlag = TRUE;
return;
}
static int DemuxGetCurrentProgramAudioNum(DEMUXDATATYPE *pDemuxData)
{
struct CdxProgramS *pProgram = &pDemuxData->cdx_mediainfo.program[0];
return pProgram->audioNum;
}
// create buffer manager
static ERRORTYPE Demux_CreateBufferMng(DEMUXDATATYPE *pDemuxData, int port_idx)
{
ERRORTYPE eError;
BUFFER_MNG* pBufferMng = &pDemuxData->mBufferMng[port_idx];
INIT_LIST_HEAD(&pBufferMng->idlePktList);
INIT_LIST_HEAD(&pBufferMng->readyPktList);
INIT_LIST_HEAD(&pBufferMng->usingPktList);
INIT_LIST_HEAD(&pBufferMng->fillingPktList);
pBufferMng->mPktListNodeCnt = 0;
for (int i = 0; i < MAX_USE_BUFFER_NUM; i++)
{
DMXPKT_NODE_T* pNode = (DMXPKT_NODE_T *)malloc(sizeof(DMXPKT_NODE_T));
if (NULL == pNode)
{
aloge("fatal error! alloc pkt_node fail");
break;
}
memset(pNode, 0, sizeof(DMXPKT_NODE_T));
pNode->stEncodedStream.nID = i + 1;
list_add_tail(&pNode->mList, &pBufferMng->idlePktList);
pBufferMng->mPktListNodeCnt++;
}
if (pBufferMng->mPktListNodeCnt == 0)
{
return FAILURE;
}
int err = pthread_mutex_init(&pBufferMng->mPktlistMutex, NULL);
if (err !=0 )
{
aloge("fatal error! pthread mutex init fail!");
eError = FAILURE;
goto err0;
}
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
err = pthread_cond_init(&pBufferMng->mWaitIdleCondition, &condAttr);
if (err != 0)
{
aloge("fatal error! init thread condition fail");
eError = FAILURE;
goto err1;
}
err = pthread_cond_init(&pBufferMng->mWaitReadyCondition, &condAttr);
if (err != 0)
{
aloge("fatal error! init thread condition fail");
eError = FAILURE;
goto err2;
}
return SUCCESS;
err3:
pthread_cond_destroy(&pBufferMng->mWaitIdleCondition);
err2:
pthread_cond_destroy(&pBufferMng->mWaitReadyCondition);
err1:
pthread_mutex_destroy(&pBufferMng->mPktlistMutex);
err0:
if (!list_empty(&pBufferMng->idlePktList))
{
DMXPKT_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pBufferMng->idlePktList, mList)
{
list_del(&pEntry->mList);
free(pEntry);
}
}
return eError;
}
// release buffer manager
static ERRORTYPE Demux_ReleaseBufferMng(DEMUXDATATYPE *pDemuxData)
{
ERRORTYPE eError = SUCCESS;
COMP_PARAM_PORTDEFINITIONTYPE* pPortDef = NULL;
COMP_INTERNAL_TUNNELINFOTYPE* pTunnelInfo = NULL;
COMP_PARAM_BUFFERSUPPLIERTYPE* pBufSupplier = NULL;
BUFFER_MNG* pBufMng = NULL;
// find all ports
int valid_ports[DEMUX_MAX_PORT_COUNT];
int valid_port_num = 0;
if (pDemuxData->video_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->video_port_idx;
valid_port_num++;
}
if (pDemuxData->audio_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->audio_port_idx;
valid_port_num++;
}
if (pDemuxData->subtitle_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->subtitle_port_idx;
valid_port_num++;
}
DMXPKT_NODE_T *pEntry, *pTmp;
for (int i = 0; i < valid_port_num; i++)
{
int port_idx = valid_ports[i];
pPortDef = &pDemuxData->sPortDef[port_idx];
pTunnelInfo = &pDemuxData->sPortTunnelInfo[port_idx];
pBufSupplier = &pDemuxData->sPortBufSupplier[port_idx];
pBufMng = &pDemuxData->mBufferMng[port_idx];
pthread_mutex_lock(&pBufMng->mPktlistMutex);
if (!list_empty(&pBufMng->readyPktList))
{
aloge("fatal error! port_idx = %d, some ready list node is still in use", port_idx);
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->readyPktList, mList)
{
list_del(&pEntry->mList);
if (pEntry->stEncodedStream.pBuffer != NULL)
{
free(pEntry->stEncodedStream.pBuffer);
pEntry->stEncodedStream.pBuffer = NULL;
}
free(pEntry);
}
}
if (!list_empty(&pBufMng->fillingPktList))
{
aloge("fatal error! port_idx = %d, some filling list node is still in use", port_idx);
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->fillingPktList, mList)
{
list_del(&pEntry->mList);
if (pEntry->stEncodedStream.pBuffer != NULL && !pDemuxData->mOutputPortTunnelFlag)
{
free(pEntry->stEncodedStream.pBuffer);
pEntry->stEncodedStream.pBuffer = NULL;
}
free(pEntry);
}
}
if (!list_empty(&pBufMng->usingPktList))
{
aloge("fatal error! port_idx = %d, some using list node is still in use", port_idx);
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->usingPktList, mList)
{
list_del(&pEntry->mList);
if (pEntry->stEncodedStream.pBuffer != NULL)
{
free(pEntry->stEncodedStream.pBuffer);
pEntry->stEncodedStream.pBuffer = NULL;
}
free(pEntry);
}
}
if (!list_empty(&pBufMng->idlePktList))
{
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->idlePktList, mList)
{
list_del(&pEntry->mList);
if (pEntry->stEncodedStream.pBuffer != NULL)
{
free(pEntry->stEncodedStream.pBuffer);
pEntry->stEncodedStream.pBuffer = NULL;
}
free(pEntry);
}
}
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
pthread_mutex_destroy(&pBufMng->mPktlistMutex);
pthread_cond_destroy(&pBufMng->mWaitIdleCondition);
pthread_cond_destroy(&pBufMng->mWaitReadyCondition);
}
return SUCCESS;
}
// check filling buffers empty when tunneo mode and input buf supplier
static ERRORTYPE Demux_CheckFillingPktEmpty(DEMUXDATATYPE *pDemuxData)
{
ERRORTYPE ret = SUCCESS;
COMP_PARAM_PORTDEFINITIONTYPE* pPortDef = NULL;
COMP_INTERNAL_TUNNELINFOTYPE* pTunnelInfo = NULL;
COMP_PARAM_BUFFERSUPPLIERTYPE* pBufSupplier = NULL;
BUFFER_MNG* pBufMng = NULL;
// find all ports
int valid_ports[DEMUX_MAX_PORT_COUNT];
int valid_port_num = 0;
if (pDemuxData->video_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->video_port_idx;
valid_port_num++;
}
if (pDemuxData->audio_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->audio_port_idx;
valid_port_num++;
}
if (pDemuxData->subtitle_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->subtitle_port_idx;
valid_port_num++;
}
for (int i = 0; i < valid_port_num; i++)
{
int port_idx = valid_ports[i];
pPortDef = &pDemuxData->sPortDef[port_idx];
pTunnelInfo = &pDemuxData->sPortTunnelInfo[port_idx];
pBufSupplier = &pDemuxData->sPortBufSupplier[port_idx];
pBufMng = &pDemuxData->mBufferMng[port_idx];
if ( pDemuxData->mOutputPortTunnelFlag[port_idx] != TRUE
|| pBufSupplier->eBufferSupplier != COMP_BufferSupplyInput
)
{
continue;
}
// check filling Pkt buffer
pthread_mutex_lock(&pBufMng->mPktlistMutex);
int idleCnt = 0;
struct list_head *pList;
list_for_each(pList, &pBufMng->idlePktList) { idleCnt++; }
int fillingCnt = 0;
list_for_each(pList, &pBufMng->fillingPktList) { fillingCnt++; }
int readyCnt = 0;
list_for_each(pList, &pBufMng->readyPktList) { readyCnt++; }
int usingCnt = 0;
list_for_each(pList, &pBufMng->usingPktList) { usingCnt++; }
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
if (fillingCnt != 0)
{
if (pPortDef->eDomain == COMP_PortDomainAudio)
{
aloge("fatal error! Port[%d]:Audio filling number:[%d]", port_idx, fillingCnt);
}
else if (pPortDef->eDomain == COMP_PortDomainVideo)
{
aloge("fatal error! Port[%d]:Video filling number:[%d]", port_idx, fillingCnt);
}
else if (pPortDef->eDomain == COMP_PortDomainSubtitle)
{
aloge("fatal error! Port[%d]:Subtitle filling number:[%d]", port_idx, fillingCnt);
}
}
}
return SUCCESS;
}
/**
* use in tunnel mode, return all buffers belong to other component.
*/
static ERRORTYPE Demux_ReturnAllBuffer(DEMUXDATATYPE *pDemuxData)
{
ERRORTYPE ret = SUCCESS;
COMP_PARAM_PORTDEFINITIONTYPE* pPortDef = NULL;
COMP_INTERNAL_TUNNELINFOTYPE* pTunnelInfo = NULL;
COMP_PARAM_BUFFERSUPPLIERTYPE* pBufSupplier = NULL;
BUFFER_MNG* pBufMng = NULL;
// find all ports
int valid_ports[DEMUX_MAX_PORT_COUNT];
int valid_port_num = 0;
if (pDemuxData->video_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->video_port_idx;
valid_port_num++;
}
if (pDemuxData->audio_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->audio_port_idx;
valid_port_num++;
}
if (pDemuxData->subtitle_port_idx != -1)
{
valid_ports[valid_port_num] = pDemuxData->subtitle_port_idx;
valid_port_num++;
}
for (int i = 0; i < valid_port_num; i++)
{
int port_idx = valid_ports[i];
pPortDef = &pDemuxData->sPortDef[port_idx];
pTunnelInfo = &pDemuxData->sPortTunnelInfo[port_idx];
pBufSupplier = &pDemuxData->sPortBufSupplier[port_idx];
pBufMng = &pDemuxData->mBufferMng[port_idx];
// Show buffer status
pthread_mutex_lock(&pBufMng->mPktlistMutex);
int idleCnt = 0;
struct list_head *pList;
list_for_each(pList, &pBufMng->idlePktList) { idleCnt++; }
int fillingCnt = 0;
list_for_each(pList, &pBufMng->fillingPktList) { fillingCnt++; }
int readyCnt = 0;
list_for_each(pList, &pBufMng->readyPktList) { readyCnt++; }
int usingCnt = 0;
list_for_each(pList, &pBufMng->usingPktList) { usingCnt++; }
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
alogd(" Port[%d]: OutTunnelFlag[%d], BufSuppier[%d] 1-input 2-output pkt num:[idle-%d][filling-%d][ready-%d][using-%d]\n"
,port_idx
,pDemuxData->mOutputPortTunnelFlag[port_idx]
,pBufSupplier->eBufferSupplier
,idleCnt, fillingCnt, readyCnt, usingCnt
);
if ( pDemuxData->mOutputPortTunnelFlag[port_idx] == TRUE
&& pBufSupplier->eBufferSupplier == COMP_BufferSupplyInput
)
{// return buffer to B comp
while(1)
{
pthread_mutex_lock(&pBufMng->mPktlistMutex);
DMXPKT_NODE_T *pNode = list_first_entry_or_null(&pBufMng->fillingPktList, DMXPKT_NODE_T, mList);
if (NULL == pNode)
{
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
ret = SUCCESS;
break;
}
list_del(&pNode->mList);
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
COMP_BUFFERHEADERTYPE omx_buffer_header;
EncodedStream dmxOutBuf;
dmxOutBuf.media_type = pNode->stEncodedStream.media_type;
dmxOutBuf.nFilledLen = -1;
dmxOutBuf.nTobeFillLen = 0;
dmxOutBuf.pBuffer = pNode->stEncodedStream.pBuffer;
dmxOutBuf.pBufferExtra = pNode->stEncodedStream.pBufferExtra;
omx_buffer_header.pOutputPortPrivate = (void*)&dmxOutBuf;
omx_buffer_header.nInputPortIndex = pTunnelInfo->nTunnelPortIndex;
alogv("curState[0x%x] nFilledLen[%d] nTobeFillLen[%d] pBuffer[%p] pBufferExtra[%p] media_type[%d]",
pDemuxData->state, dmxOutBuf.nFilledLen, dmxOutBuf.nTobeFillLen,
dmxOutBuf.pBuffer, dmxOutBuf.pBufferExtra, dmxOutBuf.media_type);
COMP_EmptyThisBuffer(pTunnelInfo->hTunnel, (void*)&omx_buffer_header);
pthread_mutex_lock(&pBufMng->mPktlistMutex);
memset(&pNode->stEncodedStream, 0, sizeof(EncodedStream));
list_add_tail(&pNode->mList, &pBufMng->idlePktList);
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
}
}
else
{// move pkt to idle list;
DMXPKT_NODE_T *pEntry, *pTmp;
pthread_mutex_lock(&pBufMng->mPktlistMutex);
if (!list_empty(&pBufMng->fillingPktList))
{
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->fillingPktList, mList)
{
list_move_tail(&pEntry->mList, &pBufMng->idlePktList);
}
}
if (!list_empty(&pBufMng->readyPktList))
{
list_for_each_entry_safe(pEntry, pTmp, &pBufMng->readyPktList, mList)
{
list_move_tail(&pEntry->mList, &pBufMng->idlePktList);
}
}
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
}
}
return ret;
}
/*****************************************************************************/
static ERRORTYPE DemuxOpenParserLib(DEMUXDATATYPE *pDemuxData)
{
ERRORTYPE eError = SUCCESS;
pDemuxData->cdx_epdk_dmx = cedarx_demux_create(pDemuxData->mSourceType); //don't need demux_type
CdxDemuxEventCallbackInfo dmxEventCbInfo;
dmxEventCbInfo.mpCbEventHandler = (void*)CB_EventHandler;
dmxEventCbInfo.mpCookie = (void*)pDemuxData;
pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_SET_DEMUX_EVENT_CALLBACK, 0, (void*)&dmxEventCbInfo);
eError = pDemuxData->cdx_epdk_dmx->open(pDemuxData->cdx_epdk_dmx, &pDemuxData->cdx_mediainfo, &pDemuxData->datasrc_desc);
if(eError < 0)
{
aloge("mpp demuxer open error");
//pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf, pDemuxData->pAppData, OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateInvalid, (OMX_PTR)&ret);
//eError = COMP_ErrorUndefined;
}
else
{
clearDataSourceFields(&pDemuxData->datasrc_desc);
close(pDemuxData->mFd);
pDemuxData->mFd = -1;
pDemuxData->demux_type = (int)ParserType2DemuxType(pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_GET_PARSER_TYPE, 0, NULL));
}
return eError;
}
static ERRORTYPE DemuxOpenReopenParserLib(DEMUXDATATYPE *pDemuxData)
{
if (NULL != pDemuxData->cdx_epdk_dmx)
{
pDemuxData->cdx_epdk_dmx->close(pDemuxData->cdx_epdk_dmx);
cedarx_demux_destory(pDemuxData->cdx_epdk_dmx);
clearCdxMediaInfoT(&pDemuxData->cdx_mediainfo, (int)DemuxType2ParserType(pDemuxData->demux_type));
pDemuxData->cdx_epdk_dmx = NULL;
pDemuxData->demux_init_end = 0;
}
if (NULL == pDemuxData->cdx_epdk_dmx && 0 == pDemuxData->cdx_epdk_dmx)
{
if (SUCCESS != DemuxOpenParserLib(pDemuxData))
{
aloge("open next file parser fail!");
return FAILURE;
}
pDemuxData->dmx_eof = 0;
pDemuxData->dmx_eof_send = 0;
pDemuxData->demux_init_end = 1;
}
return SUCCESS;
}
static ERRORTYPE CreateDemuxPorts(PARAM_IN DEMUXDATATYPE *pDemuxData, PARAM_IN CdxMediaInfoT *cdx_mediainfo)
{
pDemuxData->video_port_idx = -1;
pDemuxData->audio_port_idx = -1;
pDemuxData->subtitle_port_idx = -1;
pDemuxData->max_send_packet_time_video = -1;
pDemuxData->max_send_packet_time_audio = -1;
pDemuxData->max_send_packet_time_subtitle = -1;
BOOL audioValid = FALSE;
BOOL videoValid = FALSE;
BOOL subtitleValid = FALSE;
if (cdx_mediainfo->programNum <= 0 || cdx_mediainfo->programIndex < 0 || cdx_mediainfo->programIndex >= cdx_mediainfo->programNum)
{
aloge("fatal error! no program[%d][%d]!", cdx_mediainfo->programNum, cdx_mediainfo->programIndex);
return FAILURE;
}
struct CdxProgramS *pProgram = &cdx_mediainfo->program[cdx_mediainfo->programIndex];
// create audio output port.
if (pProgram->audioNum > 0 && pProgram->audioIndex >= 0 && pProgram->audioIndex < pProgram->audioNum)
{
if (pProgram->audio[pProgram->audioIndex].eCodecFormat > AUDIO_CODEC_FORMAT_UNKNOWN)
{
audioValid = TRUE;
}
}
else
{
alogw("no audio?[%d][%d]", pProgram->audioIndex, pProgram->audioNum);
}
if (audioValid && !(pDemuxData->disable_track & DEMUX_DISABLE_AUDIO_TRACK))
{
int i = 0;
if (pDemuxData->disable_proprity_track)
{
for (i = 0; i < pProgram->audioNum; i++)
{
if ( pProgram->audio[i].eCodecFormat != AUDIO_CODEC_FORMAT_AC3
&& pProgram->audio[i].eCodecFormat != AUDIO_CODEC_FORMAT_DTS
)
{
break;
}
}
if(i >= pProgram->audioNum)
{
alogw("no supported audio track found!");
goto _SKIP_AUDIO_PORT;
}
if (i > 0) //switch to supported track
{
alogw("demuxLib will read all audio stream, so no need to set audio track index to demuxLib now.");
pProgram->audioIndex = i;
}
}
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].bEnabled = TRUE;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDomain = COMP_PortDomainAudio;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDir = COMP_DirOutput;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].format.audio.cMIMEType = "compressed_audio";
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].pVendorInfo = (void*)&pProgram->audio[pProgram->audioIndex];
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].eBufferSupplier = COMP_BufferSupplyInput;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].eTunnelType = TUNNEL_TYPE_COMMON;
pDemuxData->audio_port_idx = pDemuxData->sPortParam.nPorts;
Demux_CreateBufferMng(pDemuxData, pDemuxData->audio_port_idx);
pDemuxData->sPortParam.nPorts++;
}
_SKIP_AUDIO_PORT:
// create video output port.
if (pProgram->videoNum > 0 && pProgram->videoIndex >= 0 && pProgram->videoIndex < pProgram->videoNum)
{
if ( pProgram->video[pProgram->videoIndex].eCodecFormat >= VIDEO_CODEC_FORMAT_MIN
&& pProgram->video[pProgram->videoIndex].eCodecFormat <= VIDEO_CODEC_FORMAT_MAX
)
{
videoValid = TRUE;
}
}
else
{
alogw("no video?[%d][%d]", pProgram->videoIndex, pProgram->videoNum);
}
if (videoValid && !(pDemuxData->disable_track & DEMUX_DISABLE_VIDEO_TRACK))
{
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].bEnabled = TRUE;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDomain = COMP_PortDomainVideo;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDir = COMP_DirOutput;
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].pVendorInfo = (void*)&pProgram->video[pProgram->videoIndex];
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].eBufferSupplier = COMP_BufferSupplyInput;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].eTunnelType = TUNNEL_TYPE_COMMON;
pDemuxData->video_port_idx = pDemuxData->sPortParam.nPorts;
Demux_CreateBufferMng(pDemuxData, pDemuxData->video_port_idx);
pDemuxData->sPortParam.nPorts++;
#if DEBUG_SAVE_VIDEO_STREAM
VideoStreamInfo *pVideoStreamInfo = (void*)&pProgram->video[pProgram->videoIndex];
if(pVideoStreamInfo->nCodecSpecificDataLen > 0)
{
fwrite(pVideoStreamInfo->pCodecSpecificData, 1, pVideoStreamInfo->nCodecSpecificDataLen, fpVideoStream);
}
#endif
}
//* if there is neither video nor audio, cedarx do not support.
if(pDemuxData->sPortParam.nPorts < 1)
//return COMP_ErrorInsufficientResources;
return ERR_DEMUX_NOT_SUPPORT;
//* create embedded subtitle output port.
if (pProgram->subtitleNum > 0 && pProgram->subtitleIndex >= 0 && pProgram->subtitleIndex < pProgram->subtitleNum)
{
if (pProgram->subtitle[pProgram->subtitleIndex].eCodecFormat > SUBTITLE_CODEC_UNKNOWN)
{
subtitleValid = TRUE;
}
}
else
{
alogw("no subtitle?[%d][%d]", pProgram->subtitleIndex, pProgram->subtitleNum);
}
if (subtitleValid && !(pDemuxData->disable_track & DEMUX_DISABLE_SUBTITLE_TRACK))
{
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].bEnabled = TRUE;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDomain = COMP_PortDomainSubtitle;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDir = COMP_DirOutput;
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].pVendorInfo = (void*)&pProgram->subtitle[pProgram->subtitleIndex];
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].eBufferSupplier = COMP_BufferSupplyInput;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].eTunnelType = TUNNEL_TYPE_COMMON;
pDemuxData->subtitle_port_idx = pDemuxData->sPortParam.nPorts;
Demux_CreateBufferMng(pDemuxData, pDemuxData->subtitle_port_idx);
pDemuxData->sPortParam.nPorts++;
}
//* create an input port for getting clock component, the Parser may use this port to get current clock value.
{
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].bEnabled = TRUE;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDomain = COMP_PortDomainOther;
pDemuxData->sPortDef[pDemuxData->sPortParam.nPorts].eDir = COMP_DirInput;
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortExtraDef[pDemuxData->sPortParam.nPorts].pVendorInfo = NULL;
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortBufSupplier[pDemuxData->sPortParam.nPorts].eBufferSupplier = COMP_BufferSupplyOutput;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].nPortIndex = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortTunnelInfo[pDemuxData->sPortParam.nPorts].eTunnelType = TUNNEL_TYPE_CLOCK;
pDemuxData->clock_port_idx = pDemuxData->sPortParam.nPorts;
pDemuxData->sPortParam.nPorts++;
}
return SUCCESS;
}
static ERRORTYPE DemuxSwitchDataSource(PARAM_IN COMP_HANDLETYPE hComponent, DEMUX_CHN_ATTR_S *pChnAttr)
{
ERRORTYPE eError = SUCCESS;
CedarXDataSourceDesc DataSrc;
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (NULL != pDemuxData->cdx_epdk_dmx)
{
pDemuxData->cdx_epdk_dmx->close(pDemuxData->cdx_epdk_dmx);
cedarx_demux_destory(pDemuxData->cdx_epdk_dmx);
clearDataSourceFields(&pDemuxData->datasrc_desc);
clearCdxMediaInfoT(&pDemuxData->cdx_mediainfo, (int)DemuxType2ParserType(pDemuxData->demux_type));
pDemuxData->cdx_epdk_dmx = NULL;
pDemuxData->demux_init_end = 0;
if (pDemuxData->mFd >= 0)
{
close(pDemuxData->mFd);
pDemuxData->mFd = -1;
}
pDemuxData->prefetch_done = 0;
}
if (pChnAttr->mSourceType == SOURCETYPE_FD)
{
if (pChnAttr->mFd > 0) {
pDemuxData->mSourceType = CEDARX_SOURCE_FD;
memset(&DataSrc, 0, sizeof(CedarXDataSourceDesc));
DataSrc.source_type = CEDARX_SOURCE_FD;
DataSrc.ext_fd_desc.fd = pChnAttr->mFd;
pDemuxData->mFd = dup(DataSrc.ext_fd_desc.fd);
DataSrc.ext_fd_desc.fd = pDemuxData->mFd;
AwDemuxerSetDataSource(&pDemuxData->datasrc_desc, &DataSrc);
}
else
{
alogd("Why ChnAttr.mFd is %d!?", pChnAttr->mFd);
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
}
else if (pChnAttr->mSourceType == SOURCETYPE_URL)
{
if (pChnAttr->mSourceUrl)
{
pDemuxData->mSourceType = CEDARX_SOURCE_FILEPATH;
memset(&DataSrc, 0, sizeof(CedarXDataSourceDesc));
DataSrc.source_type = CEDARX_SOURCE_FILEPATH;
DataSrc.source_url = pChnAttr->mSourceUrl;
AwDemuxerSetDataSource(&pDemuxData->datasrc_desc, &DataSrc);
}
else
{
alogd("Why ChnAttr.mSourceUrl is NULL?");
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
}
else
{
aloge("SourceType(%d) NOT support now!", pChnAttr->mSourceType);
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
eError = DemuxOpenReopenParserLib(pDemuxData);
return eError;
}
/*****************************************************************************/
ERRORTYPE DemuxSetCallbacks(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_CALLBACKTYPE* pCallbacks,
PARAM_IN void* pAppData)
{
DEMUXDATATYPE *pDemuxData;
ERRORTYPE eError = SUCCESS;
pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pDemuxData || !pCallbacks || !pAppData)
{
eError = ERR_DEMUX_ILLEGAL_PARAM;
goto COMP_CONF_CMD_FAIL;
}
pDemuxData->pCallbacks = pCallbacks;
pDemuxData->pAppData = pAppData;
COMP_CONF_CMD_FAIL: return eError;
}
/*****************************************************************************/
ERRORTYPE DemuxSendCommand(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_COMMANDTYPE Cmd,
PARAM_IN unsigned int nParam1,
PARAM_IN void* pCmdData)
{
DEMUXDATATYPE *pDemuxData;
CompInternalMsgType eCmd;
ERRORTYPE eError = SUCCESS;
message_t msg;
alogv("DemuxSendCommand: %d", Cmd);
pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pDemuxData)
{
eError = ERR_DEMUX_ILLEGAL_PARAM;
goto COMP_CONF_CMD_FAIL;
}
pthread_mutex_lock(&pDemuxData->mStateLock);
if (pDemuxData->state == COMP_StateInvalid)
{
eError = ERR_DEMUX_SYS_NOTREADY;
pthread_mutex_unlock(&pDemuxData->mStateLock);
goto COMP_CONF_CMD_FAIL;
}
switch (Cmd)
{
case COMP_CommandStateSet:
eCmd = SetState;
break;
case COMP_CommandFlush:
eCmd = Flush;
break;
case COMP_CommandPortDisable:
eCmd = StopPort;
break;
default:
alogw("impossible comp_command[0x%x]", Cmd);
eCmd = -1;
break;
}
msg.command = eCmd;
msg.para0 = nParam1;
put_message(&pDemuxData->cmd_queue, &msg);
pthread_mutex_unlock(&pDemuxData->mStateLock);
COMP_CONF_CMD_FAIL: return eError;
}
static ERRORTYPE DemuxsetDataSource(PARAM_IN COMP_HANDLETYPE hComponent)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
DEMUX_CHN_ATTR_S *pChnAttr = &pDemuxData->mDemuxChnAttr;
CedarXDataSourceDesc DataSrc;
if (pChnAttr->mSourceType == SOURCETYPE_FD)
{
if (pChnAttr->mFd > 0) {
pDemuxData->mSourceType = CEDARX_SOURCE_FD;
memset(&DataSrc, 0, sizeof(CedarXDataSourceDesc));
DataSrc.source_type = CEDARX_SOURCE_FD;
DataSrc.ext_fd_desc.fd = pChnAttr->mFd;
pDemuxData->mFd = dup(DataSrc.ext_fd_desc.fd);
DataSrc.ext_fd_desc.fd = pDemuxData->mFd;
AwDemuxerSetDataSource(&pDemuxData->datasrc_desc, &DataSrc);
}
else
{
alogd("Why ChnAttr.mFd is %d!?", pChnAttr->mFd);
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
}
else if (pChnAttr->mSourceType == SOURCETYPE_URL)
{
if (pChnAttr->mSourceUrl)
{
pDemuxData->mSourceType = CEDARX_SOURCE_FILEPATH;
memset(&DataSrc, 0, sizeof(CedarXDataSourceDesc));
DataSrc.source_type = CEDARX_SOURCE_FILEPATH;
DataSrc.source_url = pChnAttr->mSourceUrl;
AwDemuxerSetDataSource(&pDemuxData->datasrc_desc, &DataSrc);
}
else
{
aloge("fatal error! Why ChnAttr.mSourceUrl is NULL?");
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
}
else
{
aloge("SourceType(%d) NOT support now!", pChnAttr->mSourceType);
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
return eError;
}
//static ERRORTYPE DemuxDisableTrack(
// PARAM_IN COMP_HANDLETYPE hComponent,
// PARAM_IN int nDisableTrack)
//{
// DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
// pDemuxData->disable_track = nDisableTrack;
// return SUCCESS;
//}
//static ERRORTYPE DemuxDisableMediaType(
// PARAM_IN COMP_HANDLETYPE hComponent,
// PARAM_IN int nDisableMediaType)
//{
// DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
// pDemuxData->disable_media_type = nDisableMediaType;
// return SUCCESS;
//}
static ERRORTYPE DemuxPreparePorts(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN void* ptr)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
if(0 == pDemuxData->demux_init_end)
{
if(DemuxOpenParserLib(pDemuxData) != SUCCESS)
{
return COMP_EventError;
}
CreateDemuxPorts(pDemuxData, &pDemuxData->cdx_mediainfo);
pDemuxData->demux_init_end = 1;
}
else
{
alogd("Demux comp already init ports! init_end[%d]", pDemuxData->demux_init_end);
}
return eError;
}
ERRORTYPE DemuxSeekToPosition(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN CedarXSeekPara *pSeekPara)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
if(pDemuxData->prefetch_done == 1)
{
alogd("***************seekTo[%d]ms discard data.", pSeekPara->seek_time);
if(CDX_OK != pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_SKIP_CHUNK_DATA, 0, &pDemuxData->cdx_pkt))
{
pDemuxData->prefetch_done = 0;
return ERR_DEMUX_ILLEGAL_PARAM;
}
}
pDemuxData->prefetch_done = 0;
if(CDX_OK != pDemuxData->cdx_epdk_dmx->seek(pDemuxData->cdx_epdk_dmx, pSeekPara->seek_time/1000, 0))
{
return ERR_DEMUX_ILLEGAL_PARAM;
}
memcpy(&pDemuxData->seek_para, pSeekPara, sizeof(CedarXSeekPara));
pDemuxData->max_send_packet_time_video = -1;
pDemuxData->max_send_packet_time_audio = -1;
pDemuxData->max_send_packet_time_subtitle = -1;
pDemuxData->dmx_eof = 0;
pDemuxData->dmx_seek_flag = 1;
return eError;
}
ERRORTYPE DemuxComponentTunnelRequest(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN unsigned int nPort,
PARAM_IN COMP_HANDLETYPE hTunneledComp,
PARAM_IN unsigned int nTunneledPort,
PARAM_INOUT COMP_TUNNELSETUPTYPE* pTunnelSetup)
{
ERRORTYPE eError = SUCCESS;
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pDemuxData->mStateLock);
if (pDemuxData->state == COMP_StateExecuting)
{
alogw("Be careful! tunnel request may be some danger in StateExecuting");
}
else if(pDemuxData->state != COMP_StateIdle)
{
aloge("fatal error! tunnel request can't be in state[0x%x]", pDemuxData->state);
eError = ERR_DEMUX_NOT_PERM;
goto COMP_CMD_FAIL;
}
COMP_PARAM_PORTDEFINITIONTYPE *pPortDef;
COMP_INTERNAL_TUNNELINFOTYPE *pPortTunnelInfo;
COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier;
BOOL bFindFlag;
int i;
bFindFlag = FALSE;
for(i=0; i<DEMUX_MAX_PORT_COUNT; i++)
{
if(pDemuxData->sPortDef[i].nPortIndex == nPort)
{
pPortDef = &pDemuxData->sPortDef[i];
bFindFlag = TRUE;
break;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%u] wrong!", nPort);
eError = ERR_DEMUX_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
bFindFlag = FALSE;
for(i=0; i<DEMUX_MAX_PORT_COUNT; i++)
{
if(pDemuxData->sPortTunnelInfo[i].nPortIndex == nPort)
{
pPortTunnelInfo = &pDemuxData->sPortTunnelInfo[i];
bFindFlag = TRUE;
break;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%u] wrong!", nPort);
eError = ERR_DEMUX_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
bFindFlag = FALSE;
for(i=0; i<DEMUX_MAX_PORT_COUNT; i++)
{
if(pDemuxData->sPortBufSupplier[i].nPortIndex == nPort)
{
pPortBufSupplier = &pDemuxData->sPortBufSupplier[i];
bFindFlag = TRUE;
break;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%d] wrong!", nPort);
eError = ERR_DEMUX_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
pPortTunnelInfo->nPortIndex = nPort;
pPortTunnelInfo->hTunnel = hTunneledComp;
pPortTunnelInfo->nTunnelPortIndex = nTunneledPort;
pPortTunnelInfo->eTunnelType = (pPortDef->eDomain == COMP_PortDomainOther) ? TUNNEL_TYPE_CLOCK : TUNNEL_TYPE_COMMON;
if(NULL==hTunneledComp && 0==nTunneledPort && NULL==pTunnelSetup)
{
alogd("omx_core cancel setup tunnel on port[%d]", nPort);
eError = SUCCESS;
if(pPortDef->eDir == COMP_DirOutput)
{
pDemuxData->mOutputPortTunnelFlag[nPort] = FALSE;
}
else
{
pDemuxData->mInputPortTunnelFlag = FALSE;
}
goto COMP_CMD_FAIL;
}
if(pPortDef->eDir == COMP_DirOutput)
{
pTunnelSetup->nTunnelFlags = 0;
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
pDemuxData->mOutputPortTunnelFlag[nPort] = TRUE;
}
else
{
if (pDemuxData->mInputPortTunnelFlag) {
aloge("Dmx_Comp inport already bind, why bind again?!");
eError = FAILURE;
goto COMP_CMD_FAIL;
}
//Check the data compatibility between the ports using one or more GetParameter calls.
//B checks if its input port is compatible with the output port of component A.
COMP_PARAM_PORTDEFINITIONTYPE out_port_def;
out_port_def.nPortIndex = nTunneledPort;
((MM_COMPONENTTYPE*)hTunneledComp)->GetConfig(hTunneledComp, COMP_IndexParamPortDefinition, &out_port_def);
if(out_port_def.eDir != COMP_DirOutput)
{
aloge("fatal error! tunnel port index[%d] direction is not output!", nTunneledPort);
eError = ERR_DEMUX_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
pPortDef->format = out_port_def.format;
//The component B informs component A about the final result of negotiation.
if(pTunnelSetup->eSupplier != pPortBufSupplier->eBufferSupplier)
{
alogw("Low probability! use input portIndex[%d] buffer supplier[%d] as final!", nPort, pPortBufSupplier->eBufferSupplier);
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
}
COMP_PARAM_BUFFERSUPPLIERTYPE oSupplier;
oSupplier.nPortIndex = nTunneledPort;
((MM_COMPONENTTYPE*)hTunneledComp)->GetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
oSupplier.eBufferSupplier = pTunnelSetup->eSupplier;
((MM_COMPONENTTYPE*)hTunneledComp)->SetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
pDemuxData->mInputPortTunnelFlag = TRUE;
}
COMP_CMD_FAIL:
pthread_mutex_unlock(&pDemuxData->mStateLock);
return eError;
}
/*****************************************************************************/
ERRORTYPE DemuxGetState(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT COMP_STATETYPE* pState)
{
ERRORTYPE eError = SUCCESS;
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pDemuxData->mStateLock);
*pState = pDemuxData->state;
pthread_mutex_unlock(&pDemuxData->mStateLock);
return eError;
}
ERRORTYPE DemuxGetPortParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT COMP_PORT_PARAM_TYPE *pPortParam)
{
ERRORTYPE eError = SUCCESS;
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
memcpy(pPortParam, &pDemuxData->sPortParam, sizeof(COMP_PORT_PARAM_TYPE));
return SUCCESS;
}
ERRORTYPE DemuxGetPortDefinition(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_PARAM_PORTDEFINITIONTYPE *pPortDef)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i;
for(i=0; i<DEMUX_MAX_PORT_COUNT; i++)
{
if(pDemuxData->sPortDef[i].nPortIndex == pPortDef->nPortIndex)
{
bFindFlag = TRUE;
memcpy(pPortDef, &pDemuxData->sPortDef[i], sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE DemuxSetPortDefinition(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_PARAM_PORTDEFINITIONTYPE *pPortDef)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i;
for(i=0; i<DEMUX_MAX_PORT_COUNT; i++)
{
if(pDemuxData->sPortDef[i].nPortIndex == pPortDef->nPortIndex)
{
bFindFlag = TRUE;
memcpy(&pDemuxData->sPortDef[i], pPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE DemuxGetCompBufferSupplier(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i;
for(i=0; i<DEMUX_MAX_PORT_COUNT; i++)
{
if(pDemuxData->sPortBufSupplier[i].nPortIndex == pPortBufSupplier->nPortIndex)
{
bFindFlag = TRUE;
memcpy(pPortBufSupplier, &pDemuxData->sPortBufSupplier[i], sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE DemuxSetCompBufferSupplier(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i;
for(i=0; i<DEMUX_MAX_PORT_COUNT; i++)
{
if(pDemuxData->sPortBufSupplier[i].nPortIndex == pPortBufSupplier->nPortIndex)
{
bFindFlag = TRUE;
memcpy(&pDemuxData->sPortBufSupplier[i], pPortBufSupplier, sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE DemuxSetMPPChannelInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN MPP_CHN_S *pChn)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
copy_MPP_CHN_S(&pDemuxData->mMppChnInfo, pChn);
return SUCCESS;
}
ERRORTYPE DemuxGetMPPChannelInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT MPP_CHN_S *pChn)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
copy_MPP_CHN_S(pChn, &pDemuxData->mMppChnInfo);
return SUCCESS;
}
ERRORTYPE DemuxSetChnAttr(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN DEMUX_CHN_ATTR_S *pChnAttr)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pDemuxData->mDemuxChnAttr = *pChnAttr;
pDemuxData->disable_track = pChnAttr->mDemuxDisableTrack;
return SUCCESS;
}
ERRORTYPE DemuxGetChnAttr(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT DEMUX_CHN_ATTR_S *pChnAttr)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pChnAttr = pDemuxData->mDemuxChnAttr;
return SUCCESS;
}
static ERRORTYPE DemuxGetDemuxType(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT int *pDemuxType)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pDemuxType = pDemuxData->demux_type;
return SUCCESS;
}
static ERRORTYPE DemuxGetMediaInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT CdxMediaInfoT *pMediaInfoT)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pDemuxData->cdx_mediainfo.program[0].videoIndex = pDemuxData->mCurVideoStreamIndex;
pDemuxData->cdx_mediainfo.program[0].audioIndex = pDemuxData->mCurAudioStreamIndex;
pDemuxData->cdx_mediainfo.program[0].subtitleIndex = pDemuxData->mCurSubtitleStreamIndex;
memcpy(pMediaInfoT, &pDemuxData->cdx_mediainfo, sizeof(CdxMediaInfoT));
return SUCCESS;
}
static ERRORTYPE DemuxGetMediaType(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT int *pMediaType)
{
//DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pMediaType = CEDARX_MEDIATYPE_NORMAL;
return SUCCESS;
}
static ERRORTYPE DemuxGetPortExtraDef(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT COMP_PARAM_PORTEXTRADEFINITIONTYPE *pPortDef)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int portIdx = pPortDef->nPortIndex;
if (portIdx < pDemuxData->sPortParam.nPorts)
{
memcpy(pPortDef, &pDemuxData->sPortExtraDef[portIdx], sizeof(COMP_PARAM_PORTEXTRADEFINITIONTYPE));
return TRUE;
}
else
{
return FAILURE;
}
}
static ERRORTYPE DemuxGetOutputBuffer(PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT EncodedStream *pDmxOutBuf,
PARAM_IN int nMilliSec)
{
ERRORTYPE eError;
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pDmxOutBuf == NULL)
{
aloge("error input func param");
return ERR_DEMUX_ILLEGAL_PARAM;
}
pthread_mutex_lock(&pDemuxData->mStateLock);
if (pDemuxData->dmx_eof)
{
pthread_mutex_unlock(&pDemuxData->mStateLock);
return DBG_DEMUX_FILE_PARSER_COMPLETE;
}
if(COMP_StateIdle != pDemuxData->state && COMP_StateExecuting != pDemuxData->state)
{
alogw("call getbuf in wrong state[0x%x]", pDemuxData->state);
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_NOT_PERM;
}
if ( pDemuxData->mOutputPortTunnelFlag[pDemuxData->audio_port_idx]
&& pDemuxData->mOutputPortTunnelFlag[pDemuxData->video_port_idx]
)
{
aloge("fatal error! can't call getoutbuf in tunnel mode!");
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_NOT_PERM;
}
int port_idx = -1;
//int audio_pkt_cnt = 0;
//int video_pkt_cnt = 0;
//int subtitle_pkt_cnt = 0;
DMXPKT_NODE_T *pEntry = NULL;
int64_t nMinPts = -1;
BUFFER_MNG* pBufferMng = NULL;
if ( pDemuxData->sPortDef[pDemuxData->audio_port_idx].bEnabled == TRUE
&& !pDemuxData->mOutputPortTunnelFlag[pDemuxData->audio_port_idx]
)
{
pBufferMng = &pDemuxData->mBufferMng[pDemuxData->audio_port_idx];
//struct list_head *pList;
//list_for_each(pList, &pBufferMng->readyPktList) { audio_pkt_cnt++; }
if(!list_empty(&pBufferMng->readyPktList))
{
pEntry = list_first_entry(&pBufferMng->readyPktList, DMXPKT_NODE_T, mList);
nMinPts = pEntry->stEncodedStream.nTimeStamp;
}
port_idx = pDemuxData->audio_port_idx;
}
if ( pDemuxData->sPortDef[pDemuxData->video_port_idx].bEnabled == TRUE
&& !pDemuxData->mOutputPortTunnelFlag[pDemuxData->video_port_idx]
)
{
pBufferMng = &pDemuxData->mBufferMng[pDemuxData->video_port_idx];
// struct list_head *pList;
// list_for_each(pList, &pBufferMng->readyPktList) { video_pkt_cnt++; }
// if (video_pkt_cnt > audio_pkt_cnt)
// {
// port_idx = pDemuxData->video_port_idx;
// }
if(!list_empty(&pBufferMng->readyPktList))
{
pEntry = list_first_entry(&pBufferMng->readyPktList, DMXPKT_NODE_T, mList);
if((-1==nMinPts) || (pEntry->stEncodedStream.nTimeStamp < nMinPts))
{
nMinPts = pEntry->stEncodedStream.nTimeStamp;
port_idx = pDemuxData->video_port_idx;
}
}
if(-1 == port_idx)
{
port_idx = pDemuxData->video_port_idx;
}
}
if ( pDemuxData->sPortDef[pDemuxData->subtitle_port_idx].bEnabled == TRUE
&& !pDemuxData->mOutputPortTunnelFlag[pDemuxData->subtitle_port_idx]
)
{
pBufferMng = &pDemuxData->mBufferMng[pDemuxData->subtitle_port_idx];
// struct list_head *pList;
// list_for_each(pList, &pBufferMng->readyPktList) { subtitle_pkt_cnt++; }
// if (subtitle_pkt_cnt > video_pkt_cnt && subtitle_pkt_cnt > audio_pkt_cnt)
// {
// port_idx = pDemuxData->subtitle_port_idx;
// }
if(!list_empty(&pBufferMng->readyPktList))
{
pEntry = list_first_entry(&pBufferMng->readyPktList, DMXPKT_NODE_T, mList);
if((-1==nMinPts) || (pEntry->stEncodedStream.nTimeStamp < nMinPts))
{
nMinPts = pEntry->stEncodedStream.nTimeStamp;
port_idx = pDemuxData->subtitle_port_idx;
}
}
if(-1 == port_idx)
{
port_idx = pDemuxData->subtitle_port_idx;
}
}
if (port_idx == -1)
{
aloge("fatal error! can't find port!");
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_NOT_PERM;
}
pBufferMng = &pDemuxData->mBufferMng[port_idx];
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
_TryToGetOutBuf:
if(!list_empty(&pBufferMng->readyPktList))
{
DMXPKT_NODE_T *pPktOut = list_first_entry(&pBufferMng->readyPktList, DMXPKT_NODE_T, mList);
memcpy(pDmxOutBuf, &pPktOut->stEncodedStream, sizeof(EncodedStream));
list_move_tail(&pPktOut->mList, &pBufferMng->usingPktList);
eError = SUCCESS;
}
else
{
if(0 == nMilliSec)
{
eError = ERR_DEMUX_NOBUF;
}
else if(nMilliSec < 0)
{
pBufferMng->mWaitReadyPktFlag = TRUE;
while(list_empty(&pBufferMng->readyPktList))
{
pthread_cond_wait(&pBufferMng->mWaitReadyCondition, &pBufferMng->mPktlistMutex);
}
pBufferMng->mWaitReadyPktFlag = FALSE;
goto _TryToGetOutBuf;
}
else
{
pBufferMng->mWaitReadyPktFlag = TRUE;
eError = pthread_cond_wait_timeout(&pBufferMng->mWaitReadyCondition, &pBufferMng->mPktlistMutex, nMilliSec);
if(ETIMEDOUT == eError)
{
alogv("wait output dmxpkt timeout[%d]ms, ret[%d]", nMilliSec, eError);
eError = ERR_DEMUX_NOBUF;
pBufferMng->mWaitReadyPktFlag = FALSE;
}
else if(0 == eError)
{
pBufferMng->mWaitReadyPktFlag = FALSE;
goto _TryToGetOutBuf;
}
else
{
aloge("fatal error! pthread cond wait timeout ret[%d]", eError);
eError = ERR_DEMUX_NOBUF;
pBufferMng->mWaitReadyPktFlag = FALSE;
}
}
}
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
pthread_mutex_unlock(&pDemuxData->mStateLock);
return eError;
}
static ERRORTYPE DemuxReleaseOutputBuffer(PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT EncodedStream *pDmxOutBuf)
{
ERRORTYPE eError;
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pDmxOutBuf == NULL)
{
aloge("error input func param");
return ERR_DEMUX_ILLEGAL_PARAM;
}
// Get port properties
int port_idx = -1;
if (CDX_PacketVideo == pDmxOutBuf->media_type)
port_idx = pDemuxData->video_port_idx;
else if (CDX_PacketAudio == pDmxOutBuf->media_type)
port_idx = pDemuxData->audio_port_idx;
else if (CDX_PacketSubtitle == pDmxOutBuf->media_type)
port_idx = pDemuxData->subtitle_port_idx;
else
{
aloge("fatal error! unknown media_type[%d]", pDmxOutBuf->media_type);
return ERR_DEMUX_ILLEGAL_PARAM;
}
COMP_PARAM_PORTDEFINITIONTYPE* pPortDef = &pDemuxData->sPortDef[port_idx];
COMP_INTERNAL_TUNNELINFOTYPE* pTunnelInfo = &pDemuxData->sPortTunnelInfo[port_idx];
COMP_PARAM_BUFFERSUPPLIERTYPE* pBufSupplier = &pDemuxData->sPortBufSupplier[port_idx];
BUFFER_MNG* pBufMng = &pDemuxData->mBufferMng[port_idx];
pthread_mutex_lock(&pDemuxData->mStateLock);
if (COMP_StateIdle != pDemuxData->state && COMP_StateExecuting != pDemuxData->state)
{
alogw("call release buf in wrong state[0x%x]", pDemuxData->state);
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_NOT_PERM;
}
if (pDemuxData->mOutputPortTunnelFlag[port_idx])
{
aloge("fatal error! can't call release buf() in tunnel mode!");
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_NOT_PERM;
}
pthread_mutex_lock(&pBufMng->mPktlistMutex);
if (!list_empty(&pBufMng->usingPktList))
{
DMXPKT_NODE_T *pPktOut = list_first_entry(&pBufMng->usingPktList, DMXPKT_NODE_T, mList);
if (pPktOut->stEncodedStream.pBuffer == pDmxOutBuf->pBuffer && pPktOut->stEncodedStream.nBufferLen == pDmxOutBuf->nBufferLen)
{
list_move_tail(&pPktOut->mList, &pBufMng->idlePktList);
if (pBufMng->mWaitIdlePktFlag)
{
pthread_cond_signal(&pBufMng->mWaitIdleCondition);
}
eError = SUCCESS;
}
else
{
aloge("fatal error! release buf[%p][%p] is not match usingPktList first entry[%p][%p]",
pPktOut->stEncodedStream.pBuffer, pPktOut->stEncodedStream.pBufferExtra,
pDmxOutBuf->pBuffer, pDmxOutBuf->pBufferExtra);
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
}
else
{
alogw("Be careful! buf not find, maybe reset channel before call this function?");
eError = ERR_DEMUX_ILLEGAL_PARAM;
}
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
pthread_mutex_unlock(&pDemuxData->mStateLock);
return eError;
}
/*
// demux not need it?
ERRORTYPE DemuxGetChannelFd(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT int *pChnFd)
{
DEMUXDATATYPE *pDemuxEncData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pChnFd = pDemuxEncData->mOutputFrameNotifyPipeFds[0];
return SUCCESS;
}
*/
ERRORTYPE DemuxGetTunnelInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_INTERNAL_TUNNELINFOTYPE *pTunnelInfo)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError;
int portIdx = pTunnelInfo->nPortIndex;
if (portIdx < pDemuxData->sPortParam.nPorts)
{
memcpy(pTunnelInfo, &pDemuxData->sPortTunnelInfo[portIdx], sizeof(COMP_INTERNAL_TUNNELINFOTYPE));
eError = TRUE;
}
else
{
eError = ERR_DEMUX_UNEXIST;
}
return eError;
}
static ERRORTYPE DemuxSelectVideoStream(
PARAM_IN COMP_HANDLETYPE hCOmponent,
PARAM_IN int nVideoIndex)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hCOmponent)->pComponentPrivate);
ERRORTYPE eError;
if (nVideoIndex > 0
&& nVideoIndex < pDemuxData->cdx_mediainfo.program[pDemuxData->cdx_mediainfo.programIndex].videoNum
&& nVideoIndex < VIDEO_STREAM_LIMIT)
{
pDemuxData->mCurVideoStreamIndex = nVideoIndex;
//update video vencdor info
for (int i = 0; i < DEMUX_MAX_PORT_COUNT; i++)
{
if (COMP_PortDomainVideo == pDemuxData->sPortDef[i].eDomain)
{
pDemuxData->sPortExtraDef[i].pVendorInfo =
&pDemuxData->cdx_mediainfo.program[pDemuxData->cdx_mediainfo.programIndex].video[nVideoIndex];
eError = SUCCESS;
break;
}
}
pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_SWITCH_VIDEO, 0, (void*)&pDemuxData->mCurVideoStreamIndex);
}
else
{
alogw("use default video stream track[%d]", pDemuxData->mCurVideoStreamIndex);
}
return eError;
}
static ERRORTYPE DemuxSelectAudioStream(
PARAM_IN COMP_HANDLETYPE hCOmponent,
PARAM_IN int nAudioIndex)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hCOmponent)->pComponentPrivate);
ERRORTYPE eError;
if (nAudioIndex > 0 &&
nAudioIndex < pDemuxData->cdx_mediainfo.program[pDemuxData->cdx_mediainfo.programIndex].audioNum)
{
for (int i = 0; i < DEMUX_MAX_PORT_COUNT; i++)
{
pDemuxData->mCurAudioStreamIndex = nAudioIndex;
//update audio Vendor info
if (COMP_PortDomainAudio == pDemuxData->sPortDef[i].eDomain)
{
pDemuxData->sPortExtraDef[i].pVendorInfo =
&pDemuxData->cdx_mediainfo.program[pDemuxData->cdx_mediainfo.programIndex].audio[nAudioIndex];
eError = SUCCESS;
break;
}
}
}
else
{
alogw("use default audio stream track[%d]", pDemuxData->mCurAudioStreamIndex);
}
return eError;
}
static ERRORTYPE DemuxSelectSubtitleStream(
PARAM_IN COMP_HANDLETYPE hCOmponent,
PARAM_IN int nSubtitleIndex)
{
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hCOmponent)->pComponentPrivate);
ERRORTYPE eError;
if (nSubtitleIndex > 0 &&
nSubtitleIndex < pDemuxData->cdx_mediainfo.program[pDemuxData->cdx_mediainfo.programIndex].subtitleNum)
{
for (int i = 0; i < DEMUX_MAX_PORT_COUNT; i++)
{
pDemuxData->mCurSubtitleStreamIndex = nSubtitleIndex;
//update subtitle Vendor info
if (COMP_PortDomainSubtitle == pDemuxData->sPortDef[i].eDomain)
{
pDemuxData->sPortExtraDef[i].pVendorInfo =
&pDemuxData->cdx_mediainfo.program[pDemuxData->cdx_mediainfo.programIndex].subtitle[nSubtitleIndex];
eError = SUCCESS;
break;
}
}
}
else
{
alogw("use default subtitle stream track[%d]", pDemuxData->mCurAudioStreamIndex);
}
return eError;
}
/*****************************************************************************/
ERRORTYPE DemuxGetConfig(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_INDEXTYPE nIndex,
PARAM_IN void* pComponentConfigStructure)
{
ERRORTYPE eError = SUCCESS;
switch(nIndex)
{
case COMP_IndexVendorGetPortParam:
{
eError = DemuxGetPortParam(hComponent, (COMP_PORT_PARAM_TYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexParamPortDefinition:
{
eError = DemuxGetPortDefinition(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexParamCompBufferSupplier:
{
eError = DemuxGetCompBufferSupplier(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelInfo:
{
eError = DemuxGetMPPChannelInfo(hComponent, (MPP_CHN_S*)pComponentConfigStructure);
break;
}
#if 0
case COMP_IndexVendorMPPChannelFd:
{
eError = DemuxGetChannelFd(hComponent, (int*)pComponentConfigStructure);
break;
}
#endif
case COMP_IndexVendorTunnelInfo:
{
eError = DemuxGetTunnelInfo(hComponent, (COMP_INTERNAL_TUNNELINFOTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxChnAttr:
{
eError = DemuxGetChnAttr(hComponent, (DEMUX_CHN_ATTR_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxChnPriority:
{
alogw("unsupported temporary get demux chn priority!");
eError = ERR_DEMUX_NOT_SUPPORT;
break;
}
case COMP_IndexVendorDemuxType:
{
eError = DemuxGetDemuxType(hComponent, (int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxMediaInfo:
{
eError = DemuxGetMediaInfo(hComponent, (CdxMediaInfoT*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxMediaType:
{
eError = DemuxGetMediaType(hComponent, (int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorParamPortExtraDefinition:
{
eError = DemuxGetPortExtraDef(hComponent, (COMP_PARAM_PORTEXTRADEFINITIONTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxOutBuffer:
{
DemuxStream *pStream = (DemuxStream *)pComponentConfigStructure;
eError = DemuxGetOutputBuffer(hComponent, pStream->pEncodedStream, pStream->nMilliSec);
break;
}
default:
{
aloge("fatal error! unknown getConfig Index[0x%x]", nIndex);
eError = ERR_DEMUX_ILLEGAL_PARAM;
break;
}
}
return eError;
}
/*****************************************************************************/
ERRORTYPE DemuxSetConfig(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_INDEXTYPE nIndex,
PARAM_IN void* pComponentConfigStructure)
{
ERRORTYPE eError = SUCCESS;
switch (nIndex)
{
case COMP_IndexParamPortDefinition:
{
eError = DemuxSetPortDefinition(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexParamCompBufferSupplier:
{
eError = DemuxSetCompBufferSupplier(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelInfo:
{
eError = DemuxSetMPPChannelInfo(hComponent, (MPP_CHN_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxChnAttr:
{
eError = DemuxSetChnAttr(hComponent, (DEMUX_CHN_ATTR_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxChnPriority:
{
alogw("not impl SetChnPriority!");
eError = ERR_DEMUX_NOT_SUPPORT;
break;
}
//case COMP_IndexVendorDemuxResetChannel:
//{
// alogw("not impl ResetChannel!");
// //eError = DemuxResetChannel(hComponent);
// eError = ERR_DEMUX_NOT_SUPPORT;
// break;
//}
case COMP_IndexVendorDemuxSetDataSource:
{
eError = DemuxsetDataSource(hComponent);
break;
}
//case COMP_IndexVendorDemuxDisableTrack:
//{
// eError = DemuxDisableTrack(hComponent, *(int*)pComponentConfigStructure);
// break;
//}
//case COMP_IndexVendorDemuxDisableMediaType:
//{
// eError = DemuxDisableMediaType(hComponent, *(int*)pComponentConfigStructure);
// break;
//}
//case COMP_IndexVendorDemuxDisableProprityTrack:
//{
// aloge("not impl DisableProrityTrack!");
// eError = ERR_DEMUX_NOT_SUPPORT;
// break;
//}
case COMP_IndexVendorDemuxPreparePorts:
{
eError = DemuxPreparePorts(hComponent, pComponentConfigStructure);
break;
}
case COMP_IndexVendorSeekToPosition:
{
eError = DemuxSeekToPosition(hComponent, (CedarXSeekPara*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxOutBuffer:
{
eError = DemuxReleaseOutputBuffer(hComponent, (EncodedStream*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorSwitchVideo:
{
eError = DemuxSelectVideoStream(hComponent, *(int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorSwitchAudio:
{
eError = DemuxSelectAudioStream(hComponent, *(int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorSwitchSubtitle:
{
eError = DemuxSelectSubtitleStream(hComponent, *(int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorDemuxSwitchDateSource:
{
eError = DemuxSwitchDataSource(hComponent, (DEMUX_CHN_ATTR_S *)pComponentConfigStructure);
break;
}
default:
{
aloge("unknown Index[0x%x]", nIndex);
eError = ERR_DEMUX_ILLEGAL_PARAM;
break;
}
}
return eError;
}
/*****************************************************************************/
ERRORTYPE DemuxComponentDeInit(PARAM_IN COMP_HANDLETYPE hComponent)
{
DEMUXDATATYPE *pDemuxData;
ERRORTYPE eError;
CompInternalMsgType eCmd;
message_t msg;
pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
eError = SUCCESS;
eCmd = Stop;
msg.command = eCmd;
put_message(&pDemuxData->cmd_queue, &msg);
alogd("wait demux component exit!...");
// Wait for thread to exit
pthread_join(pDemuxData->thread_id, (void*) &eError);
if(pDemuxData->cdx_epdk_dmx != NULL)
{
pDemuxData->cdx_epdk_dmx->close(pDemuxData->cdx_epdk_dmx);
cedarx_demux_destory(pDemuxData->cdx_epdk_dmx);
}
message_destroy(&pDemuxData->cmd_queue);
clearDataSourceFields(&pDemuxData->datasrc_desc);
clearCdxMediaInfoT(&pDemuxData->cdx_mediainfo, (int)DemuxType2ParserType(pDemuxData->demux_type));
pthread_mutex_destroy(&pDemuxData->mStateLock);
if(pDemuxData->mFd >= 0)
{
if(0 == pDemuxData->mFd)
{
alogw("Be careful! fd==0!");
}
close(pDemuxData->mFd);
pDemuxData->mFd = -1;
}
Demux_ReleaseBufferMng(pDemuxData);
#if DEBUG_SAVE_VIDEO_STREAM
if(fpVideoStream)
{
fclose(fpVideoStream);
fpVideoStream = NULL;
}
#endif
if(pDemuxData)
{
free(pDemuxData);
}
alogd("demux component exited!");
return eError;
}
/*****************************************************************************/
ERRORTYPE DemuxComponentInit(PARAM_IN COMP_HANDLETYPE hComponent)
{
MM_COMPONENTTYPE* pComp;
DEMUXDATATYPE* pDemuxData;
ERRORTYPE eError;
int err;
eError = SUCCESS;
pComp = (MM_COMPONENTTYPE *)hComponent;
// Create private data
pDemuxData = (DEMUXDATATYPE *)malloc(sizeof(DEMUXDATATYPE));
if (NULL == pDemuxData)
{
return FAILURE;
}
memset(pDemuxData, 0x0, sizeof(DEMUXDATATYPE));
pComp->pComponentPrivate = (void*) pDemuxData;
pDemuxData->state = COMP_StateLoaded;
pthread_mutex_init(&pDemuxData->mStateLock, NULL);
pDemuxData->hSelf = hComponent;
pDemuxData->mFd = -1;
// Fill in function pointers
pComp->SetCallbacks = DemuxSetCallbacks;
pComp->SendCommand = DemuxSendCommand;
pComp->GetState = DemuxGetState;
pComp->GetConfig = DemuxGetConfig;
pComp->SetConfig = DemuxSetConfig;
pComp->ComponentTunnelRequest = DemuxComponentTunnelRequest;
pComp->ComponentDeInit = DemuxComponentDeInit;
pComp->FillThisBuffer = DemuxFillThisBuffer;
pComp->EmptyThisBuffer = DemuxEmptyThisBuffer;
// Initialize component data structures to default values
pDemuxData->sPortParam.nPorts = 0; //no ports currently
pDemuxData->sPortParam.nStartPortNumber = 0x0;
/* To initialize some info that indicating the attribute of stream to
fix bug that system crash when to play file that created by app but terminated by kill cmd.
pls chk the beggining point of function Demux_ReleaseBufferMng(),where the variable valid_port_num
will get incorrect value,because of the initialization of variable showing below.*/
pDemuxData->video_port_idx = -1;
pDemuxData->audio_port_idx = -1;
pDemuxData->subtitle_port_idx = -1;
pDemuxData->max_send_packet_time_video = -1;
pDemuxData->max_send_packet_time_audio = -1;
pDemuxData->max_send_packet_time_subtitle = -1;
if(message_create(&pDemuxData->cmd_queue)<0)
{
aloge("message error!");
eError = ERR_DEMUX_NOMEM;
goto err_out1;
}
// Create the component thread
err = pthread_create(&pDemuxData->thread_id, NULL, ComponentThread, pDemuxData);
if (err || !pDemuxData->thread_id)
{
eError = ERR_DEMUX_NOMEM;
goto err_out2;
}
#if DEBUG_SAVE_VIDEO_STREAM
fpVideoStream = fopen(fpVideoStreamPath, "wb");
if(NULL == fpVideoStream)
{
aloge("fatal error! fopen[%s] fail", fpVideoStreamPath);
}
#endif
EXIT:
return eError;
err_out2:
message_destroy(&pDemuxData->cmd_queue);
err_out1:
pthread_mutex_destroy(&pDemuxData->mStateLock);
free(pDemuxData);
return FAILURE;
}
ERRORTYPE DemuxEmptyThisBuffer(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_BUFFERHEADERTYPE *pBuffer)
{
ERRORTYPE eError = SUCCESS;
alogd("fatal error! DemuxEmptyThisBuffer.");
return eError;
}
ERRORTYPE DemuxFillThisBuffer(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_BUFFERHEADERTYPE *pBuffer)
{
ERRORTYPE eError = SUCCESS;
// Get component private data
DEMUXDATATYPE *pDemuxData = (DEMUXDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
EncodedStream stEncodedStream = *(EncodedStream*)pBuffer->pOutputPortPrivate;
if (NULL == stEncodedStream.pBuffer)
{
aloge("fatal error! call FillThisBuffer using the buffer is NULL!");
return ERR_DEMUX_NOBUF;
}
// Get port properties
int port_idx = -1;
if (CDX_PacketVideo == stEncodedStream.media_type)
port_idx = pDemuxData->video_port_idx;
else if (CDX_PacketAudio == stEncodedStream.media_type)
port_idx = pDemuxData->audio_port_idx;
else if (CDX_PacketSubtitle == stEncodedStream.media_type)
port_idx = pDemuxData->subtitle_port_idx;
else
{
aloge("fatal error! unknown media_type[%d]", stEncodedStream.media_type);
return ERR_DEMUX_ILLEGAL_PARAM;
}
COMP_PARAM_PORTDEFINITIONTYPE* pPortDef = &pDemuxData->sPortDef[port_idx];
COMP_INTERNAL_TUNNELINFOTYPE* pTunnelInfo = &pDemuxData->sPortTunnelInfo[port_idx];
COMP_PARAM_BUFFERSUPPLIERTYPE* pBufSupplier = &pDemuxData->sPortBufSupplier[port_idx];
BUFFER_MNG* pBufMng = &pDemuxData->mBufferMng[port_idx];
pthread_mutex_lock(&pDemuxData->mStateLock);
// Check state
if (pDemuxData->state != COMP_StateExecuting)
{
alogw("Be careful! Call DemuxFillThisBuffer in state[0x%x]!", pDemuxData->state);
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_NOT_PERM;
}
// Ensure it is outport tunnel mode
if (!pDemuxData->mOutputPortTunnelFlag[port_idx])
{
aloge("fatal error! can't call DemuxFillThisBuffer in non-tunnel mode!");
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_NOT_SUPPORT;
}
if (pBufSupplier->eBufferSupplier == COMP_BufferSupplyOutput)
{
pthread_mutex_lock(&pBufMng->mPktlistMutex);
if (!list_empty(&pBufMng->usingPktList))
{
BOOL bFindFlag = FALSE;
DMXPKT_NODE_T *pEntry;
list_for_each_entry(pEntry, &pBufMng->usingPktList, mList)
{
if( pEntry->stEncodedStream.nID == stEncodedStream.nID
&& pEntry->stEncodedStream.pBuffer == stEncodedStream.pBuffer
&& pEntry->stEncodedStream.nBufferLen == stEncodedStream.nBufferLen
)
{
bFindFlag = TRUE;
break;
}
}
if (bFindFlag)
{
list_move_tail(&pEntry->mList, &pBufMng->idlePktList);
if (pBufMng->mWaitIdlePktFlag)
{
pthread_cond_signal(&pBufMng->mWaitIdleCondition);
}
}
else
{
aloge("fatal error! not find buf[ID=%d][%p][%p] in used list."
,stEncodedStream.nID
,stEncodedStream.pBuffer
,stEncodedStream.pBufferExtra
);
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
pthread_mutex_unlock(&pDemuxData->mStateLock);
return ERR_DEMUX_UNEXIST;
}
}
else
{
alogw("Be careful! buf not find, maybe reset channel before call this function?");
}
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
}
else if (pBufSupplier->eBufferSupplier == COMP_BufferSupplyInput)
{
pthread_mutex_lock(&pBufMng->mPktlistMutex);
_TryToGetIdlePktNode:
if (!list_empty(&pBufMng->idlePktList))
{
// Record buf from B component to idlePktList
DMXPKT_NODE_T *pPktIdleNode = list_first_entry(&pBufMng->idlePktList, DMXPKT_NODE_T, mList);
pPktIdleNode->stEncodedStream.media_type = stEncodedStream.media_type;
pPktIdleNode->stEncodedStream.pBuffer = stEncodedStream.pBuffer;
pPktIdleNode->stEncodedStream.nBufferLen = stEncodedStream.nBufferLen;
pPktIdleNode->stEncodedStream.pBufferExtra = stEncodedStream.pBufferExtra;
pPktIdleNode->stEncodedStream.nBufferExtraLen = stEncodedStream.nBufferExtraLen;
alogv("DemuxFillThisBuffer media_type[%d] pBuffer[%p] nBufferLen[%d] pBufferExtra[%p] nBufferExtraLen[%d]"
,stEncodedStream.media_type
,pPktIdleNode->stEncodedStream.pBuffer
,pPktIdleNode->stEncodedStream.nBufferLen
,pPktIdleNode->stEncodedStream.pBufferExtra
,pPktIdleNode->stEncodedStream.nBufferExtraLen
);
list_move_tail(&pPktIdleNode->mList, &pBufMng->fillingPktList);
// Send message to DemuxCompThread
message_t cmd_msg;
if (CDX_PacketVideo == pPktIdleNode->stEncodedStream.media_type)
{
cmd_msg.command = DemuxComp_VideoBufferAvailable;
cmd_msg.para0 = 0;
if (TRUE == pDemuxData->mWaitVideoBufFlag)
{
pDemuxData->mWaitVideoBufFlag = FALSE;
}
}
else if (CDX_PacketAudio == pPktIdleNode->stEncodedStream.media_type)
{
cmd_msg.command = DemuxComp_AudioBufferAvailable;
cmd_msg.para0 = 0;
if (TRUE == pDemuxData->mWaitAudioBufFlag)
{
pDemuxData->mWaitAudioBufFlag = FALSE;
}
}
else if (CDX_PacketSubtitle == pPktIdleNode->stEncodedStream.media_type)
{
cmd_msg.command = DemuxComp_SubtitleBufferAvailable;
cmd_msg.para0 = 0;
if (TRUE == pDemuxData->mWaitSubtitleBufFlag)
{
pDemuxData->mWaitSubtitleBufFlag = FALSE;
}
}
else
{
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
pthread_mutex_unlock(&pDemuxData->mStateLock);
aloge("fatal error! failed to get the unknow media_type [%d]", pPktIdleNode->stEncodedStream.media_type);
return ERR_DEMUX_UNEXIST;
}
put_message(&pDemuxData->cmd_queue, &cmd_msg);
}
else
{// no idle buffer, create a new node
alogw("idlePktList Empty, create new node");
DMXPKT_NODE_T *pNode = (DMXPKT_NODE_T *)malloc(sizeof(DMXPKT_NODE_T));
if (NULL == pNode)
{
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
pthread_mutex_unlock(&pDemuxData->mStateLock);
aloge("alloc idle_pkt_node fail");
return ERR_DEMUX_NOMEM;
}
memset(pNode, 0, sizeof(DMXPKT_NODE_T));
list_add_tail(&pNode->mList, &pBufMng->idlePktList);
pBufMng->mPktListNodeCnt++;
goto _TryToGetIdlePktNode;
}
pthread_mutex_unlock(&pBufMng->mPktlistMutex);
}
else
{
aloge("fatal error! Unsupported buffer supplier type %d", pBufSupplier->eBufferSupplier);
}
pthread_mutex_unlock(&pDemuxData->mStateLock);
return eError;
}
#define MAX_BUFFER_PACKET_TIMES 2000000 //unit:us
static void* ComponentThread(void* pThreadData)
{
CompInternalMsgType cmd;
unsigned int cmddata;
message_t cmd_msg;
MM_COMPONENTTYPE* hnd_clock_comp = NULL;
DMXPKT_NODE_T *pNode, *pEntry, *pTmp;
// Get component private data
DEMUXDATATYPE* pDemuxData = (DEMUXDATATYPE*)pThreadData;
alogd("Demux ComponentThread start run...");
sprintf(pDemuxData->mThreadName, "DmxChn%d", pDemuxData->mMppChnInfo.mChnId);
prctl(PR_SET_NAME, (unsigned long)pDemuxData->mThreadName, 0, 0, 0);
while (1)
{
PROCESS_MESSAGE:
if (get_message(&pDemuxData->cmd_queue, &cmd_msg) == 0)
{// pump message from message queue
cmd = cmd_msg.command;
cmddata = cmd_msg.para0;
alogv("Demux ComponentThread get_message cmd:%d", cmd);
// State transition command
if (cmd == SetState)
{
pthread_mutex_lock(&pDemuxData->mStateLock);
// If the parameter states a transition to the same state
// raise a same state transition error.
pDemuxData->switching_state = 0;
if (pDemuxData->state == (COMP_STATETYPE)(cmddata))
{
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf, pDemuxData->pAppData, COMP_EventError, ERR_DEMUX_SAMESTATE, 0, NULL);
}
else
{
// transitions/callbacks made based on state transition table
// cmddata contains the target state
switch ((COMP_STATETYPE)(cmddata))
{
case COMP_StateInvalid:
{
pDemuxData->state = COMP_StateInvalid;
pDemuxData->pCallbacks->EventHandler
(pDemuxData->hSelf
,pDemuxData->pAppData
,COMP_EventCmdComplete
,COMP_CommandStateSet
,pDemuxData->state
,NULL
);
break;
}
case COMP_StateLoaded:
{
if (pDemuxData->demux_init_end)
{
if (pDemuxData->cdx_epdk_dmx != NULL)
{
pDemuxData->cdx_epdk_dmx->close(pDemuxData->cdx_epdk_dmx);
cedarx_demux_destory(pDemuxData->cdx_epdk_dmx);
pDemuxData->cdx_epdk_dmx = NULL;
}
pDemuxData->demux_init_end = 0;
}
if(pDemuxData->state != COMP_StateIdle)
{
aloge("fatal error! state[0x%x] is not idle!", pDemuxData->state);
}
Demux_CheckFillingPktEmpty(pDemuxData);
//return all buffers to vdec, adec, etc.
Demux_ReturnAllBuffer(pDemuxData);
pDemuxData->state = COMP_StateLoaded;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf, pDemuxData->pAppData, COMP_EventCmdComplete, COMP_CommandStateSet, pDemuxData->state, NULL);
break;
}
case COMP_StateIdle:
{
if (pDemuxData->state == COMP_StateInvalid)
{
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf, pDemuxData->pAppData, COMP_EventError, ERR_DEMUX_INCORRECT_STATE_TRANSITION, pDemuxData->state, NULL);
}
else
{
if(0 == pDemuxData->demux_init_end)
{
if(DemuxOpenParserLib(pDemuxData) != SUCCESS)
{
int ret = -1;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf, pDemuxData->pAppData, COMP_EventCmdComplete, COMP_CommandStateSet, COMP_StateInvalid, (void*)&ret);
break;
}
CreateDemuxPorts(pDemuxData, &pDemuxData->cdx_mediainfo);
pDemuxData->demux_init_end = 1;
}
if(COMP_StateLoaded == pDemuxData->state)
{
}
else if(COMP_StatePause == pDemuxData->state || COMP_StateExecuting == pDemuxData->state)
{
//return all buffers to vdec, adec, etc.
Demux_ReturnAllBuffer(pDemuxData);
}
else
{
aloge("fatal error! unknown state[0x%x]", pDemuxData->state);
}
pDemuxData->state = COMP_StateIdle;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pDemuxData->state,
NULL);
}
break;
}
case COMP_StateExecuting:
{
// Transition can only happen from pause or idle state
if (pDemuxData->state == COMP_StateIdle || pDemuxData->state == COMP_StatePause)
{
hnd_clock_comp = (MM_COMPONENTTYPE *)(pDemuxData->sPortTunnelInfo[pDemuxData->clock_port_idx].hTunnel);
if (pDemuxData->state == COMP_StateIdle && !pDemuxData->mAllocBufFlag)
{
allocDmxOutputBuf(pDemuxData);
}
pDemuxData->dmx_eof_send = 0;
pDemuxData->state = COMP_StateExecuting;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pDemuxData->state, NULL);
}
else
{
pDemuxData->state = COMP_StateIdle;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventError,
ERR_DEMUX_INCORRECT_STATE_TRANSITION,
pDemuxData->state,
NULL);
}
break;
}
case COMP_StatePause:
{
// Transition can only happen from idle or executing state
if (pDemuxData->state == COMP_StateIdle || pDemuxData->state == COMP_StateExecuting)
{
pDemuxData->state = COMP_StatePause;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pDemuxData->state,
NULL);
}
else
{
aloge("fatal error! state[0x%x]->Pause!", pDemuxData->state);
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventError,
ERR_DEMUX_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
Demux_ReturnAllBuffer(pDemuxData);
break;
}
default:
{
break;
}
}
}
pthread_mutex_unlock(&pDemuxData->mStateLock);
}
else if (cmd == StopPort)
{
//* do nothing.
}
else if (cmd == Flush)
{
//* do nothing.
}
else if (cmd == Stop)
{
//* kill the thread.
goto EXIT;
}
else if (cmd == DemuxComp_VideoBufferAvailable)
{
//* do nothing.
}
else if (cmd == DemuxComp_AudioBufferAvailable)
{
//* do nothing.
}
else if (cmd == DemuxComp_SubtitleBufferAvailable)
{
//* do nothing.
}
//precede to process message
goto PROCESS_MESSAGE;
} /* End of process message */
// Check EOF flag
if (pDemuxData->dmx_eof)
{
alogw("[%p]:Demux EOF found! A", pDemuxData->hSelf);
if (pDemuxData->dmx_eof_send == 0)
{
pDemuxData->dmx_eof_send = 1;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf, pDemuxData->pAppData, COMP_EventBufferFlag, 0, 0, NULL);
}
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 0);
goto PROCESS_MESSAGE;
}
// Ensure it is in Exec state
if (pDemuxData->state != COMP_StateExecuting)
{
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 0);
goto PROCESS_MESSAGE;
}
// Get system time
int64_t system_time;
if (pDemuxData->mOutputPortTunnelFlag[0])
{
if(hnd_clock_comp)
{
COMP_TIME_CONFIG_TIMESTAMPTYPE time_stamp;
COMP_GetConfig(hnd_clock_comp, COMP_IndexConfigTimeCurrentMediaTime, &time_stamp);
system_time = time_stamp.nTimestamp;
}
else
{
system_time = -1;
}
}
else
{
system_time = -1;
}
// Control read speed
if( (system_time == -1)
|| ( (pDemuxData->max_send_packet_time_video - system_time < MAX_BUFFER_PACKET_TIMES)
|| (pDemuxData->max_send_packet_time_audio - system_time < MAX_BUFFER_PACKET_TIMES)
)
)
{
//nothing to do
}
else
{// read too fast, wait a while
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 200);
goto PROCESS_MESSAGE;
}
// Prefetch media data
if (pDemuxData->prefetch_done == 0)
{
if (pDemuxData->cdx_epdk_dmx->prefetch(pDemuxData->cdx_epdk_dmx, &pDemuxData->cdx_pkt) != 0)
{// prefetch failed
int err = pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_GET_STATUS, 0, NULL);
if (err == PSR_IO_ERR)
{
aloge("IO ERROR");
}
else if (err == PSR_USER_CANCEL)
{
aloge("PSR USER CANCEL, do nothing");
}
else
{
alogd("getconfig [%p]:Demuxer EOF found! B", pDemuxData->hSelf);
pDemuxData->dmx_eof = 1;
pDemuxData->dmx_eof_send = 1;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventBufferFlag,
0,
0,
NULL);
}
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 200);
goto PROCESS_MESSAGE;
}
/*
alogd("pDemuxData->cdx_pkt.type: %d, pDemuxData->cdx_pkt.streamIndex: %d",
pDemuxData->cdx_pkt.type, pDemuxData->cdx_pkt.streamIndex);
*/
// prefetch success
pDemuxData->prefetch_done = 1; // Set prefetch success flag, only prefetch once
}
// Get tunnel_port_idx and nStreamIndex
int tunnel_port_idx = -1;
int nStreamIndex = -1;
if (pDemuxData->cdx_pkt.type == CDX_MEDIA_VIDEO)
{// video data
//alogd("vpkt_streamId:%d, pts:[%lld]ms", pDemuxData->cdx_pkt.streamIndex, pDemuxData->cdx_pkt.pts/1000);
if (0 == (pDemuxData->disable_track & DEMUX_DISABLE_VIDEO_TRACK))
{
tunnel_port_idx = pDemuxData->video_port_idx;
nStreamIndex = (pDemuxData->cdx_pkt.flags & MINOR_STREAM) == 0 ? 0 : 1;
if (pDemuxData->max_send_packet_time_video < pDemuxData->cdx_pkt.pts)
{
pDemuxData->max_send_packet_time_video = pDemuxData->cdx_pkt.pts;
}
}
else
{
tunnel_port_idx = -1;
//alogv("[%d] is not current video stream index, skip", pDemuxData->cdx_pkt.streamIndex);
}
}
else if (pDemuxData->cdx_pkt.type == CDX_MEDIA_AUDIO)
{
//alogd("apkt_streamId:%d, pts:[%lld]ms", pDemuxData->cdx_pkt.streamIndex, pDemuxData->cdx_pkt.pts/1000);
if ( 0 == (pDemuxData->disable_track & DEMUX_DISABLE_AUDIO_TRACK)
&& pDemuxData->cdx_pkt.streamIndex == pDemuxData->mCurAudioStreamIndex // mCurAudioStreamIndex for 2 channels
)
{
tunnel_port_idx = pDemuxData->audio_port_idx;
nStreamIndex = pDemuxData->cdx_pkt.streamIndex;
if (pDemuxData->max_send_packet_time_audio < pDemuxData->cdx_pkt.pts)
{
pDemuxData->max_send_packet_time_audio = pDemuxData->cdx_pkt.pts;
}
}
else
{
tunnel_port_idx = -1;
alogv("[%d] is not current audio stream index[%d], skip", pDemuxData->cdx_pkt.streamIndex, pDemuxData->mCurAudioStreamIndex);
}
}
else if (pDemuxData->cdx_pkt.type == CDX_MEDIA_SUBTITLE)
{
//alogd("spkt_streamId:%d, pts:[%lld]ms", pDemuxData->cdx_pkt.streamIndex, pDemuxData->cdx_pkt.pts/1000);
if ( 0 == (pDemuxData->disable_track & DEMUX_DISABLE_SUBTITLE_TRACK)
&& pDemuxData->cdx_pkt.streamIndex == pDemuxData->mCurSubtitleStreamIndex
)
{
tunnel_port_idx = pDemuxData->subtitle_port_idx;
nStreamIndex = pDemuxData->cdx_pkt.streamIndex;
if (pDemuxData->max_send_packet_time_subtitle < pDemuxData->cdx_pkt.pts)
{
pDemuxData->max_send_packet_time_subtitle = pDemuxData->cdx_pkt.pts;
}
}
else
{
tunnel_port_idx = -1;
alogv("[%d] is not current subtitle stream index[%d], skip", pDemuxData->cdx_pkt.streamIndex, pDemuxData->mCurSubtitleStreamIndex);
}
}
else
{
aloge("fatal error! media type from parser not valid, should not run here, abort().");
tunnel_port_idx = -1;
}
// Ensure tunnel_port_idx is valid
if (tunnel_port_idx < 0)
{
if(CDX_OK!=pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_SKIP_CHUNK_DATA, 0, &pDemuxData->cdx_pkt))
{
aloge("fatal error! skip chunk data fail!");
}
pDemuxData->prefetch_done = 0;
goto PROCESS_MESSAGE;
}
// Prepare data
EncodedStream dmxOutBuf;
memset(&dmxOutBuf, 0, sizeof(EncodedStream));
dmxOutBuf.nTobeFillLen = pDemuxData->cdx_pkt.length;
if (pDemuxData->cdx_pkt.type == CDX_MEDIA_VIDEO)
{
enum VIDEO_TYPE video_type = (nStreamIndex == 0) ? VIDEO_TYPE_MAJOR : VIDEO_TYPE_MINOR;
if (video_type == VIDEO_TYPE_MAJOR)
{
dmxOutBuf.video_stream_type = VIDEO_TYPE_MAJOR; //CDX_VIDEO_STREAM_MAJOR;
}
else if (video_type == VIDEO_TYPE_MINOR)
{
dmxOutBuf.video_stream_type = VIDEO_TYPE_MINOR; //CDX_VIDEO_STREAM_MINOR;
}
else
{
dmxOutBuf.video_stream_type = VIDEO_TYPE_NOT_VIDEO; //CDX_VIDEO_STREAM_NONE;
}
}
if (pDemuxData->mOutputPortTunnelFlag[tunnel_port_idx])
{// outport tunnel mode
// Get tunnel_info handle
COMP_INTERNAL_TUNNELINFOTYPE* tunnel_info = &pDemuxData->sPortTunnelInfo[tunnel_port_idx];
COMP_PARAM_BUFFERSUPPLIERTYPE* pBufSupplier = &pDemuxData->sPortBufSupplier[tunnel_port_idx];
BUFFER_MNG* pBufferMng = &pDemuxData->mBufferMng[tunnel_port_idx];
COMP_BUFFERHEADERTYPE omx_buffer_header;
memset(&omx_buffer_header, 0, sizeof(omx_buffer_header));
omx_buffer_header.pOutputPortPrivate = (void*)&dmxOutBuf;
omx_buffer_header.nInputPortIndex = tunnel_info->nTunnelPortIndex;
if (pBufSupplier->eBufferSupplier == COMP_BufferSupplyOutput)
{
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
while (list_empty(&pBufferMng->idlePktList))
{
pBufferMng->mWaitIdlePktFlag = TRUE;
pthread_cond_wait(&pBufferMng->mWaitIdleCondition, &pBufferMng->mPktlistMutex);
}
pBufferMng->mWaitIdlePktFlag = FALSE;
BOOL bFindFlag = FALSE;
list_for_each_entry_safe(pEntry, pTmp, &pBufferMng->idlePktList, mList)
{
if (pEntry->stEncodedStream.nBufferLen >= dmxOutBuf.nTobeFillLen)
{
bFindFlag = TRUE;
break;
}
}
if (bFindFlag)
{
pNode = pEntry;
}
else
{
pNode = list_first_entry(&pBufferMng->idlePktList, DMXPKT_NODE_T, mList);
int size = dmxOutBuf.nTobeFillLen;
alogv("search and find no node that capacity is big enough, realloc size: %d", size);
if (pNode->stEncodedStream.pBuffer != NULL)
{
free(pNode->stEncodedStream.pBuffer);
pNode->stEncodedStream.pBuffer = NULL;
pNode->stEncodedStream.nBufferLen = 0;
}
pNode->stEncodedStream.nBufferLen = size;
pNode->stEncodedStream.pBuffer = (unsigned char *)malloc(size);
if (pNode->stEncodedStream.pBuffer == NULL)
{
pNode->stEncodedStream.nBufferLen = 0;
aloge("malloc %d Bytes fail, skip this pkt", size);
if (CDX_OK != pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_SKIP_CHUNK_DATA, 0, &pDemuxData->cdx_pkt))
{
aloge("fatal error! skip chunk data fail!");
}
pDemuxData->prefetch_done = 0;
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
goto PROCESS_MESSAGE;
}
}
list_move_tail(&pNode->mList, &pBufferMng->fillingPktList);
pNode->stEncodedStream.media_type = map_PacketType_To_MediaType(pDemuxData->cdx_pkt.type);
pNode->stEncodedStream.video_stream_type = dmxOutBuf.video_stream_type;
pDemuxData->cdx_pkt.buf = NULL;
pDemuxData->cdx_pkt.ringBuf = NULL;
pDemuxData->cdx_pkt.buflen = 0;
pDemuxData->cdx_pkt.ringBufLen = 0;
pDemuxData->cdx_pkt.buf = pNode->stEncodedStream.pBuffer;
if(pNode->stEncodedStream.nBufferLen >= pDemuxData->cdx_pkt.length)
{
pDemuxData->cdx_pkt.buflen = pDemuxData->cdx_pkt.length;
}
else
{
pDemuxData->cdx_pkt.buflen = pNode->stEncodedStream.nBufferLen;
pDemuxData->cdx_pkt.ringBuf = pNode->stEncodedStream.pBufferExtra;
pDemuxData->cdx_pkt.ringBufLen = pDemuxData->cdx_pkt.length - pNode->stEncodedStream.nBufferLen;
}
}
else if (pBufSupplier->eBufferSupplier == COMP_BufferSupplyInput)
{
// Find correspond media data buffer
BOOL bFindFlag;
BOOL bBufferEnough;
_TryToFindBuffer:
bFindFlag = FALSE;
bBufferEnough = FALSE;
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
list_for_each_entry_safe(pEntry, pTmp, &pBufferMng->fillingPktList, mList)
{
bFindFlag = FALSE;
bBufferEnough = FALSE;
int media_type = map_PacketType_To_MediaType(pDemuxData->cdx_pkt.type);
if (pEntry->stEncodedStream.media_type == media_type)
{
bFindFlag = TRUE;
if ((pEntry->stEncodedStream.nBufferLen + pEntry->stEncodedStream.nBufferExtraLen) >= dmxOutBuf.nTobeFillLen)
{
bBufferEnough = TRUE;
}
break;
}
}
if (bFindFlag && bBufferEnough)
{
pNode = pEntry;
}
else if (bFindFlag && !bBufferEnough)
{
alogv("find that node buffer capacity is not big enough, request size: %d", dmxOutBuf.nTobeFillLen);
pNode = pEntry;
dmxOutBuf.nFilledLen = -1; // indicate buffer is not enough. requir length is nTobeFillLen
dmxOutBuf.pBuffer = pNode->stEncodedStream.pBuffer;
dmxOutBuf.pBufferExtra = pNode->stEncodedStream.pBufferExtra;
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
COMP_EmptyThisBuffer(tunnel_info->hTunnel, (void*)&omx_buffer_header);
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
memset(&pNode->stEncodedStream, 0, sizeof(EncodedStream));
list_move_tail(&pNode->mList, &pBufferMng->idlePktList);
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
goto _TryToFindBuffer;
}
else if (!bFindFlag)
{
alogv("call Thread pDemuxData->cdx_pkt.type[%d] mWaitVideoBufFlag[%d] mWaitAudioBufFlag[%d]",
pDemuxData->cdx_pkt.type,
pDemuxData->mWaitVideoBufFlag,
pDemuxData->mWaitAudioBufFlag);
// wait stream buffer
if (pDemuxData->cdx_pkt.type == CDX_MEDIA_VIDEO)
{
pDemuxData->mWaitVideoBufFlag = TRUE;
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 0);
goto PROCESS_MESSAGE;
}
else if (pDemuxData->cdx_pkt.type == CDX_MEDIA_AUDIO)
{
pDemuxData->mWaitAudioBufFlag = TRUE;
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 0);
goto PROCESS_MESSAGE;
}
else if (pDemuxData->cdx_pkt.type == CDX_MEDIA_SUBTITLE)
{
pDemuxData->mWaitSubtitleBufFlag = TRUE;
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 0);
goto PROCESS_MESSAGE;
}
else
{
aloge("fatal error! Unknown media_type[%d]", pDemuxData->cdx_pkt.type);
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
goto PROCESS_MESSAGE;
}
}
else
{
aloge("fatal error! Should not come here");
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
goto PROCESS_MESSAGE;
}
pDemuxData->cdx_pkt.buf = NULL;
pDemuxData->cdx_pkt.ringBuf = NULL;
pDemuxData->cdx_pkt.buflen = 0;
pDemuxData->cdx_pkt.ringBufLen = 0;
pDemuxData->cdx_pkt.buf = pNode->stEncodedStream.pBuffer;
if(pNode->stEncodedStream.nBufferLen >= pDemuxData->cdx_pkt.length)
{
pDemuxData->cdx_pkt.buflen = pDemuxData->cdx_pkt.length;
}
else
{
pDemuxData->cdx_pkt.buflen = pNode->stEncodedStream.nBufferLen;
pDemuxData->cdx_pkt.ringBuf = pNode->stEncodedStream.pBufferExtra;
pDemuxData->cdx_pkt.ringBufLen = pDemuxData->cdx_pkt.length - pNode->stEncodedStream.nBufferLen;
}
}
else
{
aloge("fatal error: invalide BufferSupplier type %d", pBufSupplier->eBufferSupplier);
abort();
}
if (pDemuxData->cdx_epdk_dmx->read(pDemuxData->cdx_epdk_dmx, &pDemuxData->cdx_pkt) == CDX_ERROR)
{// read failed
int err = pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_GET_STATUS, 0, NULL);
if(err == PSR_IO_ERR)
{
aloge("IO ERROR");
}
else if (err == PSR_USER_CANCEL)
{
/* do noting */
alogd("PSR USER CANCEL, do nothing");
}
else
{
alogd("getconfig [%p]:Demuxer EOF found! C", pDemuxData->hSelf);
pDemuxData->dmx_eof = 1;
pDemuxData->dmx_eof_send = 1;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventBufferFlag,
0,
0,
NULL);
}
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
TMessage_WaitQueueNotEmpty(&pDemuxData->cmd_queue, 200);
goto PROCESS_MESSAGE;
}
#if DEBUG_SAVE_VIDEO_STREAM
if (CDX_MEDIA_VIDEO == pDemuxData->cdx_pkt.type)
{
if(pDemuxData->cdx_pkt.buflen > 0)
{
fwrite(pDemuxData->cdx_pkt.buf, 1, pDemuxData->cdx_pkt.buflen, fpVideoStream);
}
if(pDemuxData->cdx_pkt.ringBufLen > 0)
{
fwrite(pDemuxData->cdx_pkt.ringBuf, 1, pDemuxData->cdx_pkt.ringBufLen, fpVideoStream);
}
}
#endif
// Get ctrl_bits
int ctrl_bits = 0;
ctrl_bits |= CEDARV_FLAG_PTS_VALID;
if (pDemuxData->cdx_pkt.flags & FIRST_PART)
{
ctrl_bits |= CEDARV_FLAG_FIRST_PART;
}
if (pDemuxData->cdx_pkt.flags & LAST_PART)
{
ctrl_bits |= CEDARV_FLAG_LAST_PART;
}
if (pDemuxData->cdx_pkt.flags & KEY_FRAME)
{
ctrl_bits |= CEDARV_FLAG_KEYFRAME;
}
dmxOutBuf.media_type = map_PacketType_To_MediaType(pDemuxData->cdx_pkt.type);
dmxOutBuf.nID = pNode->stEncodedStream.nID;
dmxOutBuf.nFilledLen = pDemuxData->cdx_pkt.length;
dmxOutBuf.nTobeFillLen = pDemuxData->cdx_pkt.length;
dmxOutBuf.nTimeStamp = pDemuxData->cdx_pkt.pts;
dmxOutBuf.nFlags = ctrl_bits;
dmxOutBuf.pBuffer = pNode->stEncodedStream.pBuffer;
dmxOutBuf.nBufferLen = pNode->stEncodedStream.nBufferLen;
dmxOutBuf.pBufferExtra = pNode->stEncodedStream.pBufferExtra;
dmxOutBuf.nBufferExtraLen = pNode->stEncodedStream.nBufferExtraLen;
//dmxOutBuf.video_stream_type has already been set
//dmxOutBuf.video_frame_info only needed by venc
dmxOutBuf.infoVersion = pDemuxData->cdx_pkt.infoVersion;
dmxOutBuf.pChangedStreamsInfo = pDemuxData->cdx_pkt.info;
dmxOutBuf.duration = pDemuxData->cdx_pkt.duration;
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
alogv("========= media_type[%d](1-video 2-audio) ID[%d] pts[%lld]", dmxOutBuf.media_type, dmxOutBuf.nID, dmxOutBuf.nTimeStamp);
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
if (pBufSupplier->eBufferSupplier == COMP_BufferSupplyOutput)
{
list_move_tail(&pNode->mList, &pBufferMng->usingPktList);
}
else if (pBufSupplier->eBufferSupplier == COMP_BufferSupplyInput)
{
memset(&pNode->stEncodedStream, 0, sizeof(EncodedStream));
list_move_tail(&pNode->mList, &pBufferMng->idlePktList);
}
else
{
aloge("fatal error! Unsupported buffer suppier type %d", pBufSupplier->eBufferSupplier);
abort();
}
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
// Send data to component B
COMP_EmptyThisBuffer(tunnel_info->hTunnel, (void*)&omx_buffer_header);
pDemuxData->prefetch_done = 0;
} //outporttunnelflag
else
{// outport non-tunnel mode
BUFFER_MNG* pBufferMng = &pDemuxData->mBufferMng[tunnel_port_idx];
int eWaitRet;
const int nMilliSec = 1000; //unit:ms
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
while (list_empty(&pBufferMng->idlePktList))
{
//alogd("wait idle dmxpkt node");
pBufferMng->mWaitIdlePktFlag = TRUE;
eWaitRet = pthread_cond_wait_timeout(&pBufferMng->mWaitIdleCondition, &pBufferMng->mPktlistMutex, nMilliSec);
if(ETIMEDOUT == eWaitRet)
{
alogv("wait idle dmxpkt timeout[%d]ms, ret[%d]", nMilliSec, eWaitRet);
//detect message
if(get_message_count(&pDemuxData->cmd_queue) > 0)
{
alogd("dmx wait idle packet timeout in non-tunnel mode, goto process message.");
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
goto PROCESS_MESSAGE;
}
}
else if(0 == eWaitRet)
{
continue;
}
else
{
aloge("fatal error! pthread cond wait timeout ret[%d]", eWaitRet);
}
}
pBufferMng->mWaitIdlePktFlag = FALSE;
BOOL bFindFlag = FALSE;
list_for_each_entry_safe(pEntry, pTmp, &pBufferMng->idlePktList, mList)
{
if (pEntry->stEncodedStream.nBufferLen >= dmxOutBuf.nTobeFillLen)
{
bFindFlag = TRUE;
break;
}
}
if (bFindFlag)
{
pNode = pEntry;
}
else
{
pNode = list_first_entry(&pBufferMng->idlePktList,DMXPKT_NODE_T, mList);
int size = dmxOutBuf.nTobeFillLen;
alogd("search and find no node that capacity is big enough, realloc size: %d", size);
if (pNode->stEncodedStream.pBuffer != NULL)
{
free(pNode->stEncodedStream.pBuffer);
pNode->stEncodedStream.pBuffer = NULL;
pNode->stEncodedStream.nBufferLen = 0;
}
pNode->stEncodedStream.nBufferLen = size;
pNode->stEncodedStream.pBuffer = (unsigned char *)malloc(size);
if (pNode->stEncodedStream.pBuffer == NULL)
{
pNode->stEncodedStream.nBufferLen = 0;
aloge("fatal error! malloc %d Bytes fail, skip this pkt", size);
if (CDX_OK!=pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_SKIP_CHUNK_DATA, 0, &pDemuxData->cdx_pkt))
{
aloge("fatal error! skip chunk data fail!");
}
pDemuxData->prefetch_done = 0;
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
goto PROCESS_MESSAGE;
}
}
list_move_tail(&pNode->mList, &pBufferMng->fillingPktList); //in case thread go out, the node is discard, not link to list
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
pNode->stEncodedStream.media_type = map_PacketType_To_MediaType(pDemuxData->cdx_pkt.type);
pNode->stEncodedStream.video_stream_type = dmxOutBuf.video_stream_type;
pDemuxData->cdx_pkt.buf = pNode->stEncodedStream.pBuffer;
pDemuxData->cdx_pkt.buflen = pNode->stEncodedStream.nBufferLen;
pDemuxData->cdx_pkt.ringBuf = pNode->stEncodedStream.pBufferExtra;
pDemuxData->cdx_pkt.ringBufLen = pNode->stEncodedStream.nBufferExtraLen;
if (pDemuxData->cdx_epdk_dmx->read(pDemuxData->cdx_epdk_dmx, &pDemuxData->cdx_pkt) == CDX_ERROR)
{
int err = pDemuxData->cdx_epdk_dmx->control(pDemuxData->cdx_epdk_dmx, CDX_DMX_CMD_GET_STATUS, 0, NULL);
if (err == PSR_IO_ERR)
{
aloge("IO ERROR");
}
else if (err == PSR_USER_CANCEL)
{
/* do noting */
alogd("PSR USER CANCEL, do nothing");
}
else
{
alogd("getconfig [%p]:Demuxer EOF found! C", pDemuxData->hSelf);
pDemuxData->dmx_eof = 1;
pDemuxData->dmx_eof_send = 1;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf,
pDemuxData->pAppData,
COMP_EventBufferFlag,
0,
0,
NULL);
}
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
list_move_tail(&pNode->mList, &pBufferMng->idlePktList);
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
goto PROCESS_MESSAGE;
}
int ctrl_bits = 0;
ctrl_bits |= CEDARV_FLAG_PTS_VALID;
if (pDemuxData->cdx_pkt.flags & FIRST_PART)
{
ctrl_bits |= CEDARV_FLAG_FIRST_PART;
}
if (pDemuxData->cdx_pkt.flags & LAST_PART)
{
ctrl_bits |= CEDARV_FLAG_LAST_PART;
}
if (pDemuxData->cdx_pkt.flags & KEY_FRAME)
{
ctrl_bits |= CEDARV_FLAG_KEYFRAME;
}
pNode->stEncodedStream.nFilledLen = pDemuxData->cdx_pkt.length;
pNode->stEncodedStream.nTobeFillLen = pDemuxData->cdx_pkt.length;
pNode->stEncodedStream.nTimeStamp = pDemuxData->cdx_pkt.pts;
pNode->stEncodedStream.nFlags = ctrl_bits;//pDemuxData->cdx_pkt.flags;
pNode->stEncodedStream.infoVersion = pDemuxData->cdx_pkt.infoVersion;
pNode->stEncodedStream.pChangedStreamsInfo = pDemuxData->cdx_pkt.info;
pNode->stEncodedStream.duration = pDemuxData->cdx_pkt.duration;
pthread_mutex_lock(&pBufferMng->mPktlistMutex);
list_move_tail(&pNode->mList, &pBufferMng->readyPktList);
if (pBufferMng->mWaitReadyPktFlag)
{
pthread_cond_signal(&pBufferMng->mWaitReadyCondition);
pBufferMng->mWaitReadyPktFlag = FALSE;
}
pthread_mutex_unlock(&pBufferMng->mPktlistMutex);
pDemuxData->prefetch_done = 0;
}
// Clear seek flag
if ( pDemuxData->dmx_seek_flag
&& (pDemuxData->cdx_pkt.flags & LAST_PART)
)
{
alogd("seek done? start schedure to other thread for first frame");
pDemuxData->dmx_seek_flag = 0;
if (get_message_count(&pDemuxData->cmd_queue) > 0)
{
goto PROCESS_MESSAGE;
}
}
}
EXIT:
alogv("Demuxer ComponentThread stopped");
return (void*) SUCCESS;
}
static ERRORTYPE CB_EventHandler(void* cookie, int event, void *data)
{
DEMUXDATATYPE* pDemuxData;
pDemuxData = (DEMUXDATATYPE*)cookie;
pDemuxData->pCallbacks->EventHandler(pDemuxData->hSelf, pDemuxData->pAppData, event, 0, 0, data);
return SUCCESS;
}