mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 18:50:48 +00:00
aa6049eb61
Original commit message from CVS: * docs/gst/Makefile.am: Remove --ignore-fail-on-non-empty (#150331) * docs/libs/Makefile.am: same * docs/gst/tmpl/gstxml.sgml: Remove GstXMLNs * docs/random/ds/0.9-planning: random additions * docs/random/ds/0.9-suggested-changes: same * gst/gstxml.h: remove vestigal GstXMLNs definition Preferred caps: (#147789) * docs/gst/gstreamer-sections.txt: Add symbols * docs/gst/tmpl/gstcaps.sgml: Add symbols * gst/gstcaps.c: (gst_caps_copy), (gst_caps_free), (gst_caps_append), (gst_caps_copy_1), (gst_caps_intersect), (gst_caps_union), (gst_caps_save_thyself), (gst_caps_load_thyself), (gst_caps_get_preferred), (gst_caps_set_preferred), (gst_caps_get_structure_by_id), (gst_caps_prefer_foreach), (gst_caps_use_preferred): Handle caps preferences * gst/gstcaps.h: Add caps preferences * gst/gstpad.c: (gst_pad_link_get_preferred), (gst_pad_link_fixate), (gst_pad_link_call_link_functions), (gst_pad_renegotiate), (gst_pad_guess_preferred), (gst_pad_get_caps), (gst_pad_push): Use caps preferences for negotiation.
165 lines
5.7 KiB
Text
165 lines
5.7 KiB
Text
|
|
|
|
|
|
Scheduling:
|
|
|
|
- remove loop/get/chain from GstElement and add a "iterate" method.
|
|
The iterate method is called with the event (or events) that
|
|
triggered it, performs some action, and resets the events (file
|
|
descriptors becoming readable, semaphores, pads becoming readable
|
|
or writable, or a time occurs).
|
|
|
|
- Add GstLoopElement, GstChainElement, etc. for compatibility.
|
|
|
|
- Remove existing state handling and create 2 states, "playing" and
|
|
"stopped". "playing" means that the iterate() method of the
|
|
element may be called, that is, the element is allowed to move
|
|
buffers, negotiate, etc. "stopped" means that no gstreamer-ish
|
|
things happen to an element, only gobject-ish. A separate
|
|
reset() method will handle the difference between READY and NULL.
|
|
|
|
- Add a flag "ready" to GstElement that is under the control of the
|
|
element. If the element is ready to stream, it sets this flag,
|
|
and the entire pipeline starts streaming. (This is basically
|
|
the difference between PAUSED and PLAYING.) For example, osssink
|
|
won't set the ready flag until the device is opened and there is
|
|
a buffer available to write to the device.
|
|
|
|
- Scheduling of elements and movement of buffers will be timed by
|
|
clocks.
|
|
|
|
|
|
|
|
Example #1:
|
|
|
|
Pipeline: sinesrc ! osssink
|
|
|
|
- The application creates the pipeline and sets it to "playing".
|
|
|
|
- The clock is created and set to "paused".
|
|
|
|
- sinesrc.iterate() decides to watch for the event "src pad
|
|
negotiation" and sets the available caps on the pad.
|
|
|
|
- osssink.iterate() opens device, determines available caps, and
|
|
sets the available caps on the pad. Then it decides to wait for
|
|
"sink pad negotiation".
|
|
|
|
- The scheduler realizes that the two elements are waiting for
|
|
negotiation, so it negotiates the link.
|
|
|
|
- sinesrc.iterate() sets the "ready" flag (because it needs no more
|
|
preparation to stream) and decides to watch for the event "src
|
|
pad ready to accept buffer".
|
|
|
|
- osssink.iterate() decides to watch for the event "sink pad has
|
|
available buffer".
|
|
|
|
- The scheduler realizes that sinesrc.srcpad is now ready, so it
|
|
calls sinesrc.iterate()
|
|
|
|
- sinesrc.iterate() creates a buffer and pushes it, and decides to
|
|
wait for the same event.
|
|
|
|
- The scheduler realizes that osssink.sinkpad now has a buffer, so
|
|
it calls osssink.iterate().
|
|
|
|
- osssink.iterate() is now ready to stream, so it sets the "ready"
|
|
flag and waits for "time 0".
|
|
|
|
- The pipeline is now completely ready, so the clock may be
|
|
started. A signal is fired to let the application know this
|
|
(and possibly change the default behavior).
|
|
|
|
- The clock starts with the time 0. The scheduler realizes this,
|
|
and decides to schedule osssink.
|
|
|
|
- osssink.iterate() is called, and writes the buffer to the device.
|
|
This starts the clock counting. (Actually, the buffer could be
|
|
written by the clock code, since presumably the clock is related
|
|
to osssink.) iterate() then waits for "sink pad has available
|
|
buffer".
|
|
|
|
We're now basically in streaming mode. A streaming cycle:
|
|
|
|
- osssink.iterate() decides the audio output buffer is full enough,
|
|
so it waits for "time X", where X is the time when the output
|
|
buffer will be below some threshold.
|
|
|
|
- osssink.iterate() waits for "sink pad has available buffer"
|
|
|
|
- sinesrc.iterate() creates and pushes a buffer, then waits for
|
|
"src pad ready".
|
|
|
|
|
|
Further ideas:
|
|
|
|
- osssink can set a hard deadline time, which means that if it is
|
|
not scheduled before that time, you'll get a skip. Skipping
|
|
involves setting osssink to "not ready" and pauses the clock.
|
|
Then the scheduler needs to go through the same process as above
|
|
to start the clock.
|
|
|
|
- As a shortcut, osssink can say "I need a buffer on the sinkpad
|
|
at time X". This information can be passed upstream, and be used
|
|
in filters -- filter.sinkpad says "I need a buffer at time X-N",
|
|
where N is the latency of the filter.
|
|
|
|
|
|
Example #2:
|
|
|
|
Pipeline: osssrc ! osssink
|
|
|
|
- The application creates the pipeline and sets it to "playing".
|
|
|
|
- The clock is created and set to "paused".
|
|
|
|
- negotiation happens roughly as in example #1, although osssrc
|
|
additionally opens and prepares the device.
|
|
|
|
- osssrc.iterate() sets the "ready" flag (because it needs no more
|
|
preparation to stream) and waits for "time 0", since it presumably
|
|
can't wait for the file descriptor (audio input hasn't been
|
|
enabled on the device yet.)
|
|
|
|
- osssink.iterate() decides to watch for the event "sink pad has
|
|
available buffer".
|
|
|
|
- The scheduler realizes the deadlock and (somehow) tells osssink
|
|
that it can't pre-roll. (This needs more work) In other words,
|
|
osssink can't be the clock master, but only a clock slave.
|
|
|
|
- osssink.iterates() agrees to start at time SOME_LATENCY, sets the
|
|
"ready" flag, and waits for a buffer on its sink pad.
|
|
|
|
- The pipeline is now completely ready, so the clock may be
|
|
started. A signal is fired to let the application know this
|
|
(and possibly change the default behavior).
|
|
|
|
- The clock starting causes two things to happen: osssrc starts
|
|
the recording of data, and osssink starts the outputting of data.
|
|
The data being output is a chunk of silence equal to SOME_LATENCY.
|
|
|
|
- osssrc.iterate() is called for "time 0", does nothing, and waits
|
|
on the file descriptor (via the scheduler, of course). All waiting
|
|
on file descriptors should have an associated timeout.
|
|
|
|
- osssrc.iterate() is called when the file descriptor is ready,
|
|
reads a chunk of data, and pushes the buffer. It then waits for
|
|
its file descriptor to be ready.
|
|
|
|
- osssink.iterate() is called
|
|
|
|
|
|
Evil:
|
|
|
|
fakesrc ! tee ! fakesink tee0. ! never_accept_a_buffer_sink
|
|
|
|
sinesrc ! osssink videotestsrc ! ximagesink
|
|
|
|
fakesrc ! fakesink (pausing)
|
|
|
|
sinesrc ! identity ! osssink
|
|
|
|
|
|
|