summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libvdpau/dpb.c11
-rw-r--r--src/libvdpau/dpb.h2
-rw-r--r--src/libvdpau/h264_parser.c5
-rw-r--r--src/libvdpau/vdpau_h264.c38
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;
}