mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
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.
This commit is contained in:
parent
029c8d820b
commit
b9dbb55105
13 changed files with 1180 additions and 98 deletions
50
ChangeLog
50
ChangeLog
|
@ -1,3 +1,53 @@
|
||||||
|
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>
|
2006-05-08 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times),
|
* 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
|
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
|
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
|
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
|
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
|
to the clock must use the stop times of the previous newsegment events to
|
||||||
make the buffer timestamps increasing (part-segments.txt).
|
make the buffer timestamps increasing (part-segments.txt).
|
||||||
|
|
||||||
|
|
||||||
TAG
|
TAG
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,15 @@ Introduction
|
||||||
an example of an ogg/vorbis playback pipeline.
|
an example of an ogg/vorbis playback pipeline.
|
||||||
|
|
||||||
+-----------------------------------------------------------+
|
+-----------------------------------------------------------+
|
||||||
|
| ----------> downstream -------------------> |
|
||||||
|
| |
|
||||||
| pipeline |
|
| pipeline |
|
||||||
| +---------+ +----------+ +-----------+ +----------+ |
|
| +---------+ +----------+ +-----------+ +----------+ |
|
||||||
| | filesrc | | oggdemux | | vorbisdec | | alsasink | |
|
| | filesrc | | oggdemux | | vorbisdec | | alsasink | |
|
||||||
| | src-sink src-sink src-sink | |
|
| | src-sink src-sink src-sink | |
|
||||||
| +---------+ +----------+ +-----------+ +----------+ |
|
| +---------+ +----------+ +-----------+ +----------+ |
|
||||||
|
| |
|
||||||
|
| <---------< upstream <-------------------< |
|
||||||
+-----------------------------------------------------------+
|
+-----------------------------------------------------------+
|
||||||
|
|
||||||
The filesrc element reads data from a file on disk. The oggdemux element parses
|
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
|
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.
|
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
|
Pipeline construction
|
||||||
|
|
|
@ -36,6 +36,7 @@ Typical stream
|
||||||
- marks valid buffer timestamp range (start, stop)
|
- marks valid buffer timestamp range (start, stop)
|
||||||
- marks stream_time of buffers (time)
|
- marks stream_time of buffers (time)
|
||||||
- marks playback rate (rate)
|
- marks playback rate (rate)
|
||||||
|
- marks applied rate (applied_rate)
|
||||||
|
|
||||||
2) N buffers
|
2) N buffers
|
||||||
- displayable buffers are between start/stop of the NEW_SEGMENT
|
- 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
|
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
|
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
|
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
|
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.
|
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.
|
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.
|
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
|
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
|
to 1.0 so that the client side trickmode is not enabled. The applied rate in the
|
||||||
of client side and serverside trickmode can be used, for example if the server does
|
segment is set to the rate transformation done by the server.
|
||||||
not support certain rates, the client can perform rate conversion for the remainder.
|
|
||||||
|
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
|
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
|
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,
|
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
|
client side forward trickmodes
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
The seek happens as stated above. a NEW_SEGMENT event is sent downstream with a rate
|
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, ...).
|
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
|
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
|
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
|
or retimestamp, it should modify the NEW_SEGMENT with a rate of 1.0 and update the
|
||||||
downstream elements don't resample again.
|
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
|
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
|
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 rate in the NEW_SEGMENT is less than 0.0.
|
||||||
- the NEW_SEGMENT start position is less than the stop position, playback will
|
- the NEW_SEGMENT start position is less than the stop position, playback will
|
||||||
however happen from stop to start in reverse.
|
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:
|
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,
|
Timestamps on the buffers are set starting from the stop position to start,
|
||||||
effectively going backwards.
|
effectively going backwards.
|
||||||
|
|
||||||
- A decoder decodes and accumulates all frames. If a new keyframe is received,
|
- A decoder decodes and accumulates all frames. If a new keyframe or EOS is received,
|
||||||
all accumulated frames are sent backwards.
|
all accumulated frames are sent downsteam in reverse.
|
||||||
|
|
||||||
- A sink reverses (for audio) and retimestamps (audio, video) the buffers before
|
- A sink reverses (for audio) and retimestamps (audio, video) the buffers before
|
||||||
playing them back. Retimestamping occurs relative to the stop position, making
|
playing them back. Retimestamping occurs relative to the stop position, making
|
||||||
|
|
150
gst/gstevent.c
150
gst/gstevent.c
|
@ -416,31 +416,94 @@ gst_event_new_eos (void)
|
||||||
* @stop: the stop value of the segment
|
* @stop: the stop value of the segment
|
||||||
* @position: stream position
|
* @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
|
||||||
*
|
*
|
||||||
* The newsegment event marks the range of buffers to be processed. All
|
* This method calls gst_event_new_new_segment_full() passing a default
|
||||||
* data not within the segment range is not to be processed. This can be
|
* value of 1.0 for applied_rate
|
||||||
* used intelligently by plugins to use 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.
|
|
||||||
*
|
|
||||||
* @start cannot be -1, @stop can be -1. If there
|
|
||||||
* is a valid @stop given, it must be greater or equal than @start.
|
|
||||||
*
|
|
||||||
* After a newsegment event, the buffer stream time is calculated with:
|
|
||||||
*
|
|
||||||
* stream_time + (TIMESTAMP(buf) - start) * ABS (rate)
|
|
||||||
*
|
|
||||||
* Returns: A new newsegment event.
|
|
||||||
*/
|
*/
|
||||||
GstEvent *
|
GstEvent *
|
||||||
gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
|
gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
|
||||||
gint64 start, gint64 stop, gint64 position)
|
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 apply more efficient methods of skipping
|
||||||
|
* unneeded packets.
|
||||||
|
*
|
||||||
|
* 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 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:
|
||||||
|
*
|
||||||
|
* position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
|
||||||
|
*
|
||||||
|
* Returns: A new newsegment event.
|
||||||
|
*
|
||||||
|
* Since: 0.10.6
|
||||||
|
*/
|
||||||
|
GstEvent *
|
||||||
|
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 (rate != 0.0, NULL);
|
||||||
|
g_return_val_if_fail (applied_rate != 0.0, NULL);
|
||||||
|
|
||||||
if (format == GST_FORMAT_TIME) {
|
if (format == GST_FORMAT_TIME) {
|
||||||
GST_CAT_INFO (GST_CAT_EVENT,
|
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 %"
|
"start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
|
||||||
G_GINT64_FORMAT, update, rate, format, start, stop, position);
|
G_GINT64_FORMAT, update, rate, format, start, stop, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_val_if_fail (position != -1, NULL);
|
g_return_val_if_fail (position != -1, NULL);
|
||||||
g_return_val_if_fail (start != -1, NULL);
|
g_return_val_if_fail (start != -1, NULL);
|
||||||
if (stop != -1)
|
if (stop != -1)
|
||||||
|
@ -464,6 +528,7 @@ gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
|
||||||
gst_structure_new ("GstEventNewsegment",
|
gst_structure_new ("GstEventNewsegment",
|
||||||
"update", G_TYPE_BOOLEAN, update,
|
"update", G_TYPE_BOOLEAN, update,
|
||||||
"rate", G_TYPE_DOUBLE, rate,
|
"rate", G_TYPE_DOUBLE, rate,
|
||||||
|
"applied_rate", G_TYPE_DOUBLE, applied_rate,
|
||||||
"format", GST_TYPE_FORMAT, format,
|
"format", GST_TYPE_FORMAT, format,
|
||||||
"start", G_TYPE_INT64, start,
|
"start", G_TYPE_INT64, start,
|
||||||
"stop", G_TYPE_INT64, stop,
|
"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
|
* @event: The event to query
|
||||||
* @update: A pointer to the update flag of the segment
|
* @update: A pointer to the update flag of the segment
|
||||||
* @rate: A pointer to the rate 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
|
* @format: A pointer to the format of the newsegment values
|
||||||
* @start: A pointer to store the start value in
|
* @start: A pointer to store the start value in
|
||||||
* @stop: A pointer to store the stop value in
|
* @stop: A pointer to store the stop value in
|
||||||
* @position: A pointer to store the stream time 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
|
void
|
||||||
gst_event_parse_new_segment (GstEvent * event, gboolean * update,
|
gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
|
||||||
gdouble * rate, GstFormat * format, gint64 * start,
|
gdouble * rate, gdouble * applied_rate, GstFormat * format,
|
||||||
gint64 * stop, gint64 * position)
|
gint64 * start, gint64 * stop, gint64 * position)
|
||||||
{
|
{
|
||||||
const GstStructure *structure;
|
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);
|
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
|
||||||
|
|
||||||
structure = gst_event_get_structure (event);
|
structure = gst_event_get_structure (event);
|
||||||
if (update)
|
if (G_LIKELY (update))
|
||||||
*update =
|
*update =
|
||||||
g_value_get_boolean (gst_structure_get_value (structure, "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"));
|
*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"));
|
*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"));
|
*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"));
|
*stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
|
||||||
if (position)
|
if (G_LIKELY (position))
|
||||||
*position =
|
*position =
|
||||||
g_value_get_int64 (gst_structure_get_value (structure, "position"));
|
g_value_get_int64 (gst_structure_get_value (structure, "position"));
|
||||||
}
|
}
|
||||||
|
@ -521,7 +595,6 @@ GstEvent *
|
||||||
gst_event_new_tag (GstTagList * taglist)
|
gst_event_new_tag (GstTagList * taglist)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (taglist != NULL, NULL);
|
g_return_val_if_fail (taglist != NULL, NULL);
|
||||||
|
|
||||||
return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
|
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_IS_EVENT (event));
|
||||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
|
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
|
||||||
|
|
||||||
if (taglist)
|
if (taglist)
|
||||||
*taglist = (GstTagList *) event->structure;
|
*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
|
"creating buffersize format %d, minsize %" G_GINT64_FORMAT
|
||||||
", maxsize %" G_GINT64_FORMAT ", async %d", format,
|
", maxsize %" G_GINT64_FORMAT ", async %d", format,
|
||||||
minsize, maxsize, async);
|
minsize, maxsize, async);
|
||||||
|
|
||||||
return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
|
return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
|
||||||
gst_structure_new ("GstEventBufferSize",
|
gst_structure_new ("GstEventBufferSize",
|
||||||
"format", GST_TYPE_FORMAT, format,
|
"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_IS_EVENT (event));
|
||||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
|
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
|
||||||
|
|
||||||
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_get_value (structure, "format"));
|
||||||
|
@ -645,9 +715,9 @@ gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
|
||||||
GstClockTime timestamp)
|
GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
GST_CAT_INFO (GST_CAT_EVENT,
|
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,
|
", 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,
|
return gst_event_new_custom (GST_EVENT_QOS,
|
||||||
gst_structure_new ("GstEventQOS",
|
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_IS_EVENT (event));
|
||||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
|
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
|
||||||
|
|
||||||
structure = gst_event_get_structure (event);
|
structure = gst_event_get_structure (event);
|
||||||
if (proportion)
|
if (proportion)
|
||||||
*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.
|
* Parses a seek @event and stores the results in the given result locations.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
|
gst_event_parse_seek (GstEvent * event, gdouble * rate,
|
||||||
GstSeekFlags * flags,
|
GstFormat * format, GstSeekFlags * flags, GstSeekType * cur_type,
|
||||||
GstSeekType * cur_type, gint64 * cur,
|
gint64 * cur, GstSeekType * stop_type, gint64 * stop)
|
||||||
GstSeekType * stop_type, gint64 * stop)
|
|
||||||
{
|
{
|
||||||
const GstStructure *structure;
|
const GstStructure *structure;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_EVENT (event));
|
g_return_if_fail (GST_IS_EVENT (event));
|
||||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
|
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
|
||||||
|
|
||||||
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_get_value (structure, "rate"));
|
||||||
|
@ -802,6 +869,5 @@ GstEvent *
|
||||||
gst_event_new_navigation (GstStructure * structure)
|
gst_event_new_navigation (GstStructure * structure)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (structure != NULL, NULL);
|
g_return_val_if_fail (structure != NULL, NULL);
|
||||||
|
|
||||||
return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
|
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,
|
GstFormat format,
|
||||||
gint64 start, gint64 stop,
|
gint64 start, gint64 stop,
|
||||||
gint64 position);
|
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,
|
void gst_event_parse_new_segment (GstEvent *event,
|
||||||
gboolean *update,
|
gboolean *update,
|
||||||
gdouble *rate,
|
gdouble *rate,
|
||||||
GstFormat *format,
|
GstFormat *format,
|
||||||
gint64 *start, gint64 *stop,
|
gint64 *start, gint64 *stop,
|
||||||
gint64 *position);
|
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 */
|
/* tag event */
|
||||||
GstEvent* gst_event_new_tag (GstTagList *taglist);
|
GstEvent* gst_event_new_tag (GstTagList *taglist);
|
||||||
void gst_event_parse_tag (GstEvent *event, GstTagList **taglist);
|
void gst_event_parse_tag (GstEvent *event, GstTagList **taglist);
|
||||||
|
|
155
gst/gstsegment.c
155
gst/gstsegment.c
|
@ -49,11 +49,13 @@
|
||||||
* A segment structure is initialized with gst_segment_init(), which takes a #GstFormat
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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 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.
|
* 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()
|
* 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
|
* 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,
|
* 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
|
* 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).
|
* 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 *
|
static GstSegment *
|
||||||
|
@ -154,6 +157,7 @@ gst_segment_init (GstSegment * segment, GstFormat format)
|
||||||
|
|
||||||
segment->rate = 1.0;
|
segment->rate = 1.0;
|
||||||
segment->abs_rate = 1.0;
|
segment->abs_rate = 1.0;
|
||||||
|
segment->applied_rate = 1.0;
|
||||||
segment->format = format;
|
segment->format = format;
|
||||||
segment->flags = 0;
|
segment->flags = 0;
|
||||||
segment->start = 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
|
* from GST_SEEK_TYPE_NONE, the current position is not updated and
|
||||||
* streaming should continue from the last position, possibly with
|
* streaming should continue from the last position, possibly with
|
||||||
* updated rate, flags or stop position.
|
* 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
|
void
|
||||||
gst_segment_set_seek (GstSegment * segment, gdouble rate,
|
gst_segment_set_seek (GstSegment * segment, gdouble rate,
|
||||||
|
@ -324,6 +332,7 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
|
||||||
|
|
||||||
segment->rate = rate;
|
segment->rate = rate;
|
||||||
segment->abs_rate = ABS (rate);
|
segment->abs_rate = ABS (rate);
|
||||||
|
segment->applied_rate = 1.0;
|
||||||
segment->flags = flags;
|
segment->flags = flags;
|
||||||
segment->start = cur;
|
segment->start = cur;
|
||||||
if (update_start) {
|
if (update_start) {
|
||||||
|
@ -346,15 +355,41 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
|
||||||
* @stop: the new stop value
|
* @stop: the new stop value
|
||||||
* @time: the new stream time
|
* @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
|
void
|
||||||
gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
|
gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
|
||||||
GstFormat format, gint64 start, gint64 stop, gint64 time)
|
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;
|
gint64 duration;
|
||||||
|
|
||||||
g_return_if_fail (rate != 0.0);
|
g_return_if_fail (rate != 0.0);
|
||||||
|
g_return_if_fail (applied_rate != 0.0);
|
||||||
g_return_if_fail (segment != NULL);
|
g_return_if_fail (segment != NULL);
|
||||||
|
|
||||||
if (segment->format == GST_FORMAT_UNDEFINED)
|
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
|
* segment. the accumulated time is used when syncing to the
|
||||||
* clock.
|
* clock.
|
||||||
*/
|
*/
|
||||||
if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
|
if (segment->stop != -1) {
|
||||||
duration = segment->stop - segment->start;
|
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 */
|
/* else use last seen timestamp as segment stop */
|
||||||
duration = segment->last_stop - segment->start;
|
duration = segment->last_stop - segment->start;
|
||||||
} else {
|
} 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;
|
duration = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* use previous rate to calculate duration */
|
/* use previous rate to calculate duration */
|
||||||
segment->accum += gst_gdouble_to_guint64 (
|
if (segment->abs_rate != 1.0)
|
||||||
(gst_guint64_to_gdouble (duration) / segment->abs_rate));
|
duration /= segment->abs_rate;
|
||||||
|
|
||||||
|
/* accumulate duration */
|
||||||
|
segment->accum += duration;
|
||||||
|
|
||||||
/* then update the current segment */
|
/* then update the current segment */
|
||||||
segment->rate = rate;
|
segment->rate = rate;
|
||||||
segment->abs_rate = ABS (rate);
|
segment->abs_rate = ABS (rate);
|
||||||
|
segment->applied_rate = applied_rate;
|
||||||
segment->start = start;
|
segment->start = start;
|
||||||
segment->last_stop = start;
|
segment->last_stop = start;
|
||||||
segment->stop = stop;
|
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
|
* This function is typically used by elements that need to operate on
|
||||||
* the stream time of the buffers it receives, such as effect plugins.
|
* the stream time of the buffers it receives, such as effect plugins.
|
||||||
* In those use cases, @position is typically the buffer timestamp that
|
* In those use cases, @position is typically the buffer timestamp or
|
||||||
* one wants to convert to the stream time.
|
* clock time that one wants to convert to the stream time.
|
||||||
* The stream time is always between 0 and the total duration of the
|
* The stream time is always between 0 and the total duration of the
|
||||||
* media stream.
|
* media stream.
|
||||||
*
|
*
|
||||||
|
@ -429,22 +470,52 @@ gint64
|
||||||
gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
|
gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
|
||||||
gint64 position)
|
gint64 position)
|
||||||
{
|
{
|
||||||
gint64 result, time;
|
gint64 result;
|
||||||
|
gdouble abs_applied_rate;
|
||||||
|
|
||||||
g_return_val_if_fail (segment != NULL, -1);
|
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)
|
if (segment->format == GST_FORMAT_UNDEFINED)
|
||||||
segment->format = format;
|
segment->format = format;
|
||||||
else
|
else
|
||||||
g_return_val_if_fail (segment->format == format, -1);
|
g_return_val_if_fail (segment->format == format, -1);
|
||||||
|
|
||||||
if ((time = segment->time) == -1)
|
/* outside of the segment boundary stop */
|
||||||
time = 0;
|
if (segment->stop != -1 && position >= segment->stop)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (position != -1 && position >= segment->start)
|
/* before the segment boundary */
|
||||||
result = ((position - segment->start) / segment->abs_rate) + time;
|
if (position < segment->start)
|
||||||
else
|
return -1;
|
||||||
result = -1;
|
|
||||||
|
/* time must be known */
|
||||||
|
if (segment->time == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* bring to uncorrected position in segment */
|
||||||
|
result = position - segment->start;
|
||||||
|
|
||||||
|
abs_applied_rate = ABS (segment->applied_rate);
|
||||||
|
|
||||||
|
/* correct for applied rate if needed */
|
||||||
|
if (abs_applied_rate != 1.0)
|
||||||
|
result *= abs_applied_rate;
|
||||||
|
|
||||||
|
/* add or subtract from segment time based on applied rate */
|
||||||
|
if (segment->applied_rate > 0.0) {
|
||||||
|
/* correct for segment time */
|
||||||
|
result += segment->time;
|
||||||
|
} else {
|
||||||
|
/* correct for segment time, clamp at 0 */
|
||||||
|
if (segment->time > result)
|
||||||
|
result = segment->time - result;
|
||||||
|
else
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -456,14 +527,18 @@ gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
|
||||||
* @position: the position in the segment
|
* @position: the position in the segment
|
||||||
*
|
*
|
||||||
* Translate @position to the total running time using the currently configured
|
* Translate @position to the total running time using the currently configured
|
||||||
* and previously accumulated segments.
|
* and previously accumulated segments. Position is a value between @segment
|
||||||
|
* start and stop time.
|
||||||
*
|
*
|
||||||
* This function is typically used by elements that need to synchronize to the
|
* This function is typically used by elements that need to synchronize to the
|
||||||
* global clock in a pipeline. The runnning time is a constantly increasing value
|
* global clock in a pipeline. The runnning time is a constantly increasing value
|
||||||
* starting from 0. When gst_segment_init() is called, this value will reset to
|
* starting from 0. When gst_segment_init() is called, this value will reset to
|
||||||
* 0.
|
* 0.
|
||||||
*
|
*
|
||||||
* Returns: the position as the total running time.
|
* This function returns -1 if the position is outside of @segment start and stop.
|
||||||
|
*
|
||||||
|
* Returns: the position as the total running time or -1 when an invalid position
|
||||||
|
* was given.
|
||||||
*/
|
*/
|
||||||
gint64
|
gint64
|
||||||
gst_segment_to_running_time (GstSegment * segment, GstFormat format,
|
gst_segment_to_running_time (GstSegment * segment, GstFormat format,
|
||||||
|
@ -473,15 +548,42 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
|
||||||
|
|
||||||
g_return_val_if_fail (segment != NULL, -1);
|
g_return_val_if_fail (segment != NULL, -1);
|
||||||
|
|
||||||
|
if (position == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (segment->format == GST_FORMAT_UNDEFINED)
|
if (segment->format == GST_FORMAT_UNDEFINED)
|
||||||
segment->format = format;
|
segment->format = format;
|
||||||
else if (segment->accum)
|
else if (segment->accum)
|
||||||
g_return_val_if_fail (segment->format == format, -1);
|
g_return_val_if_fail (segment->format == format, -1);
|
||||||
|
|
||||||
if (position != -1 && position >= segment->start)
|
/* before the segment boundary */
|
||||||
result = ((position - segment->start) / segment->abs_rate) + segment->accum;
|
if (position < segment->start)
|
||||||
else
|
return -1;
|
||||||
result = -1;
|
|
||||||
|
if (segment->rate > 0.0) {
|
||||||
|
/* outside of the segment boundary stop */
|
||||||
|
if (segment->stop != -1 && position >= segment->stop)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* bring to uncorrected position in segment */
|
||||||
|
result = position - segment->start;
|
||||||
|
} else {
|
||||||
|
/* cannot continue if no stop position set or outside of
|
||||||
|
* the segment. */
|
||||||
|
if (segment->stop == -1 || position >= segment->stop)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* bring to uncorrected position in segment */
|
||||||
|
result = segment->stop - position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scale based on the rate, avoid division by and conversion to
|
||||||
|
* float when not needed */
|
||||||
|
if (segment->abs_rate != 1.0)
|
||||||
|
result /= segment->abs_rate;
|
||||||
|
|
||||||
|
/* correct for accumulated segments */
|
||||||
|
result += segment->accum;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -496,7 +598,8 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
|
||||||
* @clip_stop: the clipped stop position in the segment
|
* @clip_stop: the clipped stop position in the segment
|
||||||
*
|
*
|
||||||
* Clip the given @start and @stop values to the segment boundaries given
|
* Clip the given @start and @stop values to the segment boundaries given
|
||||||
* in @segment.
|
* in @segment. @start and @stop are compared and clipped to @segment
|
||||||
|
* start and stop values.
|
||||||
*
|
*
|
||||||
* If the function returns FALSE, @start and @stop are known to fall
|
* If the function returns FALSE, @start and @stop are known to fall
|
||||||
* outside of @segment and @clip_start and @clip_stop are not updated.
|
* outside of @segment and @clip_start and @clip_stop are not updated.
|
||||||
|
|
|
@ -35,7 +35,7 @@ typedef struct _GstSegment GstSegment;
|
||||||
/**
|
/**
|
||||||
* GstSegment:
|
* GstSegment:
|
||||||
* @rate: the rate of the segment
|
* @rate: the rate of the segment
|
||||||
* @abs_rate: absolute value of the rate
|
* @abs_rate: absolute value of @rate
|
||||||
* @format: the format of the segment values
|
* @format: the format of the segment values
|
||||||
* @flags: flags for this segment
|
* @flags: flags for this segment
|
||||||
* @start: the start of the segment
|
* @start: the start of the segment
|
||||||
|
@ -44,6 +44,7 @@ typedef struct _GstSegment GstSegment;
|
||||||
* @accum: accumulated segment
|
* @accum: accumulated segment
|
||||||
* @last_stop: last known stop time
|
* @last_stop: last known stop time
|
||||||
* @duration: total duration of segment
|
* @duration: total duration of segment
|
||||||
|
* @applied_rate: the already applied rate to the segment
|
||||||
*
|
*
|
||||||
* A helper structure that holds the configured region of
|
* A helper structure that holds the configured region of
|
||||||
* interest in a media file.
|
* interest in a media file.
|
||||||
|
@ -62,8 +63,12 @@ struct _GstSegment {
|
||||||
gint64 last_stop;
|
gint64 last_stop;
|
||||||
gint64 duration;
|
gint64 duration;
|
||||||
|
|
||||||
|
/* API added 0.10.6 */
|
||||||
|
gdouble applied_rate;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
//gpointer _gst_reserved[GST_PADDING-2];
|
||||||
|
guint8 _gst_reserved[(sizeof (gpointer) * GST_PADDING) - sizeof (gdouble)];
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_segment_get_type (void);
|
GType gst_segment_get_type (void);
|
||||||
|
@ -84,6 +89,9 @@ void gst_segment_set_seek (GstSegment *segment, gdouble rate,
|
||||||
|
|
||||||
void gst_segment_set_newsegment (GstSegment *segment, gboolean update, gdouble rate,
|
void gst_segment_set_newsegment (GstSegment *segment, gboolean update, gdouble rate,
|
||||||
GstFormat format, gint64 start, gint64 stop, gint64 time);
|
GstFormat format, gint64 start, gint64 stop, gint64 time);
|
||||||
|
void gst_segment_set_newsegment_full (GstSegment *segment, gboolean update, gdouble rate,
|
||||||
|
gdouble applied_rate, GstFormat format, gint64 start,
|
||||||
|
gint64 stop, gint64 time);
|
||||||
|
|
||||||
gint64 gst_segment_to_stream_time (GstSegment *segment, GstFormat format, gint64 position);
|
gint64 gst_segment_to_stream_time (GstSegment *segment, GstFormat format, gint64 position);
|
||||||
gint64 gst_segment_to_running_time (GstSegment *segment, GstFormat format, gint64 position);
|
gint64 gst_segment_to_running_time (GstSegment *segment, GstFormat format, gint64 position);
|
||||||
|
|
|
@ -700,7 +700,7 @@ gst_base_sink_configure_segment (GstBaseSink * basesink, GstPad * pad,
|
||||||
GstEvent * event, GstSegment * segment)
|
GstEvent * event, GstSegment * segment)
|
||||||
{
|
{
|
||||||
gboolean update;
|
gboolean update;
|
||||||
gdouble rate;
|
gdouble rate, arate;
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
gint64 start;
|
gint64 start;
|
||||||
gint64 stop;
|
gint64 stop;
|
||||||
|
@ -708,7 +708,7 @@ gst_base_sink_configure_segment (GstBaseSink * basesink, GstPad * pad,
|
||||||
|
|
||||||
/* the newsegment event is needed to bring the buffer timestamps to the
|
/* the newsegment event is needed to bring the buffer timestamps to the
|
||||||
* stream time and to drop samples outside of the playback segment. */
|
* stream time and to drop samples outside of the playback segment. */
|
||||||
gst_event_parse_new_segment (event, &update, &rate, &format,
|
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||||
&start, &stop, &time);
|
&start, &stop, &time);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (basesink);
|
GST_OBJECT_LOCK (basesink);
|
||||||
|
@ -716,7 +716,8 @@ gst_base_sink_configure_segment (GstBaseSink * basesink, GstPad * pad,
|
||||||
if (segment->format != format)
|
if (segment->format != format)
|
||||||
gst_segment_init (segment, format);
|
gst_segment_init (segment, format);
|
||||||
|
|
||||||
gst_segment_set_newsegment (segment, update, rate, format, start, stop, time);
|
gst_segment_set_newsegment_full (segment, update, rate, arate, format, start,
|
||||||
|
stop, time);
|
||||||
|
|
||||||
if (format == GST_FORMAT_TIME) {
|
if (format == GST_FORMAT_TIME) {
|
||||||
GST_DEBUG_OBJECT (basesink,
|
GST_DEBUG_OBJECT (basesink,
|
||||||
|
@ -2289,7 +2290,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
|
||||||
|
|
||||||
base = GST_ELEMENT_CAST (basesink)->base_time;
|
base = GST_ELEMENT_CAST (basesink)->base_time;
|
||||||
accum = basesink->segment.accum;
|
accum = basesink->segment.accum;
|
||||||
rate = basesink->segment.rate;
|
rate = basesink->segment.rate * basesink->segment.applied_rate;
|
||||||
gst_base_sink_get_position_last (basesink, &last);
|
gst_base_sink_get_position_last (basesink, &last);
|
||||||
|
|
||||||
gst_object_ref (clock);
|
gst_object_ref (clock);
|
||||||
|
@ -2301,7 +2302,8 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
|
||||||
now = gst_clock_get_time (clock);
|
now = gst_clock_get_time (clock);
|
||||||
/* subtract base time and accumulated time from the clock time.
|
/* subtract base time and accumulated time from the clock time.
|
||||||
* Make sure we don't go negative. This is the current time in
|
* Make sure we don't go negative. This is the current time in
|
||||||
* the segment which we need to scale with the rate */
|
* the segment which we need to scale with the combined
|
||||||
|
* rate and applied rate. */
|
||||||
base += accum;
|
base += accum;
|
||||||
base = MIN (now, base);
|
base = MIN (now, base);
|
||||||
/* for negative rate this will count back from the segment time */
|
/* for negative rate this will count back from the segment time */
|
||||||
|
|
|
@ -1170,18 +1170,18 @@ gst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event)
|
||||||
case GST_EVENT_NEWSEGMENT:
|
case GST_EVENT_NEWSEGMENT:
|
||||||
{
|
{
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
gdouble rate;
|
gdouble rate, arate;
|
||||||
gint64 start, stop, time;
|
gint64 start, stop, time;
|
||||||
gboolean update;
|
gboolean update;
|
||||||
|
|
||||||
gst_event_parse_new_segment (event, &update, &rate, &format, &start,
|
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||||
&stop, &time);
|
&start, &stop, &time);
|
||||||
|
|
||||||
if (trans->segment.format != format)
|
if (trans->segment.format != format)
|
||||||
gst_segment_init (&trans->segment, format);
|
gst_segment_init (&trans->segment, format);
|
||||||
|
|
||||||
gst_segment_set_newsegment (&trans->segment, update, rate, format, start,
|
gst_segment_set_newsegment_full (&trans->segment, update, rate, arate,
|
||||||
stop, time);
|
format, start, stop, time);
|
||||||
|
|
||||||
trans->have_newsegment = TRUE;
|
trans->have_newsegment = TRUE;
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ GST_START_TEST (create_custom_events)
|
||||||
}
|
}
|
||||||
/* NEWSEGMENT */
|
/* NEWSEGMENT */
|
||||||
{
|
{
|
||||||
gdouble rate;
|
gdouble rate, applied_rate;
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
gint64 start, end, base;
|
gint64 start, end, base;
|
||||||
gboolean update;
|
gboolean update;
|
||||||
|
@ -82,8 +82,42 @@ GST_START_TEST (create_custom_events)
|
||||||
fail_unless (end == G_MAXINT64);
|
fail_unless (end == G_MAXINT64);
|
||||||
fail_unless (base == 0xdeadbeef);
|
fail_unless (base == 0xdeadbeef);
|
||||||
|
|
||||||
|
/* Check that the new segment was created with applied_rate of 1.0 */
|
||||||
|
gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
|
||||||
|
&format, &start, &end, &base);
|
||||||
|
|
||||||
|
fail_unless (update == FALSE);
|
||||||
|
fail_unless (rate == 0.5);
|
||||||
|
fail_unless (applied_rate == 1.0);
|
||||||
|
fail_unless (format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (start == 1);
|
||||||
|
fail_unless (end == G_MAXINT64);
|
||||||
|
|
||||||
|
gst_event_unref (event);
|
||||||
|
|
||||||
|
event =
|
||||||
|
gst_event_new_new_segment_full (TRUE, 0.75, 0.5, GST_FORMAT_BYTES, 0,
|
||||||
|
G_MAXINT64 - 1, 0xdeadbeef);
|
||||||
|
|
||||||
|
fail_if (event == NULL);
|
||||||
|
fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
|
||||||
|
fail_if (GST_EVENT_IS_UPSTREAM (event));
|
||||||
|
fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
|
||||||
|
fail_unless (GST_EVENT_IS_SERIALIZED (event));
|
||||||
|
|
||||||
|
gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
|
||||||
|
&format, &start, &end, &base);
|
||||||
|
|
||||||
|
fail_unless (update == TRUE);
|
||||||
|
fail_unless (rate == 0.75);
|
||||||
|
fail_unless (applied_rate == 0.5);
|
||||||
|
fail_unless (format == GST_FORMAT_BYTES);
|
||||||
|
fail_unless (start == 0);
|
||||||
|
fail_unless (end == (G_MAXINT64 - 1));
|
||||||
|
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TAGS */
|
/* TAGS */
|
||||||
{
|
{
|
||||||
GstTagList *taglist = gst_tag_list_new ();
|
GstTagList *taglist = gst_tag_list_new ();
|
||||||
|
|
|
@ -53,7 +53,7 @@ GST_START_TEST (segment_seek_nosize)
|
||||||
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
|
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
|
||||||
fail_unless (res == FALSE);
|
fail_unless (res == FALSE);
|
||||||
|
|
||||||
/* touching lower bound */
|
/* touching lower bound, still outside of the segment */
|
||||||
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
|
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
|
||||||
fail_unless (res == FALSE);
|
fail_unless (res == FALSE);
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ GST_START_TEST (segment_seek_nosize)
|
||||||
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
|
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
|
||||||
fail_unless (res == FALSE);
|
fail_unless (res == FALSE);
|
||||||
|
|
||||||
/* start outside */
|
/* start outside, we don't know the stop */
|
||||||
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
|
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
|
||||||
fail_unless (res == TRUE);
|
fail_unless (res == TRUE);
|
||||||
fail_unless (cstart == 100);
|
fail_unless (cstart == 100);
|
||||||
|
@ -108,7 +108,8 @@ GST_START_TEST (segment_seek_nosize)
|
||||||
fail_unless (segment.stop == 300);
|
fail_unless (segment.stop == 300);
|
||||||
|
|
||||||
/* add 100 to start (to 300), set stop to 200, this is not allowed.
|
/* add 100 to start (to 300), set stop to 200, this is not allowed.
|
||||||
* nothing should be updated in the segment. */
|
* nothing should be updated in the segment. A g_warning is
|
||||||
|
* emited. */
|
||||||
ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
|
ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
|
||||||
GST_FORMAT_BYTES,
|
GST_FORMAT_BYTES,
|
||||||
GST_SEEK_FLAG_NONE,
|
GST_SEEK_FLAG_NONE,
|
||||||
|
@ -417,7 +418,7 @@ GST_START_TEST (segment_newsegment_open)
|
||||||
fail_unless (segment.time == 100);
|
fail_unless (segment.time == 100);
|
||||||
fail_unless (segment.accum == 100);
|
fail_unless (segment.accum == 100);
|
||||||
|
|
||||||
/* last_stop unknown, accum does not change */
|
/* last_stop 0, accum does not change */
|
||||||
gst_segment_set_newsegment (&segment, FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
|
gst_segment_set_newsegment (&segment, FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
|
||||||
|
|
||||||
fail_unless (segment.start == 0);
|
fail_unless (segment.start == 0);
|
||||||
|
@ -498,6 +499,778 @@ GST_START_TEST (segment_newsegment_closed)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* mess with the segment structure in the time format */
|
||||||
|
GST_START_TEST (segment_newsegment_streamtime)
|
||||||
|
{
|
||||||
|
GstSegment segment;
|
||||||
|
gint64 result;
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
* Normal segment
|
||||||
|
***************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 1.0);
|
||||||
|
fail_unless (segment.applied_rate == 1.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 0);
|
||||||
|
fail_unless (segment.accum == 0);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* time shifted by 500
|
||||||
|
*********************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 500);
|
||||||
|
|
||||||
|
fail_unless (segment.accum == 200);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 500);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 600);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 500);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* time offset by 500
|
||||||
|
*********************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 500, 700, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.accum == 400);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* before segment is invalid */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 500);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 600);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 700);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 800);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
* time offset by 500, shifted by 200
|
||||||
|
*************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 500, 700, 200);
|
||||||
|
|
||||||
|
fail_unless (segment.accum == 600);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* before segment is invalid */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 500);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 600);
|
||||||
|
fail_unless (result == 300);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 700);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 800);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* mess with the segment structure in the time format */
|
||||||
|
GST_START_TEST (segment_newsegment_streamtime_rate)
|
||||||
|
{
|
||||||
|
GstSegment segment;
|
||||||
|
gint64 result;
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
* Normal segment rate 2.0
|
||||||
|
***************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 2.0);
|
||||||
|
fail_unless (segment.applied_rate == 1.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 0);
|
||||||
|
fail_unless (segment.accum == 0);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 150);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* Normal segment rate 2.0, offset
|
||||||
|
***************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 100, 300, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.accum == 100);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 250);
|
||||||
|
fail_unless (result == 150);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* Normal segment rate -1.0, offset
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
/* buffers will arrive from 300 to 100 in a sink, stream time
|
||||||
|
* calculation is unaffected by the rate */
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 100, 300, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.accum == 200);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
* Normal segment rate -1.0, offset, time = 200
|
||||||
|
***********************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 100, 300, 200);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == 300);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* mess with the segment structure in the time format */
|
||||||
|
GST_START_TEST (segment_newsegment_streamtime_applied_rate)
|
||||||
|
{
|
||||||
|
GstSegment segment;
|
||||||
|
gint64 result;
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Normal segment rate 1.0, applied rate -1.0
|
||||||
|
* This means the timestamps represents a stream going backwards
|
||||||
|
* starting from @time to 0.
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 200);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 1.0);
|
||||||
|
fail_unless (segment.applied_rate == -1.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 200);
|
||||||
|
fail_unless (segment.accum == 0);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* we count backwards from 200 */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 50);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Normal segment rate 1.0, applied rate 2.0
|
||||||
|
* This means the timestamps represents a stream at twice the
|
||||||
|
* normal rate
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 2.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 1.0);
|
||||||
|
fail_unless (segment.applied_rate == 2.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 0);
|
||||||
|
fail_unless (segment.accum == 200);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
/* the stream prepresents a stream going twice as fast, the position
|
||||||
|
* in the segment is therefore scaled by the applied rate */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 300);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Normal segment rate 1.0, applied rate -2.0
|
||||||
|
* This means the timestamps represents a stream at twice the
|
||||||
|
* reverse rate
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -2.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 400);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 1.0);
|
||||||
|
fail_unless (segment.applied_rate == -2.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 400);
|
||||||
|
/* previous segment lasted 200, rate of 2.0 was already applied */
|
||||||
|
fail_unless (segment.accum == 400);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* we count backwards from 400 */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 400);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Normal segment rate 1.0, applied rate -2.0
|
||||||
|
* This means the timestamps represents a stream at twice the
|
||||||
|
* reverse rate, start time cannot compensate the complete
|
||||||
|
* duration of the segment so we stop at 0
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -2.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 200);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 1.0);
|
||||||
|
fail_unless (segment.applied_rate == -2.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 200);
|
||||||
|
fail_unless (segment.accum == 600);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* we count backwards from 200 */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
/* clamp at 0 */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* mess with the segment structure in the time format */
|
||||||
|
GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
|
||||||
|
{
|
||||||
|
GstSegment segment;
|
||||||
|
gint64 result;
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Segment rate 2.0, applied rate 2.0
|
||||||
|
* this means we have a double speed stream that we should
|
||||||
|
* speed up by a factor of 2.0 some more. the resulting
|
||||||
|
* stream will be played at four times the speed.
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 2.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 2.0);
|
||||||
|
fail_unless (segment.applied_rate == 2.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 0);
|
||||||
|
fail_unless (segment.accum == 0);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* only applied rate affects our calculation of the stream time */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 300);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Segment rate 2.0, applied rate -1.0
|
||||||
|
* this means we have a reverse stream that we should
|
||||||
|
* speed up by a factor of 2.0
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 2.0, -1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 200);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 2.0);
|
||||||
|
fail_unless (segment.applied_rate == -1.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 200);
|
||||||
|
/* previous segment lasted 100 */
|
||||||
|
fail_unless (segment.accum == 100);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* only applied rate affects our calculation of the stream time */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 50);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Segment rate -1.0, applied rate -1.0
|
||||||
|
* this means we have a reverse stream that we should
|
||||||
|
* reverse to get the normal stream again.
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, -1.0, -1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 200);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == -1.0);
|
||||||
|
fail_unless (segment.applied_rate == -1.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 200);
|
||||||
|
/* accumulated 100 of previous segment to make 200 */
|
||||||
|
fail_unless (segment.accum == 200);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* only applied rate affects our calculation of the stream time */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 50);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Segment rate -1.0, applied rate -1.0
|
||||||
|
* this means we have a reverse stream that we should
|
||||||
|
* reverse to get the normal stream again.
|
||||||
|
************************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 2.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == -1.0);
|
||||||
|
fail_unless (segment.applied_rate == 2.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 0);
|
||||||
|
fail_unless (segment.accum == 400);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* only applied rate affects our calculation of the stream time */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
|
||||||
|
fail_unless (result == 300);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* mess with the segment structure in the time format */
|
||||||
|
GST_START_TEST (segment_newsegment_runningtime)
|
||||||
|
{
|
||||||
|
GstSegment segment;
|
||||||
|
gint64 result;
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
* Normal segment
|
||||||
|
***************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 0);
|
||||||
|
|
||||||
|
fail_unless (segment.rate == 1.0);
|
||||||
|
fail_unless (segment.applied_rate == 1.0);
|
||||||
|
fail_unless (segment.format == GST_FORMAT_TIME);
|
||||||
|
fail_unless (segment.flags == 0);
|
||||||
|
fail_unless (segment.start == 0);
|
||||||
|
fail_unless (segment.stop == 200);
|
||||||
|
fail_unless (segment.time == 0);
|
||||||
|
fail_unless (segment.accum == 0);
|
||||||
|
fail_unless (segment.last_stop == 0);
|
||||||
|
fail_unless (segment.duration == -1);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 0);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 100);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 300);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* time shifted by 500, check if accumulation worked.
|
||||||
|
* Rate convert to twice the speed which means scaling down
|
||||||
|
* all positions by 2.0 in this segment.
|
||||||
|
* Then time argument is not used at all here.
|
||||||
|
***********************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 0, 200, 500);
|
||||||
|
|
||||||
|
/* normal speed gives elapsed of 200 */
|
||||||
|
fail_unless (segment.accum == 200);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 0);
|
||||||
|
fail_unless (result == 200);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless (result == 250);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/********************************************
|
||||||
|
* time offset by 500
|
||||||
|
* applied rate is not used for running time
|
||||||
|
********************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 2.0,
|
||||||
|
GST_FORMAT_TIME, 500, 700, 0);
|
||||||
|
|
||||||
|
/* previous segment played at double speed gives elapsed time of
|
||||||
|
* 100 added to previous accum of 200 gives 300. */
|
||||||
|
fail_unless (segment.accum == 300);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* before segment is invalid */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
|
||||||
|
fail_unless (result == 300);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
|
||||||
|
fail_unless (result == 400);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
* time offset by 500, shifted by 200
|
||||||
|
* Negative rate makes the running time go backwards
|
||||||
|
* relative to the segment stop position. again time
|
||||||
|
* is ignored.
|
||||||
|
**********************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
|
||||||
|
GST_FORMAT_TIME, 500, 700, 200);
|
||||||
|
|
||||||
|
fail_unless (segment.accum == 500);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* before segment is invalid */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
|
||||||
|
fail_unless (result == 700);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
|
||||||
|
fail_unless (result == 600);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
* time offset by 500, shifted by 200
|
||||||
|
* Negative rate makes the running time go backwards at
|
||||||
|
* twice speed relative to the segment stop position. again
|
||||||
|
* time is ignored.
|
||||||
|
**********************************************************/
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -2.0,
|
||||||
|
GST_FORMAT_TIME, 500, 700, 200);
|
||||||
|
|
||||||
|
fail_unless (segment.accum == 700);
|
||||||
|
|
||||||
|
/* invalid time gives invalid result */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* before segment is invalid */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* total scaled segment time is 100, accum is 700, so we get 800 */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
|
||||||
|
fail_unless (result == 800);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
|
||||||
|
fail_unless (result == 750);
|
||||||
|
|
||||||
|
/* outside of the segment */
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
|
||||||
|
fail_unless (result == -1);
|
||||||
|
|
||||||
|
/* see if negative rate closed segment correctly */
|
||||||
|
gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -1.0,
|
||||||
|
GST_FORMAT_TIME, 500, 700, 200);
|
||||||
|
|
||||||
|
/* previous segment lasted 100, and was at 700 so we should get 800 */
|
||||||
|
fail_unless (segment.accum == 800);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
Suite *
|
Suite *
|
||||||
gstsegments_suite (void)
|
gstsegments_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -511,6 +1284,12 @@ gstsegments_suite (void)
|
||||||
tcase_add_test (tc_chain, segment_seek_size);
|
tcase_add_test (tc_chain, segment_seek_size);
|
||||||
tcase_add_test (tc_chain, segment_newsegment_open);
|
tcase_add_test (tc_chain, segment_newsegment_open);
|
||||||
tcase_add_test (tc_chain, segment_newsegment_closed);
|
tcase_add_test (tc_chain, segment_newsegment_closed);
|
||||||
|
tcase_add_test (tc_chain, segment_newsegment_streamtime);
|
||||||
|
tcase_add_test (tc_chain, segment_newsegment_streamtime_rate);
|
||||||
|
tcase_add_test (tc_chain, segment_newsegment_streamtime_applied_rate);
|
||||||
|
tcase_add_test (tc_chain, segment_newsegment_streamtime_applied_rate_rate);
|
||||||
|
tcase_add_test (tc_chain, segment_newsegment_runningtime);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue