Commit b9dbb551 authored by Wim Taymans's avatar Wim Taymans

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

Original commit message from CVS:
* docs/design/part-overview.txt:
Make upsteam/downstream concepts more clear.
Give an example of serialized/non-serialized events.
* docs/design/part-events.txt:
* docs/design/part-streams.txt:
Mention applied_rate.
* docs/design/part-trickmodes.txt:
Mention applied rate, flesh out some more use cases.
* gst/gstevent.c: (gst_event_new_new_segment),
(gst_event_parse_new_segment), (gst_event_new_new_segment_full),
(gst_event_parse_new_segment_full), (gst_event_new_tag),
(gst_event_parse_tag), (gst_event_new_buffer_size),
(gst_event_parse_buffer_size), (gst_event_new_qos),
(gst_event_parse_qos), (gst_event_parse_seek),
(gst_event_new_navigation):
* gst/gstevent.h:
Add applied_rate field to NEWSEGMENT event.
API: gst_event_new_new_segment_full()
API: gst_event_parse_new_segment_full()
* gst/gstsegment.c: (gst_segment_init), (gst_segment_set_seek),
(gst_segment_set_newsegment), (gst_segment_set_newsegment_full),
(gst_segment_to_stream_time), (gst_segment_to_running_time):
* gst/gstsegment.h:
Add applied_rate to GstSegment structure.
Make calculation of stream_time and running_time more correct
wrt rate/applied_rate.
Add some more docs.
API: GstSegment::applied_rate field
API: gst_segment_set_newsegment_full();
* libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment),
(gst_base_sink_get_sync_times), (gst_base_sink_get_position):
* libs/gst/base/gstbasetransform.c:
(gst_base_transform_sink_eventfunc),
(gst_base_transform_handle_buffer):
Parse and use applied_rate in the GstSegment field.
* tests/check/gst/gstevent.c: (GST_START_TEST):
Add check for applied_rate field.
* tests/check/gst/gstsegment.c: (GST_START_TEST),
(gstsegments_suite):
Add more checks for various GstSegment operations.
parent 029c8d82
2006-05-08 Wim Taymans <wim@fluendo.com>
* docs/design/part-overview.txt:
Make upsteam/downstream concepts more clear.
Give an example of serialized/non-serialized events.
* docs/design/part-events.txt:
* docs/design/part-streams.txt:
Mention applied_rate.
* docs/design/part-trickmodes.txt:
Mention applied rate, flesh out some more use cases.
* gst/gstevent.c: (gst_event_new_new_segment),
(gst_event_parse_new_segment), (gst_event_new_new_segment_full),
(gst_event_parse_new_segment_full), (gst_event_new_tag),
(gst_event_parse_tag), (gst_event_new_buffer_size),
(gst_event_parse_buffer_size), (gst_event_new_qos),
(gst_event_parse_qos), (gst_event_parse_seek),
(gst_event_new_navigation):
* gst/gstevent.h:
Add applied_rate field to NEWSEGMENT event.
API: gst_event_new_new_segment_full()
API: gst_event_parse_new_segment_full()
* gst/gstsegment.c: (gst_segment_init), (gst_segment_set_seek),
(gst_segment_set_newsegment), (gst_segment_set_newsegment_full),
(gst_segment_to_stream_time), (gst_segment_to_running_time):
* gst/gstsegment.h:
Add applied_rate to GstSegment structure.
Make calculation of stream_time and running_time more correct
wrt rate/applied_rate.
Add some more docs.
API: GstSegment::applied_rate field
API: gst_segment_set_newsegment_full();
* libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment),
(gst_base_sink_get_sync_times), (gst_base_sink_get_position):
* libs/gst/base/gstbasetransform.c:
(gst_base_transform_sink_eventfunc),
(gst_base_transform_handle_buffer):
Parse and use applied_rate in the GstSegment field.
* tests/check/gst/gstevent.c: (GST_START_TEST):
Add check for applied_rate field.
* tests/check/gst/gstsegment.c: (GST_START_TEST),
(gstsegments_suite):
Add more checks for various GstSegment operations.
2006-05-08 Wim Taymans <wim@fluendo.com>
* libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times),
......
......@@ -101,7 +101,7 @@ NEWSEGMENT
A newsegment event is sent downstream by an element to indicate that the following
group of buffers start and end at the specified positions. The newsegment event
also contains the playback speed of the stream.
also contains the playback speed and the applied rate of the stream.
Since the stream time is always set to 0 at start and after a seek, a 0
point for all next buffer's timestamps has to be propagated through the
......@@ -134,6 +134,7 @@ streamtime of the pipeline will not be reset to 0 so any element that syncs
to the clock must use the stop times of the previous newsegment events to
make the buffer timestamps increasing (part-segments.txt).
TAG
---
......
......@@ -29,11 +29,15 @@ Introduction
an example of an ogg/vorbis playback pipeline.
+-----------------------------------------------------------+
| ----------> downstream -------------------> |
| |
| pipeline |
| +---------+ +----------+ +-----------+ +----------+ |
| | filesrc | | oggdemux | | vorbisdec | | alsasink | |
| | src-sink src-sink src-sink | |
| +---------+ +----------+ +-----------+ +----------+ |
| |
| <---------< upstream <-------------------< |
+-----------------------------------------------------------+
The filesrc element reads data from a file on disk. The oggdemux element parses
......@@ -244,7 +248,14 @@ Dataflow and events
the events are used to denote special conditions in the dataflow such as EOS or
to inform plugins of special events such as flushing or seeking.
Some events must be serialized with the buffer flow, others don't.
Some events must be serialized with the buffer flow, others don't. Serialized
events are inserted between the buffers. Non serialized events jump in front
of any buffers current being processed.
An example of a serialized event is a TAG event that is inserted between buffers
to mark metadata for those buffers.
An example of a non serialized event is the FLUSH event.
Pipeline construction
......
......@@ -36,6 +36,7 @@ Typical stream
- marks valid buffer timestamp range (start, stop)
- marks stream_time of buffers (time)
- marks playback rate (rate)
- marks applied rate (applied_rate)
2) N buffers
- displayable buffers are between start/stop of the NEW_SEGMENT
......
......@@ -69,11 +69,15 @@ When performing a seek, the following steps have to be taken by the application:
For client side trickmode a NEW_SEGMENT event will be sent downstream with
the new rate and start/stop positions. All elements prepare themselves to
handle the rate (see below).
handle the rate (see below). The applied rate of the NEW_SEGMENT event will
be set to 1.0 to indicate that no rate adjustment has been done.
for server side trick mode a NEW_SEGMENT event is sent downstream with a
rate of 1.0 and the start/stop positions. The elements will configure themselves
for normal playback speed since the server will perform the rate conversions.
The applied rate will be set to the rate that will be applied by the server. This
is done to insure that the position reporting performed in the sink is aware
of the trick mode.
When the seek succeeds, the _send_event() function will return TRUE.
......@@ -95,9 +99,12 @@ The rate value in the segment should be used to reopen the connection to the ser
requesting data at the new speed and possibly a new playback position.
When the server connection was successfully reopened, set the rate of the segment
to 1.0 so that the client side trickmode is not enabled. Alternatively a combination
of client side and serverside trickmode can be used, for example if the server does
not support certain rates, the client can perform rate conversion for the remainder.
to 1.0 so that the client side trickmode is not enabled. The applied rate in the
segment is set to the rate transformation done by the server.
Alternatively a combination of client side and serverside trickmode can be used, for
example if the server does not support certain rates, the client can perform rate
conversion for the remainder.
source server
......@@ -117,22 +124,27 @@ not support certain rates, the client can perform rate conversion for the remain
After performing the seek, the source will inform the downstream elements of the
new segment that is to be played back. Since the segment will have a rate of 1.0,
no client side trick modes are enabled.
no client side trick modes are enabled. The segment will have an applied rate
different from 1.0 to indicate that the media contains data with non-standard
playback speed or direction.
client side forward trickmodes
------------------------------
The seek happens as stated above. a NEW_SEGMENT event is sent downstream with a rate
bigger than 1.0. Plugins receiving the NEW_SEGMENT can decide to perform the
different from 1.0. Plugins receiving the NEW_SEGMENT can decide to perform the
rate conversion of the media data (retimestamp video frames, resample audio, ...).
A plugin can also decide to drop frames in the case of fast playback or use a more
efficient decoding algorithm (skip B frames, ...). If a plugin decides to resample
or retimestamp, it should modify the NEW_SEGMENT with a rate of 1.0 so that
downstream elements don't resample again.
or retimestamp, it should modify the NEW_SEGMENT with a rate of 1.0 and update the
applied rate so that downstream elements don't resample again but are aware that the
media has been modified.
The GStreamer base audio and video sinks will resample automatically if they receive
a NEW_SEGMENT event with a rate different from 1.0.
a NEW_SEGMENT event with a rate different from 1.0. The position reporting in the
base audio and video sinks will also depend on the applied rate of the segment
information.
client side backwards trickmode
......@@ -143,6 +155,8 @@ For backwards playback the following rules apply:
- the rate in the NEW_SEGMENT is less than 0.0.
- the NEW_SEGMENT start position is less than the stop position, playback will
however happen from stop to start in reverse.
- the time member in the NEW_SEGMENT is set to the stream time of the start
position.
For plugins the following rules apply:
......@@ -154,8 +168,8 @@ For plugins the following rules apply:
Timestamps on the buffers are set starting from the stop position to start,
effectively going backwards.
- A decoder decodes and accumulates all frames. If a new keyframe is received,
all accumulated frames are sent backwards.
- A decoder decodes and accumulates all frames. If a new keyframe or EOS is received,
all accumulated frames are sent downsteam in reverse.
- A sink reverses (for audio) and retimestamps (audio, video) the buffers before
playing them back. Retimestamping occurs relative to the stop position, making
......
This diff is collapsed.
......@@ -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);
......
This diff is collapsed.
......@@ -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 ();
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment