diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libvdpau/vdpau_vc1.c | 174 |
1 files changed, 152 insertions, 22 deletions
diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 1ee76d2c4..85f28e76d 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -21,7 +21,7 @@ * */ -#define LOG +//#define LOG #define LOG_MODULE "vdpau_vc1" @@ -62,6 +62,8 @@ typedef struct { VdpPictureInfoVC1 vdp_infos; + int hrd_param_flag; + int hrd_num_leaky_buckets; int type; } picture_t; @@ -168,6 +170,7 @@ static void init_sequence( sequence_t *sequence ) sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; sequence->ratio = 0; sequence->video_step = 0; + sequence->picture.hrd_param_flag = 0; reset_sequence( sequence ); } @@ -194,22 +197,97 @@ static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) +static void update_metadata( vdpau_vc1_decoder_t *this_gen ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + + if ( !sequence->have_header ) { + sequence->have_header = 1; + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); + _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" ); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this_gen->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = sequence->coded_width; + data.height = sequence->coded_height; + data.aspect = sequence->ratio; + xine_event_send( this_gen->stream, &event ); + } +} + + + static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { lprintf( "sequence_header_advanced\n" ); + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + + if ( len < 5 ) + return; + + sequence->profile = VDP_DECODER_PROFILE_VC1_ADVANCED; + lprintf("VDP_DECODER_PROFILE_VC1_ADVANCED\n"); + int off = 15; + sequence->picture.vdp_infos.postprocflag = get_bits(buf,off++,1); + sequence->coded_width = (get_bits(buf,off,12)+1)<<1; + off += 12; + sequence->coded_height = (get_bits(buf,off,12)+1)<<1; + off += 12; + ++off; + sequence->picture.vdp_infos.interlace = get_bits(buf,off++,1); + sequence->picture.vdp_infos.tfcntrflag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.finterpflag = get_bits(buf,off++,1); + ++off; + sequence->picture.vdp_infos.psf = get_bits(buf,off++,1); + sequence->picture.vdp_infos.maxbframes = 7; + if ( get_bits(buf,off++,1) ) { + int w, h, ar=0; + w = get_bits(buf,off,14)+1; + off += 14; + h = get_bits(buf,off,14)+1; + off += 14; + if ( get_bits(buf,off++,1) ) { + ar = get_bits(buf,off,4); + off += 4; + } + if ( ar==15 ) { + w = get_bits(buf,off,8); + off += 8; + h = get_bits(buf,off,8); + off += 8; + } + if ( get_bits(buf,off++,1) ) { + if ( get_bits(buf,off++,1) ) + off += 16; + else + off += 12; + } + if ( get_bits(buf,off++,1) ) + off += 24; + } + sequence->picture.hrd_param_flag = get_bits(buf,off++,1); + if ( sequence->picture.hrd_param_flag ) + sequence->picture.hrd_num_leaky_buckets = get_bits(buf,off,5); + + update_metadata( this_gen ); } static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { + lprintf( "sequence_header\n" ); sequence_t *sequence = (sequence_t*)&this_gen->sequence; if ( len < 4 ) return; - lprintf( "sequence_header\n" ); - switch ( get_bits(buf,0,2) ) { case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; lprintf("VDP_DECODER_PROFILE_VC1_SIMPLE\n"); break; case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("VDP_DECODER_PROFILE_VC1_MAIN\n"); break; @@ -230,23 +308,54 @@ static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int le sequence->picture.vdp_infos.quantizer = get_bits(buf,28,2); sequence->picture.vdp_infos.finterpflag = get_bits(buf,30,1); - if ( !sequence->have_header ) { - sequence->have_header = 1; - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); - _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" ); - xine_event_t event; - xine_format_change_data_t data; - event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; - event.stream = this_gen->stream; - event.data = &data; - event.data_length = sizeof(data); - data.width = sequence->coded_width; - data.height = sequence->coded_height; - data.aspect = sequence->ratio; - xine_event_send( this_gen->stream, &event ); + update_metadata( this_gen ); +} + + + +static void entry_point( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + lprintf( "entry_point\n" ); + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + int off=2; + + sequence->picture.vdp_infos.panscan_flag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.refdist_flag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.loopfilter = get_bits(buf,off++,1); + sequence->picture.vdp_infos.fastuvmc = get_bits(buf,off++,1); + sequence->picture.vdp_infos.extended_mv = get_bits(buf,off++,1); + sequence->picture.vdp_infos.dquant = get_bits(buf,off,2); + off += 2; + sequence->picture.vdp_infos.vstransform = get_bits(buf,off++,1); + sequence->picture.vdp_infos.overlap = get_bits(buf,off++,1); + sequence->picture.vdp_infos.quantizer = get_bits(buf,off,2); + off += 2; + + if ( sequence->picture.hrd_param_flag ) { + int i; + for ( i=0; i<sequence->picture.hrd_num_leaky_buckets; ++i ) + off += 8; + } + + if ( get_bits(buf,off++,1) ) { + sequence->coded_width = (get_bits(buf,off,12)+1)<<1; + off += 12; + sequence->coded_height = (get_bits(buf,off,12)+1)<<1; + off += 12; + } + + if ( sequence->picture.vdp_infos.extended_mv ) + sequence->picture.vdp_infos.extended_dmv = get_bits(buf,off++,1); + + sequence->picture.vdp_infos.range_mapy_flag = get_bits(buf,off++,1); + if ( sequence->picture.vdp_infos.range_mapy_flag ) { + sequence->picture.vdp_infos.range_mapy = get_bits(buf,off,3); + off += 3; + } + sequence->picture.vdp_infos.range_mapuv_flag = get_bits(buf,off++,1); + if ( sequence->picture.vdp_infos.range_mapuv_flag ) { + sequence->picture.vdp_infos.range_mapuv = get_bits(buf,off,3); + off += 3; } } @@ -291,6 +400,27 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len +static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + int off=0; + + while ( off < (len-4) ) { + uint8_t *buffer = buf+off; + if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { + switch ( buffer[3] ) { + case sequence_header_code: sequence_header( this_gen, buf+off+4, len-off-4 ); break; + case entry_point_code: entry_point( this_gen, buf+off+4, len-off-4 ); break; + } + } + ++off; + } + if ( !sequence->have_header ) + sequence_header( this_gen, buf, len ); +} + + + static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) { sequence_t *seq = (sequence_t*)&vd->sequence; @@ -338,7 +468,7 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) picture_header( vd, seq->buf, seq->bufpos ); VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, pic->type, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; @@ -467,7 +597,7 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf seq->coded_height = bih->biHeight; lprintf( "width=%d height=%d\n", bih->biWidth, bih->biHeight ); if ( buf->size > bs ) { - sequence_header( this, buf->content+bs, buf->size-bs ); + parse_header( this, buf->content+bs, buf->size-bs ); } int i; for ( i=0; i<buf->size; ++i ) |