📄 mp4descriptors.c
字号:
/* * * Copyright (c) Sigma Designs, Inc. 2006. All rights reserved. * *//** @file mp4descriptors.c @brief IOD parsing for MP4 streams @author Yifan Liu @ingroup dccsamplecode*/#include "../samples/sample_os.h"#define ALLOW_OS_CODE 1#include "../dcc/include/dcc.h"#include "../samples/common.h"#include "psfdemux_common.h"#include "mp4descriptors.h"#if 1#define CALLDBG ENABLE#else#define CALLDBG DISABLE#endif/* Parameters p - input stream count - input stream length *count - return the actually parsed length *iod - a null pointer allocated with created objects Return pointer for success, NULL for failures */struct MP4_IOD * CreateIODDescriptor(RMuint8 *p, RMuint16 * count ){ struct MP4_IOD * iod = NULL; RMuint16 i; RMuint16 acclength = 9; RMuint16 maxlength = *count; RMDBGLOG((CALLDBG, "CreateIODDescriptor 0x%x, %02x %02x %02x %02x\n", *count, p[0], p[1], p[2], p[3] )); if( maxlength < acclength ) { RMDBGLOG((ENABLE, "Error: input stream not long enough\n" )); return NULL; } iod = (struct MP4_IOD *)RMMalloc( sizeof(struct MP4_IOD) ); if( !iod ) { RMDBGLOG((ENABLE, "Error: failed create iod \n" )); return NULL; } RMMemset( iod, 0, sizeof(struct MP4_IOD) ); iod->tag = p[0]; /* 8 bits, default to 0x02 */// assert( iod->tag == 0x02 ); iod->size = p[1]; /* 8 bits, spec says 16 bits */ iod->id = (((RMuint16)p[2] & 0xff)<<2) | (RMuint16)((p[3]>>6) & 0x3); /* 10 bits */ iod->URL_flag = (p[3]>>5) & 0x1; /* 1 bit */ iod->includeInlineProfiles = (p[3]>>4) & 0x1; /* 1 bit */// assert( (p[3]& 0x0f) == 0x0f );/* 4 bits reserved default to 0b1111 */ iod->esDescrNum = 0; for( i=0; i<256; i++ ) iod->esDescr[i] = NULL; if( iod->URL_flag ) { RMDBGLOG((ENABLE, "Error: does not parse URL_Flag == 1 \n" )); DestoryIODDescriptor(iod); return NULL; } else { iod->profileLevelIndication1 = p[4];/* 8 bits */; iod->sceneProfileLevelIndication = p[5]; /* 8 bits 0x01 */; iod->audioProfileLevelIndication = p[6]; /* 8 bits 0x0c*/; iod->visualProfileLevelIndication = p[7]; /* 8 bits */; iod->graphicsProfileLevelIndication = p[8];/* 8 bits 0x04*/; while( acclength < maxlength ) { RMuint16 nextlength = p[acclength+1]+2; iod->esDescr[iod->esDescrNum] = CreateDescriptor( (p+acclength), &nextlength ); if( iod->esDescr[iod->esDescrNum] == NULL ) { RMDBGLOG((ENABLE, "Error: create descr failed %d\n", iod->esDescrNum )); DestoryIODDescriptor(iod); return NULL; } iod->esDescrNum ++; acclength += nextlength; RMDBGLOG((CALLDBG, "Accumulated : 0x%x\n", acclength )); } } /* possible extended descriptors here, assume none for now */ *count = acclength; return iod;}void DestoryIODDescriptor(struct MP4_IOD * iod){ RMuint8 i; for( i = 0; i < iod->esDescrNum; i++ ) { DestoryDescriptor( (AnyDescriptor *)iod->esDescr[i] ); } RMFree( iod ); return;}struct MP4_ES_Descriptor * CreateESDescriptor(RMuint8 *p, RMuint16 * count ){ struct MP4_ES_Descriptor * des = NULL; RMuint16 i; RMuint16 acclength = 5; RMuint16 maxlength = *count; RMDBGLOG((CALLDBG, "CreateESDescriptor 0x%x, %02x %02x %02x %02x\n", *count, p[0], p[1], p[2], p[3] )); if( maxlength < acclength ) { RMDBGLOG((ENABLE, "Error: input stream not long enough\n" )); return NULL; } des = (struct MP4_ES_Descriptor *)RMMalloc( sizeof(struct MP4_ES_Descriptor) ); if( !des ) { RMDBGLOG((ENABLE, "Error: failed create descriptor\n" )); return NULL; } RMMemset( des, 0, sizeof(struct MP4_ES_Descriptor) ); des->tag = p[0]; /* 8 bits, default to 0x03 */// assert( des->tag == 0x03 ); des->size = p[1]; /* 8 bits */ des->ES_id = (((RMuint16)p[2] & 0xff)<<8) | (RMuint16)(p[3]); /* 16 bits */ RMDBGLOG((CALLDBG, " ES_id = 0x%x\n", des->ES_id )); des->streamDependentFlag = (p[4]>>7) & 0x01; /* 1 bit */ des->URL_flag = (p[4]>>6) & 0x01; /* 1 bit */ des->OCRstreamFlag = (p[4]>>5) & 0x01; /* 1 bit */ des->streamPriority = p[4] & 0x1f; /* 5 bits */ acclength = 5; if( des->streamDependentFlag ) { des->dependsOn_ES_id = ( ((RMuint16)p[acclength] & 0xff)<<8) | (RMuint16)(p[acclength+1] ); /* 16 bits */ acclength += 2; } if( des->URL_flag ) { RMuint8 j; des->URLlength = p[acclength]; /* 8 bits */ acclength ++; for( j=0; j<des->URLlength; j++ ) { des->URLstring[j] = p[acclength ++]; //assert ( j < 256 ) } } if( des->OCRstreamFlag ) { des->OCR_ES_id = ( ((RMuint16)p[acclength] & 0xff)<<8) | (RMuint16)(p[acclength+1] ); /* 16 bits */ acclength += 2; } des->esDescrNum = 0; for( i=0; i<256; i++ ) des->esDescr[i] = NULL; while( acclength < maxlength ) { RMuint16 nextlength = p[acclength+1]+2; des->esDescr[des->esDescrNum] = CreateDescriptor( (p+acclength), &nextlength ); if( des->esDescr[des->esDescrNum] == NULL ) { RMDBGLOG((ENABLE, "Error: create descr failed %d\n", des->esDescrNum )); DestoryESDescriptor( des ); return NULL; } des->esDescrNum ++; acclength += nextlength; RMDBGLOG((CALLDBG, "Accumulated : 0x%x\n", acclength )); } *count = acclength; return des; }void DestoryESDescriptor(struct MP4_ES_Descriptor * des){ RMuint8 i; for( i = 0; i < des->esDescrNum; i++ ) { DestoryDescriptor( (AnyDescriptor *)des->esDescr[i] ); } RMFree( des ); return;}struct MP4_DecoderConfigDescriptor * CreateDecoderConfigDescriptor(RMuint8 *p, RMuint16 * count){ struct MP4_DecoderConfigDescriptor * des = NULL; RMuint16 acclength = 15; RMuint16 maxlength = *count; RMDBGLOG((CALLDBG, "CreateDecoderConfigDescriptor 0x%x, %02x %02x %02x %02x\n", *count, p[0], p[1], p[2], p[3] )); if( maxlength < acclength ) { RMDBGLOG((ENABLE, "Error: input stream not long enough\n" )); return NULL; } des = (struct MP4_DecoderConfigDescriptor *)RMMalloc( sizeof(struct MP4_DecoderConfigDescriptor) ); if( !des ) { RMDBGLOG((ENABLE, "Error: failed create iod \n" )); return NULL; } RMMemset( des, 0, sizeof(struct MP4_DecoderConfigDescriptor) ); des->tag = p[0]; /* 8 bits, default to 0x04 */// assert( des->tag == 0x04 ); des->size = p[1]; /* 8 bits */ des->objectTypeIndication = p[2]; /* 8 bits */ RMDBGLOG((CALLDBG, " objectTypeIndication = 0x%x\n", des->objectTypeIndication )); des->streamType = (p[3]>>2) & 0x3f; /* 6 bits */ RMDBGLOG((CALLDBG, " streamType = 0x%x\n", des->streamType )); des->upstream = (p[3]>>1) & 0x01; /* 1 bit */ /* 1 bit reserved */ des->bufferSizeDB = (((RMuint32)p[4]<<16)&0x00ff0000) | (((RMuint32)p[5]<<8)&0x0000ff00) | ((RMuint32)p[6]&0x000000ff); /* 24 bits */ des->maxBitrate = (((RMuint32)p[7]<<24)&0xff000000) | (((RMuint32)p[8]<<16)&0x00ff0000) | (((RMuint32)p[9]<< 8)&0x0000ff00) | ((RMuint32)p[10]&0x000000ff); /* 32 bits */ des->avgBitrate = (((RMuint32)p[11]<<24)&0xff000000) | (((RMuint32)p[12]<<16)&0x00ff0000) | (((RMuint32)p[13]<< 8)&0x0000ff00) | ((RMuint32)p[14]&0x000000ff); /* 32 bits */ *count = acclength; return des;}void DestoryDecoderConfigDescriptor(struct MP4_DecoderConfigDescriptor * des){ RMFree( des );}/*static void print_sl_descr( struct MP4_SLConfigDescriptor * sl ){ RMDBGLOG((CALLDBG, "\nSLConfigDescriptor 0x%x, %02x %02x %02x% 02x\n", (int)sl )); RMDBGLOG((CALLDBG, "tag (8 bits, default to 0x06) 0x%x \n", sl->tag )); RMDBGLOG((CALLDBG, "size (8 bits) 0x%x \n", sl->size )); RMDBGLOG((CALLDBG, "predefined (8 bits default 0) 0x%x\n", sl->predefined )); RMDBGLOG((CALLDBG, "useAccessUnitStartFlag %d\n", sl->useAccessUnitStartFlag )); RMDBGLOG((CALLDBG, "useAccessUnitEndFlag %d\n", sl->useAccessUnitEndFlag )); RMDBGLOG((CALLDBG, "useRandomAccessPointFlag %d\n", sl->useRandomAccessPointFlag )); RMDBGLOG((CALLDBG, "hasRandomAccessUnitsOnlyFlag %d\n", sl->hasRandomAccessUnitsOnlyFlag )); RMDBGLOG((CALLDBG, "usePaddingFlag %d\n", sl->usePaddingFlag )); RMDBGLOG((CALLDBG, "useTimeStampsFlag %d\n", sl->useTimeStampsFlag )); RMDBGLOG((CALLDBG, "useIdleFlag %d\n", sl->useIdleFlag )); RMDBGLOG((CALLDBG, "durationFlag %d\n", sl->durationFlag )); RMDBGLOG((CALLDBG, "timeStampResolution (32 bits) 0x%08x (%d)\n", sl->timeStampResolution, sl->timeStampResolution )); RMDBGLOG((CALLDBG, "OCRResolution (32 bits) 0x%08x (%d)\n", sl->OCRResolution, sl->OCRResolution )); RMDBGLOG((CALLDBG, "timeStampLength (8 bits) 0x%x \n", sl->timeStampLength )); RMDBGLOG((CALLDBG, "OCRLength (8 bits) 0x%x \n", sl->OCRLength )); RMDBGLOG((CALLDBG, "AU_Length (8 bits) 0x%x \n", sl->AU_Length )); RMDBGLOG((CALLDBG, "instantBitrateLength (8 bits) 0x%x \n", sl->instantBitrateLength )); RMDBGLOG((CALLDBG, "degradationPriorityLength (4 bits) 0x%x \n", sl->degradationPriorityLength )); RMDBGLOG((CALLDBG, "AU_seqNumLength (5 bits) 0x%x \n", sl->AU_seqNumLength )); RMDBGLOG((CALLDBG, "packet_SeqNumLength (5 bits) 0x%x \n", sl->packet_SeqNumLength )); return; }*/struct MP4_SLConfigDescriptor * CreateSLConfigDescriptor(RMuint8 *p, RMuint16 * count){ struct MP4_SLConfigDescriptor * des = NULL; RMuint16 acclength = 18; RMuint16 maxlength = *count; RMDBGLOG((CALLDBG, "CreateSLConfigDescriptor 0x%x, %02x %02x %02x% 02x\n", *count, p[0], p[1], p[2], p[3] )); if( maxlength < acclength ) { fprintf( stderr, "Error: input stream not long enough\n" ); return NULL; } des = (struct MP4_SLConfigDescriptor *)RMMalloc( sizeof(struct MP4_SLConfigDescriptor) ); if( !des ) { fprintf( stderr, "Error: failed create iod \n" ); return NULL; } RMMemset( des, 0, sizeof(struct MP4_SLConfigDescriptor) ); des->tag = p[0]; /* 8 bits, default to 0x06 */// assert( des->tag == 0x06 ); des->size = p[1]; /* 8 bits */ des->predefined = p[2]; /* 8 bits */// assert( des->predefined == 0 );// if( des->predefined == 0 ) des->useAccessUnitStartFlag = (p[3]>>7) & 0x01; /* 1 bit */ des->useAccessUnitEndFlag = (p[3]>>6) & 0x01; /* 1 bit */ des->useRandomAccessPointFlag = (p[3]>>5) & 0x01;/* 1 bit */ des->hasRandomAccessUnitsOnlyFlag = (p[3]>>4) & 0x01; /* 1 bit */ des->usePaddingFlag = (p[3]>>3) & 0x01; /* 1 bit */ des->useTimeStampsFlag = (p[3]>>2) & 0x01; /* 1 bit */ des->useIdleFlag = (p[3]>>1) & 0x01; /* 1 bit */ des->durationFlag = (p[3]) & 0x01; /* 1 bit */ des->timeStampResolution = (((RMuint32)p[4]<<24)&0xff000000) | (((RMuint32)p[5]<<16)&0x00ff0000) | (((RMuint32)p[6]<< 8)&0x0000ff00) | ((RMuint32)p[7]&0x000000ff); /* 32 bits */ des->OCRResolution = (((RMuint32)p[8]<<24)&0xff000000) | (((RMuint32)p[9]<<16)&0x00ff0000) | (((RMuint32)p[10]<< 8)&0x0000ff00) | ((RMuint32)p[11]&0x000000ff); /* 32 bits */ des->timeStampLength = p[12]; /* 8 bits */ des->OCRLength = p[13]; /* 8 bits */ des->AU_Length = p[14]; /* 8 bits */ des->instantBitrateLength = p[15]; /* 8 bits */ des->degradationPriorityLength = (p[16]>>4) & 0x0f; /* 4 bits */ des->AU_seqNumLength = ((p[16]&0x0f) << 1) | ((p[17]>>7)& 0x01); /* 5 bits */ des->packet_SeqNumLength = ((p[17]>>2)& 0x1f); /* 5 bits */// assert( (p[17]&0x03) == 0x03 ); /* 2 bit reserved default 0b11 */ if( des->durationFlag ) { des->timeScale = (((RMuint32)p[18]<<24)&0xff000000) | (((RMuint32)p[19]<<16)&0x00ff0000) | (((RMuint32)p[20]<< 8)&0x0000ff00) | ((RMuint32)p[21]&0x000000ff); /* 32 bits */ des->accessUnitDuration = (((RMuint16)p[22]<<8)&0xff00) | ((RMuint16)p[23]&0x00ff) ; /* 16 bits */ des->compositionUnitDuration = (((RMuint16)p[24]<<8)&0xff00) | ((RMuint16)p[25]&0x00ff) ; /* 16 bits */ }// if( ! des->useTimeStampsFlag ) { // startDecodingTimeStamp; // startCompositionTimeStamp;// } *count = acclength;// print_sl_descr( des ); return des;}void DestorySLConfigDescriptor(struct MP4_SLConfigDescriptor * des){ RMFree( des );}/* Parameters p - input stream count - input stream length *count - return the actually parsed length *des - a null pointer allocated with created objects Return RM_OK for success, RM_ERROR for failures Note, in case CreateDescriptor() encounters error DestoryDescriptor() must be called to cover possible memory leaks */AnyDescriptor * CreateDescriptor( RMuint8 * p, RMuint16* count ){// RMDBGLOG((CALLDBG, "CreateDescriptor 0x%x %02x %x\n", des, *p, *count )); switch( p[0] ) { /* use swtich based on the tag for now */ case 0x02: return (AnyDescriptor * )CreateIODDescriptor(p, count); case 0x03: return (AnyDescriptor * )CreateESDescriptor(p, count); case 0x04: return (AnyDescriptor * )CreateDecoderConfigDescriptor(p, count); case 0x06: return (AnyDescriptor * )CreateSLConfigDescriptor(p, count); default: RMDBGLOG((CALLDBG, "unknown descriptor %d \n", (int)p[0] )); return NULL; };}void DestoryDescriptor( AnyDescriptor * des ){ struct MP4_IOD * d = (struct MP4_IOD *)des; RMDBGLOG((CALLDBG, "DestoryDescriptor 0x%x\n", des)); if( ! des ) return; switch( d->tag ) { /* use switch based on the tag for now */ case 0x02: DestoryIODDescriptor((struct MP4_IOD *)des); break; case 0x03: DestoryESDescriptor((struct MP4_ES_Descriptor *)des); break; case 0x04: DestoryDecoderConfigDescriptor((struct MP4_DecoderConfigDescriptor *)des); break; case 0x06: DestorySLConfigDescriptor((struct MP4_SLConfigDescriptor *)des); break; default: fprintf( stderr, "unknown descriptor %d \n", (int)d->tag ); }; return;}void ParseIODDescriptor(RMuint8 *p, RMuint16 * bifs, RMuint16 * od ){ struct MP4_IOD * iod = NULL; RMuint16 i; RMuint16 count = p[1]-2; RMDBGLOG((CALLDBG, "parseIODDescriptor\n")); if (p == NULL) return; iod = (struct MP4_IOD *)CreateDescriptor( (p+4), &count ); /* now the BIFS and OD descriptors are inside the iod */ if( iod == NULL ) { RMDBGLOG((ENABLE, "Cannot create IOD Descriptor\n")); return; } for( i=0; i<iod->esDescrNum; i++ ) { //fprintf( stdout, "i %d, iod esDescrNum %d \n ", (int)i, (int)iod->esDescrNum ); struct MP4_ES_Descriptor * t = (struct MP4_ES_Descriptor *)iod->esDescr[i]; //fprintf( stdout, "tag %d, \n ", (int)t->tag ); if( t->tag == 0x03 ) { /* it is an ES descriptor */ RMuint16 j ; for( j=0; j<t->esDescrNum; j++ ) { struct MP4_DecoderConfigDescriptor * tt = (struct MP4_DecoderConfigDescriptor*)t->esDescr[j]; if( tt->tag == 0x04 ) { /* it is a decoderconfigdescriptor */ if( tt->streamType == 0x01 ) *od = t->ES_id; /* ObjectDescriptorStream ID */ else if( tt->streamType == 0x03 ) *bifs = t->ES_id; /* SceneDescriptorStream ID */ } } } } DestoryDescriptor( (void*)iod ); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -