mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
message: add QoS message to inform apps of lost data
This has been implemented as per part-qos.txt and partially addresses bug #322947
This commit is contained in:
parent
9cc1b172c2
commit
1a3257132d
7 changed files with 315 additions and 2 deletions
|
@ -1167,6 +1167,12 @@ gst_message_parse_async_start
|
|||
gst_message_new_async_done
|
||||
gst_message_new_step_start
|
||||
gst_message_parse_step_start
|
||||
gst_message_new_qos
|
||||
gst_message_set_qos_values
|
||||
gst_message_set_qos_stats
|
||||
gst_message_parse_qos
|
||||
gst_message_parse_qos_values
|
||||
gst_message_parse_qos_stats
|
||||
|
||||
GstStructureChangeType
|
||||
gst_message_new_structure_change
|
||||
|
|
213
gst/gstmessage.c
213
gst/gstmessage.c
|
@ -111,6 +111,7 @@ static GstMessageQuarks message_quarks[] = {
|
|||
{GST_MESSAGE_ASYNC_DONE, "async-done", 0},
|
||||
{GST_MESSAGE_REQUEST_STATE, "request-state", 0},
|
||||
{GST_MESSAGE_STEP_START, "step-start", 0},
|
||||
{GST_MESSAGE_QOS, "qos", 0},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -1793,3 +1794,215 @@ gst_message_parse_step_start (GstMessage * message, gboolean * active,
|
|||
GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
|
||||
GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_new_qos:
|
||||
* @src: The object originating the message.
|
||||
* @live: if the message was generated by a live element
|
||||
* @running_time: the running time of the buffer that generated the message
|
||||
* @stream_time: the stream time of the buffer that generated the message
|
||||
* @timestamp: the timestamps of the buffer that generated the message
|
||||
* @duration: the duration of the buffer that generated the message
|
||||
*
|
||||
* A QOS message is posted on the bus whenever an element decides to:
|
||||
*
|
||||
* - drop a buffer because of QoS reasons
|
||||
* - change its processing strategy because of QoS reasons (quality)
|
||||
*
|
||||
* This message can be posted by an element that performs synchronisation against the
|
||||
* clock (live) or it could be dropped by an element that performs QoS because of QOS
|
||||
* events received from a downstream element (!live).
|
||||
*
|
||||
* @running_time, @stream_time, @timestamp, @duration should be set to the
|
||||
* respective running-time, stream-time, timestamp and duration of the (dropped)
|
||||
* buffer that generated the QoS event. Values can be left to
|
||||
* GST_CLOCK_TIME_NONE when unknown.
|
||||
*
|
||||
* Returns: The new qos message.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 0.10.29
|
||||
*/
|
||||
GstMessage *
|
||||
gst_message_new_qos (GstObject * src, gboolean live, guint64 running_time,
|
||||
guint64 stream_time, guint64 timestamp, guint64 duration)
|
||||
{
|
||||
GstMessage *message;
|
||||
GstStructure *structure;
|
||||
|
||||
structure = gst_structure_id_new (GST_QUARK (MESSAGE_QOS),
|
||||
GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
|
||||
GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
|
||||
GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
|
||||
GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp,
|
||||
GST_QUARK (DURATION), G_TYPE_UINT64, duration,
|
||||
GST_QUARK (JITTER), G_TYPE_INT64, (gint64) 0,
|
||||
GST_QUARK (PROPORTION), G_TYPE_DOUBLE, (gdouble) 1.0,
|
||||
GST_QUARK (QUALITY), G_TYPE_INT, (gint) 1000000,
|
||||
GST_QUARK (FORMAT), GST_TYPE_FORMAT, GST_FORMAT_UNDEFINED,
|
||||
GST_QUARK (PROCESSED), G_TYPE_UINT64, (guint64) - 1,
|
||||
GST_QUARK (DROPPED), G_TYPE_UINT64, (guint64) - 1, NULL);
|
||||
message = gst_message_new_custom (GST_MESSAGE_QOS, src, structure);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_set_qos_values:
|
||||
* @message: A valid #GstMessage of type GST_MESSAGE_QOS.
|
||||
* @jitter: The difference of the running-time against the deadline.
|
||||
* @proportion: Long term prediction of the ideal rate relative to normal rate
|
||||
* to get optimal quality.
|
||||
* @quality: An element dependent integer value that specifies the current
|
||||
* quality level of the element. The default maximum quality is 1000000.
|
||||
*
|
||||
* Set the QoS values that have been calculated/analysed from the QoS data
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 0.10.29
|
||||
*/
|
||||
void
|
||||
gst_message_set_qos_values (GstMessage * message, gint64 jitter,
|
||||
gdouble proportion, gint quality)
|
||||
{
|
||||
g_return_if_fail (GST_IS_MESSAGE (message));
|
||||
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
|
||||
|
||||
gst_structure_id_set (message->structure,
|
||||
GST_QUARK (JITTER), G_TYPE_INT64, jitter,
|
||||
GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
|
||||
GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_set_qos_stats:
|
||||
* @message: A valid #GstMessage of type GST_MESSAGE_QOS.
|
||||
* @format: Units of the 'processed' and 'dropped' fields. Video sinks and video
|
||||
* filters will use GST_FORMAT_BUFFERS (frames). Audio sinks and audio filters
|
||||
* will likely use GST_FORMAT_DEFAULT (samples).
|
||||
* @processed: Total number of units correctly processed since the last state
|
||||
* change to READY or a flushing operation.
|
||||
* @dropped: Total number of units dropped since the last state change to READY
|
||||
* or a flushing operation.
|
||||
*
|
||||
* Set the QoS stats representing the history of the current continuous pipeline
|
||||
* playback period.
|
||||
*
|
||||
* When @format is @GST_FORMAT_UNDEFINED both @dropped and @processed are
|
||||
* invalid. Values of -1 for either @processed or @dropped mean unknown values.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 0.10.29
|
||||
*/
|
||||
void
|
||||
gst_message_set_qos_stats (GstMessage * message, GstFormat format,
|
||||
guint64 processed, guint64 dropped)
|
||||
{
|
||||
g_return_if_fail (GST_IS_MESSAGE (message));
|
||||
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
|
||||
|
||||
gst_structure_id_set (message->structure,
|
||||
GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
|
||||
GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
|
||||
GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_parse_qos:
|
||||
* @message: A valid #GstMessage of type GST_MESSAGE_QOS.
|
||||
* @live: if the message was generated by a live element
|
||||
* @running_time: the running time of the buffer that generated the message
|
||||
* @stream_time: the stream time of the buffer that generated the message
|
||||
* @timestamp: the timestamps of the buffer that generated the message
|
||||
* @duration: the duration of the buffer that generated the message
|
||||
*
|
||||
* Extract the timestamps and live status from the QoS message.
|
||||
*
|
||||
* The returned values give the running_time, stream_time, timestamp and
|
||||
* duration of the dropped buffer. Values of GST_CLOCK_TIME_NONE mean unknown
|
||||
* values.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 0.10.29
|
||||
*/
|
||||
void
|
||||
gst_message_parse_qos (GstMessage * message, gboolean * live,
|
||||
guint64 * running_time, guint64 * stream_time, guint64 * timestamp,
|
||||
guint64 * duration)
|
||||
{
|
||||
g_return_if_fail (GST_IS_MESSAGE (message));
|
||||
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
|
||||
|
||||
gst_structure_id_get (message->structure,
|
||||
GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
|
||||
GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
|
||||
GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
|
||||
GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp,
|
||||
GST_QUARK (DURATION), G_TYPE_UINT64, duration, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_parse_qos_values:
|
||||
* @message: A valid #GstMessage of type GST_MESSAGE_QOS.
|
||||
* @jitter: The difference of the running-time against the deadline.
|
||||
* @proportion: Long term prediction of the ideal rate relative to normal rate
|
||||
* to get optimal quality.
|
||||
* @quality: An element dependent integer value that specifies the current
|
||||
* quality level of the element. The default maximum quality is 1000000.
|
||||
*
|
||||
* Extract the QoS values that have been calculated/analysed from the QoS data
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 0.10.29
|
||||
*/
|
||||
void
|
||||
gst_message_parse_qos_values (GstMessage * message, gint64 * jitter,
|
||||
gdouble * proportion, gint * quality)
|
||||
{
|
||||
g_return_if_fail (GST_IS_MESSAGE (message));
|
||||
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
|
||||
|
||||
gst_structure_id_get (message->structure,
|
||||
GST_QUARK (JITTER), G_TYPE_INT64, jitter,
|
||||
GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
|
||||
GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_parse_qos_stats:
|
||||
* @message: A valid #GstMessage of type GST_MESSAGE_QOS.
|
||||
* @format: Units of the 'processed' and 'dropped' fields. Video sinks and video
|
||||
* filters will use GST_FORMAT_BUFFERS (frames). Audio sinks and audio filters
|
||||
* will likely use GST_FORMAT_DEFAULT (samples).
|
||||
* @processed: Total number of units correctly processed since the last state
|
||||
* change to READY or a flushing operation.
|
||||
* @dropped: Total number of units dropped since the last state change to READY
|
||||
* or a flushing operation.
|
||||
*
|
||||
* Extract the QoS stats representing the history of the current continuous
|
||||
* pipeline playback period.
|
||||
*
|
||||
* When @format is @GST_FORMAT_UNDEFINED both @dropped and @processed are
|
||||
* invalid. Values of -1 for either @processed or @dropped mean unknown values.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Since: 0.10.29
|
||||
*/
|
||||
void
|
||||
gst_message_parse_qos_stats (GstMessage * message, GstFormat * format,
|
||||
guint64 * processed, guint64 * dropped)
|
||||
{
|
||||
g_return_if_fail (GST_IS_MESSAGE (message));
|
||||
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
|
||||
|
||||
gst_structure_id_get (message->structure,
|
||||
GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
|
||||
GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
|
||||
GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
|
||||
}
|
||||
|
|
|
@ -86,6 +86,8 @@ typedef struct _GstMessageClass GstMessageClass;
|
|||
* change state. This message is a suggestion to the application which can
|
||||
* decide to perform the state change on (part of) the pipeline. Since: 0.10.23.
|
||||
* @GST_MESSAGE_STEP_START: A stepping operation was started.
|
||||
* @GST_MESSAGE_QOS: A buffer was dropped or an element changed its processing
|
||||
* strategy for Quality of Service reasons.
|
||||
* @GST_MESSAGE_ANY: mask for all of the above messages.
|
||||
*
|
||||
* The different message types that are available.
|
||||
|
@ -120,6 +122,7 @@ typedef enum
|
|||
GST_MESSAGE_ASYNC_DONE = (1 << 21),
|
||||
GST_MESSAGE_REQUEST_STATE = (1 << 22),
|
||||
GST_MESSAGE_STEP_START = (1 << 23),
|
||||
GST_MESSAGE_QOS = (1 << 24),
|
||||
GST_MESSAGE_ANY = ~0
|
||||
} GstMessageType;
|
||||
|
||||
|
@ -474,6 +477,20 @@ void gst_message_parse_step_start (GstMessage * message, gboolean
|
|||
guint64 *amount, gdouble *rate, gboolean *flush,
|
||||
gboolean *intermediate);
|
||||
|
||||
/* QOS */
|
||||
GstMessage * gst_message_new_qos (GstObject * src, gboolean live, guint64 running_time,
|
||||
guint64 stream_time, guint64 timestamp, guint64 duration);
|
||||
void gst_message_set_qos_values (GstMessage * message, gint64 jitter, gdouble proportion,
|
||||
gint quality);
|
||||
void gst_message_set_qos_stats (GstMessage * message, GstFormat format, guint64 processed,
|
||||
guint64 dropped);
|
||||
void gst_message_parse_qos (GstMessage * message, gboolean * live, guint64 * running_time,
|
||||
guint64 * stream_time, guint64 * timestamp, guint64 * duration);
|
||||
void gst_message_parse_qos_values (GstMessage * message, gint64 * jitter, gdouble * proportion,
|
||||
gint * quality);
|
||||
void gst_message_parse_qos_stats (GstMessage * message, GstFormat * format, guint64 * processed,
|
||||
guint64 * dropped);
|
||||
|
||||
/* custom messages */
|
||||
GstMessage * gst_message_new_custom (GstMessageType type,
|
||||
GstObject * src,
|
||||
|
|
|
@ -48,7 +48,8 @@ static const gchar *_quark_strings[] = {
|
|||
"GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering",
|
||||
"GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush",
|
||||
"intermediate", "GstMessageStepStart", "active", "eos", "sink-message",
|
||||
"message"
|
||||
"message", "GstMessageQOS", "running-time", "stream-time", "jitter",
|
||||
"quality", "processed", "dropped"
|
||||
};
|
||||
|
||||
GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
|
@ -119,8 +119,15 @@ typedef enum _GstQuarkId
|
|||
GST_QUARK_EOS = 90,
|
||||
GST_QUARK_EVENT_SINK_MESSAGE = 91,
|
||||
GST_QUARK_MESSAGE = 92,
|
||||
GST_QUARK_MESSAGE_QOS = 93,
|
||||
GST_QUARK_RUNNING_TIME = 94,
|
||||
GST_QUARK_STREAM_TIME = 95,
|
||||
GST_QUARK_JITTER = 96,
|
||||
GST_QUARK_QUALITY = 97,
|
||||
GST_QUARK_PROCESSED = 98,
|
||||
GST_QUARK_DROPPED = 99,
|
||||
|
||||
GST_QUARK_MAX = 93
|
||||
GST_QUARK_MAX = 100
|
||||
} GstQuarkId;
|
||||
|
||||
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
|
@ -257,6 +257,69 @@ GST_START_TEST (test_parsing)
|
|||
gst_message_parse_request_state (message, &state);
|
||||
fail_unless (state == GST_STATE_PAUSED);
|
||||
|
||||
gst_message_unref (message);
|
||||
}
|
||||
/* GST_MESSAGE_QOS */
|
||||
{
|
||||
gboolean live;
|
||||
GstClockTime running_time;
|
||||
GstClockTime stream_time;
|
||||
GstClockTime timestamp, duration;
|
||||
gint64 jitter;
|
||||
gdouble proportion;
|
||||
gint quality;
|
||||
GstFormat format;
|
||||
guint64 processed;
|
||||
guint64 dropped;
|
||||
|
||||
running_time = 1 * GST_SECOND;
|
||||
stream_time = 2 * GST_SECOND;
|
||||
timestamp = 3 * GST_SECOND;
|
||||
duration = 4 * GST_SECOND;
|
||||
|
||||
message =
|
||||
gst_message_new_qos (NULL, TRUE, running_time, stream_time, timestamp,
|
||||
duration);
|
||||
fail_if (message == NULL);
|
||||
fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
|
||||
fail_unless (GST_MESSAGE_SRC (message) == NULL);
|
||||
|
||||
/* check defaults */
|
||||
gst_message_parse_qos_values (message, &jitter, &proportion, &quality);
|
||||
fail_unless (jitter == 0);
|
||||
fail_unless (proportion == 1.0);
|
||||
fail_unless (quality == 1000000);
|
||||
|
||||
gst_message_parse_qos_stats (message, &format, &processed, &dropped);
|
||||
fail_unless (format == GST_FORMAT_UNDEFINED);
|
||||
fail_unless (processed == -1);
|
||||
fail_unless (dropped == -1);
|
||||
|
||||
/* set some wrong values to check if the parse method overwrites them
|
||||
* with the good values */
|
||||
running_time = stream_time = timestamp = duration = 5 * GST_SECOND;
|
||||
live = FALSE;
|
||||
gst_message_parse_qos (message, &live, &running_time, &stream_time,
|
||||
×tamp, &duration);
|
||||
fail_unless (live == TRUE);
|
||||
fail_unless (running_time == 1 * GST_SECOND);
|
||||
fail_unless (stream_time == 2 * GST_SECOND);
|
||||
fail_unless (timestamp == 3 * GST_SECOND);
|
||||
fail_unless (duration == 4 * GST_SECOND);
|
||||
|
||||
/* change some values */
|
||||
gst_message_set_qos_values (message, -10, 2.0, 5000);
|
||||
gst_message_parse_qos_values (message, &jitter, &proportion, &quality);
|
||||
fail_unless (jitter == -10);
|
||||
fail_unless (proportion == 2.0);
|
||||
fail_unless (quality == 5000);
|
||||
|
||||
gst_message_set_qos_stats (message, GST_FORMAT_DEFAULT, 1030, 65);
|
||||
gst_message_parse_qos_stats (message, &format, &processed, &dropped);
|
||||
fail_unless (format == GST_FORMAT_DEFAULT);
|
||||
fail_unless (processed == 1030);
|
||||
fail_unless (dropped == 65);
|
||||
|
||||
gst_message_unref (message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -496,6 +496,7 @@ EXPORTS
|
|||
gst_message_new_info
|
||||
gst_message_new_latency
|
||||
gst_message_new_new_clock
|
||||
gst_message_new_qos
|
||||
gst_message_new_request_state
|
||||
gst_message_new_segment_done
|
||||
gst_message_new_segment_start
|
||||
|
@ -517,6 +518,9 @@ EXPORTS
|
|||
gst_message_parse_error
|
||||
gst_message_parse_info
|
||||
gst_message_parse_new_clock
|
||||
gst_message_parse_qos
|
||||
gst_message_parse_qos_stats
|
||||
gst_message_parse_qos_values
|
||||
gst_message_parse_request_state
|
||||
gst_message_parse_segment_done
|
||||
gst_message_parse_segment_start
|
||||
|
@ -529,6 +533,8 @@ EXPORTS
|
|||
gst_message_parse_tag_full
|
||||
gst_message_parse_warning
|
||||
gst_message_set_buffering_stats
|
||||
gst_message_set_qos_stats
|
||||
gst_message_set_qos_values
|
||||
gst_message_set_seqnum
|
||||
gst_message_set_stream_status_object
|
||||
gst_message_type_get_name
|
||||
|
|
Loading…
Reference in a new issue