Commit b9dbb551 authored by Wim Taymans's avatar Wim Taymans
Browse files

docs/design/part-overview.txt: Make upsteam/downstream concepts more clear.

Original commit message from CVS:
* docs/design/part-overview.txt:
Make upsteam/downstream concepts more clear.
Give an example of serialized/non-serialized events.
* docs/design/part-events.txt:
* docs/design/part-streams.txt:
Mention applied_rate.
* docs/design/part-trickmodes.txt:
Mention applied rate, flesh out some more use cases.
* gst/gstevent.c: (gst_event_new_new_segment),
(gst_event_parse_new_segment), (gst_event_new_new_segment_full),
(gst_event_parse_new_segment_full), (gst_event_new_tag),
(gst_event_parse_tag), (gst_event_new_buffer_size),
(gst_event_parse_buffer_size), (gst_event_new_qos),
(gst_event_parse_qos), (gst_event_parse_seek),
(gst_event_new_navigation):
* gst/gstevent.h:
Add applied_rate field to NEWSEGMENT event.
API: gst_event_new_new_segment_full()
API: gst_event_parse_new_segment_full()
* gst/gstsegment.c: (gst_segment_init), (gst_segment_set_seek),
(gst_segment_set_newsegment), (gst_segment_set_newsegment_full),
(gst_segment_to_stream_time), (gst_segment_to_running_time):
* gst/gstsegment.h:
Add applied_rate to GstSegment structure.
Make calculation of stream_time and running_time more correct
wrt rate/applied_rate.
Add some more docs.
API: GstSegment::applied_rate field
API: gst_segment_set_newsegment_full();
* libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment),
(gst_base_sink_get_sync_times), (gst_base_sink_get_position):
* libs/gst/base/gstbasetransform.c:
(gst_base_transform_sink_eventfunc),
(gst_base_transform_handle_buffer):
Parse and use applied_rate in the GstSegment field.
* tests/check/gst/gstevent.c: (GST_START_TEST):
Add check for applied_rate field.
* tests/check/gst/gstsegment.c: (GST_START_TEST),
(gstsegments_suite):
Add more checks for various GstSegment operations.
parent 029c8d82
2006-05-08 Wim Taymans <wim@fluendo.com>
* docs/design/part-overview.txt:
Make upsteam/downstream concepts more clear.
Give an example of serialized/non-serialized events.
* docs/design/part-events.txt:
* docs/design/part-streams.txt:
Mention applied_rate.
* docs/design/part-trickmodes.txt:
Mention applied rate, flesh out some more use cases.
* gst/gstevent.c: (gst_event_new_new_segment),
(gst_event_parse_new_segment), (gst_event_new_new_segment_full),
(gst_event_parse_new_segment_full), (gst_event_new_tag),
(gst_event_parse_tag), (gst_event_new_buffer_size),
(gst_event_parse_buffer_size), (gst_event_new_qos),
(gst_event_parse_qos), (gst_event_parse_seek),
(gst_event_new_navigation):
* gst/gstevent.h:
Add applied_rate field to NEWSEGMENT event.
API: gst_event_new_new_segment_full()
API: gst_event_parse_new_segment_full()
* gst/gstsegment.c: (gst_segment_init), (gst_segment_set_seek),
(gst_segment_set_newsegment), (gst_segment_set_newsegment_full),
(gst_segment_to_stream_time), (gst_segment_to_running_time):
* gst/gstsegment.h:
Add applied_rate to GstSegment structure.
Make calculation of stream_time and running_time more correct
wrt rate/applied_rate.
Add some more docs.
API: GstSegment::applied_rate field
API: gst_segment_set_newsegment_full();
* libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment),
(gst_base_sink_get_sync_times), (gst_base_sink_get_position):
* libs/gst/base/gstbasetransform.c:
(gst_base_transform_sink_eventfunc),
(gst_base_transform_handle_buffer):
Parse and use applied_rate in the GstSegment field.
* tests/check/gst/gstevent.c: (GST_START_TEST):
Add check for applied_rate field.
* tests/check/gst/gstsegment.c: (GST_START_TEST),
(gstsegments_suite):
Add more checks for various GstSegment operations.
2006-05-08 Wim Taymans <wim@fluendo.com>
 
* libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times),
......
......@@ -101,7 +101,7 @@ NEWSEGMENT
A newsegment event is sent downstream by an element to indicate that the following
group of buffers start and end at the specified positions. The newsegment event
also contains the playback speed of the stream.
also contains the playback speed and the applied rate of the stream.
Since the stream time is always set to 0 at start and after a seek, a 0
point for all next buffer's timestamps has to be propagated through the
......@@ -134,6 +134,7 @@ streamtime of the pipeline will not be reset to 0 so any element that syncs
to the clock must use the stop times of the previous newsegment events to
make the buffer timestamps increasing (part-segments.txt).
TAG
---
......
......@@ -29,11 +29,15 @@ Introduction
an example of an ogg/vorbis playback pipeline.
+-----------------------------------------------------------+
| ----------> downstream -------------------> |
| |
| pipeline |
| +---------+ +----------+ +-----------+ +----------+ |
| | filesrc | | oggdemux | | vorbisdec | | alsasink | |
| | src-sink src-sink src-sink | |
| +---------+ +----------+ +-----------+ +----------+ |
| |
| <---------< upstream <-------------------< |
+-----------------------------------------------------------+
The filesrc element reads data from a file on disk. The oggdemux element parses
......@@ -244,7 +248,14 @@ Dataflow and events
the events are used to denote special conditions in the dataflow such as EOS or
to inform plugins of special events such as flushing or seeking.
Some events must be serialized with the buffer flow, others don't.
Some events must be serialized with the buffer flow, others don't. Serialized
events are inserted between the buffers. Non serialized events jump in front
of any buffers current being processed.
An example of a serialized event is a TAG event that is inserted between buffers
to mark metadata for those buffers.
An example of a non serialized event is the FLUSH event.
Pipeline construction
......
......@@ -36,6 +36,7 @@ Typical stream
- marks valid buffer timestamp range (start, stop)
- marks stream_time of buffers (time)
- marks playback rate (rate)
- marks applied rate (applied_rate)
2) N buffers
- displayable buffers are between start/stop of the NEW_SEGMENT
......
......@@ -69,11 +69,15 @@ When performing a seek, the following steps have to be taken by the application:
For client side trickmode a NEW_SEGMENT event will be sent downstream with
the new rate and start/stop positions. All elements prepare themselves to
handle the rate (see below).
handle the rate (see below). The applied rate of the NEW_SEGMENT event will
be set to 1.0 to indicate that no rate adjustment has been done.
for server side trick mode a NEW_SEGMENT event is sent downstream with a
rate of 1.0 and the start/stop positions. The elements will configure themselves
for normal playback speed since the server will perform the rate conversions.
The applied rate will be set to the rate that will be applied by the server. This
is done to insure that the position reporting performed in the sink is aware
of the trick mode.
When the seek succeeds, the _send_event() function will return TRUE.
......@@ -95,9 +99,12 @@ The rate value in the segment should be used to reopen the connection to the ser
requesting data at the new speed and possibly a new playback position.
When the server connection was successfully reopened, set the rate of the segment
to 1.0 so that the client side trickmode is not enabled. Alternatively a combination
of client side and serverside trickmode can be used, for example if the server does
not support certain rates, the client can perform rate conversion for the remainder.
to 1.0 so that the client side trickmode is not enabled. The applied rate in the
segment is set to the rate transformation done by the server.
Alternatively a combination of client side and serverside trickmode can be used, for
example if the server does not support certain rates, the client can perform rate
conversion for the remainder.
source server
......@@ -117,22 +124,27 @@ not support certain rates, the client can perform rate conversion for the remain
After performing the seek, the source will inform the downstream elements of the
new segment that is to be played back. Since the segment will have a rate of 1.0,
no client side trick modes are enabled.
no client side trick modes are enabled. The segment will have an applied rate
different from 1.0 to indicate that the media contains data with non-standard
playback speed or direction.
client side forward trickmodes
------------------------------
The seek happens as stated above. a NEW_SEGMENT event is sent downstream with a rate
bigger than 1.0. Plugins receiving the NEW_SEGMENT can decide to perform the
different from 1.0. Plugins receiving the NEW_SEGMENT can decide to perform the
rate conversion of the media data (retimestamp video frames, resample audio, ...).
A plugin can also decide to drop frames in the case of fast playback or use a more
efficient decoding algorithm (skip B frames, ...). If a plugin decides to resample
or retimestamp, it should modify the NEW_SEGMENT with a rate of 1.0 so that
downstream elements don't resample again.
or retimestamp, it should modify the NEW_SEGMENT with a rate of 1.0 and update the
applied rate so that downstream elements don't resample again but are aware that the
media has been modified.
The GStreamer base audio and video sinks will resample automatically if they receive
a NEW_SEGMENT event with a rate different from 1.0.
a NEW_SEGMENT event with a rate different from 1.0. The position reporting in the
base audio and video sinks will also depend on the applied rate of the segment
information.
client side backwards trickmode
......@@ -143,6 +155,8 @@ For backwards playback the following rules apply:
- the rate in the NEW_SEGMENT is less than 0.0.
- the NEW_SEGMENT start position is less than the stop position, playback will
however happen from stop to start in reverse.
- the time member in the NEW_SEGMENT is set to the stream time of the start
position.
For plugins the following rules apply:
......@@ -154,8 +168,8 @@ For plugins the following rules apply:
Timestamps on the buffers are set starting from the stop position to start,
effectively going backwards.
- A decoder decodes and accumulates all frames. If a new keyframe is received,
all accumulated frames are sent backwards.
- A decoder decodes and accumulates all frames. If a new keyframe or EOS is received,
all accumulated frames are sent downsteam in reverse.
- A sink reverses (for audio) and retimestamps (audio, video) the buffers before
playing them back. Retimestamping occurs relative to the stop position, making
......
......@@ -416,31 +416,94 @@ gst_event_new_eos (void)
* @stop: the stop value of the segment
* @position: stream position
*
* Allocate a new newsegment event with the given format/values tripplets.
* Allocate a new newsegment event with the given format/values tripplets
*
* This method calls gst_event_new_new_segment_full() passing a default
* value of 1.0 for applied_rate
*/
GstEvent *
gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
gint64 start, gint64 stop, gint64 position)
{
return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
stop, position);
}
/**
* gst_event_parse_new_segment:
* @event: The event to query
* @update: A pointer to the update flag of the segment
* @rate: A pointer to the rate of the segment
* @format: A pointer to the format of the newsegment values
* @start: A pointer to store the start value in
* @stop: A pointer to store the stop value in
* @position: A pointer to store the stream time in
*
* Get the update flag, rate, format, start, stop and position in the
* newsegment event. In general, gst_event_parse_new_segment_full() should
* be used instead of this, to also retrieve the applied_rate value of the
* segment. See gst_event_new_new_segment_full() for a full description
* of the newsegment event.
*/
void
gst_event_parse_new_segment (GstEvent * event, gboolean * update,
gdouble * rate, GstFormat * format, gint64 * start,
gint64 * stop, gint64 * position)
{
gst_event_parse_new_segment_full (event, update, rate, NULL, format, start,
stop, position);
}
/**
* gst_event_new_new_segment_full:
* @update: Whether this segment is an update to a previous one
* @rate: A new rate for playback
* @applied_rate: The rate factor which has already been applied
* @format: The format of the segment values
* @start: The start value of the segment
* @stop: The stop value of the segment
* @position: stream position
*
* Allocate a new newsegment event with the given format/values triplets.
*
* The newsegment event marks the range of buffers to be processed. All
* data not within the segment range is not to be processed. This can be
* used intelligently by plugins to use more efficient methods of skipping
* used intelligently by plugins to apply more efficient methods of skipping
* unneeded packets.
*
* The stream time of the segment is used to convert the buffer timestamps
* into the stream time again, this is usually done in sinks to report the
* current stream_time. @stream_time cannot be -1.
* The position value of the segment is used in conjunction with the start
* value to convert the buffer timestamps into the stream time. This is
* usually done in sinks to report the current stream_time.
* @position represents the stream_time of a buffer carrying a timestamp of
* @start. @position cannot be -1.
*
* @start cannot be -1, @stop can be -1. If there
* is a valid @stop given, it must be greater or equal than @start.
* is a valid @stop given, it must be greater or equal the @start, including
* when the indicated playback @rate is < 0
*
* The @applied_rate value provides information about any rate adjustment that
* has already been made to the timestamps and content on the buffers of the
* stream. (@rate * @applied_rate) should always equal the rate that has been
* requested for playback. For example, if an element has an input segment
* with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust
* incoming timestamps and buffer content by half and output a newsegment event
* with @rate of 1.0 and @applied_rate of 2.0
*
* After a newsegment event, the buffer stream time is calculated with:
*
* stream_time + (TIMESTAMP(buf) - start) * ABS (rate)
* position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
*
* Returns: A new newsegment event.
*
* Since: 0.10.6
*/
GstEvent *
gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
gint64 start, gint64 stop, gint64 position)
gst_event_new_new_segment_full (gboolean update, gdouble rate,
gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
gint64 position)
{
g_return_val_if_fail (rate != 0.0, NULL);
g_return_val_if_fail (applied_rate != 0.0, NULL);
if (format == GST_FORMAT_TIME) {
GST_CAT_INFO (GST_CAT_EVENT,
......@@ -455,6 +518,7 @@ gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
"start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
G_GINT64_FORMAT, update, rate, format, start, stop, position);
}
g_return_val_if_fail (position != -1, NULL);
g_return_val_if_fail (start != -1, NULL);
if (stop != -1)
......@@ -464,6 +528,7 @@ gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
gst_structure_new ("GstEventNewsegment",
"update", G_TYPE_BOOLEAN, update,
"rate", G_TYPE_DOUBLE, rate,
"applied_rate", G_TYPE_DOUBLE, applied_rate,
"format", GST_TYPE_FORMAT, format,
"start", G_TYPE_INT64, start,
"stop", G_TYPE_INT64, stop,
......@@ -471,21 +536,26 @@ gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
}
/**
* gst_event_parse_new_segment:
* gst_event_parse_new_segment_full:
* @event: The event to query
* @update: A pointer to the update flag of the segment
* @rate: A pointer to the rate of the segment
* @applied_rate: A pointer to the applied_rate of the segment
* @format: A pointer to the format of the newsegment values
* @start: A pointer to store the start value in
* @stop: A pointer to store the stop value in
* @position: A pointer to store the stream time in
*
* Get the format, start, stop and position in the newsegment event.
* Get the update, rate, applied_rate, format, start, stop and
* position in the newsegment event. See gst_event_new_new_segment_full()
* for a full description of the newsegment event.
*
* Since: 0.10.6
*/
void
gst_event_parse_new_segment (GstEvent * event, gboolean * update,
gdouble * rate, GstFormat * format, gint64 * start,
gint64 * stop, gint64 * position)
gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
gdouble * rate, gdouble * applied_rate, GstFormat * format,
gint64 * start, gint64 * stop, gint64 * position)
{
const GstStructure *structure;
......@@ -493,18 +563,22 @@ gst_event_parse_new_segment (GstEvent * event, gboolean * update,
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
structure = gst_event_get_structure (event);
if (update)
if (G_LIKELY (update))
*update =
g_value_get_boolean (gst_structure_get_value (structure, "update"));
if (rate)
if (G_LIKELY (rate))
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
if (format)
if (G_LIKELY (applied_rate))
*applied_rate =
g_value_get_double (gst_structure_get_value (structure,
"applied_rate"));
if (G_LIKELY (format))
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
if (start)
if (G_LIKELY (start))
*start = g_value_get_int64 (gst_structure_get_value (structure, "start"));
if (stop)
if (G_LIKELY (stop))
*stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
if (position)
if (G_LIKELY (position))
*position =
g_value_get_int64 (gst_structure_get_value (structure, "position"));
}
......@@ -521,7 +595,6 @@ GstEvent *
gst_event_new_tag (GstTagList * taglist)
{
g_return_val_if_fail (taglist != NULL, NULL);
return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
}
......@@ -537,7 +610,6 @@ gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
{
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
if (taglist)
*taglist = (GstTagList *) event->structure;
}
......@@ -565,7 +637,6 @@ gst_event_new_buffer_size (GstFormat format, gint64 minsize,
"creating buffersize format %d, minsize %" G_GINT64_FORMAT
", maxsize %" G_GINT64_FORMAT ", async %d", format,
minsize, maxsize, async);
return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
gst_structure_new ("GstEventBufferSize",
"format", GST_TYPE_FORMAT, format,
......@@ -592,7 +663,6 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
structure = gst_event_get_structure (event);
if (format)
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
......@@ -645,9 +715,9 @@ gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
GstClockTime timestamp)
{
GST_CAT_INFO (GST_CAT_EVENT,
"creating qos proportion %lf, diff %" GST_TIME_FORMAT
"creating qos proportion %lf, diff %" G_GINT64_FORMAT
", timestamp %" GST_TIME_FORMAT, proportion,
GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
diff, GST_TIME_ARGS (timestamp));
return gst_event_new_custom (GST_EVENT_QOS,
gst_structure_new ("GstEventQOS",
......@@ -673,7 +743,6 @@ gst_event_parse_qos (GstEvent * event, gdouble * proportion,
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
structure = gst_event_get_structure (event);
if (proportion)
*proportion =
......@@ -761,16 +830,14 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
* Parses a seek @event and stores the results in the given result locations.
*/
void
gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
GstSeekFlags * flags,
GstSeekType * cur_type, gint64 * cur,
GstSeekType * stop_type, gint64 * stop)
gst_event_parse_seek (GstEvent * event, gdouble * rate,
GstFormat * format, GstSeekFlags * flags, GstSeekType * cur_type,
gint64 * cur, GstSeekType * stop_type, gint64 * stop)
{
const GstStructure *structure;
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
structure = gst_event_get_structure (event);
if (rate)
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
......@@ -802,6 +869,5 @@ GstEvent *
gst_event_new_navigation (GstStructure * structure)
{
g_return_val_if_fail (structure != NULL, NULL);
return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
}
......@@ -368,12 +368,25 @@ GstEvent* gst_event_new_new_segment (gboolean update, gdouble rate,
GstFormat format,
gint64 start, gint64 stop,
gint64 position);
GstEvent* gst_event_new_new_segment_full (gboolean update, gdouble rate,
gdouble applied_rate,
GstFormat format,
gint64 start, gint64 stop,
gint64 position);
void gst_event_parse_new_segment (GstEvent *event,
gboolean *update,
gdouble *rate,
GstFormat *format,
gint64 *start, gint64 *stop,
gint64 *position);
void gst_event_parse_new_segment_full (GstEvent *event,
gboolean *update,
gdouble *rate,
gdouble *applied_rate,
GstFormat *format,
gint64 *start, gint64 *stop,
gint64 *position);
/* tag event */
GstEvent* gst_event_new_tag (GstTagList *taglist);
void gst_event_parse_tag (GstEvent *event, GstTagList **taglist);
......
......@@ -49,11 +49,13 @@
* A segment structure is initialized with gst_segment_init(), which takes a #GstFormat
* that will be used as the format of the segment values. The segment will be configured
* with a start value of 0 and a stop/duration of -1, which is undefined. The default
* rate is 1.0.
* rate and applied_rate is 1.0.
*
* If the segment is used for managing seeks, the segment duration should be set with
* gst_segment_set_duration(). The public duration field contains the duration of the
* segment.
* segment. When using the segment for seeking, the start and time members should
* normally be left to their default 0 value. The stop position is left to -1 unless
* explicitly configured to a different value after a seek event.
*
* The current position in the segment should be set with the gst_segment_set_last_stop().
* The public last_stop field contains the last set stop position in the segment.
......@@ -71,13 +73,14 @@
*
* For elements that want to synchronize to the pipeline clock, gst_segment_to_running_time()
* can be used to convert a timestamp to a value that can be used to synchronize
* to the clock. This function takes into account all accumulated segments.
* to the clock. This function takes into account all accumulated segments as well as
* any rate or applied_rate conversions.
*
* For elements that need to perform operations on media data in stream_time,
* gst_segment_to_stream_time() can be used to convert a timestamp and the segment
* info to stream time (which is always between 0 and the duration of the stream).
*
* Last reviewed on 2006-03-12 (0.10.5)
* Last reviewed on 2006-05-03 (0.10.6)
*/
static GstSegment *
......@@ -154,6 +157,7 @@ gst_segment_init (GstSegment * segment, GstFormat format)
segment->rate = 1.0;
segment->abs_rate = 1.0;
segment->applied_rate = 1.0;
segment->format = format;
segment->flags = 0;
segment->start = 0;
......@@ -235,6 +239,10 @@ gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
* from GST_SEEK_TYPE_NONE, the current position is not updated and
* streaming should continue from the last position, possibly with
* updated rate, flags or stop position.
*
* The applied rate of the segment will be set to 1.0 by default.
* If the caller can apply a rate change, it should update @segment
* rate and applied_rate after calling this function.
*/
void
gst_segment_set_seek (GstSegment * segment, gdouble rate,
......@@ -324,6 +332,7 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
segment->rate = rate;
segment->abs_rate = ABS (rate);
segment->applied_rate = 1.0;
segment->flags = flags;
segment->start = cur;
if (update_start) {
......@@ -346,15 +355,41 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
* @stop: the new stop value
* @time: the new stream time
*
* Update the segment structure with the field values of a new segment event.
* Update the segment structure with the field values of a new segment event and
* with a default applied_rate of 1.0.
*
* Since: 0.10.6
*/
void
gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
GstFormat format, gint64 start, gint64 stop, gint64 time)
{
gst_segment_set_newsegment_full (segment, update, rate, 1.0, format, start,
stop, time);
}
/**
* gst_segment_set_newsegment_full:
* @segment: a #GstSegment structure.
* @update: flag indicating a new segment is started or updated
* @rate: the rate of the segment.
* @applied_rate: the applied rate of the segment.
* @format: the format of the segment.
* @start: the new start value
* @stop: the new stop value
* @time: the new stream time
*
* Update the segment structure with the field values of a new segment event.
*/
void
gst_segment_set_newsegment_full (GstSegment * segment, gboolean update,
gdouble rate, gdouble applied_rate, GstFormat format, gint64 start,
gint64 stop, gint64 time)
{
gint64 duration;
g_return_if_fail (rate != 0.0);
g_return_if_fail (applied_rate != 0.0);
g_return_if_fail (segment != NULL);
if (segment->format == GST_FORMAT_UNDEFINED)
......@@ -382,23 +417,29 @@ gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
* segment. the accumulated time is used when syncing to the
* clock.
*/
if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
if (segment->stop != -1) {
duration = segment->stop - segment->start;
} else if (GST_CLOCK_TIME_IS_VALID (segment->last_stop)) {
} else if (segment->last_stop != -1) {
/* else use last seen timestamp as segment stop */
duration = segment->last_stop - segment->start;
} else {
/* else we don't know */
/* else we don't know and throw a warning.. really, this should
* be fixed in the element. */
g_warning ("closing segment of unknown duration, assuming duration of 0");
duration = 0;
}
}
/* use previous rate to calculate duration */
segment->accum += gst_gdouble_to_guint64 (
(gst_guint64_to_gdouble (duration) / segment->abs_rate));
if (segment->abs_rate != 1.0)
duration /= segment->abs_rate;
/* accumulate duration */
segment->accum += duration;
/* then update the current segment */
segment->rate = rate;
segment->abs_rate = ABS (rate);
segment->applied_rate = applied_rate;
segment->start = start;
segment->last_stop = start;
segment->stop = stop;
......@@ -417,8 +458,8 @@ gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
*
* This function is typically used by elements that need to operate on
* the stream time of the buffers it receives, such as effect plugins.
* In those use cases, @position is typically the buffer timestamp that
* one wants to convert to the stream time.
* In those use cases, @position is typically the buffer timestamp or
* clock time that one wants to convert to the stream time.
* The stream time is always between 0 and the total duration of the
* media stream.
*
......@@ -429,22 +470,52 @@ gint64
gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
gint64 position)
{
gint64 result, time;
gint64 result;
gdouble abs_applied_rate;
g_return_val_if_fail (segment != NULL, -1);
/* format does not matter for -1 */
if (position == -1)
return -1;
if (segment->format == GST_FORMAT_UNDEFINED)