📄 mp4parse.cpp
字号:
/* <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>
* </DOC_AMD_STD> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "mp4parse.h"
#include "mp4util.h"
#include "mai_component.h" /* to access Reader component */
#define DPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#define APIPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#define INFOPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#define USE_FILE_READ
#define BUFF_SIZE 1024*1024
#define MAX_TRACKS 20
typedef struct _TRACK_ {
CTrackHeaderBox *pTrkHdrBox;
CMediaHeaderBox *pMediaHdr;
TRACK_TYPES type;
} TRACK;
unsigned char inBuffer[BUFF_SIZE];
CSampleDescriptionBox *pSampleDescription[NUM_TRACK_TYPES];
CTimeToSampleBox *pTimeToSample[NUM_TRACK_TYPES];
CSampleToChunkBox *pSampleToChunk[NUM_TRACK_TYPES];
CChunkOffsetBox *pCunkOffset[NUM_TRACK_TYPES];
CSampleSizeBox *pSampleSize[NUM_TRACK_TYPES];
CDataReferenceBox *pDataReference;
CTrackHeaderBox *pTrkHdrBox;
CMovieHeaderBox *pMovHdrBox;
CMediaDataBox *pMediaDataBox;
TRACK TrackList[MAX_TRACKS];
m_bool g_bSeenMetaData=0;
void Parse_mdia(Byte_Stream &input_stream, long lData,m_bool bMP4File, int TrackNum);
extern "C" MAIStatus_e inputread(unsigned char *pucData, unsigned int uiSize, unsigned int *puiBytesRead);
extern "C" MAIStatus_e inputseek(unsigned int uiOffset);
void InitParser()
{
int i;
for(i=0;i<MAX_TRACKS;i++)
{
TrackList[i].pMediaHdr = NULL;
TrackList[i].pTrkHdrBox = NULL;
TrackList[i].type = UNKNOWN;
}
for(i=0;i<NUM_TRACK_TYPES;i++)
{
pSampleDescription[i] = NULL;
pTimeToSample[i] = NULL;
pSampleToChunk[i] = NULL;
pCunkOffset[i] = NULL;
pSampleSize[i] = NULL;
}
pDataReference = NULL;
pTrkHdrBox = NULL;
pMovHdrBox = NULL;
pMediaDataBox = NULL;
}
void CloseParser()
{
int i;
for(i=0;i< NUM_TRACK_TYPES;i++)
{
if(pSampleDescription[i])
{
delete pSampleDescription[i];
pSampleDescription[i] = NULL;
}
if(pTimeToSample[i])
{
delete pTimeToSample[i];
pTimeToSample[i] = NULL;
}
if(pSampleToChunk[i])
{
delete pSampleToChunk[i];
pSampleToChunk[i] = NULL;
}
if(pSampleSize[i])
{
delete pSampleSize[i];
pSampleSize[i] = NULL;
}
}
for(i=0;i<MAX_TRACKS;i++)
{
if(TrackList[i].pMediaHdr)
{
delete TrackList[i].pMediaHdr;
TrackList[i].pMediaHdr = NULL;
}
if(TrackList[i].pTrkHdrBox)
{
delete TrackList[i].pTrkHdrBox;
TrackList[i].pTrkHdrBox = NULL;
}
}
}
// parse mdia, container for media info in a track
void Parse_mdia(Byte_Stream &input_stream, long lData,m_bool bMP4File,int TrackNum)
{
long Len=0,Len1=0,Len2=0;
unsigned int mid ,mid1,mid2 ;
int index;
CHandlerBox *pHandler;
while(lData > 8)
{
Len = input_stream.GetUINT();
mid = input_stream.GetUINT();
lData -= Len;
switch(mid)
{
case FOURCC('m','d','h','d'): // media header
TrackList[TrackNum].pMediaHdr = new CMediaHeaderBox(Len);
TrackList[TrackNum].pMediaHdr->ReadData(input_stream);
break;
case FOURCC('h','d','l','r'): // handler, media type
m_u32 handler_type;
pHandler = new CHandlerBox(Len);
pHandler->ReadData(input_stream,Len-8);
handler_type = pHandler->GetHandlerType();
switch(handler_type)
{
case FOURCC('s','o','u','n'):
index = AUDIO;
TrackList[TrackNum].type = AUDIO;
break;
case FOURCC('v','i','d','e'):
index = VIDEO;
TrackList[TrackNum].type = VIDEO;
break;
case FOURCC('h','i','n','t'):
index = HINT;
TrackList[TrackNum].type = HINT;
break;
default:
index = OD;
TrackList[TrackNum].type = OD;
break;
}
delete pHandler;
pHandler=NULL;
break;
case FOURCC('m','i','n','f'): // media information container
while(Len > 8)
{
Len1 =input_stream.GetUINT();
mid1 = input_stream.GetUINT();
Len -= Len1;
switch(mid1)
{
case FOURCC('v','m','h','d'): //
if(Len1 > 8)
input_stream.Advance(Len1-8);
break;
case FOURCC('s','m','h','d'): //
if(Len1 > 8)
input_stream.Advance(Len1-8);
break;
case FOURCC('h','m','h','d'): // data info box
if(Len1 > 8)
input_stream.Advance(Len1-8);
break;
case FOURCC('d','i','n','f'): // data info box
Len2 =input_stream.GetUINT();
mid2 = input_stream.GetUINT();
if(Len2 > 8)
input_stream.Advance(Len2-8);
// TODO:
/*
if(mid2 == FOURCC('d','r','e','f'))
{
pDataReference = new CDataReferenceBox(Len1) ;
pDataReference->ReadData(input_stream,Len2-8);
}
*/
break;
case FOURCC('s','t','b','l'): // time space map
while(Len1 > 8)
{
Len2 =input_stream.GetUINT();
mid2 = input_stream.GetUINT();
Len1 -= Len2;
switch(mid2)
{
case FOURCC('s','t','s','d'): // sample descriptions (codec types, initialization,etc.)
// TODO, look for mp4a, mp4v, and esds , while(Len2 > 8) or pass Len2 to ReadData
if(index == VIDEO || index == AUDIO )
{
if(pSampleDescription[index])
{
delete pSampleDescription[index];
pSampleDescription[index] = NULL;
}
pSampleDescription[index] = new CSampleDescriptionBox(Len2);
pSampleDescription[index]->ReadData(input_stream,index,bMP4File);
} else
{
input_stream.Advance(Len2-8);
}
break;
case FOURCC('s','t','t','s'): // (decoding) time-to-sample
if(pTimeToSample[index])
{
delete pTimeToSample[index];
pTimeToSample[index] = NULL;
}
pTimeToSample[index] = new CTimeToSampleBox(Len2);
pTimeToSample[index]->ReadData(input_stream);
break;
case FOURCC('s','t','s','c'): // sample-to-chunk, partial data-offset information
if(pSampleToChunk[index])
{
delete pSampleToChunk[index];
pSampleToChunk[index] = NULL;
}
pSampleToChunk[index] = new CSampleToChunkBox(Len2);
pSampleToChunk[index]->ReadData(input_stream);
break;
case FOURCC('s','t','s','z'): // sample sizes (framing)
if(pSampleSize[index])
{
delete pSampleSize[index];
pSampleSize[index] = NULL;
}
pSampleSize[index] = new CSampleSizeBox(Len2);
pSampleSize[index]->ReadData(input_stream);
break;
case FOURCC('s','t','c','o'): // chunk offset, partial data-offset information
if(pCunkOffset[index])
{
delete pCunkOffset[index];
pCunkOffset[index] = NULL;
}
pCunkOffset[index] = new CChunkOffsetBox(Len2);
pCunkOffset[index]->ReadData(input_stream);
break;
case FOURCC('m','p','4','a'):
if(Len2 > 8)
input_stream.Advance(Len2-8);
break;
case FOURCC('m','p','4','v'):
if(Len2 > 8)
input_stream.Advance(Len2-8);
break;
default:
if(Len2 > 8)
input_stream.Advance(Len2-8);
break;
}
}
break;
default:
if(Len1 > 8)
input_stream.Advance(Len1-8);
break;
}
}
break;
default:
if(Len > 8)
input_stream.Advance(Len-8);
break;
}
}
Len = 0;
}
void ParseMP4(MAIOSFile_t g_hFile)
{
unsigned int bytesread,bytesprocessed=0;
unsigned long filepos=0,boxlength;
long lbytesLeft;
Byte_Stream input_stream;
unsigned char *ptemp;
long offset = 0;
long Len ,Len1 ;
unsigned int mid,mid1;
int TrackCount=0;
m_bool bSeek = 1;
g_bSeenMetaData = 0;
InitParser();
while(1)
{
if(bSeek = 1)
inputseek(filepos);
inputread(inBuffer, BUFF_SIZE, &bytesread);
if(bytesread <= 8 || g_bSeenMetaData )
break;
offset = 0;
ptemp = inBuffer;
input_stream.Initialize(ptemp, bytesread);
bytesprocessed = 0;
while(bytesprocessed < bytesread - 8)
{
long dwLen =input_stream.GetUINT();
unsigned int id = input_stream.GetUINT();
lbytesLeft = bytesread - bytesprocessed;
boxlength = dwLen;
bSeek = 0;
if(g_bSeenMetaData ) // got the required meta data
break;
switch(id)
{
case FOURCC('m','o','o','v'): // all meta-data
g_bSeenMetaData = 1;
if(dwLen > lbytesLeft)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -