diff --git a/gst/gstevent.c b/gst/gstevent.c index ed5d1e90a5..7976ec77ea 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -133,6 +133,7 @@ static GstEventQuarks event_quarks[] = { {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}, + {GST_EVENT_INSTANT_RATE_SYNC_TIME, "instant-rate-sync-time", 0}, {0, NULL, 0} }; @@ -2239,3 +2240,83 @@ gst_event_parse_instant_rate_change (GstEvent * event, rate_multiplier, GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, new_flags, NULL); } + +/** + * gst_event_new_instant_rate_sync_time: + * @rate_multiplier: the new playback rate multiplier to be applied + * @running_time: Running time when the rate change should be applied + * @upstream_running_time: The upstream-centric running-time when the + * rate change should be applied. + * + * Create a new instant-rate-sync-time event. This event is sent by the + * pipeline to notify elements handling the instant-rate-change event about + * the running-time when the new rate should be applied. The running time + * may be in the past when elements handle this event, which can lead to + * switching artifacts. The magnitude of those depends on the exact timing + * of event delivery to each element and the magnitude of the change in + * playback rate being applied. + * + * The @running_time and @upstream_running_time are the same if this + * is the first instant-rate adjustment, but will differ for later ones + * to compensate for the accumulated offset due to playing at a rate + * different to the one indicated in the playback segments. + * + * Returns: (transfer full): the new instant-rate-sync-time event. + * + * Since: 1.18 + */ +GstEvent * +gst_event_new_instant_rate_sync_time (gdouble rate_multiplier, + GstClockTime running_time, GstClockTime upstream_running_time) +{ + GstEvent *event; + + g_return_val_if_fail (rate_multiplier != 0.0, NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (running_time), NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (upstream_running_time), NULL); + + GST_CAT_TRACE (GST_CAT_EVENT, + "creating instant-rate-sync-time event %lf %" GST_TIME_FORMAT + " %" GST_TIME_FORMAT, rate_multiplier, + GST_TIME_ARGS (running_time), GST_TIME_ARGS (upstream_running_time)); + + event = gst_event_new_custom (GST_EVENT_INSTANT_RATE_SYNC_TIME, + gst_structure_new_id (GST_QUARK (EVENT_INSTANT_RATE_SYNC_TIME), + GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier, + GST_QUARK (RUNNING_TIME), GST_TYPE_CLOCK_TIME, running_time, + GST_QUARK (UPSTREAM_RUNNING_TIME), GST_TYPE_CLOCK_TIME, + upstream_running_time, NULL)); + + return event; +} + +/** + * gst_event_parse_instant_rate_sync_time: + * @event: a #GstEvent of type #GST_EVENT_INSTANT_RATE_CHANGE + * @rate_multiplier: (out) (allow-none): location where to store the rate of + * the instant-rate-sync-time event, or %NULL + * @running_time: (out) (allow-none): location in which to store the running time + * of the instant-rate-sync-time event, or %NULL + * @upstream_running_time: (out) (allow-none): location in which to store the + * upstream running time of the instant-rate-sync-time event, or %NULL + * + * Extract the rate multiplier and running times from an instant-rate-sync-time event. + * + * Since: 1.18 + */ +void +gst_event_parse_instant_rate_sync_time (GstEvent * event, + gdouble * rate_multiplier, GstClockTime * running_time, + GstClockTime * upstream_running_time) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_SYNC_TIME); + + structure = GST_EVENT_STRUCTURE (event); + gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE, + rate_multiplier, GST_QUARK (RUNNING_TIME), GST_TYPE_CLOCK_TIME, + running_time, GST_QUARK (UPSTREAM_RUNNING_TIME), GST_TYPE_CLOCK_TIME, + upstream_running_time, NULL); +} diff --git a/gst/gstevent.h b/gst/gstevent.h index c3db309316..2a6089f5c9 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -123,6 +123,9 @@ typedef enum { * 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_INSTANT_RATE_SYNC_TIME: Sent by the pipeline to notify elements that handle the + * instant-rate-change event about the running-time when + * the rate multiplier should be applied (or was applied). (Since: 1.18) * @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event * @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the * data flow. @@ -169,14 +172,15 @@ typedef enum { 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)), - GST_EVENT_NAVIGATION = GST_EVENT_MAKE_TYPE (210, FLAG(UPSTREAM)), - GST_EVENT_LATENCY = GST_EVENT_MAKE_TYPE (220, FLAG(UPSTREAM)), - GST_EVENT_STEP = GST_EVENT_MAKE_TYPE (230, FLAG(UPSTREAM)), - GST_EVENT_RECONFIGURE = GST_EVENT_MAKE_TYPE (240, FLAG(UPSTREAM)), - GST_EVENT_TOC_SELECT = GST_EVENT_MAKE_TYPE (250, FLAG(UPSTREAM)), - GST_EVENT_SELECT_STREAMS = GST_EVENT_MAKE_TYPE (260, FLAG(UPSTREAM)), + GST_EVENT_QOS = GST_EVENT_MAKE_TYPE (190, FLAG(UPSTREAM)), + GST_EVENT_SEEK = GST_EVENT_MAKE_TYPE (200, FLAG(UPSTREAM)), + GST_EVENT_NAVIGATION = GST_EVENT_MAKE_TYPE (210, FLAG(UPSTREAM)), + GST_EVENT_LATENCY = GST_EVENT_MAKE_TYPE (220, FLAG(UPSTREAM)), + GST_EVENT_STEP = GST_EVENT_MAKE_TYPE (230, FLAG(UPSTREAM)), + GST_EVENT_RECONFIGURE = GST_EVENT_MAKE_TYPE (240, FLAG(UPSTREAM)), + GST_EVENT_TOC_SELECT = GST_EVENT_MAKE_TYPE (250, FLAG(UPSTREAM)), + GST_EVENT_SELECT_STREAMS = GST_EVENT_MAKE_TYPE (260, FLAG(UPSTREAM)), + GST_EVENT_INSTANT_RATE_SYNC_TIME = GST_EVENT_MAKE_TYPE (261, FLAG(UPSTREAM)), /* custom events start here */ GST_EVENT_CUSTOM_UPSTREAM = GST_EVENT_MAKE_TYPE (270, FLAG(UPSTREAM)), @@ -745,6 +749,19 @@ GST_API void gst_event_parse_instant_rate_change (GstEvent *event, gdouble *rate_multiplier, GstSegmentFlags *new_flags); +/* instant-rate-change-sync-time event */ + +GST_API +GstEvent * gst_event_new_instant_rate_sync_time (gdouble rate, + GstClockTime running_time, + GstClockTime upstream_running_time) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_instant_rate_sync_time (GstEvent *event, + gdouble *rate, + GstClockTime *running_time, + GstClockTime *upstream_running_time); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEvent, gst_event_unref) G_END_DECLS diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 8429252d45..4ce08a4146 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -112,6 +112,7 @@ static GstMessageQuarks message_quarks[] = { {GST_MESSAGE_STREAM_COLLECTION, "stream-collection", 0}, {GST_MESSAGE_STREAMS_SELECTED, "streams-selected", 0}, {GST_MESSAGE_REDIRECT, "redirect", 0}, + {GST_MESSAGE_INSTANT_RATE_REQUEST, "instant-rate-request", 0}, {0, NULL, 0} }; @@ -3266,3 +3267,59 @@ gst_message_get_num_redirect_entries (GstMessage * message) return size; } + +/** + * gst_message_new_instant_rate_request: + * @src: The #GstObject that posted the message + * @rate_multiplier: the rate multiplier factor that should be applied + * + * Creates a new instant-rate-request message. Elements handling the + * instant-rate-change event must post this message. The message is + * handled at the pipeline, and allows the pipeline to select the + * running time when the rate change should happen and to send an + * @GST_EVENT_INSTANT_RATE_SYNC_TIME event to notify the elements + * in the pipeline. + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.18 + */ +GstMessage * +gst_message_new_instant_rate_request (GstObject * src, gdouble rate_multiplier) +{ + GstStructure *structure; + GstMessage *message; + + g_return_val_if_fail (rate_multiplier != 0.0, NULL); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_INSTANT_RATE_REQUEST), + GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier, NULL); + message = + gst_message_new_custom (GST_MESSAGE_INSTANT_RATE_REQUEST, src, structure); + + return message; +} + +/** + * gst_message_parse_instant_rate_request: + * @message: a #GstMessage of type %GST_MESSAGE_INSTANT_RATE_REQUEST + * @rate_multiplier: (out) (allow-none): return location for the rate, or %NULL + * + * Parses the rate_multiplier from the instant-rate-request message. + * + * Since: 1.18 + */ +void +gst_message_parse_instant_rate_request (GstMessage * message, + gdouble * rate_multiplier) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == + GST_MESSAGE_INSTANT_RATE_REQUEST); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE, + rate_multiplier, NULL); +} diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 9b46a2e430..69013e853d 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -121,6 +121,9 @@ typedef struct _GstMessage GstMessage; * response is received with a non-HTTP URL inside. (Since: 1.10) * @GST_MESSAGE_DEVICE_CHANGED: Message indicating a #GstDevice was changed * a #GstDeviceProvider (Since: 1.16) + * @GST_MESSAGE_INSTANT_RATE_REQUEST: Message sent by elements to request the + * running time from the pipeline when an instant rate change should + * be applied (which may be in the past when the answer arrives). (Since: 1.18) * @GST_MESSAGE_ANY: mask for all of the above messages. * * The different message types that are available. @@ -174,6 +177,7 @@ typedef enum GST_MESSAGE_STREAMS_SELECTED = GST_MESSAGE_EXTENDED + 5, GST_MESSAGE_REDIRECT = GST_MESSAGE_EXTENDED + 6, GST_MESSAGE_DEVICE_CHANGED = GST_MESSAGE_EXTENDED + 7, + GST_MESSAGE_INSTANT_RATE_REQUEST = GST_MESSAGE_EXTENDED + 8, GST_MESSAGE_ANY = (gint) (0xffffffff) } GstMessageType; @@ -869,6 +873,13 @@ void gst_message_parse_redirect_entry (GstMessage * message, gsiz GST_API gsize gst_message_get_num_redirect_entries (GstMessage * message); +/* INSTANT_RATE_REQUEST */ + +GST_API +GstMessage * gst_message_new_instant_rate_request (GstObject * src, gdouble rate_multiplier) G_GNUC_MALLOC; +GST_API +void gst_message_parse_instant_rate_request (GstMessage * message, gdouble * rate_multiplier); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMessage, gst_message_unref) G_END_DECLS diff --git a/gst/gstquark.c b/gst/gstquark.c index 8c689db8f8..fe00e7bf89 100644 --- a/gst/gstquark.c +++ b/gst/gstquark.c @@ -78,6 +78,8 @@ static const gchar *_quark_strings[] = { "GstEventStreamGroupDone", "GstQueryBitrate", "nominal-bitrate", "GstMessageDeviceChanged", "device-changed", "trickmode-interval", "GstEventInstantRateChange", + "GstEventInstantRateSyncTime", "GstMessageInstantRateRequest", + "upstream-running-time" }; GQuark _priv_gst_quark_table[GST_QUARK_MAX]; diff --git a/gst/gstquark.h b/gst/gstquark.h index fa5535127c..3a90f85143 100644 --- a/gst/gstquark.h +++ b/gst/gstquark.h @@ -223,7 +223,10 @@ typedef enum _GstQuarkId GST_QUARK_DEVICE_CHANGED = 192, GST_QUARK_TRICKMODE_INTERVAL = 193, GST_QUARK_EVENT_INSTANT_RATE_CHANGE = 194, - GST_QUARK_MAX = 195 + GST_QUARK_EVENT_INSTANT_RATE_SYNC_TIME = 195, + GST_QUARK_MESSAGE_INSTANT_RATE_REQUEST = 196, + GST_QUARK_UPSTREAM_RUNNING_TIME = 197, + GST_QUARK_MAX = 198 } GstQuarkId; extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];