summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/vdpau/gstvdpmpegdecoder.c43
-rw-r--r--sys/vdpau/gstvdpmpegdecoder.h4
2 files changed, 47 insertions, 0 deletions
diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c
index 9b4aa99d..d2ec7fd1 100644
--- a/sys/vdpau/gstvdpmpegdecoder.c
+++ b/sys/vdpau/gstvdpmpegdecoder.c
@@ -148,6 +148,18 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec)
buffer = gst_adapter_take_buffer (mpeg_dec->adapter,
gst_adapter_available (mpeg_dec->adapter));
+ /* if the frame is a B_FRAME we store it for future decoding */
+ if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) {
+ mpeg_dec->b_buffer = buffer;
+ memcpy (&mpeg_dec->b_vdp_info, &mpeg_dec->vdp_info,
+ sizeof (VdpPictureInfoMPEG1Or2));
+
+ /* unset forward_reference since next frame must be an I_FRAME */
+ mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE;
+
+ return GST_FLOW_OK;
+ }
+
outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420,
dec->width, dec->height);
surface = outbuf->surface;
@@ -179,6 +191,35 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec)
return GST_FLOW_ERROR;
}
+ /* if we have stored away a B_FRAME we can now decode it */
+ if (mpeg_dec->b_buffer) {
+ GstVdpVideoBuffer *b_outbuf;
+
+ b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420,
+ dec->width, dec->height);
+ mpeg_dec->b_vdp_info.backward_reference = surface;
+ vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
+ vbit[0].bitstream = GST_BUFFER_DATA (mpeg_dec->b_buffer);
+ vbit[0].bitstream_bytes = GST_BUFFER_SIZE (mpeg_dec->b_buffer);
+
+ status = device->vdp_decoder_render (mpeg_dec->decoder, b_outbuf->surface,
+ (VdpPictureInfo *) & mpeg_dec->b_vdp_info, 1, vbit);
+ gst_buffer_unref (mpeg_dec->b_buffer);
+ mpeg_dec->b_buffer = NULL;
+
+ if (status != VDP_STATUS_OK) {
+ GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ,
+ ("Could not decode B_FRAME"),
+ ("Error returned from vdpau was: %s",
+ device->vdp_get_error_string (status)));
+
+ if (mpeg_dec->b_vdp_info.forward_reference != VDP_INVALID_HANDLE)
+ gst_buffer_unref (mpeg_dec->f_buffer);
+ }
+
+ gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), b_outbuf);
+ }
+
gst_buffer_ref (GST_BUFFER (outbuf));
ret = gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec),
@@ -441,6 +482,8 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec,
mpeg_dec->decoder = VDP_INVALID_HANDLE;
gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info);
+ mpeg_dec->b_buffer = NULL;
+
mpeg_dec->adapter = gst_adapter_new ();
gst_pad_set_chain_function (dec->sink, gst_vdp_mpeg_decoder_chain);
diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h
index 3ec8244d..3761cff6 100644
--- a/sys/vdpau/gstvdpmpegdecoder.h
+++ b/sys/vdpau/gstvdpmpegdecoder.h
@@ -46,6 +46,10 @@ struct _GstVdpMpegDecoder
VdpDecoder decoder;
VdpPictureInfoMPEG1Or2 vdp_info;
GstBuffer *f_buffer;
+
+ /* holds B_FRAMES */
+ GstBuffer *b_buffer;
+ VdpPictureInfoMPEG1Or2 b_vdp_info;
GstAdapter *adapter;
};