从 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
|
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++的虚函数功能,妙啊