va: mpeg2dec: Using the current picture's surface when missing reference.
authorHe Junyan <junyan.he@intel.com>
Wed, 30 Dec 2020 15:29:47 +0000 (23:29 +0800)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Mon, 4 Jan 2021 13:09:01 +0000 (13:09 +0000)
When missing the reference frames, we should not just discard the current
frame. Some streams have group of picture header. It is an optional header
that can be used immediately before a coded I-frame to indicate to the decoder
if the first consecutive B-pictures immediately following the coded I-frame can
be reconstructed properly in the case of a random access.
In that case, the B frames may miss the previous reference and can still be
correctly decoded. We also notice that the second field of the I frame may
be set to P type, and it only ref its first field.
We should not skip all those frames, and even the frame really misses the
reference frame, some manner such as inserting grey picture should be used
to handle these cases.

The driver crashes when it needs to access the reference picture while we set
forward_reference_picture or backward_reference_picture to VA_INVALID_ID. We
now set it to current picture to avoid this. This is just a temp manner.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1929>

sys/va/gstvampeg2dec.c

index 51da9d5..c3d7db7 100644 (file)
@@ -459,7 +459,9 @@ gst_va_mpeg2_dec_start_picture (GstMpeg2Decoder * decoder,
         prev_picture ? gst_mpeg2_picture_get_user_data (prev_picture) : NULL;
     if (!prev_pic) {
       GST_WARNING_OBJECT (self, "Missing the forward reference picture");
-      return FALSE;
+      pic_param.forward_reference_picture =
+          gst_va_decode_picture_get_surface (gst_mpeg2_picture_get_user_data
+          (picture));
     } else {
       pic_param.forward_reference_picture =
           gst_va_decode_picture_get_surface (prev_pic);
@@ -473,7 +475,9 @@ gst_va_mpeg2_dec_start_picture (GstMpeg2Decoder * decoder,
         next_picture ? gst_mpeg2_picture_get_user_data (next_picture) : NULL;
     if (!next_pic) {
       GST_WARNING_OBJECT (self, "Missing the backward reference picture");
-      return FALSE;
+      pic_param.backward_reference_picture =
+          gst_va_decode_picture_get_surface (gst_mpeg2_picture_get_user_data
+          (picture));
     } else {
       pic_param.backward_reference_picture =
           gst_va_decode_picture_get_surface (next_pic);