2005-03-28 14:54:33 +00:00
|
|
|
Negotiation
|
|
|
|
-----------
|
|
|
|
|
2007-01-10 21:15:08 +00:00
|
|
|
Capabilities negotiation is the process of deciding on an adequate
|
|
|
|
format for dataflow within a GStreamer pipeline. Ideally, negotiation
|
|
|
|
(also known as "capsnego") transfers information from those parts of the
|
|
|
|
pipeline that have information to those parts of the pipeline that are
|
|
|
|
flexible, constrained by those parts of the pipeline that are not
|
|
|
|
flexible.
|
|
|
|
|
|
|
|
GStreamer's two scheduling modes, push mode and pull mode, lend
|
2007-02-02 11:33:19 +00:00
|
|
|
themselves to different mechanisms to achieve this goal. As it is more
|
2007-01-10 21:15:08 +00:00
|
|
|
common we describe push mode negotiation first.
|
|
|
|
|
|
|
|
Push-mode negotiation
|
2010-11-01 13:32:43 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~
|
2007-01-10 21:15:08 +00:00
|
|
|
|
2007-02-02 11:33:19 +00:00
|
|
|
Push-mode negotiation happens when elements want to push buffers and
|
2007-01-10 21:15:08 +00:00
|
|
|
need to decide on the format. This is called downstream negotiation
|
|
|
|
because the upstream element decides the format for the downstream
|
|
|
|
element. This is the most common case.
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
Negotiation can also happen when a downstream element wants to receive
|
|
|
|
another data format from an upstream element. This is called upstream
|
|
|
|
negotiation.
|
|
|
|
|
|
|
|
The basics of negotiation are as follows:
|
|
|
|
|
2011-06-06 14:11:31 +00:00
|
|
|
- GstCaps (see part-caps.txt) are refcounted before they are pushed as
|
|
|
|
an event to describe the contents of the following buffer.
|
|
|
|
|
|
|
|
- An element should reconfigure itself to the new format received as a CAPS
|
|
|
|
event before processing the following buffers. If the data type in the
|
|
|
|
caps event is not acceptable, the element should refuse the buffer by
|
docs/design/part-negotiation.txt: Small doc update.
Original commit message from CVS:
* docs/design/part-negotiation.txt:
Small doc update.
* docs/libs/gstreamer-libs-sections.txt:
* libs/gst/base/gstbasesink.c: (gst_base_sink_class_init),
(gst_base_sink_pad_getcaps), (gst_base_sink_pad_setcaps),
(gst_base_sink_init), (gst_base_sink_set_blocksize),
(gst_base_sink_get_blocksize), (gst_base_sink_set_property),
(gst_base_sink_get_property), (gst_base_sink_needs_preroll),
(gst_base_sink_loop), (gst_base_sink_pad_activate),
(gst_base_sink_negotiate_pull), (gst_base_sink_pad_activate_pull),
(gst_base_sink_change_state):
* libs/gst/base/gstbasesink.h:
Add blocksize property and methods to control the amount of data
to pull.
Negotiate first before activating upstream in pull mode so that they can
negotiate themselves.
When we operate in pull mode, we only accept the caps that we
negotiated.
Make the sink go ASYNC to PAUSED, like all other sinks.
API: GstBaseSink::gst_base_sink_set_blocksize()
API: GstBaseSink::gst_base_sink_get_blocksize()
API: GstBaseSink::blocksize
* libs/gst/base/gstbasesrc.c: (gst_base_src_wait_playing),
(gst_base_src_set_live), (gst_base_src_is_live),
(gst_base_src_set_format), (gst_base_src_query_latency),
(gst_base_src_set_blocksize), (gst_base_src_get_blocksize),
(gst_base_src_set_do_timestamp), (gst_base_src_get_do_timestamp),
(gst_base_src_set_property), (gst_base_src_get_property):
* libs/gst/base/gstbasesrc.h:
Add typechecking in public API functions.
Add methods to control the blocksize in subclasses.
API: GstBaseSrc::gst_base_src_set_blocksize()
API: GstBaseSrc::gst_base_src_get_blocksize()
2008-10-10 10:01:36 +00:00
|
|
|
returning an appropriate GST_FLOW_NOT_NEGOTIATED return value from the
|
|
|
|
chain function.
|
2005-03-28 14:54:33 +00:00
|
|
|
|
2011-06-07 12:03:29 +00:00
|
|
|
- Downstream elements can request a format change of the stream by sending a
|
2011-06-06 14:11:31 +00:00
|
|
|
RECONFIGURE event upstream. Upstream elements will renegotiate a new format
|
|
|
|
when they receive a RECONFIGURE event.
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
The general flow for a source pad starting the negotiation.
|
|
|
|
|
|
|
|
src sink
|
|
|
|
| |
|
|
|
|
| accepts? |
|
|
|
|
type A |---------------->|
|
|
|
|
| yes |
|
2011-06-06 14:11:31 +00:00
|
|
|
|< - - - - - - - -|
|
2005-03-28 14:54:33 +00:00
|
|
|
| |
|
2011-06-06 14:11:31 +00:00
|
|
|
| send_event() |
|
|
|
|
send CAPS |---------------->| Receive type A, reconfigure to
|
|
|
|
event A | | process type A.
|
2005-03-28 14:54:33 +00:00
|
|
|
| |
|
|
|
|
| push |
|
2011-06-06 14:11:31 +00:00
|
|
|
push buffer |---------------->| Process buffer of type A
|
2005-03-28 14:54:33 +00:00
|
|
|
| |
|
|
|
|
|
|
|
|
One possible implementation in pseudo code:
|
|
|
|
|
|
|
|
[element wants to create a buffer]
|
|
|
|
if not format
|
|
|
|
# see what we can do
|
|
|
|
ourcaps = gst_pad_get_caps (srcpad)
|
2011-06-22 10:26:19 +00:00
|
|
|
# see what the peer can do filtered against our caps
|
|
|
|
candidates = gst_pad_peer_get_caps (srcpad, ourcaps)
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
foreach candidate in candidates
|
|
|
|
# make sure the caps is fixed
|
|
|
|
fixedcaps = gst_pad_fixate_caps (srcpad, candidate)
|
|
|
|
|
|
|
|
# see if the peer accepts it
|
|
|
|
if gst_pad_peer_accept_caps (srcpad, fixedcaps)
|
|
|
|
# store the caps as the negotiated caps, this will
|
|
|
|
# call the setcaps function on the pad
|
2011-06-06 14:11:31 +00:00
|
|
|
gst_pad_push_event (srcpad, gst_event_new_caps (fixedcaps))
|
2005-03-28 14:54:33 +00:00
|
|
|
break
|
|
|
|
endif
|
|
|
|
done
|
|
|
|
endif
|
|
|
|
|
2011-06-22 10:26:19 +00:00
|
|
|
#negotiate allocator/bufferpool with the ALLOCATION query
|
|
|
|
|
|
|
|
buffer = gst_buffer_new_allocate (NULL, size, 0);
|
|
|
|
# fill buffer and push
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
The general flow for a sink pad starting a renegotiation.
|
|
|
|
|
|
|
|
src sink
|
|
|
|
| |
|
|
|
|
| accepts? |
|
2008-06-29 15:00:26 +00:00
|
|
|
|<----------------| type B
|
2005-03-28 14:54:33 +00:00
|
|
|
| yes |
|
2011-06-06 14:11:31 +00:00
|
|
|
|- - - - - - - - >|-.
|
|
|
|
| | | suggest B caps next
|
|
|
|
| |<'
|
2005-03-28 14:54:33 +00:00
|
|
|
| |
|
2011-06-06 14:11:31 +00:00
|
|
|
| push_event() |
|
|
|
|
mark .-|<----------------| send RECONFIGURE event
|
|
|
|
renegotiate| | |
|
|
|
|
'>| |
|
|
|
|
| get_caps() |
|
|
|
|
renegotiate |---------------->|
|
|
|
|
| suggest B |
|
|
|
|
|< - - - - - - - -|
|
|
|
|
| |
|
|
|
|
| send_event() |
|
|
|
|
send CAPS |---------------->| Receive type B, reconfigure to
|
|
|
|
event B | | process type B.
|
2005-03-28 14:54:33 +00:00
|
|
|
| |
|
|
|
|
| push |
|
2011-06-06 14:11:31 +00:00
|
|
|
push buffer |---------------->| Process buffer of type B
|
2005-03-28 14:54:33 +00:00
|
|
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
Use case:
|
|
|
|
|
|
|
|
|
|
|
|
videotestsrc ! xvimagesink
|
|
|
|
|
|
|
|
1) Who decides what format to use?
|
|
|
|
- src pad always decides, by convention. sinkpad can suggest a format
|
|
|
|
by putting it high in the getcaps function GstCaps.
|
|
|
|
- since the src decides, it can always choose something that it can do,
|
|
|
|
so this step can only fail if the sinkpad stated it could accept
|
|
|
|
something while later on it couldn't.
|
|
|
|
|
|
|
|
2) When does negotiation happen?
|
|
|
|
- before srcpad does a push, it figures out a type as stated in 1), then
|
2011-06-06 14:11:31 +00:00
|
|
|
it pushes a caps event with the type. The sink checks the media type and
|
|
|
|
configures itself for this type.
|
|
|
|
- the source then usually does an ALLOCATION query to negotiate a bufferpool
|
|
|
|
with the sink. It then allocates a buffer from the pool and pushes it to
|
|
|
|
the sink. since the sink accepted the caps, it can create a pool for the
|
|
|
|
format.
|
2005-03-28 14:54:33 +00:00
|
|
|
- since the sink stated in 1) it could accept the type, it will be able to
|
2011-06-06 14:11:31 +00:00
|
|
|
handle it.
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
3) How can sink request another format?
|
|
|
|
- sink asks if new format is possible for the source.
|
2011-06-06 14:11:31 +00:00
|
|
|
- sink pushes RECONFIGURE event upstream
|
|
|
|
- src receives the RECONFIGURE event and marks renegotiation
|
|
|
|
- On the next buffer push, the source renegotiates the caps and the
|
|
|
|
bufferpool. The sink will put the new new prefered format high in the list
|
|
|
|
of caps it returns from its getcaps function.
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
videotestsrc ! queue ! xvimagesink
|
|
|
|
|
|
|
|
- queue proxies all accept and getcaps to the other peer pad.
|
2011-06-06 14:11:31 +00:00
|
|
|
- queue proxies the bufferpool
|
|
|
|
- queue proxies the RECONFIGURE event
|
|
|
|
- queue stores CAPS event in the queue. This means that the queue can contain
|
|
|
|
buffers with different types.
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
|
2007-01-10 21:15:08 +00:00
|
|
|
Pull-mode negotiation
|
2010-11-01 13:32:43 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~
|
2007-01-10 21:15:08 +00:00
|
|
|
|
2007-01-12 15:39:57 +00:00
|
|
|
Rationale
|
2010-11-01 13:32:43 +00:00
|
|
|
^^^^^^^^^
|
2007-01-12 15:39:57 +00:00
|
|
|
|
2007-01-10 21:15:08 +00:00
|
|
|
A pipeline in pull mode has different negotiation needs than one
|
|
|
|
activated in push mode. Push mode is optimized for two use cases:
|
|
|
|
|
|
|
|
* Playback of media files, in which the demuxers and the decoders are
|
|
|
|
the points from which format information should disseminate to the
|
|
|
|
rest of the pipeline; and
|
|
|
|
|
|
|
|
* Recording from live sources, in which users are accustomed to putting
|
|
|
|
a capsfilter directly after the source element; thus the caps
|
|
|
|
information flow proceeds from the user, through the potential caps
|
|
|
|
of the source, to the sinks of the pipeline.
|
|
|
|
|
|
|
|
In contrast, pull mode has other typical use cases:
|
|
|
|
|
|
|
|
* Playback from a lossy source, such as RTP, in which more knowledge
|
|
|
|
about the latency of the pipeline can increase quality; or
|
|
|
|
|
|
|
|
* Audio synthesis, in which audio APIs are tuned to producing only the
|
|
|
|
necessary number of samples, typically driven by a hardware interrupt
|
|
|
|
to fill a DMA buffer or a Jack[0] port buffer.
|
|
|
|
|
|
|
|
* Low-latency effects processing, whereby filters should be applied as
|
|
|
|
data is transferred from a ring buffer to a sink instead of
|
|
|
|
beforehand. For example, instead of using the internal alsasink
|
|
|
|
ringbuffer thread in push-mode wavsrc ! volume ! alsasink, placing
|
|
|
|
the volume inside the sound card writer thread via wavsrc !
|
|
|
|
audioringbuffer ! volume ! alsasink.
|
|
|
|
|
|
|
|
[0] http://jackit.sf.net
|
|
|
|
|
2007-01-12 15:39:57 +00:00
|
|
|
The problem with pull mode is that the sink has to know the format in
|
2007-01-10 21:15:08 +00:00
|
|
|
order to know how many bytes to pull via gst_pad_pull_range(). This
|
|
|
|
means that before pulling, the sink must initiate negotation to decide
|
|
|
|
on a format.
|
|
|
|
|
|
|
|
Recalling the principles of capsnego, whereby information must flow from
|
|
|
|
those that have it to those that do not, we see that the two named use
|
|
|
|
cases have different negotiation requirements:
|
|
|
|
|
|
|
|
* RTP and low-latency playback are both like the normal playback case,
|
|
|
|
in which information flows downstream.
|
|
|
|
|
|
|
|
* In audio synthesis, the part of the pipeline that has the most
|
|
|
|
information is the sink, constrained by the capabilities of the graph
|
|
|
|
that feeds it. However the caps are not completely specified; at some
|
|
|
|
point the user has to intervene to choose the sample rate, at least.
|
|
|
|
This can be done externally to gstreamer, as in the jack elements, or
|
2007-01-10 21:24:08 +00:00
|
|
|
internally via a capsfilter, as is customary with live sources.
|
2007-01-10 21:15:08 +00:00
|
|
|
|
|
|
|
Given that sinks potentially need the input of sources, as in the RTP
|
|
|
|
case and at least as a filter in the synthesis case, there must be a
|
2007-01-12 15:39:57 +00:00
|
|
|
negotiation phase before the pull thread is activated. Also, given the
|
|
|
|
low latency offered by pull mode, we want to avoid capsnego from within
|
|
|
|
the pulling thread, in case it causes us to miss our scheduling
|
|
|
|
deadlines.
|
|
|
|
|
2008-10-10 15:12:11 +00:00
|
|
|
The pull thread is usually started in the PAUSED->PLAYING state change. We must
|
|
|
|
be able to complete the negotiation before this state change happens.
|
|
|
|
|
2011-06-06 14:11:31 +00:00
|
|
|
The time to do capsnego, then, is after the SCHEDULING query has succeeded,
|
2008-10-10 15:12:11 +00:00
|
|
|
but before the sink has spawned the pulling thread.
|
2007-01-12 15:39:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
Mechanism
|
2010-11-01 13:32:43 +00:00
|
|
|
^^^^^^^^^
|
2007-01-12 15:39:57 +00:00
|
|
|
|
2008-10-10 15:12:11 +00:00
|
|
|
The sink determines that the upstream elements support pull based scheduling by
|
2011-06-06 14:11:31 +00:00
|
|
|
doing a SCHEDULING query.
|
2008-10-10 15:12:11 +00:00
|
|
|
|
2007-01-12 15:39:57 +00:00
|
|
|
The sink initiates the negotiation process by intersecting the results
|
|
|
|
of gst_pad_get_caps() on its sink pad and its peer src pad. This is the
|
|
|
|
operation performed by gst_pad_get_allowed_caps(). In the simple
|
|
|
|
passthrough case, the peer pad's getcaps() function should return the
|
|
|
|
intersection of calling get_allowed_caps() on all of its sink pads. In
|
|
|
|
this way the sink element knows the capabilities of the entire pipeline.
|
|
|
|
|
|
|
|
The sink element then fixates the resulting caps, if necessary,
|
2011-06-06 14:11:31 +00:00
|
|
|
resulting in the flow caps. From now on, the getcaps function
|
2008-10-10 15:12:11 +00:00
|
|
|
of the sinkpad will only return these fixed caps meaning that upstream elements
|
|
|
|
will only be able to produce this format.
|
2007-01-12 15:39:57 +00:00
|
|
|
|
|
|
|
If the sink element could not set caps on its sink pad, it should post
|
|
|
|
an error message on the bus indicating that negotiation was not
|
|
|
|
possible.
|
|
|
|
|
2008-10-10 15:12:11 +00:00
|
|
|
When negotiation succeeded, the sinkpad and all upstream internally linked pads
|
|
|
|
are activated in pull mode. Typically, this operation will trigger negotiation
|
|
|
|
on the downstream elements, which will now be forced to negotiation to the
|
|
|
|
final fixed desired caps of the sinkpad.
|
|
|
|
|
|
|
|
After these steps, the sink element returns ASYNC from the state change
|
|
|
|
function. The state will commit to PAUSED when the first buffer is received in
|
|
|
|
the sink. This is needed to provide a consistent API to the applications that
|
|
|
|
expect ASYNC return values from sinks but it also allows us to perform the
|
|
|
|
remainder of the negotiation outside of the context of the pulling thread.
|