在开发到退出一个视频播放功能时,看到对AVCodec*这个指针做了初始化,但是突然有一个好奇的疑问,这个AVCodec到底是否需要人工手动销毁?
我在初始化的时候这样用的:
const AVCodec *v_codec = NULL;
AVCodecContext *v_decode_ctx = NULL;
*v_index = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1,0,&v_codec,0);
//alloc video decode ctx
v_decode_ctx = avcodec_alloc_context3(v_codec);
可以看到在av_find_best_stream内部针对const AVCodec *指针做了初始化,然后把初始化后的AVCodec传递给了avcodec_alloc_context3()函数,对AVCodecContext *指针做初始化。
先来看下av_find_best_stream如何对AVCodec进行初始化的:
libavformat/avformat.c #av_find_best_stream:
av_find_best_stream->
decoder = ff_find_decoder(ic, st, par->codec_id); ->
在该函数中,判断是否存在,如何存在的话,就直接返回了,不存在就按照codec_id继续查找:
const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st,
enum AVCodecID codec_id)
{
switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (s->video_codec) return s->video_codec;
break;
case AVMEDIA_TYPE_AUDIO:
if (s->audio_codec) return s->audio_codec;
break;
case AVMEDIA_TYPE_SUBTITLE:
if (s->subtitle_codec) return s->subtitle_codec;
break;
}
return avcodec_find_decoder(codec_id);
}
avcodec_find_decoder(codec_id);--->
find_codec(id, av_codec_is_decoder);--->
最终会调用到av_codec_iterate:
在av_codec_iterate函数中可以看到是对一个结构体做了&取地址,然后返回的:
p就是AVCodec的结构体变量:
typedef struct FFCodec {
/**
* The public AVCodec. See codec.h for it.
*/
AVCodec p;
...
}
再来看下avcodec_alloc_context3函数:
libavcodec/options.c #avcodec_alloc_context3:
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
{
AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
if (!avctx)
return NULL;
if (init_context_defaults(avctx, codec) < 0) {
av_free(avctx);
return NULL;
}
return avctx;
}
调用了init_context_defaults,在init_context_defaults函数中对codec进行了赋值:
在avcodec_alloc_context3函数中可以看到malloc了一个AVCodecContext,然后返回的:
AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
所以这个AVCodecContext指针是必定要free的。
为了一探究竟,AVCodec到底是否需要销毁?我们再追一下销毁AVCodecContext的函数avcodec_free_context:
libavcodec/options.c #avcodec_free_context:
再看avcodec_close函数:
调用了AVCodec的close函数,最后把AVCodecContext中的codec赋值为了NULL
拿flv的encoder来说:最终AVCodecContext中的codec就长下面这样:
可以看到在封装的close函数中做了很多free的操作:
所以真香大白了,总的来说:
- 1、AVCodec不需要单独的销毁;
- 2、销毁的地方主要是:
- (1)在avcodec_close函数中会调用在AVCodec的close函数;
- (2)在avcodec_close函数中close后赋值为了NULL;