调用void avcodec_register_all(void)会注册所有的编解码器
比如里面调用了
REGISTER_HWACCEL(H264_VAAPI, h264_vaapi);
展开为
av_register_hwaccel(&ff_h264_vaapi_hwaccel);
定义在vaapi_h264.h里
AVHWAccel ff_h264_vaapi_hwaccel = {
.name = "h264_vaapi",
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.pix_fmt = AV_PIX_FMT_VAAPI_VLD,
.start_frame = vaapi_h264_start_frame,
.end_frame = vaapi_h264_end_frame,
.decode_slice = vaapi_h264_decode_slice,
};
av_register_hwaccel会将编解码器加入一个列表里,
static AVHWAccel *first_hwaccel = NULL;
static AVHWAccel **last_hwaccel = &first_hwaccel;
要使用时通过ff_find_hwaccel来找到对应的编解码器
AVHWAccel *ff_find_hwaccel(AVCodecContext *avctx)
{
enum AVCodecID codec_id = avctx->codec->id;
enum AVPixelFormat pix_fmt = avctx->pix_fmt;
AVHWAccel *hwaccel = NULL;
while ((hwaccel = av_hwaccel_next(hwaccel)))
if (hwaccel->id == codec_id
&& hwaccel->pix_fmt == pix_fmt)
return hwaccel;
return NULL;
}
ff_find_hwaccel在h264_slice_header_init里调用的:
h->avctx->hwaccel = ff_find_hwaccel(h->avctx);
将找到的硬件加速赋值给hwaccel
h264_slice_header_init在decode_slice_header里调用
decode_slice_header里会在h264_slice_header_init之前对h->avctx->pix_fmt 复制,如下:
if ((ret = get_pixel_format(h, 1)) < 0)
return ret;
h->avctx->pix_fmt = ret;
av_log(h->avctx, AV_LOG_INFO, "Reinit context to %dx%d, "
"pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(h->avctx->pix_fmt));
if ((ret = h264_slice_header_init(h, 1)) < 0) {
av_log(h->avctx, AV_LOG_ERROR,
"h264_slice_header_init() failed\n");
return ret;
上面get_pixel_format里会调用
enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
{
return avctx->get_format(avctx, fmt);
}
来得到格式,这个格式是函数指针get_format指定的,我们可以重写这个函数
enum ffGetFormat(AVCodecContext *p_context, const enum PixelFormat *pi_fmt )
{
return AV_PIX_FMT_VAAPI_VLD;
}
这样就能使用VAAPI来编解码了,调用到 ff_h264_vaapi_hwaccel 里的函数了