📄 libmp4.c
字号:
static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, int64_t *i_read ){ unsigned int i_b; unsigned int i_len = 0; do { i_b = **pp_peek; (*pp_peek)++; (*i_read)--; i_len = ( i_len << 7 ) + ( i_b&0x7f ); } while( i_b&0x80 ); return( i_len );}static void MP4_FreeBox_esds( MP4_Box_t *p_box ){ FREENULL( p_box->data.p_esds->es_descriptor.psz_URL ); if( p_box->data.p_esds->es_descriptor.p_decConfigDescr ) { FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info ); FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr ); }}static int MP4_ReadBox_esds( stream_t *p_stream, MP4_Box_t *p_box ){#define es_descriptor p_box->data.p_esds->es_descriptor unsigned int i_len; unsigned int i_flags; unsigned int i_type; MP4_READBOX_ENTER( MP4_Box_data_esds_t ); MP4_GETVERSIONFLAGS( p_box->data.p_esds ); MP4_GET1BYTE( i_type ); if( i_type == 0x03 ) /* MP4ESDescrTag */ { i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );#ifdef MP4_VERBOSE msg_Dbg( p_stream, "found esds MPEG4ESDescr (%dBytes)", i_len );#endif MP4_GET2BYTES( es_descriptor.i_ES_ID ); MP4_GET1BYTE( i_flags ); es_descriptor.b_stream_dependence = ( (i_flags&0x80) != 0); es_descriptor.b_url = ( (i_flags&0x40) != 0); es_descriptor.b_OCRstream = ( (i_flags&0x20) != 0); es_descriptor.i_stream_priority = i_flags&0x1f; if( es_descriptor.b_stream_dependence ) { MP4_GET2BYTES( es_descriptor.i_depend_on_ES_ID ); } if( es_descriptor.b_url ) { unsigned int i_len; MP4_GET1BYTE( i_len ); es_descriptor.psz_URL = malloc( i_len + 1 ); if( es_descriptor.psz_URL ) { memcpy( es_descriptor.psz_URL, p_peek, i_len ); es_descriptor.psz_URL[i_len] = 0; } p_peek += i_len; i_read -= i_len; } else { es_descriptor.psz_URL = NULL; } if( es_descriptor.b_OCRstream ) { MP4_GET2BYTES( es_descriptor.i_OCR_ES_ID ); } MP4_GET1BYTE( i_type ); /* get next type */ } if( i_type != 0x04)/* MP4DecConfigDescrTag */ { es_descriptor.p_decConfigDescr = NULL; MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */ } i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );#ifdef MP4_VERBOSE msg_Dbg( p_stream, "found esds MP4DecConfigDescr (%dBytes)", i_len );#endif es_descriptor.p_decConfigDescr = calloc( 1, sizeof( MP4_descriptor_decoder_config_t )); if( es_descriptor.p_decConfigDescr == NULL ) MP4_READBOX_EXIT( 0 ); MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication ); MP4_GET1BYTE( i_flags ); es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2; es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01; MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB ); MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate ); MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate ); MP4_GET1BYTE( i_type ); if( i_type != 0x05 )/* MP4DecSpecificDescrTag */ { es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = 0; es_descriptor.p_decConfigDescr->p_decoder_specific_info = NULL; MP4_READBOX_EXIT( 1 ); } i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );#ifdef MP4_VERBOSE msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%dBytes)", i_len );#endif if( i_len > i_read ) MP4_READBOX_EXIT( 0 ); es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len; es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len ); if( es_descriptor.p_decConfigDescr->p_decoder_specific_info == NULL ) MP4_READBOX_EXIT( 0 ); memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info, p_peek, i_len ); MP4_READBOX_EXIT( 1 );#undef es_descriptor}static void MP4_FreeBox_avcC( MP4_Box_t *p_box ){ MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC; int i; if( p_avcC->i_avcC > 0 ) FREENULL( p_avcC->p_avcC ); if( p_avcC->sps ) { for( i = 0; i < p_avcC->i_sps; i++ ) FREENULL( p_avcC->sps[i] ); } if( p_avcC->pps ) { for( i = 0; i < p_avcC->i_pps; i++ ) FREENULL( p_avcC->pps[i] ); } if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->sps ); if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->i_sps_length ); if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->pps ); if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->i_pps_length );}static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box ){ MP4_Box_data_avcC_t *p_avcC; int i; MP4_READBOX_ENTER( MP4_Box_data_avcC_t ); p_avcC = p_box->data.p_avcC; p_avcC->i_avcC = i_read; if( p_avcC->i_avcC > 0 ) { uint8_t * p = p_avcC->p_avcC = malloc( p_avcC->i_avcC ); if( p ) memcpy( p, p_peek, i_read ); } MP4_GET1BYTE( p_avcC->i_version ); MP4_GET1BYTE( p_avcC->i_profile ); MP4_GET1BYTE( p_avcC->i_profile_compatibility ); MP4_GET1BYTE( p_avcC->i_level ); MP4_GET1BYTE( p_avcC->i_reserved1 ); p_avcC->i_length_size = (p_avcC->i_reserved1&0x03) + 1; p_avcC->i_reserved1 >>= 2; MP4_GET1BYTE( p_avcC->i_reserved2 ); p_avcC->i_sps = p_avcC->i_reserved2&0x1f; p_avcC->i_reserved2 >>= 5; if( p_avcC->i_sps > 0 ) { p_avcC->i_sps_length = calloc( p_avcC->i_sps, sizeof( uint16_t ) ); p_avcC->sps = calloc( p_avcC->i_sps, sizeof( uint8_t* ) ); if( !p_avcC->i_sps_length || !p_avcC->sps ) goto error; for( i = 0; i < p_avcC->i_sps; i++ ) { MP4_GET2BYTES( p_avcC->i_sps_length[i] ); p_avcC->sps[i] = malloc( p_avcC->i_sps_length[i] ); if( p_avcC->sps[i] ) memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] ); p_peek += p_avcC->i_sps_length[i]; i_read -= p_avcC->i_sps_length[i]; } } MP4_GET1BYTE( p_avcC->i_pps ); if( p_avcC->i_pps > 0 ) { p_avcC->i_pps_length = calloc( p_avcC->i_pps, sizeof( uint16_t ) ); p_avcC->pps = calloc( p_avcC->i_pps, sizeof( uint8_t* ) ); if( !p_avcC->i_pps_length || !p_avcC->pps ) goto error; for( i = 0; i < p_avcC->i_pps; i++ ) { MP4_GET2BYTES( p_avcC->i_pps_length[i] ); p_avcC->pps[i] = malloc( p_avcC->i_pps_length[i] ); if( p_avcC->pps[i] ) memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] ); p_peek += p_avcC->i_pps_length[i]; i_read -= p_avcC->i_pps_length[i]; } }#ifdef MP4_VERBOSE msg_Dbg( p_stream, "read box: \"avcC\" version=%d profile=0x%x level=0x%x length size=%d sps=%d pps=%d", p_avcC->i_version, p_avcC->i_profile, p_avcC->i_level, p_avcC->i_length_size, p_avcC->i_sps, p_avcC->i_pps ); for( i = 0; i < p_avcC->i_sps; i++ ) { msg_Dbg( p_stream, " - sps[%d] length=%d", i, p_avcC->i_sps_length[i] ); } for( i = 0; i < p_avcC->i_pps; i++ ) { msg_Dbg( p_stream, " - pps[%d] length=%d", i, p_avcC->i_pps_length[i] ); }#endif MP4_READBOX_EXIT( 1 );error: MP4_READBOX_EXIT( 0 );}static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box ){ unsigned int i; MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t ); p_box->data.p_sample_soun->p_qt_description = NULL; /* Sanity check needed because the "wave" box does also contain an * "mp4a" box that we don't understand. */ if( i_read < 28 ) { i_read -= 30; MP4_READBOX_EXIT( 1 ); } for( i = 0; i < 6 ; i++ ) { MP4_GET1BYTE( p_box->data.p_sample_soun->i_reserved1[i] ); } MP4_GET2BYTES( p_box->data.p_sample_soun->i_data_reference_index ); /* * XXX hack -> produce a copy of the nearly complete chunk */ p_box->data.p_sample_soun->i_qt_description = 0; p_box->data.p_sample_soun->p_qt_description = NULL; if( i_read > 0 ) { p_box->data.p_sample_soun->p_qt_description = malloc( i_read ); if( p_box->data.p_sample_soun->p_qt_description ) { p_box->data.p_sample_soun->i_qt_description = i_read; memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read ); } } MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version ); MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_revision_level ); MP4_GET4BYTES( p_box->data.p_sample_soun->i_qt_vendor ); MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount ); MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize ); MP4_GET2BYTES( p_box->data.p_sample_soun->i_predefined ); MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 ); MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi ); MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo ); if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 ) { /* SoundDescriptionV1 */ MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet ); MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet ); MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame ); MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_sample );#ifdef MP4_VERBOSE msg_Dbg( p_stream, "read box: \"soun\" qt3+ sample/packet=%d bytes/packet=%d " "bytes/frame=%d bytes/sample=%d", p_box->data.p_sample_soun->i_sample_per_packet, p_box->data.p_sample_soun->i_bytes_per_packet, p_box->data.p_sample_soun->i_bytes_per_frame, p_box->data.p_sample_soun->i_bytes_per_sample );#endif stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 44 ); } else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 ) { /* SoundDescriptionV2 */ double f_sample_rate; int64_t dummy; uint32_t i_channel; MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet ); MP4_GET8BYTES( dummy ); memcpy( &f_sample_rate, &dummy, 8 ); msg_Dbg( p_stream, "read box: %f Hz", f_sample_rate ); p_box->data.p_sample_soun->i_sampleratehi = (int)f_sample_rate % 65536; p_box->data.p_sample_soun->i_sampleratelo = f_sample_rate / 65536; MP4_GET4BYTES( i_channel ); p_box->data.p_sample_soun->i_channelcount = i_channel;#ifdef MP4_VERBOSE msg_Dbg( p_stream, "read box: \"soun\" V2" );#endif stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 + 36 ); } else { p_box->data.p_sample_soun->i_sample_per_packet = 0; p_box->data.p_sample_soun->i_bytes_per_packet = 0; p_box->data.p_sample_soun->i_bytes_per_frame = 0; p_box->data.p_sample_soun->i_bytes_per_sample = 0; msg_Dbg( p_stream, "read box: \"soun\" mp4 or qt1/2 (rest=%"PRId64")", i_read ); stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 ); } if( p_box->i_type == FOURCC_drms ) { p_box->data.p_sample_soun->p_drms = drms_alloc( config_GetHomeDir() ); if( p_box->data.p_sample_soun->p_drms == NULL ) { msg_Err( p_stream, "drms_alloc() failed" ); } } if( p_box->i_type == FOURCC_samr || p_box->i_type == FOURCC_sawb ) { /* Ignore channelcount for AMR (3gpp AMRSpecificBox) */ p_box->data.p_sample_soun->i_channelcount = 1; } MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds/wave/... */#ifdef MP4_VERBOSE msg_Dbg( p_stream, "read box: \"soun\" in stsd channel %d " "sample size %d sample rate %f", p_box->data.p_sample_soun->i_channelcount, p_box->data.p_sample_soun->i_samplesize, (float)p_box->data.p_sample_soun->i_sampleratehi + (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );#endif MP4_READBOX_EXIT( 1 );}static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box ){ FREENULL( p_box->data.p_sample_soun->p_qt_description ); if( p_box->i_type == FOURCC_drms ) { if( p_box->data.p_sample_soun->p_drms ) { drms_free( p_box->data.p_sample_soun->p_drms ); } }}int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box ){ unsigned int i; MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t ); for( i = 0; i < 6 ; i++ ) { MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] ); } MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index ); /* * XXX hack -> produce a copy of the nearly complete chunk */ if( i_read > 0 ) { p_box->data.p_sample_vide->p_qt_image_description = malloc( i_read ); if( p_box->data.p_sample_vide->p_qt_image_description == NULL ) MP4_READBOX_EXIT( 0 ); p_box->data.p_sample_vide->i_qt_image_description = i_read; memcpy( p_box->data.p_sample_vide->p_qt_image_description, p_peek, i_read ); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -