📄 maimp4demux.c
字号:
{
pData = (m_u8 *) malloc(sizeof(m_u8) * 16*1024);
if(pData != NULL)
{
GetConfigInfo(pData,&lData);
pBufferInfo->uiDataSize = lData;
pBufferInfo->dwFlags = MAICOMPBUF_FLAG_NEWFORMAT;
pBufferInfo->tTimeStamp = 0;
memcpy(pBufferInfo->pBuffer, pData,lData);
APIPRINTF((M_TEXT("MP4Demux: Passing config data to the video decoder, data size %d\n"),lData));
g_pfOutputVideoPutBuf(g_hOutputVideoOwner,pBufferInfo);
free(pData);
}
}
}
}
//#define DUMP_OUTPUT
// Main working thread...
static m_u32 DemuxThread(MAIOSThread_t hThread, void *pUserData)
{
MAICompHandle_t hComp=(MAICompHandle_t)pUserData;
MAIStatus_e eStatus = MAI_STATUS_OK;
unsigned int codec_version=0;
unsigned int bytesread;
TRACK_TYPES index;
m_u32 filepos;
m_u32 samplesize;
m_u32 apts,vpts;
m_bool bAudioPTSKnown=M_FALSE, bVideoPTSKnown=M_FALSE;
long vsize = 0;
long scount;
APIPRINTF((M_TEXT("MP4DEMUX: DemuxThread() enter: State=%d Terminate=%d\n"), g_eCompState, g_bTerminate) );
#ifdef DUMP_OUTPUT
FILE *fp_audio,*fp_video;
fp_audio = fopen("audio.es","wb");
if(fp_audio == NULL)
{
DPRINTF((M_TEXT("could not open audio output file \n")));
return 1;
}
fp_video = fopen("video.es","wb");
if(fp_audio == NULL)
{
DPRINTF((M_TEXT("could not open video output file \n")));
return 1;
}
#endif
eStatus=_startprocessing(hComp);
if (eStatus!=MAI_STATUS_OK && eStatus!=MAI_STATUS_ALREADYOPEN)
{
APIPRINTF((M_TEXT("MP4DEMUX: DemuxThread(): _startprocessing failed: eStatus=0x%08X\n"), eStatus));
return 0;
}
APIPRINTF((M_TEXT("MP4DEMUX: Start of demux loop\n")));
while (g_eCompState!=MAI_RUNSTATE_NONE && g_eCompState!=MAI_RUNSTATE_DESTROYING)
{
if (g_eCompState==MAI_RUNSTATE_STOPPING)
_ChangeState(hComp, MAI_RUNSTATE_STOPPED);
if (g_eCompState==MAI_RUNSTATE_PAUSED || g_eCompState==MAI_RUNSTATE_STOPPED)
{
MAIOSSleep(200);
continue;
}
/* start of a new stream */
APIPRINTF((M_TEXT("MP4DEMUX: Start of New Stream\n")));
_ChangeState(hComp, MAI_RUNSTATE_STARTING);
APIPRINTF( (M_TEXT("MP4DEMUX: DemuxThread() Send SOS\n")) );
_SendProgressCB(hComp, MAI_PROGRESSFLAG_START);
_ReportStart(hComp); /* report Start of stream to engine */
if ((g_eCompState & (MAI_RUNSTATE_INIT|MAI_RUNSTATE_IDLE|MAI_RUNSTATE_PAUSING|MAI_RUNSTATE_PAUSED|MAI_RUNSTATE_STARTING|MAI_RUNSTATE_PLAYING)) != 0 )
{
unsigned int loop_count=0;
long uiVideoSamplesLeft=0, uiAudioSamplesLeft=0;
unsigned int uiVideoSampleInc=1, uiAudioSampleInc=1;
/* run demux loop */
if ((g_uiCurrentSpeed&MAI_SPEED_REVERSEFLAG)!=0)
{
uiAudioSamplesLeft = g_uiAudioSampleNum;
uiVideoSamplesLeft = g_uiVideoSampleNum;
}
else
{
uiAudioSamplesLeft = g_uiAudioSampleCount - g_uiAudioSampleNum;
uiVideoSamplesLeft = g_uiVideoSampleCount - g_uiVideoSampleNum;
}
APIPRINTF((M_TEXT("MP4DEMUX: total video samples %d, audio samples %d \n"),uiVideoSamplesLeft,uiAudioSamplesLeft));
ConfigDecoders();
/* loop while we still have audio or video packets left over */
while ( (g_eCompState & (MAI_RUNSTATE_INIT|MAI_RUNSTATE_IDLE|MAI_RUNSTATE_PAUSING|MAI_RUNSTATE_PAUSED|MAI_RUNSTATE_STARTING|MAI_RUNSTATE_PLAYING)) != 0)
{
m_bool bIdle=M_TRUE;
loop_count++;
/* See if a speed change is requested */
if (g_bSpeedChange)
{
g_bSpeedChange=M_FALSE;
g_uiPlaySleep=0; /* default to no sleeps */
if (g_uiCurrentSpeed!=g_uiNextSpeed)
{
/* speed has changed */
if ((g_uiNextSpeed&MAI_SPEED_REVERSEFLAG)!=0)
{
unsigned int uiPlayRate=(g_uiNextSpeed==MAI_SPEED_UNSPECIFIED)?MAI_SPEED_NORMAL:(g_uiNextSpeed&MAI_SPEED_RATEMASK);
/* pick a reasonable sleep time: (spacing_in_ms*MAI_SPEED_NORMAL)/uiPlayRate */
g_uiPlaySleep=(60*MAI_SPEED_NORMAL)/uiPlayRate;
if (g_uiPlaySleep>1000)
g_uiPlaySleep=1000;
if (g_uiAudioSampleNum>2)
g_uiAudioSampleNum-=2;
else
g_uiAudioSampleNum = 0;
if (g_uiVideoSampleNum>2)
g_uiVideoSampleNum-=2;
else
g_uiVideoSampleNum = 0;
}
if (g_uiAudioSampleCount)
{
/* make sure audio is synced up with video sample position */
g_uiAudioSampleNum=time_to_sample(AUDIO, vpts+AUDIO_READ_AHEAD); // DARRELL
apts=vpts;
}
/* check for direction change */
if ((g_uiNextSpeed&MAI_SPEED_REVERSEFLAG)!=(g_uiCurrentSpeed&MAI_SPEED_REVERSEFLAG))
{
/* codecs must treat direction change as a discontinuity */
g_bVDiscon=M_TRUE;
g_bADiscon=M_TRUE;
}
/* update Samples Left variables */
if ((g_uiNextSpeed&MAI_SPEED_REVERSEFLAG)!=0)
{
uiAudioSamplesLeft = g_uiAudioSampleNum;
uiVideoSamplesLeft = g_uiVideoSampleNum;
}
else
{
uiAudioSamplesLeft = g_uiAudioSampleCount - g_uiAudioSampleNum;
uiVideoSamplesLeft = g_uiVideoSampleCount - g_uiVideoSampleNum;
}
g_uiCurrentSpeed=g_uiNextSpeed;
}
}
/* See if a seek is pending */
if (g_bSeekPending)
{
if (_streamseek(hComp, g_lSeekValue, g_eSeekType)==MAI_STATUS_OK)
{
g_bVDiscon=M_TRUE;
g_bADiscon=M_TRUE;
}
if ((g_uiCurrentSpeed&MAI_SPEED_REVERSEFLAG)!=0)
{
uiAudioSamplesLeft = g_uiAudioSampleNum;
uiVideoSamplesLeft = g_uiVideoSampleNum;
}
else
{
uiAudioSamplesLeft = g_uiAudioSampleCount - g_uiAudioSampleNum;
uiVideoSamplesLeft = g_uiVideoSampleCount - g_uiVideoSampleNum;
}
bAudioPTSKnown = 0;
bVideoPTSKnown = 0;
g_bSeekPending = M_FALSE;
g_eEOS=EOS_NONE;
_ReportStart(hComp); /* report Start of stream to engine */
}
if ((g_eCompState&(MAI_RUNSTATE_PAUSED|MAI_RUNSTATE_PAUSING))!=0)
{
_ChangeState(hComp, MAI_RUNSTATE_PAUSED);
MAIOSSleep(200);
continue;
}
if ((!g_pfOutputAudioGetBuf || uiAudioSamplesLeft==0) && (!g_pfOutputVideoGetBuf || uiVideoSamplesLeft==0))
{
m_bool bPausingAtEOS=M_FALSE;
/* no more data to read - must be EOS */
if ((g_eCompState&(MAI_RUNSTATE_INIT|MAI_RUNSTATE_STARTING|MAI_RUNSTATE_PLAYING)) != 0)
{
APIPRINTF(( M_TEXT("MP4DEMUX: Pausing at EOS\n") ));
_ChangeState(hComp, MAI_RUNSTATE_PAUSING); /* enter pause since we can't read past EOS */
bPausingAtEOS=M_TRUE;
}
_ReportEOS(hComp);
if (g_bLooping)
{
APIPRINTF(( M_TEXT("MP4DEMUX: Looping at EOS\n") ));
if (bPausingAtEOS && (g_eCompState&(MAI_RUNSTATE_PLAYING|MAI_RUNSTATE_PAUSING))!=0)
_ChangeState(hComp, MAI_RUNSTATE_PAUSED); /* we should always be in paused state during seek */
else
bPausingAtEOS=M_FALSE;
APIPRINTF(( M_TEXT("MP4DEMUX: Looping set SeekPending(TRUE)\n") ));
g_bSeekPending = M_TRUE;
g_lSeekValue = 0; /* seek to beginning */
g_eSeekType = MAI_SEEKTYPE_ABS;
if (bPausingAtEOS)
_ChangeState(hComp, MAI_RUNSTATE_STARTING); /* we'll be starting up again after seek */
}
continue;
}
/* decide if we should read next audio or video packet */
DPRINTF((M_TEXT("MP4DEMUX: videonum=%d vpts=%d(%d) audionum=%d apts=%d(%d)\n"),
g_uiVideoSampleNum,vpts,bVideoPTSKnown,
g_uiAudioSampleNum,apts,bAudioPTSKnown));
if (!g_pfOutputAudioGetBuf) /* audio output not connected */
index = VIDEO;
else if (!g_pfOutputVideoGetBuf) /* video output not connected */
index = AUDIO;
else if ((g_uiCurrentSpeed&(MAI_SPEED_REVERSEFLAG|MAI_SPEED_RATEMASK))!=MAI_SPEED_NORMAL)
{
/* trick mode - so provide only Video */
index = VIDEO;
}
else if (bAudioPTSKnown && bVideoPTSKnown)
{
/* use PTS to determine which stream to read from next */
if (uiAudioSamplesLeft>0 && apts<(vpts+AUDIO_READ_AHEAD))
index = AUDIO;
else
index = VIDEO;
}
else
{
/* worst case, just cycle between audio and video packet reading - VERY inefficient! */
if(uiVideoSamplesLeft==0 ||
(uiAudioSamplesLeft>0 && (loop_count%2)))
index = AUDIO;
else
index = VIDEO;
}
if ((g_eCompState&MAI_RUNSTATE_STARTING)!=0 && (uiVideoSamplesLeft || uiAudioSamplesLeft))
{
g_eEOS=EOS_NONE; /* clear EOS, we have samples to play */
_ChangeState(hComp, MAI_RUNSTATE_PLAYING);
}
if(index == VIDEO && uiVideoSamplesLeft > 0)
{
if (g_pfOutputVideoGetBuf)
{
MAICompBuffer_t *pBufferInfo;
unsigned int sampleread=0;
m_bool bNewPTS=M_TRUE;
sample_info(g_uiVideoSampleNum,index,&samplesize,&filepos);
scount = sample_timming_info(g_uiVideoSampleNum,index,&vpts);
bIdle=M_FALSE;
bVideoPTSKnown=M_TRUE;
g_tLastPTS=vpts;
DPRINTF((M_TEXT("MP4DEMUX: g_uiVideoSampleNum=%d vpts=%d scount=%d samplesize=%d\n"),
g_uiVideoSampleNum,vpts,scount,samplesize));
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: OutputVideoGetBuf()\n")));
if (MAI_STATUS_OK!=g_pfOutputVideoGetBuf(g_hOutputVideoOwner,&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_pfOutputVideoPutBuf(g_hOutputVideoOwner, pBufferInfo);
}
break;
}
//fwrite(pBufferInfo->pBuffer+sampleread,1,bytesread,fp_video);
pBufferInfo->dwFlags |= MAICOMPBUF_FLAG_VIDEO;
if (bNewPTS)
{
TIME_LOHI_TO_MAITIME(vpts, 0, pBufferInfo->tTimeStamp);
pBufferInfo->dwFlags |= MAICOMPBUF_FLAG_PTS;
bNewPTS=M_FALSE;
}
if (g_bVDiscon) /* See if stream discontinuity */
{
PUTPRINTF((M_TEXT("MP4DEMUX: g_uiVideoSampleNum=%d vpts=%d DATADISCON\n"),
g_uiVideoSampleNum,vpts));
pBufferInfo->dwFlags |= MAICOMPBUF_FLAG_DATADISCON;
g_bVDiscon = M_FALSE;
}
pBufferInfo->uiDataSize = bytesread;
PUTPRINTF((M_TEXT("MP4DEMUX: OutputVideoPutBuf(DataSize=%d PTS=%d Flags=0x%X)\n"),
pBufferInfo->uiDataSize,MAITIME_LO32(pBufferInfo->tTimeStamp)));
g_pfOutputVideoPutBuf(g_hOutputVideoOwner, pBufferInfo);
pBufferInfo=NULL;
sampleread+=bytesread;
}
if (g_uiPlaySleep)
MAIOSSleep(g_uiPlaySleep);
}
else
{ // video decoder is not connected
#ifdef DUMP_OUTPUT
m_u8 *data_buffer;
sample_info(g_uiVideoSampleNum,index,&samplesize,&filepos);
scount = sample_timming_info(g_uiAudioSampleNum,index,&apts);
//DPRINTF((M_TEXT("MP4DEMUX: g_uiVideoSampleNum %d, vpts %d, scount %d\n"),g_uiVideoSampleNum,vpts,scount));
if(vsize+samplesize > 10000)
vsize = vsize;
if (MAI_STATUS_OK!=inputseek(filepos))
break;
data_buffer = (m_u8*) malloc(samplesize * sizeof(m_u8));
if(data_buffer == NULL) {
ERRORPRINTF((M_TEXT("MP4DEMUX: Could not allocate memory, sample size %d, sample num %d \n"),samplesize,g_uiVideoSampleNum));
_ChangeState(hComp, MAI_RUNSTATE_ERROR);
break;
}
if (MAI_STATUS_OK!=inputread(data_buffer, samplesize, &bytesread))
break;
fwrite(data_buffer,1,bytesread,fp_video);
vsize += bytesread;
if(data_buffer != NULL) {
free(data_buffer);
data_buffer = NULL;
}
#endif
}
if ((g_uiCurrentSpeed&MAI_SPEED_REVERSEFLAG)!=0)
{
if (g_uiVideoSampleNum<uiVideoSampleInc)
{
g_uiVideoSampleNum=0;
uiVideoSamplesLeft=0;
}
else
{
g_uiVideoSampleNum-=uiVideoSampleInc;
uiVideoSamplesLeft+=uiVideoSampleInc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -