mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 21:51:09 +00:00
vdpaumpegdec: handle multiple B_FRAMEs in a row
This commit is contained in:
parent
a168fdc1d3
commit
e0ddcabd7a
3 changed files with 48 additions and 35 deletions
|
@ -131,6 +131,12 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
VdpPictureInfoMPEG1Or2 vdp_info;
|
||||||
|
} GstVdpBFrame;
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec)
|
gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec)
|
||||||
{
|
{
|
||||||
|
@ -150,13 +156,17 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec)
|
||||||
|
|
||||||
/* if the frame is a B_FRAME we store it for future decoding */
|
/* if the frame is a B_FRAME we store it for future decoding */
|
||||||
if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) {
|
if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) {
|
||||||
mpeg_dec->b_buffer = buffer;
|
GstVdpBFrame *b_frame;
|
||||||
memcpy (&mpeg_dec->b_vdp_info, &mpeg_dec->vdp_info,
|
|
||||||
|
b_frame = g_slice_new (GstVdpBFrame);
|
||||||
|
|
||||||
|
b_frame->buffer = buffer;
|
||||||
|
memcpy (&b_frame->vdp_info, &mpeg_dec->vdp_info,
|
||||||
sizeof (VdpPictureInfoMPEG1Or2));
|
sizeof (VdpPictureInfoMPEG1Or2));
|
||||||
|
|
||||||
/* unset forward_reference since next frame must be an I_FRAME */
|
mpeg_dec->b_frames = g_slist_append (mpeg_dec->b_frames, b_frame);
|
||||||
mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE;
|
|
||||||
|
|
||||||
|
gst_buffer_ref (mpeg_dec->f_buffer);
|
||||||
mpeg_dec->vdp_info.slice_count = 0;
|
mpeg_dec->vdp_info.slice_count = 0;
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -188,23 +198,28 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec)
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we have stored away a B_FRAME we can now decode it */
|
/* if we have stored away some B_FRAMEs we can now decode them */
|
||||||
if (mpeg_dec->b_buffer) {
|
if (mpeg_dec->b_frames) {
|
||||||
|
GSList *iter;
|
||||||
|
|
||||||
|
for (iter = mpeg_dec->b_frames; iter; iter = g_slist_next (iter)) {
|
||||||
|
GstVdpBFrame *b_frame;
|
||||||
GstVdpVideoBuffer *b_outbuf;
|
GstVdpVideoBuffer *b_outbuf;
|
||||||
|
|
||||||
|
b_frame = (GstVdpBFrame *) iter->data;
|
||||||
|
|
||||||
b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420,
|
b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420,
|
||||||
dec->width, dec->height);
|
dec->width, dec->height);
|
||||||
mpeg_dec->b_vdp_info.backward_reference =
|
|
||||||
mpeg_dec->b_vdp_info.forward_reference;
|
b_frame->vdp_info.forward_reference = surface;
|
||||||
mpeg_dec->b_vdp_info.forward_reference = surface;
|
|
||||||
vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
|
vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
|
||||||
vbit[0].bitstream = GST_BUFFER_DATA (mpeg_dec->b_buffer);
|
vbit[0].bitstream = GST_BUFFER_DATA (b_frame->buffer);
|
||||||
vbit[0].bitstream_bytes = GST_BUFFER_SIZE (mpeg_dec->b_buffer);
|
vbit[0].bitstream_bytes = GST_BUFFER_SIZE (b_frame->buffer);
|
||||||
|
|
||||||
status = device->vdp_decoder_render (mpeg_dec->decoder, b_outbuf->surface,
|
status = device->vdp_decoder_render (mpeg_dec->decoder, b_outbuf->surface,
|
||||||
(VdpPictureInfo *) & mpeg_dec->b_vdp_info, 1, vbit);
|
(VdpPictureInfo *) & b_frame->vdp_info, 1, vbit);
|
||||||
gst_buffer_unref (mpeg_dec->b_buffer);
|
gst_buffer_unref (b_frame->buffer);
|
||||||
mpeg_dec->b_buffer = NULL;
|
g_slice_free (GstVdpBFrame, b_frame);
|
||||||
|
|
||||||
if (status != VDP_STATUS_OK) {
|
if (status != VDP_STATUS_OK) {
|
||||||
GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ,
|
GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ,
|
||||||
|
@ -213,11 +228,14 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec)
|
||||||
device->vdp_get_error_string (status)));
|
device->vdp_get_error_string (status)));
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), b_outbuf);
|
gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec),
|
||||||
|
b_outbuf);
|
||||||
|
|
||||||
if (mpeg_dec->b_vdp_info.forward_reference != VDP_INVALID_HANDLE)
|
|
||||||
gst_buffer_unref (mpeg_dec->f_buffer);
|
gst_buffer_unref (mpeg_dec->f_buffer);
|
||||||
}
|
}
|
||||||
|
g_slist_free (mpeg_dec->b_frames);
|
||||||
|
mpeg_dec->b_frames = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gst_buffer_ref (GST_BUFFER (outbuf));
|
gst_buffer_ref (GST_BUFFER (outbuf));
|
||||||
|
|
||||||
|
@ -295,7 +313,6 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec,
|
||||||
|
|
||||||
mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type;
|
mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type;
|
||||||
|
|
||||||
|
|
||||||
if (pic_hdr.pic_type == I_FRAME &&
|
if (pic_hdr.pic_type == I_FRAME &&
|
||||||
mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) {
|
mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) {
|
||||||
gst_buffer_unref (mpeg_dec->f_buffer);
|
gst_buffer_unref (mpeg_dec->f_buffer);
|
||||||
|
@ -481,7 +498,7 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec,
|
||||||
mpeg_dec->decoder = VDP_INVALID_HANDLE;
|
mpeg_dec->decoder = VDP_INVALID_HANDLE;
|
||||||
gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info);
|
gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info);
|
||||||
|
|
||||||
mpeg_dec->b_buffer = NULL;
|
mpeg_dec->b_frames = NULL;
|
||||||
|
|
||||||
mpeg_dec->adapter = gst_adapter_new ();
|
mpeg_dec->adapter = gst_adapter_new ();
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,7 @@ struct _GstVdpMpegDecoder
|
||||||
GstBuffer *f_buffer;
|
GstBuffer *f_buffer;
|
||||||
|
|
||||||
/* holds B_FRAMES */
|
/* holds B_FRAMES */
|
||||||
GstBuffer *b_buffer;
|
GSList *b_frames;
|
||||||
VdpPictureInfoMPEG1Or2 b_vdp_info;
|
|
||||||
|
|
||||||
GstAdapter *adapter;
|
GstAdapter *adapter;
|
||||||
};
|
};
|
||||||
|
|
|
@ -285,14 +285,11 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end)
|
||||||
/* Skip the sync word */
|
/* Skip the sync word */
|
||||||
data += 4;
|
data += 4;
|
||||||
|
|
||||||
hdr->pic_type = (data[1] >> 3) & 0x07;
|
hdr->pic_type = read_bits (data + 1, 2, 3);
|
||||||
if (hdr->pic_type == 0 || hdr->pic_type > 4)
|
if (hdr->pic_type == 0 || hdr->pic_type > 4)
|
||||||
return FALSE; /* Corrupted picture packet */
|
return FALSE; /* Corrupted picture packet */
|
||||||
|
|
||||||
if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) {
|
if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) {
|
||||||
if (G_UNLIKELY ((end - data) < 5))
|
|
||||||
return FALSE; /* packet too small */
|
|
||||||
|
|
||||||
hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1);
|
hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1);
|
||||||
hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3);
|
hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue