sdk-hwV1.3/external/eyesee-mpp/dragonboard/apps/DragonBoard/testcase/vdectester/sample_demux2vdec2vo.c

797 lines
25 KiB
C
Executable File

/******************************************************************************
Copyright (C), 2001-2016, Allwinner Tech. Co., Ltd.
******************************************************************************
File Name :
Version : Initial Draft
Author : Allwinner BU3-PD2 Team
Created : 2016/11/4
Last Modified :
Description :
Function List :
History :
******************************************************************************/
#define LOG_NDEBUG 0
#define LOG_TAG "SampleDemux2Vdec2Vo"
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include "plat_log.h"
#include <mpi_demux.h>
#include <mpi_vdec.h>
#include <mpi_clock.h>
#include "hwdisplay.h"
#include "sample_demux2vdec2vo.h"
#include "sample_demux2vdec2vo_common.h"
#define DMX2VDEC2VO_DEFAULT_SRC_FILE "/mnt/extsd/sample_demux2vdec2vo/test.mp4"
static SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData;
static ERRORTYPE InitDemux2Vdec2VoData(void)
{
pDemux2Vdec2VoData = (SAMPLE_DEMUX2VDEC2VO_S* )malloc(sizeof(SAMPLE_DEMUX2VDEC2VO_S));
if (pDemux2Vdec2VoData == NULL)
{
aloge("malloc struct fail");
return FAILURE;
}
memset(pDemux2Vdec2VoData, 0, sizeof(SAMPLE_DEMUX2VDEC2VO_S));
pDemux2Vdec2VoData->mConfigPara.mUserSetPixelFormat = MM_PIXEL_FORMAT_YVU_PLANAR_420;
//pDemux2Vdec2VoData->mConfigPara.mUserSetPixelFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputWidth = 1920;
pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputHeight= 1080;
pDemux2Vdec2VoData->mDmxChn = MM_INVALID_CHN;
pDemux2Vdec2VoData->mVdecChn = MM_INVALID_CHN;
pDemux2Vdec2VoData->mClockChn = MM_INVALID_CHN;
pDemux2Vdec2VoData->mVoDev = MM_INVALID_DEV;
pDemux2Vdec2VoData->mVoLayer = MM_INVALID_CHN;
pDemux2Vdec2VoData->mVoChn = MM_INVALID_CHN;
pDemux2Vdec2VoData->mUILayer = MM_INVALID_CHN;
return SUCCESS;
}
static int parseCmdLine(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData, int argc, char** argv)
{
int ret = -1;
while (*argv)
{
if (!strcmp(*argv, "-path"))
{
argv++;
if (*argv)
{
ret = 0;
if (strlen(*argv) >= MAX_FILE_PATH_LEN)
{
aloge("fatal error! file path[%s] too long:!", *argv);
}
strncpy(pDemux2Vdec2VoData->mCmdLinePara.mConfigFilePath, *argv, MAX_FILE_PATH_LEN-1);
pDemux2Vdec2VoData->mCmdLinePara.mConfigFilePath[MAX_FILE_PATH_LEN-1] = '\0';
}
}
else if(!strcmp(*argv, "-h"))
{
printf("CmdLine param:\n"
"\t-path /home/sample_demux2vdec2vo.conf\n");
break;
}
else if (*argv)
{
argv++;
}
}
return ret;
}
static ERRORTYPE loadConfigPara(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData, const char *conf_path)
{
int ret;
char *ptr;
CONFPARSER_S mConf;
strcpy(pDemux2Vdec2VoData->mConfigPara.srcFile, "/mnt/extsd/test.mp4");
pDemux2Vdec2VoData->mConfigPara.seekTime = 0;
pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputWidth = 1920;
pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputHeight= 1080;
pDemux2Vdec2VoData->mConfigPara.mInitRotation = 0;
pDemux2Vdec2VoData->mConfigPara.mUserSetPixelFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420; //MM_PIXEL_FORMAT_YVU_PLANAR_420
pDemux2Vdec2VoData->mConfigPara.mTestDuration = 0;
pDemux2Vdec2VoData->mConfigPara.mDisplayX = 0;
pDemux2Vdec2VoData->mConfigPara.mDisplayY = 0;
pDemux2Vdec2VoData->mConfigPara.mDisplayWidth = 480;
pDemux2Vdec2VoData->mConfigPara.mDisplayHeight = 640;
pDemux2Vdec2VoData->mConfigPara.mbForceFramePackage = FALSE;
if(conf_path != NULL)
{
ret = createConfParser(conf_path, &mConf);
if (ret < 0)
{
aloge("load conf fail");
return FAILURE;
}
ptr = (char *)GetConfParaString(&mConf, DMX2VDEC2VO_CFG_SRC_FILE_STR, NULL);
strcpy(pDemux2Vdec2VoData->mConfigPara.srcFile, ptr);
pDemux2Vdec2VoData->mConfigPara.seekTime = GetConfParaInt(&mConf, DMX2VDEC2VO_CFG_SEEK_POSITION, 0);
pDemux2Vdec2VoData->mConfigPara.mTestDuration = GetConfParaInt(&mConf, DMX2VDEC2VO_CFG_TEST_DURATION, 0);
pDemux2Vdec2VoData->mConfigPara.mDisplayX = GetConfParaInt(&mConf, DMX2VDEC2VO_CFG_DISPLAY_X, 0);
pDemux2Vdec2VoData->mConfigPara.mDisplayY = GetConfParaInt(&mConf, DMX2VDEC2VO_CFG_DISPLAY_Y, 0);
pDemux2Vdec2VoData->mConfigPara.mDisplayWidth = GetConfParaInt(&mConf, DMX2VDEC2VO_CFG_DISPLAY_WIDTH, 0);
pDemux2Vdec2VoData->mConfigPara.mDisplayHeight = GetConfParaInt(&mConf, DMX2VDEC2VO_CFG_DISPLAY_HEIGHT, 0);
pDemux2Vdec2VoData->mConfigPara.mVeFreq = GetConfParaInt(&mConf, DMX2VDEC2VO_CFG_VE_FREQ, 0);
alogd("src_file:%s, seek_time:%d, test_time=%d", pDemux2Vdec2VoData->mConfigPara.srcFile,\
pDemux2Vdec2VoData->mConfigPara.seekTime, pDemux2Vdec2VoData->mConfigPara.mTestDuration);
destroyConfParser(&mConf);
}
return SUCCESS;
}
static ERRORTYPE MPPCallbackWrapper(void *cookie, MPP_CHN_S *pChn, MPP_EVENT_TYPE event, void *pEventData)
{
SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData = (SAMPLE_DEMUX2VDEC2VO_S *)cookie;
if (pChn->mModId == MOD_ID_DEMUX)
{
switch (event)
{
case MPP_EVENT_NOTIFY_EOF:
alogd("demux to end of file");
if (pDemux2Vdec2VoData->mVdecChn >= 0)
{
AW_MPI_VDEC_SetStreamEof(pDemux2Vdec2VoData->mVdecChn, 1);
}
//cdx_sem_up(&pDemux2Vdec2VoData->mSemExit);
break;
default:
break;
}
}
else if (pChn->mModId == MOD_ID_VDEC)
{
switch (event)
{
case MPP_EVENT_NOTIFY_EOF:
alogd("vdec to the end of file");
if (pDemux2Vdec2VoData->mVoChn >= 0)
{
AW_MPI_VO_SetStreamEof(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn, 1);
}
//cdx_sem_up(&pDemux2Vdec2VoData->mSemExit);
break;
default:
break;
}
}
else if (pChn->mModId == MOD_ID_VOU)
{
switch (event)
{
case MPP_EVENT_NOTIFY_EOF:
alogd("vo to the end of file");
cdx_sem_up(&pDemux2Vdec2VoData->mSemExit);
break;
case MPP_EVENT_RENDERING_START:
alogd("vo start to rendering");
break;
default:
break;
}
}
return SUCCESS;
}
static ERRORTYPE createClockChn(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
BOOL bSuccessFlag = FALSE;
pDemux2Vdec2VoData->mClockChn = 0;
while (pDemux2Vdec2VoData->mClockChn < CLOCK_MAX_CHN_NUM)
{
ret = AW_MPI_CLOCK_CreateChn(pDemux2Vdec2VoData->mClockChn, &pDemux2Vdec2VoData->mClockChnAttr);
if (SUCCESS == ret)
{
bSuccessFlag = TRUE;
alogd("create clock channel[%d] success!", pDemux2Vdec2VoData->mClockChn);
break;
}
else if (ERR_CLOCK_EXIST == ret)
{
alogd("clock channel[%d] is exist, find next!", pDemux2Vdec2VoData->mClockChn);
pDemux2Vdec2VoData->mClockChn++;
}
else
{
alogd("create clock channel[%d] ret[0x%x]!", pDemux2Vdec2VoData->mClockChn, ret);
break;
}
}
if (FALSE == bSuccessFlag)
{
pDemux2Vdec2VoData->mClockChn = MM_INVALID_CHN;
aloge("fatal error! create clock channel fail!");
return FAILURE;
}
else
{
return SUCCESS;
}
}
static ERRORTYPE configDmxChnAttr(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
pDemux2Vdec2VoData->mDmxChnAttr.mStreamType = STREAMTYPE_LOCALFILE;
pDemux2Vdec2VoData->mDmxChnAttr.mSourceType = SOURCETYPE_FD;
pDemux2Vdec2VoData->mDmxChnAttr.mSourceUrl = NULL;
pDemux2Vdec2VoData->mDmxChnAttr.mFd = pDemux2Vdec2VoData->srcFd;
pDemux2Vdec2VoData->mDmxChnAttr.mDemuxDisableTrack = pDemux2Vdec2VoData->mTrackDisFlag = DEMUX_DISABLE_SUBTITLE_TRACK|DEMUX_DISABLE_AUDIO_TRACK;
return SUCCESS;
}
static ERRORTYPE createDemuxChn(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
BOOL nSuccessFlag = FALSE;
configDmxChnAttr(pDemux2Vdec2VoData);
pDemux2Vdec2VoData->mDmxChn = 0;
while (pDemux2Vdec2VoData->mDmxChn < DEMUX_MAX_CHN_NUM)
{
ret = AW_MPI_DEMUX_CreateChn(pDemux2Vdec2VoData->mDmxChn, &pDemux2Vdec2VoData->mDmxChnAttr);
if (SUCCESS == ret)
{
nSuccessFlag = TRUE;
alogd("create demux channel[%d] success!", pDemux2Vdec2VoData->mDmxChn);
break;
}
else if (ERR_DEMUX_EXIST == ret)
{
alogd("demux channel[%d] is exist, find next!", pDemux2Vdec2VoData->mDmxChn);
pDemux2Vdec2VoData->mDmxChn++;
}
else
{
alogd("create demux channel[%d] ret[0x%x]!", pDemux2Vdec2VoData->mDmxChn, ret);
break;
}
}
if (FALSE == nSuccessFlag)
{
pDemux2Vdec2VoData->mDmxChn = MM_INVALID_CHN;
aloge("fatal error! create demux channel fail!");
return FAILURE;
}
else
{
MPPCallbackInfo cbInfo;
cbInfo.cookie = (void*)pDemux2Vdec2VoData;
cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper;
AW_MPI_DEMUX_RegisterCallback(pDemux2Vdec2VoData->mDmxChn, &cbInfo);
return SUCCESS;
}
}
static ERRORTYPE ConfigVdecChnAttr(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData, DEMUX_VIDEO_STREAM_INFO_S *pStreamInfo)
{
memset(&pDemux2Vdec2VoData->mVdecChnAttr, 0, sizeof(VDEC_CHN_ATTR_S));
pDemux2Vdec2VoData->mVdecChnAttr.mPicWidth = pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputWidth;
pDemux2Vdec2VoData->mVdecChnAttr.mPicHeight = pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputHeight;
pDemux2Vdec2VoData->mVdecChnAttr.mInitRotation = pDemux2Vdec2VoData->mConfigPara.mInitRotation;
pDemux2Vdec2VoData->mVdecChnAttr.mOutputPixelFormat = pDemux2Vdec2VoData->mConfigPara.mUserSetPixelFormat;
pDemux2Vdec2VoData->mVdecChnAttr.mType = pStreamInfo->mCodecType;
pDemux2Vdec2VoData->mVdecChnAttr.mVdecVideoAttr.mSupportBFrame = 0; //1
pDemux2Vdec2VoData->mVdecChnAttr.mVdecVideoAttr.mMode = VIDEO_MODE_FRAME;
return SUCCESS;
}
static ERRORTYPE createVdecChn(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
BOOL nSuccessFlag = FALSE;
if ((pDemux2Vdec2VoData->mDemuxMediaInfo.mVideoNum >0 ) && !(pDemux2Vdec2VoData->mDmxChnAttr.mDemuxDisableTrack & DEMUX_DISABLE_VIDEO_TRACK))
{
ConfigVdecChnAttr(pDemux2Vdec2VoData, &pDemux2Vdec2VoData->mDemuxMediaInfo.mVideoStreamInfo[pDemux2Vdec2VoData->mDemuxMediaInfo.mVideoIndex]);
pDemux2Vdec2VoData->mVdecChn = 0;
while (pDemux2Vdec2VoData->mVdecChn < VDEC_MAX_CHN_NUM)
{
ret = AW_MPI_VDEC_CreateChn(pDemux2Vdec2VoData->mVdecChn, &pDemux2Vdec2VoData->mVdecChnAttr);
if (SUCCESS == ret)
{
nSuccessFlag = TRUE;
alogd("create vdec channel[%d] success!", pDemux2Vdec2VoData->mVdecChn);
break;
}
else if (ERR_VDEC_EXIST == ret)
{
alogd("vdec channel[%d] is exist, find next!", pDemux2Vdec2VoData->mVdecChn);
pDemux2Vdec2VoData->mVdecChn++;
}
else
{
alogd("create vdec channel[%d] ret[0x%x]!", pDemux2Vdec2VoData->mVdecChn, ret);
break;
}
}
if (FALSE == nSuccessFlag)
{
pDemux2Vdec2VoData->mVdecChn = MM_INVALID_CHN;
aloge("fatal error! create vdec channel fail!");
return FAILURE;
}
else
{
if (pDemux2Vdec2VoData->mConfigPara.mVeFreq)
{
alogd("vdec set ve freq %d MHz", pDemux2Vdec2VoData->mConfigPara.mVeFreq);
AW_MPI_VDEC_SetVEFreq(pDemux2Vdec2VoData->mVdecChn, pDemux2Vdec2VoData->mConfigPara.mVeFreq);
}
alogd("add call back");
MPPCallbackInfo cbInfo;
cbInfo.cookie = (void*)pDemux2Vdec2VoData;
cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper;
AW_MPI_VDEC_RegisterCallback(pDemux2Vdec2VoData->mVdecChn, &cbInfo);
AW_MPI_VDEC_ForceFramePackage(pDemux2Vdec2VoData->mVdecChn, pDemux2Vdec2VoData->mConfigPara.mbForceFramePackage);
return SUCCESS;
}
}
else
{
return FAILURE;
}
}
static ERRORTYPE createVoChn(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
BOOL nSuccessFlag = FALSE;
pDemux2Vdec2VoData->mVoDev = 0;
pDemux2Vdec2VoData->mUILayer = HLAY(2, 0);
AW_MPI_VO_Enable(pDemux2Vdec2VoData->mVoDev);
AW_MPI_VO_AddOutsideVideoLayer(pDemux2Vdec2VoData->mUILayer);
AW_MPI_VO_CloseVideoLayer(pDemux2Vdec2VoData->mUILayer);//close ui layer.
VO_PUB_ATTR_S spPubAttr;
AW_MPI_VO_GetPubAttr(pDemux2Vdec2VoData->mVoDev, &spPubAttr);
spPubAttr.enIntfType = VO_INTF_LCD;
spPubAttr.enIntfSync = VO_OUTPUT_NTSC;
AW_MPI_VO_SetPubAttr(pDemux2Vdec2VoData->mVoDev, &spPubAttr);
//enable vo layer
int hlay0 = 0;
while (hlay0 < VO_MAX_LAYER_NUM)
{
if (SUCCESS == AW_MPI_VO_EnableVideoLayer(hlay0))
{
break;
}
hlay0++;
}
if (hlay0 >= VO_MAX_LAYER_NUM)
{
aloge("fatal error! enable video layer fail!");
pDemux2Vdec2VoData->mVoLayer = MM_INVALID_DEV;
AW_MPI_VO_RemoveOutsideVideoLayer(pDemux2Vdec2VoData->mUILayer);
AW_MPI_VO_Disable(pDemux2Vdec2VoData->mVoDev);
return FAILURE;
}
pDemux2Vdec2VoData->mVoLayer = hlay0;
AW_MPI_VO_GetVideoLayerAttr(pDemux2Vdec2VoData->mVoLayer, &pDemux2Vdec2VoData->mVoLayerAttr);
pDemux2Vdec2VoData->mVoLayerAttr.stDispRect.X = pDemux2Vdec2VoData->mConfigPara.mDisplayX;
pDemux2Vdec2VoData->mVoLayerAttr.stDispRect.Y = pDemux2Vdec2VoData->mConfigPara.mDisplayY;
pDemux2Vdec2VoData->mVoLayerAttr.stDispRect.Width = pDemux2Vdec2VoData->mConfigPara.mDisplayWidth;
pDemux2Vdec2VoData->mVoLayerAttr.stDispRect.Height = pDemux2Vdec2VoData->mConfigPara.mDisplayHeight;
pDemux2Vdec2VoData->mVoLayerAttr.enPixFormat = pDemux2Vdec2VoData->mConfigPara.mUserSetPixelFormat;
AW_MPI_VO_SetVideoLayerAttr(pDemux2Vdec2VoData->mVoLayer, &pDemux2Vdec2VoData->mVoLayerAttr);
pDemux2Vdec2VoData->mVoChn = 0;
while (pDemux2Vdec2VoData->mVoChn < VO_MAX_CHN_NUM)
{
ret = AW_MPI_VO_CreateChn(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn);
if (SUCCESS == ret)
{
nSuccessFlag = TRUE;
alogd("create vo channel[%d] success!", pDemux2Vdec2VoData->mVoChn);
break;
}
else if(ERR_VO_CHN_NOT_DISABLE == ret)
{
alogd("vo channel[%d] is exist, find next!", pDemux2Vdec2VoData->mVoChn);
pDemux2Vdec2VoData->mVoChn++;
}
else
{
alogd("create vo channel[%d] ret[0x%x]!", pDemux2Vdec2VoData->mVoChn, ret);
break;
}
}
if (FALSE == nSuccessFlag)
{
pDemux2Vdec2VoData->mVoChn = MM_INVALID_CHN;
aloge("fatal error! create vo channel fail!");
return FAILURE;
}
else
{
MPPCallbackInfo cbInfo;
cbInfo.cookie = (void*)pDemux2Vdec2VoData;
cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper;
AW_MPI_VO_RegisterCallback(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn, &cbInfo);
AW_MPI_VO_SetChnDispBufNum(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn, 2);
return SUCCESS;
}
}
static ERRORTYPE prepare(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
DEMUX_MEDIA_INFO_S DemuxMediaInfo = {0};
if (createDemuxChn(pDemux2Vdec2VoData) != SUCCESS)
{
aloge("create demux chn fail");
return FAILURE;
}
alogd("prepare");
if (AW_MPI_DEMUX_GetMediaInfo(pDemux2Vdec2VoData->mDmxChn, &DemuxMediaInfo) != SUCCESS)
{
aloge("fatal error! get media info fail!");
return FAILURE;
}
if ((DemuxMediaInfo.mVideoNum >0 && DemuxMediaInfo.mVideoIndex >= DemuxMediaInfo.mVideoNum)
|| (DemuxMediaInfo.mAudioNum >0 && DemuxMediaInfo.mAudioIndex >= DemuxMediaInfo.mAudioNum)
|| (DemuxMediaInfo.mSubtitleNum >0 && DemuxMediaInfo.mSubtitleIndex >= DemuxMediaInfo.mSubtitleNum))
{
alogd("fatal error, trackIndex wrong! [%d][%d],[%d][%d],[%d][%d]",
DemuxMediaInfo.mVideoNum, DemuxMediaInfo.mVideoIndex, DemuxMediaInfo.mAudioNum, DemuxMediaInfo.mAudioIndex, DemuxMediaInfo.mSubtitleNum, DemuxMediaInfo.mSubtitleIndex);
return FAILURE;
}
memcpy(&pDemux2Vdec2VoData->mDemuxMediaInfo, &DemuxMediaInfo, sizeof(DEMUX_MEDIA_INFO_S));
pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputWidth = DemuxMediaInfo.mVideoStreamInfo[0].mWidth;
pDemux2Vdec2VoData->mConfigPara.mMaxVdecOutputHeight = DemuxMediaInfo.mVideoStreamInfo[0].mHeight;
if (DemuxMediaInfo.mVideoNum >0)
{
ret = createVdecChn(pDemux2Vdec2VoData);
if (ret == SUCCESS)
{
alogd("bind demux & vdec");
MPP_CHN_S DmxChn = {MOD_ID_DEMUX, 0, pDemux2Vdec2VoData->mDmxChn};
MPP_CHN_S VdecChn = {MOD_ID_VDEC, 0, pDemux2Vdec2VoData->mVdecChn};
AW_MPI_SYS_Bind(&DmxChn, &VdecChn);
}
else
{
alogd("create vdec chn fail");
return FAILURE;
}
ret = createVoChn(pDemux2Vdec2VoData);
if (ret == SUCCESS)
{
alogd("bind vdec & vo");
MPP_CHN_S VdecChn = {MOD_ID_VDEC, 0, pDemux2Vdec2VoData->mVdecChn};
MPP_CHN_S VoChn = {MOD_ID_VOU, pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn};
AW_MPI_SYS_Bind(&VdecChn, &VoChn);
}
else
{
alogd("create vo chn fail");
return FAILURE;
}
pDemux2Vdec2VoData->mClockChnAttr.nWaitMask |= 1<<CLOCK_PORT_VIDEO; //becareful this is too important!!!
ret = createClockChn(pDemux2Vdec2VoData);
if (ret == SUCCESS)
{
alogd("bind clock & demux");
MPP_CHN_S ClockChn = {MOD_ID_CLOCK, 0, pDemux2Vdec2VoData->mClockChn};
MPP_CHN_S DmxChn = {MOD_ID_DEMUX, 0, pDemux2Vdec2VoData->mDmxChn};
MPP_CHN_S VoChn = {MOD_ID_VOU, pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn};
AW_MPI_SYS_Bind(&ClockChn, &DmxChn);
AW_MPI_SYS_Bind(&ClockChn, &VoChn);
}
else
{
alogd("create clock chn fail");
return FAILURE;
}
return SUCCESS;
}
else
{
return FAILURE;
}
}
static ERRORTYPE start(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
alogd("start stream");
AW_MPI_CLOCK_Start(pDemux2Vdec2VoData->mClockChn);
if (pDemux2Vdec2VoData->mVdecChn >= 0)
{
AW_MPI_VDEC_StartRecvStream(pDemux2Vdec2VoData->mVdecChn);
}
if ((pDemux2Vdec2VoData->mVoLayer >= 0) && (pDemux2Vdec2VoData->mVoChn >= 0))
{
AW_MPI_VO_StartChn(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn);
}
ret = AW_MPI_DEMUX_Start(pDemux2Vdec2VoData->mDmxChn);
return ret;
}
static ERRORTYPE pauseTranse(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
if (pDemux2Vdec2VoData->mDmxChn >= 0)
{
AW_MPI_DEMUX_Pause(pDemux2Vdec2VoData->mDmxChn);
}
if (pDemux2Vdec2VoData->mVdecChn >= 0)
{
AW_MPI_VDEC_Pause(pDemux2Vdec2VoData->mVdecChn);
}
if (pDemux2Vdec2VoData->mClockChn >= 0)
{
AW_MPI_CLOCK_Pause(pDemux2Vdec2VoData->mClockChn);
}
if ((pDemux2Vdec2VoData->mVoLayer >= 0) && (pDemux2Vdec2VoData->mVoChn >= 0))
{
AW_MPI_VO_PauseChn(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn);
}
return SUCCESS;
}
static ERRORTYPE stop(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
//vo stop must before vdec stop (when vo stop, will return buffer to vdec, just all buffer sync)
if ((pDemux2Vdec2VoData->mVoLayer >=0) && (pDemux2Vdec2VoData->mVoChn >= 0))
{
alogd("stop vo chn");
AW_MPI_VO_StopChn(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn);
}
if (pDemux2Vdec2VoData->mVdecChn >= 0)
{
AW_MPI_VDEC_StopRecvStream(pDemux2Vdec2VoData->mVdecChn);
}
ret = AW_MPI_DEMUX_Stop(pDemux2Vdec2VoData->mDmxChn);
AW_MPI_CLOCK_Stop(pDemux2Vdec2VoData->mClockChn);
return ret;
}
static ERRORTYPE seekto(SAMPLE_DEMUX2VDEC2VO_S *pDemux2Vdec2VoData)
{
ERRORTYPE ret;
alogd("seek to");
ret = AW_MPI_DEMUX_Seek(pDemux2Vdec2VoData->mDmxChn, pDemux2Vdec2VoData->mConfigPara.seekTime);
if (pDemux2Vdec2VoData->mVdecChn >= 0)
{
AW_MPI_VDEC_SetStreamEof(pDemux2Vdec2VoData->mVdecChn, 0);
}
if ((pDemux2Vdec2VoData->mVoLayer >= 0) && (pDemux2Vdec2VoData->mVoChn >= 0))
{
AW_MPI_VO_SetStreamEof(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn, 0);
}
if (pDemux2Vdec2VoData->mVdecChn >= 0)
{
AW_MPI_VDEC_Seek(pDemux2Vdec2VoData->mVdecChn);
}
if ((pDemux2Vdec2VoData->mVoLayer >= 0) && (pDemux2Vdec2VoData->mVoChn >= 0))
{
AW_MPI_VO_Seek(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn);
}
return ret;
}
static void handle_exit(int signo)
{
alogd("user want to exit!");
if(NULL != pDemux2Vdec2VoData)
{
cdx_sem_up(&pDemux2Vdec2VoData->mSemExit);
}
}
int main(int argc, char** argv)
{
int result = -1;
//int ret = 0;
if (InitDemux2Vdec2VoData() != SUCCESS)
{
return -1;
}
cdx_sem_init(&pDemux2Vdec2VoData->mSemExit, 0);
char *pConfFilePath = NULL;
if(argc > 1)
{
if (parseCmdLine(pDemux2Vdec2VoData, argc, argv) != 0)
{
goto err_out_0;
}
pConfFilePath = pDemux2Vdec2VoData->mCmdLinePara.mConfigFilePath;
}
else
{
pConfFilePath = NULL;
}
if (loadConfigPara(pDemux2Vdec2VoData, pConfFilePath) != SUCCESS)
{
aloge("no config file or parse conf file fail");
goto err_out_0;
}
/* register process function for SIGINT, to exit program. */
if (signal(SIGINT, handle_exit) == SIG_ERR)
aloge("can't catch SIGSEGV");
pDemux2Vdec2VoData->srcFd = open(pDemux2Vdec2VoData->mConfigPara.srcFile, O_RDONLY);
if (pDemux2Vdec2VoData->srcFd < 0)
{
aloge("ERROR: cannot open video src file");
goto err_out_0;
}
pDemux2Vdec2VoData->mSysConf.nAlignWidth = 32;
AW_MPI_SYS_SetConf(&pDemux2Vdec2VoData->mSysConf);
result = AW_MPI_SYS_Init();
if (SUCCESS != result)
{
goto err_out_0;
}
if (prepare(pDemux2Vdec2VoData) != SUCCESS)
{
result = -1;
aloge("prepare failed");
goto err_out_1;
}
if (pDemux2Vdec2VoData->mConfigPara.seekTime > 0)
{
seekto(pDemux2Vdec2VoData);
}
if (start(pDemux2Vdec2VoData) != SUCCESS)
{
result = -1;
aloge("start play fail");
goto err_out_2;
}
if (pDemux2Vdec2VoData->mConfigPara.mTestDuration > 0)
{
cdx_sem_down_timedwait(&pDemux2Vdec2VoData->mSemExit, pDemux2Vdec2VoData->mConfigPara.mTestDuration*1000);
}
else
{
cdx_sem_down(&pDemux2Vdec2VoData->mSemExit);
}
pDemux2Vdec2VoData->mOverFlag = TRUE;
alogw("over");
if (stop(pDemux2Vdec2VoData) != SUCCESS)
{
result = -1;
alogw("stop fail");
}
result = 0;
err_out_2:
//vo stop/destroy must before vdec stop (when vo destroy, will return buffer to vdec(2 frames), just all buffer sync)
if (pDemux2Vdec2VoData->mVoLayer >= 0)
{
if (pDemux2Vdec2VoData->mVoChn >= 0)
{
AW_MPI_VO_DestroyChn(pDemux2Vdec2VoData->mVoLayer, pDemux2Vdec2VoData->mVoChn);
pDemux2Vdec2VoData->mVoChn = MM_INVALID_CHN;
}
AW_MPI_VO_DisableVideoLayer(pDemux2Vdec2VoData->mVoLayer);
//wait hwdisplay kernel driver processing frame buffer, must guarantee this! Then vdec can free frame buffer.
usleep(50*1000);
pDemux2Vdec2VoData->mVoLayer = MM_INVALID_CHN;
AW_MPI_VO_RemoveOutsideVideoLayer(pDemux2Vdec2VoData->mUILayer);
AW_MPI_VO_Disable(pDemux2Vdec2VoData->mVoDev);
pDemux2Vdec2VoData->mVoDev = MM_INVALID_DEV;
}
if (pDemux2Vdec2VoData->mVdecChn >= 0)
{
int ret = AW_MPI_VDEC_DestroyChn(pDemux2Vdec2VoData->mVdecChn);
alogd("ret = %d", ret);
}
if (pDemux2Vdec2VoData->mDmxChn >= 0)
{
AW_MPI_DEMUX_DestroyChn(pDemux2Vdec2VoData->mDmxChn);
}
if (pDemux2Vdec2VoData->mClockChn >= 0)
{
AW_MPI_CLOCK_DestroyChn(pDemux2Vdec2VoData->mClockChn);
}
err_out_1:
//exit mpp system
AW_MPI_SYS_Exit();
close(pDemux2Vdec2VoData->srcFd);
err_out_0:
cdx_sem_deinit(&pDemux2Vdec2VoData->mSemExit);
free(pDemux2Vdec2VoData);
pDemux2Vdec2VoData = NULL;
int disp_fd = open("/dev/fb0", O_RDWR);
if (disp_fd < 0)
{
alogd("[%s] open fb0 fail!", LOG_TAG);
}
printf("%s", ((0 == result) ? "PASS" : "FAIL"));
return result;
}