📄 mpeg4audio.c
字号:
if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts ) { /* We've just started the stream, wait for the first PTS. */ block_Release( *pp_block ); return NULL; } if( (*pp_block)->i_flags&BLOCK_FLAG_DISCONTINUITY ) { p_sys->i_state = STATE_NOSYNC; } block_BytestreamPush( &p_sys->bytestream, *pp_block ); while( 1 ) { switch( p_sys->i_state ) { case STATE_NOSYNC: while( block_PeekBytes( &p_sys->bytestream, p_header, 2 ) == VLC_SUCCESS ) { /* Look for sync word - should be 0xfff + 2 layer bits */ if( p_header[0] == 0xff && (p_header[1] & 0xf6) == 0xf0 ) { p_sys->i_state = STATE_SYNC; break; } block_SkipByte( &p_sys->bytestream ); } if( p_sys->i_state != STATE_SYNC ) { block_BytestreamFlush( &p_sys->bytestream ); /* Need more data */ return NULL; } case STATE_SYNC: /* New frame, set the Presentation Time Stamp */ p_sys->i_pts = p_sys->bytestream.p_block->i_pts; if( p_sys->i_pts != 0 && p_sys->i_pts != aout_DateGet( &p_sys->end_date ) ) { aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } p_sys->i_state = STATE_HEADER; break; case STATE_HEADER: /* Get ADTS frame header (ADTS_HEADER_SIZE bytes) */ if( block_PeekBytes( &p_sys->bytestream, p_header, ADTS_HEADER_SIZE ) != VLC_SUCCESS ) { /* Need more data */ return NULL; } /* Check if frame is valid and get frame info */ p_sys->i_frame_size = ADTSSyncInfo( p_dec, p_header, &p_sys->i_channels, &p_sys->i_rate, &p_sys->i_frame_length, &p_sys->i_header_size, &p_sys->i_raw_blocks ); if( p_sys->i_frame_size <= 0 ) { msg_Dbg( p_dec, "emulated sync word" ); block_SkipByte( &p_sys->bytestream ); p_sys->i_state = STATE_NOSYNC; break; } p_sys->i_state = STATE_NEXT_SYNC; case STATE_NEXT_SYNC: /* TODO: If p_block == NULL, flush the buffer without checking the * next sync word */ /* Check if next expected frame contains the sync word */ if( block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_frame_size + p_sys->i_header_size, p_header, 2 ) != VLC_SUCCESS ) { /* Need more data */ return NULL; } if( p_header[0] != 0xff || (p_header[1] & 0xf6) != 0xf0 ) { msg_Dbg( p_dec, "emulated sync word " "(no sync on following frame)" ); p_sys->i_state = STATE_NOSYNC; block_SkipByte( &p_sys->bytestream ); break; } p_sys->i_state = STATE_SEND_DATA; break; case STATE_GET_DATA: /* Make sure we have enough data. * (Not useful if we went through NEXT_SYNC) */ if( block_WaitBytes( &p_sys->bytestream, p_sys->i_frame_size + p_sys->i_header_size) != VLC_SUCCESS ) { /* Need more data */ return NULL; } p_sys->i_state = STATE_SEND_DATA; case STATE_SEND_DATA: if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) { //p_dec->b_error = VLC_TRUE; return NULL; } /* When we reach this point we already know we have enough * data available. */ /* Skip the ADTS header */ block_SkipBytes( &p_sys->bytestream, p_sys->i_header_size ); /* Copy the whole frame into the buffer */ block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size ); /* Make sure we don't reuse the same pts twice */ if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts ) p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0; /* So p_block doesn't get re-added several times */ *pp_block = block_BytestreamPop( &p_sys->bytestream ); p_sys->i_state = STATE_NOSYNC; return p_out_buffer; } } return NULL;}/***************************************************************************** * GetOutBuffer: *****************************************************************************/static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer ){ decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate ) { msg_Info( p_dec, "AAC channels: %d samplerate: %d", p_sys->i_channels, p_sys->i_rate ); aout_DateInit( &p_sys->end_date, p_sys->i_rate ); aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } p_dec->fmt_out.audio.i_rate = p_sys->i_rate; p_dec->fmt_out.audio.i_channels = p_sys->i_channels; p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size; p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;#if 0 p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf; p_dec->fmt_out.audio.i_physical_channels = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;#endif p_block = block_New( p_dec, p_sys->i_frame_size ); if( p_block == NULL ) return NULL; p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); p_block->i_length = aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ) - p_block->i_pts; *pp_out_buffer = p_block; return p_block->p_buffer;}/***************************************************************************** * ClosePacketizer: clean up the packetizer *****************************************************************************/static void ClosePacketizer( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; block_BytestreamRelease( &p_sys->bytestream ); free( p_dec->p_sys );}/***************************************************************************** * ADTSSyncInfo: parse MPEG 4 audio ADTS sync info *****************************************************************************/static int ADTSSyncInfo( decoder_t * p_dec, const byte_t * p_buf, unsigned int * pi_channels, unsigned int * pi_sample_rate, unsigned int * pi_frame_length, unsigned int * pi_header_size, unsigned int * pi_raw_blocks_in_frame ){ int i_id, i_profile, i_sample_rate_idx, i_frame_size; vlc_bool_t b_crc; /* Fixed header between frames */ i_id = ( (p_buf[1] >> 3) & 0x01 ) ? 2 : 4; b_crc = !(p_buf[1] & 0x01); i_profile = p_buf[2] >> 6; i_sample_rate_idx = (p_buf[2] >> 2) & 0x0f; *pi_sample_rate = i_sample_rates[i_sample_rate_idx]; *pi_channels = ((p_buf[2] & 0x01) << 2) | ((p_buf[3] >> 6) & 0x03); /* Variable header */ i_frame_size = ((p_buf[3] & 0x03) << 11) | (p_buf[4] << 3) | ((p_buf[5] >> 5) & 0x7); *pi_raw_blocks_in_frame = (p_buf[6] & 0x02) + 1; if( !*pi_sample_rate || !*pi_channels || !i_frame_size ) { return 0; } /* Fixme */ *pi_frame_length = 1024; /* Build the decoder specific info header */ if( !p_dec->fmt_out.i_extra ) { p_dec->fmt_out.i_extra = 2; p_dec->fmt_out.p_extra = malloc( 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -