⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg4audio.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
    }    /* Wait for the configuration */    if( !p_sys->b_latm_cfg )        return 0;    /* FIXME do we need to split the subframe into independent packet ? */    if( p_sys->latm.i_sub_frames > 1 )        msg_Err( p_dec, "latm sub frames not yet supported, please send a sample" );    for( i_sub = 0; i_sub < p_sys->latm.i_sub_frames; i_sub++ )    {        int pi_payload[LATM_MAX_PROGRAM][LATM_MAX_LAYER];        if( p_sys->latm.b_same_time_framing )        {            int i_program;            /* Payload length */            for( i_program = 0; i_program < p_sys->latm.i_programs; i_program++ )            {                int i_layer;                for( i_layer = 0; i_layer < p_sys->latm.pi_layers[i_program]; i_layer++ )                {                    latm_stream_t *st = &p_sys->latm.stream[p_sys->latm.pi_stream[i_program][i_layer]];                    if( st->i_frame_length_type == 0 )                    {                        int i_payload = 0;                        for( ;; )                        {                            int i_tmp = bs_read( &s, 8 );                            i_payload += i_tmp;                            if( i_tmp != 255 )                                break;                        }                        pi_payload[i_program][i_layer] = i_payload;                    }                    else if( st->i_frame_length_type == 1 )                    {                        pi_payload[i_program][i_layer] = st->i_frame_length / 8; /* XXX not correct */                    }                    else if( ( st->i_frame_length_type == 3 ) ||                             ( st->i_frame_length_type == 5 ) ||                             ( st->i_frame_length_type == 7 ) )                    {                        bs_skip( &s, 2 ); // muxSlotLengthCoded                        pi_payload[i_program][i_layer] = 0; /* TODO */                    }                    else                    {                        pi_payload[i_program][i_layer] = 0; /* TODO */                    }                }            }            /* Payload Data */            for( i_program = 0; i_program < p_sys->latm.i_programs; i_program++ )            {                int i_layer;                int i;                for( i_layer = 0; i_layer < p_sys->latm.pi_layers[i_program]; i_layer++ )                {                    /* XXX we only extract 1 stream */                    if( i_program != 0 || i_layer != 0 )                        break;                    if( pi_payload[i_program][i_layer] <= 0 )                        continue;                    /* FIXME that's slow (and a bit ugly to write in place) */                    for( i = 0; i < pi_payload[i_program][i_layer]; i++ )                        p_buffer[i_accumulated++] = bs_read( &s, 8 );                }            }        }        else        {            const int i_chunks = bs_read( &s, 4 );            int pi_program[16];            int pi_layer[16];            int i_chunk;            msg_Err( p_dec, "latm without same time frameing not yet supported, please send a sample" );            for( i_chunk = 0; i_chunk < i_chunks; i_chunk++ )            {                const int streamIndex = bs_read( &s, 4 );                latm_stream_t *st = &p_sys->latm.stream[streamIndex];                const int i_program = st->i_program;                const int i_layer = st->i_layer;                pi_program[i_chunk] = i_program;                pi_layer[i_chunk] = i_layer;                if( st->i_frame_length_type == 0 )                {                    int i_payload = 0;                    for( ;; )                    {                        int i_tmp = bs_read( &s, 8 );                        i_payload += i_tmp;                        if( i_tmp != 255 )                            break;                    }                    pi_payload[i_program][i_layer] = i_payload;                    bs_skip( &s, 1 ); // auEndFlag                }                else if( st->i_frame_length_type == 1 )                {                    pi_payload[i_program][i_layer] = st->i_frame_length / 8; /* XXX not correct */                }                else if( ( st->i_frame_length_type == 3 ) ||                         ( st->i_frame_length_type == 5 ) ||                         ( st->i_frame_length_type == 7 ) )                {                    bs_read( &s, 2 ); // muxSlotLengthCoded                }                else                {                }            }            for( i_chunk = 0; i_chunk < i_chunks; i_chunk++ )            {                //const int i_program = pi_program[i_chunk];                //const int i_layer = pi_layer[i_chunk];                /* TODO ? Payload */            }        }    }    if( p_sys->latm.i_other_data > 0 )    {        /* Other data XXX we just ignore them */    }    bs_align( &s );    return i_accumulated;}/**************************************************************************** * PacketizeStreamBlock: ADTS/LOAS packetizer ****************************************************************************/static void SetupOutput( decoder_t *p_dec, block_t *p_block );static block_t *PacketizeStreamBlock( decoder_t *p_dec, block_t **pp_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    uint8_t p_header[ADTS_HEADER_SIZE + LOAS_HEADER_SIZE];    block_t *p_out_buffer;    uint8_t *p_buf;    if( !pp_block || !*pp_block ) return NULL;    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )    {        if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )        {            p_sys->i_state = STATE_NOSYNC;            block_BytestreamFlush( &p_sys->bytestream );        }        //aout_DateSet( &p_sys->end_date, 0 );        block_Release( *pp_block );        return NULL;    }    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_rate > 0 )        p_sys->i_input_rate = (*pp_block)->i_rate;    block_BytestreamPush( &p_sys->bytestream, *pp_block );    for( ;; )    {        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(adts) or 0x2b7(loas) */                if( p_header[0] == 0xff && (p_header[1] & 0xf6) == 0xf0 )                {                    if( p_sys->i_type != TYPE_ADTS )                        msg_Dbg( p_dec, "detected ADTS format" );                    p_sys->i_state = STATE_SYNC;                    p_sys->i_type = TYPE_ADTS;                    break;                }                else if( p_header[0] == 0x56 && (p_header[1] & 0xe0) == 0xe0 )                {                    if( p_sys->i_type != TYPE_LOAS )                        msg_Dbg( p_dec, "detected LOAS format" );                    p_sys->i_state = STATE_SYNC;                    p_sys->i_type = TYPE_LOAS;                    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:            if( p_sys->i_type == TYPE_ADTS )            {                /* 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 );            }            else            {                assert( p_sys->i_type == TYPE_LOAS );                /* Get LOAS frame header (LOAS_HEADER_SIZE bytes) */                if( block_PeekBytes( &p_sys->bytestream, p_header,                                     LOAS_HEADER_SIZE ) != VLC_SUCCESS )                {                    /* Need more data */                    return NULL;                }                /* Check if frame is valid and get frame info */                p_sys->i_frame_size = LOASSyncInfo( p_header, &p_sys->i_header_size );            }            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 */            if( p_sys->bytestream.p_block == NULL )            {                p_sys->i_state = STATE_NOSYNC;                block_BytestreamFlush( &p_sys->bytestream );                return NULL;            }            /* 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;            }            assert( (p_sys->i_type == TYPE_ADTS) || (p_sys->i_type == TYPE_LOAS) );            if( ( ( p_sys->i_type == TYPE_ADTS ) &&                  ( p_header[0] != 0xff || (p_header[1] & 0xf6) != 0xf0 ) ) ||                ( ( p_sys->i_type == TYPE_LOAS ) &&                  ( p_header[0] != 0x56 || (p_header[1] & 0xe0) != 0xe0 ) ) )            {                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:            /* When we reach this point we already know we have enough             * data available. */            p_out_buffer = block_New( p_dec, p_sys->i_frame_size );            if( !p_out_buffer )            {                //p_dec->b_error = true;                return NULL;            }            p_buf = p_out_buffer->p_buffer;            /* Skip the ADTS/LOAS header */            block_SkipBytes( &p_sys->bytestream, p_sys->i_header_size );            if( p_sys->i_type == TYPE_ADTS )            {                /* Copy the whole frame into the buffer */                block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );            }            else            {                assert( p_sys->i_type == TYPE_LOAS );                /* Copy the whole frame into the buffer and parse/extract it */                block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );                p_out_buffer->i_buffer = LOASParse( p_dec, p_buf, p_sys->i_frame_size );                if( p_out_buffer->i_buffer <= 0 )                {                    if( !p_sys->b_latm_cfg )                        msg_Warn( p_dec, "waiting for header" );                    block_Release( p_out_buffer );                    p_out_buffer = NULL;                    p_sys->i_state = STATE_NOSYNC;                    break;                }            }            SetupOutput( p_dec, p_out_buffer );            /* 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;}/***************************************************************************** * SetupBuffer: *****************************************************************************/static void SetupOutput( decoder_t *p_dec, block_t *p_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    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->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_sys->i_input_rate / INPUT_RATE_DEFAULT ) -                                p_block->i_pts;}/***************************************************************************** * 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 );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -