[FFmpeg-devel] AVBufferRef from AVBuffer

Soft Works softworkz at hotmail.com
Sat May 21 12:58:32 EEST 2022


Hi,

I have a question. I wonder whether it would be acceptable to add the following
function to buffer.c?

-----------------------------------------------------------------------

AVBufferRef *av_buffer_ref(AVBuffer *buf)
{
    AVBufferRef *ref = av_mallocz(sizeof(*ref));

    if (!ref)
        return NULL;

    ref->buffer = buf;
    ref->data   = buf->data;
    ref->size   = buf->size;

    atomic_fetch_add_explicit(&buf->refcount, 1, memory_order_relaxed);

    return ref;
}

-----------------------------------------------------------------------

Probably some will immediately say that this would be wrong and not the way
it's meant to be used, that AVBuffer needs to be treated as an opaque data
structure and similar.

After thinking about this for a while, I tend to think that it still fits 
into the picture of the AVBuffer API. The only "risk" when dealing with 
AVBuffer without an AVBufferRef is that the AVBuffer  can get freed at any
time. But "any time" doesn't mean that there's no control over it; with 
a custom "free" function, it is easy possible to know about the lifetime
of those buffers, and thus still allowing a safe implementation.


Why would I want that?

I need some kind of "weak reference" mechanism, and of course not something
totally new but something in the context of the AVBufferRef mechanism.

The use case in brief: there's a need to have bidirectional references 
(some 1:1, some 1:n) between hardware device contexts and when using AVBufferRef
for all of them, it would lead to circular references and device contexts
wouldn't get released anymore.


All this should be done in a clean and clear way and avoid having references 
hanging around where you might not now whether still valid or already 
freed and invalid. To overcome that I started with a very simple concept:

- When a device context is created it is registered in a global array
  (with thread-safe access) and gets a reg number (1, 2, 3, ...)

- When a device context is freed, it gets unregistered 
  (removed from the array)

- Now, a device context can reference other device contexts just 
  through that number (of course not knowing whether the corresponding
  device is still "alive"

- But this can easily be queried from the array which can return an
  AVBufferRef to that device on success.


But here comes the problem: how to store references to the device contexts
in that array?

- When creating new AVBufferRefs for the device contexts, none of them 
  would get freed anymore due to the additional reference

- Storing the first AVBufferRef which is available during device creation
  doesn't work either, because that one could get freed while other 
  references still exist, and the reference would be invalid then

- Storing a plain pointer in the array doesn't work out either, because 
  in that case it wouldn't be possible to return an AVBufferRef with
  reference counting.


None of that can work, but one way that does work would be to store
AVBuffer (not ..Ref) in that array. With the function above, it's
possible to create AVBufferRef from AVBuffer without needing another
AVBufferRef. As the registration will be unregistered when freed, 
there's no concern about invalid AVBuffer references.


Please let me know what you think and whether that would be acceptable.
Of course, other ideas are welcome as well!

Thanks,
softworks


More information about the ffmpeg-devel mailing list