ffmpeg 接口到 x264 接口

libavcodec/libx264.c 中定义了结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const FFCodec ff_libx264_encoder = {
.p.name = "libx264",
CODEC_LONG_NAME("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_H264,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
AV_CODEC_CAP_OTHER_THREADS |
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE |
AV_CODEC_CAP_ENCODER_FLUSH |
AV_CODEC_CAP_ENCODER_RECON_FRAME,
.p.priv_class = &x264_class,
.p.wrapper_name = "libx264",
.priv_data_size = sizeof(X264Context),
.init = X264_init,
FF_CODEC_ENCODE_CB(X264_frame),
.flush = X264_flush,
.close = X264_close,
.defaults = x264_defaults,
CODEC_PIXFMTS_ARRAY(pix_fmts_all),
.color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS
#if X264_BUILD < 158
| FF_CODEC_CAP_NOT_INIT_THREADSAFE
#endif
,
};

其中的 .init, FF_CODEC_ENCODE_CB, .flush, .close 分别为x264接口封装后的函数指针

FFCodec这个结构体第一个字段为 AVCodec p,所以通过 libavcodec/allcodecs.c:avcodec_find_encoder 遍历查找到的AVCodec* 地址也就是FFCodec* , 可通过 ffcodec 函数把 AVCodec* 强转为 FFCodec*

1
2
3
4
5
6
// codec_internal.h

static av_always_inline const FFCodec *ffcodec(const AVCodec *codec)
{
return (const FFCodec*)codec;
}

在avcodec_open2中会调用 codec2->init 实际就是调用的 X264_init

avcodec_send_frame –> encode_send_frame_internal –> av_frame_ref –> av_frame_copy 把送入的YUV拷贝到了 AVCodecContext.internal.buffer_frame

encode_receive_packet_internal –> encode_simple_receive_packet –> encode_simple_internal –> ff_encode_encode_cb –> codec->cb.encode 实际就是调用的 X264_frame

C语言实现了C++的虚函数功能,妙啊