mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-28 20:05:38 +00:00
event: Add new GST_EVENT_INSTANT_RATE_CHANGE and GST_SEEK_FLAGS_INSTANT_RATE_CHANGE
A seek with that flag set must be non-flushing, not change the playback direction and start/stop position. A seek handler will then send the new GST_EVENT_INSTANT_RATE_CHANGE event downstream for downstream elements to immediately apply the new playback rate before the new in-band segment event arrives.
This commit is contained in:
parent
9707db909d
commit
be3c4d00cf
5 changed files with 108 additions and 1 deletions
|
@ -132,6 +132,7 @@ static GstEventQuarks event_quarks[] = {
|
|||
{GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
|
||||
{GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
|
||||
{GST_EVENT_STREAM_GROUP_DONE, "stream-group-done", 0},
|
||||
{GST_EVENT_INSTANT_RATE_CHANGE, "instant-rate-change", 0},
|
||||
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
@ -1270,6 +1271,10 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
|
|||
GstStructure *structure;
|
||||
|
||||
g_return_val_if_fail (rate != 0.0, NULL);
|
||||
g_return_val_if_fail ((flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) == 0
|
||||
|| (start_type == GST_SEEK_TYPE_NONE
|
||||
&& stop_type == GST_SEEK_TYPE_NONE
|
||||
&& (flags & GST_SEEK_FLAG_FLUSH) == 0), NULL);
|
||||
|
||||
/* SNAP flags only make sense in combination with the KEYUNIT flag. Warn
|
||||
* and unset the SNAP flags if they're set without the KEYUNIT flag */
|
||||
|
@ -2167,3 +2172,70 @@ gst_event_parse_segment_done (GstEvent * event, GstFormat * format,
|
|||
if (position != NULL)
|
||||
*position = g_value_get_int64 (val);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_instant_rate_change:
|
||||
* @rate_multiplier: the multiplier to be applied to the playback rate
|
||||
* @new_flags: A new subset of segment flags to replace in segments
|
||||
*
|
||||
* Create a new instant-rate-change event. This event is sent by seek
|
||||
* handlers (e.g. demuxers) when receiving a seek with the
|
||||
* %GST_SEEK_FLAG_INSTANT_RATE_CHANGE and signals to downstream elements that
|
||||
* the playback rate in the existing segment should be immediately multiplied
|
||||
* by the @rate_multiplier factor.
|
||||
*
|
||||
* The flags provided replace any flags in the existing segment, for the
|
||||
* flags within the %GST_SEGMENT_INSTANT_FLAGS set. Other GstSegmentFlags
|
||||
* are ignored and not transferred in the event.
|
||||
*
|
||||
* Returns: (transfer full): the new instant-rate-change event.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_instant_rate_change (gdouble rate_multiplier,
|
||||
GstSegmentFlags new_flags)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
g_return_val_if_fail (rate_multiplier != 0.0, NULL);
|
||||
|
||||
new_flags &= GST_SEGMENT_INSTANT_FLAGS;
|
||||
|
||||
GST_CAT_TRACE (GST_CAT_EVENT, "creating instant-rate-change event %lf %08x",
|
||||
rate_multiplier, new_flags);
|
||||
|
||||
event = gst_event_new_custom (GST_EVENT_INSTANT_RATE_CHANGE,
|
||||
gst_structure_new_id (GST_QUARK (EVENT_INSTANT_RATE_CHANGE),
|
||||
GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier,
|
||||
GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, new_flags, NULL));
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_parse_instant_rate_change:
|
||||
* @event: a #GstEvent of type #GST_EVENT_INSTANT_RATE_CHANGE
|
||||
* @rate_multiplier: (out) (allow-none): location in which to store the rate
|
||||
* multiplier of the instant-rate-change event, or %NULL
|
||||
* @new_flags: (out) (allow-none): location in which to store the new
|
||||
* segment flags of the instant-rate-change event, or %NULL
|
||||
*
|
||||
* Extract rate and flags from an instant-rate-change event.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
void
|
||||
gst_event_parse_instant_rate_change (GstEvent * event,
|
||||
gdouble * rate_multiplier, GstSegmentFlags * new_flags)
|
||||
{
|
||||
GstStructure *structure;
|
||||
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_CHANGE);
|
||||
|
||||
structure = GST_EVENT_STRUCTURE (event);
|
||||
gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE,
|
||||
rate_multiplier, GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, new_flags,
|
||||
NULL);
|
||||
}
|
||||
|
|
|
@ -121,6 +121,8 @@ typedef enum {
|
|||
* @GST_EVENT_RECONFIGURE: A request for upstream renegotiating caps and reconfiguring.
|
||||
* @GST_EVENT_TOC_SELECT: A request for a new playback position based on TOC
|
||||
* entry's UID.
|
||||
* @GST_EVENT_INSTANT_RATE_CHANGE: Notify downstream that a playback rate override
|
||||
* should be applied as soon as possible. (Since: 1.18)
|
||||
* @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event
|
||||
* @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the
|
||||
* data flow.
|
||||
|
@ -163,6 +165,9 @@ typedef enum {
|
|||
GST_EVENT_SEGMENT_DONE = GST_EVENT_MAKE_TYPE (150, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
|
||||
GST_EVENT_GAP = GST_EVENT_MAKE_TYPE (160, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
|
||||
|
||||
/* sticky downstream non-serialized */
|
||||
GST_EVENT_INSTANT_RATE_CHANGE = GST_EVENT_MAKE_TYPE (180, FLAG(DOWNSTREAM) | FLAG(STICKY)),
|
||||
|
||||
/* upstream events */
|
||||
GST_EVENT_QOS = GST_EVENT_MAKE_TYPE (190, FLAG(UPSTREAM)),
|
||||
GST_EVENT_SEEK = GST_EVENT_MAKE_TYPE (200, FLAG(UPSTREAM)),
|
||||
|
@ -731,6 +736,15 @@ GstEvent* gst_event_new_segment_done (GstFormat format, gint64 positi
|
|||
GST_API
|
||||
void gst_event_parse_segment_done (GstEvent *event, GstFormat *format, gint64 *position);
|
||||
|
||||
/* instant-rate-change event */
|
||||
|
||||
GST_API
|
||||
GstEvent * gst_event_new_instant_rate_change (gdouble rate_multiplier, GstSegmentFlags new_flags) G_GNUC_MALLOC;
|
||||
|
||||
GST_API
|
||||
void gst_event_parse_instant_rate_change (GstEvent *event,
|
||||
gdouble *rate_multiplier, GstSegmentFlags *new_flags);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEvent, gst_event_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -77,6 +77,7 @@ static const gchar *_quark_strings[] = {
|
|||
"redirect-entry-taglists", "redirect-entry-structures",
|
||||
"GstEventStreamGroupDone", "GstQueryBitrate", "nominal-bitrate",
|
||||
"GstMessageDeviceChanged", "device-changed", "trickmode-interval",
|
||||
"GstEventInstantRateChange",
|
||||
};
|
||||
|
||||
GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
|
@ -222,7 +222,8 @@ typedef enum _GstQuarkId
|
|||
GST_QUARK_MESSAGE_DEVICE_CHANGED = 191,
|
||||
GST_QUARK_DEVICE_CHANGED = 192,
|
||||
GST_QUARK_TRICKMODE_INTERVAL = 193,
|
||||
GST_QUARK_MAX = 194
|
||||
GST_QUARK_EVENT_INSTANT_RATE_CHANGE = 194,
|
||||
GST_QUARK_MAX = 195
|
||||
} GstQuarkId;
|
||||
|
||||
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
|
@ -81,6 +81,10 @@ typedef enum {
|
|||
* @GST_SEEK_FLAG_TRICKMODE_NO_AUDIO: when doing fast forward or fast reverse
|
||||
* playback, request that audio decoder elements skip
|
||||
* decoding and output only gap events or silence. (Since: 1.6)
|
||||
* @GST_SEEK_FLAG_INSTANT_RATE_CHANGE: Signals that a rate change should be
|
||||
* applied immediately. Only valid if start/stop position
|
||||
* are GST_CLOCK_TIME_NONE, the playback direction does not change
|
||||
* and the seek is not flushing. (Since: 1.18)
|
||||
* @GST_SEEK_FLAG_SKIP: Deprecated backward compatibility flag, replaced
|
||||
* by %GST_SEEK_FLAG_TRICKMODE
|
||||
*
|
||||
|
@ -101,6 +105,16 @@ typedef enum {
|
|||
* continue playback. With this seek method it is possible to perform seamless
|
||||
* looping or simple linear editing.
|
||||
*
|
||||
* When only changing the playback rate and not the direction, the
|
||||
* %GST_SEEK_FLAG_INSTANT_RATE_CHANGE flag can be used for a non-flushing seek
|
||||
* to signal that the rate change should be applied immediately. This requires
|
||||
* special support in the seek handlers (e.g. demuxers) and any elements
|
||||
* synchronizing to the clock, and in general can't work in all cases (for example
|
||||
* UDP streaming where the delivery rate is controlled by a remote server). The
|
||||
* instant-rate-change mode supports changing the trickmode-related GST_SEEK_ flags,
|
||||
* but can't be used in conjunction with other seek flags that affect the new
|
||||
* playback position - as the playback position will not be changing.
|
||||
*
|
||||
* When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode
|
||||
* playback, the %GST_SEEK_FLAG_TRICKMODE flag can be used to instruct decoders
|
||||
* and demuxers to adjust the playback rate by skipping frames. This can improve
|
||||
|
@ -143,6 +157,7 @@ typedef enum {
|
|||
GST_SEEK_FLAG_TRICKMODE_KEY_UNITS = (1 << 7),
|
||||
GST_SEEK_FLAG_TRICKMODE_NO_AUDIO = (1 << 8),
|
||||
GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED = (1 << 9),
|
||||
GST_SEEK_FLAG_INSTANT_RATE_CHANGE = (1 << 10),
|
||||
} GstSeekFlags;
|
||||
|
||||
/**
|
||||
|
@ -178,6 +193,10 @@ typedef enum { /*< flags >*/
|
|||
GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO = GST_SEEK_FLAG_TRICKMODE_NO_AUDIO
|
||||
} GstSegmentFlags;
|
||||
|
||||
/* Flags that are reflected for instant-rate-change seeks */
|
||||
#define GST_SEGMENT_INSTANT_FLAGS \
|
||||
(GST_SEGMENT_FLAG_TRICKMODE|GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS|GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED|GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO)
|
||||
|
||||
/**
|
||||
* GstSegment:
|
||||
* @flags: flags for this segment
|
||||
|
|
Loading…
Reference in a new issue