| A lot of data streams need a few initial buffers to make sense of the |
| data stream. With these initial buffers, it can pick up at any point in |
| the rest of the data stream. |
| |
| Examples: |
| - Vorbis and Theora have three initial Ogg packets |
| - MPEG4 has codec data |
| - GDP protocol serializes the initial new_segment event and the initial caps |
| |
| It is important that elements that get connected after the stream starts, |
| receive these initial buffers. Also, sink elements should know that these |
| initial buffers are necessary for every new "client" of the sink element; |
| for example, multifdsink needs to send these initial buffers before the |
| normal buffers. |
| |
| Currently, this is done by putting a 'streamheader' value on the caps. |
| 'streamheader' is a GST_TYPE_ARRAY of GstBuffer, ie. an ordered list of |
| buffers. |
| |
| The buffers themselves still get pushed as normal buffers, but with the |
| IN_CAPS flag set. This allows elements that do not know about streamheader |
| to still function correctly (ie. filesink and others) |
| |
| It is of course important that these streamheader buffers are not sent twice |
| (once because they're in the caps, and once because they're received as |
| buffers). |
| |
| So, an element that is aware of streamheader in the caps should probably best |
| drop all incoming IN_CAPS buffers. |
| |
| Rules for sending streamheaders: |
| - all streamheader buffers should have IN_CAPS set |
| - from this list of streamheader buffers, a "streamheader" caps field should |
| be created as a GST_TYPE_ARRAY of GstBuffer. This should be done by |
| copying the buffers. |
| (the only important thing about the buffers in this list is the data; |
| other attributes of the buffers get ignored) |
| - each of these buffers should then have these caps set on them. |
| - when all streamheader buffers are collected in the element, pad caps should |
| be set, including this streamheader |
| - streamheader buffers should be sent consecutively, and before any of the |
| data (non-IN_CAPS) buffers they apply to. If necessary, the element |
| should internally queue non-IN_CAPS buffers until the streamheaders |
| are completely assembled. |
| - when new streamheader buffers need to be pushed out, this process is |
| repeated. Receiving a new IN_CAPS buffer after a non-IN_CAPS buffer |
| signifies resetting streamheader, as does the new set_caps with different |
| streamheader right before. (FIXME: it's probably better to explicitly |
| have an event/buffer that clears streamheaders; consider the case of |
| an element like GDP that has created streamheader from the first newsegment |
| and the first caps, and then receives a new tag event that it also wants |
| to put on the streamheader - it should be able to invalidate the previous |
| ones) |
| |
| Elements that can send streamheader caps: |
| - vorbisenc |
| - theoraenc |
| - gdppay |
| |
| Elements that can receive streamheader caps: |
| - multifdsink |
| |
| Elements that can receive and send streamheader caps: |
| - oggmux |
| |
| Elements that could/should use this: |
| - ffenc_mpeg4 (currently uses/sets codec_data) |
| - theoradec, vorbisdec (currently only look at incoming buffers) |
| - oggdemux |
| |
| FUTURE PLANS |
| ------------ |
| The concept of streamheader is more generally applicable. We may want to |
| find a better way of implementing this than having two ways of telling |
| downstream elements about them. Currently an element that is |
| streamheader-aware needs to look both at caps and incoming buffers. |
| |
| One option would be to only rely on the buffer flow, and make all elements |
| aware of a HEADER flag, causing them to keep these buffers around and push |
| them for each new pad link. This needs to be done in every element; a |
| scenario like |
| videotestsrc ! theoraenc |
| where later on an oggmux gets connected, should still work without dropping |
| these header buffers. But similarly, |
| videotestsrc ! theoraenc ! identity |
| with a later connection of oggmux to identity should work. |
| |
| This could tie in with an idea to have pads store some initial data (the |
| first new_segment event, tag events, ...), which at the moment also get |
| dropped on dynamic in-stream links. |