mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
docs: update docs
This commit is contained in:
parent
e2bbfd294d
commit
964ea9eccb
3 changed files with 277 additions and 119 deletions
|
@ -15,10 +15,16 @@ Requirements
|
|||
- Must be able to attach artibtrary metadata to buffers
|
||||
- efficient handling of subbuffer, copy, span, trim
|
||||
|
||||
Writability
|
||||
-----------
|
||||
Lifecycle
|
||||
~~~~~~~~~
|
||||
|
||||
The Buffers is writable when the refcount is 1. This means that:
|
||||
GstMemory extends from GstMiniObject and therefore uses its lifecycle
|
||||
management (See part-miniobject.txt).
|
||||
|
||||
Writability
|
||||
~~~~~~~~~~~
|
||||
|
||||
When a Buffers is writable as returned from gst_buffer_is_writable():
|
||||
|
||||
- metadata can be added/removed and the metadata can be changed
|
||||
- GstMemory blocks can be added/removed
|
||||
|
|
|
@ -14,118 +14,6 @@ Requirements
|
|||
and trim.
|
||||
|
||||
|
||||
Allocators
|
||||
~~~~~~~~~~
|
||||
|
||||
GstMemory objects are created by allocators. Allocators are created from
|
||||
a GstMemoryInfo structure.
|
||||
|
||||
struct _GstMemoryInfo {
|
||||
const gchar *mem_type;
|
||||
|
||||
GstAllocatorAllocFunction alloc;
|
||||
|
||||
GstMemoryMapFunction mem_map;
|
||||
GstMemoryUnmapFunction mem_unmap;
|
||||
GstMemoryFreeFunction mem_free;
|
||||
|
||||
GstMemoryCopyFunction mem_copy;
|
||||
GstMemoryShareFunction mem_share;
|
||||
GstMemoryIsSpanFunction mem_is_span;
|
||||
};
|
||||
|
||||
Allocators are refcounted. It is also possible to register the allocator to the
|
||||
GStreamer system. This way, the allocator can be retrieved by name.
|
||||
|
||||
After an allocator is created, new GstMemory can be created with
|
||||
|
||||
GstMemory * gst_allocator_alloc (const GstAllocator * allocator,
|
||||
gsize maxsize, gsize align);
|
||||
|
||||
The GstMemory object is a refcounted object that must be freed with
|
||||
gst_memory_unref ().
|
||||
|
||||
It is also possible to create a new GstMemory object that wraps existing
|
||||
memory with:
|
||||
|
||||
GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags,
|
||||
gpointer data, gsize maxsize,
|
||||
gsize offset, gsize size,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
Lifecycle
|
||||
~~~~~~~~~
|
||||
|
||||
GstMemory objects are refcounted. When the GstMemory object is first created, it
|
||||
has a refcount of 1.
|
||||
|
||||
Each variable holding a reference to the GstMemory object is responsible for
|
||||
updating the refcount.
|
||||
|
||||
When the refcount reaches 0, and thus no objects hold a reference anymore, we
|
||||
can free the memory. The GstMemoryFreeFunction of the allocator will be called
|
||||
to cleanup the memory.
|
||||
|
||||
|
||||
Access management
|
||||
-----------------
|
||||
|
||||
GstMemory objects can be shared between multiple GstBuffer objects. It is
|
||||
important that when a thread writes to the shared GstMemory that the other
|
||||
buffers don't not see the changes.
|
||||
|
||||
We need 2 concepts:
|
||||
|
||||
- count how many objects are sharing this GstMemory (exclusive counter)
|
||||
- control the READ/WRITE access to the GstMemory (locking)
|
||||
|
||||
* exclusive counter
|
||||
|
||||
Each object that wants to keep a reference to the GstMemory and doesn't want to
|
||||
see the changes from other owners of the same GstMemory needs to lock the
|
||||
GstMemory in EXCLUSIVE mode, which will increase the exclusive counter.
|
||||
|
||||
The exclusive counter counts the amount of objects that share this GstMemory
|
||||
object. The counter is initially 0, meaning that the object is not shared with
|
||||
any object. When a GstBuffer (or other object) receives a ref to a GstMemory,
|
||||
it will lock in EXCLUSIVE mode.
|
||||
|
||||
When the GstMemory is removed from the buffer, both the ref count and the
|
||||
exclusive counter will be decreased with gst_object_unref() and
|
||||
gst_memory_unlock () respectively.
|
||||
|
||||
* locking
|
||||
|
||||
All read and write access must be performed between a gst_memory_lock() and
|
||||
gst_memory_unlock() pair with the requested access method.
|
||||
|
||||
A gst_memory_lock() can fail when a WRITE lock is requested and the exclusive
|
||||
counter is > 1. Indeed a GstMemory object with an exclusive counter > 1 is
|
||||
locked EXCLUSIVELY by at least 2 objects and is therefore not writable.
|
||||
|
||||
Once the memory is locked with a certain access mode, it can be recursively
|
||||
locked with the same or narrower access mode. For example, first locking the
|
||||
memory in READWRITE mode allows you to recusively lock the memory in
|
||||
READWRITE, READ and WRITE mode. Memory locked in READ mode cannot be locked
|
||||
recursively in WRITE or READWRITE mode.
|
||||
|
||||
Note that multiple threads can READ lock the memory concurrently but cannot
|
||||
lock the memory in WRITE mode because the exclusive counter must be > 1.
|
||||
|
||||
All calls to gst_memory_lock() need to be paired with one gst_memory_unlock()
|
||||
call with the same access mode. When the last refcount of the memory is
|
||||
removed, the should be no more outstanding locks.
|
||||
|
||||
Note that a shared counter of both 0 and 1 leaves the memory writable. The
|
||||
reason is to make it easy to create and pass ownership of the memory to
|
||||
another object while keeping it the memory writable. When the memory is
|
||||
created with a shared count of 0, it is writable. When the memory is then
|
||||
added to another object, the shared count is incremented to 1 and the memory
|
||||
remains writable. The 0 share counter has a similar purpose as the floating
|
||||
reference in GObject.
|
||||
|
||||
|
||||
Memory layout
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -153,6 +41,58 @@ Memory layout
|
|||
void gst_memory_resize (GstMemory *mem, gssize offset, gsize size);
|
||||
|
||||
|
||||
Allocators
|
||||
~~~~~~~~~~
|
||||
|
||||
GstMemory objects are created by allocators. Allocators are created from
|
||||
a GstMemoryInfo structure.
|
||||
|
||||
struct _GstMemoryInfo {
|
||||
const gchar *mem_type;
|
||||
|
||||
GstAllocatorAllocFunction alloc;
|
||||
|
||||
GstMemoryMapFunction mem_map;
|
||||
GstMemoryUnmapFunction mem_unmap;
|
||||
GstMemoryFreeFunction mem_free;
|
||||
|
||||
GstMemoryCopyFunction mem_copy;
|
||||
GstMemoryShareFunction mem_share;
|
||||
GstMemoryIsSpanFunction mem_is_span;
|
||||
};
|
||||
|
||||
Allocators are refcounted. It is also possible to register the allocator to the
|
||||
GStreamer system. This way, the allocator can be retrieved by name.
|
||||
|
||||
After an allocator is created, new GstMemory can be created with
|
||||
|
||||
GstMemory * gst_allocator_alloc (const GstAllocator * allocator,
|
||||
gsize size,
|
||||
GstAllocationParams *params);
|
||||
|
||||
GstAllocationParams contain extra info such as flags, alignment, prefix and
|
||||
padding.
|
||||
|
||||
The GstMemory object is a refcounted object that must be freed with
|
||||
gst_memory_unref ().
|
||||
|
||||
It is also possible to create a new GstMemory object that wraps existing
|
||||
memory with:
|
||||
|
||||
GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags,
|
||||
gpointer data, gsize maxsize,
|
||||
gsize offset, gsize size,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
Lifecycle
|
||||
~~~~~~~~~
|
||||
|
||||
GstMemory extends from GstMiniObject and therefore uses its lifecycle
|
||||
management (See part-miniobject.txt).
|
||||
|
||||
|
||||
|
||||
Data Access
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
@ -160,6 +100,9 @@ Data Access
|
|||
call. This allows the implementation to monitor the access patterns or set up
|
||||
the required memory mappings when needed.
|
||||
|
||||
The access of the memory object is controlled with the locking mechanism on
|
||||
GstMiniObject (See part-miniobject.txt).
|
||||
|
||||
Mapping a memory region requires the caller to specify the access method: READ
|
||||
and/or WRITE. Mapping a memory region will first try to get a lock on the
|
||||
memory in the requested access mode. This means that the map operation can
|
||||
|
@ -170,10 +113,10 @@ Data Access
|
|||
After the data has been accessed in the object, the unmap call must be
|
||||
performed, which will unlock the memory again.
|
||||
|
||||
It is allowed to map multiple times with different access modes. for each of
|
||||
the map calls, an corresponding unmap call needs to be made. WRITE-only memory
|
||||
cannot be mapped in READ mode and READ-only memory cannot be mapped in WRITE
|
||||
mode.
|
||||
It is allowed to recusively map multiple times with the same or narrower
|
||||
access modes. for each of the map calls, an corresponding unmap call needs to
|
||||
be made. WRITE-only memory cannot be mapped in READ mode and READ-only memory
|
||||
cannot be mapped in WRITE mode.
|
||||
|
||||
The memory pointer returned from the map call is guaranteed to remain valid in
|
||||
the requested mapping mode until the corresponding unmap call is performed on
|
||||
|
|
209
docs/design/part-miniobject.txt
Normal file
209
docs/design/part-miniobject.txt
Normal file
|
@ -0,0 +1,209 @@
|
|||
GstMiniObject
|
||||
-------------
|
||||
|
||||
This document describes the design of the miniobject base class.
|
||||
|
||||
The miniobject abstract base class is used to construct lightweight refcounted
|
||||
and boxed types that are frequently created and destroyed.
|
||||
|
||||
Requirements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- Be lightweight
|
||||
- Refcounted
|
||||
- I must be possible to control access to the object, ie. when the object is
|
||||
readable and writable.
|
||||
- Subclasses must be able to use their own allocator for the memory.
|
||||
|
||||
|
||||
Usage
|
||||
~~~~~
|
||||
|
||||
Users of the GstMiniObject infrastructure will need to define a structure that
|
||||
includes the GstMiniObject structure as the first field.
|
||||
|
||||
struct {
|
||||
GstMiniObject mini_object;
|
||||
|
||||
/* my fields */
|
||||
...
|
||||
} MyObject
|
||||
|
||||
The subclass should then implement a constructor method where it allocates the
|
||||
memory for its structure and initializes the miniobject structure with
|
||||
gst_mini_object_init(). Copy and Free functions are provided to the
|
||||
gst_mini_object_init() function.
|
||||
|
||||
MyObject *
|
||||
my_object_new()
|
||||
{
|
||||
MyObject *res = g_slice_new (MyObject);
|
||||
|
||||
gst_mini_object_init (GST_MINI_OBJECT_CAST (res), 0,
|
||||
MY_TYPE_OBJECT,
|
||||
(GstMiniObjectCopyFunction) _my_object_copy,
|
||||
(GstMiniObjectDisposeFunction) NULL,
|
||||
(GstMiniObjectFreeFunction) _my_object_free);
|
||||
|
||||
/* other init */
|
||||
.....
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
The Free function is responsible for freeing the allocated memory for
|
||||
the structure.
|
||||
|
||||
static void
|
||||
_my_object_free (MyObject *obj)
|
||||
{
|
||||
/* other cleanup */
|
||||
...
|
||||
|
||||
g_slice_free (MyObject, obj);
|
||||
}
|
||||
|
||||
|
||||
Lifecycle
|
||||
~~~~~~~~~
|
||||
|
||||
GstMiniObject is refcounted. When a GstMiniObject is first created,
|
||||
it has a refcount of 1.
|
||||
|
||||
Each variable holding a reference to a GstMiniObject is responsible for
|
||||
updating the refcount. This includes incrementing the refcount with
|
||||
gst_mini_object_ref() when a reference is kept to a miniobject or
|
||||
gst_mini_object_unref() when a reference is released.
|
||||
|
||||
When the refcount reaches 0, and thus no objects hold a reference to the
|
||||
miniobject anymore, we can free the miniobject.
|
||||
|
||||
When freeing the miniobject, first the GstMiniObjectDisposeFunction is called.
|
||||
This function is allowed to revive the object again by incrementing the
|
||||
refcount, in which case it should return FALSE from the dispose function. The
|
||||
dispose function is used by GstBuffer to revive the buffer back into the
|
||||
GstBufferPool when needed.
|
||||
|
||||
When the dispose function returns TRUE, the GstMiniObjectFreeFunction will be
|
||||
called and the miniobject will be freed.
|
||||
|
||||
|
||||
Copy
|
||||
~~~~
|
||||
|
||||
A miniobject can be copied with gst_mini_object_copy(). This function will
|
||||
call the custom copy function that was provided when registering the new
|
||||
GstMiniObject subclass.
|
||||
|
||||
The copy function should try to preserve as much info from the original object
|
||||
as possible.
|
||||
|
||||
The new copy should be writable.
|
||||
|
||||
|
||||
Access management
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
GstMiniObject can be shared between multiple threads. It is important that when
|
||||
a thread writes to a GstMiniObject that the other threads don't not see the
|
||||
changes.
|
||||
|
||||
To avoid exposing changes from one thread to another thread, the miniobjects
|
||||
are managed in a Copy-On-Write way. A copy is only made when it is known that
|
||||
the object is shared between multiple objects or threads.
|
||||
|
||||
There are 2 methods implemented for controlling access to the miniobject.
|
||||
|
||||
- A first method relies on the refcount of the object to control writability.
|
||||
Objects using this method have the LOCKABLE flag unset.
|
||||
|
||||
- A second method relies on a separate counter for controlling
|
||||
the access to the object. Objects using this method have the LOCKABLE flag
|
||||
set.
|
||||
|
||||
You can check if an object is writable with gst_mini_object_is_writable() and
|
||||
you can make any miniobject writable with gst_mini_object_make_writable().
|
||||
This will create a writable copy when the object was not writable.
|
||||
|
||||
|
||||
non-LOCKABLE GstMiniObjects
|
||||
---------------------------
|
||||
|
||||
These GstMiniObjects have the LOCKABLE flag unset. They use the refcount value
|
||||
to control writability of the object.
|
||||
|
||||
When the refcount of the miniobject is > 1, the objects it referenced by at
|
||||
least 2 objects and is thus considered unwritable. A copy must be made before a
|
||||
modification to the object can be done.
|
||||
|
||||
Using the refcount to control writability is problematic for many language
|
||||
bindings that can keep additional references to the objects. This method is
|
||||
mainly for historical reasons until all users of the miniobjects are
|
||||
converted to use the LOCAKBLE flag.
|
||||
|
||||
|
||||
LOCKABLE GstMiniObjects
|
||||
-----------------------
|
||||
|
||||
These GstMiniObjects have the LOCKABLE flag set. They use a separate counter
|
||||
for controlling writability and access to the object.
|
||||
|
||||
It consists of 2 components:
|
||||
|
||||
* exclusive counter
|
||||
|
||||
Each object that wants to keep a reference to a GstMiniObject and doesn't want to
|
||||
see the changes from other owners of the same GstMiniObject needs to lock the
|
||||
GstMiniObject in EXCLUSIVE mode, which will increase the exclusive counter.
|
||||
|
||||
The exclusive counter counts the amount of objects that share this
|
||||
GstMiniObject. The counter is initially 0, meaning that the object is not shared with
|
||||
any object.
|
||||
|
||||
When a reference to a GstMiniObject release, both the ref count and the
|
||||
exclusive counter will be decreased with gst_mini_object_unref() and
|
||||
gst_mini_object_unlock () respectively.
|
||||
|
||||
* locking
|
||||
|
||||
All read and write access must be performed between a gst_mini_object_lock() and
|
||||
gst_mini_object_unlock() pair with the requested access method.
|
||||
|
||||
A gst_mini_object_lock() can fail when a WRITE lock is requested and the exclusive
|
||||
counter is > 1. Indeed a GstMiniObject object with an exclusive counter > 1 is
|
||||
locked EXCLUSIVELY by at least 2 objects and is therefore not writable.
|
||||
|
||||
Once the GstMiniObject is locked with a certain access mode, it can be recursively
|
||||
locked with the same or narrower access mode. For example, first locking the
|
||||
GstMiniObject in READWRITE mode allows you to recusively lock the
|
||||
GstMiniObject in
|
||||
READWRITE, READ and WRITE mode. Memory locked in READ mode cannot be locked
|
||||
recursively in WRITE or READWRITE mode.
|
||||
|
||||
Note that multiple threads can READ lock the GstMiniObject concurrently but cannot
|
||||
lock the object in WRITE mode because the exclusive counter must be > 1.
|
||||
|
||||
All calls to gst_mini_object_lock() need to be paired with one
|
||||
gst_mini_object_unlock() call with the same access mode. When the last refcount
|
||||
of the object is removed, there should be no more outstanding locks.
|
||||
|
||||
Note that a shared counter of both 0 and 1 leaves the GstMiniObject writable. The
|
||||
reason is to make it easy to create and pass ownership of the GstMiniObject to
|
||||
another object while keeping it writable. When the GstMiniObject is
|
||||
created with a shared count of 0, it is writable. When the GstMiniObject is then
|
||||
added to another object, the shared count is incremented to 1 and the
|
||||
GstMiniObject remains writable. The 0 share counter has a similar purpose as the floating
|
||||
reference in GObject.
|
||||
|
||||
|
||||
Weak references
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
GstMiniObject has support for weak references. A callback will be called when
|
||||
the object is freed for all registered weak references.
|
||||
|
||||
|
||||
QData
|
||||
~~~~~
|
||||
|
||||
Extra data can be associated with a GstMiniObject by using the QData API.
|
Loading…
Reference in a new issue