GStreamer Library Reference Manual (Core) | |||
---|---|---|---|
<<< Previous Page | Home | Up | Next Page >>> |
#include <gst/gst.h> #define GST_META_FLAGS (meta) #define GST_META_FLAG_IS_SET (meta,flag) #define GST_META_FLAG_SET (meta,flag) #define GST_META_FLAG_UNSET (meta,flag) enum GstMetaFlags; struct GstMeta; GstMeta* gst_meta_new_size ( |
The point of the metadata is to provide some context for each buffer. In the case of audio data, for instance, it would provide the samplerate, bit depth, and channel count.
The trick is that there may be multiple types of metadata ganged onto a single buffer. This is why they're going to be a GList. This does mean extra overhead in all cases, but I think it's minimal. The GList type uses a chunk allocater so we're not wasting too much memory or time when adding to the list.
The trick is dealing with these structs as they pass through a pipeline, since they have potentially different mutability properties. For instance, if you've got a mp3 decoder connected to a tee, which sends the buffers off to both the decoder and a spectrum analyzer (and then a visualization element). The preferred setup would be where every time a audio/raw metadata comes down the pipe (indicating a potential change in audio format), the audiosink and spectrum would just save off pointers.
So when exactly does this metadata go away (deallocated)? Well, that means metadata has to be refcounted. But that gets rather hairy. OK, in the simple case you create a metadata struct, it comes with refcount set to 1. You pass it through, it stays one, eventually someone drops the last reference on the buffer it's tied to, you free the metadata too. Easy. What if you tee? You could go through and for every metadata in the buffer, increment the refcount by the same as the buffer. So in the above case (tee'd), the audiosink and spectrum would get the buffer with a refcount of 2, and it'd have a metadata with refcount 2. Do they ref it each themselves, then unref the buffer? Or do they remove the metadata? Removing the metadata would require a buffer CoW, which would suck, so yes, they'd just ref the metadata.
But.... what if they're all in different threads? Then we're off into the magical world of mutexes. Everything with a refcount in a threaded world must be mutexed, else you can do atomic increment and atomic dec and test. Can this be done from C easily? Perhaps it needs to be found from kernel includes via autoconf?
The goal in designing the way metadata will be defined and used is to keep it as simple as possible. The basis for accomplishing this is the fact that in order to actually use (rather than just pass) the metadata, you have to know what the fields are, which means you have to have compiled in support for that metadata at build time. Therefore, if you're using metadata, you must have build-time access to the necessary include file that defines it.
So, given that you've got an include file, it would be nice if the whole thing could be contained there. This would limit the need to be linked against something, or have load-time requirements as to that has to be loaded before you are.
Given that really all metadata is is a region of memory of a given size
with a certain signature, this isn't all that hard. First you lay out the
struct that defines the metadata. Then you set up
The work is done by a few
Another
So, a hairy problem is what to do when there are utility functions associated with one of these things. One option is to not bother with them. This is very likely a possible solution, since metadata is supposed to be flat memory of a given size. Not much to do to either free or copy it, is there?
typedef enum { GST_META_FREEABLE = 1 << 0, } GstMetaFlags; |
Flags indicating properties about the meta data.
struct GstMeta { /* locking */ GMutex *lock; /* refcounting */ #ifdef HAVE_ATOMIC_H atomic_t refcount; #else int refcount; #endif guint16 type; guint16 flags; void *data; guint16 size; }; |
GstMeta* gst_meta_new_size ( |
Create a new metadata object with a given size.
#define gst_meta_new(type) (type *)gst_meta_new_size(sizeof(type)) |
Create new meta data.
void gst_meta_unref (GstMeta *meta); |
Decreases the refcount of a meta object. If the refcount is zero, the meta object is freed.