📄 maimp4demux.c
字号:
/* setup progress info fields */
memset(&ProgressInfo, 0, sizeof(MAIProgressState_t));
ProgressInfo.uiFlags=MAI_PROGRESSFLAG_EOS;
if (g_pfOutputVideoGetBuf && g_pfOutputVideoPutBuf && g_uiVideoSampleCount)
ProgressInfo.uiFlags|=MAI_PROGRESSFLAG_VIDEO;
if (g_pfOutputAudioGetBuf && g_pfOutputAudioPutBuf && g_uiAudioSampleCount)
ProgressInfo.uiFlags|=MAI_PROGRESSFLAG_AUDIO;
ProgressInfo.hComp=hComp;
ProgressInfo.eCurrentState=g_eCompState;
ProgressInfo.tCurrentTime=g_tLastPTS;
/* make progress call */
g_pfProgressCB(hComp, MAI_PROGRESS_STREAM, &ProgressInfo, sizeof(ProgressInfo));
}
g_eEOS=EOS_DELIVERED;
}
return eStatus;
}
#ifdef FILESOURCE
/*
** Function: MAICompSetStream(hComp, uiStreamID, pszURI, eURIType, pMediaType)
** Descript: Set stream source.
*/
static MAIStatus_e MAICompSetStream(MAICompHandle_t hComp, unsigned int uiStreamID, MAIStr_t *pURI, MAIStrType_e eURIType, MAIMediaType_t *pMediaType)
{
MAIStatus_e eStatus = MAI_STATUS_OK;
if (!pURI)
{
_endprocessing(hComp);
inputclose(hComp);
if (g_bInit)
CloseParser();
g_bInit=M_FALSE;
}
else
{
/* did we receive stream mediatype info? */
if (pMediaType && (pMediaType->uiFlags&MAI_MTFLAG_TYPESTREAM)!=0 && pMediaType->uiSize>=sizeof(MAIMediaTypeStream_t))
{
MAIMediaTypeStream_t *pStreamInfo=(MAIMediaTypeStream_t *)pMediaType;
/* store mediatype info that may be passed from engine's prescan */
unsigned int uiMediaTypeSize=(pMediaType->uiSize>sizeof(MAIMediaTypeStream_t))?sizeof(MAIMediaTypeStream_t):pMediaType->uiSize;
if ((g_StreamInfo.uiFlags&MAI_STREAMMTFLAG_FORMATKNOWN)==0)
{
/* format not yet determined by parser, so take all format fields being received */
memcpy(&g_StreamInfo, pMediaType, uiMediaTypeSize);
g_StreamInfo.MediaTypeInfo.uiSize=uiMediaTypeSize;
}
else
{
/* just take the fields we don't know */
g_StreamInfo.LenInBytes=pStreamInfo->LenInBytes;
}
}
else
{
memset(&g_StreamInfo, 0, sizeof(MAIMediaTypeStream_t));
g_StreamInfo.MediaTypeInfo.uiFlags=MAI_MTFLAG_TYPESTREAM;
g_StreamInfo.MediaTypeInfo.uiSize=sizeof(MAIMediaTypeStream_t);
}
/* open a URI */
#ifdef UNICODE
eStatus=MAI_STATUS_UNSUPPORTED;
#else
if (eURIType==MAI_STRTYPE_USER)
{
/* add support for User defined object here */
void *pObject=(void *)pURI;
APIPRINTF((M_TEXT("MP4DEMUX: SetStream(%d, %p, USER) pObject=%p\n"), uiStreamID, pURI, pObject));
/* not yet supported */
eStatus=MAI_STATUS_UNSUPPORTED;
}
else if (eURIType==MAI_STRTYPE_CHAR)
{
char *pszURI=(char *)pURI;
APIPRINTF((M_TEXT("MP4DEMUX: SetStream(%d, %s, CHAR)\n"), uiStreamID, pszURI));
strcpy(m_pszFilePath, pszURI); /* File to read */
/* make sure previous file is closed */
_endprocessing(hComp);
inputclose(hComp);
if (g_bInit)
CloseParser();
g_bInit=M_FALSE;
/* open new file */
eStatus=inputopen();
}
else
eStatus=MAI_STATUS_BADARG;
#endif
}
return eStatus;
}
#endif
static MAIStatus_e MAICompStart(MAICompHandle_t hComp)
{
MAIStatus_e eStatus = MAI_STATUS_OK;
int iParserStatus = 0;
APIPRINTF((M_TEXT("MP4DEMUX: MAICompStart() enter: state=%d\n"), g_eCompState));
if (g_eCompState!=MAI_RUNSTATE_NONE)
return MAI_STATUS_WRONGSTATE;
_ChangeState(hComp, MAI_RUNSTATE_INIT);
g_bTerminate=0;
g_eEOS=EOS_NONE;
g_bVDiscon=M_FALSE;
g_bADiscon=M_FALSE;
g_bFirstRead=M_TRUE;
g_bSeekPending=M_FALSE;
g_lSeekValue=0;
g_eSeekType=MAI_SEEKTYPE_NONE;
/* Allocate buffers */
if (g_hInBufferPool==M_HANDLE_INVALID) /* Allocate buffers */
{
eStatus=MAICompBufferPoolCreate(g_uiInBufferSize, g_uiInMaxBuffers, &g_hInBufferPool);
if (MAI_STATUS_OK!=eStatus)
return eStatus;
/* setup a state change callback to report buffer fullness to MAIengine */
MAICompBufferPoolSetStateCB(g_hInBufferPool, _InBufferPoolStateCB, hComp);
}
// We don't have a handle to the reader since it's file based, so just
// startup the demux thread
g_hThread = MAIOSThreadCreate(DemuxThread, hComp, 0);
if (g_hThread==M_HANDLE_INVALID)
{
ERRORPRINTF((M_TEXT("MP4DEMUX: MAIOSThreadCreate failed")));
eStatus = MAI_STATUS_EXECFAILED;
}
else
{
MAIOSThreadSetPriority(g_hThread, g_uiThreadPriority);
eStatus=MAIOSThreadStart(g_hThread);
}
APIPRINTF((M_TEXT("MP4DEMUX: MAICompStart() done: result=0x%08X state=%d\n"), eStatus, g_eCompState));
return eStatus;
}
static MAIStatus_e MAICompEnd(MAICompHandle_t hComp)
{
// Terminate outstanding reads and stop the reader thread
APIPRINTF((M_TEXT("MP4DEMUX: MAICompEnd() enter: state=%d\n"), g_eCompState));
if (g_eCompState==MAI_RUNSTATE_DESTROYING ||
g_eCompState==MAI_RUNSTATE_NONE)
{
APIPRINTF((M_TEXT("MP4DEMUX: MAICompEnd() exit: not started\n")));
return MAI_STATUS_WRONGSTATE;
}
_ChangeState(hComp, MAI_RUNSTATE_DESTROYING);
if (g_bTerminate==0)
g_bTerminate=1;
/* Abort at blocked BufferPut/Get's */
MAICompBufferPoolAbort(g_hInBufferPool, M_FALSE);
g_hInBufferPool=M_HANDLE_INVALID;
MAIOSThreadDestroy(g_hThread, M_TRUE);
g_hThread=M_HANDLE_INVALID;
// If we had a handle to the reader, it should be destroyed here.
// Free memory...
MAICompBufferPoolDestroy(g_hInBufferPool, M_TRUE);
_ChangeState(hComp, MAI_RUNSTATE_NONE);
APIPRINTF((M_TEXT("MP4DEMUX: MAICompEnd() exit\n")));
return MAI_STATUS_OK;
}
//initialize the MP4 parser and parse meta data
MAIStatus_e _startprocessing(MAICompHandle_t hComp)
{
MAIStatus_e eStatus = MAI_STATUS_OK;
APIPRINTF((M_TEXT("MP4DEMUX: _startprocessing() enter: bInit=%d\n"), g_bInit));
if (g_bInit)
eStatus=MAI_STATUS_ALREADYOPEN;
else
{
FILE_BRAND file_brand;
m_u8* inBuffer1;
unsigned int bytesread;
inBuffer1 = (m_u8 *) malloc(16*1024*sizeof(m_u8));
if(inBuffer1 == NULL)
{
ERRORPRINTF((M_TEXT("MP4DEMUX: Error, could not allocate memory \n")));
return 0;
}
g_eEOS=EOS_NONE;
g_uiPlaySleep=0;
inputopen();
inputpeek(inBuffer1, 16*1024, &bytesread);
if(bytesread > 0)
check_file_type(inBuffer1,bytesread,&file_brand);
else
{
ERRORPRINTF((M_TEXT("MP4Demux: Error reading input file !!!\n")));
return 0;
}
if(inBuffer1 != NULL) {
free(inBuffer1);
inBuffer1 = NULL;
}
switch(file_brand)
{
case eISOM: // ISO 15444-3
ParseISOM(g_hFile);
eStatus = MAI_STATUS_OK;
break;
case eMP41:
case eMP42:// ISO/IEC 14496-1:2001
ParseMP4(g_hFile);
eStatus = MAI_STATUS_OK;
break;
default:
ERRORPRINTF((M_TEXT("MP4Demux: Exiting unknown input file type !!! \n")));
g_bInit=M_FALSE;
eStatus = MAI_STATUS_UNSUPPORTED;
break;
}
if (eStatus==MAI_STATUS_OK)
{
unsigned int apts_start=0, vpts_start=0;
unsigned int apts_end=0, vpts_end=0;
unsigned int pts_start=0, pts_end=0;
/* reset current sample number indexes */
g_uiVideoSampleNum=0;
g_uiAudioSampleNum=0;
g_uiVideoSampleCount = GetSampeCount(VIDEO);
g_uiAudioSampleCount = GetSampeCount(AUDIO);
/* fill in Stream format information */
g_StreamInfo.MediaTypeInfo.eMType = MAI_MTYPE_MP4; /* MP4 muxed */
g_StreamInfo.MediaTypeInfo.eMSubtype = MAI_MSUBTYPE_NONE;
if (g_uiVideoSampleCount)
{
sample_timming_info(0,VIDEO,&vpts_start);
sample_timming_info(g_uiVideoSampleCount-1,VIDEO,&vpts_end);
}
else
vpts_end=vpts_start=0;
if (g_uiAudioSampleCount)
{
sample_timming_info(0,AUDIO,&apts_start);
sample_timming_info(g_uiAudioSampleCount-1,AUDIO,&apts_end);
}
else
apts_end=apts_start=0;
pts_start = vpts_start?vpts_start:apts_start;
pts_end =(vpts_end>apts_end)?vpts_end:apts_end;
g_StreamInfo.uiFlags|=MAI_STREAMMTFLAG_FORMATKNOWN|MAI_STREAMMTFLAG_STARTTIME|MAI_STREAMMTFLAG_ENDTIME;
if (g_uiVideoSampleCount || g_uiAudioSampleCount)
g_StreamInfo.uiFlags|=MAI_STREAMMTFLAG_CANSEEK;
MAITIME_ASSIGN32(g_StreamInfo.tStartTime, pts_start);
MAITIME_ASSIGN32(g_StreamInfo.LenInTime, pts_end);
MAITIME_ASSIGN32(g_StreamInfo.tEndTime, pts_end);
APIPRINTF((M_TEXT("MP4DEMUX: InitMP4Parse() VideoSampleCount=%d AudioSampleCount=%d startpts=%d endpts=%d\n"),
g_uiVideoSampleCount, g_uiAudioSampleCount, pts_start, pts_end));
g_bInit=M_TRUE;
}
else
{
if (g_pfErrorCB)
g_pfErrorCB(hComp, MAI_STATUS_OPENERROR, 0);
}
}
APIPRINTF((M_TEXT("MP4DEMUX: _startprocessing() done: bInit=%d eStatus=0x%08X\n"),
g_bInit, eStatus));
return eStatus; /* success */
}
MAIStatus_e _endprocessing(MAICompHandle_t hComp)
{
MAIStatus_e eStatus = MAI_STATUS_OK;
APIPRINTF((M_TEXT("MP4DEMUX: _endprocessing() enter\n")));
if (!g_bInit)
eStatus=MAI_STATUS_WRONGSTATE;
else
{
//CloseParser();
//g_bInit=M_FALSE;
}
APIPRINTF((M_TEXT("MP4DEMUX: _endprocessing() exit: status=0x%X\n"), eStatus));
return eStatus;
}
// send configuration info to audio and video decoders
void ConfigDecoders()
{
m_u8 *data_buffer;
m_u8 *pData;
m_u16 channelcount=0;
m_u16 samplerate=0;
long lData;
MAICompBuffer_t *pBufferInfo;
if(g_uiAudioSampleCount > 0) // send special header to aac decoder
{
GetAudioInfo(&channelcount,&samplerate);
data_buffer = (m_u8*) malloc(10 * sizeof(m_u8));
data_buffer[0] = 'f';
data_buffer[1] = 'a';
data_buffer[2] = 'a';
data_buffer[3] = 'c';
data_buffer[4] = (m_u8) 0x02; // object type: hard coded value
data_buffer[5] = (m_u8) channelcount;
data_buffer[6] = (m_u8) (samplerate & 0x000000ff);
data_buffer[7] = (samplerate & 0x0000ff00) >> 8;
data_buffer[8] = (samplerate & 0x00ff0000) >> 16;
data_buffer[9] = (samplerate & 0xff000000) >> 24;
if (g_pfOutputAudioGetBuf && MAI_STATUS_OK == g_pfOutputAudioGetBuf(g_hOutputAudioOwner,&pBufferInfo))
{
if(10 > pBufferInfo->uiBufSize)
{
ERRORPRINTF((M_TEXT("MP4DEMUX: Error - Data is larger than buffer size!\n")));
}
memcpy(pBufferInfo->pBuffer, data_buffer,10);
pBufferInfo->dwFlags = 0; /* default - no special flags */
pBufferInfo->tTimeStamp = 0;
pBufferInfo->uiDataSize = 10;
PUTPRINTF((M_TEXT("MP4DEMUX: Passing the data to the audio decoder\n")));
g_pfOutputAudioPutBuf(g_hOutputAudioOwner,pBufferInfo);
if(data_buffer){
free(data_buffer);
data_buffer = NULL;
}
}
}
// send configuration data to mpeg4 video decoder
if(g_uiVideoSampleCount > 0)
{
if (g_pfOutputVideoGetBuf && MAI_STATUS_OK==g_pfOutputVideoGetBuf(g_hOutputVideoOwner,&pBufferInfo))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -