📄 atomparse.h
字号:
/* <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> */
#ifndef _ATOM_PARSE_H_
#define _ATOM_PARSE_H_
#include "mai_types.h"
#include "bytestrm.h"
#include "descriptors.h"
#include <iostream>
#define FOURCC(c1,c2,c3,c4) (c1 << 24 | c2 << 16 | c3 << 8 | c4)
class CBox {
public:
CBox()
{
};
CBox(m_u32 boxsize,m_u32 boxtype)
{
size = boxsize;
type = boxtype;
};
CBox(m_u32 boxsize,m_u32 boxtype, unsigned char extended_type[16])
{
size = boxsize;
type = boxtype;
if (boxtype == FOURCC('u','u','i','d') ) {
memcpy(usertype,extended_type,16);
}
};
~CBox()
{
};
protected:
void ReadData(Byte_Stream &input_stream);
m_u32 size;
m_u32 type;
m_u64 largesize;
unsigned char usertype[16];
};
class CFullBox :public CBox
{
public:
CFullBox()
{
};
CFullBox(m_u32 boxsize,m_u32 boxtype)
:CBox(boxsize,boxtype)
{
};
CFullBox(m_u32 boxtype,m_u8 ver,m_u32 flags)
:CBox(0,boxtype)
{
version = ver;
flags = flags;
};
~CFullBox()
{
};
void ReadData(Byte_Stream &input_stream);
protected:
m_u8 version ;
m_u32 flags ;
};
class CMediaDataBox :public CBox
{
public:
CMediaDataBox(m_u32 boxsize)
:CBox(boxsize,FOURCC('m','d','a','t'))
{
};
void ReadData(Byte_Stream &input_stream,m_u32 size);
m_u8 *data;
};
class CMovieHeaderBox :public CFullBox {
public:
CMovieHeaderBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('m','v','h','d'))
{
rate = 0;
};
void ReadData(Byte_Stream &input_stream);
private:
m_u64 creation_time;
m_u64 modification_time;
m_u64 timescale ;
m_u64 duration;
m_u32 reservedar[2];
m_u32 rate;
m_u16 volume;
m_u32 reserved;
m_u16 reserved1;
m_u32 matirx[9];
m_u32 pre_defined[6];
m_u32 next_track_ID;
};
class CTrackHeaderBox: public CFullBox
{
public:
CTrackHeaderBox(m_u32 boxsize)
:CFullBox(boxsize, (FOURCC('t','k','h','d')))
{
layer = 0;
};
~CTrackHeaderBox() {};
void ReadData(Byte_Stream &input_stream,long Len);
private:
m_u64 creation_time;
m_u64 modification_time;
m_u32 track_ID;
m_u32 reserved;
m_u64 duration;
m_u32 reservedar[2];
m_u16 layer;
m_u16 alternate_group;
m_u16 volume;
m_u16 reserved1;
m_u32 matirx[9];
m_u32 width;
m_u32 height;
};
class CMediaHeaderBox :public CFullBox {
public:
CMediaHeaderBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('m','d','h','d'))
{
duration =0;
}
void ReadData(Byte_Stream &input_stream);
~CMediaHeaderBox(){};
m_u32 GetTimescale()
{
return timescale;
};
private:
m_u64 creation_time;
m_u64 modification_time;
m_u32 timescale;
m_u64 duration;
m_bool pad;
m_u8 language[3];
m_u16 pre_defined;
};
class CHandlerBox :public CFullBox
{
public:
CHandlerBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('h','d','l','r'))
{
pre_defined = 0;
}
void ReadData(Byte_Stream &input_stream,long len);
m_u32 GetHandlerType();
private:
m_u32 pre_defined;
m_u32 handler_type;
m_u32 reserved[3];
//char name; // a null-terminated string in UTF-8 characters
};
// TODO
class CDataEntryUrnBox :public CFullBox
{
public:
CDataEntryUrnBox (m_u32 boxsize,Byte_Stream &input_stream)
:CFullBox(boxsize,FOURCC('u','r','n',' '))
{
CFullBox::ReadData(input_stream);
};
char name[256];
char location[256];
};
class CDataReferenceBox :public CFullBox
{
public:
CDataReferenceBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('d','r','e','f'))
{
}
void ReadData(Byte_Stream &input_stream, long Len);
m_u32 entry_count;
CDataEntryUrnBox * data_entry_list;
};
/*
This box contains a compact version of a table that allows indexing from decoding time to sample number.
Other tables give sample sizes and pointers, from the sample number. Each entry in the table gives the
number of consecutive samples with the same time delta, and the delta of those samples.
By adding the deltas a complete time-to-sample map may be built.
The Decoding Time to Sample Box contains decode time delta's: DT(n+1) = DT(n) + STTS(n) where
STTS(n) is the (uncompressed) table entry for sample n.
The sample entries are ordered by decoding time stamps; therefore the deltas are all non-negative.
*/
class CTimeToSampleBox :public CFullBox
{
public:
CTimeToSampleBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('s','t','t','s'))
{
sample_count_list = NULL;
sample_delta_list = NULL;
};
CTimeToSampleBox()
{
sample_count_list = NULL;
sample_delta_list = NULL;
};
void ReadData(Byte_Stream &input_stream);
~CTimeToSampleBox()
{
if(sample_count_list != NULL){
delete sample_count_list;
sample_count_list = NULL;
}
if(sample_delta_list != NULL) {
delete sample_delta_list;
sample_delta_list = NULL;
}
};
void GetTimmingInfo(long lSampleNum,m_u32 *sdelta)
{
m_u32 count=0,scount;
int j=0;
count = entry_count;
scount = sample_count_list[j];
*sdelta = sample_delta_list[j];
while(lSampleNum > scount && count-- > 0) {
j++;
scount = sample_count_list[j];
*sdelta = sample_delta_list[j];
}
};
private:
m_u32 entry_count;
m_u32 *sample_count_list; //Each entry in the table gives the number of consecutive
//samples with the same time delta, and the delta of those samples.
m_u32 *sample_delta_list;
};
class CCompositionOffsetBox : public CFullBox {
public:
CCompositionOffsetBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('c','t','t','s'))
{
sample_count_list = NULL;
sample_offset_list = NULL;
}
void ReadData(Byte_Stream &input_stream);
~CCompositionOffsetBox()
{
if(sample_count_list != NULL) {
delete sample_count_list;
sample_count_list = NULL;
}
if(sample_offset_list != NULL) {
delete sample_offset_list;
sample_offset_list = NULL;
}
};
private:
m_u32 entry_count;
m_u32 *sample_count_list;
m_u32 *sample_offset_list;
};
// TODO
// abstract class
class CSampleEntry :public CBox
{
public:
CSampleEntry()
{
};
CSampleEntry (m_u32 boxsize,m_u32 format)
:CBox(boxsize,format)
{
data_reference_index = 0;
format = format;
};
void ReadData(Byte_Stream &input_stream);
m_u32 format;
m_u8 reserved[6];
m_u16 data_reference_index;
};
class CHintSampleEntry: public CSampleEntry
{
public:
CHintSampleEntry()
{
};
CHintSampleEntry(m_u32 boxsize,m_u32 protocol)
:CSampleEntry (boxsize,protocol)
{
}
m_u32 protocol;
m_u8 *data;
};
// Visual Sequences
class CVisualSampleEntry : public CSampleEntry
{
public:
CVisualSampleEntry(m_u32 boxsize,m_u32 codingname)
:CSampleEntry (boxsize,codingname)
{
pVideoDecConfigData = NULL;
}
void ReadData(Byte_Stream &input_stream);
~CVisualSampleEntry()
{
if(pVideoDecConfigData != NULL)
{
free(pVideoDecConfigData);
pVideoDecConfigData = NULL;
}
};
m_u16 pre_defined;
m_u16 reserved;
m_u32 pre_defined_list[3];
m_u16 width;
m_u16 height;
m_u32 horizresolution;
m_u32 vertresolution;
m_u32 reserved1;
m_u8 compressorname[32]; // ?? string [32]
m_u16 depth;
m_s16 pre_defined1;
m_u8 *pVideoDecConfigData;
long lConfigDataLen;
};
// Audio Sequences
class CAudioSampleEntry : public CSampleEntry
{
public:
CAudioSampleEntry(m_u32 boxsize,m_u32 codingname)
:CSampleEntry (boxsize,codingname)
{
}
void ReadData(Byte_Stream &input_stream);
m_u32 reserved[2];
m_u16 channelcount;
m_u16 samplesize;
m_u16 pre_defined;
m_u16 reserved1;
m_u16 samplerate;
};
class CESDBox:public CFullBox
{
public:
CESDBox()
:CFullBox(FOURCC('e','s','d','s'),0,0)
{
};
void ReadData(Byte_Stream &input_stream)
{
CBox::ReadData(input_stream);
CFullBox::ReadData(input_stream);
ESD.ReadData(input_stream);
};
CES_Descriptor ESD;
};
class CMP4AudioSampleEntry: public CAudioSampleEntry
{
public:
CMP4AudioSampleEntry()
:CAudioSampleEntry(0,FOURCC('m','p','4','a'))
{
};
void ReadData(Byte_Stream &input_stream);
CESDBox ES;
};
/*
The sample description table gives detailed information about the coding type used, and any
initialization information needed for that coding.The information stored in the sample description
box after the entry-count is both track-type specific as documented here, and can also have variants
within a track type (e.g. different codings may use different specific information after
some common fields, even within a video track).
For video tracks, a VisualSampleEntry is used; for audio tracks, an AudioSampleEntry. Hint tracks use an
entry format specific to their protocol, with an appropriate name.
For hint tracks, the sample description contains appropriate declarative data for the streaming protocol
being used, and the format of the hint track. The definition of the sample description is specific to
the protocol.
Multiple descriptions may be used within a track.
The ?protocol?and ?codingname?fields are registered identifiers that uniquely identify the streaming
protocol or compression format decoder to be used. A given protocol or codingname may have optional or
required extensions to the sample description (e.g. codec initialization parameters). All such extensions
shall be within boxes; these boxes occur after the required fields. Unrecognized boxes shall be ignored.
If the ?format?field of a SampleEntry is unrecognized, neither the sample description itself, nor the
associated media samples, shall be decoded.
In audio tracks, the sampling rate of the audio should be used as the timescale of the media, and also
documented in the samplerate field here.
*/
class CSampleDescriptionBox : public CFullBox
{
public:
CSampleDescriptionBox (m_u32 boxsize)
: CFullBox(boxsize,FOURCC('s','t','s','d'))
{
pCAudioSampleEntry = NULL;
pMP4AudioSampleEntry = NULL;
pCVisualSampleEntry = NULL;
};
~CSampleDescriptionBox()
{
};
void AudioSampleEntry(Byte_Stream &input_stream)
{
pCAudioSampleEntry = new CAudioSampleEntry(size,type);
pCAudioSampleEntry->ReadData(input_stream);
};
void MP4AudioSampleEntry(Byte_Stream &input_stream)
{
pMP4AudioSampleEntry = new CMP4AudioSampleEntry();
pMP4AudioSampleEntry->ReadData(input_stream);
};
void GetAudioInfo(m_u16 * ChannelCount, m_u16* SampleRate)
{
if(pCAudioSampleEntry)
{
*ChannelCount = pCAudioSampleEntry->channelcount;
*SampleRate = pCAudioSampleEntry->samplerate;
}
else
if(pMP4AudioSampleEntry)
{
*ChannelCount = pMP4AudioSampleEntry->channelcount;
*SampleRate = pMP4AudioSampleEntry->samplerate;
}
};
void VisualSampleEntry(Byte_Stream &input_stream)
{
pCVisualSampleEntry = new CVisualSampleEntry(size,type);
pCVisualSampleEntry->ReadData(input_stream);
};
//void HintSampleEntbry(){};
void ReadData(Byte_Stream &input_stream,m_u32 handler_type,m_bool bMP4File);
m_u16 GetVideoHeight()
{
if(pCVisualSampleEntry)
return pCVisualSampleEntry->height;
else
return 0;
};
m_u16 GetVideoWidth()
{
if(pCVisualSampleEntry)
return pCVisualSampleEntry->width;
else
return 0;
};
void GetConfigInfo(m_u8 *pData, long *lData)
{
if(pCVisualSampleEntry->pVideoDecConfigData != NULL)
{
memcpy(pData,pCVisualSampleEntry->pVideoDecConfigData,pCVisualSampleEntry->lConfigDataLen);
*lData = pCVisualSampleEntry->lConfigDataLen;
}
};
private:
m_u32 entry_count;
m_u32 handler_type;
CVisualSampleEntry *pCVisualSampleEntry;
CAudioSampleEntry *pCAudioSampleEntry;
//CMP4VisualSampleEntry *pMP4VisualSampleEntry;
CMP4AudioSampleEntry *pMP4AudioSampleEntry;
};
// This box contains the sample count and a table giving the size in bytes of each sample
class CSampleSizeBox :public CFullBox
{
public:
CSampleSizeBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('s','t','s','z'))
{
entry_size_list = NULL;
}
void ReadData(Byte_Stream &input_stream);
~CSampleSizeBox()
{
if(entry_size_list != NULL) {
delete entry_size_list;
entry_size_list = NULL;
}
};
m_u32 GetSampleCount();
m_u32 GetSampleSize();
m_u32 GetEntrySize(m_u32 index);
private:
m_u32 sample_size;
m_u32 sample_count;
m_u32 *entry_size_list;
};
// Sample To Chunk Box: This table can be used to find the chunk that contains
// a sample, its position, and the associated sample description.
class CSampleToChunkBox :public CFullBox
{
public:
CSampleToChunkBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('s','t','s','c'))
{
first_chunk_list = NULL;
sample_description_index_list = NULL;
samples_per_chunk_list = NULL;
}
void ReadData(Byte_Stream &input_stream);
~CSampleToChunkBox()
{
if(first_chunk_list != NULL) {
delete first_chunk_list;
first_chunk_list = NULL;
}
if(sample_description_index_list != NULL ){
delete sample_description_index_list;
sample_description_index_list = NULL;
}
if(samples_per_chunk_list != NULL ) {
delete samples_per_chunk_list;
samples_per_chunk_list = NULL;
}
};
m_u32 GetEntryCount();
m_u32 Getfirst_chunk(m_u32 index);
m_u32 Getsamples_per_chunk(m_u32 index);
m_u32 Getsample_description_index(m_u32 index);
private:
m_u32 entry_count;
m_u32 *first_chunk_list;
m_u32 *samples_per_chunk_list;
m_u32 *sample_description_index_list;
};
// The chunk offset table gives the index of each chunk into the containing file.
class CChunkOffsetBox: public CFullBox
{
public:
CChunkOffsetBox(m_u32 boxsize)
:CFullBox(boxsize,FOURCC('s','t','c','o'))
{
chunk_offset_list = NULL;
}
void ReadData(Byte_Stream &input_stream);
~CChunkOffsetBox()
{
if(chunk_offset_list != NULL ) {
delete chunk_offset_list;
chunk_offset_list = NULL;
}
}
m_u32 GetEntryCount();
m_u32 GetChunk_offset(m_u32 index);
private:
m_u32 entry_count;
m_u32 *chunk_offset_list;
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -