📄 maimp4demux.c
字号:
/* <LIC_AMD_STD>
* Copyright (C) 2003-2005 Advanced Micro Devices, Inc. All Rights Reserved.
*
* Unless otherwise designated in writing, this software and any related
* documentation are the confidential proprietary information of AMD.
* THESE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY
* UNLESS OTHERWISE NOTED IN WRITING, EXPRESS OR IMPLIED WARRANTY OF ANY
* KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE AND IN NO
* EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER.
*
* AMD does not assume any responsibility for any errors which may appear
* in the Materials nor any responsibility to support or update the
* Materials. AMD retains the right to modify the Materials at any time,
* without notice, and is not obligated to provide such modified
* Materials to you. AMD is not obligated to furnish, support, or make
* any further information available to you.
* </LIC_AMD_STD> */
/* <CTL_AMD_STD>
* </CTL_AMD_STD> */
/* <DOC_AMD_STD>
* File: maimp4demux.c
* Date: 03/14/05
* </DOC_AMD_STD> */
#define FILESOURCE /* use direct file reads */
// Windows Header Files:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h> /* for memset */
#include <string.h> /* for strcpy */
#include "mp4parse.h"
#include "mai_osal.h"
#include "mai_component.h"
#include "mai_param.h"
#ifdef TRACE_BUILD
#define DPRINTF(_args_) MAIOSDebugPrint _args_
#define APIPRINTF(_args_) MAIOSDebugPrint _args_
#define PUTPRINTF(_args_) //MAIOSDebugPrint _args_
#define GETPRINTF(_args_) //MAIOSDebugPrint _args_
#define ERRORPRINTF(_args_) MAIOSDebugPrint _args_
#else
#define DPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#define APIPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#define PUTPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#define GETPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#define ERRORPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#endif
#define AUDIO_READ_AHEAD 500 /* max audio in millisecs to read ahead of audio (help prevent audio gaps) */
#define MAX_READ_PERSTREAM 500 /* max data in millisecs to read from a stream per loop (larger reduces seeks) */
/* Global Variables */
static pfMAICompGetBufferCB_t g_pfOutputVideoGetBuf = NULL;
static pfMAICompPutBufferCB_t g_pfOutputVideoPutBuf = NULL;
static MAICompHandle_t g_hOutputVideoOwner=M_HANDLE_INVALID;
static pfMAICompGetBufferCB_t g_pfOutputAudioGetBuf = NULL;
static pfMAICompPutBufferCB_t g_pfOutputAudioPutBuf = NULL;
static MAICompHandle_t g_hOutputAudioOwner=M_HANDLE_INVALID;
static MAICompBufferPool_t g_hInBufferPool=M_HANDLE_INVALID;
/* local */
static MAICompHandle_t g_hReaderComp = M_HANDLE_INVALID; /* this is a handle to the FileReader component */
static MAIRunState_e g_eCompState=MAI_RUNSTATE_NONE;
static MAIOSThread_t g_hThread=M_HANDLE_INVALID;
static unsigned int g_uiThreadPriority=MAICOMP_DEFAULT_THREAD_PRIORITY;
m_bool g_bTerminate=0;
static unsigned int g_uiInBufferSize=64*1024;
static unsigned int g_uiInMaxBuffers=2;
static pfMAICompErrorCB_t g_pfErrorCB = NULL;
static pfMAICompProgressCB_t g_pfProgressCB = NULL;
static unsigned int g_uiProgressSelectFlags = 0; /* flags enabling progress calls */
static MAIMediaTypeStream_t g_StreamInfo;
static MAITimeStamp_t g_tLastPTS = 0;
static m_bool g_bLooping = M_FALSE;
static m_bool g_bSeekPending = M_FALSE;
static m_s32 g_lSeekValue = 0;
static MAISeekType_e g_eSeekType = MAI_SEEKTYPE_NONE; /* MAI_SEEKTYPE_ABS, _ABSPCT, _REL, _RELPCT */
static m_bool g_bInit = M_FALSE; /* is the file open and demux successfully initialized */
static m_bool g_bVDiscon; /* video stream discontinuity (i.e. seek, loop) */
static m_bool g_bADiscon; /* audio stream discontinuity (i.e. seek, loop) */
static m_bool g_bFirstRead; /* TRUE if we have not read first buffer at the stream starting position */
static unsigned int g_eEOS;
static MAISpeed_e g_uiCurrentSpeed = MAI_SPEED_NORMAL;
static MAISpeed_e g_uiNextSpeed = 0;
static m_bool g_bSpeedChange = M_FALSE; /* TRUE if speed is being changed */
static unsigned int g_uiPlaySleep = 0; /* time to sleep between each segment that's delivered */
/* End-Of-Stream states */
#define EOS_NONE 0x0000
#define EOS_ON_INPUT 0x0001 /* an EOS has been reported on a input buffer */
#define EOS_ON_INPUT_WITH_BUFFERS 0x0002 /* an EOS has been reported on an input buffer, but data is still queued */
#define EOS_DELIVERED 0x8000 /* EOS has been reported to app */
static m_tchar m_pszFilePath[300]; /* current file (if not connected to filereader) */
static m_bool g_bFileOpen=M_FALSE;
static m_u32 g_uiAudioSampleCount=0; /* total Audio samples */
static m_u32 g_uiVideoSampleCount=0; /* total Video samples */
static m_u32 g_uiAudioSampleNum=0; /* current Audio sample */
static m_u32 g_uiVideoSampleNum=0; /* current Video sample */
MAIOSFile_t g_hFile;
// Main Thread
static m_u32 DemuxThread(MAIOSThread_t hThread, void *pUserData);
MAIStatus_e _startprocessing(MAICompHandle_t hComp);
MAIStatus_e _endprocessing(MAICompHandle_t hComp);
static MAIStatus_e MAIMP4Demux_GetBuffer(MAICompHandle_t hComp,MAICompBuffer_t **ppBufferInfo);
static MAIStatus_e MAIMP4Demux_PutBuffer(MAICompHandle_t hComp,MAICompBuffer_t *pBufferInfo);
void _SendProgressCB(MAICompHandle_t hComp, unsigned int uiFlags)
{
APIPRINTF((M_TEXT("MP4DEMUX: _SendProgressCB(Flags=0x%X)\n"), uiFlags));
if (g_pfProgressCB)
{
MAIProgressStream_t SProgressInfo;
memset(&SProgressInfo, 0, sizeof(MAIProgressStream_t));
SProgressInfo.hComp=hComp;
SProgressInfo.uiFlags=uiFlags;
//if (pCompInfo->m_ePTSState==PTS_STATE_KNOWN)
//{
// SProgressInfo.uiFlags |= MAICOMPBUF_FLAG_PTS;
// MAITIME_ASSIGN(SProgressInfo.tCurrentTime, pCompInfo->m_tLastPTS);
//}
g_pfProgressCB(hComp, MAI_PROGRESS_STREAM, &SProgressInfo, sizeof(MAIProgressStream_t));
}
}
/* HWG - file wrapper routines to allow streaming input */
static unsigned int g_uiOffset=0;
static unsigned int g_bInputEOS=0;
static MAIStatus_e inputopen()
{
MAIStatus_e eStatus = MAI_STATUS_OK;
APIPRINTF((M_TEXT("MP4DEMUX: inputopen()\n")));
if (!g_bFileOpen)
{
if (g_hReaderComp!=M_HANDLE_INVALID)
{
APIPRINTF((M_TEXT("MP4DEMUX: inputopen() Using Reader Comp: %p\n"), g_hReaderComp));
g_uiOffset=0;
g_bInputEOS=0;
g_bFileOpen=M_TRUE;
}
else
{
#ifdef FILESOURCE
g_hFile = MAIOSFileOpenForRead(m_pszFilePath);
if(g_hFile == NULL)
{
eStatus=MAI_STATUS_OPENERROR;
ERRORPRINTF((M_TEXT("MP4DEMUX: inputopen() Error opening input file [%s].\n"),m_pszFilePath));
g_bFileOpen=M_FALSE;
g_uiOffset=0;
g_bInputEOS=1;
}
else
g_bFileOpen=M_TRUE;
#else
g_bFileOpen=M_TRUE;
#endif
if (g_bFileOpen) /* successfully opened */
{
APIPRINTF( M_TEXT(("MP4DEMUX: inputopen() File opened\n")) );
g_uiOffset=0;
g_bInputEOS=0;
g_StreamInfo.LenInBytes=0; //_streamlength(hComp);
g_bFirstRead=M_TRUE;
//_newposition(pPInfo, 0); /* assume file starts at zero timestamp */
//pPInfo->m_bFormatChange=M_TRUE;
g_bVDiscon=M_FALSE;
g_bADiscon=M_FALSE;
}
}
}
return eStatus;
}
static void inputclose(MAICompHandle_t hComp)
{
APIPRINTF((M_TEXT("MP4DEMUX: inputclose()\n")));
if (g_bFileOpen) /* close old file if open */
{
APIPRINTF( (M_TEXT("MP4DEMUX: inputclose() Send EOS\n")) );
_SendProgressCB(hComp, MAI_PROGRESSFLAG_EOS);
MAIOSFileClose(g_hFile);
g_bFileOpen=M_FALSE;
}
}
MAIStatus_e inputread(unsigned char *pucData, unsigned int uiSize, unsigned int *puiBytesRead)
{
unsigned int uiTotalRead=0;
MAIStatus_e eStatus=MAI_STATUS_NOBUFAVAIL;
GETPRINTF((M_TEXT("MP4DEMUX: inputread(size=%d) actualoffset=%d\n"), uiSize, g_uiOffset));
if (!g_bTerminate)
{
if (g_hReaderComp!=M_HANDLE_INVALID)
{
MAICompBuffer_t BufferInfo;
MAICompBuffer_t *pBufferInfo=&BufferInfo;
BufferInfo.dwFlags=0;
BufferInfo.uiBufSize=uiSize;
BufferInfo.uiDataSize=0;
BufferInfo.pBuffer=pucData;
eStatus=MAIComp_ReadBuffer(g_hReaderComp, 0, &pBufferInfo, MAI_TIMEOUT_INFINITE);
uiTotalRead+=BufferInfo.uiDataSize;
}
else
{
#ifdef FILESOURCE
eStatus=MAIOSFileRead(g_hFile, pucData, uiSize, &uiTotalRead);
#else
MAICompBuffer_t BufferInfo;
BufferInfo.dwFlags=0;
/* get an empty buffer from the buffer pool */
do
{
BufferInfo.uiBufSize=uiSize-uiTotalRead;
BufferInfo.pBuffer=pucData+uiTotalRead;
eStatus=MAICompBufferPoolRead(g_hInBufferPool, &BufferInfo, g_bInputEOS?MAI_TIMEOUT_NONE:MAI_TIMEOUT_INFINITE);
uiTotalRead+=BufferInfo.uiDataSize;
if ((BufferInfo.dwFlags&MAICOMPBUF_FLAG_EOS)!=0)
g_bInputEOS=1;
} while (eStatus==MAI_STATUS_OK && uiTotalRead<uiSize && !g_bInputEOS);
#endif
}
GETPRINTF((M_TEXT("MP4DEMUX: inputread(size=%d) return %d bytes: 0x%02X 0x%02X\n"), uiSize, uiTotalRead, pucData[0], pucData[1]));
}
if (puiBytesRead)
*puiBytesRead=uiTotalRead;
g_uiOffset+=uiTotalRead;
return eStatus;
}
MAIStatus_e inputseek(unsigned int uiOffset)
{
MAIStatus_e eStatus=MAI_STATUS_OK;
GETPRINTF((M_TEXT("MP4DEMUX: inputseek(offset=%d) actualoffset=%d\n"), uiOffset, g_uiOffset));
if (g_hReaderComp!=M_HANDLE_INVALID)
{
eStatus=MAIComp_SendCommand(g_hReaderComp, MAICOMP_CMD_SEEK, MAI_SEEKTYPE_ABS, uiOffset);
g_uiOffset=uiOffset;
}
else
{
#ifdef FILESOURCE
eStatus=MAIOSFileSeek(g_hFile, uiOffset);
g_uiOffset=uiOffset;
#else
if (uiOffset>g_uiOffset)
inputadvance(uiOffset-g_uiOffset);
if (uiOffset!=g_uiOffset)
{
ERRORPRINTF((M_TEXT("MP4DEMUX: inputseek(offset=%d) actualoffset=%d: SEEK backwards\n"), uiOffset, g_uiOffset));
eStatus=MAI_STATUS_UNSUPPORTED;
}
#endif
}
return eStatus;
}
static unsigned int inputpeek(unsigned char *pucData, unsigned int uiSize, unsigned int *puiBytesRead)
{
unsigned int uiTotalRead=0;
MAIStatus_e eStatus=MAI_STATUS_NOBUFAVAIL;
GETPRINTF((M_TEXT("MP4DEMUX: inputpeek(size=%d) actualoffset=%d\n"), uiSize, g_uiOffset));
if (!g_bTerminate)
{
#ifdef FILESOURCE
eStatus=inputread(pucData, uiSize, &uiTotalRead);
eStatus=inputseek(g_uiOffset);
#else
MAICompBuffer_t BufferInfo;
MAICompBuffer_t *pBufferInfo=&BufferInfo;
BufferInfo.dwFlags=0;
BufferInfo.uiBufSize=uiSize;
BufferInfo.uiDataSize=0;
BufferInfo.pBuffer=pucData;
eStatus=MAICompBufferPoolPeek(g_hInBufferPool, &pBufferInfo, MAI_TIMEOUT_INFINITE);
if (pBufferInfo!=&BufferInfo) /* if peek returned a different buffer, copy the data to ours */
{
uiTotalRead=(pBufferInfo->uiDataSize<uiSize)?pBufferInfo->uiDataSize:uiSize;
memcpy(pucData, pBufferInfo->pBuffer, uiTotalRead);
}
else
uiTotalRead=BufferInfo.uiDataSize;
#endif
GETPRINTF((M_TEXT("MP4DEMUX: inputpeek(size=%d) return %d bytes: 0x%02X 0x%02X\n"), uiSize, uiTotalRead, pucData[0], pucData[1]));
}
if (puiBytesRead)
*puiBytesRead=uiTotalRead;
return uiTotalRead;
}
/* advance the file position (seek forward) */
static unsigned int inputadvance(unsigned int uiBytes)
{
unsigned char pucDummyBuf[4*1024];
unsigned int uiTotalSkipped=0;
/* we just issue dummy reads to advance to file position */
while (uiBytes>0)
{
unsigned int uiRead=0;
inputread(pucDummyBuf, (uiBytes>sizeof(pucDummyBuf))?sizeof(pucDummyBuf):uiBytes, &uiRead);
uiBytes-=uiRead;
}
return uiTotalSkipped;
}
static int inputpos()
{
return g_uiOffset;
}
MAIStatus_e _streamseek(MAICompHandle_t hComp, long lSeekValue, MAISeekType_e eSeekType)
{
//ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)HCOMP_TO_USERINFO(hComp);
MAIStatus_e eStatus = MAI_STATUS_NOTOPEN;
GETPRINTF( (M_TEXT("MP4DEMUX: _streamseek(SeekValue=%d, SeekType=%d)\n"), (unsigned int)lSeekValue, eSeekType) );
if (g_bFileOpen)
{
unsigned int uiNewVSamplePosition=0, uiNewASamplePosition=0;
if (eSeekType==MAI_SEEKTYPE_ABSTIME)
{
if (!g_bInit)
{
/* stream is not open yet, allow only to start */
if (!lSeekValue) /* seek to start allowed */
eStatus=inputseek((m_u32)lSeekValue);
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -