From bb4191a149108cda6d8a34814c1a3acdcfc74f56 Mon Sep 17 00:00:00 2001 From: Rafostar <40623528+Rafostar@users.noreply.github.com> Date: Mon, 9 Nov 2020 11:22:32 +0100 Subject: [PATCH] player: set seek mode without stopping playback Move seek mode setting outside of "config" object, so it can be changed without stopping playback. --- gst-libs/gst/player/gstplayer.c | 117 ++++++++++++++++++++------------ gst-libs/gst/player/gstplayer.h | 30 ++++++-- 2 files changed, 98 insertions(+), 49 deletions(-) diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c index 45705c671..d13c0cc63 100644 --- a/gst-libs/gst/player/gstplayer.c +++ b/gst-libs/gst/player/gstplayer.c @@ -70,6 +70,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_player_debug); #define DEFAULT_POSITION_UPDATE_INTERVAL_MS 100 #define DEFAULT_AUDIO_VIDEO_OFFSET 0 #define DEFAULT_SUBTITLE_VIDEO_OFFSET 0 +#define DEFAULT_SEEK_MODE GST_PLAYER_SEEK_MODE_DEFAULT /** * gst_player_error_quark: @@ -87,7 +88,6 @@ typedef enum { CONFIG_QUARK_USER_AGENT = 0, CONFIG_QUARK_POSITION_INTERVAL_UPDATE, - CONFIG_QUARK_ACCURATE_SEEK, CONFIG_QUARK_MAX } ConfigQuarkId; @@ -95,7 +95,6 @@ typedef enum static const gchar *_config_quark_strings[] = { "user-agent", "position-interval-update", - "accurate-seek", }; GQuark _config_quark_table[CONFIG_QUARK_MAX]; @@ -123,6 +122,7 @@ enum PROP_VIDEO_MULTIVIEW_FLAGS, PROP_AUDIO_VIDEO_OFFSET, PROP_SUBTITLE_VIDEO_OFFSET, + PROP_SEEK_MODE, PROP_LAST }; @@ -188,6 +188,8 @@ struct _GstPlayer GstStructure *config; + GstPlayerSeekMode seek_mode; + /* Protected by lock */ gboolean seek_pending; /* Only set from main context */ GstClockTime last_seek_time; /* Only set from main context */ @@ -294,7 +296,6 @@ gst_player_init (GstPlayer * self) /* *INDENT-OFF* */ self->config = gst_structure_new_id (QUARK_CONFIG, CONFIG_QUARK (POSITION_INTERVAL_UPDATE), G_TYPE_UINT, DEFAULT_POSITION_UPDATE_INTERVAL_MS, - CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, FALSE, NULL); /* *INDENT-ON* */ @@ -424,6 +425,12 @@ gst_player_class_init (GstPlayerClass * klass) "The synchronisation offset between text and video in nanoseconds", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + param_specs[PROP_SEEK_MODE] = + g_param_spec_enum ("seek-mode", "Player Seek Mode", + "Selected player seek mode to use when performing seeks", + GST_TYPE_PLAYER_SEEK_MODE, DEFAULT_SEEK_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (gobject_class, PROP_LAST, param_specs); signals[SIGNAL_URI_LOADED] = @@ -747,6 +754,11 @@ gst_player_set_property (GObject * object, guint prop_id, case PROP_SUBTITLE_VIDEO_OFFSET: g_object_set_property (G_OBJECT (self->playbin), "text-offset", value); break; + case PROP_SEEK_MODE: + g_mutex_lock (&self->lock); + self->seek_mode = g_value_get_enum (value); + g_mutex_unlock (&self->lock); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -847,6 +859,11 @@ gst_player_get_property (GObject * object, guint prop_id, case PROP_SUBTITLE_VIDEO_OFFSET: g_object_get_property (G_OBJECT (self->playbin), "text-offset", value); break; + case PROP_SEEK_MODE: + g_mutex_lock (&self->lock); + g_value_set_enum (value, self->seek_mode); + g_mutex_unlock (&self->lock); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2988,6 +3005,7 @@ gst_player_main (gpointer data) self->is_eos = FALSE; self->is_live = FALSE; self->rate = 1.0; + self->seek_mode = DEFAULT_SEEK_MODE; GST_TRACE_OBJECT (self, "Starting main loop"); g_main_loop_run (self->loop); @@ -3316,8 +3334,8 @@ gst_player_seek_internal_locked (GstPlayer * self) gdouble rate; GstStateChangeReturn state_ret; GstEvent *s_event; + GstPlayerSeekMode seek_mode; GstSeekFlags flags = 0; - gboolean accurate = FALSE; remove_seek_source (self); @@ -3330,8 +3348,6 @@ gst_player_seek_internal_locked (GstPlayer * self) if (state_ret == GST_STATE_CHANGE_FAILURE) { emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED, "Failed to seek")); - g_mutex_lock (&self->lock); - return; } g_mutex_lock (&self->lock); return; @@ -3342,6 +3358,7 @@ gst_player_seek_internal_locked (GstPlayer * self) self->seek_position = GST_CLOCK_TIME_NONE; self->seek_pending = TRUE; rate = self->rate; + seek_mode = self->seek_mode; g_mutex_unlock (&self->lock); remove_tick_source (self); @@ -3349,12 +3366,15 @@ gst_player_seek_internal_locked (GstPlayer * self) flags |= GST_SEEK_FLAG_FLUSH; - accurate = gst_player_config_get_seek_accurate (self->config); - - if (accurate) { - flags |= GST_SEEK_FLAG_ACCURATE; - } else { - flags &= ~GST_SEEK_FLAG_ACCURATE; + switch (seek_mode) { + case GST_PLAYER_SEEK_MODE_ACCURATE: + flags |= GST_SEEK_FLAG_ACCURATE; + break; + case GST_PLAYER_SEEK_MODE_FAST: + flags |= GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_AFTER; + break; + default: + break; } if (rate != 1.0) { @@ -4692,51 +4712,62 @@ gst_player_config_get_position_update_interval (const GstStructure * config) return interval; } +GType +gst_player_seek_mode_get_type (void) +{ + static gsize id = 0; + static const GEnumValue values[] = { + {C_ENUM (GST_PLAYER_SEEK_MODE_DEFAULT), "GST_PLAYER_SEEK_MODE_DEFAULT", + "default"}, + {C_ENUM (GST_PLAYER_SEEK_MODE_ACCURATE), "GST_PLAYER_SEEK_MODE_ACCURATE", + "accurate"}, + {C_ENUM (GST_PLAYER_SEEK_MODE_FAST), "GST_PLAYER_SEEK_MODE_FAST", "fast"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (&id)) { + GType tmp = g_enum_register_static ("GstPlayerSeekMode", values); + g_once_init_leave (&id, tmp); + } + + return (GType) id; +} + /** - * gst_player_config_set_seek_accurate: - * @config: a #GstPlayer configuration - * @accurate: accurate seek or not - * - * Enable or disable accurate seeking. When enabled, elements will try harder - * to seek as accurately as possible to the requested seek position. Generally - * it will be slower especially for formats that don't have any indexes or - * timestamp markers in the stream. - * - * If accurate seeking is disabled, elements will seek as close as the request - * position without slowing down seeking too much. + * gst_player_get_seek_mode: + * @player: #GstPlayer instance * - * Accurate seeking is disabled by default. + * Returns: The currently used seek mode, Default: 0 "default" * - * Since: 1.12 + * Since: 1.20 */ -void -gst_player_config_set_seek_accurate (GstStructure * config, gboolean accurate) +GstPlayerSeekMode +gst_player_get_seek_mode (GstPlayer * self) { - g_return_if_fail (config != NULL); + GstPlayerSeekMode mode; - gst_structure_id_set (config, - CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, accurate, NULL); + g_return_val_if_fail (GST_IS_PLAYER (self), DEFAULT_SEEK_MODE); + + g_object_get (self, "seek-mode", &mode, NULL); + + return mode; } /** - * gst_player_config_get_seek_accurate: - * @config: a #GstPlayer configuration + * gst_player_set_seek_mode: + * @player: #GstPlayer instance + * @mode: #GstPlayerSeekMode * - * Returns: %TRUE if accurate seeking is enabled + * Changes currently used player seek mode to the one of @mode * - * Since: 1.12 + * Since: 1.20 */ -gboolean -gst_player_config_get_seek_accurate (const GstStructure * config) +void +gst_player_set_seek_mode (GstPlayer * self, GstPlayerSeekMode mode) { - gboolean accurate = FALSE; - - g_return_val_if_fail (config != NULL, FALSE); - - gst_structure_id_get (config, - CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, &accurate, NULL); + g_return_if_fail (GST_IS_PLAYER (self)); - return accurate; + g_object_set (self, "seek-mode", mode, NULL); } /** diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h index e853ed875..9c0ab5a60 100644 --- a/gst-libs/gst/player/gstplayer.h +++ b/gst-libs/gst/player/gstplayer.h @@ -96,6 +96,23 @@ typedef enum GST_PLAYER_API const gchar *gst_player_color_balance_type_get_name (GstPlayerColorBalanceType type); +GST_PLAYER_API +GType gst_player_seek_mode_get_type (void); +#define GST_TYPE_PLAYER_SEEK_MODE (gst_player_seek_mode_get_type ()) + +/** + * GstPlayerSeekMode: + * @GST_PLAYER_SEEK_MODE_DEFAULT: default seek method (flush only). + * @GST_PLAYER_SEEK_MODE_ACCURATE: accurate seek method. + * @GST_PLAYER_SEEK_MODE_FAST: fast seek method (next keyframe). + */ +typedef enum +{ + GST_PLAYER_SEEK_MODE_DEFAULT, + GST_PLAYER_SEEK_MODE_ACCURATE, + GST_PLAYER_SEEK_MODE_FAST, +} GstPlayerSeekMode; + #define GST_TYPE_PLAYER (gst_player_get_type ()) #define GST_IS_PLAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAYER)) #define GST_IS_PLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAYER)) @@ -127,6 +144,13 @@ GST_PLAYER_API void gst_player_seek (GstPlayer * player, GstClockTime position); +GST_PLAYER_API +GstPlayerSeekMode gst_player_get_seek_mode (GstPlayer * player); + +GST_PLAYER_API +void gst_player_set_seek_mode (GstPlayer * player, + GstPlayerSeekMode mode); + GST_PLAYER_API void gst_player_set_rate (GstPlayer * player, gdouble rate); @@ -282,12 +306,6 @@ void gst_player_config_set_position_update_interval (GstStructure * c GST_PLAYER_API guint gst_player_config_get_position_update_interval (const GstStructure * config); -GST_PLAYER_API -void gst_player_config_set_seek_accurate (GstStructure * config, gboolean accurate); - -GST_PLAYER_API -gboolean gst_player_config_get_seek_accurate (const GstStructure * config); - typedef enum { GST_PLAYER_THUMBNAIL_RAW_NATIVE = 0, -- 2.26.2