avvidec: Ensure skipping strategy gets properly reset
authorEdward Hervey <edward@centricular.com>
Thu, 4 Aug 2016 08:45:14 +0000 (10:45 +0200)
committerEdward Hervey <bilboed@bilboed.com>
Thu, 4 Aug 2016 08:45:14 +0000 (10:45 +0200)
When switching playback modes, like from TRICKMODE or TRICKMODE_KEY_UNITS
back to regular playback, we need to make sure we set the skip mode
back to the default setting.

While this field would be properly reset when we *have* feedback from
downstream (i.e. diff != G_MAXINT64), it would not be reset during
the initial phase (i.e. when the decoder hasn't pushed a buffer yet,
and therefore the sink hasn't sent back QoS information).

This avoids dropping plenty of frames when going back to regular playback

ext/libav/gstavviddec.c

index d341174..8aabcb1 100644 (file)
@@ -1156,29 +1156,36 @@ gst_ffmpegviddec_do_qos (GstFFMpegVidDec * ffmpegdec,
     *mode_switch = TRUE;
   }
 
+  if (*mode_switch == TRUE) {
+    /* We've already switched mode, we can return straight away
+     * without any further calculation */
+    return;
+  }
+
   diff =
       gst_video_decoder_get_max_decode_time (GST_VIDEO_DECODER (ffmpegdec),
       frame);
 
   /* if we don't have timing info, then we don't do QoS */
-  if (G_UNLIKELY (diff == G_MAXINT64))
+  if (G_UNLIKELY (diff == G_MAXINT64)) {
+    /* Ensure the skipping strategy is the default one */
+    ffmpegdec->context->skip_frame = ffmpegdec->skip_frame;
     return;
+  }
 
   GST_DEBUG_OBJECT (ffmpegdec, "decoding time %" G_GINT64_FORMAT, diff);
 
-  if (*mode_switch == FALSE) {
-    if (diff > 0 && ffmpegdec->context->skip_frame != AVDISCARD_DEFAULT) {
-      ffmpegdec->context->skip_frame = AVDISCARD_DEFAULT;
-      *mode_switch = TRUE;
-      GST_DEBUG_OBJECT (ffmpegdec, "QOS: normal mode");
-    }
+  if (diff > 0 && ffmpegdec->context->skip_frame != AVDISCARD_DEFAULT) {
+    ffmpegdec->context->skip_frame = AVDISCARD_DEFAULT;
+    *mode_switch = TRUE;
+    GST_DEBUG_OBJECT (ffmpegdec, "QOS: normal mode");
+  }
 
-    else if (diff <= 0 && ffmpegdec->context->skip_frame != AVDISCARD_NONREF) {
-      ffmpegdec->context->skip_frame = AVDISCARD_NONREF;
-      *mode_switch = TRUE;
-      GST_DEBUG_OBJECT (ffmpegdec,
-          "QOS: hurry up, diff %" G_GINT64_FORMAT " >= 0", diff);
-    }
+  else if (diff <= 0 && ffmpegdec->context->skip_frame != AVDISCARD_NONREF) {
+    ffmpegdec->context->skip_frame = AVDISCARD_NONREF;
+    *mode_switch = TRUE;
+    GST_DEBUG_OBJECT (ffmpegdec,
+        "QOS: hurry up, diff %" G_GINT64_FORMAT " >= 0", diff);
   }
 }