这部分代码个人觉得还布整洁,因为没机会整理,所以前段时间删除了。一位网友请求重新发表,于是我在整理一下发上来了
//filename mp4_boxes.cpp
#include < iostream >
#include < fstream >
#include < string >
#include < cstring >
#include < cstdlib >
#include < cerrno >
#include " mp4_boxes.h "
#ifndef RELEASE
#define RELEASE 1
#endif
#ifndef VARIABLES
#define VARIABLES \
int k = 0 ; \
unsigned char p[ 5 ]; \
int inner_size = 0 ;
#endif
static struct mp4_moov_box moov;
/* final box
*/
int mp4_read_mvhd_box(FILE * f, int size) // level 3
{
printf( " \t+%s\n " , " mvhd " );
VARIABLES;
int level_4_box_size = 0 ;
mp4_mvhd_box mvhd;
memset( & mvhd, 0 , sizeof (mvhd));
mvhd.size = size;
mvhd.type = ( ' m ' | ' v ' << 8 | ' h ' << 16 | ' d ' << 24 );
mvhd.version = read_uint8(f); // 1
fread(mvhd.flags, sizeof (mvhd.flags), 1 , f); // 3
mvhd.creation_time = read_uint32_lit(f); // 4
mvhd.modification_time = read_uint32_lit(f); // 4
mvhd.timescale = read_uint32_lit(f); // 4
mvhd.duration = read_uint32_lit(f); // 4
mvhd.rate = read_uint32_lit(f); // 4
mvhd.volume = read_uint16_big(f); // 2
fread( & mvhd.reserved1, sizeof (mvhd.reserved1), 1 , f); // 2
fread( & mvhd.reserved2, sizeof (mvhd.reserved2), 1 , f); // 8
fread(mvhd.matrix, sizeof (mvhd.matrix), 1 , f); // 36
fread(mvhd.pre_defined, sizeof (mvhd.pre_defined), 1 , f); // 24
mvhd.next_track_id = read_uint32_lit(f); // 4
moov.mvhd = mvhd;
printf( " \t\ttimescale: %u\n " , moov.mvhd.timescale);
printf( " \t\tduration: %u\n " , moov.mvhd.duration);
printf( " \t\trate: %u\n " , moov.mvhd.rate );
printf( " \t\tvolume: 0x%x\n " , moov.mvhd.volume);
printf( " \t\tmatrix:\n " );
for ( int i = 0 ; i < 3 ; ++ i){
printf( " \t\t " );
for ( int j = 0 ; j < 3 ; ++ j){
printf( " %8u " , moov.mvhd.matrix[i * 3 + j]);
}
printf( " \n " );
}
printf( " \t\tnext track id: %u\n " , moov.mvhd.next_track_id);
printf( " \n " );
}
/* final box
*/
struct mp4_tkhd_box mp4_read_tkhd_box(FILE * f, int size) // level 4
{
printf( " \t\t+%s\n " , " tkhd " );
VARIABLES;
mp4_tkhd_box box;
box.size = size;
box.type = 0 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.creation_time = read_uint32_lit(f);
box.modification_time = read_uint32_lit(f);
box.track_ID = read_uint32_lit(f);
box.reserved1 = read_uint32_lit(f);
box.duration = read_uint32_lit(f);
fread( & box.reserved2, sizeof (box.reserved2), 1 , f);
box.layer = read_uint16_big(f);
box.alternate_group = read_uint16_big(f);
box.volume = read_uint16_big(f);
box.reserved3 = read_uint16_big(f);
fread( & box.matrix, sizeof (box.matrix), 1 , f);
box.width = read_uint32_lit(f);
box.height = read_uint32_lit(f);
// printf("\t\t\tflags: 0x%4x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
// printf("\t\t\tcreation time: %u\n", box.creation_time);
// printf("\t\t\tmodifaction time: %u\n",
// box.modification_time);
printf( " \t\t\ttrack id: %u\n " , box.track_ID);
// printf("\t\t\treserved1: 0x%x\n", box.reserved1);
printf( " \t\t\tduration: %d\n " ,box.duration);
// printf("\t\t\treserved2: 0x%x, 0x%x\n",
// box.reserved2[0], box.reserved2[1]);
printf( " \t\t\tlayer: %d\n " ,box.layer);
printf( " \t\t\talternate group: %d\n " , box.alternate_group);
printf( " \t\t\tvolume: 0x%x\n " , box.volume);
// printf("\t\t\treserved3: 0x%x\n", box.reserved3);
printf( " \t\t\tmatrix:\n " );
for ( int i = 0 ; i < 3 ; ++ i){
printf( " \t\t\t " );
for ( int j = 0 ; j < 3 ; ++ j){
printf( " %8u " , box.matrix[i * 3 + j]);
}
printf( " \n " );
}
////////////////////////////////////////// @a mark still don't know
printf( " \t\t\twidth: %u\n " ,box.width);
printf( " \t\t\theight: [%u].[%u]\n " ,
box.height & 0xffff0000 >> 16 ,
box.height & 0xffff );
printf( " \n " );
return box;
}
/* container box
(elst)
*/
struct mp4_edts_box mp4_read_edts_box(FILE * f, int size)
{
printf( " \t\t+%s\n " , " edts " );
// return mp4_edts_box();
}
/* final box
*/
struct mp4_mdhd_box mp4_read_mdhd_box(FILE * f, int size)
{
printf( " \t\t\t+mdhd\n " );
struct mp4_mdhd_box box;
VARIABLES;
box.size = size;
box.type = 0 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.creation_time = read_uint32_lit(f);
box.modification_time = read_uint32_lit(f);
box.timescale = read_uint32_lit(f);
box.duration = read_uint32_lit(f);
box.language = read_uint16_big(f);
box.pre_defined = read_uint16_big(f);
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
// printf("\t\t\t\t\tcreation time: %u\n", box.creation_time);
// printf("\t\t\t\t\tmodifaction time: %u\n",
// box.modification_time);
printf( " \t\t\t\ttimescale: %u\n " , box.timescale);
printf( " \t\t\t\tduration: %u\n " , box.duration);
printf( " \t\t\t\tlanguage: %u\n " , box.language);
// printf("\t\t\t\tpre-defined: %u\n", box.pre_defined);
// printf("\n");
return box;
}
/* filnal box
*/
struct mp4_hdlr_box mp4_read_hdlr_box(FILE * f, int size)
{
printf( " \t\t\t%s\n " , " +hdlr " );
struct mp4_hdlr_box box;
VARIABLES;
box.size = size;
box.type = ' h ' | ' d ' << 8 | ' l ' << 16 | ' r ' << 24 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.pre_defined = read_uint32_lit(f);
fread( & box.handler_type, sizeof (box.handler_type), 1 , f);
box.handler_type[ 4 ] = 0 ;
fread( & box.reserved, sizeof (box.reserved), 1 , f);
fread( & inner_size, 1 , 1 , f);
box.name = new char [inner_size + 1 ];
for ( int i = 0 ; i < inner_size; ++ i)
fread( & box.name[i], sizeof (unsigned char ), 1 , f);
// printf("\t\t\t\tflags: 0x%x\n",
// box.flags[2] | box.flags[1] | box.flags[0]);
// printf("\t\t\t\tpre-defined: %d\n", box.pre_defined);
printf( " \t\t\t\thandler type: %s\n " , box.handler_type);
// printf("\t\t\t\treserved: 0x%x, 0x%x, 0x%x\n",
// box.reserved[0], box.reserved[1], box.reserved[2]);
printf( " \t\t\t\tname: %s\n " , box.name); // I have no idea what
// is this using for
// printf("\n");
return box;
}
/* final box
*/
struct mp4_vmhd_box * mp4_read_vmhd_box(FILE * f, int size)
{
printf( " \t\t\t\t+%s\n " , " vmhd " );
VARIABLES;
mp4_vmhd_box * box = new mp4_vmhd_box;
box -> size = size;
box -> type = 0 ;
box -> version = read_uint8(f);
fread( & (box -> flags), sizeof (box -> flags), 1 , f);
box -> graphics_mode = read_uint32_lit(f);
fread( & (box -> opcolor), sizeof (box -> opcolor), 1 , f);
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
printf( " \t\t\t\t\tgraphics mode: %u\n " , box -> graphics_mode);
printf( " \t\t\t\t\topcolor: %u,%u,%u,%u\n " ,
box -> opcolor[ 0 ], box -> opcolor[ 1 ],
box -> opcolor[ 2 ], box -> opcolor[ 3 ]);
// printf("\n");
}
/* final box
*/
struct mp4_smhd_box * mp4_read_smhd_box(FILE * f, int size)
{
printf( " \t\t\t\t+%s\n " , " smhd " );
mp4_smhd_box box;
box.size = size;
box.type = ' s ' | ' m ' << 8 | ' h ' << 16 | ' d ' << 24 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.balance = read_uint16_big(f);
box.reserved = read_uint16_big(f);
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
printf( " \t\t\t\t\tbalance: %d,%d\n " ,
box.balance & 0xff00 >> 8 , box.balance & 0xff );
// printf("\t\t\t\t\treserved: 0x%x\n", box.reserved);
// printf("\n");
mp4_smhd_box * newbox = new mp4_smhd_box;
* newbox = box;
return newbox;
}
struct mp4_stts_box mp4_read_stts_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stts " );
mp4_stts_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.number_of_entries = read_uint32_lit(f);
// printf("\t\t\t\t\t\tflags: %u\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tnumber of entries: %u\n " ,box.number_of_entries);
printf( " \t\t\t\t\t\tentries:\n\t\t\t\t\t\t " );
box.time_to_sample_table = new uint32_t[box.number_of_entries];
for ( int i = 0 ; i < box.number_of_entries; ++ i){
box.time_to_sample_table[i] = read_uint32_lit(f);
// printf("%5u ", box.time_to_sample_table[i]);
// if(i%16 == 0) printf("\n");
}
// delete [] box.time_to_sample_table;
printf( " \n " );
return box;
}
/* final box */
struct mp4_avcC_box * mp4_read_avcC_box(FILE * f)
{
struct mp4_avcC_box * ptr = new mp4_avcC_box;
ptr -> size = read_uint32_lit(f);
printf( " avcC_size:%u\n " ,ptr -> size);
ptr -> type = read_uint32_lit(f);
if ( ptr -> type == ( ' a ' << 24 | ' v ' << 16 | ' c ' << 8 | ' C ' )){
printf( " type:avcC\n " );
}
ptr -> configurationVersion = read_uint8(f);
printf( " configurationVersion:%u\n " , ptr -> configurationVersion);
ptr -> AVCProfileIndication = read_uint8(f);
printf( " AVCProfileIndication: %x\n " , ptr -> AVCProfileIndication);
ptr -> profile_compatibility = read_uint8(f);
ptr -> AVCLevelIndication = read_uint8(f);
ptr -> lengthSizeMinusOne = 0x3 & read_uint8(f); // 2 bit
printf( " lengthSizeMinusOne:%u\n " , ptr -> lengthSizeMinusOne);
ptr -> numOfSequenceParameterSet = 0x1F & read_uint8(f); // 5bit
printf( " numOfSequenceParameterSet:%x\n " , ptr -> numOfSequenceParameterSet);
ptr -> sps = new mp4_avcC_box::SPS[ptr -> numOfSequenceParameterSet];
for ( int i = 0 ; i < ptr -> numOfSequenceParameterSet; ++ i ){
ptr -> sps[i].sequenceParameterSetLength = read_uint16_lit(f);
printf( " sequenceParameterSetLength: %u\n " , ptr -> sps[i].sequenceParameterSetLength);
ptr -> sps[i].sequenceParameterSetNALUnit =
new uint8_t[ptr -> sps[i].sequenceParameterSetLength];
fread((ptr -> sps[i].sequenceParameterSetNALUnit),
(ptr -> sps[i].sequenceParameterSetLength), 1 , f);
for ( int j = 0 ; j < ptr -> sps[i].sequenceParameterSetLength; ++ j){
printf( " %x " , ptr -> sps[i].sequenceParameterSetNALUnit[j]);
}
printf( " ============\n " );
}
ptr -> numOfPictureParameterSets = read_uint8(f);
printf( " numOfPictureParameterSets:%u\n " , ptr -> numOfPictureParameterSets);
ptr -> pps = new mp4_avcC_box::PPS[ptr -> numOfPictureParameterSets];
for ( int i = 0 ; i < ptr -> numOfPictureParameterSets; ++ i){
ptr -> pps[i].pictureParameterSetLength = read_uint16_lit(f);
printf( " %d\n " , ptr -> pps[i].pictureParameterSetLength);
ptr -> pps[i].pictureParameterSetNALUnit
= new uint8_t[ptr -> pps[i].pictureParameterSetLength];
fread(ptr -> pps[i].pictureParameterSetNALUnit,
ptr -> pps[i].pictureParameterSetLength, 1 , f);
for ( int j = 0 ; j < ptr -> pps[i].pictureParameterSetLength; ++ j){
printf( " %x " , ptr -> pps[i].pictureParameterSetNALUnit[j]);
}
printf( " ============\n " );
}
return ptr;
}
/* final box
@a special contain a avcC box
*/
struct mp4_avc1_box * mp4_read_avc1_box(FILE * f, int size) // level 9
{
mp4_avc1_box * ptr = new mp4_avc1_box;
ptr -> size = size;
ptr -> type = (( ' a ' << 24 ) | ( ' v ' << 16 ) | ( ' c ' << 8 ) | ( ' 1 ' ));
fread(ptr -> reserved, sizeof (ptr -> reserved), 1 , f); // 6
ptr -> data_reference_index = read_uint16_lit(f); // 2
ptr -> pre_defined = read_uint16_big(f); // 2
ptr -> reserved1 = read_uint16_big(f); // 2
fread(ptr -> pre_defined1, sizeof (ptr -> pre_defined1), 1 , f); // 3*4
ptr -> width = read_uint16_lit(f); // 2
ptr -> height = read_uint16_lit(f); // 2
ptr -> horiz_res = read_uint32_lit(f); // 4
ptr -> vert_res = read_uint32_lit(f); // 4
ptr -> reserved2 = read_uint32_lit(f); // 4
ptr -> frames_count = read_uint16_lit(f); // 2
fread(ptr -> compressor_name, sizeof (ptr -> compressor_name), 1 , f); // 33
ptr -> bit_depth = read_uint8(f); // 1
ptr -> pre_defined2 = read_uint16_big(f); // 2
// avcC --AVCDecoderConfigurationRecord
printf( " -------------------------------------\n " );
printf( " data_reference_index:%x\n " , ptr -> data_reference_index);
printf( " width:%u\n " , ptr -> width);
printf( " height:%u\n " , ptr -> height);
printf( " frames_count:%x\n " , ptr -> frames_count);
printf( " bit_depth:%u\n " , ptr -> bit_depth);
printf( " pre_defined2: %x\n " , ptr -> pre_defined2);
ptr -> avcC = mp4_read_avcC_box(f);
printf( " -------------------------------------\n " );
return ptr;
}
/* final box
*/
struct mp4_mp4a_box * mp4_read_mp4a_box(FILE * f, int size) // level 9
{
printf( " \t\t\t\t\t\t+mp4a\n " );
return 0 ;
}
/* container box
(mp4a,avc1)
*/
struct mp4_stsd_box mp4_read_stsd_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stsd " );
mp4_stsd_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.number_of_entries = read_uint32_lit(f);
// printf("\t\t\t\t\t\tflags: %u\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tnumber of entries: %u\n " , box.number_of_entries);
box.sample_description = new Sample_description[box.number_of_entries];
for ( int i = 0 ; i < box.number_of_entries; ++ i){
box.sample_description[i].size = read_uint32_lit(f);
box.sample_description[i].type = read_uint32_lit(f);
if ( box.sample_description[i].type == (( ' m ' << 24 ) | ( ' p ' << 16 ) | ( ' 4 ' << 8 ) | ( ' a ' ))){
box.sample_description[i].mp4a
= mp4_read_mp4a_box(f, box.sample_description[i].size);
box.sample_description[i].avc1 = 0 ;
} else if (box.sample_description[i].type
== (( ' a ' << 24 ) | ( ' v ' << 16 ) | ( ' c ' << 8 ) | ( ' 1 ' ))){
box.sample_description[i].avc1
= mp4_read_avc1_box(f, box.sample_description[i].size);
box.sample_description[i].mp4a = 0 ;
}
}
return box;
}
/* final box
*/
struct mp4_stss_box mp4_read_stss_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stss " );
mp4_stss_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.number_of_entries = read_uint32_lit(f);
// printf("\t\t\t\t\t\t\tflags: %u\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tnumber of entries: %u\n " ,box.number_of_entries);
printf( " \t\t\t\t\t\tentries:\n " );
box.sync_sample_table = new uint32_t[box.number_of_entries];
for ( int i = 0 ; i < box.number_of_entries; ++ i){
box.sync_sample_table[i] = read_uint32_lit(f);
printf( " %6u " , box.sync_sample_table[i]);
if ( (i + 1 ) % 12 == 0 ) printf( " \n " );
}
// delete box.sync_sample_table;
printf( " \n " );
return box;
}
/* final box
*/
struct mp4_stsc_box mp4_read_stsc_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stsc " );
mp4_stsc_box box;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.map_amount = read_uint32_lit(f);
printf( " \t\t\t\t\t\tmap-amount: %u\n " , box.map_amount);
box.scmap = new mp4_list_t[box.map_amount];
printf( " \t\t\t\t\t\tfirst trunk:\tsamples-per-thunk:\tsample-description-ID\n " );
for ( int i = 0 ; i < box.map_amount; ++ i){
box.scmap[i].first_chunk_num = read_uint32_lit(f);
box.scmap[i].sample_amount_in_cur_table = read_uint32_lit(f);
box.scmap[i].sample_description_id = read_uint32_lit(f);
printf( " \t\t\t\t\t\t%13d " , box.scmap[i].first_chunk_num);
printf( " \t%13d " , box.scmap[i].sample_amount_in_cur_table);
printf( " \t%13d\n " , box.scmap[i].sample_description_id);
}
// delete box.scmap;
return box;
}
/* final box
*/
struct mp4_stsz_box mp4_read_stsz_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stsz " );
mp4_stsz_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.samples_size_intotal = read_uint32_lit(f);
if (box.samples_size_intotal == 0 ){
box.table_size = read_uint32_lit(f);
box.sample_size_table = new uint32_t[box.table_size];
// printf("\t\t\t\t\t\tflags: 0x%x\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tall samples amount: %u\n " , box.samples_size_intotal);
printf( " \t\t\t\t\t\tsample table size: %u\n " , box.table_size);
printf( " \t\t\t\t\t\tsmple_size_table:\n " );
for ( int i = 0 ; i < box.table_size; ++ i){
box.sample_size_table[i] = read_uint32_lit(f);
printf( " %8u " , box.sample_size_table[i]);
if ((i + 1 ) % 10 == 0 ) printf( " \n " );
}
printf( " \n " );
}
return box;
}
/* final box
*/
struct mp4_stco_box mp4_read_stco_box(FILE * f, int size)
{
printf( " \t\t\t\t\t+%s\n " , " stco " );
mp4_stco_box box;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.chunk_offset_amount = read_uint32_lit(f);
printf( " \t\t\t\t\t\tflags: 0x %x\n " ,
box.flags[ 0 ] | box.flags[ 1 ] | box.flags[ 2 ]);
printf( " \t\t\t\t\t\tchunk offest amount: %u\n " ,
box.chunk_offset_amount);
printf( " \t\t\t\t\t\tchunk offset:\n " );
box.chunk_offset_from_file_begin = new uint32_t[box.chunk_offset_amount];
for ( int i = 0 ; i < box.chunk_offset_amount; ++ i){
box.chunk_offset_from_file_begin[i] = read_uint32_lit(f);
printf( " %8x " , box.chunk_offset_from_file_begin[i]);
if ((i + 1 ) % 10 == 0 ) printf( " \n " );
}
// delete [] box.chunk_offset_from_file_begin;
return box;
}
/* container box
(stsd, stts, stsz|stz2, stsc, stco|co64, ctts, stss)
*/
struct mp4_stbl_box mp4_read_stbl_box(FILE * f, int size)
{
printf( " \t\t\t\t+stbl\n " );
mp4_stbl_box box;
VARIABLES;
int box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " stsd " ) {
box.stsd = mp4_read_stsd_box(f, box_size);
// 根据不同的编码方案和存储数据的文件数目,
// 每个media可以有一个到多个sample description。
// sample-to-chunk atom通过这个索引表,
// 找到合适medai中每个sample的description。
} else if (name == " stts " ){
box.stts = mp4_read_stts_box(f, box_size);
// Time-to-sample atoms存储了media sample的duration 信息,
// 提供了时间对具体data sample的映射方法,通过这个atom,
// 你可以找到任何时间的sample,类型是'stts'。
} else if (name == " stss " ){
box.stss = mp4_read_stss_box(f, box_size);
// sync sample atom确定media中的关键帧。
} else if (name == " stsc " ){
box.stsc = mp4_read_stsc_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7922.html
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7923.html
} else if (name == " stsz " || name == " stz2 " ){
box.stsz = mp4_read_stsz_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7924.html
} else if (name == " stco " || name == " c064 " ){
box.stco = mp4_read_stco_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7925.html
} else if (name == " ctts " ) {
// @a undefined
} else {
// printf("\t\t====size: %u\n", box_size);
printf( " \t\t\t\t\t+%s===============mark undifined\n " , p);
}
cur_pos += box_size;
inner_size += box_size;
} while (inner_size + 8 != size);
// printf("\n");
return box;
}
/* container box
()
*/
struct mp4_dinf_box mp4_read_dinf_box(FILE * f, int size)
{
printf( " \t\t\t\t+dinf\n " );
struct mp4_dinf_box box;
return box;
}
/* container box
(vmhd, smhd, hmhd, nmhd)
*/
struct mp4_minf_box mp4_read_minf_box(FILE * f, int size)
{
struct mp4_minf_box box;
printf( " \t\t\t+%s\n " , " minf " );
VARIABLES;
int level_5_box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
level_5_box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " vmhd " ) {
box.vmhd = mp4_read_vmhd_box(f, level_5_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7913.html
} else if (name == " dinf " ) {
box.dinf = mp4_read_dinf_box(f, level_5_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7915.html
} else if (name == " stbl " ) {
box.stbl = mp4_read_stbl_box(f, level_5_box_size);
// @a unfind
} else if (name == " smhd " ){
box.smhd = mp4_read_smhd_box(f, level_5_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7914.html
} else {
printf( " \t\t====size: %u\n " , level_5_box_size);
printf( " \t\t====type: %s\n " , p);
}
cur_pos += level_5_box_size;
inner_size += level_5_box_size;
} while (inner_size + 8 != size);
printf( " \n " );
return box;
}
/* container box
(mdhd, hdlr, minf)
*/
struct mp4_mdia_box mp4_read_mdia_box(FILE * f, int size)
{
printf( " \t\t+%s\n " , " mdia " );
mp4_mdia_box box;
box.size = size;
box.type = ' m ' | ' d ' << 8 | ' i ' << 16 | ' a ' << 24 ;
VARIABLES;
int box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " mdhd " ) {
box.mdhd = mp4_read_mdhd_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7908.html
} else if (name == " hdlr " ) {
box.hdlr = mp4_read_hdlr_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7909.html
} else if (name == " minf " ){
box.minf = mp4_read_minf_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7910.html
} else {
// printf("\t\t====size: %u\n", box_size);
printf( " \t\t====type: %s\n " , p);
}
cur_pos += box_size;
inner_size += box_size;
} while (inner_size + 8 != size);
printf( " \n " );
return box;
}
/* container box
*/
struct mp4_udta_box mp4_read_udta_box(FILE * f, int size)
{
printf( " \t\t+%s\n " , " udta " );
return mp4_udta_box();
}
/* container box
(tkhd, mdia)
*/
int mp4_read_trak_box(FILE * f, int size)
{
printf( " \t+%s\n " , " trak " );
struct mp4_trak_box * trak = new struct mp4_trak_box;
VARIABLES;
int box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " tkhd " ) {
trak -> tkhd = mp4_read_tkhd_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7903.html
} else if (name == " edts " ) {
trak -> edts = mp4_read_edts_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7904.html
} else if (name == " mdia " ){
trak -> mdia = mp4_read_mdia_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7907.html
} else if (name == " udta " ){
trak -> udta = mp4_read_udta_box(f, box_size);
// same as the level 3 box, @a special
} else {
// printf("\t====size: %u\n", box_size);
printf( " \t\t+%s===========\n " , p);
}
cur_pos += box_size;
inner_size += box_size;
} while (inner_size + 8 != size);
moov.trak.push_back(trak);
}
/* final box
*/
int mp4_read_iods_box(FILE * f, int size) // level 3
{
printf( " \t+iods-------------------------undefined\n\n " );
}
/* container box
(mvhd, trak)
*/
int mp4_read_moov_box(FILE * f, int size) // level 2
{
printf( " +%s\n " , " moov " );
moov.size = size;
moov.type = ' m ' | ' o ' << 8 | ' o ' << 16 | ' v ' << 24 ;
VARIABLES;
int level_2_box_size = 0 ;
int cur_pos = ftell(f);
do {
fseek(f, cur_pos, SEEK_SET);
level_2_box_size = read_uint32_lit(f);
fread( & k, sizeof (k), 1 , f); // read byte
indian_a.size = k;
memcpy(p, indian_a. byte , sizeof (indian_a. byte ));
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " mvhd " ){
mp4_read_mvhd_box(f, level_2_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7901.html
} else if (name == " trak " ) {
mp4_read_trak_box(f, level_2_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7902.html
} else if (name == " iods " ){
mp4_read_iods_box(f, level_2_box_size);
} else if (name == " udta " ){
mp4_read_udta_box(f, level_2_box_size);
// @a mark parse it, unknow what it is
} else {
printf( " ====%s\n\n " , p);
}
cur_pos += level_2_box_size;
inner_size += level_2_box_size;
} while ( inner_size + 8 != size);
}
/* final box
*/
int mp4_read_ftyp_box(FILE * f, int size) // level 2
{
printf( " +ftyp\n " );
size -= 8 ;
char * ch = new char [size + 1 ];
for ( int i = 0 ; i < size; ++ i) {
fread( & ch[i], sizeof ( char ), 1 , f);
}
ch[size] = 0 ;
printf( " \tftyp: %s\n " , ch);
delete [] ch;
}
/* @a special final box
*/
int mp4_read_mdat_box(FILE * f, int size)
{
printf( " \t+%s\n " , " mdat " );
printf( " \t\tthis is the real media data\n " );
}
/* container box
(ftyp, free, mdat, moov)
*/
int mp4_read_root_box(FILE * f) // level 1
{
int k = 0 ;
unsigned char p[ 5 ];
int level_1_box_size = read_uint32_lit(f);
fread( & k, sizeof (k), 1 , f); // read byte
indian_a.size = k;
memcpy(p, indian_a. byte , sizeof (indian_a. byte ));
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " moov " ){
mp4_read_moov_box(f, level_1_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7900.html
} else if (name == " ftyp " ){
mp4_read_ftyp_box(f, level_1_box_size);
} else if (level_1_box_size == 0 ){ // till the end of file
return 1 ;
} else if (name == " mdat " ){
mp4_read_mdat_box(f, level_1_box_size);
} else if (name == " free " ){
printf( " +free\n " );
} else {
// printf("==%u\n", level_1_box_size);
printf( " %s==mark undifined\n " , p);
}
return level_1_box_size;
}
void print_trak( const struct mp4_trak_box * trak)
{
printf( " trak\n " );
printf( " \t+%s\n " , " tkhd " );
printf( " \t\ttrack id: %u\n " , trak -> tkhd.track_ID);
printf( " \t\tduration: %d\n " , trak -> tkhd.duration);
printf( " \t\t\tlayer: %d\n " ,trak -> tkhd.layer);
printf( " \t\t\talternate group: %d\n " , trak -> tkhd.alternate_group);
printf( " \t\t\tvolume: 0x%x\n " , trak -> tkhd.volume);
printf( " \t\t\tmatrix:\n " );
for ( int i = 0 ; i < 3 ; ++ i){
printf( " \t\t\t " );
for ( int j = 0 ; j < 3 ; ++ j){
printf( " %8u " , trak -> tkhd.matrix[i * 3 + j]);
}
printf( " \n " );
}
printf( " \t\t\twidth: %u\n " ,trak -> tkhd.width);
printf( " \t\t\theight: [%u].[%u]\n " ,
trak -> tkhd.height & 0xffff0000 >> 16 ,
trak -> tkhd.height & 0xffff );
printf( " \t+%s\n " , " mdia " );
printf( " \t\t\t\t\t\t+stsd\n " );
printf( " \t\t\t\t\t\t\tnumber of entries: %u\n " ,
trak -> mdia.minf.stbl.stsd.number_of_entries);
// printf("\t\t\t\t\t\t+stts: time to sample\n");
// printf("\t\t\t\t\t\t\tentries:\n\t\t\t\t\t\t\t");
// for(int i =0; i < trak->mdia.minf.stbl.stts.number_of_entries; ++i){
// printf("%15u ", trak->mdia.minf.stbl.stts.time_to_sample_table[i]);
// }
// printf("\n");
// printf("\t\t\t\t\t+stss:关键帧\n");
// printf("\t\t\t\t\t\t\tentries:\n\t\t\t\t\t\t\t");
// for(int i =0; i < trak->mdia.minf.stbl.stss.number_of_entries; ++i){
// printf("%15u ", trak->mdia.minf.stbl.stss.sync_sample_table[i]);
// }
// printf("\n");
printf( " \t\t\t\t\t\t+stsc:sample to chunk table\n " );
printf( " \t\t\t\t\t\tfirst trunk:\tsamples-per-thunk:\tsample-description-ID\n " );
for ( int i = 0 ; i < trak -> mdia.minf.stbl.stsc.map_amount; ++ i){
printf( " \t\t\t\t\t\t%13d " , trak -> mdia.minf.stbl.stsc.scmap[i].first_chunk_num);
printf( " \t%13d " , trak -> mdia.minf.stbl.stsc.scmap[i].sample_amount_in_cur_table);
printf( " \t%13d\n " , trak -> mdia.minf.stbl.stsc.scmap[i].sample_description_id);
} printf( " \n " );
printf( " \t\t\t\t\t\t+%s\n " , " stsz " );
printf( " \t\t\t\t\t\t\tsmple_size_table:\n\t\t\t\t\t\t " );
for ( int i = 0 ; i < trak -> mdia.minf.stbl.stsz.table_size; ++ i){
printf( " %8u " , trak -> mdia.minf.stbl.stsz.sample_size_table[i]);
} printf( " \n " );
printf( " \t\t\t\t\t\t+stco\n " );
printf( " \t\t\t\t\t\tchunk offset:\n\t\t\t\t\t " );
for ( int i = 0 ; i < trak -> mdia.minf.stbl.stco.chunk_offset_amount; ++ i){
printf( " %8u " ,trak -> mdia.minf.stbl.stco.chunk_offset_from_file_begin[i]);
}
}
uint32_t get_sample_num_in_cur_chunk( const struct mp4_stsc_box & box,
const uint32_t chunk_index) // begin from 0
{
int sample_num_in_cur_chunk_ = 0 ;
for ( int i = 0 ; i < box.map_amount; ++ i) {
if (i + 1 == box.map_amount){
// std::cout<<"chunk_index:"<<chunk_index<<std::endl;
sample_num_in_cur_chunk_
= box.scmap[i].sample_amount_in_cur_table;
}
if (chunk_index + 1 >= box.scmap[i].first_chunk_num
&& chunk_index + 1 < box.scmap[i + 1 ].first_chunk_num){
sample_num_in_cur_chunk_
= box.scmap[i].sample_amount_in_cur_table;
break ;
}
}
// std::cout<<"sample_num_in_cur_chunk_:"<< sample_num_in_cur_chunk_;
return sample_num_in_cur_chunk_;
}
/* @a return index from 0 */
uint32_t get_sample_index( const struct mp4_stsc_box & box,
const uint32_t chunk_index) // [1,end)
{
/* chunk samples id
1 8 1
2 7 1
46 6 1
*/
uint32_t me = chunk_index;
uint32_t sindex = 0 ;
for ( int i = 0 ; i < box.map_amount; ++ i) {
uint32_t chunk_amount = 0 ;
uint32_t curr = box.scmap[i].first_chunk_num;
if (i + 1 == box.map_amount){ // end() , we can't have next one to index
chunk_amount = me - curr; // do not add ONE
sindex += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
break ;
}
uint32_t next = box.scmap[i + 1 ].first_chunk_num;
if (me > curr){
if (me < next){
chunk_amount = me - curr; // do not add ONE
sindex += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
break ;
} else {
chunk_amount = next - curr; // do not add ONE
sindex += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
}
} else if (me == curr){
break ;
}
}
return sindex;
}
uint32_t get_sample_size( const struct mp4_stsz_box & box,
const uint32_t chunk_index) // [0, end)
{
for ( int i = 0 ; i < box.table_size; ++ i) {
if (chunk_index == i)
return box.sample_size_table[i];
}
}
void copy_chunk_data(FILE * fin,
const struct mp4_stbl_box & box,
const uint32_t chunk_index, // [0, end)
FILE * fout)
{
fseek(fin, box.stco.chunk_offset_from_file_begin[chunk_index],
SEEK_SET);
uint32_t sample_num_in_cur_chunk_
= get_sample_num_in_cur_chunk(box.stsc, chunk_index); // @a mark
uint32_t sample_index_
= get_sample_index(box.stsc, chunk_index + 1 );
printf( " %x\tindex=%u\t " ,
box.stco.chunk_offset_from_file_begin[chunk_index],
sample_index_);
for ( int i = 0 ; i < sample_num_in_cur_chunk_; ++ i) {
uint32_t sample_size_ = get_sample_size(box.stsz, sample_index_ + i);
std::cout << sample_size_ << std::endl;
uint32_t NALU_size = 0 ;
uint32_t NALU_total = 0 ;
while (NALU_total < sample_size_){
NALU_size = read_uint32_lit(fin);
NALU_total += NALU_size + 4 ;
printf( " \tNALU_size:%x\n " , NALU_size);
char * ptr = new char [NALU_size];
fread(ptr, NALU_size, 1 , fin);
static uint32_t one = 1 << 24 ;
fwrite( & one, sizeof (one), 1 , fout);
fwrite(ptr, NALU_size, 1 , fout);
delete [] ptr;
NALU_size = 0 ;
}
}
}
void make_file(FILE * fin, const struct mp4_trak_box * trak, std:: string name)
{
int chunk_offset_amount = trak -> mdia.minf.stbl.stco.chunk_offset_amount;
#if RELEASE
struct mp4_avc1_box * avc1 =
trak -> mdia.minf.stbl.stsd.sample_description[ 0 ].avc1;
name += " x " ;
FILE * fout = fopen(name.c_str(), " w " );
if ( ! fout){
std:: string tmp = " fopen_ " + name ;
perror(tmp.c_str());
}
if (avc1 != 0 ){
uint32_t one = 1 << 24 ;
fwrite( & one, sizeof (one), 1 , fout);
struct mp4_avcC_box * avcC = avc1 -> avcC;
fwrite(avcC -> sps[ 0 ].sequenceParameterSetNALUnit,
avcC -> sps[ 0 ].sequenceParameterSetLength, 1 , fout);
fwrite( & one, sizeof (one), 1 , fout);
fwrite(avcC -> pps[ 0 ].pictureParameterSetNALUnit,
avcC -> pps[ 0 ].pictureParameterSetLength, 1 , fout);
}
for ( int chunk_index = 0 ; chunk_index < chunk_offset_amount;
++ chunk_index) {
copy_chunk_data(fin, trak -> mdia.minf.stbl, chunk_index, fout);
}
fclose(fout);
#else
system(std:: string ( " rm -rf " + name).c_str());
system(std:: string ( " mkdir " + name).c_str());
for ( int chunk_index = 0 ; chunk_index < chunk_offset_amount;
++ chunk_index) {
char char_num[ 10 ];
sprintf(char_num, " %u " , chunk_index);
FILE * fout =
fopen(std:: string (name + " / " + name + char_num).c_str(), " w " );
if (fout == (FILE * ) 0 ){
printf( " error\n " );
std::exit( - 1 );
}
copy_chunk_data(fin, trak -> mdia.minf.stbl, chunk_index, fout);
fclose(fout);
}
#endif
}
int main(){
std::ios_base::sync_with_stdio( true );
std:: string luo = " luohunshidai01_001.mp4 " ;
std:: string _600 = " 6004501011.mp4 " ;
// FILE *fin = fopen(luo.c_str(), "r");
FILE * fin = fopen(_600.c_str(), " r " );
// FILE *f_video = fopen("video", "w+");
// FILE *f_audio = fopen("audio", "w+");
if (fin == (FILE * ) 0 ){
printf( " failed to open\n " );
return 0 ;
}
// level 0
int cur_pos = ftell(fin);
for (; ! feof(fin); ) {
fseek(fin, cur_pos, SEEK_SET);
printf( " ----------------------------------------level 0\n " );
cur_pos += mp4_read_root_box(fin);
}
// print_trak(moov.trak[0]);
// print_trak(moov.trak[1]);
make_file(fin, moov.trak[ 0 ], ( " video " ));
// make_file(fin, moov.trak[1], ("audio"));
return 0 ;
}
#include < iostream >
#include < fstream >
#include < string >
#include < cstring >
#include < cstdlib >
#include < cerrno >
#include " mp4_boxes.h "
#ifndef RELEASE
#define RELEASE 1
#endif
#ifndef VARIABLES
#define VARIABLES \
int k = 0 ; \
unsigned char p[ 5 ]; \
int inner_size = 0 ;
#endif
static struct mp4_moov_box moov;
/* final box
*/
int mp4_read_mvhd_box(FILE * f, int size) // level 3
{
printf( " \t+%s\n " , " mvhd " );
VARIABLES;
int level_4_box_size = 0 ;
mp4_mvhd_box mvhd;
memset( & mvhd, 0 , sizeof (mvhd));
mvhd.size = size;
mvhd.type = ( ' m ' | ' v ' << 8 | ' h ' << 16 | ' d ' << 24 );
mvhd.version = read_uint8(f); // 1
fread(mvhd.flags, sizeof (mvhd.flags), 1 , f); // 3
mvhd.creation_time = read_uint32_lit(f); // 4
mvhd.modification_time = read_uint32_lit(f); // 4
mvhd.timescale = read_uint32_lit(f); // 4
mvhd.duration = read_uint32_lit(f); // 4
mvhd.rate = read_uint32_lit(f); // 4
mvhd.volume = read_uint16_big(f); // 2
fread( & mvhd.reserved1, sizeof (mvhd.reserved1), 1 , f); // 2
fread( & mvhd.reserved2, sizeof (mvhd.reserved2), 1 , f); // 8
fread(mvhd.matrix, sizeof (mvhd.matrix), 1 , f); // 36
fread(mvhd.pre_defined, sizeof (mvhd.pre_defined), 1 , f); // 24
mvhd.next_track_id = read_uint32_lit(f); // 4
moov.mvhd = mvhd;
printf( " \t\ttimescale: %u\n " , moov.mvhd.timescale);
printf( " \t\tduration: %u\n " , moov.mvhd.duration);
printf( " \t\trate: %u\n " , moov.mvhd.rate );
printf( " \t\tvolume: 0x%x\n " , moov.mvhd.volume);
printf( " \t\tmatrix:\n " );
for ( int i = 0 ; i < 3 ; ++ i){
printf( " \t\t " );
for ( int j = 0 ; j < 3 ; ++ j){
printf( " %8u " , moov.mvhd.matrix[i * 3 + j]);
}
printf( " \n " );
}
printf( " \t\tnext track id: %u\n " , moov.mvhd.next_track_id);
printf( " \n " );
}
/* final box
*/
struct mp4_tkhd_box mp4_read_tkhd_box(FILE * f, int size) // level 4
{
printf( " \t\t+%s\n " , " tkhd " );
VARIABLES;
mp4_tkhd_box box;
box.size = size;
box.type = 0 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.creation_time = read_uint32_lit(f);
box.modification_time = read_uint32_lit(f);
box.track_ID = read_uint32_lit(f);
box.reserved1 = read_uint32_lit(f);
box.duration = read_uint32_lit(f);
fread( & box.reserved2, sizeof (box.reserved2), 1 , f);
box.layer = read_uint16_big(f);
box.alternate_group = read_uint16_big(f);
box.volume = read_uint16_big(f);
box.reserved3 = read_uint16_big(f);
fread( & box.matrix, sizeof (box.matrix), 1 , f);
box.width = read_uint32_lit(f);
box.height = read_uint32_lit(f);
// printf("\t\t\tflags: 0x%4x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
// printf("\t\t\tcreation time: %u\n", box.creation_time);
// printf("\t\t\tmodifaction time: %u\n",
// box.modification_time);
printf( " \t\t\ttrack id: %u\n " , box.track_ID);
// printf("\t\t\treserved1: 0x%x\n", box.reserved1);
printf( " \t\t\tduration: %d\n " ,box.duration);
// printf("\t\t\treserved2: 0x%x, 0x%x\n",
// box.reserved2[0], box.reserved2[1]);
printf( " \t\t\tlayer: %d\n " ,box.layer);
printf( " \t\t\talternate group: %d\n " , box.alternate_group);
printf( " \t\t\tvolume: 0x%x\n " , box.volume);
// printf("\t\t\treserved3: 0x%x\n", box.reserved3);
printf( " \t\t\tmatrix:\n " );
for ( int i = 0 ; i < 3 ; ++ i){
printf( " \t\t\t " );
for ( int j = 0 ; j < 3 ; ++ j){
printf( " %8u " , box.matrix[i * 3 + j]);
}
printf( " \n " );
}
////////////////////////////////////////// @a mark still don't know
printf( " \t\t\twidth: %u\n " ,box.width);
printf( " \t\t\theight: [%u].[%u]\n " ,
box.height & 0xffff0000 >> 16 ,
box.height & 0xffff );
printf( " \n " );
return box;
}
/* container box
(elst)
*/
struct mp4_edts_box mp4_read_edts_box(FILE * f, int size)
{
printf( " \t\t+%s\n " , " edts " );
// return mp4_edts_box();
}
/* final box
*/
struct mp4_mdhd_box mp4_read_mdhd_box(FILE * f, int size)
{
printf( " \t\t\t+mdhd\n " );
struct mp4_mdhd_box box;
VARIABLES;
box.size = size;
box.type = 0 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.creation_time = read_uint32_lit(f);
box.modification_time = read_uint32_lit(f);
box.timescale = read_uint32_lit(f);
box.duration = read_uint32_lit(f);
box.language = read_uint16_big(f);
box.pre_defined = read_uint16_big(f);
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
// printf("\t\t\t\t\tcreation time: %u\n", box.creation_time);
// printf("\t\t\t\t\tmodifaction time: %u\n",
// box.modification_time);
printf( " \t\t\t\ttimescale: %u\n " , box.timescale);
printf( " \t\t\t\tduration: %u\n " , box.duration);
printf( " \t\t\t\tlanguage: %u\n " , box.language);
// printf("\t\t\t\tpre-defined: %u\n", box.pre_defined);
// printf("\n");
return box;
}
/* filnal box
*/
struct mp4_hdlr_box mp4_read_hdlr_box(FILE * f, int size)
{
printf( " \t\t\t%s\n " , " +hdlr " );
struct mp4_hdlr_box box;
VARIABLES;
box.size = size;
box.type = ' h ' | ' d ' << 8 | ' l ' << 16 | ' r ' << 24 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.pre_defined = read_uint32_lit(f);
fread( & box.handler_type, sizeof (box.handler_type), 1 , f);
box.handler_type[ 4 ] = 0 ;
fread( & box.reserved, sizeof (box.reserved), 1 , f);
fread( & inner_size, 1 , 1 , f);
box.name = new char [inner_size + 1 ];
for ( int i = 0 ; i < inner_size; ++ i)
fread( & box.name[i], sizeof (unsigned char ), 1 , f);
// printf("\t\t\t\tflags: 0x%x\n",
// box.flags[2] | box.flags[1] | box.flags[0]);
// printf("\t\t\t\tpre-defined: %d\n", box.pre_defined);
printf( " \t\t\t\thandler type: %s\n " , box.handler_type);
// printf("\t\t\t\treserved: 0x%x, 0x%x, 0x%x\n",
// box.reserved[0], box.reserved[1], box.reserved[2]);
printf( " \t\t\t\tname: %s\n " , box.name); // I have no idea what
// is this using for
// printf("\n");
return box;
}
/* final box
*/
struct mp4_vmhd_box * mp4_read_vmhd_box(FILE * f, int size)
{
printf( " \t\t\t\t+%s\n " , " vmhd " );
VARIABLES;
mp4_vmhd_box * box = new mp4_vmhd_box;
box -> size = size;
box -> type = 0 ;
box -> version = read_uint8(f);
fread( & (box -> flags), sizeof (box -> flags), 1 , f);
box -> graphics_mode = read_uint32_lit(f);
fread( & (box -> opcolor), sizeof (box -> opcolor), 1 , f);
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
printf( " \t\t\t\t\tgraphics mode: %u\n " , box -> graphics_mode);
printf( " \t\t\t\t\topcolor: %u,%u,%u,%u\n " ,
box -> opcolor[ 0 ], box -> opcolor[ 1 ],
box -> opcolor[ 2 ], box -> opcolor[ 3 ]);
// printf("\n");
}
/* final box
*/
struct mp4_smhd_box * mp4_read_smhd_box(FILE * f, int size)
{
printf( " \t\t\t\t+%s\n " , " smhd " );
mp4_smhd_box box;
box.size = size;
box.type = ' s ' | ' m ' << 8 | ' h ' << 16 | ' d ' << 24 ;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.balance = read_uint16_big(f);
box.reserved = read_uint16_big(f);
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
// | box.flags[1] | box.flags[0]);
printf( " \t\t\t\t\tbalance: %d,%d\n " ,
box.balance & 0xff00 >> 8 , box.balance & 0xff );
// printf("\t\t\t\t\treserved: 0x%x\n", box.reserved);
// printf("\n");
mp4_smhd_box * newbox = new mp4_smhd_box;
* newbox = box;
return newbox;
}
struct mp4_stts_box mp4_read_stts_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stts " );
mp4_stts_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.number_of_entries = read_uint32_lit(f);
// printf("\t\t\t\t\t\tflags: %u\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tnumber of entries: %u\n " ,box.number_of_entries);
printf( " \t\t\t\t\t\tentries:\n\t\t\t\t\t\t " );
box.time_to_sample_table = new uint32_t[box.number_of_entries];
for ( int i = 0 ; i < box.number_of_entries; ++ i){
box.time_to_sample_table[i] = read_uint32_lit(f);
// printf("%5u ", box.time_to_sample_table[i]);
// if(i%16 == 0) printf("\n");
}
// delete [] box.time_to_sample_table;
printf( " \n " );
return box;
}
/* final box */
struct mp4_avcC_box * mp4_read_avcC_box(FILE * f)
{
struct mp4_avcC_box * ptr = new mp4_avcC_box;
ptr -> size = read_uint32_lit(f);
printf( " avcC_size:%u\n " ,ptr -> size);
ptr -> type = read_uint32_lit(f);
if ( ptr -> type == ( ' a ' << 24 | ' v ' << 16 | ' c ' << 8 | ' C ' )){
printf( " type:avcC\n " );
}
ptr -> configurationVersion = read_uint8(f);
printf( " configurationVersion:%u\n " , ptr -> configurationVersion);
ptr -> AVCProfileIndication = read_uint8(f);
printf( " AVCProfileIndication: %x\n " , ptr -> AVCProfileIndication);
ptr -> profile_compatibility = read_uint8(f);
ptr -> AVCLevelIndication = read_uint8(f);
ptr -> lengthSizeMinusOne = 0x3 & read_uint8(f); // 2 bit
printf( " lengthSizeMinusOne:%u\n " , ptr -> lengthSizeMinusOne);
ptr -> numOfSequenceParameterSet = 0x1F & read_uint8(f); // 5bit
printf( " numOfSequenceParameterSet:%x\n " , ptr -> numOfSequenceParameterSet);
ptr -> sps = new mp4_avcC_box::SPS[ptr -> numOfSequenceParameterSet];
for ( int i = 0 ; i < ptr -> numOfSequenceParameterSet; ++ i ){
ptr -> sps[i].sequenceParameterSetLength = read_uint16_lit(f);
printf( " sequenceParameterSetLength: %u\n " , ptr -> sps[i].sequenceParameterSetLength);
ptr -> sps[i].sequenceParameterSetNALUnit =
new uint8_t[ptr -> sps[i].sequenceParameterSetLength];
fread((ptr -> sps[i].sequenceParameterSetNALUnit),
(ptr -> sps[i].sequenceParameterSetLength), 1 , f);
for ( int j = 0 ; j < ptr -> sps[i].sequenceParameterSetLength; ++ j){
printf( " %x " , ptr -> sps[i].sequenceParameterSetNALUnit[j]);
}
printf( " ============\n " );
}
ptr -> numOfPictureParameterSets = read_uint8(f);
printf( " numOfPictureParameterSets:%u\n " , ptr -> numOfPictureParameterSets);
ptr -> pps = new mp4_avcC_box::PPS[ptr -> numOfPictureParameterSets];
for ( int i = 0 ; i < ptr -> numOfPictureParameterSets; ++ i){
ptr -> pps[i].pictureParameterSetLength = read_uint16_lit(f);
printf( " %d\n " , ptr -> pps[i].pictureParameterSetLength);
ptr -> pps[i].pictureParameterSetNALUnit
= new uint8_t[ptr -> pps[i].pictureParameterSetLength];
fread(ptr -> pps[i].pictureParameterSetNALUnit,
ptr -> pps[i].pictureParameterSetLength, 1 , f);
for ( int j = 0 ; j < ptr -> pps[i].pictureParameterSetLength; ++ j){
printf( " %x " , ptr -> pps[i].pictureParameterSetNALUnit[j]);
}
printf( " ============\n " );
}
return ptr;
}
/* final box
@a special contain a avcC box
*/
struct mp4_avc1_box * mp4_read_avc1_box(FILE * f, int size) // level 9
{
mp4_avc1_box * ptr = new mp4_avc1_box;
ptr -> size = size;
ptr -> type = (( ' a ' << 24 ) | ( ' v ' << 16 ) | ( ' c ' << 8 ) | ( ' 1 ' ));
fread(ptr -> reserved, sizeof (ptr -> reserved), 1 , f); // 6
ptr -> data_reference_index = read_uint16_lit(f); // 2
ptr -> pre_defined = read_uint16_big(f); // 2
ptr -> reserved1 = read_uint16_big(f); // 2
fread(ptr -> pre_defined1, sizeof (ptr -> pre_defined1), 1 , f); // 3*4
ptr -> width = read_uint16_lit(f); // 2
ptr -> height = read_uint16_lit(f); // 2
ptr -> horiz_res = read_uint32_lit(f); // 4
ptr -> vert_res = read_uint32_lit(f); // 4
ptr -> reserved2 = read_uint32_lit(f); // 4
ptr -> frames_count = read_uint16_lit(f); // 2
fread(ptr -> compressor_name, sizeof (ptr -> compressor_name), 1 , f); // 33
ptr -> bit_depth = read_uint8(f); // 1
ptr -> pre_defined2 = read_uint16_big(f); // 2
// avcC --AVCDecoderConfigurationRecord
printf( " -------------------------------------\n " );
printf( " data_reference_index:%x\n " , ptr -> data_reference_index);
printf( " width:%u\n " , ptr -> width);
printf( " height:%u\n " , ptr -> height);
printf( " frames_count:%x\n " , ptr -> frames_count);
printf( " bit_depth:%u\n " , ptr -> bit_depth);
printf( " pre_defined2: %x\n " , ptr -> pre_defined2);
ptr -> avcC = mp4_read_avcC_box(f);
printf( " -------------------------------------\n " );
return ptr;
}
/* final box
*/
struct mp4_mp4a_box * mp4_read_mp4a_box(FILE * f, int size) // level 9
{
printf( " \t\t\t\t\t\t+mp4a\n " );
return 0 ;
}
/* container box
(mp4a,avc1)
*/
struct mp4_stsd_box mp4_read_stsd_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stsd " );
mp4_stsd_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.number_of_entries = read_uint32_lit(f);
// printf("\t\t\t\t\t\tflags: %u\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tnumber of entries: %u\n " , box.number_of_entries);
box.sample_description = new Sample_description[box.number_of_entries];
for ( int i = 0 ; i < box.number_of_entries; ++ i){
box.sample_description[i].size = read_uint32_lit(f);
box.sample_description[i].type = read_uint32_lit(f);
if ( box.sample_description[i].type == (( ' m ' << 24 ) | ( ' p ' << 16 ) | ( ' 4 ' << 8 ) | ( ' a ' ))){
box.sample_description[i].mp4a
= mp4_read_mp4a_box(f, box.sample_description[i].size);
box.sample_description[i].avc1 = 0 ;
} else if (box.sample_description[i].type
== (( ' a ' << 24 ) | ( ' v ' << 16 ) | ( ' c ' << 8 ) | ( ' 1 ' ))){
box.sample_description[i].avc1
= mp4_read_avc1_box(f, box.sample_description[i].size);
box.sample_description[i].mp4a = 0 ;
}
}
return box;
}
/* final box
*/
struct mp4_stss_box mp4_read_stss_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stss " );
mp4_stss_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.number_of_entries = read_uint32_lit(f);
// printf("\t\t\t\t\t\t\tflags: %u\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tnumber of entries: %u\n " ,box.number_of_entries);
printf( " \t\t\t\t\t\tentries:\n " );
box.sync_sample_table = new uint32_t[box.number_of_entries];
for ( int i = 0 ; i < box.number_of_entries; ++ i){
box.sync_sample_table[i] = read_uint32_lit(f);
printf( " %6u " , box.sync_sample_table[i]);
if ( (i + 1 ) % 12 == 0 ) printf( " \n " );
}
// delete box.sync_sample_table;
printf( " \n " );
return box;
}
/* final box
*/
struct mp4_stsc_box mp4_read_stsc_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stsc " );
mp4_stsc_box box;
box.version = read_uint8(f);
fread( & box.flags, sizeof (box.flags), 1 , f);
box.map_amount = read_uint32_lit(f);
printf( " \t\t\t\t\t\tmap-amount: %u\n " , box.map_amount);
box.scmap = new mp4_list_t[box.map_amount];
printf( " \t\t\t\t\t\tfirst trunk:\tsamples-per-thunk:\tsample-description-ID\n " );
for ( int i = 0 ; i < box.map_amount; ++ i){
box.scmap[i].first_chunk_num = read_uint32_lit(f);
box.scmap[i].sample_amount_in_cur_table = read_uint32_lit(f);
box.scmap[i].sample_description_id = read_uint32_lit(f);
printf( " \t\t\t\t\t\t%13d " , box.scmap[i].first_chunk_num);
printf( " \t%13d " , box.scmap[i].sample_amount_in_cur_table);
printf( " \t%13d\n " , box.scmap[i].sample_description_id);
}
// delete box.scmap;
return box;
}
/* final box
*/
struct mp4_stsz_box mp4_read_stsz_box(FILE * f, int size) // level 8
{
printf( " \t\t\t\t\t+%s\n " , " stsz " );
mp4_stsz_box box;
box.size = size;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.samples_size_intotal = read_uint32_lit(f);
if (box.samples_size_intotal == 0 ){
box.table_size = read_uint32_lit(f);
box.sample_size_table = new uint32_t[box.table_size];
// printf("\t\t\t\t\t\tflags: 0x%x\n",
// box.flags[0]|box.flags[1]|box.flags[2]);
printf( " \t\t\t\t\t\tall samples amount: %u\n " , box.samples_size_intotal);
printf( " \t\t\t\t\t\tsample table size: %u\n " , box.table_size);
printf( " \t\t\t\t\t\tsmple_size_table:\n " );
for ( int i = 0 ; i < box.table_size; ++ i){
box.sample_size_table[i] = read_uint32_lit(f);
printf( " %8u " , box.sample_size_table[i]);
if ((i + 1 ) % 10 == 0 ) printf( " \n " );
}
printf( " \n " );
}
return box;
}
/* final box
*/
struct mp4_stco_box mp4_read_stco_box(FILE * f, int size)
{
printf( " \t\t\t\t\t+%s\n " , " stco " );
mp4_stco_box box;
box.version = read_uint8(f);
fread(box.flags, sizeof (box.flags), 1 , f);
box.chunk_offset_amount = read_uint32_lit(f);
printf( " \t\t\t\t\t\tflags: 0x %x\n " ,
box.flags[ 0 ] | box.flags[ 1 ] | box.flags[ 2 ]);
printf( " \t\t\t\t\t\tchunk offest amount: %u\n " ,
box.chunk_offset_amount);
printf( " \t\t\t\t\t\tchunk offset:\n " );
box.chunk_offset_from_file_begin = new uint32_t[box.chunk_offset_amount];
for ( int i = 0 ; i < box.chunk_offset_amount; ++ i){
box.chunk_offset_from_file_begin[i] = read_uint32_lit(f);
printf( " %8x " , box.chunk_offset_from_file_begin[i]);
if ((i + 1 ) % 10 == 0 ) printf( " \n " );
}
// delete [] box.chunk_offset_from_file_begin;
return box;
}
/* container box
(stsd, stts, stsz|stz2, stsc, stco|co64, ctts, stss)
*/
struct mp4_stbl_box mp4_read_stbl_box(FILE * f, int size)
{
printf( " \t\t\t\t+stbl\n " );
mp4_stbl_box box;
VARIABLES;
int box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " stsd " ) {
box.stsd = mp4_read_stsd_box(f, box_size);
// 根据不同的编码方案和存储数据的文件数目,
// 每个media可以有一个到多个sample description。
// sample-to-chunk atom通过这个索引表,
// 找到合适medai中每个sample的description。
} else if (name == " stts " ){
box.stts = mp4_read_stts_box(f, box_size);
// Time-to-sample atoms存储了media sample的duration 信息,
// 提供了时间对具体data sample的映射方法,通过这个atom,
// 你可以找到任何时间的sample,类型是'stts'。
} else if (name == " stss " ){
box.stss = mp4_read_stss_box(f, box_size);
// sync sample atom确定media中的关键帧。
} else if (name == " stsc " ){
box.stsc = mp4_read_stsc_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7922.html
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7923.html
} else if (name == " stsz " || name == " stz2 " ){
box.stsz = mp4_read_stsz_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7924.html
} else if (name == " stco " || name == " c064 " ){
box.stco = mp4_read_stco_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7925.html
} else if (name == " ctts " ) {
// @a undefined
} else {
// printf("\t\t====size: %u\n", box_size);
printf( " \t\t\t\t\t+%s===============mark undifined\n " , p);
}
cur_pos += box_size;
inner_size += box_size;
} while (inner_size + 8 != size);
// printf("\n");
return box;
}
/* container box
()
*/
struct mp4_dinf_box mp4_read_dinf_box(FILE * f, int size)
{
printf( " \t\t\t\t+dinf\n " );
struct mp4_dinf_box box;
return box;
}
/* container box
(vmhd, smhd, hmhd, nmhd)
*/
struct mp4_minf_box mp4_read_minf_box(FILE * f, int size)
{
struct mp4_minf_box box;
printf( " \t\t\t+%s\n " , " minf " );
VARIABLES;
int level_5_box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
level_5_box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " vmhd " ) {
box.vmhd = mp4_read_vmhd_box(f, level_5_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7913.html
} else if (name == " dinf " ) {
box.dinf = mp4_read_dinf_box(f, level_5_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7915.html
} else if (name == " stbl " ) {
box.stbl = mp4_read_stbl_box(f, level_5_box_size);
// @a unfind
} else if (name == " smhd " ){
box.smhd = mp4_read_smhd_box(f, level_5_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7914.html
} else {
printf( " \t\t====size: %u\n " , level_5_box_size);
printf( " \t\t====type: %s\n " , p);
}
cur_pos += level_5_box_size;
inner_size += level_5_box_size;
} while (inner_size + 8 != size);
printf( " \n " );
return box;
}
/* container box
(mdhd, hdlr, minf)
*/
struct mp4_mdia_box mp4_read_mdia_box(FILE * f, int size)
{
printf( " \t\t+%s\n " , " mdia " );
mp4_mdia_box box;
box.size = size;
box.type = ' m ' | ' d ' << 8 | ' i ' << 16 | ' a ' << 24 ;
VARIABLES;
int box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " mdhd " ) {
box.mdhd = mp4_read_mdhd_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7908.html
} else if (name == " hdlr " ) {
box.hdlr = mp4_read_hdlr_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7909.html
} else if (name == " minf " ){
box.minf = mp4_read_minf_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7910.html
} else {
// printf("\t\t====size: %u\n", box_size);
printf( " \t\t====type: %s\n " , p);
}
cur_pos += box_size;
inner_size += box_size;
} while (inner_size + 8 != size);
printf( " \n " );
return box;
}
/* container box
*/
struct mp4_udta_box mp4_read_udta_box(FILE * f, int size)
{
printf( " \t\t+%s\n " , " udta " );
return mp4_udta_box();
}
/* container box
(tkhd, mdia)
*/
int mp4_read_trak_box(FILE * f, int size)
{
printf( " \t+%s\n " , " trak " );
struct mp4_trak_box * trak = new struct mp4_trak_box;
VARIABLES;
int box_size = 0 ;
int cur_pos = ftell(f) ;
do {
fseek(f, cur_pos, SEEK_SET);
box_size = read_uint32_lit(f);
fread(p, 4 , 1 , f);
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " tkhd " ) {
trak -> tkhd = mp4_read_tkhd_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7903.html
} else if (name == " edts " ) {
trak -> edts = mp4_read_edts_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7904.html
} else if (name == " mdia " ){
trak -> mdia = mp4_read_mdia_box(f, box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7907.html
} else if (name == " udta " ){
trak -> udta = mp4_read_udta_box(f, box_size);
// same as the level 3 box, @a special
} else {
// printf("\t====size: %u\n", box_size);
printf( " \t\t+%s===========\n " , p);
}
cur_pos += box_size;
inner_size += box_size;
} while (inner_size + 8 != size);
moov.trak.push_back(trak);
}
/* final box
*/
int mp4_read_iods_box(FILE * f, int size) // level 3
{
printf( " \t+iods-------------------------undefined\n\n " );
}
/* container box
(mvhd, trak)
*/
int mp4_read_moov_box(FILE * f, int size) // level 2
{
printf( " +%s\n " , " moov " );
moov.size = size;
moov.type = ' m ' | ' o ' << 8 | ' o ' << 16 | ' v ' << 24 ;
VARIABLES;
int level_2_box_size = 0 ;
int cur_pos = ftell(f);
do {
fseek(f, cur_pos, SEEK_SET);
level_2_box_size = read_uint32_lit(f);
fread( & k, sizeof (k), 1 , f); // read byte
indian_a.size = k;
memcpy(p, indian_a. byte , sizeof (indian_a. byte ));
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " mvhd " ){
mp4_read_mvhd_box(f, level_2_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7901.html
} else if (name == " trak " ) {
mp4_read_trak_box(f, level_2_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7902.html
} else if (name == " iods " ){
mp4_read_iods_box(f, level_2_box_size);
} else if (name == " udta " ){
mp4_read_udta_box(f, level_2_box_size);
// @a mark parse it, unknow what it is
} else {
printf( " ====%s\n\n " , p);
}
cur_pos += level_2_box_size;
inner_size += level_2_box_size;
} while ( inner_size + 8 != size);
}
/* final box
*/
int mp4_read_ftyp_box(FILE * f, int size) // level 2
{
printf( " +ftyp\n " );
size -= 8 ;
char * ch = new char [size + 1 ];
for ( int i = 0 ; i < size; ++ i) {
fread( & ch[i], sizeof ( char ), 1 , f);
}
ch[size] = 0 ;
printf( " \tftyp: %s\n " , ch);
delete [] ch;
}
/* @a special final box
*/
int mp4_read_mdat_box(FILE * f, int size)
{
printf( " \t+%s\n " , " mdat " );
printf( " \t\tthis is the real media data\n " );
}
/* container box
(ftyp, free, mdat, moov)
*/
int mp4_read_root_box(FILE * f) // level 1
{
int k = 0 ;
unsigned char p[ 5 ];
int level_1_box_size = read_uint32_lit(f);
fread( & k, sizeof (k), 1 , f); // read byte
indian_a.size = k;
memcpy(p, indian_a. byte , sizeof (indian_a. byte ));
p[ 4 ] = 0 ;
std:: string name = ( char * )p;
if (name == " moov " ){
mp4_read_moov_box(f, level_1_box_size);
// @a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7900.html
} else if (name == " ftyp " ){
mp4_read_ftyp_box(f, level_1_box_size);
} else if (level_1_box_size == 0 ){ // till the end of file
return 1 ;
} else if (name == " mdat " ){
mp4_read_mdat_box(f, level_1_box_size);
} else if (name == " free " ){
printf( " +free\n " );
} else {
// printf("==%u\n", level_1_box_size);
printf( " %s==mark undifined\n " , p);
}
return level_1_box_size;
}
void print_trak( const struct mp4_trak_box * trak)
{
printf( " trak\n " );
printf( " \t+%s\n " , " tkhd " );
printf( " \t\ttrack id: %u\n " , trak -> tkhd.track_ID);
printf( " \t\tduration: %d\n " , trak -> tkhd.duration);
printf( " \t\t\tlayer: %d\n " ,trak -> tkhd.layer);
printf( " \t\t\talternate group: %d\n " , trak -> tkhd.alternate_group);
printf( " \t\t\tvolume: 0x%x\n " , trak -> tkhd.volume);
printf( " \t\t\tmatrix:\n " );
for ( int i = 0 ; i < 3 ; ++ i){
printf( " \t\t\t " );
for ( int j = 0 ; j < 3 ; ++ j){
printf( " %8u " , trak -> tkhd.matrix[i * 3 + j]);
}
printf( " \n " );
}
printf( " \t\t\twidth: %u\n " ,trak -> tkhd.width);
printf( " \t\t\theight: [%u].[%u]\n " ,
trak -> tkhd.height & 0xffff0000 >> 16 ,
trak -> tkhd.height & 0xffff );
printf( " \t+%s\n " , " mdia " );
printf( " \t\t\t\t\t\t+stsd\n " );
printf( " \t\t\t\t\t\t\tnumber of entries: %u\n " ,
trak -> mdia.minf.stbl.stsd.number_of_entries);
// printf("\t\t\t\t\t\t+stts: time to sample\n");
// printf("\t\t\t\t\t\t\tentries:\n\t\t\t\t\t\t\t");
// for(int i =0; i < trak->mdia.minf.stbl.stts.number_of_entries; ++i){
// printf("%15u ", trak->mdia.minf.stbl.stts.time_to_sample_table[i]);
// }
// printf("\n");
// printf("\t\t\t\t\t+stss:关键帧\n");
// printf("\t\t\t\t\t\t\tentries:\n\t\t\t\t\t\t\t");
// for(int i =0; i < trak->mdia.minf.stbl.stss.number_of_entries; ++i){
// printf("%15u ", trak->mdia.minf.stbl.stss.sync_sample_table[i]);
// }
// printf("\n");
printf( " \t\t\t\t\t\t+stsc:sample to chunk table\n " );
printf( " \t\t\t\t\t\tfirst trunk:\tsamples-per-thunk:\tsample-description-ID\n " );
for ( int i = 0 ; i < trak -> mdia.minf.stbl.stsc.map_amount; ++ i){
printf( " \t\t\t\t\t\t%13d " , trak -> mdia.minf.stbl.stsc.scmap[i].first_chunk_num);
printf( " \t%13d " , trak -> mdia.minf.stbl.stsc.scmap[i].sample_amount_in_cur_table);
printf( " \t%13d\n " , trak -> mdia.minf.stbl.stsc.scmap[i].sample_description_id);
} printf( " \n " );
printf( " \t\t\t\t\t\t+%s\n " , " stsz " );
printf( " \t\t\t\t\t\t\tsmple_size_table:\n\t\t\t\t\t\t " );
for ( int i = 0 ; i < trak -> mdia.minf.stbl.stsz.table_size; ++ i){
printf( " %8u " , trak -> mdia.minf.stbl.stsz.sample_size_table[i]);
} printf( " \n " );
printf( " \t\t\t\t\t\t+stco\n " );
printf( " \t\t\t\t\t\tchunk offset:\n\t\t\t\t\t " );
for ( int i = 0 ; i < trak -> mdia.minf.stbl.stco.chunk_offset_amount; ++ i){
printf( " %8u " ,trak -> mdia.minf.stbl.stco.chunk_offset_from_file_begin[i]);
}
}
uint32_t get_sample_num_in_cur_chunk( const struct mp4_stsc_box & box,
const uint32_t chunk_index) // begin from 0
{
int sample_num_in_cur_chunk_ = 0 ;
for ( int i = 0 ; i < box.map_amount; ++ i) {
if (i + 1 == box.map_amount){
// std::cout<<"chunk_index:"<<chunk_index<<std::endl;
sample_num_in_cur_chunk_
= box.scmap[i].sample_amount_in_cur_table;
}
if (chunk_index + 1 >= box.scmap[i].first_chunk_num
&& chunk_index + 1 < box.scmap[i + 1 ].first_chunk_num){
sample_num_in_cur_chunk_
= box.scmap[i].sample_amount_in_cur_table;
break ;
}
}
// std::cout<<"sample_num_in_cur_chunk_:"<< sample_num_in_cur_chunk_;
return sample_num_in_cur_chunk_;
}
/* @a return index from 0 */
uint32_t get_sample_index( const struct mp4_stsc_box & box,
const uint32_t chunk_index) // [1,end)
{
/* chunk samples id
1 8 1
2 7 1
46 6 1
*/
uint32_t me = chunk_index;
uint32_t sindex = 0 ;
for ( int i = 0 ; i < box.map_amount; ++ i) {
uint32_t chunk_amount = 0 ;
uint32_t curr = box.scmap[i].first_chunk_num;
if (i + 1 == box.map_amount){ // end() , we can't have next one to index
chunk_amount = me - curr; // do not add ONE
sindex += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
break ;
}
uint32_t next = box.scmap[i + 1 ].first_chunk_num;
if (me > curr){
if (me < next){
chunk_amount = me - curr; // do not add ONE
sindex += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
break ;
} else {
chunk_amount = next - curr; // do not add ONE
sindex += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
}
} else if (me == curr){
break ;
}
}
return sindex;
}
uint32_t get_sample_size( const struct mp4_stsz_box & box,
const uint32_t chunk_index) // [0, end)
{
for ( int i = 0 ; i < box.table_size; ++ i) {
if (chunk_index == i)
return box.sample_size_table[i];
}
}
void copy_chunk_data(FILE * fin,
const struct mp4_stbl_box & box,
const uint32_t chunk_index, // [0, end)
FILE * fout)
{
fseek(fin, box.stco.chunk_offset_from_file_begin[chunk_index],
SEEK_SET);
uint32_t sample_num_in_cur_chunk_
= get_sample_num_in_cur_chunk(box.stsc, chunk_index); // @a mark
uint32_t sample_index_
= get_sample_index(box.stsc, chunk_index + 1 );
printf( " %x\tindex=%u\t " ,
box.stco.chunk_offset_from_file_begin[chunk_index],
sample_index_);
for ( int i = 0 ; i < sample_num_in_cur_chunk_; ++ i) {
uint32_t sample_size_ = get_sample_size(box.stsz, sample_index_ + i);
std::cout << sample_size_ << std::endl;
uint32_t NALU_size = 0 ;
uint32_t NALU_total = 0 ;
while (NALU_total < sample_size_){
NALU_size = read_uint32_lit(fin);
NALU_total += NALU_size + 4 ;
printf( " \tNALU_size:%x\n " , NALU_size);
char * ptr = new char [NALU_size];
fread(ptr, NALU_size, 1 , fin);
static uint32_t one = 1 << 24 ;
fwrite( & one, sizeof (one), 1 , fout);
fwrite(ptr, NALU_size, 1 , fout);
delete [] ptr;
NALU_size = 0 ;
}
}
}
void make_file(FILE * fin, const struct mp4_trak_box * trak, std:: string name)
{
int chunk_offset_amount = trak -> mdia.minf.stbl.stco.chunk_offset_amount;
#if RELEASE
struct mp4_avc1_box * avc1 =
trak -> mdia.minf.stbl.stsd.sample_description[ 0 ].avc1;
name += " x " ;
FILE * fout = fopen(name.c_str(), " w " );
if ( ! fout){
std:: string tmp = " fopen_ " + name ;
perror(tmp.c_str());
}
if (avc1 != 0 ){
uint32_t one = 1 << 24 ;
fwrite( & one, sizeof (one), 1 , fout);
struct mp4_avcC_box * avcC = avc1 -> avcC;
fwrite(avcC -> sps[ 0 ].sequenceParameterSetNALUnit,
avcC -> sps[ 0 ].sequenceParameterSetLength, 1 , fout);
fwrite( & one, sizeof (one), 1 , fout);
fwrite(avcC -> pps[ 0 ].pictureParameterSetNALUnit,
avcC -> pps[ 0 ].pictureParameterSetLength, 1 , fout);
}
for ( int chunk_index = 0 ; chunk_index < chunk_offset_amount;
++ chunk_index) {
copy_chunk_data(fin, trak -> mdia.minf.stbl, chunk_index, fout);
}
fclose(fout);
#else
system(std:: string ( " rm -rf " + name).c_str());
system(std:: string ( " mkdir " + name).c_str());
for ( int chunk_index = 0 ; chunk_index < chunk_offset_amount;
++ chunk_index) {
char char_num[ 10 ];
sprintf(char_num, " %u " , chunk_index);
FILE * fout =
fopen(std:: string (name + " / " + name + char_num).c_str(), " w " );
if (fout == (FILE * ) 0 ){
printf( " error\n " );
std::exit( - 1 );
}
copy_chunk_data(fin, trak -> mdia.minf.stbl, chunk_index, fout);
fclose(fout);
}
#endif
}
int main(){
std::ios_base::sync_with_stdio( true );
std:: string luo = " luohunshidai01_001.mp4 " ;
std:: string _600 = " 6004501011.mp4 " ;
// FILE *fin = fopen(luo.c_str(), "r");
FILE * fin = fopen(_600.c_str(), " r " );
// FILE *f_video = fopen("video", "w+");
// FILE *f_audio = fopen("audio", "w+");
if (fin == (FILE * ) 0 ){
printf( " failed to open\n " );
return 0 ;
}
// level 0
int cur_pos = ftell(fin);
for (; ! feof(fin); ) {
fseek(fin, cur_pos, SEEK_SET);
printf( " ----------------------------------------level 0\n " );
cur_pos += mp4_read_root_box(fin);
}
// print_trak(moov.trak[0]);
// print_trak(moov.trak[1]);
make_file(fin, moov.trak[ 0 ], ( " video " ));
// make_file(fin, moov.trak[1], ("audio"));
return 0 ;
}
//filename mp4_boxes.h
#ifndef MP4_BOXES_H
#define MP4_BOXES_H
#include < vector >
#include < inttypes.h >
static union ____indian_swap{
unsigned char byte [ 4 ];
unsigned int size;
}indian_a , indian_b;
unsigned read_uint16_big(FILE * f)
{
unsigned short k = 0 ;
fread( & k, sizeof (k), 1 , f);
return k;
}
uint16_t read_uint16_lit(FILE * f)
{
uint16_t k;
fread( & k, sizeof (k), 1 , f);
return ((k & 0xff00 ) >> 8 ) | ((k & 0xff ) << 8 );
}
unsigned char read_uint8(FILE * f)
{
unsigned char x;
fread( & x, sizeof (x), 1 , f);
return x;
}
int read_uint32_lit(FILE * f){
int k = 0 ;
fread( & k, sizeof (k), 1 , f);
indian_a.size = k;
for ( int i = 0 , j = 3 ; i < 4 ; i ++ , j -- )
indian_b. byte [i] = indian_a. byte [j];
return indian_b.size;
}
#ifndef MP4_BASE_BOX
#define MP4_BASE_BOX \
uint32_t type; \
uint32_t size;
#endif
#ifndef MP4_FULL_BOX
#define MP4_FULL_BOX \
MP4_BASE_BOX; \
uint8_t version; \
uint8_t flags[ 3 ]
#endif
#ifndef MP4_SAMPLE_ENTRY_FIELDS
#define MP4_SAMPLE_ENTRY_FIELDS \
MP4_BASE_BOX; \
char reserved[ 6 ]; \
uint16_t data_reference_index;
#endif
#ifndef VISUAL_SAMPLE_ENTRY_FIELDS
#define VISUAL_SAMPLE_ENTRY_FIELDS \
MP4_SAMPLE_ENTRY_FIELDS; \
uint16_t pre_defined; \
uint16_t reserved1; \
uint32_t pre_defined1[ 3 ]; \
uint16_t width; \
uint16_t height; \
uint32_t horiz_res; \
uint32_t vert_res; \
uint32_t reserved2; \
/**/ uint16_t frames_count; \
/* 以下是AVCDecoderConfigurationRecord */ \
/**/ char compressor_name[ 33 ]; \
/**/ uint16_t bit_depth; \
/**/ int16_t pre_defined2
#endif
struct mp4_box{
MP4_BASE_BOX;
};
struct mp4_avcC_box{
uint32_t size;
uint32_t type;
uint8_t configurationVersion; // =1
uint8_t AVCProfileIndication;
uint8_t profile_compatibility;
uint8_t AVCLevelIndication;
uint8_t lengthSizeMinusOne; // & 0x3, ==2 bit
uint8_t numOfSequenceParameterSet; // & 0x1F ==5bit
struct SPS{
uint16_t sequenceParameterSetLength;
uint8_t * sequenceParameterSetNALUnit;
} * sps;
uint8_t numOfPictureParameterSets;
struct PPS{
uint16_t pictureParameterSetLength;
uint8_t * pictureParameterSetNALUnit;
} * pps;
};
struct mp4_avc1_box {
VISUAL_SAMPLE_ENTRY_FIELDS;
struct mp4_avcC_box * avcC;
struct mp4_btrt_box * btrt;
/* ext descriptors */
struct mp4_m4ds_box * m4ds;
};
struct mp4_tkhd_box {
MP4_FULL_BOX;
uint32_t creation_time;
uint32_t modification_time;
uint32_t track_ID;
uint32_t reserved1;
uint32_t duration;
uint32_t reserved2[ 2 ];
uint16_t layer;
uint16_t alternate_group;
uint16_t volume;
uint16_t reserved3;
uint32_t matrix[ 9 ];
uint32_t width;
uint32_t height;
};
struct editList{
uint32_t trak_duration;
uint32_t duration;
uint32_t rate;
};
struct mp4_elst_box{
MP4_FULL_BOX;
uint32_t amount;
editList * edit_list;
};
struct mp4_mdhd_box {
MP4_FULL_BOX;
uint32_t creation_time;
uint32_t modification_time;
uint32_t timescale;
uint32_t duration;
uint16_t language;
uint16_t pre_defined;
};
struct mp4_vmhd_box{
MP4_FULL_BOX;
uint32_t graphics_mode;
uint8_t opcolor[ 4 ]; // ==============take care
};
struct mp4_dref_box{
MP4_FULL_BOX;
uint32_t entry_count;
// there are many urls
// ======================================
};
struct mp4_list_t{
uint32_t first_chunk_num;
uint32_t sample_amount_in_cur_table;
uint32_t sample_description_id;
};
struct mp4_stsc_box{ // Sample-to-Chunk Atoms
MP4_FULL_BOX;
uint32_t map_amount;
mp4_list_t * scmap; // sample-to-trunk表的结构
};
struct mp4_stsz_box{ // sample size
MP4_FULL_BOX;
uint32_t samples_size_intotal;
uint32_t table_size; // 全部sample的数目。如果所有的sample有相同的长度,这个字段就是这个值。
// 否则,这个字段的值就是0。那些长度存在sample size表中
uint32_t * sample_size_table; // 多个sample的大小相加就是整个电影的长度
};
struct mp4_stco_box{ // Chunk Offset
MP4_FULL_BOX;
uint32_t chunk_offset_amount;
uint32_t * chunk_offset_from_file_begin;
};
struct mp4_stss_box{ // Sync Sample
MP4_FULL_BOX;
uint32_t number_of_entries;
uint32_t * sync_sample_table;
};
struct mp4_stts_box{ // Time-to-Sample
MP4_FULL_BOX;
uint32_t number_of_entries;
uint32_t * time_to_sample_table;
};
#ifndef MP4_SAMPLE_ENTRY_FIELDS
#define MP4_SAMPLE_ENTRY_FIELDS \
MP4_BASE_BOX; \
char reserved[ 6 ]; \
uint16_t data_reference_index;
#endif
struct mp4_mp4a_box{
};
struct Sample_description{
uint32_t size;
uint32_t type;
struct mp4_avc1_box * avc1;
struct mp4_mp4a_box * mp4a;
// 利用这个索引可以检索与当前sample description关联的数据。
// 数据引用存储在data reference atoms。
};
struct mp4_stsd_box{
MP4_FULL_BOX; // 12 bytes
uint32_t number_of_entries; // 4 bytes
Sample_description * sample_description;
};
struct mp4_smhd_box{ // sound media header box
MP4_FULL_BOX;
uint16_t balance;
uint16_t reserved;
};
struct mp4_hdlr_box {
MP4_FULL_BOX;
uint32_t pre_defined;
uint8_t handler_type[ 5 ];
uint32_t reserved[ 3 ];
char * name; // end with '\0'
};
/* 14496-12 8.2, media data container */
struct mp4_mdat_box {
MP4_BASE_BOX;
uint64_t data_size;
char * data;
};
struct mp4_mvhd_box{
MP4_FULL_BOX; // 12
uint32_t creation_time; // 4
uint32_t modification_time; // 4
uint32_t timescale; // 4
uint32_t duration; // 4
uint32_t rate; // 4
uint16_t volume; // 2
uint16_t reserved1; // 2
uint32_t reserved2[ 2 ]; // 8
uint32_t matrix[ 9 ]; // 36
uint32_t pre_defined[ 6 ]; // 24
uint32_t next_track_id; // 4
};
struct mp4_iods_box{
};
struct mp4_udta_box{
};
struct mp4_dinf_box{
};
struct mp4_stbl_box{
struct mp4_stsd_box stsd;
struct mp4_stts_box stts;
struct mp4_stss_box stss;
struct mp4_stsc_box stsc;
struct mp4_stsz_box stsz;
struct mp4_stco_box stco;
};
struct mp4_minf_box{
MP4_BASE_BOX;
struct mp4_vmhd_box * vmhd;
struct mp4_smhd_box * smhd;
struct mp4_hdlr_box hdlr;
struct mp4_dinf_box dinf;
struct mp4_stbl_box stbl;
};
struct mp4_mdia_box{
MP4_BASE_BOX;
struct mp4_mdhd_box mdhd;
struct mp4_hdlr_box hdlr;
struct mp4_minf_box minf;
};
struct mp4_edts_box{
};
struct mp4_trak_box{
struct mp4_tkhd_box tkhd;
struct mp4_mdia_box mdia;
struct mp4_edts_box edts;
struct mp4_udta_box udta;
};
struct mp4_moov_box{
MP4_BASE_BOX;
struct mp4_mvhd_box mvhd;
struct mp4_iods_box iods;
std::vector < struct mp4_trak_box *>
trak;
struct mp4_udta_box udta;
};
#endif // MP4_BOXES_H
#ifndef MP4_BOXES_H
#define MP4_BOXES_H
#include < vector >
#include < inttypes.h >
static union ____indian_swap{
unsigned char byte [ 4 ];
unsigned int size;
}indian_a , indian_b;
unsigned read_uint16_big(FILE * f)
{
unsigned short k = 0 ;
fread( & k, sizeof (k), 1 , f);
return k;
}
uint16_t read_uint16_lit(FILE * f)
{
uint16_t k;
fread( & k, sizeof (k), 1 , f);
return ((k & 0xff00 ) >> 8 ) | ((k & 0xff ) << 8 );
}
unsigned char read_uint8(FILE * f)
{
unsigned char x;
fread( & x, sizeof (x), 1 , f);
return x;
}
int read_uint32_lit(FILE * f){
int k = 0 ;
fread( & k, sizeof (k), 1 , f);
indian_a.size = k;
for ( int i = 0 , j = 3 ; i < 4 ; i ++ , j -- )
indian_b. byte [i] = indian_a. byte [j];
return indian_b.size;
}
#ifndef MP4_BASE_BOX
#define MP4_BASE_BOX \
uint32_t type; \
uint32_t size;
#endif
#ifndef MP4_FULL_BOX
#define MP4_FULL_BOX \
MP4_BASE_BOX; \
uint8_t version; \
uint8_t flags[ 3 ]
#endif
#ifndef MP4_SAMPLE_ENTRY_FIELDS
#define MP4_SAMPLE_ENTRY_FIELDS \
MP4_BASE_BOX; \
char reserved[ 6 ]; \
uint16_t data_reference_index;
#endif
#ifndef VISUAL_SAMPLE_ENTRY_FIELDS
#define VISUAL_SAMPLE_ENTRY_FIELDS \
MP4_SAMPLE_ENTRY_FIELDS; \
uint16_t pre_defined; \
uint16_t reserved1; \
uint32_t pre_defined1[ 3 ]; \
uint16_t width; \
uint16_t height; \
uint32_t horiz_res; \
uint32_t vert_res; \
uint32_t reserved2; \
/**/ uint16_t frames_count; \
/* 以下是AVCDecoderConfigurationRecord */ \
/**/ char compressor_name[ 33 ]; \
/**/ uint16_t bit_depth; \
/**/ int16_t pre_defined2
#endif
struct mp4_box{
MP4_BASE_BOX;
};
struct mp4_avcC_box{
uint32_t size;
uint32_t type;
uint8_t configurationVersion; // =1
uint8_t AVCProfileIndication;
uint8_t profile_compatibility;
uint8_t AVCLevelIndication;
uint8_t lengthSizeMinusOne; // & 0x3, ==2 bit
uint8_t numOfSequenceParameterSet; // & 0x1F ==5bit
struct SPS{
uint16_t sequenceParameterSetLength;
uint8_t * sequenceParameterSetNALUnit;
} * sps;
uint8_t numOfPictureParameterSets;
struct PPS{
uint16_t pictureParameterSetLength;
uint8_t * pictureParameterSetNALUnit;
} * pps;
};
struct mp4_avc1_box {
VISUAL_SAMPLE_ENTRY_FIELDS;
struct mp4_avcC_box * avcC;
struct mp4_btrt_box * btrt;
/* ext descriptors */
struct mp4_m4ds_box * m4ds;
};
struct mp4_tkhd_box {
MP4_FULL_BOX;
uint32_t creation_time;
uint32_t modification_time;
uint32_t track_ID;
uint32_t reserved1;
uint32_t duration;
uint32_t reserved2[ 2 ];
uint16_t layer;
uint16_t alternate_group;
uint16_t volume;
uint16_t reserved3;
uint32_t matrix[ 9 ];
uint32_t width;
uint32_t height;
};
struct editList{
uint32_t trak_duration;
uint32_t duration;
uint32_t rate;
};
struct mp4_elst_box{
MP4_FULL_BOX;
uint32_t amount;
editList * edit_list;
};
struct mp4_mdhd_box {
MP4_FULL_BOX;
uint32_t creation_time;
uint32_t modification_time;
uint32_t timescale;
uint32_t duration;
uint16_t language;
uint16_t pre_defined;
};
struct mp4_vmhd_box{
MP4_FULL_BOX;
uint32_t graphics_mode;
uint8_t opcolor[ 4 ]; // ==============take care
};
struct mp4_dref_box{
MP4_FULL_BOX;
uint32_t entry_count;
// there are many urls
// ======================================
};
struct mp4_list_t{
uint32_t first_chunk_num;
uint32_t sample_amount_in_cur_table;
uint32_t sample_description_id;
};
struct mp4_stsc_box{ // Sample-to-Chunk Atoms
MP4_FULL_BOX;
uint32_t map_amount;
mp4_list_t * scmap; // sample-to-trunk表的结构
};
struct mp4_stsz_box{ // sample size
MP4_FULL_BOX;
uint32_t samples_size_intotal;
uint32_t table_size; // 全部sample的数目。如果所有的sample有相同的长度,这个字段就是这个值。
// 否则,这个字段的值就是0。那些长度存在sample size表中
uint32_t * sample_size_table; // 多个sample的大小相加就是整个电影的长度
};
struct mp4_stco_box{ // Chunk Offset
MP4_FULL_BOX;
uint32_t chunk_offset_amount;
uint32_t * chunk_offset_from_file_begin;
};
struct mp4_stss_box{ // Sync Sample
MP4_FULL_BOX;
uint32_t number_of_entries;
uint32_t * sync_sample_table;
};
struct mp4_stts_box{ // Time-to-Sample
MP4_FULL_BOX;
uint32_t number_of_entries;
uint32_t * time_to_sample_table;
};
#ifndef MP4_SAMPLE_ENTRY_FIELDS
#define MP4_SAMPLE_ENTRY_FIELDS \
MP4_BASE_BOX; \
char reserved[ 6 ]; \
uint16_t data_reference_index;
#endif
struct mp4_mp4a_box{
};
struct Sample_description{
uint32_t size;
uint32_t type;
struct mp4_avc1_box * avc1;
struct mp4_mp4a_box * mp4a;
// 利用这个索引可以检索与当前sample description关联的数据。
// 数据引用存储在data reference atoms。
};
struct mp4_stsd_box{
MP4_FULL_BOX; // 12 bytes
uint32_t number_of_entries; // 4 bytes
Sample_description * sample_description;
};
struct mp4_smhd_box{ // sound media header box
MP4_FULL_BOX;
uint16_t balance;
uint16_t reserved;
};
struct mp4_hdlr_box {
MP4_FULL_BOX;
uint32_t pre_defined;
uint8_t handler_type[ 5 ];
uint32_t reserved[ 3 ];
char * name; // end with '\0'
};
/* 14496-12 8.2, media data container */
struct mp4_mdat_box {
MP4_BASE_BOX;
uint64_t data_size;
char * data;
};
struct mp4_mvhd_box{
MP4_FULL_BOX; // 12
uint32_t creation_time; // 4
uint32_t modification_time; // 4
uint32_t timescale; // 4
uint32_t duration; // 4
uint32_t rate; // 4
uint16_t volume; // 2
uint16_t reserved1; // 2
uint32_t reserved2[ 2 ]; // 8
uint32_t matrix[ 9 ]; // 36
uint32_t pre_defined[ 6 ]; // 24
uint32_t next_track_id; // 4
};
struct mp4_iods_box{
};
struct mp4_udta_box{
};
struct mp4_dinf_box{
};
struct mp4_stbl_box{
struct mp4_stsd_box stsd;
struct mp4_stts_box stts;
struct mp4_stss_box stss;
struct mp4_stsc_box stsc;
struct mp4_stsz_box stsz;
struct mp4_stco_box stco;
};
struct mp4_minf_box{
MP4_BASE_BOX;
struct mp4_vmhd_box * vmhd;
struct mp4_smhd_box * smhd;
struct mp4_hdlr_box hdlr;
struct mp4_dinf_box dinf;
struct mp4_stbl_box stbl;
};
struct mp4_mdia_box{
MP4_BASE_BOX;
struct mp4_mdhd_box mdhd;
struct mp4_hdlr_box hdlr;
struct mp4_minf_box minf;
};
struct mp4_edts_box{
};
struct mp4_trak_box{
struct mp4_tkhd_box tkhd;
struct mp4_mdia_box mdia;
struct mp4_edts_box edts;
struct mp4_udta_box udta;
};
struct mp4_moov_box{
MP4_BASE_BOX;
struct mp4_mvhd_box mvhd;
struct mp4_iods_box iods;
std::vector < struct mp4_trak_box *>
trak;
struct mp4_udta_box udta;
};
#endif // MP4_BOXES_H