From d6b7c72aa0a4d2c0d0b119895776e0feba5c85c8 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 12 Jun 2010 10:28:06 +0200 Subject: rewrite vo_frame_t handling for field coded content - fix tff marking - make code easier to read --- src/video_dec/libvdpau/dpb.c | 37 +++++++++- src/video_dec/libvdpau/dpb.h | 18 +---- src/video_dec/libvdpau/vdpau_h264.c | 136 +++++++++++++++++------------------- 3 files changed, 102 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/video_dec/libvdpau/dpb.c b/src/video_dec/libvdpau/dpb.c index aecbf7d77..d37603ba5 100644 --- a/src/video_dec/libvdpau/dpb.c +++ b/src/video_dec/libvdpau/dpb.c @@ -32,10 +32,44 @@ #include "dpb.h" #include "nal.h" +#include "h264_parser.h" + #include "accel_vdpau.h" #include +int dp_top_field_first(struct decoded_picture *decoded_pic) +{ + int top_field_first = 0; + + + if (decoded_pic->coded_pic[1] != NULL) { + if (!decoded_pic->coded_pic[0]->slc_nal->slc.bottom_field_flag && + decoded_pic->coded_pic[1]->slc_nal->slc.bottom_field_flag && + decoded_pic->coded_pic[0]->top_field_order_cnt != + decoded_pic->coded_pic[1]->bottom_field_order_cnt) { + top_field_first = decoded_pic->coded_pic[0]->top_field_order_cnt < decoded_pic->coded_pic[1]->bottom_field_order_cnt; + } else if (decoded_pic->coded_pic[0]->slc_nal->slc.bottom_field_flag && + !decoded_pic->coded_pic[1]->slc_nal->slc.bottom_field_flag && + decoded_pic->coded_pic[0]->top_field_order_cnt != + decoded_pic->coded_pic[1]->bottom_field_order_cnt) { + top_field_first = decoded_pic->coded_pic[0]->top_field_order_cnt > decoded_pic->coded_pic[1]->bottom_field_order_cnt; + } + } + + if (decoded_pic->coded_pic[0]->flag_mask & PIC_STRUCT_PRESENT) { + uint8_t pic_struct = decoded_pic->coded_pic[0]->sei_nal->sei.pic_timing.pic_struct; + if(pic_struct == DISP_TOP_BOTTOM || + pic_struct == DISP_TOP_BOTTOM_TOP) { + top_field_first = 1; + } else if (pic_struct == DISP_FRAME) { + top_field_first = 0; + } + } + + return top_field_first; +} + /** * ---------------------------------------------------------------------------- * decoded picture @@ -44,8 +78,7 @@ void free_decoded_picture(struct decoded_picture *pic); -struct decoded_picture* init_decoded_picture(struct coded_picture *cpic, - VdpVideoSurface surface, vo_frame_t *img) +struct decoded_picture* init_decoded_picture(struct coded_picture *cpic, vo_frame_t *img) { struct decoded_picture *pic = calloc(1, sizeof(struct decoded_picture)); diff --git a/src/video_dec/libvdpau/dpb.h b/src/video_dec/libvdpau/dpb.h index 42d9abd95..472a3e649 100644 --- a/src/video_dec/libvdpau/dpb.h +++ b/src/video_dec/libvdpau/dpb.h @@ -63,7 +63,7 @@ struct dpb* create_dpb(); void release_dpb(struct dpb *dpb); struct decoded_picture* init_decoded_picture(struct coded_picture *cpic, - VdpVideoSurface surface, vo_frame_t *img); + vo_frame_t *img); void release_decoded_picture(struct decoded_picture *pic); void lock_decoded_picture(struct decoded_picture *pic); void decoded_pic_check_reference(struct decoded_picture *pic); @@ -91,20 +91,6 @@ void dpb_clear_all_pts(struct dpb *dpb); int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); -static int dp_top_field_first(struct decoded_picture *decoded_pic) -{ - int top_field_first = 0; - - - if (decoded_pic->coded_pic[0]->slc_nal->slc.field_pic_flag == 0) { - top_field_first = 1; - } else { - if (decoded_pic->coded_pic[0]->slc_nal->slc.delta_pic_order_cnt_bottom == 1) { - top_field_first = 1; - } - } - - return top_field_first; -} +int dp_top_field_first(struct decoded_picture *decoded_pic); #endif /* DPB_H_ */ diff --git a/src/video_dec/libvdpau/vdpau_h264.c b/src/video_dec/libvdpau/vdpau_h264.c index e10e095e7..8f3e956d9 100644 --- a/src/video_dec/libvdpau/vdpau_h264.c +++ b/src/video_dec/libvdpau/vdpau_h264.c @@ -66,8 +66,8 @@ typedef struct vdpau_h264_decoder_s { 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; + + struct decoded_picture *incomplete_pic; uint32_t last_top_field_order_cnt; int have_frame_boundary_marks; @@ -83,7 +83,6 @@ typedef struct vdpau_h264_decoder_s { xine_t *xine; struct coded_picture *completed_pic; - vo_frame_t *last_img; vo_frame_t *dangling_img; uint8_t *codec_private; @@ -369,7 +368,6 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) this->dangling_img->free(this->dangling_img); } this->dangling_img = img; - this->last_img = img; this->vdpau_accel = (vdpau_accel_t*)img->accel_data; @@ -394,15 +392,22 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; - vo_frame_t *img = this->last_img; + vo_frame_t *img = NULL; + + /* if we wait for a second field for this frame, we + * have to render to the same surface again. + */ + if (this->incomplete_pic) { + img = this->incomplete_pic->img; + } // 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); - if(this->last_ref_pic) { - release_decoded_picture(this->last_ref_pic); - this->last_ref_pic = NULL; + if(this->incomplete_pic) { + release_decoded_picture(this->incomplete_pic); + this->incomplete_pic = NULL; } } @@ -445,6 +450,14 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v printf("\nE: ---------------------------------------------------------------\n"); #endif + /* check if we expect a second field, but got a frame */ + if (this->incomplete_pic && img && !slc->field_pic_flag) { + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "H264 warning: Expected a second field, but got a frame\n"); + release_decoded_picture(this->incomplete_pic); + this->incomplete_pic = NULL; + img = NULL; + } + if(img == NULL) { img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, @@ -495,7 +508,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); if (this->dangling_img) this->dangling_img->free(this->dangling_img); - img = this->last_img = this->dangling_img = NULL; + img = NULL; + this->dangling_img = NULL; free_coded_picture(this->completed_pic); this->completed_pic = NULL; } @@ -532,72 +546,55 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->vdpau_accel->color_standard = this->color_standard; 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->completed_pic, surface, img); - this->completed_pic = NULL; - if(this->last_ref_pic) { - release_decoded_picture(this->last_ref_pic); - this->last_ref_pic = NULL; - } - this->last_ref_pic = decoded_pic; - lock_decoded_picture(this->last_ref_pic); - dpb_add_picture(this->nal_parser->dpb, decoded_pic, sps->num_ref_frames); - this->dangling_img = NULL; - } else if(slc->field_pic_flag && this->wait_for_bottom_field) { - if(this->last_ref_pic) { - decoded_pic = this->last_ref_pic; - lock_decoded_picture(decoded_pic); - decoded_pic_add_field(decoded_pic, this->completed_pic); - this->completed_pic = NULL; - } - } - } - if(!slc->field_pic_flag || - (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { + uint8_t draw_frame = 0; + if (!slc->field_pic_flag) { /* frame coded: simply add to dpb */ + decoded_pic = init_decoded_picture(this->completed_pic, img); + this->completed_pic = NULL; + this->dangling_img = NULL; + + dpb_add_picture(this->nal_parser->dpb, decoded_pic, sps->num_ref_frames); - if(!decoded_pic) { - decoded_pic = init_decoded_picture(this->completed_pic, surface, img); + draw_frame = 1; + } else { /* field coded: check for second field */ + if (!this->incomplete_pic) { + decoded_pic = init_decoded_picture(this->completed_pic, img); this->completed_pic = NULL; + this->incomplete_pic = decoded_pic; + lock_decoded_picture(this->incomplete_pic); dpb_add_picture(this->nal_parser->dpb, decoded_pic, sps->num_ref_frames); + + /* don't do a draw yet as the field was incomplete */ + draw_frame = 0; + } else { + decoded_pic = this->incomplete_pic; + lock_decoded_picture(decoded_pic); + + /* picture is complete now */ + release_decoded_picture(this->incomplete_pic); + this->incomplete_pic = NULL; this->dangling_img = NULL; - } - this->last_img = img = NULL; + decoded_pic_add_field(decoded_pic, this->completed_pic); + this->completed_pic = NULL; - /* release the decoded picture, which was headed - * over to the dpb - */ - release_decoded_picture(decoded_pic); - decoded_pic = NULL; + draw_frame = 1; + } + } - /* now retrieve the next output frame */ + release_decoded_picture(decoded_pic); + + /* draw the next frame in display order */ + if (draw_frame) { if ((decoded_pic = dpb_get_next_out_picture(this->nal_parser->dpb, 0)) != NULL) { decoded_pic->img->top_field_first = dp_top_field_first(decoded_pic); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_unmark_picture_delayed(this->nal_parser->dpb, decoded_pic); decoded_pic = NULL; } - - this->wait_for_bottom_field = 0; - - } else if(slc->field_pic_flag && !slc->bottom_field_flag) { - /* don't draw yet, second field is missing. */ - this->wait_for_bottom_field = 1; - this->last_img = img; - if(this->completed_pic) { - free_coded_picture(this->completed_pic); - } - this->completed_pic = NULL; } - - /* release the decoded picture as we won't use it - * in this method anymore - */ - release_decoded_picture(decoded_pic); } return 1; @@ -725,11 +722,11 @@ static void vdpau_h264_flush (video_decoder_t *this_gen) { if(this->dangling_img) this->dangling_img->free(this->dangling_img); - this->last_img = this->dangling_img = NULL; + this->dangling_img = NULL; - if (this->last_ref_pic) { - release_decoded_picture(this->last_ref_pic); - this->last_ref_pic = NULL; + if (this->incomplete_pic) { + release_decoded_picture(this->incomplete_pic); + this->incomplete_pic = NULL; } while ((decoded_pic = dpb_get_next_out_picture(this->nal_parser->dpb, 1)) != NULL) { @@ -764,7 +761,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->nal_parser = init_parser(this->xine); this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; - this->wait_for_bottom_field = 0; this->video_step = 0; if(this->codec_private_len > 0) { @@ -777,9 +773,9 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->wait_for_frame_start = this->have_frame_boundary_marks; } - if (this->last_ref_pic) { - release_decoded_picture(this->last_ref_pic); - this->last_ref_pic = NULL; + if (this->incomplete_pic) { + release_decoded_picture(this->incomplete_pic); + this->incomplete_pic = NULL; } if (this->dangling_img) { @@ -787,8 +783,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->dangling_img = NULL; } - this->last_img = NULL; - this->reset = VO_NEW_SEQUENCE_FLAG; } @@ -809,9 +803,9 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - if (this->last_ref_pic) { - release_decoded_picture(this->last_ref_pic); - this->last_ref_pic = NULL; + if (this->incomplete_pic) { + release_decoded_picture(this->incomplete_pic); + this->incomplete_pic = NULL; } if (this->dangling_img) { -- cgit v1.2.3