|  | OUTDATED | 
|  | -------- | 
|  |  | 
|  | 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&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 #defines that expand to | 
|  | the size of the struct in question, as well as the four-cc code that | 
|  | defines the type. | 
|  |  | 
|  | The work is done by a few #defines, a la the #defines used in all Gtk | 
|  | objects.  The first is a NEW() method that allocates the memory for the | 
|  | metadata and fills in all the normal fields (type, size, utility | 
|  | functions).  Because of the way it's defined (as a #define, no less), | 
|  | you'll have to invoke it as META_NEW(meta), since it can't return() | 
|  | anything. | 
|  |  | 
|  | Another #define will check to make sure a meta is indeed that type by | 
|  | verifying the type code and size.  Theoretically, meta types can overlap | 
|  | with the same fourcc code, as long as they have different sizes.  But I | 
|  | probably ought to have a global public registry so people writing things | 
|  | don't conflict.  MSFT got that right, at least. | 
|  |  | 
|  | 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? |