mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
130 lines
6.1 KiB
Text
130 lines
6.1 KiB
Text
|
|
||
|
plans:
|
||
|
|
||
|
- The primary object that applications deal with is a GstPipeline. A
|
||
|
given pipeline is connected to a particular main loop (GMainLoop for
|
||
|
glib, etc.). Calls to gst_ functions for objects owned by that
|
||
|
pipeline must be done from the context of the pipeline's main loop.
|
||
|
Signals fired by elements are marshalled in the pipeline's main
|
||
|
loop.
|
||
|
|
||
|
Notably, this means the gst_ API is not necessarily thread-safe.
|
||
|
However, it is safe to operate on different GstPipelines from
|
||
|
different threads. This makes it possible, for example, for
|
||
|
rhythmbox to play music and gather metadata from different threads
|
||
|
using different pipelines. Likewise, it's also possible to do
|
||
|
both in the same thread.
|
||
|
|
||
|
- The primary method of scheduling an element is through a generic
|
||
|
'iterate()' method. The iterate method explicitly tells the core
|
||
|
what it is waiting for (a specific time, pads to have available
|
||
|
data, etc.), and the core calls the iterate method when these
|
||
|
"triggers" happen. GstElement subclasses will be created to
|
||
|
emulate 0.8-style get/chain/loop methods. Existing elements will
|
||
|
be converted to the new subclasses rather than implement the
|
||
|
iterate method directly, unless there is a compelling reason to
|
||
|
do so. Iterate implementations are expected not to block, ever.
|
||
|
|
||
|
Rationale: This makes it possible to create completely non-blocking
|
||
|
elements.
|
||
|
|
||
|
- Scheduling elements will be done in either a threaded or
|
||
|
non-threaded way. The idle handler that is called by a pipeline's
|
||
|
main loop determines which elements are ready to be iterated
|
||
|
(based on their triggers), and puts them into a ready queue. In
|
||
|
the non-threaded case, the idle handler then calls the iterate()
|
||
|
method on each element in the ready queue. In the threaded case,
|
||
|
additional helper threads (which are completely owned by the
|
||
|
pipeline) are used to call the iterate methods.
|
||
|
|
||
|
Note that in the threaded case, elements may not always be run
|
||
|
in the same thread.
|
||
|
|
||
|
Some elements are much easier to write if they run in the same
|
||
|
thread as the main loop (i.e., elements that are also GUI widgets).
|
||
|
An element flag can be set to make the manager always call the
|
||
|
iterate method in the manager context (i.e., in the main loop
|
||
|
thread). Also, elements like spider need to make core calls
|
||
|
which may not be allowed from other threads.
|
||
|
|
||
|
Rationale: Doing all bookkeeping in a single thread/context makes
|
||
|
the core code _much_ simpler. This bookkeeping takes only a
|
||
|
minimal amount of CPU time, less than 5% of the CPU time in a
|
||
|
rhythmbox pipeline. There is very little benefit to spreading
|
||
|
this over multiple CPUs until the number of CPUs is greater than
|
||
|
~16, and you have _huge_ pipelines. Also, a single-threaded
|
||
|
manager significantly decreases the number of locks necessary
|
||
|
in the core, decreasing lock contention (if any) and making it
|
||
|
easier to understand deadlocks (if any).
|
||
|
|
||
|
- There are essentially two types of objects/structures. One type
|
||
|
includes objects that are derived from GObject, and are passed in
|
||
|
function calls similarly to gtk. The other type includes objects
|
||
|
(structures, really) that are not reference counted and passed
|
||
|
around similar to how GstCaps works in 0.8. That is, functions
|
||
|
that take 'const GstCaps *' do not take ownership of the passed
|
||
|
object, whereas functions that take 'GstCaps *' do. Similar is
|
||
|
true for return values.
|
||
|
|
||
|
- The concept of GstBuffer from 0.8 will be split into two types.
|
||
|
One type will focus solely on holding information pertaining to
|
||
|
ownership of a memory area (call this GstMemBuffer), and the
|
||
|
other type will focus solely in transfering information between
|
||
|
elements (call this GstPipeBuffer). In case you get confused,
|
||
|
GstMemBuffers _are not_ transferred between elements, and
|
||
|
GstPipeBuffers _do not_ own the memory they point to.
|
||
|
|
||
|
In general, GstPipeBuffers point to (and reference) a GstMemBuffer.
|
||
|
GstMemBuffers are GObjects. GstPipeBuffers are structs, like
|
||
|
GstCaps. GstPipeBuffers have timestamps, durations, and flags.
|
||
|
GstMemBuffers contain read/write flags. There are no subbuffers
|
||
|
for either type, because they are not necessary. Essentially,
|
||
|
GstPipeBuffers completely replace the concept of subbuffers.
|
||
|
|
||
|
(I'd like to continue to use the name GstBuffer for GstPipeBuffers,
|
||
|
since its usage is much more common in elements.)
|
||
|
|
||
|
Rationale: Memory regions need an ultimate owner and reference
|
||
|
counting. However, chunks passed around between elements need
|
||
|
to be small and efficient. These goals are non-overlapping and
|
||
|
conflicting, and thus are inappropriate to be combined in the
|
||
|
same class.
|
||
|
|
||
|
- Core objects should have very few (if any) public fields. This
|
||
|
means that accessor macros will all be eliminated and replaced
|
||
|
with accessor functions.
|
||
|
|
||
|
Rationale: This makes it possible to change the core more during
|
||
|
an ABI-stable series.
|
||
|
|
||
|
- Remove pluggable scheduling.
|
||
|
|
||
|
Rationale: We need one good scheduler. Having multiple schedulers
|
||
|
is directly opposed to this goal.
|
||
|
|
||
|
- 0.8-style element states are split up. One state (AppState)
|
||
|
indicates what the application wants the element to be doing,
|
||
|
and is completely under the control of the application. The
|
||
|
other state (ElementState) indicates what the element is actually
|
||
|
doing, and is under control of the element. If the application
|
||
|
wants an element to pause, it sets the AppState to PAUSED, and
|
||
|
the element eventually changes its ElementState to PAUSED (and
|
||
|
fires a signal). If the element has an error or EOS, it sets
|
||
|
its ElementState to SOME_STATE and fires a signal, while the
|
||
|
AppState remains at PLAYING. The actual number and descriptions
|
||
|
of states has not been discussed.
|
||
|
|
||
|
Rationale: It's pretty obvious that we're mixing concepts for
|
||
|
elements states in 0.8.
|
||
|
|
||
|
- getcaps() methods will be replaced by an element_allowed_caps()
|
||
|
field in the pad. The primary reason for this is because
|
||
|
renegotiation only needs to happen when circumstances change.
|
||
|
This is more easily done by a field in GstPad and notification
|
||
|
of peers when this changes.
|
||
|
|
||
|
Somewhere, there's a document I wrote about completely redoing
|
||
|
caps.
|
||
|
|
||
|
|