playbin{2,3}: fix base_time selection when flush seeking live
authorMathieu Duponchelle <mathieu@centricular.com>
Mon, 12 Apr 2021 12:02:46 +0000 (14:02 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 12 Apr 2021 12:43:53 +0000 (12:43 +0000)
This is a direct translation of
<https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/429>,
as playbin{2,3} insulates its sub groups state changes from the pipeline
base class, it needs to track whether the subgroup is live itself,
and handle RESET_TIME the same way GstPipeline does.

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

gst/playback/gstplaybin2.c
gst/playback/gstplaybin3.c

index ff0912c..961103f 100644 (file)
@@ -465,6 +465,8 @@ struct _GstPlayBin
   guint64 ring_buffer_max_size; /* 0 means disabled */
 
   GList *contexts;
+
+  gboolean is_live;
 };
 
 struct _GstPlayBinClass
@@ -1629,6 +1631,8 @@ gst_play_bin_finalize (GObject * object)
   g_mutex_clear (&playbin->dyn_lock);
   g_mutex_clear (&playbin->elements_lock);
 
+  playbin->is_live = FALSE;
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -2877,6 +2881,7 @@ gst_play_bin_handle_message (GstBin * bin, GstMessage * msg)
 {
   GstPlayBin *playbin = GST_PLAY_BIN (bin);
   GstSourceGroup *group;
+  gboolean do_reset_time = FALSE;
 
   if (gst_is_missing_plugin_message (msg)) {
     gchar *detail;
@@ -3085,10 +3090,20 @@ gst_play_bin_handle_message (GstBin * bin, GstMessage * msg)
     gst_message_parse_have_context (msg, &context);
     gst_play_bin_update_context (playbin, context);
     gst_context_unref (context);
+  } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_RESET_TIME) {
+    if (playbin->is_live && GST_STATE_TARGET (playbin) == GST_STATE_PLAYING) {
+      do_reset_time = TRUE;
+    }
   }
 
   if (msg)
     GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
+
+  if (do_reset_time) {
+    /* If we are live, sample a new base_time immediately */
+    gst_element_change_state (GST_ELEMENT (playbin),
+        GST_STATE_CHANGE_PAUSED_TO_PLAYING);
+  }
 }
 
 static void
@@ -5848,6 +5863,7 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
       /* FIXME Release audio device when we implement that */
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+      playbin->is_live = FALSE;
       save_current_group (playbin);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -5931,6 +5947,9 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
+  if (GST_STATE_TRANSITION_NEXT (transition) == GST_STATE_PAUSED)
+    playbin->is_live = ret == GST_STATE_CHANGE_NO_PREROLL;
+
   if (ret == GST_STATE_CHANGE_NO_PREROLL)
     do_async_done (playbin);
 
index 60dd2af..512cf26 100644 (file)
@@ -516,6 +516,8 @@ struct _GstPlayBin3
   GSequence *velements;         /* a list of GstAVElements for video stream */
 
   guint64 ring_buffer_max_size; /* 0 means disabled */
+
+  gboolean is_live;             /* Whether our current group is live */
 };
 
 struct _GstPlayBin3Class
@@ -1366,6 +1368,8 @@ gst_play_bin3_init (GstPlayBin3 * playbin)
 
   playbin->multiview_mode = GST_VIDEO_MULTIVIEW_FRAME_PACKING_NONE;
   playbin->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
+
+  playbin->is_live = FALSE;
 }
 
 static void
@@ -2294,8 +2298,8 @@ gst_play_bin3_send_event (GstElement * element, GstEvent * event)
       group->selected_stream_types =
           get_stream_type_for_event (group->collection, event);
       playbin->selected_stream_types =
-          playbin->groups[0].selected_stream_types | playbin->
-          groups[1].selected_stream_types;
+          playbin->groups[0].selected_stream_types | playbin->groups[1].
+          selected_stream_types;
       if (playbin->active_stream_types != playbin->selected_stream_types)
         reconfigure_output (playbin);
     }
@@ -2413,8 +2417,8 @@ do_stream_selection (GstPlayBin3 * playbin, GstSourceGroup * group)
   group->selected_stream_types = chosen_stream_types;
   /* Update global selected_stream_types */
   playbin->selected_stream_types =
-      playbin->groups[0].selected_stream_types | playbin->
-      groups[1].selected_stream_types;
+      playbin->groups[0].selected_stream_types | playbin->groups[1].
+      selected_stream_types;
   if (playbin->active_stream_types != playbin->selected_stream_types)
     reconfigure_output (playbin);
 }
@@ -2439,6 +2443,7 @@ static void
 gst_play_bin3_handle_message (GstBin * bin, GstMessage * msg)
 {
   GstPlayBin3 *playbin = GST_PLAY_BIN3 (bin);
+  gboolean do_reset_time = FALSE;
 
   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAM_START) {
     GstSourceGroup *group = NULL, *other_group = NULL;
@@ -2539,11 +2544,21 @@ gst_play_bin3_handle_message (GstBin * bin, GstMessage * msg)
 
       gst_object_unref (collection);
     }
+  } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_RESET_TIME) {
+    if (playbin->is_live && GST_STATE_TARGET (playbin) == GST_STATE_PLAYING) {
+      do_reset_time = TRUE;
+    }
   }
 
 beach:
   if (msg)
     GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
+
+  if (do_reset_time) {
+    /* If we are live, sample a new base_time immediately */
+    gst_element_change_state (GST_ELEMENT (playbin),
+        GST_STATE_CHANGE_PAUSED_TO_PLAYING);
+  }
 }
 
 static void
@@ -4638,8 +4653,8 @@ deactivate_group (GstPlayBin3 * playbin, GstSourceGroup * group)
   group->selected_stream_types = 0;
   /* Update global selected_stream_types */
   playbin->selected_stream_types =
-      playbin->groups[0].selected_stream_types | playbin->
-      groups[1].selected_stream_types;
+      playbin->groups[0].selected_stream_types | playbin->groups[1].
+      selected_stream_types;
   if (playbin->active_stream_types != playbin->selected_stream_types)
     reconfigure_output (playbin);
 
@@ -4953,6 +4968,7 @@ gst_play_bin3_change_state (GstElement * element, GstStateChange transition)
       /* FIXME Release audio device when we implement that */
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+      playbin->is_live = FALSE;
       save_current_group (playbin);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -5002,6 +5018,9 @@ gst_play_bin3_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
+  if (GST_STATE_TRANSITION_NEXT (transition) == GST_STATE_PAUSED)
+    playbin->is_live = ret == GST_STATE_CHANGE_NO_PREROLL;
+
   if (ret == GST_STATE_CHANGE_NO_PREROLL)
     do_async_done (playbin);