diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libvdpau/dpb.c | 11 | ||||
-rw-r--r-- | src/libvdpau/dpb.h | 2 | ||||
-rw-r--r-- | src/libvdpau/h264_parser.c | 5 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 38 |
4 files changed, 39 insertions, 17 deletions
diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 25d9041f2..8ea9fd069 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -18,6 +18,9 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); pic->nal = init_nal_unit(); copy_nal_unit(pic->nal, src_nal); + pic->top_is_reference = pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; + pic->bottom_is_reference = 0; pic->surface = surface; pic->img = img; pic->next = NULL; @@ -237,10 +240,10 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->long_term_frame_idx; else reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->curr_pic_num; - reflist[i].top_is_reference = pic->nal->slc->field_pic_flag - ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; - reflist[i].bottom_is_reference = pic->nal->slc->field_pic_flag - ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1; + reflist[i].top_is_reference = pic->top_is_reference; /*pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1;*/ + reflist[i].bottom_is_reference = pic->bottom_is_reference; /*pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1;*/ reflist[i].field_order_cnt[0] = pic->nal->top_field_order_cnt; reflist[i].field_order_cnt[1] = pic->nal->bottom_field_order_cnt; i++; diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 36892b60c..06f894e44 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -18,6 +18,8 @@ struct decoded_picture { struct nal_unit *nal; uint8_t used_for_reference; + uint8_t top_is_reference; + uint8_t bottom_is_reference; struct decoded_picture *next; }; diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 24a26e86c..65ca7c85b 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -855,6 +855,9 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); + printf("MMC RESET\n"); + parser->pic_order_cnt_lsb = parser->prev_pic_order_cnt_lsb = 0; + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb = 0; } else if (memory_management_control_operation == 6) { // mark current picture as used for long-term ref, @@ -954,7 +957,7 @@ struct nal_parser* init_parser() /* no idea why we do that. inspired by libavcodec, * as we couldn't figure in the specs.... */ - parser->prev_pic_order_cnt_msb = 1 << 16; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_lsb = 1 << 16; return parser; } diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ecf8d21af..e4faf5969 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -68,6 +68,8 @@ typedef struct vdpau_h264_decoder_s { struct nal_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ + uint8_t wait_for_bottom_field; + struct decoded_picture *last_ref_pic; VdpDecoder decoder; @@ -326,13 +328,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(img == NULL) { - printf("Acquire image: "); fflush(stdout); img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - printf("OK\n"); this->vdpau_accel = (vdpau_accel_t*)img->accel_data; } @@ -353,28 +353,41 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, // FIXME: do we really hit all cases here? if(((uint8_t*)vdp_buffer.bitstream) != NULL) { - free(vdp_buffer.bitstream); - printf("Freed vdp_buffer.bitstream\n"); } if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { - printf("DECODING SUCCESS\n"); img->duration = this->video_step; img->pts = buf->pts; img->bad_frame = 0; - img->draw(img, this->stream); - if(pic.is_reference) { - struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); - } else { - img->free(img); + if(!this->wait_for_bottom_field) { + struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + this->last_ref_pic = pic; + dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); + } else { + if(this->last_ref_pic) { + this->last_ref_pic->bottom_is_reference = 1; + } + } + } + + if(!slc->field_pic_flag || + (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { + img->draw(img, this->stream); + this->wait_for_bottom_field = 0; + + if(!pic.is_reference) + img->free(img); + + img = NULL; + } else if(slc->field_pic_flag && !slc->bottom_field_flag) { + // don't draw yet, second field is missing. + this->wait_for_bottom_field = 1; } - img = NULL; } //this->vdpau_accel->vdp_video_surface_destroy(surface); @@ -457,6 +470,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->decoder_initialized = 0; this->nal_parser = init_parser(); this->buf = NULL; + this->wait_for_bottom_field = 0; return &this->video_decoder; } |