diff options
Diffstat (limited to 'src/video_dec/libvdpau/vdpau_h264.c')
-rw-r--r-- | src/video_dec/libvdpau/vdpau_h264.c | 188 |
1 files changed, 92 insertions, 96 deletions
diff --git a/src/video_dec/libvdpau/vdpau_h264.c b/src/video_dec/libvdpau/vdpau_h264.c index 2f675dfbb..c9ef68ebf 100644 --- a/src/video_dec/libvdpau/vdpau_h264.c +++ b/src/video_dec/libvdpau/vdpau_h264.c @@ -35,6 +35,9 @@ #include "accel_vdpau.h" #include "h264_parser.h" #include "dpb.h" +#include "cpb.h" + +//#define DEBUG_H264 #define VIDEOBUFSIZE 128*1024 @@ -56,7 +59,7 @@ typedef struct vdpau_h264_decoder_s { double ratio; /* the width to height ratio */ - struct nal_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ + struct h264_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ uint8_t wait_for_bottom_field; struct decoded_picture *last_ref_pic; uint32_t last_top_field_order_cnt; @@ -73,9 +76,7 @@ typedef struct vdpau_h264_decoder_s { xine_t *xine; - int64_t curr_pts; - int64_t next_pts; - + struct coded_picture *completed_pic; vo_frame_t *last_img; vo_frame_t *dangling_img; @@ -97,7 +98,7 @@ static void vdpau_h264_flush (video_decoder_t *this_gen); * xine video plugin functions *************************************************************************/ - +#ifdef DEBUG_H264 static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) { printf("C: slice_count: %d\n", pic->slice_count); @@ -168,14 +169,15 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames));*/ } +#endif static void set_ratio(video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; this->ratio = (double)this->width / (double)this->height; - if(this->nal_parser->current_nal->sps->vui_parameters.aspect_ration_info_present_flag) { - switch(this->nal_parser->current_nal->sps->vui_parameters.aspect_ratio_idc) { + if(this->completed_pic->sps_nal->sps.vui_parameters.aspect_ration_info_present_flag) { + switch(this->completed_pic->sps_nal->sps.vui_parameters.aspect_ratio_idc) { case ASPECT_1_1: this->ratio = 1 * this->ratio; break; @@ -226,8 +228,8 @@ static void set_ratio(video_decoder_t *this_gen) break; case ASPECT_EXTENDED_SAR: this->ratio *= - (double)this->nal_parser->current_nal->sps->vui_parameters.sar_width/ - (double)this->nal_parser->current_nal->sps->vui_parameters.sar_height; + (double)this->completed_pic->sps_nal->sps.vui_parameters.sar_width/ + (double)this->completed_pic->sps_nal->sps.vui_parameters.sar_height; break; } } @@ -237,15 +239,15 @@ static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slic { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; - struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; - struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; - struct slice_header *slc = this->nal_parser->current_nal->slc; + struct pic_parameter_set_rbsp *pps = &this->completed_pic->pps_nal->pps; + struct seq_parameter_set_rbsp *sps = &this->completed_pic->sps_nal->sps; + struct slice_header *slc = &this->completed_pic->slc_nal->slc; pic->slice_count = slice_count; - pic->field_order_cnt[0] = this->nal_parser->current_nal->top_field_order_cnt; - pic->field_order_cnt[1] = this->nal_parser->current_nal->bottom_field_order_cnt; + pic->field_order_cnt[0] = this->completed_pic->top_field_order_cnt; + pic->field_order_cnt[1] = this->completed_pic->bottom_field_order_cnt; pic->is_reference = - (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; + (this->completed_pic->flag_mask & REFERENCE) ? VDP_TRUE : VDP_FALSE; pic->frame_num = slc->frame_num; pic->field_pic_flag = slc->field_pic_flag; pic->bottom_field_flag = slc->bottom_field_flag; @@ -286,12 +288,9 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; vo_frame_t *img; - this->curr_pts = this->next_pts; - this->next_pts = 0; - if(this->width == 0) { - this->width = this->nal_parser->current_nal->sps->pic_width; - this->height = this->nal_parser->current_nal->sps->pic_height; + this->width = this->completed_pic->sps_nal->sps.pic_width; + this->height = this->completed_pic->sps_nal->sps.pic_height; } set_ratio(this_gen); @@ -312,7 +311,7 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) data.aspect = this->ratio; xine_event_send( this->stream, &event ); - switch(this->nal_parser->current_nal->sps->profile_idc) { + switch(this->completed_pic->sps_nal->sps.profile_idc) { case 100: this->profile = VDP_DECODER_PROFILE_H264_HIGH; break; @@ -330,8 +329,8 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) // Level 4.1 limits: int ref_frames = 0; - if(this->nal_parser->current_nal->sps->num_ref_frames) { - ref_frames = this->nal_parser->current_nal->sps->num_ref_frames; + if(this->completed_pic->sps_nal->sps.num_ref_frames) { + ref_frames = this->completed_pic->sps_nal->sps.num_ref_frames; } else { uint32_t round_width = (this->width + 15) & ~15; uint32_t round_height = (this->height + 15) & ~15; @@ -343,7 +342,8 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) ref_frames = 16; } - printf("Allocate %d reference frames\n", ref_frames); + xprintf(this->xine, XINE_VERBOSITY_LOG, "Allocate %d reference frames\n", + ref_frames); /* get the vdpau context from vo */ //(this->stream->video_out->open) (this->stream->video_out, this->stream); img = this->stream->video_out->get_frame (this->stream->video_out, @@ -352,10 +352,11 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); img->duration = this->video_step; - img->pts = this->curr_pts; + img->pts = this->completed_pic->pts; if (this->dangling_img) { - fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); + xprintf(this->xine, XINE_VERBOSITY_LOG, + "broken stream: current img wasn't processed -- freeing it\n!"); this->dangling_img->free(this->dangling_img); } this->dangling_img = img; @@ -386,23 +387,24 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; vo_frame_t *img = this->last_img; - if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { + // FIXME: what is if this is the second field of a field coded + // picture? - should we keep the first field in dpb? + if(this->completed_pic->flag_mask & IDR_PIC) { dpb_flush(&(this->nal_parser->dpb)); + this->last_ref_pic = NULL; } VdpPictureInfoH264 pic; fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); - //printf("next decode: %d, %d\n", pic.field_order_cnt[0], pic.field_order_cnt[1]); - if(!this->decoder_started && !pic.is_reference) return 0; this->decoder_started = 1; - struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; - struct slice_header *slc = this->nal_parser->current_nal->slc; + struct seq_parameter_set_rbsp *sps = &this->completed_pic->sps_nal->sps; + struct slice_header *slc = &this->completed_pic->slc_nal->slc; if(sps->vui_parameters_present_flag && sps->vui_parameters.timing_info_present_flag && @@ -410,28 +412,26 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->video_step = 2*90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); } - /* flush the DPB if this frame was an IDR */ - //printf("is_idr: %d\n", this->nal_parser->is_idr); - this->nal_parser->is_idr = 0; - /* go and decode a frame */ +#ifdef DEBUG_H264 + dump_pictureinfo_h264(&pic); - //dump_pictureinfo_h264(&pic); - - /*int i; - printf("Decode data: \n"); + int i; + printf("E: Bytes used: %d\n", vdp_buffer->bitstream_bytes); + printf("E: Decode data: \nE:"); for(i = 0; i < ((vdp_buffer->bitstream_bytes < 20) ? vdp_buffer->bitstream_bytes : 20); i++) { printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); if((i+1) % 10 == 0) - printf("\n"); + printf("\nE:"); } printf("\n...\n"); for(i = vdp_buffer->bitstream_bytes - 20; i < vdp_buffer->bitstream_bytes; i++) { printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); if((i+1) % 10 == 0) - printf("\n"); - }*/ - + printf("\nE:"); + } + printf("\nE: ---------------------------------------------------------------\n"); +#endif if(img == NULL) { img = this->stream->video_out->get_frame (this->stream->video_out, @@ -441,17 +441,23 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->vdpau_accel = (vdpau_accel_t*)img->accel_data; img->duration = this->video_step; - img->pts = this->curr_pts; + img->pts = this->completed_pic->pts; if (this->dangling_img) { - fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); + xprintf(this->xine, XINE_VERBOSITY_LOG, + "broken stream: current img wasn't processed -- freeing it\n!"); this->dangling_img->free(this->dangling_img); } this->dangling_img = img; + } else { + if (img->pts == 0) { + img->pts = this->completed_pic->pts; + } } if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { - printf("VDPAU was preempted. Reinitialise the decoder.\n"); + xprintf(this->xine, XINE_VERBOSITY_LOG, + "VDPAU was preempted. Reinitialise the decoder.\n"); this->decoder = VDP_INVALID_HANDLE; vdpau_h264_reset(this_gen); this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; @@ -460,20 +466,17 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v VdpVideoSurface surface = this->vdpau_accel->surface; - //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer->bitstream_bytes, this->curr_pts); + //xprintf(this->xine, XINE_VERBOSITY_DEBUG, + // "Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer->bitstream_bytes, this->completed_pic->pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, vdp_buffer); - /* only free the actual data, as the start seq is only - * locally allocated anyway. */ + /* free the image data */ if(((uint8_t*)vdp_buffer->bitstream) != NULL) { free((uint8_t*)vdp_buffer->bitstream); } - this->curr_pts = this->next_pts; - this->next_pts = 0; - - process_mmc_operations(this->nal_parser); + process_mmc_operations(this->nal_parser, this->completed_pic); if(status != VDP_STATUS_OK) { @@ -481,19 +484,21 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if (this->dangling_img) this->dangling_img->free(this->dangling_img); img = this->last_img = this->dangling_img = NULL; + free_coded_picture(this->completed_pic); + this->completed_pic = NULL; } else { img->bad_frame = 0; - if((sps->vui_parameters_present_flag && + img->progressive_frame = 0; + + if(/*(sps->vui_parameters_present_flag && sps->vui_parameters.pic_struct_present_flag && - !this->nal_parser->current_nal->interlaced) || + !(this->completed_pic->flag_mask & INTERLACED)) ||*/ (!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag)) img->progressive_frame = 1; - else - img->progressive_frame = 0; - if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + if(!img->progressive_frame && this->completed_pic->repeat_pic) img->repeat_first_field = 1; //else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) // img->duration *= this->nal_parser->current_nal->repeat_pic; @@ -517,7 +522,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { - decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + decoded_pic = init_decoded_picture(this->completed_pic, surface, img); + this->completed_pic = NULL; this->last_ref_pic = decoded_pic; decoded_pic->used_for_reference = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); @@ -526,8 +532,9 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(this->last_ref_pic) { decoded_pic = this->last_ref_pic; //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); - decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; - this->last_ref_pic->bottom_is_reference = 1; + + dpb_add_coded_picture(this->last_ref_pic, this->completed_pic); + this->completed_pic = NULL; } } } @@ -536,26 +543,21 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { if(!decoded_pic) { - decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + decoded_pic = init_decoded_picture(this->completed_pic, surface, img); + this->completed_pic = NULL; //decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); this->dangling_img = NULL; - - if(decoded_pic->nal->slc->bottom_field_flag) - decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; } decoded_pic->delayed_output = 1; - if(this->wait_for_bottom_field && slc->bottom_field_flag) - decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; - this->last_img = img = NULL; /* now retrieve the next output frame */ if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 0)) != NULL) { - decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); - //printf("draw pts: %lld\n", decoded_pic->img->pts); + + decoded_pic->img->top_field_first = dp_top_field_first(decoded_pic); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } @@ -564,7 +566,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v } else if(slc->field_pic_flag && !slc->bottom_field_flag) { // don't draw yet, second field is missing. - this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; + //this->last_top_field_order_cnt = this->nal_parser->completed_pic->top_field_order_cnt; this->wait_for_bottom_field = 1; this->last_img = img; } @@ -627,33 +629,36 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, parse_codec_private(this->nal_parser, codec_private, codec_private_len); } } else if (buf->decoder_info[1] == BUF_SPECIAL_PALETTE) { - printf("SPECIAL PALETTE is not yet handled\n"); + xprintf(this->xine, XINE_VERBOSITY_LOG, + "SPECIAL PALETTE is not yet handled\n"); } else - printf("UNKNOWN SPECIAL HEADER\n"); + xprintf(this->xine, XINE_VERBOSITY_LOG, + "UNKNOWN SPECIAL HEADER\n"); } else { /* parse the first nal packages to retrieve profile type */ int len = 0; - uint32_t slice_count; while(len < buf->size && !(this->wait_for_frame_start && !(buf->decoder_flags & BUF_FLAG_FRAME_START))) { this->wait_for_frame_start = 0; len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, - (uint8_t*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); + buf->pts, + (uint8_t*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &this->completed_pic); if(this->decoder == VDP_INVALID_HANDLE && - this->nal_parser->current_nal->sps != NULL && - this->nal_parser->current_nal->sps->pic_width > 0 && - this->nal_parser->current_nal->sps->pic_height > 0) { + this->completed_pic && + this->completed_pic->sps_nal != NULL && + this->completed_pic->sps_nal->sps.pic_width > 0 && + this->completed_pic->sps_nal->sps.pic_height > 0) { vdpau_decoder_init(this_gen); } if(this->decoder != VDP_INVALID_HANDLE && vdp_buffer.bitstream_bytes > 0 && - this->nal_parser->current_nal->slc != NULL && - this->nal_parser->current_nal->pps != NULL) { - vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); + this->completed_pic->slc_nal != NULL && + this->completed_pic->pps_nal != NULL) { + vdpau_decoder_render(this_gen, &vdp_buffer, this->completed_pic->slice_cnt); } /* in case the last nal was detected as END_OF_SEQUENCE @@ -662,11 +667,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(this->nal_parser->last_nal_res == 3) vdpau_h264_flush(this_gen); } - - if(buf->pts != 0 && buf->pts != this->next_pts) { - //printf("next pts: %lld\n", buf->pts); - this->next_pts = buf->pts; - } } if(buf->decoder_flags & BUF_FLAG_FRAME_END) @@ -681,11 +681,13 @@ static void vdpau_h264_flush (video_decoder_t *this_gen) { struct decoded_picture *decoded_pic = NULL; while ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 1)) != NULL) { - decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); - printf("FLUSH draw pts: %lld\n", decoded_pic->img->pts); + decoded_pic->img->top_field_first = dp_top_field_first(decoded_pic); + xprintf(this->xine, XINE_VERBOSITY_DEBUG, + "h264 flush, draw pts: %lld\n", decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } + dpb_free_all(&this->nal_parser->dpb); } /* @@ -694,8 +696,6 @@ static void vdpau_h264_flush (video_decoder_t *this_gen) { static void vdpau_h264_reset (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - printf("vdpau_h264_reset\n"); - dpb_free_all( &(this->nal_parser->dpb) ); if (this->decoder != VDP_INVALID_HANDLE) { @@ -708,8 +708,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; this->wait_for_bottom_field = 0; this->video_step = 0; - this->curr_pts = 0; - this->next_pts = 0; this->nal_parser = init_parser(); if(this->codec_private_len > 0) { @@ -736,8 +734,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { static void vdpau_h264_discontinuity (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - this->curr_pts = 0; - this->next_pts = 0; dpb_clear_all_pts(&this->nal_parser->dpb); } @@ -787,7 +783,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_H264_MAIN, 1920, 1080, 16, &decoder ); if ( st!=VDP_STATUS_OK ) { lprintf( "can't create vdpau decoder.\n" ); - return 1; + return NULL; } accel->vdp_decoder_destroy( decoder ); @@ -864,6 +860,6 @@ static const decoder_info_t dec_info_video = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { /* { type, API, "name", version, special_info, init_function } */ - { PLUGIN_VIDEO_DECODER, 19, "vdpau_h264", XINE_VERSION_CODE, &dec_info_video, init_plugin }, + { PLUGIN_VIDEO_DECODER | PLUGIN_MUST_PRELOAD, 19, "vdpau_h264", XINE_VERSION_CODE, &dec_info_video, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |