docs/design/part-TODO.txt: Remove item from the todo list because it was fixed with the latency state change rewrites.

Original commit message from CVS:
* docs/design/part-TODO.txt:
Remove item from the todo list because it was fixed with the latency
state change rewrites.
* docs/design/part-seeking.txt:
* docs/design/part-segments.txt:
Update some docs.
* gst/gstevent.c: (gst_event_new_new_segment_full),
(gst_event_parse_new_segment_full), (gst_event_new_buffer_size),
(gst_event_parse_buffer_size), (gst_event_new_qos),
(gst_event_parse_qos), (gst_event_new_seek),
(gst_event_parse_seek), (gst_event_new_latency),
(gst_event_parse_latency):
Use quarks to construct and parse events.
* gst/gstquark.c: (_priv_gst_quarks_initialize):
* gst/gstquark.h:
Add some more quarks to the table.
Emit a warning when the quark tables are not in sync.
* tests/check/gst/gstbus.c: (GST_START_TEST):
Add an assert.
This commit is contained in:
Wim Taymans 2008-10-13 17:19:25 +00:00
parent 35a2a49c00
commit 97ec47cabb
8 changed files with 224 additions and 89 deletions

View file

@ -1,3 +1,29 @@
2008-10-13 Wim Taymans <wim.taymans@collabora.co.uk>
* docs/design/part-TODO.txt:
Remove item from the todo list because it was fixed with the latency
state change rewrites.
* docs/design/part-seeking.txt:
* docs/design/part-segments.txt:
Update some docs.
* gst/gstevent.c: (gst_event_new_new_segment_full),
(gst_event_parse_new_segment_full), (gst_event_new_buffer_size),
(gst_event_parse_buffer_size), (gst_event_new_qos),
(gst_event_parse_qos), (gst_event_new_seek),
(gst_event_parse_seek), (gst_event_new_latency),
(gst_event_parse_latency):
Use quarks to construct and parse events.
* gst/gstquark.c: (_priv_gst_quarks_initialize):
* gst/gstquark.h:
Add some more quarks to the table.
Emit a warning when the quark tables are not in sync.
* tests/check/gst/gstbus.c: (GST_START_TEST):
Add an assert.
2008-10-13 Stefan Kost <ensonic@users.sf.net> 2008-10-13 Stefan Kost <ensonic@users.sf.net>
* plugins/elements/Makefile.am: * plugins/elements/Makefile.am:

View file

@ -59,12 +59,6 @@ API/ABI
- Make serialisation of structures more consistent, readable and nicer code-wise. - Make serialisation of structures more consistent, readable and nicer code-wise.
- When a seekable live source does a flushing seek, it needs a new base_time to
timestamp new data. The pipeline however does not know that there is a live
source in the pipeline and thus does not select a new base_time automatically.
There needs to be a mechanism for a live source to request a new base_time or
pipeline restart.
- pad block has several issues: - pad block has several issues:
* can't block on selected things, like push, pull, pad_alloc, events, ... * can't block on selected things, like push, pull, pad_alloc, events, ...
* can't check why the block happened. We should also be able to get the item/ * can't check why the block happened. We should also be able to get the item/

View file

@ -2,46 +2,63 @@ Seeking
------- -------
Seeking in GStreamer means configuring the pipeline for playback of the Seeking in GStreamer means configuring the pipeline for playback of the
media between a certain start and stop time, called a segment. media between a certain start and stop time, called a segment. By default a
pipeline will play from position 0 to the total duration of the media at a rate
of 1.0.
Different kinds of seeking exist: A seek is performed by sending a seek event to the sink elements of a
pipeline. Sending the seek event to a bin will by default forward
the event to all sinks in the bin.
- immediate seeking with low latency (FLUSH seek) When performing a seek, the start and stop values of the segment can be
- seeking without flush, playback will start from the new specified as absoulte positions or relative to the currently configured
position after all the queues are emptied with old data. playback segment. Note that it is not possible to seek relative to the current
- segment seeking with and without FLUSH, this can be used to playback position.
implement seamless looping or NLE functionality.
Feedback of the seek operation can be immediatly using the GST_SEEK_FLAG_FLUSH
flag. With this flag, all pending data in the pipeline is discarded and playback
starts from the new position immediatly.
When the FLUSH flag is not set, the seek will be queued and executed as
soon as possible, which might be after all queues are emptied.
Seeking can be performed in different formats such as time, frames Seeking can be performed in different formats such as time, frames
or samples. or samples.
Seeking can be performed to an absolute position or relative to the The seeking can be performed to a nearby key unit or to the exact
currently configured segment. (estimated) unit in the media (GST_SEEK_FLAG_KEY_UNIT).
For seeking to work reliably, all plugins in the pipeline need to follow The seeking can be performed by using an estimated target position or in an
the well-defined rules in this document. accurate way (GST_SEEK_FLAG_ACCURATE). For some formats this can result in
having to scan the complete file in order to accurately find the target unit.
Non segment seeking will make the pipeline emit EOS when the configured Non segment seeking will make the pipeline emit EOS when the configured
segment has been played. segment has been played.
Segment seeking will not emit an EOS at the end of the range but will Segment seeking (using the GST_SEEK_FLAG_SEGMENT) will not emit an EOS at
post a SEGMENT_DONE message on the bus. This message is posted by the the end of the playback segment but will post a SEGMENT_DONE message on the
earliest element in the pipeline, typically a demuxer. After receiving bus. This message is posted by the element driving the playback in the
the message, the application can reconnect the pipeline or issue other pipeline, typically a demuxer. After receiving the message, the application
seek events in the pipeline. Since the message is posted as early as can reconnect the pipeline or issue other seek events in the pipeline.
possible in the pipeline, the application has some time to issue a new Since the message is posted as early as possible in the pipeline, the
seek to make the transition seamless. Typically the allowed delay is application has some time to issue a new seek to make the transition seamless.
defined by the buffer sizes of the sinks as well as the size of any Typically the allowed delay is defined by the buffer sizes of the sinks as well
queues in the pipeline. as the size of any queues in the pipeline.
The seek can also change the playback speed of the configured segment. The seek can also change the playback speed of the configured segment.
A speed of 1.0 is normal speed, 2.0 is double speed. Negative values A speed of 1.0 is normal speed, 2.0 is double speed. Negative values
mean backward playback. mean backward playback.
When performing a seek with a playback rate different from 1.0, the
GST_SEEK_FLAG_SKIP flag can be used to instruct decoders and demuxers that they
are allowed to skip decoding. This can be useful when resource consumption is
more important than accurately producing all frames.
Generating seeking events Generating seeking events
------------------------- -------------------------
A seek event is created with gst_event_new_seek ().

View file

@ -38,6 +38,13 @@ Use case: FLUSHING seek
When doing a seek in this pipeline for a segment 1 to 5 seconds, avidemux When doing a seek in this pipeline for a segment 1 to 5 seconds, avidemux
will perform the seek. will perform the seek.
Avidemux starts by sending a FLUSH_START event downstream and upstream. This
will cause its streaming task to PAUSED because _pad_pull_range() and
_pad_push() will return WRONG_STATE. It then waits for the STREAM_LOCK,
which will be unlocked when the streaming task pauses. At this point no
streaming is happening anymore in the pipeline and a FLUSH_STOP is sent
upstream and downstream.
When avidemux starts playback of the segment from second 1 to 5, it pushes When avidemux starts playback of the segment from second 1 to 5, it pushes
out a newsegment with 1 and 5 as start and stop times. The stream_time in out a newsegment with 1 and 5 as start and stop times. The stream_time in
the newsegment is also 1 as this is the position we seek to. the newsegment is also 1 as this is the position we seek to.
@ -57,18 +64,21 @@ Use case: FLUSHING seek
When it reaches timestamp 5, it does not decode and push frames anymore. When it reaches timestamp 5, it does not decode and push frames anymore.
The video sink receives a frame of timestamp 1. It takes the start value of The video sink receives a frame of timestamp 1. It takes the start value of
the previous newsegment and aplies the folowing formula: the previous newsegment and aplies the folowing (simplified) formula:
render_time = BUFFER_TIMESTAMP - segment_start + element->base_time render_time = BUFFER_TIMESTAMP - segment_start + element->base_time
It then syncs against the clock with this render_time. Not that It then syncs against the clock with this render_time. Note that
BUFFER_TIMESTAMP is always >= segment_start or else it would fall outside of BUFFER_TIMESTAMP is always >= segment_start or else it would fall outside of
the configure segment. the configure segment.
Videosink reports its current position as: Videosink reports its current position as (simplified):
current_position = clock_time - element->base_time + segment_time current_position = clock_time - element->base_time + segment_time
See part-synchronisation.txt for a more detailed and accurate explanation of
synchronisation and position reporting.
Since after a flushing seek the stream_time is reset to 0, the new buffer Since after a flushing seek the stream_time is reset to 0, the new buffer
will be rendered immediatly after the seek and the current_position will be will be rendered immediatly after the seek and the current_position will be
the stream_time of the seek that was performed. the stream_time of the seek that was performed.

View file

@ -83,6 +83,7 @@
#include "gstevent.h" #include "gstevent.h"
#include "gstenumtypes.h" #include "gstenumtypes.h"
#include "gstutils.h" #include "gstutils.h"
#include "gstquark.h"
static void gst_event_init (GTypeInstance * instance, gpointer g_class); static void gst_event_init (GTypeInstance * instance, gpointer g_class);
static void gst_event_class_init (gpointer g_class, gpointer class_data); static void gst_event_class_init (gpointer g_class, gpointer class_data);
@ -545,6 +546,9 @@ gst_event_new_new_segment_full (gboolean update, gdouble rate,
gdouble applied_rate, GstFormat format, gint64 start, gint64 stop, gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
gint64 position) gint64 position)
{ {
GstEvent *event;
GstStructure *structure;
g_return_val_if_fail (rate != 0.0, NULL); g_return_val_if_fail (rate != 0.0, NULL);
g_return_val_if_fail (applied_rate != 0.0, NULL); g_return_val_if_fail (applied_rate != 0.0, NULL);
@ -568,15 +572,18 @@ gst_event_new_new_segment_full (gboolean update, gdouble rate,
if (stop != -1) if (stop != -1)
g_return_val_if_fail (start <= stop, NULL); g_return_val_if_fail (start <= stop, NULL);
return gst_event_new_custom (GST_EVENT_NEWSEGMENT, structure = gst_structure_empty_new ("GstEventNewsegment");
gst_structure_new ("GstEventNewsegment", gst_structure_id_set (structure,
"update", G_TYPE_BOOLEAN, update, GST_QUARK (UPDATE), G_TYPE_BOOLEAN, update,
"rate", G_TYPE_DOUBLE, rate, GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
"applied_rate", G_TYPE_DOUBLE, applied_rate, GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, applied_rate,
"format", GST_TYPE_FORMAT, format, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
"start", G_TYPE_INT64, start, GST_QUARK (START), G_TYPE_INT64, start,
"stop", G_TYPE_INT64, stop, GST_QUARK (STOP), G_TYPE_INT64, stop,
"position", G_TYPE_INT64, position, NULL)); GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
event = gst_event_new_custom (GST_EVENT_NEWSEGMENT, structure);
return event;
} }
/** /**
@ -609,22 +616,32 @@ gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
structure = gst_event_get_structure (event); structure = gst_event_get_structure (event);
if (G_LIKELY (update)) if (G_LIKELY (update))
*update = *update =
g_value_get_boolean (gst_structure_get_value (structure, "update")); g_value_get_boolean (gst_structure_id_get_value (structure,
GST_QUARK (UPDATE)));
if (G_LIKELY (rate)) if (G_LIKELY (rate))
*rate = g_value_get_double (gst_structure_get_value (structure, "rate")); *rate =
g_value_get_double (gst_structure_id_get_value (structure,
GST_QUARK (RATE)));
if (G_LIKELY (applied_rate)) if (G_LIKELY (applied_rate))
*applied_rate = *applied_rate =
g_value_get_double (gst_structure_get_value (structure, g_value_get_double (gst_structure_id_get_value (structure,
"applied_rate")); GST_QUARK (APPLIED_RATE)));
if (G_LIKELY (format)) if (G_LIKELY (format))
*format = g_value_get_enum (gst_structure_get_value (structure, "format")); *format =
g_value_get_enum (gst_structure_id_get_value (structure,
GST_QUARK (FORMAT)));
if (G_LIKELY (start)) if (G_LIKELY (start))
*start = g_value_get_int64 (gst_structure_get_value (structure, "start")); *start =
g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (START)));
if (G_LIKELY (stop)) if (G_LIKELY (stop))
*stop = g_value_get_int64 (gst_structure_get_value (structure, "stop")); *stop =
g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (STOP)));
if (G_LIKELY (position)) if (G_LIKELY (position))
*position = *position =
g_value_get_int64 (gst_structure_get_value (structure, "position")); g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (POSITION)));
} }
/** /**
@ -679,17 +696,23 @@ GstEvent *
gst_event_new_buffer_size (GstFormat format, gint64 minsize, gst_event_new_buffer_size (GstFormat format, gint64 minsize,
gint64 maxsize, gboolean async) gint64 maxsize, gboolean async)
{ {
GstEvent *event;
GstStructure *structure;
GST_CAT_INFO (GST_CAT_EVENT, GST_CAT_INFO (GST_CAT_EVENT,
"creating buffersize format %s, minsize %" G_GINT64_FORMAT "creating buffersize format %s, minsize %" G_GINT64_FORMAT
", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format), ", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format),
minsize, maxsize, async); minsize, maxsize, async);
return gst_event_new_custom (GST_EVENT_BUFFERSIZE, structure = gst_structure_empty_new ("GstEventBufferSize");
gst_structure_new ("GstEventBufferSize", gst_structure_id_set (structure,
"format", GST_TYPE_FORMAT, format, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
"minsize", G_TYPE_INT64, minsize, GST_QUARK (MINSIZE), G_TYPE_INT64, minsize,
"maxsize", G_TYPE_INT64, maxsize, GST_QUARK (MAXSIZE), G_TYPE_INT64, maxsize,
"async", G_TYPE_BOOLEAN, async, NULL)); GST_QUARK (ASYNC), G_TYPE_BOOLEAN, async, NULL);
event = gst_event_new_custom (GST_EVENT_BUFFERSIZE, structure);
return event;
} }
/** /**
@ -713,15 +736,21 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
structure = gst_event_get_structure (event); structure = gst_event_get_structure (event);
if (format) if (format)
*format = g_value_get_enum (gst_structure_get_value (structure, "format")); *format =
g_value_get_enum (gst_structure_id_get_value (structure,
GST_QUARK (FORMAT)));
if (minsize) if (minsize)
*minsize = *minsize =
g_value_get_int64 (gst_structure_get_value (structure, "minsize")); g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (MINSIZE)));
if (maxsize) if (maxsize)
*maxsize = *maxsize =
g_value_get_int64 (gst_structure_get_value (structure, "maxsize")); g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (MAXSIZE)));
if (async) if (async)
*async = g_value_get_boolean (gst_structure_get_value (structure, "async")); *async =
g_value_get_boolean (gst_structure_id_get_value (structure,
GST_QUARK (ASYNC)));
} }
/** /**
@ -770,6 +799,9 @@ GstEvent *
gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff, gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
GstClockTime timestamp) GstClockTime timestamp)
{ {
GstEvent *event;
GstStructure *structure;
/* diff must be positive or timestamp + diff must be positive */ /* diff must be positive or timestamp + diff must be positive */
g_return_val_if_fail (diff >= 0 || -diff <= timestamp, NULL); g_return_val_if_fail (diff >= 0 || -diff <= timestamp, NULL);
@ -778,11 +810,14 @@ gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
", timestamp %" GST_TIME_FORMAT, proportion, ", timestamp %" GST_TIME_FORMAT, proportion,
diff, GST_TIME_ARGS (timestamp)); diff, GST_TIME_ARGS (timestamp));
return gst_event_new_custom (GST_EVENT_QOS, structure = gst_structure_empty_new ("GstEventQOS");
gst_structure_new ("GstEventQOS", gst_structure_id_set (structure,
"proportion", G_TYPE_DOUBLE, proportion, GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
"diff", G_TYPE_INT64, diff, GST_QUARK (DIFF), G_TYPE_INT64, diff,
"timestamp", G_TYPE_UINT64, timestamp, NULL)); GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, NULL);
event = gst_event_new_custom (GST_EVENT_QOS, structure);
return event;
} }
/** /**
@ -807,12 +842,16 @@ gst_event_parse_qos (GstEvent * event, gdouble * proportion,
structure = gst_event_get_structure (event); structure = gst_event_get_structure (event);
if (proportion) if (proportion)
*proportion = *proportion =
g_value_get_double (gst_structure_get_value (structure, "proportion")); g_value_get_double (gst_structure_id_get_value (structure,
GST_QUARK (PROPORTION)));
if (diff) if (diff)
*diff = g_value_get_int64 (gst_structure_get_value (structure, "diff")); *diff =
g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (DIFF)));
if (timestamp) if (timestamp)
*timestamp = *timestamp =
g_value_get_uint64 (gst_structure_get_value (structure, "timestamp")); g_value_get_uint64 (gst_structure_id_get_value (structure,
GST_QUARK (TIMESTAMP)));
} }
/** /**
@ -841,9 +880,9 @@ gst_event_parse_qos (GstEvent * event, gdouble * proportion,
* configured playback segment can be queried with #GST_QUERY_SEGMENT. * configured playback segment can be queried with #GST_QUERY_SEGMENT.
* *
* @start_type and @stop_type specify how to adjust the currently configured * @start_type and @stop_type specify how to adjust the currently configured
* start and stop fields in @segment. Adjustments can be made relative or * start and stop fields in playback segment. Adjustments can be made relative
* absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE means * or absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE
* that the position should not be updated. * means that the position should not be updated.
* *
* When the rate is positive and @start has been updated, playback will start * When the rate is positive and @start has been updated, playback will start
* from the newly configured start position. * from the newly configured start position.
@ -855,7 +894,7 @@ gst_event_parse_qos (GstEvent * event, gdouble * proportion,
* It is not possible to seek relative to the current playback position, to do * It is not possible to seek relative to the current playback position, to do
* this, PAUSE the pipeline, query the current playback position with * this, PAUSE the pipeline, query the current playback position with
* #GST_QUERY_POSITION and update the playback segment current position with a * #GST_QUERY_POSITION and update the playback segment current position with a
* #GST_SEEK_TYPE_SET to the desired position. * #GST_SEEK_TYPE_SET to the desired position.
* *
* Returns: A new seek event. * Returns: A new seek event.
*/ */
@ -863,6 +902,9 @@ GstEvent *
gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags, gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop) GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop)
{ {
GstEvent *event;
GstStructure *structure;
g_return_val_if_fail (rate != 0.0, NULL); g_return_val_if_fail (rate != 0.0, NULL);
if (format == GST_FORMAT_TIME) { if (format == GST_FORMAT_TIME) {
@ -881,14 +923,18 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
stop); stop);
} }
return gst_event_new_custom (GST_EVENT_SEEK, structure = gst_structure_empty_new ("GstEventSeek");
gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate, gst_structure_id_set (structure,
"format", GST_TYPE_FORMAT, format, GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
"flags", GST_TYPE_SEEK_FLAGS, flags, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
"cur_type", GST_TYPE_SEEK_TYPE, start_type, GST_QUARK (FLAGS), GST_TYPE_SEEK_FLAGS, flags,
"cur", G_TYPE_INT64, start, GST_QUARK (CUR_TYPE), GST_TYPE_SEEK_TYPE, start_type,
"stop_type", GST_TYPE_SEEK_TYPE, stop_type, GST_QUARK (CUR), G_TYPE_INT64, start,
"stop", G_TYPE_INT64, stop, NULL)); GST_QUARK (STOP_TYPE), GST_TYPE_SEEK_TYPE, stop_type,
GST_QUARK (STOP), G_TYPE_INT64, stop, NULL);
event = gst_event_new_custom (GST_EVENT_SEEK, structure);
return event;
} }
/** /**
@ -916,21 +962,33 @@ gst_event_parse_seek (GstEvent * event, gdouble * rate,
structure = gst_event_get_structure (event); structure = gst_event_get_structure (event);
if (rate) if (rate)
*rate = g_value_get_double (gst_structure_get_value (structure, "rate")); *rate =
g_value_get_double (gst_structure_id_get_value (structure,
GST_QUARK (RATE)));
if (format) if (format)
*format = g_value_get_enum (gst_structure_get_value (structure, "format")); *format =
g_value_get_enum (gst_structure_id_get_value (structure,
GST_QUARK (FORMAT)));
if (flags) if (flags)
*flags = g_value_get_flags (gst_structure_get_value (structure, "flags")); *flags =
g_value_get_flags (gst_structure_id_get_value (structure,
GST_QUARK (FLAGS)));
if (start_type) if (start_type)
*start_type = *start_type =
g_value_get_enum (gst_structure_get_value (structure, "cur_type")); g_value_get_enum (gst_structure_id_get_value (structure,
GST_QUARK (CUR_TYPE)));
if (start) if (start)
*start = g_value_get_int64 (gst_structure_get_value (structure, "cur")); *start =
g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (CUR)));
if (stop_type) if (stop_type)
*stop_type = *stop_type =
g_value_get_enum (gst_structure_get_value (structure, "stop_type")); g_value_get_enum (gst_structure_id_get_value (structure,
GST_QUARK (STOP_TYPE)));
if (stop) if (stop)
*stop = g_value_get_int64 (gst_structure_get_value (structure, "stop")); *stop =
g_value_get_int64 (gst_structure_id_get_value (structure,
GST_QUARK (STOP)));
} }
/** /**
@ -968,12 +1026,18 @@ gst_event_new_navigation (GstStructure * structure)
GstEvent * GstEvent *
gst_event_new_latency (GstClockTime latency) gst_event_new_latency (GstClockTime latency)
{ {
GstEvent *event;
GstStructure *structure;
GST_CAT_INFO (GST_CAT_EVENT, GST_CAT_INFO (GST_CAT_EVENT,
"creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
return gst_event_new_custom (GST_EVENT_LATENCY, structure = gst_structure_empty_new ("GstEventLatency");
gst_structure_new ("GstEventLatency", gst_structure_id_set (structure,
"latency", G_TYPE_UINT64, latency, NULL)); GST_QUARK (LATENCY), G_TYPE_UINT64, latency, NULL);
event = gst_event_new_custom (GST_EVENT_LATENCY, structure);
return event;
} }
/** /**
@ -996,5 +1060,6 @@ gst_event_parse_latency (GstEvent * event, GstClockTime * latency)
structure = gst_event_get_structure (event); structure = gst_event_get_structure (event);
if (latency) if (latency)
*latency = *latency =
g_value_get_uint64 (gst_structure_get_value (structure, "latency")); g_value_get_uint64 (gst_structure_id_get_value (structure,
GST_QUARK (LATENCY)));
} }

View file

@ -34,7 +34,10 @@ static const gchar *_quark_strings[] = {
"avg-in-rate", "avg-out-rate", "buffering-left", "avg-in-rate", "avg-out-rate", "buffering-left",
"estimated-total", "old-state", "new-state", "pending-state", "estimated-total", "old-state", "new-state", "pending-state",
"clock", "ready", "position", "new-base-time", "live", "min-latency", "clock", "ready", "position", "new-base-time", "live", "min-latency",
"max-latency", "busy", "type", "owner" "max-latency", "busy", "type", "owner", "update", "applied-rate",
"start", "stop", "minsize", "maxsize", "async", "proportion",
"diff", "timestamp", "flags", "cur-type", "cur", "stop-type",
"latency"
}; };
GQuark _priv_gst_quark_table[GST_QUARK_MAX]; GQuark _priv_gst_quark_table[GST_QUARK_MAX];
@ -44,6 +47,10 @@ _priv_gst_quarks_initialize (void)
{ {
gint i; gint i;
if (G_N_ELEMENTS (_quark_strings) != GST_QUARK_MAX)
g_warning ("the quark table is not consistent! %ld != %d",
G_N_ELEMENTS (_quark_strings), GST_QUARK_MAX);
for (i = 0; i < GST_QUARK_MAX; i++) { for (i = 0; i < GST_QUARK_MAX; i++) {
_priv_gst_quark_table[i] = g_quark_from_static_string (_quark_strings[i]); _priv_gst_quark_table[i] = g_quark_from_static_string (_quark_strings[i]);
} }

View file

@ -62,8 +62,23 @@ typedef enum _GstQuarkId
GST_QUARK_BUSY = 33, GST_QUARK_BUSY = 33,
GST_QUARK_TYPE = 34, GST_QUARK_TYPE = 34,
GST_QUARK_OWNER = 35, GST_QUARK_OWNER = 35,
GST_QUARK_UPDATE = 36,
GST_QUARK_APPLIED_RATE = 37,
GST_QUARK_START = 38,
GST_QUARK_STOP = 39,
GST_QUARK_MINSIZE = 40,
GST_QUARK_MAXSIZE = 41,
GST_QUARK_ASYNC = 42,
GST_QUARK_PROPORTION = 43,
GST_QUARK_DIFF = 44,
GST_QUARK_TIMESTAMP = 45,
GST_QUARK_FLAGS = 46,
GST_QUARK_CUR_TYPE = 47,
GST_QUARK_CUR = 48,
GST_QUARK_STOP_TYPE = 49,
GST_QUARK_LATENCY = 50,
GST_QUARK_MAX = 36 GST_QUARK_MAX = 51
} GstQuarkId; } GstQuarkId;
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX]; extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];

View file

@ -165,6 +165,7 @@ GST_START_TEST (test_watch)
main_loop = g_main_loop_new (NULL, FALSE); main_loop = g_main_loop_new (NULL, FALSE);
id = gst_bus_add_watch (test_bus, gst_bus_async_signal_func, NULL); id = gst_bus_add_watch (test_bus, gst_bus_async_signal_func, NULL);
fail_if (id == 0);
g_signal_connect (test_bus, "message::eos", (GCallback) message_func_eos, g_signal_connect (test_bus, "message::eos", (GCallback) message_func_eos,
NULL); NULL);
g_signal_connect (test_bus, "message::application", g_signal_connect (test_bus, "message::application",