avcodec_find_decoder_by_name(“h264_cuvid”);
std::string name{};
if (id == AV_CODEC_ID_H264)
name = ((m_gpu < 0) ? "h264" : "h264_cuvid");
else if (id == AV_CODEC_ID_HEVC)
name = ((m_gpu < 0) ? "hevc" : "hevc_cuvid");
从这里开始分析:
libavcodec
/**
* Find a registered decoder with the specified name.
*
* @param name name of the requested decoder
* @return A decoder if one was found, NULL otherwise.
*/
AVCodec *avcodec_find_decoder_by_name(const char *name);
AVCodec *avcodec_find_decoder_by_name(const char *name)
{
return find_codec_by_name(name, av_codec_is_decoder);
}
int av_codec_is_decoder(const AVCodec *codec)
{
return codec && (codec->decode || codec->receive_frame);
}
/**
* Encode data to an AVPacket.
*
* @param avctx codec context
* @param avpkt output AVPacket (may contain a user-provided buffer)
* @param[in] frame AVFrame containing the raw data to be encoded
* @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a
* non-empty packet was returned in avpkt.
* @return 0 on success, negative error code on failure
*/
int (*decode)(struct AVCodecContext *, void *outdata, int *outdata_size, struct AVPacket *avpkt);
/**
* Decode API with decoupled packet/frame dataflow. This function is called
* to get one output frame. It should call ff_decode_get_packet() to obtain
* input data.
*/
int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame);
static AVCodec *find_codec_by_name(const char *name, int (*x)(const AVCodec *))
{
void *i = 0;
const AVCodec *p;
if (!name)
return NULL;
while ((p = av_codec_iterate(&i))) {
if (!x(p))
continue;
//对比字符串,p就是返回的解码器
if (strcmp(name, p->name) == 0)
return (AVCodec*)p;
}
return NULL;
}
一部分解码器:
extern AVCodec ff_h264_cuvid_decoder;
extern AVCodec ff_h264_mf_encoder;
extern AVCodec ff_h264_nvenc_encoder;
extern AVCodec ff_hevc_cuvid_decoder;
extern AVCodec ff_hevc_mediacodec_decoder;
extern AVCodec ff_hevc_mf_encoder;
extern AVCodec ff_hevc_nvenc_encoder;
static AVOnce av_codec_static_init = AV_ONCE_INIT;
static void av_codec_init_static(void)
{
for (int i = 0; codec_list[i]; i++) {
if (codec_list[i]->init_static_data)
//这里我们执行具体的某一个解码器的函数,比如h264
codec_list[i]->init_static_data((AVCodec*)codec_list[i]);
}
}
const AVCodec *av_codec_iterate(void **opaque)
{
uintptr_t i = (uintptr_t)*opaque;
const AVCodec *c = codec_list[i];
ff_thread_once(&av_codec_static_init, av_codec_init_static);
if (c)
*opaque = (void*)(i + 1);
return c;
}
AVCodec ff_h264_decoder = {
.name = "h264",
.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.priv_data_size = sizeof(H264Context),
.init = h264_decode_init,
.close = h264_decode_end,
.decode = h264_decode_frame,
.capabilities = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
AV_CODEC_CAP_FRAME_THREADS,
.hw_configs = (const AVCodecHWConfigInternal*[])
.....
}
接下来看一下
avcodec_find_decoder()
AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
return find_codec(id, av_codec_is_decoder);
}
static AVCodec *find_codec(enum AVCodecID id, int (*x)(const AVCodec *))
{
const AVCodec *p, *experimental = NULL;
void *i = 0;
id = remap_deprecated_codec_id(id);
while ((p = av_codec_iterate(&i))) {
if (!x(p))
continue;
//这里跟上面一样
if (p->id == id) {
if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) {
experimental = p;
} else
return (AVCodec*)p;
}
}
return (AVCodec*)experimental;
}