| |
| the current capsnegotiation sucks and plainly doesn't work for queues. |
| one of the reasons is that the core is trying to do too much, like |
| being a mediator in the negotiation process. There is also way too much |
| interaction between plugins. Plugins have to keep a lot of state too. |
| |
| The proposed method works by sending chains of caps instead, requiring |
| a worst case of 2 interactions between plugins. The drawback is that |
| a negotiating plugin has to do a bit more work, but in pactice this is |
| not a real argument against the proposed method, as the actions it has |
| to perform cannot be avoided. We will provide sufficient APIs to |
| facilitate this. |
| |
| We are not going to send random chains of caps between plugins but we |
| are going to filter them by using a new gst_caps_intersect() function |
| that can find the common media types and properties between the plugins. |
| The main idea is that the simple case should remain simple. |
| |
| We also introduce app specific filters that can be set while doing a |
| pad connection. |
| |
| We proceed with a few use cases because they tend to explain the ideas |
| better. |
| |
| |
| use case 1 |
| ---------- |
| |
| v4lsrc -> xvideosink |
| |
| no pad restrictions set on pad_connect |
| v4lsrc can do many formats, so can xvideosink |
| |
| - v4lsrc request caps: |
| |
| width and height properties were set on v4lsrc so it provides them as hints. |
| |
| GstCaps *peercaps = gst_pad_request_caps (v4lsrc->srcpad, |
| GST_CAPS_NEW ( |
| "v4lsrc_srccaps", |
| "video/raw", |
| "width", GST_PROPS_INT (352), |
| "height", GST_PROPS_INT (288))); |
| |
| - core fetches xvideosink caps. if xvideosink has a request_caps function, |
| then the intersection of the hint, v4lsrcpad template caps and xvideosink |
| sinkpad template are sent as input. |
| If xvideosink has no request_caps function, the padtemplate |
| caps of xvideosink are taken. |
| - after intersect on both caps, peercaps equals: |
| |
| peercaps == |
| gst_caps_chain ( |
| GST_CAPS_NEW ( |
| "xvideosink_caps", |
| "video/raw", |
| "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("YV12")), |
| "width", GST_PROPS_INT (352), |
| "height", GST_PROPS_INT (288) |
| ), |
| GST_CAPS_NEW ( |
| "xvideosink_caps", |
| "video/raw", |
| "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("I420")), |
| "width", GST_PROPS_INT (352), |
| "height", GST_PROPS_INT (288) |
| ), |
| GST_CAPS_NEW ( |
| "xvideosink_caps", |
| "video/raw", |
| "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("YUY2")), |
| "width", GST_PROPS_INT (352), |
| "height", GST_PROPS_INT (288) |
| ), |
| GST_CAPS_NEW ( |
| "xvideosink_caps", |
| "video/raw", |
| "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("UYVY")), |
| "width", GST_PROPS_INT (352), |
| "height", GST_PROPS_INT (288) |
| ), |
| GST_CAPS_NEW ( |
| "xvideosink_caps", |
| "video/raw", |
| "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")), |
| "bpp", GST_PROPS_INT (16), |
| "depth", GST_PROPS_INT (16), |
| "endianness", GST_PROPS_INT (G_BYTE_ORDER), |
| "red_mask", GST_PROPS_INT (0xf800), |
| "green_mask", GST_PROPS_INT (0x07e0), |
| "blue_mask", GST_PROPS_INT (0x001f), |
| "width", GST_PROPS_INT (352), |
| "height", GST_PROPS_INT (288) |
| ) |
| ) |
| |
| - v4lsrc does: |
| |
| while (peercaps) { |
| /* check if the caps can be used */ |
| if (caps_are_useful (peercaps)) { |
| break; |
| } |
| ... |
| |
| peercaps = gst_caps_new (peercaps); |
| } |
| |
| gst_pad_set_caps (v4lsrc->srcpad, peercaps); |
| |
| - core check compatibility with v4lsrc and xvideosink caps. if all goes well |
| caps are set on the pads. |
| |
| - negotiation was more effective if v4lsrc provided srcpad caps since maybe |
| YUY2 etc could be removed in the intersect (when v4lsrc doesn't support that |
| format). |
| |
| |
| use case 2 |
| ---------- |
| |
| mpeg2dec -> colorspace -> xvideosink |
| |
| |
| - mpeg2dec does: |
| |
| gst_pad_set_caps (mpeg2dec->srcpad, |
| GST_CAPS_NEW ( |
| "mpeg2dec_srccaps", |
| "video/raw", |
| "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("I420")), |
| "width", GST_PROPS_INT (720), |
| "height", GST_PROPS_INT (480) |
| ) |
| ); |
| |
| - core checks compatibility with mpeg2dec srcpad caps and colorspace caps. |
| - newcaps function of colorspace is called. |
| - colorspace requests peer pad caps with the hint. |
| - xvideosink doesn't have a request_caps function, the hint is ignored and |
| the padtemplate caps are returned. |
| - colorspace runs intersect on the two caps. |
| - if the intersection is NULL, colorspace has to set up a conversion function. |
| - runs through the list of caps, picking the first one for which a |
| converter exists between the received caps and the target caps. set up |
| the converter and set the target caps on the srcpad. |
| - if the intersection is not NULL, set received caps on colorspace srcpad. |
| |
| |
| use case 3 |
| ---------- |
| |
| mpeg2dec -> queue -> colorspace -> queue -> xvideosink |
| |
| |
| Same as use case 2, really. the queue just forwards the caps and the |
| request caps. |
| |
| can we use a default implementation for this proxying? probably. |
| for an element with no newcaps function or request_caps function, we can |
| simply set the caps on all srcpads when a set_caps is performed, or we |
| can request and intersect all srcpad caps when a peer element does |
| request_caps. This will actually work for tee too, to some degree. |
| |
| |
| use case 4 |
| ---------- |
| |
| gst_pad_connect_caps (...), |
| gst_element_connect_caps (v4lsrc, "src", xvideosink, "sink", |
| GST_CAPS_NEW ( |
| "app_caps", |
| "video/raw", |
| "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("I420")), |
| "width", GST_PROPS_INT (352), |
| "height", GST_PROPS_INT (288) |
| ) |
| ); |
| |
| - as long as the connection is not broken, the caps are set as a filter to the |
| to pads. |
| |
| - when v4lsrc requests pads, the intersection with the filter is also made. |
| |
| - v4lsrc has no other choice but to use I420. |
| |
| use case 5 |
| ---------- |
| |
| mad -> osssink |
| |
| in this case, mad can both send "int" audio samples and "float" samples. |
| |
| - mad request_caps from osssink, sending the fixed properties as hints (rate, |
| channels, ...) |
| - osssink has a request_caps function, the core first makes the intersection |
| between the hint and mad srcpad template. the core then does the intersection |
| between osssink sinkpad template and sends this list to osssinks request_caps |
| function. osssink can try this list (or whatever remains of it) and whatever |
| works is sent back as the return value of the request_caps function. |
| - mad receives the caps list, takes the top caps and does a pad_set_caps |
| - osssink recieves the final caps on its new_caps function and configures the |
| oss driver. |
| |
| |
| use case 6 |
| ---------- |
| |
| gsm -> audioscaler -> osssink |
| |
| Somebody sets some crazy low rate on the gsm srcpad (1000Hz). |
| |
| - audioscalers newcaps function is called. |
| - audioscaler does a request_caps on its srcpad with the provided |
| caps as a hint. |
| - osssink tries the caps in the request_caps function (by opening the |
| device, seeing that it doesn't support this rate at all...) |
| - osssink tries to comply as closely with the rate and sends the |
| intersection between its padtemplate caps and the findings (rate 8000Hz |
| is possible). |
| - audioscaler does the intersection between the caps list and the hint. |
| - intersection == NULL, a converter is needed between the hint and |
| the first caps of the request_caps list. |
| - intersection != NULL, set those caps (== the hint). |
| |
| |
| |