Beispiel #1
0
static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_pic = NULL;

    const int i_nal_ref_idc = (p_frag->p_buffer[3] >> 5)&0x03;
    const int i_nal_type = p_frag->p_buffer[3]&0x1f;

    if( p_sys->b_slice && !p_sys->b_sps )
    {
        block_ChainRelease( p_sys->p_frame );
        msg_Warn( p_dec, "waiting for SPS" );

        /* Reset context */
        p_sys->p_frame = NULL;
        p_sys->b_slice = VLC_FALSE;
    }

    if( !p_sys->b_sps &&
            i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR )
    {
        p_sys->b_slice = VLC_TRUE;
        /* Fragment will be discarded later on */
    }
    else if( i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR )
    {
        uint8_t *dec;
        int i_dec, i_first_mb, i_slice_type, i_frame_num, i_pic_flags = 0;
        vlc_bool_t b_pic = VLC_FALSE;
        bs_t s;

        /* do not convert the whole frame */
        nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4],
                         __MIN( p_frag->i_buffer - 4, 60 ) );
        bs_init( &s, dec, i_dec );

        /* first_mb_in_slice */
        i_first_mb = bs_read_ue( &s );

        /* slice_type */
        switch( (i_slice_type = bs_read_ue( &s )) )
        {
        case 0:
        case 5:
            i_pic_flags = BLOCK_FLAG_TYPE_P;
            break;
        case 1:
        case 6:
            i_pic_flags = BLOCK_FLAG_TYPE_B;
            break;
        case 2:
        case 7:
            i_pic_flags = BLOCK_FLAG_TYPE_I;
            break;
        case 3:
        case 8: /* SP */
            i_pic_flags = BLOCK_FLAG_TYPE_P;
            break;
        case 4:
        case 9:
            i_pic_flags = BLOCK_FLAG_TYPE_I;
            break;
        }

        /* pic_parameter_set_id */
        bs_read_ue( &s );
        /* frame_num */
        i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 );

        /* Detection of the first VCL NAL unit of a primary coded picture
         * (cf. 7.4.1.2.4) */
        if( i_frame_num != p_sys->i_frame_num ||
                ( (i_nal_ref_idc != p_sys->i_nal_ref_idc) &&
                  (!i_nal_ref_idc || !p_sys->i_nal_ref_idc) ) )
        {
            b_pic = VLC_TRUE;
        }
        p_sys->i_frame_num = i_frame_num;
        p_sys->i_nal_ref_idc = i_nal_ref_idc;

        if( !p_sys->b_frame_mbs_only )
        {
            /* field_pic_flag */
            if( bs_read( &s, 1 ) )
            {
                /* bottom_field_flag */
                bs_read( &s, 1 );
            }
        }

        if( i_nal_type == NAL_SLICE_IDR )
        {
            /* id_pic_id */
            int i_idr_pic_id = bs_read_ue( &s );
            if( p_sys->i_nal_type != i_nal_type ) b_pic = VLC_TRUE;
            if( p_sys->i_idr_pic_id != i_idr_pic_id ) b_pic = VLC_TRUE;
            p_sys->i_idr_pic_id = i_idr_pic_id;
        }
        p_sys->i_nal_type = i_nal_type;

        if( b_pic && p_sys->b_slice )
        {
            p_pic = block_ChainGather( p_sys->p_frame );
            p_pic->i_dts = p_sys->i_dts;
            p_pic->i_pts = p_sys->i_pts;
            p_pic->i_length = 0;    /* FIXME */
            p_pic->i_flags = p_sys->i_flags;

            /* Reset context */
            p_sys->p_frame = NULL;
            p_sys->b_slice = VLC_FALSE;
        }

        p_sys->b_slice = VLC_TRUE;
        p_sys->i_flags = i_pic_flags;
        p_sys->i_dts   = p_frag->i_dts;
        p_sys->i_pts   = p_frag->i_pts;

        free( dec );
    }
    else if( i_nal_type == NAL_SPS )
    {
        uint8_t *dec;
        int     i_dec;
        bs_t s;
        int i_tmp;

        msg_Dbg( p_dec, "found NAL_SPS" );

        p_sys->b_sps = VLC_TRUE;

        nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4],
                         p_frag->i_buffer - 4 );

        bs_init( &s, dec, i_dec );
        /* Skip profile(8), constraint_set012, reserver(5), level(8) */
        bs_skip( &s, 8 + 1+1+1 + 5 + 8 );
        /* sps id */
        bs_read_ue( &s );
        /* Skip i_log2_max_frame_num */
        p_sys->i_log2_max_frame_num = bs_read_ue( &s );
        /* Read poc_type */
        i_tmp = bs_read_ue( &s );
        if( i_tmp == 0 )
        {
            /* skip i_log2_max_poc_lsb */
            bs_read_ue( &s );
        }
        else if( i_tmp == 1 )
        {
            int i_cycle;
            /* skip b_delta_pic_order_always_zero */
            bs_skip( &s, 1 );
            /* skip i_offset_for_non_ref_pic */
            bs_read_se( &s );
            /* skip i_offset_for_top_to_bottom_field */
            bs_read_se( &s );
            /* read i_num_ref_frames_in_poc_cycle */
            i_cycle = bs_read_ue( &s );
            if( i_cycle > 256 ) i_cycle = 256;
            while( i_cycle > 0 )
            {
                /* skip i_offset_for_ref_frame */
                bs_read_se(&s );
            }
        }
        /* i_num_ref_frames */
        bs_read_ue( &s );
        /* b_gaps_in_frame_num_value_allowed */
        bs_skip( &s, 1 );

        /* Read size */
        p_dec->fmt_out.video.i_width  = 16 * ( bs_read_ue( &s ) + 1 );
        p_dec->fmt_out.video.i_height = 16 * ( bs_read_ue( &s ) + 1 );

        /* b_frame_mbs_only */
        p_sys->b_frame_mbs_only = bs_read( &s, 1 );
        if( p_sys->b_frame_mbs_only == 0 )
        {
            bs_skip( &s, 1 );
        }
        /* b_direct8x8_inference */
        bs_skip( &s, 1 );

        /* crop */
        i_tmp = bs_read( &s, 1 );
        if( i_tmp )
        {
            /* left */
            bs_read_ue( &s );
            /* right */
            bs_read_ue( &s );
            /* top */
            bs_read_ue( &s );
            /* bottom */
            bs_read_ue( &s );
        }

        /* vui */
        i_tmp = bs_read( &s, 1 );
        if( i_tmp )
        {
            /* read the aspect ratio part if any FIXME check it */
            i_tmp = bs_read( &s, 1 );
            if( i_tmp )
            {
                static const struct {
                    int w, h;
                } sar[14] =
                {
                    { 0,   0 }, { 1,   1 }, { 12, 11 }, { 10, 11 },
                    { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 },
                    { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 },
                    { 64, 33 }, { 160,99 },
                };
                int i_sar = bs_read( &s, 8 );
                int w, h;

                if( i_sar < 14 )
                {
                    w = sar[i_sar].w;
                    h = sar[i_sar].h;
                }
                else
                {
                    w = bs_read( &s, 16 );
                    h = bs_read( &s, 16 );
                }
                p_dec->fmt_out.video.i_aspect =
                    VOUT_ASPECT_FACTOR * w / h * p_dec->fmt_out.video.i_width /
                    p_dec->fmt_out.video.i_height;
            }
        }

        free( dec );
    }
    else if( i_nal_type == NAL_PPS )
    {
        bs_t s;
        bs_init( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );

        /* TODO */
        msg_Dbg( p_dec, "found NAL_PPS" );
    }

    /* Append the block */
    block_ChainAppend( &p_sys->p_frame, p_frag );

    return p_pic;
}
Beispiel #2
0
/* MPLS */
void bd_mpls_stream_Parse( bd_mpls_stream_t *p_stream, bs_t *s, int i_class )
{
    /* Stream entry parsing */
    const int i_entry_length = bs_read( s, 8 );
    const int i_entry_start = bs_pos( s ) / 8;

    p_stream->i_type = bs_read( s, 8 );
    p_stream->i_class = i_class;
    if( p_stream->i_type == BD_MPLS_STREAM_TYPE_PLAY_ITEM )
    {
        p_stream->play_item.i_pid = bs_read( s, 16 );
    }
    else if( p_stream->i_type == BD_MPLS_STREAM_TYPE_SUB_PATH )
    {
        p_stream->sub_path.i_sub_path_id = bs_read( s, 8 );
        p_stream->sub_path.i_sub_clip_id = bs_read( s, 8 );
        p_stream->sub_path.i_pid = bs_read( s, 16 );
    }
    else if( p_stream->i_type == BD_MPLS_STREAM_TYPE_IN_MUX_SUB_PATH )
    {
        p_stream->in_mux_sub_path.i_sub_path_id = bs_read( s, 8 );
        p_stream->in_mux_sub_path.i_pid = bs_read( s, 16 );
    }
    bs_skip( s, 8 * ( i_entry_start + i_entry_length ) - bs_pos( s ) );

    /* Stream attributes parsing */
    const int i_attributes_length = bs_read( s, 8 );
    const int i_attributes_start = bs_pos( s ) / 8;

    p_stream->i_stream_type = bs_read( s, 8 );
    strcpy( p_stream->psz_language, "" );
    p_stream->i_charset = -1;

    if( p_stream->i_stream_type == 0x02 || /* MPEG-I/II */
        p_stream->i_stream_type == 0x1b || /* AVC */
        p_stream->i_stream_type == 0xea )  /* VC-1 */
    {
        /* Video */
    }
    else if( ( p_stream->i_stream_type >= 0x80 && p_stream->i_stream_type <= 0x8f ) ||
             ( p_stream->i_stream_type >= 0xa0 && p_stream->i_stream_type <= 0xaf ) )
    {
        /* Audio */
        bs_skip( s, 4 );
        bs_skip( s, 4 );
        for( int i = 0; i < 3; i++ )
            p_stream->psz_language[i] = bs_read( s, 8 );
        p_stream->psz_language[3] = '\0';
    }
    else if( p_stream->i_stream_type == 0x90 ||   /* PG stream */
             p_stream->i_stream_type == 0x91 )    /* IG stream */
    {
        for( int i = 0; i < 3; i++ )
            p_stream->psz_language[i] = bs_read( s, 8 );
        p_stream->psz_language[3] = '\0';
    }
    else if( p_stream->i_stream_type == 0x92 )    /* Text stream */
    {
        p_stream->i_charset = bs_read( s, 8 );
        for( int i = 0; i < 3; i++ )
            p_stream->psz_language[i] = bs_read( s, 8 );
        p_stream->psz_language[3] = '\0';
    }

    bs_skip( s, 8 * ( i_attributes_start + i_attributes_length ) - bs_pos( s ) );
}
Beispiel #3
0
static int dirac_bool( bs_t *p_bs )
{
    return bs_read( p_bs, 1 );
}
Beispiel #4
0
void bd_mpls_play_item_Parse( bd_mpls_play_item_t *p_item, bs_t *s )
{
    const int i_length = bs_read( s, 16 );
    const int i_start = bs_pos( s ) / 8;

    char psz_name[5+1];
    for( int j = 0; j < 5; j++ )
        psz_name[j] = bs_read( s, 8 );
    psz_name[5] = '\0';

    p_item->clpi.i_id = strtol( psz_name, NULL, 10 );

    bs_skip( s, 32 );

    bs_skip( s, 11 );
    const bool b_angle = bs_read( s, 1 );

    p_item->i_connection = bs_read( s, 4 );
    p_item->clpi.i_stc_id = bs_read( s, 8 );
    p_item->i_in_time = bs_read( s, 32 );
    p_item->i_out_time = bs_read( s, 32 );
    bs_skip( s, 64 );
    bs_skip( s, 1 );
    bs_skip( s, 7 );
    p_item->i_still = bs_read( s, 8 );
    p_item->i_still_time = bs_read( s, 16 );
    if( p_item->i_still == BD_MPLS_PLAY_ITEM_STILL_NONE )
        p_item->i_still_time = 0;
    else if( p_item->i_still == BD_MPLS_PLAY_ITEM_STILL_INFINITE )
        p_item->i_still_time = INT_MAX;

    if( b_angle )
    {
        const int i_angle = bs_read( s, 8 );
        bs_skip( s, 6 );
        p_item->b_angle_different_audio = bs_read( s, 1 );
        p_item->b_angle_seamless = bs_read( s, 1 );

        p_item->p_clpi = calloc( i_angle, sizeof(*p_item->p_clpi) );
        for( p_item->i_clpi = 0; p_item->i_clpi < i_angle; p_item->i_clpi++ )
        {
            if( !p_item->p_clpi )
                break;

            bd_mpls_clpi_t *p_clpi = &p_item->p_clpi[p_item->i_clpi];

            char psz_name[5+1];
            for( int j = 0; j < 5; j++ )
                psz_name[j] = bs_read( s, 8 );
            psz_name[5] = '\0';

            p_clpi->i_id = strtol( psz_name, NULL, 10 );

            bs_skip( s, 32 );

            p_clpi->i_stc_id = bs_read( s, 8 );
        }
    }
    else
    {
        p_item->i_clpi = 0;
        p_item->p_clpi = NULL;
        p_item->b_angle_different_audio = false;
        p_item->b_angle_seamless = true;
    }

    /* STN Table */
    bs_skip( s, 16 );  /* Length */
    bs_skip( s, 16 );

    const int i_video = bs_read( s, 8 );
    const int i_audio = bs_read( s, 8 );
    const int i_pg = bs_read( s, 8 );
    const int i_ig = bs_read( s, 8 );
    const int i_audio_2 = bs_read( s, 8 );
    const int i_video_2 = bs_read( s, 8 );
    const int i_pip_pg = bs_read( s, 8 );
    bs_skip( s, 40 );

    p_item->i_stream = 0;
    p_item->p_stream = calloc( i_video + i_audio + i_pg + i_ig,
                               sizeof(*p_item->p_stream) );

    for( int j = 0; j < i_video; j++, p_item->i_stream++ )
    {
        if( !p_item->p_stream )
            break;

        bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s,
                              BD_MPLS_STREAM_CLASS_PRIMARY_VIDEO );
    }
    for( int j = 0; j < i_audio; j++, p_item->i_stream++ )
    {
        if( !p_item->p_stream )
            break;

        bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s,
                              BD_MPLS_STREAM_CLASS_PRIMARY_AUDIO );
    }
    for( int j = 0; j < i_pg; j++, p_item->i_stream++ )
    {
        if( !p_item->p_stream )
            break;

        bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s,
                              BD_MPLS_STREAM_CLASS_PG );
    }
    for( int j = 0; j < i_ig; j++, p_item->i_stream++ )
    {
        if( !p_item->p_stream )
            break;

        bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s,
                              BD_MPLS_STREAM_CLASS_IG );
    }
    for( int j = 0; j < i_audio_2; j++ )
    {
        /* TODO I need samples */
    }
    for( int j = 0; j < i_video_2; j++ )
    {
        /* TODO I need samples */
    }
    for( int j = 0; j < i_pip_pg; j++ )
    {
        /* TODO I need samples */
    }

    bs_skip( s, 8 * ( i_start + i_length ) - bs_pos( s ) );
}
Beispiel #5
0
int bd_mpls_Parse( bd_mpls_t *p_mpls, bs_t *s, int i_id )
{
    const int i_start = bs_pos( s ) / 8;

    /* */
    if( bs_read( s, 32 ) != 0x4d504c53 )
        return VLC_EGENERIC;
    const uint32_t i_version = bs_read( s, 32 );
    if( i_version != 0x30313030 && i_version != 0x30323030 )
        return VLC_EGENERIC;

    const uint32_t i_play_item_start = bs_read( s, 32 );
    const uint32_t i_mark_start = bs_read( s, 32 );
    bs_skip( s, 32 );   /* Extension start */

    /* */
    p_mpls->i_id = i_id;

    /* Read AppInfo: ignored */

    /* Read Playlist */
    bs_t ps = *s;
    bs_skip( &ps, 8 * ( i_start + i_play_item_start ) - bs_pos( s ) );
    bs_skip( &ps, 32 ); /* Length */
    bs_skip( &ps, 16 );
    const int i_play_item = bs_read( &ps, 16 );
    const int i_sub_path = bs_read( &ps, 16 );

    p_mpls->p_play_item = calloc( i_play_item, sizeof(*p_mpls->p_play_item) );
    for( p_mpls->i_play_item = 0; p_mpls->i_play_item < i_play_item; p_mpls->i_play_item++ )
    {
        if( !p_mpls->p_play_item )
            break;
        bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[p_mpls->i_play_item];

        bd_mpls_play_item_Parse( p_item, &ps );
    }
    p_mpls->p_sub_path = calloc( i_sub_path, sizeof(*p_mpls->p_sub_path) );
    for( p_mpls->i_sub_path = 0; p_mpls->i_sub_path < i_sub_path; p_mpls->i_sub_path++ )
    {
        if( !p_mpls->p_sub_path )
            break;
        bd_mpls_sub_path_t *p_sub = &p_mpls->p_sub_path[p_mpls->i_sub_path];

        bd_mpls_sub_path_Parse( p_sub, &ps );
    }

    /* Read Mark */
    bs_t ms = *s;
    bs_skip( &ms, 8 * ( i_start + i_mark_start ) - bs_pos( s ) );
    bs_skip( &ms, 32 );
    const int i_mark = bs_read( &ms, 16 );

    p_mpls->p_mark = calloc( i_mark, sizeof(*p_mpls->p_mark) );
    for( p_mpls->i_mark = 0; p_mpls->i_mark < i_mark; p_mpls->i_mark++ )
    {
        if( !p_mpls->p_mark )
            break;
        bd_mpls_mark_t *p_mark = &p_mpls->p_mark[p_mpls->i_mark];

        bd_mpls_mark_Parse( p_mark, &ms );
    }

    /* Read Extension: ignored */

    return VLC_SUCCESS;
}
Beispiel #6
0
static void ParseSei( decoder_t *p_dec, block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint8_t *pb_dec;
    int i_dec;

    /* */
    CreateDecodedNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5], p_frag->i_buffer - 5 );
    if( !pb_dec )
        return;

    /* The +1 is for rbsp trailing bits */
    for( int i_used = 0; i_used+1 < i_dec; )
    {
        /* Read type */
        int i_type = 0;
        while( i_used+1 < i_dec )
        {
            const int i_byte = pb_dec[i_used++];
            i_type += i_byte;
            if( i_byte != 0xff )
                break;
        }
        /* Read size */
        int i_size = 0;
        while( i_used+1 < i_dec )
        {
            const int i_byte = pb_dec[i_used++];
            i_size += i_byte;
            if( i_byte != 0xff )
                break;
        }
        /* Check room */
        if( i_used + i_size + 1 > i_dec )
            break;

        /* Look for pic timing */
        if( i_type == SEI_PIC_TIMING )
        {
            bs_t s;
            const int      i_tim = i_size;
            const uint8_t *p_tim = &pb_dec[i_used];

            bs_init( &s, p_tim, i_tim );

            if( p_sys->b_cpb_dpb_delays_present_flag )
            {
                bs_read( &s, p_sys->i_cpb_removal_delay_length_minus1 + 1 );
                bs_read( &s, p_sys->i_dpb_output_delay_length_minus1 + 1 );
            }

            if( p_sys->b_pic_struct_present_flag )
                p_sys->i_pic_struct = bs_read( &s, 4 );
            /* + unparsed remains */
        }

        /* Look for user_data_registered_itu_t_t35 */
        if( i_type == SEI_USER_DATA_REGISTERED )
        {
            static const uint8_t p_dvb1_data_start_code[] = {
                0xb5,
                0x00, 0x31,
                0x47, 0x41, 0x39, 0x34
            };
            const int      i_t35 = i_size;
            const uint8_t *p_t35 = &pb_dec[i_used];

            /* Check for we have DVB1_data() */
            if( i_t35 >= 5 &&
                !memcmp( p_t35, p_dvb1_data_start_code, sizeof(p_dvb1_data_start_code) ) )
            {
                cc_Extract( &p_sys->cc_next, true, &p_t35[3], i_t35 - 3 );
            }
        }

        /* Look for SEI recovery point */
        if( i_type == SEI_RECOVERY_POINT )
        {
            bs_t s;
            const int      i_rec = i_size;
            const uint8_t *p_rec = &pb_dec[i_used];

            bs_init( &s, p_rec, i_rec );
            int i_recovery_frames = bs_read_ue( &s );
            //bool b_exact_match = bs_read( &s, 1 );
            //bool b_broken_link = bs_read( &s, 1 );
            //int i_changing_slice_group = bs_read( &s, 2 );
            if( !p_sys->b_header )
            {
                msg_Dbg( p_dec, "Seen SEI recovery point, %d recovery frames", i_recovery_frames );
                if ( p_sys->i_recovery_frames == -1 || i_recovery_frames < p_sys->i_recovery_frames )
                    p_sys->i_recovery_frames = i_recovery_frames;
            }
        }

        i_used += i_size;
    }

    free( pb_dec );
}
Beispiel #7
0
static void PutSPS( decoder_t *p_dec, block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    uint8_t *pb_dec = NULL;
    int     i_dec = 0;
    bs_t s;
    int i_tmp;
    int i_sps_id;

    CreateDecodedNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5],
                     p_frag->i_buffer - 5 );

    bs_init( &s, pb_dec, i_dec );
    int i_profile_idc = bs_read( &s, 8 );
    p_dec->fmt_out.i_profile = i_profile_idc;
    /* Skip constraint_set0123, reserved(4) */
    bs_skip( &s, 1+1+1+1 + 4 );
    p_dec->fmt_out.i_level = bs_read( &s, 8 );
    /* sps id */
    i_sps_id = bs_read_ue( &s );
    if( i_sps_id >= SPS_MAX || i_sps_id < 0 )
    {
        msg_Warn( p_dec, "invalid SPS (sps_id=%d)", i_sps_id );
        free( pb_dec );
        block_Release( p_frag );
        return;
    }

    if( i_profile_idc == PROFILE_H264_HIGH || i_profile_idc == PROFILE_H264_HIGH_10 ||
        i_profile_idc == PROFILE_H264_HIGH_422 || i_profile_idc == PROFILE_H264_HIGH_444_PREDICTIVE ||
        i_profile_idc ==  PROFILE_H264_CAVLC_INTRA || i_profile_idc ==  PROFILE_H264_SVC_BASELINE ||
        i_profile_idc ==  PROFILE_H264_SVC_HIGH )
    {
        /* chroma_format_idc */
        const int i_chroma_format_idc = bs_read_ue( &s );
        if( i_chroma_format_idc == 3 )
            bs_skip( &s, 1 ); /* separate_colour_plane_flag */
        /* bit_depth_luma_minus8 */
        bs_read_ue( &s );
        /* bit_depth_chroma_minus8 */
        bs_read_ue( &s );
        /* qpprime_y_zero_transform_bypass_flag */
        bs_skip( &s, 1 );
        /* seq_scaling_matrix_present_flag */
        i_tmp = bs_read( &s, 1 );
        if( i_tmp )
        {
            for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ )
            {
                /* seq_scaling_list_present_flag[i] */
                i_tmp = bs_read( &s, 1 );
                if( !i_tmp )
                    continue;
                const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64;
                /* scaling_list (...) */
                int i_lastscale = 8;
                int i_nextscale = 8;
                for( int j = 0; j < i_size_of_scaling_list; j++ )
                {
                    if( i_nextscale != 0 )
                    {
                        /* delta_scale */
                        i_tmp = bs_read_se( &s );
                        i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256;
                        /* useDefaultScalingMatrixFlag = ... */
                    }
                    /* scalinglist[j] */
                    i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale;
                }
            }
        }
    }

    /* Skip i_log2_max_frame_num */
    p_sys->i_log2_max_frame_num = bs_read_ue( &s );
    if( p_sys->i_log2_max_frame_num > 12)
        p_sys->i_log2_max_frame_num = 12;
    /* Read poc_type */
    p_sys->i_pic_order_cnt_type = bs_read_ue( &s );
    if( p_sys->i_pic_order_cnt_type == 0 )
    {
        /* skip i_log2_max_poc_lsb */
        p_sys->i_log2_max_pic_order_cnt_lsb = bs_read_ue( &s );
        if( p_sys->i_log2_max_pic_order_cnt_lsb > 12 )
            p_sys->i_log2_max_pic_order_cnt_lsb = 12;
    }
    else if( p_sys->i_pic_order_cnt_type == 1 )
    {
        int i_cycle;
        /* skip b_delta_pic_order_always_zero */
        p_sys->i_delta_pic_order_always_zero_flag = bs_read( &s, 1 );
        /* skip i_offset_for_non_ref_pic */
        bs_read_se( &s );
        /* skip i_offset_for_top_to_bottom_field */
        bs_read_se( &s );
        /* read i_num_ref_frames_in_poc_cycle */
        i_cycle = bs_read_ue( &s );
        if( i_cycle > 256 ) i_cycle = 256;
        while( i_cycle > 0 )
        {
            /* skip i_offset_for_ref_frame */
            bs_read_se(&s );
            i_cycle--;
        }
    }
    /* i_num_ref_frames */
    bs_read_ue( &s );
    /* b_gaps_in_frame_num_value_allowed */
    bs_skip( &s, 1 );

    /* Read size */
    p_dec->fmt_out.video.i_width  = 16 * ( bs_read_ue( &s ) + 1 );
    p_dec->fmt_out.video.i_height = 16 * ( bs_read_ue( &s ) + 1 );

    /* b_frame_mbs_only */
    p_sys->b_frame_mbs_only = bs_read( &s, 1 );
    p_dec->fmt_out.video.i_height *=  ( 2 - p_sys->b_frame_mbs_only );
    if( p_sys->b_frame_mbs_only == 0 )
    {
        bs_skip( &s, 1 );
    }
    /* b_direct8x8_inference */
    bs_skip( &s, 1 );

    /* crop */
    i_tmp = bs_read( &s, 1 );
    if( i_tmp )
    {
        /* left */
        bs_read_ue( &s );
        /* right */
        bs_read_ue( &s );
        /* top */
        bs_read_ue( &s );
        /* bottom */
        bs_read_ue( &s );
    }

    /* vui */
    i_tmp = bs_read( &s, 1 );
    if( i_tmp )
    {
        /* read the aspect ratio part if any */
        i_tmp = bs_read( &s, 1 );
        if( i_tmp )
        {
            static const struct { int w, h; } sar[17] =
            {
                { 0,   0 }, { 1,   1 }, { 12, 11 }, { 10, 11 },
                { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 },
                { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 },
                { 64, 33 }, { 160,99 }, {  4,  3 }, {  3,  2 },
                {  2,  1 },
            };
            int i_sar = bs_read( &s, 8 );
            int w, h;

            if( i_sar < 17 )
            {
                w = sar[i_sar].w;
                h = sar[i_sar].h;
            }
            else if( i_sar == 255 )
            {
                w = bs_read( &s, 16 );
                h = bs_read( &s, 16 );
            }
            else
            {
                w = 0;
                h = 0;
            }

            if( w != 0 && h != 0 )
            {
                p_dec->fmt_out.video.i_sar_num = w;
                p_dec->fmt_out.video.i_sar_den = h;
            }
            else
            {
                p_dec->fmt_out.video.i_sar_num = 1;
                p_dec->fmt_out.video.i_sar_den = 1;
            }
        }

        /* overscan */
        i_tmp = bs_read( &s, 1 );
        if ( i_tmp )
            bs_read( &s, 1 );

        /* video signal type */
        i_tmp = bs_read( &s, 1 );
        if( i_tmp )
        {
            bs_read( &s, 4 );
            /* colour desc */
            bs_read( &s, 1 );
            if ( i_tmp )
                bs_read( &s, 24 );
        }

        /* chroma loc info */
        i_tmp = bs_read( &s, 1 );
        if( i_tmp )
        {
            bs_read_ue( &s );
            bs_read_ue( &s );
        }

        /* timing info */
        p_sys->b_timing_info_present_flag = bs_read( &s, 1 );
        if( p_sys->b_timing_info_present_flag )
        {
            p_sys->i_num_units_in_tick = bs_read( &s, 32 );
            p_sys->i_time_scale = bs_read( &s, 32 );
            p_sys->b_fixed_frame_rate = bs_read( &s, 1 );
        }

        /* Nal hrd & VC1 hrd parameters */
        p_sys->b_cpb_dpb_delays_present_flag = false;
        for ( int i=0; i<2; i++ )
        {
            i_tmp = bs_read( &s, 1 );
            if( i_tmp )
            {
                p_sys->b_cpb_dpb_delays_present_flag = true;
                uint32_t count = bs_read_ue( &s ) + 1;
                bs_read( &s, 4 );
                bs_read( &s, 4 );
                for( uint32_t i=0; i<count; i++ )
                {
                    bs_read_ue( &s );
                    bs_read_ue( &s );
                    bs_read( &s, 1 );
                }
                bs_read( &s, 5 );
                p_sys->i_cpb_removal_delay_length_minus1 = bs_read( &s, 5 );
                p_sys->i_dpb_output_delay_length_minus1 = bs_read( &s, 5 );
                bs_read( &s, 5 );
            }
        }

        if( p_sys->b_cpb_dpb_delays_present_flag )
            bs_read( &s, 1 );

        /* pic struct info */
        p_sys->b_pic_struct_present_flag = bs_read( &s, 1 );

        /* + unparsed remains */
    }

    free( pb_dec );

    /* We have a new SPS */
    if( !p_sys->b_sps )
        msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", i_sps_id );
    p_sys->b_sps = true;

    if( p_sys->pp_sps[i_sps_id] )
        block_Release( p_sys->pp_sps[i_sps_id] );
    p_sys->pp_sps[i_sps_id] = p_frag;
}
int bd_clpi_ep_map_Parse( bd_clpi_ep_map_t *p_ep_map,
                          bs_t *s, const int i_ep_map_start )
{
    p_ep_map->i_pid = bs_read( s, 16 );
    bs_skip( s, 10 );
    p_ep_map->i_type = bs_read( s, 4 );

    const int i_coarse = bs_read( s, 16 );
    const int i_fine = bs_read( s, 18 );
    const uint32_t i_coarse_start = bs_read( s, 32 );

    p_ep_map->i_ep = i_fine;
    p_ep_map->p_ep = (bd_clpi_ep_t *)calloc( i_fine, sizeof(*p_ep_map->p_ep) );			// sunqueen modify
    if( !p_ep_map->p_ep )
        return VLC_EGENERIC;

    bs_t cs = *s;
    bs_skip( &cs, 8*(i_ep_map_start + i_coarse_start) - bs_pos( s ) );

    const uint32_t i_fine_start = bs_read( &cs, 32 );

    for( int i = 0; i < i_coarse; i++ )
    {
        const int      i_fine_id = bs_read( &cs, 18 );
        const int      i_pts = bs_read( &cs, 14 );
        const uint32_t i_packet = bs_read( &cs, 32 );

        for( int j = i_fine_id; j < p_ep_map->i_ep; j++ )
        {
            p_ep_map->p_ep[j].i_pts = (int64_t)(i_pts & ~1) << 19;
            p_ep_map->p_ep[j].i_packet = i_packet & ~( (1 << 17) - 1 );
        }
    }

    bs_t fs = *s;
    bs_skip( &fs, 8*(i_ep_map_start + i_coarse_start + i_fine_start) - bs_pos( s ) );
    for( int i = 0; i < i_fine; i++ )
    {
        const bool b_angle_point = bs_read( &fs, 1 );
        bs_skip( &fs, 3 );  /* I end position offset */
        const int i_pts = bs_read( &fs, 11 );
        const int i_packet = bs_read( &fs, 17 );

        p_ep_map->p_ep[i].b_angle_point = b_angle_point;
        p_ep_map->p_ep[i].i_pts |= i_pts << 9;
        p_ep_map->p_ep[i].i_packet |= i_packet;
    }
    return VLC_SUCCESS;
}
Beispiel #9
0
static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,
                        int i_nal_ref_idc, int i_nal_type, const block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint8_t *pb_dec;
    int i_dec;
    int i_slice_type;
    slice_t slice;
    bs_t s;

    /* do not convert the whole frame */
    CreateDecodedNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5],
                     __MIN( p_frag->i_buffer - 5, 60 ) );
    bs_init( &s, pb_dec, i_dec );

    /* first_mb_in_slice */
    /* int i_first_mb = */ bs_read_ue( &s );

    /* slice_type */
    switch( (i_slice_type = bs_read_ue( &s )) )
    {
    case 0: case 5:
        slice.i_frame_type = BLOCK_FLAG_TYPE_P;
        break;
    case 1: case 6:
        slice.i_frame_type = BLOCK_FLAG_TYPE_B;
        break;
    case 2: case 7:
        slice.i_frame_type = BLOCK_FLAG_TYPE_I;
        break;
    case 3: case 8: /* SP */
        slice.i_frame_type = BLOCK_FLAG_TYPE_P;
        break;
    case 4: case 9:
        slice.i_frame_type = BLOCK_FLAG_TYPE_I;
        break;
    default:
        slice.i_frame_type = 0;
        break;
    }

    /* */
    slice.i_nal_type = i_nal_type;
    slice.i_nal_ref_idc = i_nal_ref_idc;

    slice.i_pic_parameter_set_id = bs_read_ue( &s );
    slice.i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 );

    slice.i_field_pic_flag = 0;
    slice.i_bottom_field_flag = -1;
    if( !p_sys->b_frame_mbs_only )
    {
        /* field_pic_flag */
        slice.i_field_pic_flag = bs_read( &s, 1 );
        if( slice.i_field_pic_flag )
            slice.i_bottom_field_flag = bs_read( &s, 1 );
    }

    slice.i_idr_pic_id = p_sys->slice.i_idr_pic_id;
    if( slice.i_nal_type == NAL_SLICE_IDR )
        slice.i_idr_pic_id = bs_read_ue( &s );

    slice.i_pic_order_cnt_lsb = -1;
    slice.i_delta_pic_order_cnt_bottom = -1;
    slice.i_delta_pic_order_cnt0 = 0;
    slice.i_delta_pic_order_cnt1 = 0;
    if( p_sys->i_pic_order_cnt_type == 0 )
    {
        slice.i_pic_order_cnt_lsb = bs_read( &s, p_sys->i_log2_max_pic_order_cnt_lsb + 4 );
        if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag )
            slice.i_delta_pic_order_cnt_bottom = bs_read_se( &s );
    }
    else if( (p_sys->i_pic_order_cnt_type == 1) &&
             (!p_sys->i_delta_pic_order_always_zero_flag) )
    {
        slice.i_delta_pic_order_cnt0 = bs_read_se( &s );
        if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag )
            slice.i_delta_pic_order_cnt1 = bs_read_se( &s );
    }
    free( pb_dec );

    /* Detection of the first VCL NAL unit of a primary coded picture
     * (cf. 7.4.1.2.4) */
    bool b_pic = false;
    if( slice.i_frame_num != p_sys->slice.i_frame_num ||
        slice.i_pic_parameter_set_id != p_sys->slice.i_pic_parameter_set_id ||
        slice.i_field_pic_flag != p_sys->slice.i_field_pic_flag ||
        slice.i_nal_ref_idc != p_sys->slice.i_nal_ref_idc )
        b_pic = true;
    if( (slice.i_bottom_field_flag != -1) &&
        (p_sys->slice.i_bottom_field_flag != -1) &&
        (slice.i_bottom_field_flag != p_sys->slice.i_bottom_field_flag) )
        b_pic = true;
    if( p_sys->i_pic_order_cnt_type == 0 &&
        ( slice.i_pic_order_cnt_lsb != p_sys->slice.i_pic_order_cnt_lsb ||
          slice.i_delta_pic_order_cnt_bottom != p_sys->slice.i_delta_pic_order_cnt_bottom ) )
        b_pic = true;
    else if( p_sys->i_pic_order_cnt_type == 1 &&
             ( slice.i_delta_pic_order_cnt0 != p_sys->slice.i_delta_pic_order_cnt0 ||
               slice.i_delta_pic_order_cnt1 != p_sys->slice.i_delta_pic_order_cnt1 ) )
        b_pic = true;
    if( ( slice.i_nal_type == NAL_SLICE_IDR || p_sys->slice.i_nal_type == NAL_SLICE_IDR ) &&
        ( slice.i_nal_type != p_sys->slice.i_nal_type || slice.i_idr_pic_id != p_sys->slice.i_idr_pic_id ) )
            b_pic = true;

    /* */
    *pb_new_picture = b_pic;
    *p_slice = slice;
}
int bd_clpi_Parse( bd_clpi_t *p_clpi, bs_t *s, int i_id )
{
    const int i_start = bs_pos( s ) / 8;

    /* */
    if( bs_read( s, 32 ) != 0x48444D56 )
        return VLC_EGENERIC;
    const uint32_t i_version = bs_read( s, 32 );
    if( i_version != 0x30313030 && i_version != 0x30323030 )
        return VLC_EGENERIC;

    /* */
    const uint32_t i_sequence_start = bs_read( s, 32 );
    const uint32_t i_program_start = bs_read( s, 32 );
    const uint32_t i_cpi_start = bs_read( s, 32 );
    bs_skip( s, 32 );   /* mark start */
    bs_skip( s, 32 );   /* extension start */

    /* */
    p_clpi->i_id = i_id;

    /* Read sequence */
    bs_t ss = *s;
    bs_skip( &ss, 8 * ( i_start + i_sequence_start ) - bs_pos( s ) );
    bs_skip( &ss, 32 ); /* Length */
    bs_skip( &ss, 8 );
    bs_skip( &ss, 8 );  /* ATC sequence count (MUST be 1 ?) */
    bs_skip( &ss, 32 ); /* ATC start (MUST be 0) */
    const int i_stc = bs_read( &ss, 8 );
    bs_skip( &ss, 8 );  /* STC ID offset (MUST be 0 ? */

    p_clpi->p_stc = (bd_clpi_stc_t *)calloc( i_stc, sizeof(*p_clpi->p_stc) );			// sunqueen modify
    for( p_clpi->i_stc = 0; p_clpi->i_stc < i_stc; p_clpi->i_stc++ )
    {
        if( !p_clpi->p_stc )
            break;
        bd_clpi_stc_Parse( &p_clpi->p_stc[p_clpi->i_stc], &ss );
    }

    /* Program */
    bs_t ps = *s;
    bs_skip( &ps, 8 * ( i_start + i_program_start ) - bs_pos( s ) );
    bs_skip( &ps, 32 ); /* Length */
    bs_skip( &ps, 8 );
    bs_skip( &ps, 8 );  /* Program count (MUST be 1 ?) */
    bs_skip( &ps, 32 ); /* Program sequence start (MUST be 0) */
    p_clpi->i_pmt_pid = bs_read( &ps, 16 );
    const int i_stream = bs_read( &ps, 8 );
    bs_skip( &ps, 8 );  /* Group count (MUST be 1 ?) */

    p_clpi->p_stream = (bd_clpi_stream_t *)calloc( i_stream, sizeof(*p_clpi->p_stream) );			// sunqueen modify
    for( p_clpi->i_stream = 0; p_clpi->i_stream < i_stream; p_clpi->i_stream++ )
    {
        if( !p_clpi->p_stream )
            break;
        bd_clpi_stream_Parse( &p_clpi->p_stream[p_clpi->i_stream], &ps );
    }

    /* Read CPI */
    bs_t cs = *s;
    bs_skip( &cs, 8 * ( i_start + i_cpi_start ) - bs_pos( s ) );

    const uint32_t i_cpi_length = bs_read( &cs, 32 );
    if( i_cpi_length > 0 )
    {
        bs_skip( &cs, 12 );
        bs_skip( &cs, 4 );  /* Type (MUST be 1) */

        /* EPMap */
        const int i_epmap_start = bs_pos( &cs ) / 8;
        bs_skip( &cs, 8 );
        const int i_ep_map = bs_read( &cs, 8 );

        p_clpi->p_ep_map = (bd_clpi_ep_map_t *)calloc( i_ep_map, sizeof(*p_clpi->p_ep_map) );			// sunqueen modify
        for( p_clpi->i_ep_map = 0; p_clpi->i_ep_map < i_ep_map; p_clpi->i_ep_map++ )
        {
            if( !p_clpi->p_ep_map )
                break;

            if( bd_clpi_ep_map_Parse( &p_clpi->p_ep_map[p_clpi->i_ep_map],
                                      &cs, i_epmap_start ) )
                break;
        }
    }
    else
    {
        p_clpi->i_ep_map = 0;
        p_clpi->p_ep_map = NULL;
    }
    return VLC_SUCCESS;
}
Beispiel #11
0
Datei: vc1.c Projekt: Kafay/vlc
/* ParseIDU: parse an Independent Decoding Unit */
static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_pic;
    const idu_type_t idu = p_frag->p_buffer[3];

    *pb_used_ts = false;
    if( !p_sys->b_sequence_header && idu != IDU_TYPE_SEQUENCE_HEADER )
    {
        msg_Warn( p_dec, "waiting for sequence header" );
        block_Release( p_frag );
        return NULL;
    }
    if( p_sys->b_sequence_header && !p_sys->b_entry_point && idu != IDU_TYPE_ENTRY_POINT )
    {
        msg_Warn( p_dec, "waiting for entry point" );
        block_Release( p_frag );
        return NULL;
    }
    /* TODO we do not gather ENTRY_POINT and SEQUENCE_DATA user data
     * But It should not be a problem for decoder */

    /* Do we have completed a frame */
    p_pic = NULL;
    if( p_sys->b_frame &&
        idu != IDU_TYPE_FRAME_USER_DATA &&
        idu != IDU_TYPE_FIELD && idu != IDU_TYPE_FIELD_USER_DATA &&
        idu != IDU_TYPE_SLICE && idu != IDU_TYPE_SLICE_USER_DATA &&
        idu != IDU_TYPE_END_OF_SEQUENCE )
    {
        /* Prepend SH and EP on I */
        if( p_sys->p_frame->i_flags & BLOCK_FLAG_TYPE_I )
        {
            block_t *p_list = block_Duplicate( p_sys->sh.p_sh );
            block_ChainAppend( &p_list, block_Duplicate( p_sys->ep.p_ep ) );
            block_ChainAppend( &p_list, p_sys->p_frame );

            p_list->i_flags = p_sys->p_frame->i_flags;

            p_sys->p_frame = p_list;
        }

        /* */
        p_pic = block_ChainGather( p_sys->p_frame );
        p_pic->i_dts = p_sys->i_frame_dts;
        p_pic->i_pts = p_sys->i_frame_pts;

        /* */
        if( p_pic->i_dts > VLC_TS_INVALID )
            p_sys->i_interpolated_dts = p_pic->i_dts;

        /* We can interpolate dts/pts only if we have a frame rate */
        if( p_dec->fmt_out.video.i_frame_rate != 0 && p_dec->fmt_out.video.i_frame_rate_base != 0 )
        {
            if( p_sys->i_interpolated_dts > VLC_TS_INVALID )
                p_sys->i_interpolated_dts += INT64_C(1000000) *
                                             p_dec->fmt_out.video.i_frame_rate_base /
                                             p_dec->fmt_out.video.i_frame_rate;

            //msg_Dbg( p_dec, "-------------- XXX0 dts=%"PRId64" pts=%"PRId64" interpolated=%"PRId64,
            //         p_pic->i_dts, p_pic->i_pts, p_sys->i_interpolated_dts );
            if( p_pic->i_dts <= VLC_TS_INVALID )
                p_pic->i_dts = p_sys->i_interpolated_dts;

            if( p_pic->i_pts <= VLC_TS_INVALID )
            {
                if( !p_sys->sh.b_has_bframe || (p_pic->i_flags & BLOCK_FLAG_TYPE_B ) )
                    p_pic->i_pts = p_pic->i_dts;
                /* TODO compute pts for other case */
            }
        }

        //msg_Dbg( p_dec, "-------------- dts=%"PRId64" pts=%"PRId64, p_pic->i_dts, p_pic->i_pts );

        /* Reset context */
        p_sys->b_frame = false;
        p_sys->i_frame_dts = VLC_TS_INVALID;
        p_sys->i_frame_pts = VLC_TS_INVALID;
        p_sys->p_frame = NULL;
        p_sys->pp_last = &p_sys->p_frame;
    }

    /*  */
    if( p_sys->i_frame_dts <= VLC_TS_INVALID && p_sys->i_frame_pts <= VLC_TS_INVALID )
    {
        p_sys->i_frame_dts = p_frag->i_dts;
        p_sys->i_frame_pts = p_frag->i_pts;
        *pb_used_ts = true;
    }

    /* We will add back SH and EP on I frames */
    block_t *p_release = NULL;
    if( idu != IDU_TYPE_SEQUENCE_HEADER && idu != IDU_TYPE_ENTRY_POINT )
        block_ChainLastAppend( &p_sys->pp_last, p_frag );
    else
        p_release = p_frag;

    /* Parse IDU */
    if( idu == IDU_TYPE_SEQUENCE_HEADER )
    {
        es_format_t *p_es = &p_dec->fmt_out;
        bs_t s;
        int i_profile;
        uint8_t ridu[32];
        int     i_ridu = sizeof(ridu);

        /* */
        if( p_sys->sh.p_sh )
            block_Release( p_sys->sh.p_sh );
        p_sys->sh.p_sh = block_Duplicate( p_frag );

        /* Extract the raw IDU */
        DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );

        /* Auto detect VC-1_SPMP_PESpacket_PayloadFormatHeader (SMPTE RP 227) for simple/main profile
         * TODO find a test case and valid it */
        if( i_ridu > 4 && (ridu[0]&0x80) == 0 ) /* for advanced profile, the first bit is 1 */
        {
            video_format_t *p_v = &p_dec->fmt_in.video;
            const size_t i_potential_width  = GetWBE( &ridu[0] );
            const size_t i_potential_height = GetWBE( &ridu[2] );

            if( i_potential_width >= 2  && i_potential_width <= 8192 &&
                i_potential_height >= 2 && i_potential_height <= 8192 )
            {
                if( ( p_v->i_width <= 0 && p_v->i_height <= 0  ) ||
                    ( p_v->i_width  == i_potential_width &&  p_v->i_height == i_potential_height ) )
                {
                    static const uint8_t startcode[4] = { 0x00, 0x00, 0x01, IDU_TYPE_SEQUENCE_HEADER };
                    p_es->video.i_width  = i_potential_width;
                    p_es->video.i_height = i_potential_height;

                    /* Remove it */
                    p_frag->p_buffer += 4;
                    p_frag->i_buffer -= 4;
                    memcpy( p_frag->p_buffer, startcode, sizeof(startcode) );
                }
            }
        }

        /* Parse it */
        bs_init( &s, ridu, i_ridu );
        i_profile = bs_read( &s, 2 );
        if( i_profile == 3 )
        {
            const int i_level = bs_read( &s, 3 );

            /* Advanced profile */
            p_sys->sh.b_advanced_profile = true;
            p_sys->sh.b_range_reduction = false;
            p_sys->sh.b_has_bframe = true;

            bs_skip( &s, 2+3+5+1 ); // chroma format + frame rate Q + bit rate Q + postprocflag

            p_es->video.i_width  = 2*bs_read( &s, 12 )+2;
            p_es->video.i_height = 2*bs_read( &s, 12 )+2;

            if( !p_sys->b_sequence_header )
                msg_Dbg( p_dec, "found sequence header for advanced profile level L%d resolution %dx%d",
                         i_level, p_es->video.i_width, p_es->video.i_height);

            bs_skip( &s, 1 );// pulldown
            p_sys->sh.b_interlaced = bs_read( &s, 1 );
            bs_skip( &s, 1 );// frame counter
            p_sys->sh.b_frame_interpolation = bs_read( &s, 1 );
            bs_skip( &s, 1 );       // Reserved
            bs_skip( &s, 1 );       // Psf

            if( bs_read( &s, 1 ) )  /* Display extension */
            {
                const int i_display_width  = bs_read( &s, 14 )+1;
                const int i_display_height = bs_read( &s, 14 )+1;

                p_es->video.i_aspect = VOUT_ASPECT_FACTOR * i_display_width / i_display_height;

                if( !p_sys->b_sequence_header )
                    msg_Dbg( p_dec, "display size %dx%d", i_display_width, i_display_height );

                if( bs_read( &s, 1 ) )  /* Pixel aspect ratio (PAR/SAR) */
                {
                    static const int p_ar[16][2] = {
                        { 0, 0}, { 1, 1}, {12,11}, {10,11}, {16,11}, {40,33},
                        {24,11}, {20,11}, {32,11}, {80,33}, {18,11}, {15,11},
                        {64,33}, {160,99},{ 0, 0}, { 0, 0}
                    };
                    int i_ar = bs_read( &s, 4 );
                    unsigned i_ar_w, i_ar_h;

                    if( i_ar == 15 )
                    {
                        i_ar_w = bs_read( &s, 8 );
                        i_ar_h = bs_read( &s, 8 );
                    }
                    else
                    {
                        i_ar_w = p_ar[i_ar][0];
                        i_ar_h = p_ar[i_ar][1];
                    }
                    vlc_ureduce( &i_ar_w, &i_ar_h, i_ar_w, i_ar_h, 0 );
                    if( !p_sys->b_sequence_header )
                        msg_Dbg( p_dec, "aspect ratio %d:%d", i_ar_w, i_ar_h );
                }
            }
            if( bs_read( &s, 1 ) )  /* Frame rate */
            {
                int i_fps_num = 0;
                int i_fps_den = 0;
                if( bs_read( &s, 1 ) )
                {
                    i_fps_num = bs_read( &s, 16 )+1;
                    i_fps_den = 32;
                }
                else
                {
                    const int i_nr = bs_read( &s, 8 );
                    const int i_dn = bs_read( &s, 4 );

                    switch( i_nr )
                    {
                    case 1: i_fps_num = 24000; break;
                    case 2: i_fps_num = 25000; break;
                    case 3: i_fps_num = 30000; break;
                    case 4: i_fps_num = 50000; break;
                    case 5: i_fps_num = 60000; break;
                    case 6: i_fps_num = 48000; break;
                    case 7: i_fps_num = 72000; break;
                    }
                    switch( i_dn )
                    {
                    case 1: i_fps_den = 1000; break;
                    case 2: i_fps_den = 1001; break;
                    }
                }
                if( i_fps_num != 0 && i_fps_den != 0 )
                    vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base, i_fps_num, i_fps_den, 0 );

                if( !p_sys->b_sequence_header )
                    msg_Dbg( p_dec, "frame rate %d/%d", p_es->video.i_frame_rate, p_es->video.i_frame_rate_base );
            }
        }
        else
        {
            /* Simple and main profile */
            p_sys->sh.b_advanced_profile = false;
            p_sys->sh.b_interlaced = false;

            if( !p_sys->b_sequence_header )
                msg_Dbg( p_dec, "found sequence header for %s profile", i_profile == 0 ? "simple" : "main" );

            bs_skip( &s, 2+3+5+1+1+     // reserved + frame rate Q + bit rate Q + loop filter + reserved
                         1+1+1+1+2+     // multiresolution + reserved + fast uv mc + extended mv + dquant
                         1+1+1+1 );     // variable size transform + reserved + overlap + sync marker
            p_sys->sh.b_range_reduction = bs_read( &s, 1 );
            if( bs_read( &s, 3 ) > 0 )
                p_sys->sh.b_has_bframe = true;
            else
                p_sys->sh.b_has_bframe = false;
            bs_skip( &s, 2 );           // quantizer

            p_sys->sh.b_frame_interpolation = bs_read( &s, 1 );
        }
        p_sys->b_sequence_header = true;
        BuildExtraData( p_dec );
    }
    else if( idu == IDU_TYPE_ENTRY_POINT )
    {
        if( p_sys->ep.p_ep )
            block_Release( p_sys->ep.p_ep );
        p_sys->ep.p_ep = block_Duplicate( p_frag );

        if( !p_sys->b_entry_point )
            msg_Dbg( p_dec, "found entry point" );

        p_sys->b_entry_point = true;
        BuildExtraData( p_dec );
    }
    else if( idu == IDU_TYPE_FRAME )
    {
        bs_t s;
        uint8_t ridu[8];
        int     i_ridu = sizeof(ridu);

        /* Extract the raw IDU */
        DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );

        /* Parse it + interpolate pts/dts if possible */
        bs_init( &s, ridu, i_ridu );

        if( p_sys->sh.b_advanced_profile )
        {
            int i_fcm = 0;

            if( p_sys->sh.b_interlaced )
            {
                if( bs_read( &s, 1 ) )
                {
                    if( bs_read( &s, 1 ) )
                        i_fcm = 1;  /* interlaced field */
                    else
                        i_fcm = 2;  /* interlaced frame */
                }
            }

            if( i_fcm == 1 ) /*interlaced field */
            {
                /* XXX for mixed I/P we should check reference usage before marking them I (too much work) */
                switch( bs_read( &s, 3 ) )
                {
                case 0: /* II */
                case 1: /* IP */
                case 2: /* PI */
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
                    break;
                case 3: /* PP */
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
                    break;
                case 4: /* BB */
                case 5: /* BBi */
                case 6: /* BiB */
                case 7: /* BiBi */
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
                    break;
                }
            }
            else
            {
                if( !bs_read( &s, 1 ) )
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
                else if( !bs_read( &s, 1 ) )
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
                else if( !bs_read( &s, 1 ) )
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
                else if( !bs_read( &s, 1 ) )
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;   /* Bi */
                else
                    p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;   /* P Skip */
            }
        }
        else
        {
            if( p_sys->sh.b_frame_interpolation )
                bs_skip( &s, 1 );   // interpolate
            bs_skip( &s, 2 );       // frame count
            if( p_sys->sh.b_range_reduction )
                bs_skip( &s, 1 );   // range reduction

            if( bs_read( &s, 1 ) )
                p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
            else if( !p_sys->sh.b_has_bframe || bs_read( &s, 1 ) )
                p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
            else
                p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
        }
        p_sys->b_frame = true;
    }

    if( p_release )
        block_Release( p_release );
    return p_pic;
}
bool 
h264MediaStream::ParseSqs(const buf_share_ptr SqsNode)
{
	assert(SqsNode);

	if (StreamSps == NULL)
		StreamSps = new h264_sps_t;
	uint8_t *pb_dec = NULL;
	int     i_dec = 0;
	bs_t s;
	int i_sps_id;
	i_dec = SqsNode->GetSizeValue(); 
	int nal_hrd_parameters_present_flag, vcl_hrd_parameters_present_flag;
	pb_dec = const_cast<uint8_t *>(SqsNode->GetBuffer());

	//转化00 00 03为00 00


	uint8_t *p_nal = new uint8_t[i_dec];
	int pcount = 0;
	for (int tmp = 1; tmp < i_dec ; tmp++)
	{
		if (tmp < i_dec - 3 && *(pb_dec + tmp) == 0x00 && 
			*(pb_dec + tmp + 1) == 0x00 && *(pb_dec + tmp + 2) == 0x03)
		{
			p_nal[pcount++] = 0x00;
			p_nal[pcount++] = 0x00;
			//printf("count = %d %2X\n",tmp, *(p_nal + tmp));
			tmp += 2;
			continue;
		}
		p_nal[pcount++] = *(pb_dec + tmp);
	}
	pb_dec = p_nal;

	//以下内容根据H264协议解读,属于直接复制粘贴代码 同parseslice

	bs_init( &s, pb_dec, i_dec );
	// profile(8)
	StreamSps->profile_idc = bs_read( &s, 8);

	/* constraint_set012, reserver(5), level(8) */
	bs_skip( &s, 1+1+1 + 5 + 8 );
	/* sps id */
	i_sps_id = bs_read_ue( &s );
	if( i_sps_id >= 32/*SPS_MAX*/ )
	{
		printf("invalid SPS (sps_id=%d)", i_sps_id );
		delete pb_dec;
		return false;
	}

	StreamSps->scaling_matrix_present = 0;
	if(StreamSps->profile_idc >= 100)		//high profile
	{ 
		if(bs_read_ue(&s) == 3)			//chroma_format_idc
			bs_read(&s, 1);				//residual_color_transform_flag
		bs_read_ue(&s);					//bit_depth_luma_minus8
		bs_read_ue(&s);					//bit_depth_chroma_minus8
		StreamSps->transform_bypass = bs_read(&s, 1);
		bs_skip(&s, 1); //decode_scaling_matrices(h, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8);
	}

	/* Skip i_log2_max_frame_num */
	StreamSps->log2_max_frame_num = bs_read_ue( &s );
	if( StreamSps->log2_max_frame_num > 12)
		StreamSps->log2_max_frame_num = 12;
	/* Read poc_type */
	StreamSps->poc_type/*->i_pic_order_cnt_type*/ = bs_read_ue( &s );
	if( StreamSps->poc_type == 0 )
	{
		/* skip i_log2_max_poc_lsb */
		StreamSps->log2_max_poc_lsb/*->i_log2_max_pic_order_cnt_lsb*/ = bs_read_ue( &s );
		if( StreamSps->log2_max_poc_lsb > 12 )
			StreamSps->log2_max_poc_lsb = 12;
	}
	else if( StreamSps->poc_type/*p_sys->i_pic_order_cnt_type*/ == 1 )
	{
		int i_cycle;
		/* skip b_delta_pic_order_always_zero */
		StreamSps->delta_pic_order_always_zero_flag/*->i_delta_pic_order_always_zero_flag*/ = bs_read( &s, 1 );
		/* skip i_offset_for_non_ref_pic */
		bs_read_se( &s );
		/* skip i_offset_for_top_to_bottom_field */
		bs_read_se( &s );
		/* read i_num_ref_frames_in_poc_cycle */
		i_cycle = bs_read_ue( &s );
		if( i_cycle > 256 ) i_cycle = 256;
		while( i_cycle > 0 )
		{
			/* skip i_offset_for_ref_frame */
			bs_read_se(&s );
			i_cycle--;
		}
	}
	/* i_num_ref_frames */
	bs_read_ue( &s );
	/* b_gaps_in_frame_num_value_allowed */
	bs_skip( &s, 1 );

	/* Read size */
	StreamSps->mb_width/*->fmt_out.video.i_width*/  = 16 * ( bs_read_ue( &s ) + 1 );
	StreamSps->mb_height/*fmt_out.video.i_height*/ = 16 * ( bs_read_ue( &s ) + 1 );

	/* b_frame_mbs_only */
	StreamSps->frame_mbs_only_flag/*->b_frame_mbs_only*/ = bs_read( &s, 1 );
	if( StreamSps->frame_mbs_only_flag == 0 )
	{
		bs_skip( &s, 1 );
	}
	/* b_direct8x8_inference */
	bs_skip( &s, 1 );

	/* crop */
	StreamSps->crop = bs_read( &s, 1 );
	if( StreamSps->crop )
	{
		/* left */
		bs_read_ue( &s );
		/* right */
		bs_read_ue( &s );
		/* top */
		bs_read_ue( &s );
		/* bottom */
		bs_read_ue( &s );
	}

	/* vui */
	StreamSps->vui_parameters_present_flag = bs_read( &s, 1 );
	if( StreamSps->vui_parameters_present_flag )
	{
		int aspect_ratio_info_present_flag = bs_read( &s, 1 );
		if( aspect_ratio_info_present_flag )
		{
			static const struct { int num, den; } sar[17] =
			{
				{ 0,   0 }, { 1,   1 }, { 12, 11 }, { 10, 11 },
				{ 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 },
				{ 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 },
				{ 64, 33 }, { 160,99 }, {  4,  3 }, {  3,  2 },
				{  2,  1 },
			};

			int i_sar = bs_read( &s, 8 );

			if( i_sar < 17 )
			{
				StreamSps->sar.num = sar[i_sar].num;
				StreamSps->sar.den = sar[i_sar].den;
			}
			else if( i_sar == 255 )
			{
				StreamSps->sar.num = bs_read( &s, 16 );
				StreamSps->sar.den = bs_read( &s, 16 );
			}
			else
			{
				StreamSps->sar.num = 0;
				StreamSps->sar.den = 0;
			}

			//if( den != 0 )
			//	p_dec->fmt_out.video.i_aspect = (int64_t)VOUT_ASPECT_FACTOR *
			//	( num * p_dec->fmt_out.video.i_width ) /
			//	( den * p_dec->fmt_out.video.i_height);
			//else
			//	p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR;
		}
		else
		{
			StreamSps->sar.num = 0;
			StreamSps->sar.den = 0;
		}

		if(bs_read(&s, 1))		/* overscan_info_present_flag */
		{
			bs_read(&s, 1);     /* overscan_appropriate_flag */
		}

		if(bs_read(&s, 1))		/* video_signal_type_present_flag */
		{      
			bs_read(&s, 3);		/* video_format */
			bs_read(&s, 1);     /* video_full_range_flag */

			if(bs_read(&s, 1))  /* colour_description_present_flag */
			{
				bs_read(&s, 8);	/* colour_primaries */
				bs_read(&s, 8); /* transfer_characteristics */
				bs_read(&s, 8); /* matrix_coefficients */
			}
		}

		if(bs_read(&s, 1))		/* chroma_location_info_present_flag */
		{
			bs_read_ue(&s);		/* chroma_sample_location_type_top_field */
			bs_read_ue(&s);		/* chroma_sample_location_type_bottom_field */
		}

		StreamSps->timing_info_present_flag = bs_read(&s, 1);
		if(StreamSps->timing_info_present_flag)
		{
			StreamSps->num_units_in_tick = bs_read(&s, 32);
			StreamSps->time_scale = bs_read(&s, 32);
			StreamSps->fixed_frame_rate_flag = bs_read(&s, 1);
		}

		nal_hrd_parameters_present_flag = bs_read(&s, 1);
		if(nal_hrd_parameters_present_flag)
			h264_decode_hrd_parameters(s, StreamSps);
		vcl_hrd_parameters_present_flag = bs_read(&s, 1);
		if(vcl_hrd_parameters_present_flag)
			h264_decode_hrd_parameters(s, StreamSps);
		if(nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
			bs_read(&s, 1);     /* low_delay_hrd_flag */
		bs_read(&s, 1);         /* pic_struct_present_flag */

		StreamSps->bitstream_restriction_flag = bs_read(&s, 1);
		if(StreamSps->bitstream_restriction_flag)
		{
			unsigned int num_reorder_frames;
			bs_read(&s, 1);     /* motion_vectors_over_pic_boundaries_flag */
			bs_read_ue(&s); /* max_bytes_per_pic_denom */
			bs_read_ue(&s); /* max_bits_per_mb_denom */
			bs_read_ue(&s); /* log2_max_mv_length_horizontal */
			bs_read_ue(&s); /* log2_max_mv_length_vertical */
			num_reorder_frames= bs_read_ue(&s);
			bs_read_ue(&s); /*max_dec_frame_buffering*/

			if(num_reorder_frames > 16 /*max_dec_frame_buffering || max_dec_frame_buffering > 16*/){
				printf("illegal num_reorder_frames %d\n", num_reorder_frames);
				delete pb_dec;
				return true;
			}

			StreamSps->num_reorder_frames= num_reorder_frames;
		}
	}
	delete pb_dec;
	return true;
}
void 
h264MediaStream::ParseSlice(uint8_t* p_nal,  int n_nal_size, int i_nal_type)
{	
	
	if(CurSlice == NULL)
		CurSlice = new h264_slice_t;
	//转化00 00 03为00 00
	int icount = 0;
	uint8_t p_slice[64] = {0};
	int parcount = (n_nal_size>64?64:n_nal_size);
	for (int t = 0; t < parcount; t++)
	{
		if (t < parcount-2 && p_nal[t] == 0x00 && p_nal[t + 1] == 0x00 && p_nal[t + 2] == 0x03)
		{
			p_slice[icount++] = 0x00;
			p_slice[icount++] = 0x00;
			t += 2;
			continue;
		}
		p_slice[icount++] = p_nal[t];
	}
	
	


	bs_t s;
	bs_init(&s, p_slice, icount);

	bs_read_ue( &s );	// first_mb_in_slice
	CurSlice->i_slice_type = bs_read_ue( &s );	// slice type

	int i_pic_parameter_set_id = bs_read_ue( &s );
	CurSlice->i_frame_num = bs_read( &s, StreamSps->log2_max_frame_num + 4 );

	int i_field_pic_flag = 0;
	int i_bottom_field_flag = -1;
	if( !StreamSps->frame_mbs_only_flag)
	{
		/* field_pic_flag */
		i_field_pic_flag = bs_read( &s, 1 );
		if( i_field_pic_flag )
			i_bottom_field_flag = bs_read( &s, 1 );
	}

	int i_idr_pic_id;
	if( i_nal_type == 5/*NAL_SLICE_IDR*/ )
		i_idr_pic_id = bs_read_ue( &s );

	int i_delta_pic_order_cnt_bottom = -1;
	int i_delta_pic_order_cnt0 = 0;
	int i_delta_pic_order_cnt1 = 0;

	CurSlice->i_pic_order_cnt_lsb = 0;

	if( StreamSps->poc_type == 0 )
	{
		CurSlice->i_pic_order_cnt_lsb = bs_read( &s, StreamSps->log2_max_poc_lsb + 4 );
		//if( g_pic_order_present_flag && !i_field_pic_flag )
		//	i_delta_pic_order_cnt_bottom = bs_read_se( &s );
	}
	else if( (StreamSps->poc_type == 1) &&
		(!StreamSps->delta_pic_order_always_zero_flag) )
	{
		i_delta_pic_order_cnt0 = bs_read_se( &s );
		//if( g_pic_order_present_flag && !i_field_pic_flag )
		//	i_delta_pic_order_cnt1 = bs_read_se( &s );
	}
}
Beispiel #14
0
static bool h264_parse_sequence_parameter_set_rbsp( bs_t *p_bs,
                                                    h264_sequence_parameter_set_t *p_sps )
{
    int i_tmp;

    int i_profile_idc = bs_read( p_bs, 8 );
    p_sps->i_profile = i_profile_idc;
    p_sps->i_profile_compatibility = bs_read( p_bs, 8 );
    p_sps->i_level = bs_read( p_bs, 8 );
    /* sps id */
    p_sps->i_id = bs_read_ue( p_bs );
    if( p_sps->i_id >= H264_SPS_MAX )
        return false;

    if( i_profile_idc == PROFILE_H264_HIGH ||
        i_profile_idc == PROFILE_H264_HIGH_10 ||
        i_profile_idc == PROFILE_H264_HIGH_422 ||
        i_profile_idc == PROFILE_H264_HIGH_444 || /* Old one, no longer on spec */
        i_profile_idc == PROFILE_H264_HIGH_444_PREDICTIVE ||
        i_profile_idc == PROFILE_H264_CAVLC_INTRA ||
        i_profile_idc == PROFILE_H264_SVC_BASELINE ||
        i_profile_idc == PROFILE_H264_SVC_HIGH ||
        i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_HIGH ||
        i_profile_idc == PROFILE_H264_MVC_STEREO_HIGH ||
        i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_DEPTH_HIGH ||
        i_profile_idc == PROFILE_H264_MVC_ENHANCED_MULTIVIEW_DEPTH_HIGH ||
        i_profile_idc == PROFILE_H264_MFC_HIGH )
    {
        /* chroma_format_idc */
        const int i_chroma_format_idc = bs_read_ue( p_bs );
        if( i_chroma_format_idc == 3 )
            bs_skip( p_bs, 1 ); /* separate_colour_plane_flag */
        /* bit_depth_luma_minus8 */
        bs_read_ue( p_bs );
        /* bit_depth_chroma_minus8 */
        bs_read_ue( p_bs );
        /* qpprime_y_zero_transform_bypass_flag */
        bs_skip( p_bs, 1 );
        /* seq_scaling_matrix_present_flag */
        i_tmp = bs_read( p_bs, 1 );
        if( i_tmp )
        {
            for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ )
            {
                /* seq_scaling_list_present_flag[i] */
                i_tmp = bs_read( p_bs, 1 );
                if( !i_tmp )
                    continue;
                const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64;
                /* scaling_list (...) */
                int i_lastscale = 8;
                int i_nextscale = 8;
                for( int j = 0; j < i_size_of_scaling_list; j++ )
                {
                    if( i_nextscale != 0 )
                    {
                        /* delta_scale */
                        i_tmp = bs_read_se( p_bs );
                        i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256;
                        /* useDefaultScalingMatrixFlag = ... */
                    }
                    /* scalinglist[j] */
                    i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale;
                }
            }
        }
    }

    /* Skip i_log2_max_frame_num */
    p_sps->i_log2_max_frame_num = bs_read_ue( p_bs );
    if( p_sps->i_log2_max_frame_num > 12)
        p_sps->i_log2_max_frame_num = 12;
    /* Read poc_type */
    p_sps->i_pic_order_cnt_type = bs_read_ue( p_bs );
    if( p_sps->i_pic_order_cnt_type == 0 )
    {
        /* skip i_log2_max_poc_lsb */
        p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( p_bs );
        if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 )
            p_sps->i_log2_max_pic_order_cnt_lsb = 12;
    }
    else if( p_sps->i_pic_order_cnt_type == 1 )
    {
        int i_cycle;
        /* skip b_delta_pic_order_always_zero */
        p_sps->i_delta_pic_order_always_zero_flag = bs_read( p_bs, 1 );
        /* skip i_offset_for_non_ref_pic */
        bs_read_se( p_bs );
        /* skip i_offset_for_top_to_bottom_field */
        bs_read_se( p_bs );
        /* read i_num_ref_frames_in_poc_cycle */
        i_cycle = bs_read_ue( p_bs );
        if( i_cycle > 256 ) i_cycle = 256;
        while( i_cycle > 0 )
        {
            /* skip i_offset_for_ref_frame */
            bs_read_se(p_bs );
            i_cycle--;
        }
    }
    /* i_num_ref_frames */
    bs_read_ue( p_bs );
    /* b_gaps_in_frame_num_value_allowed */
    bs_skip( p_bs, 1 );

    /* Read size */
    p_sps->pic_width_in_mbs_minus1 = bs_read_ue( p_bs );
    p_sps->pic_height_in_map_units_minus1 = bs_read_ue( p_bs );

    /* b_frame_mbs_only */
    p_sps->frame_mbs_only_flag = bs_read( p_bs, 1 );
    if( !p_sps->frame_mbs_only_flag )
        bs_skip( p_bs, 1 );

    /* b_direct8x8_inference */
    bs_skip( p_bs, 1 );

    /* crop */
    if( bs_read1( p_bs ) ) /* frame_cropping_flag */
    {
        p_sps->frame_crop.left_offset = bs_read_ue( p_bs );
        p_sps->frame_crop.right_offset = bs_read_ue( p_bs );
        p_sps->frame_crop.right_offset = bs_read_ue( p_bs );
        p_sps->frame_crop.bottom_offset = bs_read_ue( p_bs );
    }

    /* vui */
    i_tmp = bs_read( p_bs, 1 );
    if( i_tmp )
    {
        p_sps->vui.b_valid = true;
        /* read the aspect ratio part if any */
        i_tmp = bs_read( p_bs, 1 );
        if( i_tmp )
        {
            static const struct { int w, h; } sar[17] =
            {
                { 0,   0 }, { 1,   1 }, { 12, 11 }, { 10, 11 },
                { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 },
                { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 },
                { 64, 33 }, { 160,99 }, {  4,  3 }, {  3,  2 },
                {  2,  1 },
            };
            int i_sar = bs_read( p_bs, 8 );
            int w, h;

            if( i_sar < 17 )
            {
                w = sar[i_sar].w;
                h = sar[i_sar].h;
            }
            else if( i_sar == 255 )
            {
                w = bs_read( p_bs, 16 );
                h = bs_read( p_bs, 16 );
            }
            else
            {
                w = 0;
                h = 0;
            }

            if( w != 0 && h != 0 )
            {
                p_sps->vui.i_sar_num = w;
                p_sps->vui.i_sar_den = h;
            }
            else
            {
                p_sps->vui.i_sar_num = 1;
                p_sps->vui.i_sar_den = 1;
            }
        }

        /* overscan */
        i_tmp = bs_read( p_bs, 1 );
        if ( i_tmp )
            bs_read( p_bs, 1 );

        /* video signal type */
        i_tmp = bs_read( p_bs, 1 );
        if( i_tmp )
        {
            bs_read( p_bs, 4 );
            /* colour desc */
            bs_read( p_bs, 1 );
            if ( i_tmp )
                bs_read( p_bs, 24 );
        }

        /* chroma loc info */
        i_tmp = bs_read( p_bs, 1 );
        if( i_tmp )
        {
            bs_read_ue( p_bs );
            bs_read_ue( p_bs );
        }

        /* timing info */
        p_sps->vui.b_timing_info_present_flag = bs_read( p_bs, 1 );
        if( p_sps->vui.b_timing_info_present_flag )
        {
            p_sps->vui.i_num_units_in_tick = bs_read( p_bs, 32 );
            p_sps->vui.i_time_scale = bs_read( p_bs, 32 );
            p_sps->vui.b_fixed_frame_rate = bs_read( p_bs, 1 );
        }

        /* Nal hrd & VC1 hrd parameters */
        p_sps->vui.b_cpb_dpb_delays_present_flag = false;
        for ( int i=0; i<2; i++ )
        {
            i_tmp = bs_read( p_bs, 1 );
            if( i_tmp )
            {
                p_sps->vui.b_cpb_dpb_delays_present_flag = true;
                uint32_t count = bs_read_ue( p_bs ) + 1;
                bs_read( p_bs, 4 );
                bs_read( p_bs, 4 );
                for( uint32_t i=0; i<count; i++ )
                {
                    bs_read_ue( p_bs );
                    bs_read_ue( p_bs );
                    bs_read( p_bs, 1 );
                }
                bs_read( p_bs, 5 );
                p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( p_bs, 5 );
                p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( p_bs, 5 );
                bs_read( p_bs, 5 );
            }
        }

        if( p_sps->vui.b_cpb_dpb_delays_present_flag )
            bs_read( p_bs, 1 );

        /* pic struct info */
        p_sps->vui.b_pic_struct_present_flag = bs_read( p_bs, 1 );

        /* + unparsed remains */
    }

    return true;
}