有两种方法:
一. ffmpeg 添加自定义编解码插件(以修改ffmpeg源码的方式添加)
例:添加一个解码器,给这个解码器取个名字叫mydecoder,可以通过下面的步骤添加:
1.在libavcodec目录下,新建文件mydecoder.c
#include "avcodec.h"
#include "codec_internal.h"
//自己封装的编解码器的头文件
#include "MyDecoder.h"
static av_cold int mk_init_decoder(AVCodecContext *avctx)
{
//...
return 0;
}
static int mk_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame,
AVPacket *avpkt)
{
printf("decode in\n");
//...
return 0;
}
static av_cold int mk_close_decoder(AVCodecContext *avctx)
{
//...
return 0;
}
static void mk_flush(AVCodecContext *avctx)
{
//...
}
//通过此结构体,来完成对mydecoder解码器的调用
//结构体的命名规则必须为 ff_xxx_decoder
//如果是编码器则为 ff_xxx_encoder
const FFCodec ff_mydecode_decoder = {
.p.name = "myvideo",
CODEC_LONG_NAME("mk video"),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_MYVIDEO,//需要手动在code_id.h头文件中声明
.p.capabilities = AV_CODEC_CAP_PARAM_CHANGE,
.init = mk_init_decoder,
FF_CODEC_DECODE_CB(mk_decode),
.close = mk_close_decoder,
.flush = mk_flush};
2.嵌入mydecoder,使ffmpeg能识别到mydecoder解码器
-
1.在
libavcodec/code_id.h
头文件中声明 AV_CODEC_ID_MYVIDEO。后面可以通过这个ID来找到mydecoder解码器 -
2.在
libavcodec/codec_desc.c
的 AVCodecDescriptor 编解码描述结构体中中添加如下代码
...
{
.id = AV_CODEC_ID_LEAD,
.type = AVMEDIA_TYPE_VIDEO,
.name = "lead",
.long_name = NULL_IF_CONFIG_SMALL("LEAD MCMP"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
//mydecoder解码器的描述
{
.id = AV_CODEC_ID_MYVIDEO,
.type = AVMEDIA_TYPE_VIDEO,
.name = "myvideo",
.long_name = NULL_IF_CONFIG_SMALL("mk video"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
},
/* various PCM "codecs" */
{
.id = AV_CODEC_ID_PCM_S16LE,
.type = AVMEDIA_TYPE_AUDIO,
.name = "pcm_s16le",
.long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit little-endian"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
},
...
- 3.在 allcodecs.c 中添加 ff_mydecode_decoder 的声明。configure时,会通过解析此文件获取到可用的编解码器。mydecode为解码器名字,decoder表示为解码器
...
extern const FFCodec ff_mjpeg_decoder;
extern const FFCodec ff_mjpegb_decoder;
//根据这个声明,可以查找到mydecoder解码器
//ps:在执行configure时,也会根据此文件中声明的变量来获取编解码器
extern const FFCodec ff_mydecode_decoder;
extern const FFCodec ff_mmvideo_decoder;
extern const FFCodec ff_mobiclip_decoder;
...
3.修改Makefile,使mydecoder能编译进ffmpeg
...
OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o
#添加下面行,在编译时会把mydecoder.c链接到libavcodec库中
#CONFIG_MYDECODE_DECODER变量是在configure的时候根据ff_mydecode_decoder生成
OBJS-$(CONFIG_MYDECODE_DECODER) += mydecode.o
...
4.生成带mydecoder解码器的ffmpeg
-
1.执行
./configure --list-decoders
查看mydecoder解码器是否已添加 -
2.执行
./configure --disable-x86asm --enable-shared
生成配置文件 -
2.1 可以通过
./configure --help
查看使用说明 -
2.2 执行configure后,会在ffbuild目录下生成一堆文件,主要关注 .mak 文件。可以参考
https://blog.csdn.net/sunshineywz/article/details/105855939
-
3.执行
make
开始编译ffmpeg
二. 不修改ffmpeg源码的方式添加编解码器
- 在
allcodecs.c
源文件中声明了全部的编解码器。ffmpeg实现部分的编解码器,还有一部分只做了声明
,我们直接找到一个未做实现的编码器,比如extern const FFCodec ff_h264_mf_encoder;
,然后直接在
自己的项目中实现它,如下:
const FFCodec ff_h264_mf_encoder = {
.p.name = "myvideo00",
CODEC_LONG_NAME("mk video"),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_H264,
.p.capabilities = AV_CODEC_CAP_PARAM_CHANGE,
.init = mk_init_encoder,//初始化
FF_CODEC_ENCODE_CB(mk_encode),//编码一帧数据
.close = mk_close_encoder,//关闭
最后,当使用const AVCodec *codec = avcodec_find_encoder_by_name("myvideo00");
,查找编码器时,就会直接找到我们自定义的编码器。
两种添加自定义编解码器的方法的优缺点:
在C++工程中使用ffmpeg需要注意:
注意包含头文件的方法:
//在C++项目中,必须使用extern包含ffmpeg头文件,让编译器以C风格来解释ffmpeg接口
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
...
}
标签:编解码,插件,ffmpeg,自定义,mydecoder,AV,mk,CODEC,decoder
From: https://www.cnblogs.com/linxisuo/p/17903697.html