playbin{2,3}: fix base_time selection when flush seeking live

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>
This commit is contained in:
Mathieu Duponchelle 2021-04-12 14:02:46 +02:00 committed by GStreamer Marge Bot
parent a273573d1e
commit c17781e1a9
2 changed files with 44 additions and 6 deletions

View file

@ -465,6 +465,8 @@ struct _GstPlayBin
guint64 ring_buffer_max_size; /* 0 means disabled */ guint64 ring_buffer_max_size; /* 0 means disabled */
GList *contexts; GList *contexts;
gboolean is_live;
}; };
struct _GstPlayBinClass struct _GstPlayBinClass
@ -1629,6 +1631,8 @@ gst_play_bin_finalize (GObject * object)
g_mutex_clear (&playbin->dyn_lock); g_mutex_clear (&playbin->dyn_lock);
g_mutex_clear (&playbin->elements_lock); g_mutex_clear (&playbin->elements_lock);
playbin->is_live = FALSE;
G_OBJECT_CLASS (parent_class)->finalize (object); 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); GstPlayBin *playbin = GST_PLAY_BIN (bin);
GstSourceGroup *group; GstSourceGroup *group;
gboolean do_reset_time = FALSE;
if (gst_is_missing_plugin_message (msg)) { if (gst_is_missing_plugin_message (msg)) {
gchar *detail; gchar *detail;
@ -3085,10 +3090,20 @@ gst_play_bin_handle_message (GstBin * bin, GstMessage * msg)
gst_message_parse_have_context (msg, &context); gst_message_parse_have_context (msg, &context);
gst_play_bin_update_context (playbin, context); gst_play_bin_update_context (playbin, context);
gst_context_unref (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) if (msg)
GST_BIN_CLASS (parent_class)->handle_message (bin, 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 static void
@ -5848,6 +5863,7 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
/* FIXME Release audio device when we implement that */ /* FIXME Release audio device when we implement that */
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
playbin->is_live = FALSE;
save_current_group (playbin); save_current_group (playbin);
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
@ -5931,6 +5947,9 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
break; 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) if (ret == GST_STATE_CHANGE_NO_PREROLL)
do_async_done (playbin); do_async_done (playbin);

View file

@ -516,6 +516,8 @@ struct _GstPlayBin3
GSequence *velements; /* a list of GstAVElements for video stream */ GSequence *velements; /* a list of GstAVElements for video stream */
guint64 ring_buffer_max_size; /* 0 means disabled */ guint64 ring_buffer_max_size; /* 0 means disabled */
gboolean is_live; /* Whether our current group is live */
}; };
struct _GstPlayBin3Class struct _GstPlayBin3Class
@ -1366,6 +1368,8 @@ gst_play_bin3_init (GstPlayBin3 * playbin)
playbin->multiview_mode = GST_VIDEO_MULTIVIEW_FRAME_PACKING_NONE; playbin->multiview_mode = GST_VIDEO_MULTIVIEW_FRAME_PACKING_NONE;
playbin->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE; playbin->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
playbin->is_live = FALSE;
} }
static void static void
@ -2294,8 +2298,8 @@ gst_play_bin3_send_event (GstElement * element, GstEvent * event)
group->selected_stream_types = group->selected_stream_types =
get_stream_type_for_event (group->collection, event); get_stream_type_for_event (group->collection, event);
playbin->selected_stream_types = playbin->selected_stream_types =
playbin->groups[0].selected_stream_types | playbin-> playbin->groups[0].selected_stream_types | playbin->groups[1].
groups[1].selected_stream_types; selected_stream_types;
if (playbin->active_stream_types != playbin->selected_stream_types) if (playbin->active_stream_types != playbin->selected_stream_types)
reconfigure_output (playbin); reconfigure_output (playbin);
} }
@ -2413,8 +2417,8 @@ do_stream_selection (GstPlayBin3 * playbin, GstSourceGroup * group)
group->selected_stream_types = chosen_stream_types; group->selected_stream_types = chosen_stream_types;
/* Update global selected_stream_types */ /* Update global selected_stream_types */
playbin->selected_stream_types = playbin->selected_stream_types =
playbin->groups[0].selected_stream_types | playbin-> playbin->groups[0].selected_stream_types | playbin->groups[1].
groups[1].selected_stream_types; selected_stream_types;
if (playbin->active_stream_types != playbin->selected_stream_types) if (playbin->active_stream_types != playbin->selected_stream_types)
reconfigure_output (playbin); reconfigure_output (playbin);
} }
@ -2439,6 +2443,7 @@ static void
gst_play_bin3_handle_message (GstBin * bin, GstMessage * msg) gst_play_bin3_handle_message (GstBin * bin, GstMessage * msg)
{ {
GstPlayBin3 *playbin = GST_PLAY_BIN3 (bin); GstPlayBin3 *playbin = GST_PLAY_BIN3 (bin);
gboolean do_reset_time = FALSE;
if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAM_START) { if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAM_START) {
GstSourceGroup *group = NULL, *other_group = NULL; GstSourceGroup *group = NULL, *other_group = NULL;
@ -2539,11 +2544,21 @@ gst_play_bin3_handle_message (GstBin * bin, GstMessage * msg)
gst_object_unref (collection); 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: beach:
if (msg) if (msg)
GST_BIN_CLASS (parent_class)->handle_message (bin, 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 static void
@ -4638,8 +4653,8 @@ deactivate_group (GstPlayBin3 * playbin, GstSourceGroup * group)
group->selected_stream_types = 0; group->selected_stream_types = 0;
/* Update global selected_stream_types */ /* Update global selected_stream_types */
playbin->selected_stream_types = playbin->selected_stream_types =
playbin->groups[0].selected_stream_types | playbin-> playbin->groups[0].selected_stream_types | playbin->groups[1].
groups[1].selected_stream_types; selected_stream_types;
if (playbin->active_stream_types != playbin->selected_stream_types) if (playbin->active_stream_types != playbin->selected_stream_types)
reconfigure_output (playbin); reconfigure_output (playbin);
@ -4953,6 +4968,7 @@ gst_play_bin3_change_state (GstElement * element, GstStateChange transition)
/* FIXME Release audio device when we implement that */ /* FIXME Release audio device when we implement that */
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
playbin->is_live = FALSE;
save_current_group (playbin); save_current_group (playbin);
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
@ -5002,6 +5018,9 @@ gst_play_bin3_change_state (GstElement * element, GstStateChange transition)
break; 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) if (ret == GST_STATE_CHANGE_NO_PREROLL)
do_async_done (playbin); do_async_done (playbin);