📄 maimp4demux.c
字号:
}
g_bVDiscon=M_TRUE;
}
else
{
g_uiVideoSampleNum++;
uiVideoSamplesLeft--;
}
} //end of video sample if
else if(index == AUDIO && uiAudioSamplesLeft > 0)
{
if (g_pfOutputAudioGetBuf)
{
MAICompBuffer_t *pBufferInfo;
unsigned int sampleread=0;
m_bool bNewPTS=M_TRUE;
sample_info(g_uiAudioSampleNum,index,&samplesize,&filepos);
scount = sample_timming_info(g_uiAudioSampleNum,index,&apts);
bIdle=M_FALSE;
bAudioPTSKnown=M_TRUE;
g_tLastPTS=apts;
DPRINTF((M_TEXT("MP4DEMUX: g_uiAudioSampleNum %d, apts %d ,scount %d\n"),g_uiAudioSampleNum,apts,scount));
if (MAI_STATUS_OK!=inputseek(filepos))
break;
while (sampleread<samplesize) /* we may do multiple Get/PutBuffer to output sample */
{
unsigned int bytestoread;
PUTPRINTF((M_TEXT("MP4DEMUX: OutputAudioGetBuf()\n")));
if (MAI_STATUS_OK!=g_pfOutputAudioGetBuf(g_hOutputAudioOwner,&pBufferInfo))
break;
pBufferInfo->uiDataSize=0;
bytestoread=(samplesize-sampleread);
if (bytestoread>pBufferInfo->uiBufSize)
bytestoread=pBufferInfo->uiBufSize;
if (MAI_STATUS_OK!=inputread(pBufferInfo->pBuffer, bytestoread, &bytesread))
{
if (pBufferInfo) /* return the output buffer */
g_pfOutputAudioPutBuf(g_hOutputAudioOwner, pBufferInfo);
break;
}
//fwrite(pBufferInfo->pBuffer+sampleread,1,bytesread,fp_video);
pBufferInfo->dwFlags |= MAICOMPBUF_FLAG_AUDIO;
if (bNewPTS)
{
TIME_LOHI_TO_MAITIME(apts, 0, pBufferInfo->tTimeStamp);
pBufferInfo->dwFlags |= MAICOMPBUF_FLAG_PTS;
bNewPTS=M_FALSE;
}
if (g_bADiscon) /* See if stream discontinuity */
{
pBufferInfo->dwFlags |= MAICOMPBUF_FLAG_DATADISCON;
g_bADiscon = M_FALSE;
PUTPRINTF((M_TEXT("MP4DEMUX: g_uiAudioSampleNum=%d apts=%d DATADISCON\n"),
g_uiAudioSampleNum,apts));
}
pBufferInfo->uiDataSize = bytesread;
PUTPRINTF((M_TEXT("MP4DEMUX: OutputAudioPutBuf(DataSize=%d PTS=%d Flags=0x%X)\n"),
pBufferInfo->uiDataSize,MAITIME_LO32(pBufferInfo->tTimeStamp)));
g_pfOutputAudioPutBuf(g_hOutputAudioOwner, pBufferInfo);
pBufferInfo=NULL;
sampleread+=bytesread;
}
}
if ((g_uiCurrentSpeed&MAI_SPEED_REVERSEFLAG)!=0)
{
if (g_uiVideoSampleNum<uiAudioSampleInc)
{
g_uiAudioSampleNum=0;
uiAudioSamplesLeft=0;
}
else
{
g_uiAudioSampleNum-=uiAudioSampleInc;
uiAudioSamplesLeft+=uiAudioSampleInc;
}
g_bADiscon=M_TRUE;
}
else
{
g_uiAudioSampleNum++;
uiAudioSamplesLeft--;
}
}
if (bIdle)
{
MAIOSSleep(200); /* prevent spinning when reaching last packet */
}
} /* while loop to process samples */
}
else
{
MAIOSSleep(200); /* prevent spinning in unsupported states */
}
} /* main while loop */
if (g_eCompState!=MAI_RUNSTATE_NONE
&& (g_eCompState&(MAI_RUNSTATE_INIT|MAI_RUNSTATE_DESTROYING))==0)
_ChangeState(hComp, MAI_RUNSTATE_INIT);
_endprocessing(hComp);
APIPRINTF((M_TEXT("MP4DEMUX: DemuxThread() exit\n")));
return 0;
}
static MAIStatus_e MAIMP4Demux_GetBuffer(MAICompHandle_t hComp,MAICompBuffer_t **ppBufferInfo)
{
MAICompBuffer_t *pFreeBufferInfo=NULL;
MAIStatus_e eStatus=MAI_STATUS_NOBUFAVAIL;
PUTPRINTF((M_TEXT("MP4DEMUX: MAIDecoder_GetBuffer\n")));
if ((g_eCompState&(MAI_RUNSTATE_DESTROYING|MAI_RUNSTATE_STOPPED))!=0)
eStatus=MAI_STATUS_STOPPED;
else
{
/* get an empty buffer from the buffer pool */
eStatus=MAICompBufferPoolGet(g_hInBufferPool, MAI_BUFSTATE_EMPTY, &pFreeBufferInfo, MAI_TIMEOUT_INFINITE);
if ((g_eCompState&(MAI_RUNSTATE_DESTROYING|MAI_RUNSTATE_STOPPED))!=0)
{
if (eStatus==MAI_STATUS_OK) /* put back the buffer since we're terminating */
eStatus=MAICompBufferPoolPut(g_hInBufferPool, MAI_BUFSTATE_EMPTY, pFreeBufferInfo, MAI_TIMEOUT_INFINITE);
eStatus=MAI_STATUS_STOPPED;
}
else if (eStatus==MAI_STATUS_OK)
*ppBufferInfo = pFreeBufferInfo;
}
PUTPRINTF((M_TEXT("MP4DEMUX: MAIDecoder_GetBuffer() done: %d\n"), eStatus));
return eStatus;
}
static MAIStatus_e MAIMP4Demux_PutBuffer(MAICompHandle_t hComp,MAICompBuffer_t *pBufferInfo)
{
MAIStatus_e eStatus;
PUTPRINTF((M_TEXT("MP4DEMUX: MAIDecoder_PutBuffer() enter: size=%d pts=%d\n"), pBufferInfo->uiDataSize, (unsigned int)pBufferInfo->tTimeStamp));
if ((pBufferInfo->dwFlags & MAICOMPBUF_FLAG_EOS)!=0)
{
APIPRINTF((M_TEXT("MP4DEMUX: MAIDecoder_PutBuffer() MAICOMPBUF_FLAG_EOS\n")));
}
/* put a filled buffer back into the buffer pool */
eStatus=MAICompBufferPoolPut(g_hInBufferPool, MAI_BUFSTATE_FILLED, pBufferInfo, MAI_TIMEOUT_INFINITE);
PUTPRINTF((M_TEXT("MP4DEMUX: MAIDecoder_PutBuffer() done: %d\n"), eStatus));
return eStatus;
}
static MAIStatus_e MAICompConnect(MAICompHandle_t hComp, MAICompHandle_t hCompToConnect, MAICompDirection_e eDirection, MAICompPinID_t uiPinID, MAIMediaType_t *pMediaType)
{
MAIStatus_e eStatus = MAI_STATUS_UNSUPPORTED;
APIPRINTF((M_TEXT("MP4DEMUX: MAICompConnect(hCompToConnect=%p, eDirection=%d)\n"),
hCompToConnect, eDirection));
if (eDirection==MAICOMP_DIR_INPUT)
{
MAICompHandleInfo_t *pConnectToCompInfo=(MAICompHandleInfo_t *)hCompToConnect;
if (!pConnectToCompInfo)
{
/* no handle, so we disconnect */
g_hReaderComp=M_NULL;
eStatus=MAI_STATUS_OK;
}
else if ((pConnectToCompInfo->Info.eType&(MAICOMP_TYPE_READER|MAICOMP_TYPE_CAPTURE))==0)
eStatus=MAI_STATUS_BADARG; /* not a reader/capture source filter */
else if (!pConnectToCompInfo->pfReadBuffer)
eStatus=MAI_STATUS_BADARG; /* no ReadBuffer interface to pull data from */
else
{
g_hReaderComp=hCompToConnect; /* save the reader handle */
/* start processing - this will attempt open the file (read headers, etc.) */
eStatus=_startprocessing(hComp);
if (eStatus!=MAI_STATUS_OK && eStatus!=MAI_STATUS_ALREADYOPEN)
{
APIPRINTF((M_TEXT("MP4DEMUX: MAICompConnect(): _startprocessing failed: eStatus=0x%08X\n"), eStatus));
}
else
{
APIPRINTF((M_TEXT("MP4DEMUX: MAICompConnect(): _startprocessing success\n")));
}
}
}
return eStatus;
}
static MAIStatus_e MAICompSendCommand(MAICompHandle_t hComp, m_u32 uiCommand,
m_u32 uiParam1, m_u32 uiParam2, m_u32 uiParam3,
void *pUserInstance, MAITimeOut_t uiTimeOut)
{
MAIStatus_e eStatus = MAI_STATUS_OK;
switch (uiCommand)
{
case MAICOMP_CMD_SEEK:
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(MAICOMP_CMD_SEEK) %d %d\n"), uiParam1, uiParam2));
g_lSeekValue = (m_s32)uiParam2; /* position in the file to seek to */
g_eSeekType = (MAISeekType_e)uiParam1;
if (g_eCompState==MAI_RUNSTATE_NONE || g_eCompState==MAI_RUNSTATE_INIT)
{
/* not streaming, so it's safe to just do a seek */
eStatus=_streamseek(hComp, g_lSeekValue, g_eSeekType);
g_bSeekPending = M_FALSE;
}
else /* we're streaming, so Reads may be busy */
{
g_bSeekPending = M_TRUE; /* Flag a seek to the running thread */
//_ChangeState(hComp, MAI_RUNSTATE_SEEKING);
//eStatus=MAI_STATUS_WRONGSTATE; /* can't seek while thread is busy reading */
}
break;
case MAICOMP_CMD_PLAY:
if (g_eCompState!=MAI_RUNSTATE_NONE && g_eCompState!=MAI_RUNSTATE_INIT)
{
unsigned int uiTotalWait=0;
MAISpeed_e NewSpeed=(MAISpeed_e)uiParam1;
unsigned int uiNewPlayRate=NewSpeed&MAI_SPEED_RATEMASK;
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand() CMD_PLAY(speed=0x%X): state=0x%X CurrentSpeed=%d\n"),
uiParam1, g_eCompState, g_uiCurrentSpeed));
/* wait for completion of any special state transitions */
while ((g_eCompState&(MAI_RUNSTATE_STARTING|MAI_RUNSTATE_PAUSING|MAI_RUNSTATE_SEEKING|MAI_RUNSTATE_STOPPING))!=0
&& uiTotalWait<1000)
{
uiTotalWait+=200;
MAIOSSleep(200);
}
/* wait for any pending seeks */
while (g_bSeekPending && (g_eCompState&(MAI_RUNSTATE_PLAYING|MAI_RUNSTATE_PAUSED|MAI_RUNSTATE_SEEKING))!=0
&& uiTotalWait<10000)
{
uiTotalWait+=200;
MAIOSSleep(200);
}
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand() CMD_PLAY(): wait done: time=%d state=0x%X\n"),
uiTotalWait, g_eCompState));
if (uiNewPlayRate!=0 && NewSpeed!=MAI_SPEED_UNSPECIFIED)
{
g_uiNextSpeed=NewSpeed;
g_bSpeedChange=M_TRUE;
}
}
if (g_eCompState==MAI_RUNSTATE_PAUSED)
_ChangeState(hComp, MAI_RUNSTATE_PLAYING);
else if ((g_eCompState&(MAI_RUNSTATE_STOPPING|MAI_RUNSTATE_STOPPED))!=0)
{
_ChangeState(hComp, MAI_RUNSTATE_STARTING);
if (g_hInBufferPool!=M_HANDLE_INVALID)
{
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(MAICOMP_CMD_PLAY) ClearAbort(In)\n")));
MAICompBufferPoolClearAbort(g_hInBufferPool);
}
}
break;
case MAICOMP_CMD_PAUSE:
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(MAICOMP_CMD_PAUSE) enter: state=0x%X\n"), g_eCompState));
if ((g_eCompState&(MAI_RUNSTATE_PLAYING|MAI_RUNSTATE_PAUSING))!=0)
{
unsigned int uiTotalWait=0;
if (g_hInBufferPool!=M_HANDLE_INVALID)
{
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(MAICOMP_CMD_PAUSE) ClearAbort(In)\n")));
MAICompBufferPoolClearAbort(g_hInBufferPool);
}
_ChangeState(hComp, MAI_RUNSTATE_PAUSING);
while ((g_eCompState&MAI_RUNSTATE_PAUSED)==0 && uiTotalWait<uiTimeOut)
{
uiTotalWait+=200;
MAIOSSleep(200);
}
}
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(MAICOMP_CMD_PAUSE) done: state=0x%X\n"),g_eCompState));
break;
case MAICOMP_CMD_STOP:
APIPRINTF(("MP4DEMUX: SendCommand(MAICOMP_CMD_STOP)\n"));
if (g_eCompState!=MAI_RUNSTATE_NONE &&
(g_eCompState&(MAI_RUNSTATE_STARTING|MAI_RUNSTATE_PLAYING|MAI_RUNSTATE_PAUSING|MAI_RUNSTATE_PAUSED|MAI_RUNSTATE_STOPPING))!=0)
{
unsigned int uiTotalWait=0;
_ChangeState(hComp, MAI_RUNSTATE_STOPPING);
if (g_hInBufferPool!=M_HANDLE_INVALID)
{
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(MAICOMP_CMD_STOP) PoolAbort(In)\n")));
MAICompBufferPoolAbort(g_hInBufferPool, M_FALSE);
}
while ((g_eCompState&MAI_RUNSTATE_STOPPING)!=0 && uiTotalWait<uiTimeOut)
{
uiTotalWait+=200;
MAIOSSleep(200);
}
g_uiOffset=0;
}
else
{
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(MAICOMP_CMD_STOP) wrong state\n")));
eStatus=MAI_STATUS_WRONGSTATE;
}
break;
default:
APIPRINTF((M_TEXT("MP4DEMUX: SendCommand(%d) unsupported\n"), uiCommand));
eStatus=MAI_STATUS_UNSUPPORTED;
break;
}
return eStatus;
}
static MAIStatus_e MAICompGetParam(MAICompHandle_t hComp, unsigned int uiParam, void *pvParamData, unsigned int uiDataSize)
{
MAIStatus_e eStatus = MAI_STATUS_OK;
if (!pvParamData)
eStatus=MAI_STATUS_BADARG;
else
switch(uiParam)
{
case MAI_PARAM_PRIORITY:
*((unsigned int *)pvParamData) = g_uiThreadPriority;
break;
case MAI_PARAM_LOOP:
APIPRINTF((M_TEXT("MP4DEMUX: MAICompGetParam(MAI_PARAM_LOOP) bLoop=%d\n"), uiParam));
if (pvParamData && uiDataSize>=sizeof(m_bool)) /* make sure user supplies us a big enough buffer to return setting */
*((m_bool *)pvParamData)=g_bLooping;
else
eStatus=MAI_STATUS_BADARG;
break;
case MAI_PARAM_STREAMINDEX:
if (uiDataSize<sizeof(MAIParamStreamIndex_t))
eStatus=MAI_STATUS_BADARG; /* structure smaller than expected */
else
{
MAIParamStreamIndex_t *pStreamIndex=(MAIParamStreamIndex_t *)pvParamData;
unsigned int uiTotalIndexSize=sizeof(MAIParamStreamIndex_t);
if (g_bFileOpen)
{
uiTotalIndexSize+=sizeof(MAIParamStreamIndexEntry_t)*g_uiVideoSampleCount;
pStreamIndex->uiSize=uiTotalIndexSize;
if ((pStreamIndex->uiFlags&MAI_STREAMINDEX_FLAG_QUERYSIZE)!=0)
{
/* caller is just interested in the size of the memory required to hold the index */
eStatus=MAI_STATUS_OK;
}
else if (pStreamIndex->uiSize<uiTotalIndexSize)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -