docs/design/part-segments.txt: More docs.

Original commit message from CVS:
* docs/design/part-segments.txt:
More docs.

* gst/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf):
Correctly set caps, even on the subbufer.
This commit is contained in:
Wim Taymans 2005-10-21 15:13:08 +00:00
parent e1a166a584
commit 5cce351ef3
4 changed files with 60 additions and 12 deletions

View file

@ -1,3 +1,11 @@
2005-10-21 Wim Taymans <wim@fluendo.com>
* docs/design/part-segments.txt:
More docs.
* gst/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf):
Correctly set caps, even on the subbufer.
2005-10-21 Wim Taymans <wim@fluendo.com> 2005-10-21 Wim Taymans <wim@fluendo.com>
* docs/gst/gstreamer-docs.sgml: * docs/gst/gstreamer-docs.sgml:

View file

@ -6,8 +6,8 @@ processed. A segment has a start time, a stop time and a processing
rate. rate.
A media stream has a start and a stop time. The start time is A media stream has a start and a stop time. The start time is
always 0 and the stop time is the duration (or -1 if unknown, for example always 0 and the stop time is the total duration (or -1 if unknown,
a live stream). We call this the complete media stream. for example a live stream). We call this the complete media stream.
The segment of the complete media stream can be played by issuing a seek The segment of the complete media stream can be played by issuing a seek
on the stream. The seek has a start time, a stop time and a processing rate. on the stream. The seek has a start time, a stop time and a processing rate.
@ -27,12 +27,20 @@ The purpose of this newsegment is to inform downstream elements of the
requested segment positions. Some elements might produce buffers that fall requested segment positions. Some elements might produce buffers that fall
outside of the segment and that might therefore be discarded or clipped. outside of the segment and that might therefore be discarded or clipped.
Use case: FLUSHING seek
-----------------------
ex. ex.
filesrc ! avidemux ! videodecoder ! videosink filesrc ! avidemux ! videodecoder ! videosink
When doing a seek in this pipeline for a segment 1 to 5 seconds, avidemux
will perform the seek.
When avidemux starts playback of the segment from second 1 to 5, it pushes When avidemux starts playback of the segment from second 1 to 5, it pushes
out a newsegment with 1 and 5 as start and stop times. out a newsegment with 1 and 5 as start and stop times. The stream_time in
the newsegment is also 1 as this is the position we seek to.
The video decoder stores these values internally and forwards them to the The video decoder stores these values internally and forwards them to the
next downstream element (videosink, which also stores the values) next downstream element (videosink, which also stores the values)
@ -48,14 +56,44 @@ outside of the segment and that might therefore be discarded or clipped.
keyframe. It then continues to decode and push frames with timestamps >= 1. keyframe. It then continues to decode and push frames with timestamps >= 1.
When it reaches timestamp 5, it does not decode and push frames anymore. When it reaches timestamp 5, it does not decode and push frames anymore.
The video sink receives a frame of timestamp 1. It takes the start value of
the previous newsegment and aplies the folowing formula:
render_time = BUFFER_TIMESTAMP - segment_start + element->base_time
It then syncs against the clock with this render_time. Not that
BUFFER_TIMESTAMP is always >= segment_start or else it would fall outside of
the configure segment.
Videosink reports its current position as:
current_position = clock_time - element->base_time + segment_time
Since after a flushing seek the stream_time is reset to 0, the new buffer
will be rendered immediatly after the seek and the current_position will be
the stream_time of the seek that was performed.
The stop time is important when the video format contains B frames. The The stop time is important when the video format contains B frames. The
video decoder receives a P frame first, which is can decode but not push yet. video decoder receives a P frame first, which is can decode but not push yet.
When it receives a B frame, it can decode the B frame and push the B frame When it receives a B frame, it can decode the B frame and push the B frame
followed by the previously decoded P frame. If the P frame is outside of the followed by the previously decoded P frame. If the P frame is outside of the
segment, the decoder knows it should not send the P frame. segment, the decoder knows it should not send the P frame.
Avidemux stops sending data after pushing frame with timestamp 5 and pushes Avidemux stops sending data after pushing a frame with timestamp 5 and pushes
an EOS event downstream to finish playback. an EOS event downstream to finish playback.
Use case: live stream
---------------------
Use case: segment looping
-------------------------
Consider the case of a wav file with raw audio.
filesrc ! wavparse ! alsasink

View file

@ -246,9 +246,10 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
/* Buffer has no caps. See if the output pad only supports fixed caps */ /* Buffer has no caps. See if the output pad only supports fixed caps */
GstCaps *out_caps; GstCaps *out_caps;
if (GST_PAD_CAPS (trans->srcpad) != NULL) { out_caps = GST_PAD_CAPS (trans->srcpad);
gst_caps_ref (GST_PAD_CAPS (trans->srcpad));
out_caps = GST_PAD_CAPS (trans->srcpad); if (out_caps != NULL) {
gst_caps_ref (out_caps);
} else { } else {
out_caps = gst_pad_get_allowed_caps (trans->srcpad); out_caps = gst_pad_get_allowed_caps (trans->srcpad);
g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR); g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
@ -264,7 +265,7 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps"); GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps");
*buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input)); *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
} }
GST_BUFFER_CAPS (input) = out_caps; GST_BUFFER_CAPS (*buf) = out_caps;
if (GST_PAD_CAPS (trans->srcpad) == NULL) if (GST_PAD_CAPS (trans->srcpad) == NULL)
gst_pad_set_caps (trans->srcpad, out_caps); gst_pad_set_caps (trans->srcpad, out_caps);

View file

@ -246,9 +246,10 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
/* Buffer has no caps. See if the output pad only supports fixed caps */ /* Buffer has no caps. See if the output pad only supports fixed caps */
GstCaps *out_caps; GstCaps *out_caps;
if (GST_PAD_CAPS (trans->srcpad) != NULL) { out_caps = GST_PAD_CAPS (trans->srcpad);
gst_caps_ref (GST_PAD_CAPS (trans->srcpad));
out_caps = GST_PAD_CAPS (trans->srcpad); if (out_caps != NULL) {
gst_caps_ref (out_caps);
} else { } else {
out_caps = gst_pad_get_allowed_caps (trans->srcpad); out_caps = gst_pad_get_allowed_caps (trans->srcpad);
g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR); g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
@ -264,7 +265,7 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps"); GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps");
*buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input)); *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
} }
GST_BUFFER_CAPS (input) = out_caps; GST_BUFFER_CAPS (*buf) = out_caps;
if (GST_PAD_CAPS (trans->srcpad) == NULL) if (GST_PAD_CAPS (trans->srcpad) == NULL)
gst_pad_set_caps (trans->srcpad, out_caps); gst_pad_set_caps (trans->srcpad, out_caps);