mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-28 18:18:38 +00:00
Latest begotiation doc
Original commit message from CVS: Latest begotiation doc
This commit is contained in:
parent
d0d6cd30d4
commit
25457e2e39
1 changed files with 148 additions and 80 deletions
|
@ -120,14 +120,15 @@ has been processed by the element.
|
||||||
|
|
||||||
pads are usually created from the templates. When the pad is created
|
pads are usually created from the templates. When the pad is created
|
||||||
it has no GstCaps* attached to it yet. The possible caps this pad
|
it has no GstCaps* attached to it yet. The possible caps this pad
|
||||||
can have is exposed in the padtemplate.
|
can have is exposed in the padtemplate. The caps are filled in by
|
||||||
|
the element when it knows the values for the caps.
|
||||||
|
|
||||||
|
|
||||||
4) the connect function
|
4) the connect function
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
when two pads are connected the following steps will take
|
when two pads are connected the following steps will take
|
||||||
place:
|
placei (not sure, FIXME):
|
||||||
|
|
||||||
- if both pads have caps, the caps are checked. If the caps
|
- if both pads have caps, the caps are checked. If the caps
|
||||||
are incompatible, the padtemplates are checked, if they
|
are incompatible, the padtemplates are checked, if they
|
||||||
|
@ -157,115 +158,182 @@ These caps must follow the following rules:
|
||||||
|
|
||||||
- the caps cannot contain ranges or lists.
|
- the caps cannot contain ranges or lists.
|
||||||
|
|
||||||
by setting the caps of the src pad, the following procedure
|
when the element wants to change the caps of a pad, it has to
|
||||||
happens:
|
perform gst_pad_renegotiate (GstPad *pad). this will trigger
|
||||||
|
the caps negotiation procedure.
|
||||||
|
|
||||||
- if the peer pad has a negotiate function, it is called and
|
this will trigger the class method of the pad and calls the pads
|
||||||
negotiation is performed (see later)
|
gst_pad_negotiate function:
|
||||||
|
|
||||||
- if the peer pad has no negotiate function, the padtemplate
|
GstCaps *gst_pad_negotiate (GstPad *pad, GstCaps *caps, guint count);
|
||||||
is checked:
|
|
||||||
|
|
||||||
- if the caps are compatible with the template, the peer pad
|
This function takes a GstCaps *structure as an argument (typically the
|
||||||
receives the same caps as the src pad.
|
current caps of the pad) and a negotiation counter. this counter can be
|
||||||
|
used to keep track of the negotiation process.
|
||||||
|
|
||||||
- if the caps are not compatible, the negotiation fails and
|
The pad then creates a new caps structure with the desired caps.
|
||||||
the elements are disconnected. A signal is emitted to inform
|
If the caps are accepted, it just returns the provided input caps. the
|
||||||
the user app or the manager of the element to find a solution.
|
_renegotiate function will set the caps of both pads whenever the
|
||||||
|
input caps are the same (pointer wise) as the input caps.
|
||||||
|
|
||||||
the caps can be set with the gst_pad_set_caps function, which accepts
|
the caps structure is checked against the padtemplate of the peer pad,
|
||||||
the following parameters:
|
if it is incompatible the gst_pad_negotiate function is called again
|
||||||
|
and the element is supposed to create another caps structure.
|
||||||
|
|
||||||
- the pad to set the caps to
|
the gst_pad_renegotiate function then calls the gst_pad_negotiate
|
||||||
- a GstCaps* structure
|
function of the peer pad with the new caps as the argument. The peer
|
||||||
|
pad can adjust or create a new caps if it doesn't accept it.
|
||||||
|
|
||||||
example4:
|
the caps structure keeps on bouncing between the two pads until one
|
||||||
!
|
of the pads negotiation functions returns the caps unmodified.
|
||||||
! an audio element setting its src pad caps (need something easier):
|
|
||||||
!
|
|
||||||
! gst_pad_set_caps (
|
|
||||||
! pad,
|
|
||||||
! gst_caps_new_with_props (
|
|
||||||
! "src_caps", /* name */
|
|
||||||
! "audio/raw", /* mime */
|
|
||||||
! gst_props_new (
|
|
||||||
! "format", GST_PROPS_INT (AFMT_S16_LE),
|
|
||||||
! "depth", GST_PROPS_INT (16),
|
|
||||||
! "rate", GST_PROPS_INT (44100),
|
|
||||||
! "channels", GST_PROPS_INT (2),
|
|
||||||
! NULL
|
|
||||||
! )
|
|
||||||
! )
|
|
||||||
! );
|
|
||||||
|
|
||||||
The _set_caps method will trigger the caps negotiation with the
|
The element can also return a NULL pointer if it has run out of
|
||||||
peer pad (if connected).
|
options for the caps structure. When this happens, both pads are set
|
||||||
|
the the NULL caps again and the pad connnection is broken.
|
||||||
|
|
||||||
|
The negotiation process is stopped after a fixed number of tries,
|
||||||
|
when the counter has reached some limit. This limit is typically
|
||||||
|
checked by the pads negotiate function.
|
||||||
|
|
||||||
|
|
||||||
6) caps negotiation function
|
6) caps negotiation function
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
the negotiate function of a pad is called whenever the peer pad
|
the negotiate function of a pad is called whenever the pad or
|
||||||
modifies the caps using the gst_pad_set_caps function.
|
peer pad has performed _renegotiate.
|
||||||
|
|
||||||
The negotiate function has to return a gboolean indicating the
|
|
||||||
new caps are acceptable. When it accepts the caps, both pads will
|
|
||||||
be set to the negotiated caps.
|
|
||||||
|
|
||||||
example5:
|
example5:
|
||||||
!
|
!
|
||||||
! this is the caps negotiation function implemented by an element on
|
! this is the caps negotiation function implemented by an element on
|
||||||
! one of its sink pads.
|
! one of its sink pads.
|
||||||
!
|
!
|
||||||
! static gboolean
|
! static GstCaps*
|
||||||
! gst_pad_caps_negotiate (GstPad *pad, GstCaps *caps)
|
! gst_pad_negotiate (GstPad *pad, GstCaps *caps, guint counter)
|
||||||
! {
|
! {
|
||||||
! /* we don't accept anything else than audio/raw */
|
! /* we don't accept anything else than audio/raw */
|
||||||
! if (strcmp (gst_caps_get_mime (caps), "audio/raw"))
|
! if (strcmp (gst_caps_get_mime (caps), "audio/raw"))
|
||||||
! return FALSE;
|
! return NULL;
|
||||||
!
|
!
|
||||||
! if (gst_caps_get_int_prop (caps, "format") != AFMT_S16_LE)
|
! if (gst_caps_get_int_prop (caps, "format") != AFMT_S16_LE)
|
||||||
! return FALSE;
|
! return NULL;
|
||||||
!
|
!
|
||||||
! /* we accept everything else */
|
! /* we accept everything else */
|
||||||
! return TRUE;
|
! return caps;
|
||||||
! }
|
! }
|
||||||
|
|
||||||
When the negotiate function returns FALSE (it does not accept the
|
When the negotiate function returns NULL (it does not accept the
|
||||||
specified caps of the peer pad),
|
specified caps of the peer pad), the negotiation process is stopped.
|
||||||
|
|
||||||
|
|
||||||
figure1
|
|
||||||
!
|
|
||||||
!
|
|
||||||
! element pad pad->peer
|
|
||||||
! !
|
|
||||||
! ! _negotiate(pad)
|
|
||||||
! !------------------>!
|
|
||||||
! ! gst_pad_negotiate()
|
|
||||||
! !------.
|
|
||||||
! !<-----'
|
|
||||||
! ! _caps_negotiate()
|
|
||||||
! !--------------------->!
|
|
||||||
!
|
|
||||||
!
|
|
||||||
|
|
||||||
|
|
||||||
the element has some of its internal properties changed. It wants
|
|
||||||
to renegotiate the caps with its peer element. The element does:
|
|
||||||
|
|
||||||
gst_pad_renegotiate (element->srcpad);
|
|
||||||
|
|
||||||
this will trigger the class method of the pad and
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
APPENDIX A: use cases
|
||||||
|
=====================
|
||||||
|
|
||||||
7) use cases
|
1) mpg123 src!sink audiosink
|
||||||
------------
|
----------------------------
|
||||||
|
|
||||||
|
When the pads are connected the padtemplates are checked and it
|
||||||
|
turns out that the pads might be incompatible (mpg123 can do
|
||||||
|
48000Hz while audiosink can do 44000Hz). Nothing happens at
|
||||||
|
connect time except for the user app that can mark this connection
|
||||||
|
as possibly dangerous and keep some spare elements ready for when
|
||||||
|
the pads turn out to be incompatible.
|
||||||
|
|
||||||
|
both elements start out with no caps at all (NULL). mpg123 wants
|
||||||
|
to output a buffer with specific properties. It calls
|
||||||
|
gst_pad_renegotiate (mpg123->srcpad).
|
||||||
|
|
||||||
|
The _renegotiate functions calls the negotiate function of the
|
||||||
|
mpg123->srcpad. the negotiate function would look like this:
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The mpg123 element cannot convert the decoded type into something
|
||||||
|
* else so it has to force the caps of the src pad into the specific
|
||||||
|
* type as defined by the mp3.
|
||||||
|
*/
|
||||||
|
static GstCaps*
|
||||||
|
gst_mpeg123_src_negotiate (GstPad *pad, GstCaps *caps, guint counter)
|
||||||
|
{
|
||||||
|
GstMpg123 *mpg123;
|
||||||
|
|
||||||
|
mpg123 = GST_MPG123 (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
/* we got caps in, check them */
|
||||||
|
if (caps != NULL) {
|
||||||
|
if (!strcmp (gst_caps_get_mime (caps), "audio/raw") &&
|
||||||
|
(gst_caps_get_int_prop (caps, "format") == AFMT_S16_LE) &&
|
||||||
|
(gst_caps_get_int_prop (caps, "depth") == 16) &&
|
||||||
|
(gst_caps_get_int_prop (caps, "rate") == mpg123->rate) &&
|
||||||
|
(gst_caps_get_int_prop (caps, "channels") == mpg123->channels)) {
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* we didn't get caps, so we decide */
|
||||||
|
else if (counter != 2) {
|
||||||
|
GstCaps *new;
|
||||||
|
|
||||||
|
/* fill in our desired caps */
|
||||||
|
new = gst_caps_new_with_props (
|
||||||
|
"src_caps", /* name */
|
||||||
|
"audio/raw", /* mime */
|
||||||
|
gst_props_new (
|
||||||
|
"format", GST_PROPS_INT (AFMT_S16_LE),
|
||||||
|
"depth", GST_PROPS_INT (16),
|
||||||
|
"rate", GST_PROPS_INT (mpg123->rate),
|
||||||
|
"channels", GST_PROPS_INT (mpg123->channels),
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
/* too many attempts at nogotiation, bail out */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
The audiosink pad negotiate function would look like this:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The audiosink has a wide range of possible parameters for
|
||||||
|
* its sink pad, based on the audio card capabilities and
|
||||||
|
* possibly the element configuration.
|
||||||
|
* we assume the audiosink element can be both the initiator of
|
||||||
|
* the negotiations and the negotiated one.
|
||||||
|
*/
|
||||||
|
static GstCaps*
|
||||||
|
gst_audiosink_sink_negotiate (GstPad *pad, GstCaps *caps, guint counter)
|
||||||
|
{
|
||||||
|
GstAudiosink *audiosink;
|
||||||
|
gboolean accepted = TRUE;
|
||||||
|
|
||||||
|
audiosink = GST_AUDIOSINK (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
/* we got caps in, we know they will match the padtemplate */
|
||||||
|
if (caps != NULL) {
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
/* we didn't get caps, so we decide */
|
||||||
|
else if (counter != 2) {
|
||||||
|
GstCaps *new;
|
||||||
|
|
||||||
|
/* fill in our desired caps */
|
||||||
|
new = gst_caps_new_with_props (
|
||||||
|
"sink_caps", /* name */
|
||||||
|
"audio/raw", /* mime */
|
||||||
|
gst_props_new (
|
||||||
|
"format", GST_PROPS_INT (audiosink->format),
|
||||||
|
"depth", GST_PROPS_INT (audiosink->depth),
|
||||||
|
"rate", GST_PROPS_INT (audiosink->rate),
|
||||||
|
"channels", GST_PROPS_INT (audiosink->channels),
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
/* too many attempts at nogotiation, bail out */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue