mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +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>
|
||||
|
||||
* libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times),
|
||||
|
|
|
@ -101,7 +101,7 @@ NEWSEGMENT
|
|||
|
||||
A newsegment event is sent downstream by an element to indicate that the following
|
||||
group of buffers start and end at the specified positions. The newsegment event
|
||||
also contains the playback speed of the stream.
|
||||
also contains the playback speed and the applied rate of the stream.
|
||||
|
||||
Since the stream time is always set to 0 at start and after a seek, a 0
|
||||
point for all next buffer's timestamps has to be propagated through the
|
||||
|
@ -134,6 +134,7 @@ streamtime of the pipeline will not be reset to 0 so any element that syncs
|
|||
to the clock must use the stop times of the previous newsegment events to
|
||||
make the buffer timestamps increasing (part-segments.txt).
|
||||
|
||||
|
||||
TAG
|
||||
---
|
||||
|
||||
|
|
|
@ -29,11 +29,15 @@ Introduction
|
|||
an example of an ogg/vorbis playback pipeline.
|
||||
|
||||
+-----------------------------------------------------------+
|
||||
| ----------> downstream -------------------> |
|
||||
| |
|
||||
| pipeline |
|
||||
| +---------+ +----------+ +-----------+ +----------+ |
|
||||
| | filesrc | | oggdemux | | vorbisdec | | alsasink | |
|
||||
| | src-sink src-sink src-sink | |
|
||||
| +---------+ +----------+ +-----------+ +----------+ |
|
||||
| |
|
||||
| <---------< upstream <-------------------< |
|
||||
+-----------------------------------------------------------+
|
||||
|
||||
The filesrc element reads data from a file on disk. The oggdemux element parses
|
||||
|
@ -244,7 +248,14 @@ Dataflow and events
|
|||
the events are used to denote special conditions in the dataflow such as EOS or
|
||||
to inform plugins of special events such as flushing or seeking.
|
||||
|
||||
Some events must be serialized with the buffer flow, others don't.
|
||||
Some events must be serialized with the buffer flow, others don't. Serialized
|
||||
events are inserted between the buffers. Non serialized events jump in front
|
||||
of any buffers current being processed.
|
||||
|
||||
An example of a serialized event is a TAG event that is inserted between buffers
|
||||
to mark metadata for those buffers.
|
||||
|
||||
An example of a non serialized event is the FLUSH event.
|
||||
|
||||
|
||||
Pipeline construction
|
||||
|
|
|
@ -36,6 +36,7 @@ Typical stream
|
|||
- marks valid buffer timestamp range (start, stop)
|
||||
- marks stream_time of buffers (time)
|
||||
- marks playback rate (rate)
|
||||
- marks applied rate (applied_rate)
|
||||
|
||||
2) N buffers
|
||||
- displayable buffers are between start/stop of the NEW_SEGMENT
|
||||
|
|
|
@ -69,11 +69,15 @@ When performing a seek, the following steps have to be taken by the application:
|
|||
|
||||
For client side trickmode a NEW_SEGMENT event will be sent downstream with
|
||||
the new rate and start/stop positions. All elements prepare themselves to
|
||||
handle the rate (see below).
|
||||
handle the rate (see below). The applied rate of the NEW_SEGMENT event will
|
||||
be set to 1.0 to indicate that no rate adjustment has been done.
|
||||
|
||||
for server side trick mode a NEW_SEGMENT event is sent downstream with a
|
||||
rate of 1.0 and the start/stop positions. The elements will configure themselves
|
||||
for normal playback speed since the server will perform the rate conversions.
|
||||
The applied rate will be set to the rate that will be applied by the server. This
|
||||
is done to insure that the position reporting performed in the sink is aware
|
||||
of the trick mode.
|
||||
|
||||
When the seek succeeds, the _send_event() function will return TRUE.
|
||||
|
||||
|
@ -95,9 +99,12 @@ The rate value in the segment should be used to reopen the connection to the ser
|
|||
requesting data at the new speed and possibly a new playback position.
|
||||
|
||||
When the server connection was successfully reopened, set the rate of the segment
|
||||
to 1.0 so that the client side trickmode is not enabled. Alternatively a combination
|
||||
of client side and serverside trickmode can be used, for example if the server does
|
||||
not support certain rates, the client can perform rate conversion for the remainder.
|
||||
to 1.0 so that the client side trickmode is not enabled. The applied rate in the
|
||||
segment is set to the rate transformation done by the server.
|
||||
|
||||
Alternatively a combination of client side and serverside trickmode can be used, for
|
||||
example if the server does not support certain rates, the client can perform rate
|
||||
conversion for the remainder.
|
||||
|
||||
|
||||
source server
|
||||
|
@ -117,22 +124,27 @@ not support certain rates, the client can perform rate conversion for the remain
|
|||
|
||||
After performing the seek, the source will inform the downstream elements of the
|
||||
new segment that is to be played back. Since the segment will have a rate of 1.0,
|
||||
no client side trick modes are enabled.
|
||||
no client side trick modes are enabled. The segment will have an applied rate
|
||||
different from 1.0 to indicate that the media contains data with non-standard
|
||||
playback speed or direction.
|
||||
|
||||
|
||||
client side forward trickmodes
|
||||
------------------------------
|
||||
|
||||
The seek happens as stated above. a NEW_SEGMENT event is sent downstream with a rate
|
||||
bigger than 1.0. Plugins receiving the NEW_SEGMENT can decide to perform the
|
||||
different from 1.0. Plugins receiving the NEW_SEGMENT can decide to perform the
|
||||
rate conversion of the media data (retimestamp video frames, resample audio, ...).
|
||||
A plugin can also decide to drop frames in the case of fast playback or use a more
|
||||
efficient decoding algorithm (skip B frames, ...). If a plugin decides to resample
|
||||
or retimestamp, it should modify the NEW_SEGMENT with a rate of 1.0 so that
|
||||
downstream elements don't resample again.
|
||||
or retimestamp, it should modify the NEW_SEGMENT with a rate of 1.0 and update the
|
||||
applied rate so that downstream elements don't resample again but are aware that the
|
||||
media has been modified.
|
||||
|
||||
The GStreamer base audio and video sinks will resample automatically if they receive
|
||||
a NEW_SEGMENT event with a rate different from 1.0.
|
||||
a NEW_SEGMENT event with a rate different from 1.0. The position reporting in the
|
||||
base audio and video sinks will also depend on the applied rate of the segment
|
||||
information.
|
||||
|
||||
|
||||
client side backwards trickmode
|
||||
|
@ -143,6 +155,8 @@ For backwards playback the following rules apply:
|
|||
- the rate in the NEW_SEGMENT is less than 0.0.
|
||||
- the NEW_SEGMENT start position is less than the stop position, playback will
|
||||
however happen from stop to start in reverse.
|
||||
- the time member in the NEW_SEGMENT is set to the stream time of the start
|
||||
position.
|
||||
|
||||
For plugins the following rules apply:
|
||||
|
||||
|
@ -154,8 +168,8 @@ For plugins the following rules apply:
|
|||
Timestamps on the buffers are set starting from the stop position to start,
|
||||
effectively going backwards.
|
||||
|
||||
- A decoder decodes and accumulates all frames. If a new keyframe is received,
|
||||
all accumulated frames are sent backwards.
|
||||
- A decoder decodes and accumulates all frames. If a new keyframe or EOS is received,
|
||||
all accumulated frames are sent downsteam in reverse.
|
||||
|
||||
- A sink reverses (for audio) and retimestamps (audio, video) the buffers before
|
||||
playing them back. Retimestamping occurs relative to the stop position, making
|
||||
|
|
150
gst/gstevent.c
150
gst/gstevent.c
|
@ -416,31 +416,94 @@ gst_event_new_eos (void)
|
|||
* @stop: the stop value of the segment
|
||||
* @position: stream position
|
||||
*
|
||||
* Allocate a new newsegment event with the given format/values tripplets.
|
||||
* Allocate a new newsegment event with the given format/values tripplets
|
||||
*
|
||||
* The newsegment event marks the range of buffers to be processed. All
|
||||
* data not within the segment range is not to be processed. This can be
|
||||
* used intelligently by plugins to use more efficient methods of skipping
|
||||
* 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.
|
||||
* This method calls gst_event_new_new_segment_full() passing a default
|
||||
* value of 1.0 for applied_rate
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
|
||||
gint64 start, gint64 stop, gint64 position)
|
||||
{
|
||||
return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
|
||||
stop, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_parse_new_segment:
|
||||
* @event: The event to query
|
||||
* @update: A pointer to the update flag of the segment
|
||||
* @rate: A pointer to the rate of the segment
|
||||
* @format: A pointer to the format of the newsegment values
|
||||
* @start: A pointer to store the start value in
|
||||
* @stop: A pointer to store the stop value in
|
||||
* @position: A pointer to store the stream time in
|
||||
*
|
||||
* Get the update flag, rate, format, start, stop and position in the
|
||||
* newsegment event. In general, gst_event_parse_new_segment_full() should
|
||||
* be used instead of this, to also retrieve the applied_rate value of the
|
||||
* segment. See gst_event_new_new_segment_full() for a full description
|
||||
* of the newsegment event.
|
||||
*/
|
||||
void
|
||||
gst_event_parse_new_segment (GstEvent * event, gboolean * update,
|
||||
gdouble * rate, GstFormat * format, gint64 * start,
|
||||
gint64 * stop, gint64 * position)
|
||||
{
|
||||
gst_event_parse_new_segment_full (event, update, rate, NULL, format, start,
|
||||
stop, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_new_segment_full:
|
||||
* @update: Whether this segment is an update to a previous one
|
||||
* @rate: A new rate for playback
|
||||
* @applied_rate: The rate factor which has already been applied
|
||||
* @format: The format of the segment values
|
||||
* @start: The start value of the segment
|
||||
* @stop: The stop value of the segment
|
||||
* @position: stream position
|
||||
*
|
||||
* Allocate a new newsegment event with the given format/values triplets.
|
||||
*
|
||||
* The newsegment event marks the range of buffers to be processed. All
|
||||
* data not within the segment range is not to be processed. This can be
|
||||
* used intelligently by plugins to 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 (applied_rate != 0.0, NULL);
|
||||
|
||||
if (format == GST_FORMAT_TIME) {
|
||||
GST_CAT_INFO (GST_CAT_EVENT,
|
||||
|
@ -455,6 +518,7 @@ gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
|
|||
"start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
|
||||
G_GINT64_FORMAT, update, rate, format, start, stop, position);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (position != -1, NULL);
|
||||
g_return_val_if_fail (start != -1, NULL);
|
||||
if (stop != -1)
|
||||
|
@ -464,6 +528,7 @@ gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
|
|||
gst_structure_new ("GstEventNewsegment",
|
||||
"update", G_TYPE_BOOLEAN, update,
|
||||
"rate", G_TYPE_DOUBLE, rate,
|
||||
"applied_rate", G_TYPE_DOUBLE, applied_rate,
|
||||
"format", GST_TYPE_FORMAT, format,
|
||||
"start", G_TYPE_INT64, start,
|
||||
"stop", G_TYPE_INT64, stop,
|
||||
|
@ -471,21 +536,26 @@ gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
|
|||
}
|
||||
|
||||
/**
|
||||
* gst_event_parse_new_segment:
|
||||
* gst_event_parse_new_segment_full:
|
||||
* @event: The event to query
|
||||
* @update: A pointer to the update flag of the segment
|
||||
* @rate: A pointer to the rate of the segment
|
||||
* @applied_rate: A pointer to the applied_rate of the segment
|
||||
* @format: A pointer to the format of the newsegment values
|
||||
* @start: A pointer to store the start value in
|
||||
* @stop: A pointer to store the stop value in
|
||||
* @position: A pointer to store the stream time in
|
||||
*
|
||||
* Get the format, start, stop and position in the newsegment event.
|
||||
* Get the update, rate, applied_rate, format, start, stop and
|
||||
* position in the newsegment event. See gst_event_new_new_segment_full()
|
||||
* for a full description of the newsegment event.
|
||||
*
|
||||
* Since: 0.10.6
|
||||
*/
|
||||
void
|
||||
gst_event_parse_new_segment (GstEvent * event, gboolean * update,
|
||||
gdouble * rate, GstFormat * format, gint64 * start,
|
||||
gint64 * stop, gint64 * position)
|
||||
gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
|
||||
gdouble * rate, gdouble * applied_rate, GstFormat * format,
|
||||
gint64 * start, gint64 * stop, gint64 * position)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
|
@ -493,18 +563,22 @@ gst_event_parse_new_segment (GstEvent * event, gboolean * update,
|
|||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
if (update)
|
||||
if (G_LIKELY (update))
|
||||
*update =
|
||||
g_value_get_boolean (gst_structure_get_value (structure, "update"));
|
||||
if (rate)
|
||||
if (G_LIKELY (rate))
|
||||
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
|
||||
if (format)
|
||||
if (G_LIKELY (applied_rate))
|
||||
*applied_rate =
|
||||
g_value_get_double (gst_structure_get_value (structure,
|
||||
"applied_rate"));
|
||||
if (G_LIKELY (format))
|
||||
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
|
||||
if (start)
|
||||
if (G_LIKELY (start))
|
||||
*start = g_value_get_int64 (gst_structure_get_value (structure, "start"));
|
||||
if (stop)
|
||||
if (G_LIKELY (stop))
|
||||
*stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
|
||||
if (position)
|
||||
if (G_LIKELY (position))
|
||||
*position =
|
||||
g_value_get_int64 (gst_structure_get_value (structure, "position"));
|
||||
}
|
||||
|
@ -521,7 +595,6 @@ GstEvent *
|
|||
gst_event_new_tag (GstTagList * taglist)
|
||||
{
|
||||
g_return_val_if_fail (taglist != NULL, NULL);
|
||||
|
||||
return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
|
||||
}
|
||||
|
||||
|
@ -537,7 +610,6 @@ gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
|
|||
{
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
|
||||
|
||||
if (taglist)
|
||||
*taglist = (GstTagList *) event->structure;
|
||||
}
|
||||
|
@ -565,7 +637,6 @@ gst_event_new_buffer_size (GstFormat format, gint64 minsize,
|
|||
"creating buffersize format %d, minsize %" G_GINT64_FORMAT
|
||||
", maxsize %" G_GINT64_FORMAT ", async %d", format,
|
||||
minsize, maxsize, async);
|
||||
|
||||
return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
|
||||
gst_structure_new ("GstEventBufferSize",
|
||||
"format", GST_TYPE_FORMAT, format,
|
||||
|
@ -592,7 +663,6 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
|
|||
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
if (format)
|
||||
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
|
||||
|
@ -645,9 +715,9 @@ gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
|
|||
GstClockTime timestamp)
|
||||
{
|
||||
GST_CAT_INFO (GST_CAT_EVENT,
|
||||
"creating qos proportion %lf, diff %" GST_TIME_FORMAT
|
||||
"creating qos proportion %lf, diff %" G_GINT64_FORMAT
|
||||
", timestamp %" GST_TIME_FORMAT, proportion,
|
||||
GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
|
||||
diff, GST_TIME_ARGS (timestamp));
|
||||
|
||||
return gst_event_new_custom (GST_EVENT_QOS,
|
||||
gst_structure_new ("GstEventQOS",
|
||||
|
@ -673,7 +743,6 @@ gst_event_parse_qos (GstEvent * event, gdouble * proportion,
|
|||
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
if (proportion)
|
||||
*proportion =
|
||||
|
@ -761,16 +830,14 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
|
|||
* Parses a seek @event and stores the results in the given result locations.
|
||||
*/
|
||||
void
|
||||
gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
|
||||
GstSeekFlags * flags,
|
||||
GstSeekType * cur_type, gint64 * cur,
|
||||
GstSeekType * stop_type, gint64 * stop)
|
||||
gst_event_parse_seek (GstEvent * event, gdouble * rate,
|
||||
GstFormat * format, GstSeekFlags * flags, GstSeekType * cur_type,
|
||||
gint64 * cur, GstSeekType * stop_type, gint64 * stop)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
g_return_if_fail (GST_IS_EVENT (event));
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
if (rate)
|
||||
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
|
||||
|
@ -802,6 +869,5 @@ GstEvent *
|
|||
gst_event_new_navigation (GstStructure * structure)
|
||||
{
|
||||
g_return_val_if_fail (structure != NULL, NULL);
|
||||
|
||||
return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
|
||||
}
|
||||
|
|
|
@ -368,12 +368,25 @@ GstEvent* gst_event_new_new_segment (gboolean update, gdouble rate,
|
|||
GstFormat format,
|
||||
gint64 start, gint64 stop,
|
||||
gint64 position);
|
||||
GstEvent* gst_event_new_new_segment_full (gboolean update, gdouble rate,
|
||||
gdouble applied_rate,
|
||||
GstFormat format,
|
||||
gint64 start, gint64 stop,
|
||||
gint64 position);
|
||||
void gst_event_parse_new_segment (GstEvent *event,
|
||||
gboolean *update,
|
||||
gdouble *rate,
|
||||
GstFormat *format,
|
||||
gint64 *start, gint64 *stop,
|
||||
gint64 *position);
|
||||
void gst_event_parse_new_segment_full (GstEvent *event,
|
||||
gboolean *update,
|
||||
gdouble *rate,
|
||||
gdouble *applied_rate,
|
||||
GstFormat *format,
|
||||
gint64 *start, gint64 *stop,
|
||||
gint64 *position);
|
||||
|
||||
/* tag event */
|
||||
GstEvent* gst_event_new_tag (GstTagList *taglist);
|
||||
void gst_event_parse_tag (GstEvent *event, GstTagList **taglist);
|
||||
|
|
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
|
||||
* that will be used as the format of the segment values. The segment will be configured
|
||||
* with a start value of 0 and a stop/duration of -1, which is undefined. The default
|
||||
* rate is 1.0.
|
||||
* rate and applied_rate is 1.0.
|
||||
*
|
||||
* If the segment is used for managing seeks, the segment duration should be set with
|
||||
* gst_segment_set_duration(). The public duration field contains the duration of the
|
||||
* segment.
|
||||
* segment. When using the segment for seeking, the start and time members should
|
||||
* normally be left to their default 0 value. The stop position is left to -1 unless
|
||||
* explicitly configured to a different value after a seek event.
|
||||
*
|
||||
* The current position in the segment should be set with the gst_segment_set_last_stop().
|
||||
* The public last_stop field contains the last set stop position in the segment.
|
||||
|
@ -71,13 +73,14 @@
|
|||
*
|
||||
* For elements that want to synchronize to the pipeline clock, gst_segment_to_running_time()
|
||||
* can be used to convert a timestamp to a value that can be used to synchronize
|
||||
* to the clock. This function takes into account all accumulated segments.
|
||||
* to the clock. This function takes into account all accumulated segments as well as
|
||||
* any rate or applied_rate conversions.
|
||||
*
|
||||
* For elements that need to perform operations on media data in stream_time,
|
||||
* gst_segment_to_stream_time() can be used to convert a timestamp and the segment
|
||||
* info to stream time (which is always between 0 and the duration of the stream).
|
||||
*
|
||||
* Last reviewed on 2006-03-12 (0.10.5)
|
||||
* Last reviewed on 2006-05-03 (0.10.6)
|
||||
*/
|
||||
|
||||
static GstSegment *
|
||||
|
@ -154,6 +157,7 @@ gst_segment_init (GstSegment * segment, GstFormat format)
|
|||
|
||||
segment->rate = 1.0;
|
||||
segment->abs_rate = 1.0;
|
||||
segment->applied_rate = 1.0;
|
||||
segment->format = format;
|
||||
segment->flags = 0;
|
||||
segment->start = 0;
|
||||
|
@ -235,6 +239,10 @@ gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
|
|||
* from GST_SEEK_TYPE_NONE, the current position is not updated and
|
||||
* streaming should continue from the last position, possibly with
|
||||
* updated rate, flags or stop position.
|
||||
*
|
||||
* The applied rate of the segment will be set to 1.0 by default.
|
||||
* If the caller can apply a rate change, it should update @segment
|
||||
* rate and applied_rate after calling this function.
|
||||
*/
|
||||
void
|
||||
gst_segment_set_seek (GstSegment * segment, gdouble rate,
|
||||
|
@ -324,6 +332,7 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
|
|||
|
||||
segment->rate = rate;
|
||||
segment->abs_rate = ABS (rate);
|
||||
segment->applied_rate = 1.0;
|
||||
segment->flags = flags;
|
||||
segment->start = cur;
|
||||
if (update_start) {
|
||||
|
@ -346,15 +355,41 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
|
|||
* @stop: the new stop value
|
||||
* @time: the new stream time
|
||||
*
|
||||
* Update the segment structure with the field values of a new segment event.
|
||||
* Update the segment structure with the field values of a new segment event and
|
||||
* with a default applied_rate of 1.0.
|
||||
*
|
||||
* Since: 0.10.6
|
||||
*/
|
||||
void
|
||||
gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
|
||||
GstFormat format, gint64 start, gint64 stop, gint64 time)
|
||||
{
|
||||
gst_segment_set_newsegment_full (segment, update, rate, 1.0, format, start,
|
||||
stop, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_segment_set_newsegment_full:
|
||||
* @segment: a #GstSegment structure.
|
||||
* @update: flag indicating a new segment is started or updated
|
||||
* @rate: the rate of the segment.
|
||||
* @applied_rate: the applied rate of the segment.
|
||||
* @format: the format of the segment.
|
||||
* @start: the new start value
|
||||
* @stop: the new stop value
|
||||
* @time: the new stream time
|
||||
*
|
||||
* Update the segment structure with the field values of a new segment event.
|
||||
*/
|
||||
void
|
||||
gst_segment_set_newsegment_full (GstSegment * segment, gboolean update,
|
||||
gdouble rate, gdouble applied_rate, GstFormat format, gint64 start,
|
||||
gint64 stop, gint64 time)
|
||||
{
|
||||
gint64 duration;
|
||||
|
||||
g_return_if_fail (rate != 0.0);
|
||||
g_return_if_fail (applied_rate != 0.0);
|
||||
g_return_if_fail (segment != NULL);
|
||||
|
||||
if (segment->format == GST_FORMAT_UNDEFINED)
|
||||
|
@ -382,23 +417,29 @@ gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
|
|||
* segment. the accumulated time is used when syncing to the
|
||||
* clock.
|
||||
*/
|
||||
if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
|
||||
if (segment->stop != -1) {
|
||||
duration = segment->stop - segment->start;
|
||||
} else if (GST_CLOCK_TIME_IS_VALID (segment->last_stop)) {
|
||||
} else if (segment->last_stop != -1) {
|
||||
/* else use last seen timestamp as segment stop */
|
||||
duration = segment->last_stop - segment->start;
|
||||
} else {
|
||||
/* else we don't know */
|
||||
/* else we don't know and throw a warning.. really, this should
|
||||
* be fixed in the element. */
|
||||
g_warning ("closing segment of unknown duration, assuming duration of 0");
|
||||
duration = 0;
|
||||
}
|
||||
}
|
||||
/* use previous rate to calculate duration */
|
||||
segment->accum += gst_gdouble_to_guint64 (
|
||||
(gst_guint64_to_gdouble (duration) / segment->abs_rate));
|
||||
if (segment->abs_rate != 1.0)
|
||||
duration /= segment->abs_rate;
|
||||
|
||||
/* accumulate duration */
|
||||
segment->accum += duration;
|
||||
|
||||
/* then update the current segment */
|
||||
segment->rate = rate;
|
||||
segment->abs_rate = ABS (rate);
|
||||
segment->applied_rate = applied_rate;
|
||||
segment->start = start;
|
||||
segment->last_stop = start;
|
||||
segment->stop = stop;
|
||||
|
@ -417,8 +458,8 @@ gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
|
|||
*
|
||||
* This function is typically used by elements that need to operate on
|
||||
* the stream time of the buffers it receives, such as effect plugins.
|
||||
* In those use cases, @position is typically the buffer timestamp that
|
||||
* one wants to convert to the stream time.
|
||||
* In those use cases, @position is typically the buffer timestamp or
|
||||
* clock time that one wants to convert to the stream time.
|
||||
* The stream time is always between 0 and the total duration of the
|
||||
* media stream.
|
||||
*
|
||||
|
@ -429,22 +470,52 @@ gint64
|
|||
gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
|
||||
gint64 position)
|
||||
{
|
||||
gint64 result, time;
|
||||
gint64 result;
|
||||
gdouble abs_applied_rate;
|
||||
|
||||
g_return_val_if_fail (segment != NULL, -1);
|
||||
|
||||
/* format does not matter for -1 */
|
||||
if (position == -1)
|
||||
return -1;
|
||||
|
||||
if (segment->format == GST_FORMAT_UNDEFINED)
|
||||
segment->format = format;
|
||||
else
|
||||
g_return_val_if_fail (segment->format == format, -1);
|
||||
|
||||
if ((time = segment->time) == -1)
|
||||
time = 0;
|
||||
/* outside of the segment boundary stop */
|
||||
if (segment->stop != -1 && position >= segment->stop)
|
||||
return -1;
|
||||
|
||||
if (position != -1 && position >= segment->start)
|
||||
result = ((position - segment->start) / segment->abs_rate) + time;
|
||||
else
|
||||
result = -1;
|
||||
/* before the segment boundary */
|
||||
if (position < segment->start)
|
||||
return -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;
|
||||
}
|
||||
|
@ -456,14 +527,18 @@ gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
|
|||
* @position: the position in the segment
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
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);
|
||||
|
||||
if (position == -1)
|
||||
return -1;
|
||||
|
||||
if (segment->format == GST_FORMAT_UNDEFINED)
|
||||
segment->format = format;
|
||||
else if (segment->accum)
|
||||
g_return_val_if_fail (segment->format == format, -1);
|
||||
|
||||
if (position != -1 && position >= segment->start)
|
||||
result = ((position - segment->start) / segment->abs_rate) + segment->accum;
|
||||
else
|
||||
result = -1;
|
||||
/* before the segment boundary */
|
||||
if (position < segment->start)
|
||||
return -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;
|
||||
}
|
||||
|
@ -496,7 +598,8 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
|
|||
* @clip_stop: the clipped stop position in the segment
|
||||
*
|
||||
* 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
|
||||
* outside of @segment and @clip_start and @clip_stop are not updated.
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef struct _GstSegment GstSegment;
|
|||
/**
|
||||
* GstSegment:
|
||||
* @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
|
||||
* @flags: flags for this segment
|
||||
* @start: the start of the segment
|
||||
|
@ -44,6 +44,7 @@ typedef struct _GstSegment GstSegment;
|
|||
* @accum: accumulated segment
|
||||
* @last_stop: last known stop time
|
||||
* @duration: total duration of segment
|
||||
* @applied_rate: the already applied rate to the segment
|
||||
*
|
||||
* A helper structure that holds the configured region of
|
||||
* interest in a media file.
|
||||
|
@ -62,8 +63,12 @@ struct _GstSegment {
|
|||
gint64 last_stop;
|
||||
gint64 duration;
|
||||
|
||||
/* API added 0.10.6 */
|
||||
gdouble applied_rate;
|
||||
|
||||
/*< 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);
|
||||
|
@ -84,6 +89,9 @@ void gst_segment_set_seek (GstSegment *segment, gdouble rate,
|
|||
|
||||
void gst_segment_set_newsegment (GstSegment *segment, gboolean update, gdouble rate,
|
||||
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_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)
|
||||
{
|
||||
gboolean update;
|
||||
gdouble rate;
|
||||
gdouble rate, arate;
|
||||
GstFormat format;
|
||||
gint64 start;
|
||||
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
|
||||
* 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);
|
||||
|
||||
GST_OBJECT_LOCK (basesink);
|
||||
|
@ -716,7 +716,8 @@ gst_base_sink_configure_segment (GstBaseSink * basesink, GstPad * pad,
|
|||
if (segment->format != 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) {
|
||||
GST_DEBUG_OBJECT (basesink,
|
||||
|
@ -2289,7 +2290,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
|
|||
|
||||
base = GST_ELEMENT_CAST (basesink)->base_time;
|
||||
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_object_ref (clock);
|
||||
|
@ -2301,7 +2302,8 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
|
|||
now = gst_clock_get_time (clock);
|
||||
/* subtract base time and accumulated time from the clock time.
|
||||
* 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 = MIN (now, base);
|
||||
/* 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:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate;
|
||||
gdouble rate, arate;
|
||||
gint64 start, stop, time;
|
||||
gboolean update;
|
||||
|
||||
gst_event_parse_new_segment (event, &update, &rate, &format, &start,
|
||||
&stop, &time);
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||
&start, &stop, &time);
|
||||
|
||||
if (trans->segment.format != format)
|
||||
gst_segment_init (&trans->segment, format);
|
||||
|
||||
gst_segment_set_newsegment (&trans->segment, update, rate, format, start,
|
||||
stop, time);
|
||||
gst_segment_set_newsegment_full (&trans->segment, update, rate, arate,
|
||||
format, start, stop, time);
|
||||
|
||||
trans->have_newsegment = TRUE;
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ GST_START_TEST (create_custom_events)
|
|||
}
|
||||
/* NEWSEGMENT */
|
||||
{
|
||||
gdouble rate;
|
||||
gdouble rate, applied_rate;
|
||||
GstFormat format;
|
||||
gint64 start, end, base;
|
||||
gboolean update;
|
||||
|
@ -82,8 +82,42 @@ GST_START_TEST (create_custom_events)
|
|||
fail_unless (end == G_MAXINT64);
|
||||
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);
|
||||
}
|
||||
|
||||
/* TAGS */
|
||||
{
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
fail_unless (res == TRUE);
|
||||
fail_unless (cstart == 100);
|
||||
|
@ -108,7 +108,8 @@ GST_START_TEST (segment_seek_nosize)
|
|||
fail_unless (segment.stop == 300);
|
||||
|
||||
/* 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,
|
||||
GST_FORMAT_BYTES,
|
||||
GST_SEEK_FLAG_NONE,
|
||||
|
@ -417,7 +418,7 @@ GST_START_TEST (segment_newsegment_open)
|
|||
fail_unless (segment.time == 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);
|
||||
|
||||
fail_unless (segment.start == 0);
|
||||
|
@ -498,6 +499,778 @@ GST_START_TEST (segment_newsegment_closed)
|
|||
|
||||
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 *
|
||||
gstsegments_suite (void)
|
||||
{
|
||||
|
@ -511,6 +1284,12 @@ gstsegments_suite (void)
|
|||
tcase_add_test (tc_chain, segment_seek_size);
|
||||
tcase_add_test (tc_chain, segment_newsegment_open);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue