0

Can I create and use C++ smart pointers for different pointer types from FFmpeg?

  1. "AVCodecContext *" which is used only as a pointer in all functions except deallocation.

Alloc:

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

Free:

void avcodec_free_context(AVCodecContext **avctx);

Use:

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

Then the smart pointer:

std::shared_ptr<AVCodecContext> av_codec_context(avcodec_alloc_context3(av_codec),
[](AVCodecContext* _context)
{
  if (_context) avcodec_free_context(&_context);
});
avcodec_open2(av_codec_context.get(), av_codec, NULL)

Is this correct?

  1. "AVDictionary **" which is used in all functions only as a pointer to a pointer.

Alloc and use:

int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);

where pm is a Pointer to a pointer to a dictionary struct. If *pm is NULL a dictionary struct is allocated and put in *pm.

Free:

void av_dict_free(AVDictionary **m);

Then a smart pointer:

std::shared_ptr<AVDictionary*> av_dict(new (AVDictionary*),
[](AVDictionary** _dict)
{
  if (_dict)
  {
    if(*_dict)
      av_dict_free(_dict);
    delete _dict;
  }
});
av_dict_set(av_dict.get(), "key", "value", 0);

Is this correct?

  1. "AVFormatContext *" which is used both as a pointer and as a pointer to a pointer.

Alloc:

AVFormatContext *avformat_alloc_context(void);

Free:

void avformat_free_context(AVFormatContext *s);

Use:

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

or

int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options);

where ps is a Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). May be a pointer to NULL, in which case an AVFormatContext is allocated by this function and written into ps.

Then a smart pointer:

std::shared_ptr<AVFormatContext> av_format_context(avformat_alloc_context(),
[](AVFormatContext* _context)
{
  if(_context)
    avformat_free_context(_context);
});
avformat_find_stream_info(av_format_context.get(), NULL);

Is this correct? But how can I use it with the avformat_open_input() function, which needs a pointer to a pointer and may want to create an object by this pointer?

6
  • 1
    did you try any of this? Did it work? Did it not work? And please try to focus on one question. Commented Oct 12 at 12:52
  • IMHO this is one question about using smart pointers C++ and I would also like to add that this is more of a question about the C++ language, and FFmpeg is used only for specific examples. Formally, the first two options work. But I am not sure whether this use is correct for the second option. And I don't even know how to fully implement the third option.
    – Elija
    Commented Oct 12 at 13:16
  • new (AVDictionary*) leaks currently, and you don't need that allocation anyway
    – Jarod42
    Commented Oct 12 at 14:07
  • Thank you. I agree. Added delete _dict. But why don't I need to allocate it?
    – Elija
    Commented Oct 12 at 14:20
  • Your approach to #2 is all wrong. When an API takes a double-pointer, it expects you to pass in the address of a single-pointer and the API is allowed to update that pointer. But you can't get the address of a pointer that is held inside a standard C++ smart pointer (some 3rd party smart pointers let you do so). So you have to use a raw pointer and transfer it to/from a smart pointer when making the API call Commented Oct 12 at 23:58

1 Answer 1

0
  1. is correct.

pointer on pointer is unneeded, you just need single pointer, i.e:

std::shared_ptr<AVDictionary> make_AVDictionaryPtr(const char *key,
                                                   const char *value,
                                                   int flags)
{
    AVDictionary* p = nullptr;
    av_dict_set(&p, key, value, flags); // "equivalent to" p = some_alloc(..)

    return std::shared_ptr<AVDictionary>{
        p,
        [](AVDictionary* dict) {
            if (dict) {
                av_dict_free(&dict);
            }
        }
    };
}
// ...
auto av_dict = make_AVDictionaryPtr("key", "value", 0);
av_dict_set(av_dict.get(), "key2", "value2", 0);
  1. Is this correct?

Yes

But how can I use it with the avformat_open_input() function, which needs a pointer to a pointer and may want to create an object by this pointer?

As for 2. if you want to use it directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.