📄 mpeg4audio.c
字号:
} p_dec->fmt_out.i_extra = 2; ((uint8_t *)p_dec->fmt_out.p_extra)[0] = (i_profile + 1) << 3 | (i_sample_rate_idx >> 1); ((uint8_t *)p_dec->fmt_out.p_extra)[1] = ((i_sample_rate_idx & 0x01) << 7) | (*pi_channels <<3); } /* ADTS header length */ *pi_header_size = b_crc ? 9 : 7; return i_frame_size - *pi_header_size;}/**************************************************************************** * LOAS helpers ****************************************************************************/static int LOASSyncInfo( uint8_t p_header[LOAS_HEADER_SIZE], unsigned int *pi_header_size ){ *pi_header_size = 3; return ( ( p_header[1] & 0x1f ) << 8 ) + p_header[2];}static int Mpeg4GAProgramConfigElement( bs_t *s ){ /* TODO compute channels count ? */ int i_tag = bs_read( s, 4 ); if( i_tag != 0x05 ) return -1; bs_skip( s, 2 + 4 ); // object type + sampling index int i_num_front = bs_read( s, 4 ); int i_num_side = bs_read( s, 4 ); int i_num_back = bs_read( s, 4 ); int i_num_lfe = bs_read( s, 2 ); int i_num_assoc_data = bs_read( s, 3 ); int i_num_valid_cc = bs_read( s, 4 ); if( bs_read1(s) ) bs_skip( s, 4 ); // mono downmix if( bs_read1(s) ) bs_skip( s, 4 ); // stereo downmix if( bs_read1(s) ) bs_skip( s, 2+1 ); // matrix downmix + pseudo_surround bs_skip( s, i_num_front * (1+4) ); bs_skip( s, i_num_side * (1+4) ); bs_skip( s, i_num_back * (1+4) ); bs_skip( s, i_num_lfe * (4) ); bs_skip( s, i_num_assoc_data * (4) ); bs_skip( s, i_num_valid_cc * (5) ); bs_align( s ); int i_comment = bs_read( s, 8 ); bs_skip( s, i_comment * 8 ); return 0;}static int Mpeg4GASpecificConfig( mpeg4_cfg_t *p_cfg, bs_t *s ){ p_cfg->i_frame_length = bs_read1(s) ? 960 : 1024; if( bs_read1( s ) ) // depend on core coder bs_skip( s, 14 ); // core coder delay int i_extension_flag = bs_read1( s ); if( p_cfg->i_channel == 0 ) { Mpeg4GAProgramConfigElement( s ); } if( p_cfg->i_object_type == 6 || p_cfg->i_object_type == 20 ) bs_skip( s, 3 ); // layer if( i_extension_flag ) { if( p_cfg->i_object_type == 22 ) { bs_skip( s, 5 + 11 ); // numOfSubFrame + layer length } if( p_cfg->i_object_type == 17 || p_cfg->i_object_type == 19 || p_cfg->i_object_type == 20 || p_cfg->i_object_type == 23 ) { bs_skip( s, 1+1+1 ); // ER data : section scale spectral */ } if( bs_read1( s ) ) // extension 3 fprintf( stderr, "Mpeg4GASpecificConfig: error 1\n" ); } return 0;}static int Mpeg4ReadAudioObjectType( bs_t *s ){ int i_type = bs_read( s, 5 ); if( i_type == 0x1f ) i_type += bs_read( s, 6 ); return i_type;}static int Mpeg4ReadAudioSamplerate( bs_t *s ){ int i_index = bs_read( s, 4 ); if( i_index != 0x0f ) return pi_sample_rates[i_index]; return bs_read( s, 24 );}static int Mpeg4ReadAudioSpecificInfo( mpeg4_cfg_t *p_cfg, int *pi_extra, uint8_t *p_extra, bs_t *s, int i_max_size ){#if 0 static const char *ppsz_otype[] = { "NULL", "AAC Main", "AAC LC", "AAC SSR", "AAC LTP", "SBR", "AAC Scalable", "TwinVQ", "CELP", "HVXC", "Reserved", "Reserved", "TTSI", "Main Synthetic", "Wavetables Synthesis", "General MIDI", "Algorithmic Synthesis and Audio FX", "ER AAC LC", "Reserved", "ER AAC LTP", "ER AAC Scalable", "ER TwinVQ", "ER BSAC", "ER AAC LD", "ER CELP", "ER HVXC", "ER HILN", "ER Parametric", "SSC", "Reserved", "Reserved", "Escape", "Layer 1", "Layer 2", "Layer 3", "DST", };#endif const int i_pos_start = bs_pos( s ); bs_t s_sav = *s; int i_bits; int i; memset( p_cfg, 0, sizeof(*p_cfg) ); *pi_extra = 0; p_cfg->i_object_type = Mpeg4ReadAudioObjectType( s ); p_cfg->i_samplerate = Mpeg4ReadAudioSamplerate( s ); p_cfg->i_channel = bs_read( s, 4 ); if( p_cfg->i_channel == 7 ) p_cfg->i_channel = 8; // 7.1 else if( p_cfg->i_channel >= 8 ) p_cfg->i_channel = -1; p_cfg->i_sbr = -1; p_cfg->extension.i_object_type = 0; p_cfg->extension.i_samplerate = 0; if( p_cfg->i_object_type == 5 ) { p_cfg->i_sbr = 1; p_cfg->extension.i_object_type = p_cfg->i_object_type; p_cfg->extension.i_samplerate = Mpeg4ReadAudioSamplerate( s ); p_cfg->i_object_type = Mpeg4ReadAudioObjectType( s ); } switch( p_cfg->i_object_type ) { case 1: case 2: case 3: case 4: case 6: case 7: case 17: case 19: case 20: case 21: case 22: case 23: Mpeg4GASpecificConfig( p_cfg, s ); break; case 8: // CelpSpecificConfig(); break; case 9: // HvxcSpecificConfig(); break; case 12: // TTSSSpecificConfig(); break; case 13: case 14: case 15: case 16: // StructuredAudioSpecificConfig(); break; case 24: // ERCelpSpecificConfig(); break; case 25: // ERHvxcSpecificConfig(); break; case 26: case 27: // ParametricSpecificConfig(); break; case 28: // SSCSpecificConfig(); break; case 32: case 33: case 34: // MPEG_1_2_SpecificConfig(); break; case 35: // DSTSpecificConfig(); break; default: // error break; } switch( p_cfg->i_object_type ) { case 17: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: { int epConfig = bs_read( s, 2 ); if( epConfig == 2 || epConfig == 3 ) { //ErrorProtectionSpecificConfig(); } if( epConfig == 3 ) { int directMapping = bs_read1( s ); if( directMapping ) { // tbd ... } } break; } default: break; } if( p_cfg->extension.i_object_type != 5 && i_max_size > 0 && i_max_size - (bs_pos(s) - i_pos_start) >= 16 && bs_read( s, 11 ) == 0x2b7 ) { p_cfg->extension.i_object_type = Mpeg4ReadAudioObjectType( s ); if( p_cfg->extension.i_object_type == 5 ) { p_cfg->i_sbr = bs_read1( s ); if( p_cfg->i_sbr == 1 ) p_cfg->extension.i_samplerate = Mpeg4ReadAudioSamplerate( s ); } } //fprintf( stderr, "Mpeg4ReadAudioSpecificInfo: t=%s(%d)f=%d c=%d sbr=%d\n", // ppsz_otype[p_cfg->i_object_type], p_cfg->i_object_type, p_cfg->i_samplerate, p_cfg->i_channel, p_cfg->i_sbr ); i_bits = bs_pos(s) - i_pos_start; *pi_extra = ( i_bits + 7 ) / 8; for( i = 0; i < __MIN( LATM_MAX_EXTRA_SIZE, *pi_extra ); i++ ) { const int i_read = __MIN( 8, i_bits - 8*i ); p_extra[i] = bs_read( &s_sav, i_read ) << (8-i_read); } return i_bits;}static int LatmGetValue( bs_t *s ){ int i_bytes = bs_read( s, 2 ); int v = 0; int i; for( i = 0; i < i_bytes; i++ ) v = (v << 8) + bs_read( s, 8 ); return v;}static int LatmReadStreamMuxConfiguration( latm_mux_t *m, bs_t *s ){ int i_mux_version; int i_mux_versionA; int i_program; i_mux_version = bs_read( s, 1 ); i_mux_versionA = 0; if( i_mux_version ) i_mux_versionA = bs_read( s, 1 ); if( i_mux_versionA != 0 ) /* support only A=0 */ return -1; memset( m, 0, sizeof(*m) ); if( i_mux_versionA == 0 ) { if( i_mux_version == 1 ) { LatmGetValue(s); /* taraBufferFullness */ } } m->b_same_time_framing = bs_read1( s ); m->i_sub_frames = 1 + bs_read( s, 6 ); m->i_programs = 1 + bs_read( s, 4 ); for( i_program = 0; i_program < m->i_programs; i_program++ ) { int i_layer; m->pi_layers[i_program] = 1+bs_read( s, 3 ); for( i_layer = 0; i_layer < m->pi_layers[i_program]; i_layer++ ) { latm_stream_t *st = &m->stream[m->i_streams]; bool b_previous_cfg; m->pi_stream[i_program][i_layer] = m->i_streams; st->i_program = i_program; st->i_layer = i_layer; b_previous_cfg = false; if( i_program != 0 || i_layer != 0 ) b_previous_cfg = bs_read1( s ); if( b_previous_cfg ) { assert( m->i_streams > 0 ); st->cfg = m->stream[m->i_streams-1].cfg; } else { int i_cfg_size = 0; if( i_mux_version == 1 ) i_cfg_size = LatmGetValue(s); i_cfg_size -= Mpeg4ReadAudioSpecificInfo( &st->cfg, &st->i_extra, st->extra, s, i_cfg_size ); if( i_cfg_size > 0 ) bs_skip( s, i_cfg_size ); } st->i_frame_length_type = bs_read( s, 3 ); switch( st->i_frame_length_type ) { case 0: { bs_skip( s, 8 ); /* latmBufferFullnes */ if( !m->b_same_time_framing ) { if( st->cfg.i_object_type == 6 || st->cfg.i_object_type == 20 || st->cfg.i_object_type == 8 || st->cfg.i_object_type == 24 ) { bs_skip( s, 6 ); /* eFrameOffset */ } } break; } case 1: st->i_frame_length = bs_read( s, 9 ); break; case 3: case 4: case 5: st->i_frame_length_index = bs_read( s, 6 ); // celp break; case 6: case 7: st->i_frame_length_index = bs_read( s, 1 ); // hvxc default: break; } /* Next stream */ m->i_streams++; } } /* other data */ if( bs_read1( s ) ) { if( i_mux_version == 1 ) { m->i_other_data = LatmGetValue( s ); } else { int b_continue; do { b_continue = bs_read1(s); m->i_other_data = (m->i_other_data << 8) + bs_read( s, 8 ); } while( b_continue ); } } /* crc */ m->i_crc = -1; if( bs_read1( s ) ) m->i_crc = bs_read( s, 8 ); return 0;}static int LOASParse( decoder_t *p_dec, uint8_t *p_buffer, int i_buffer ){ decoder_sys_t *p_sys = p_dec->p_sys; bs_t s; int i_sub; int i_accumulated = 0; bs_init( &s, p_buffer, i_buffer ); /* Read the stream mux configuration if present */ if( !bs_read1( &s ) ) { if( !LatmReadStreamMuxConfiguration( &p_sys->latm, &s ) && p_sys->latm.i_streams > 0 ) { const latm_stream_t *st = &p_sys->latm.stream[0]; p_sys->i_channels = st->cfg.i_channel; p_sys->i_rate = st->cfg.i_samplerate; p_sys->i_frame_length = st->cfg.i_frame_length; /* FIXME And if it changes ? */ if( !p_dec->fmt_out.i_extra && st->i_extra > 0 ) { p_dec->fmt_out.i_extra = st->i_extra; p_dec->fmt_out.p_extra = malloc( st->i_extra ); if( !p_dec->fmt_out.p_extra ) { p_dec->fmt_out.i_extra = 0; return 0; } memcpy( p_dec->fmt_out.p_extra, st->extra, st->i_extra ); } p_sys->b_latm_cfg = true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -