FFMPEG音视频API-----------------复用(编码)篇

1.获取AVFormatContext音视频格式上下文

根据后面的几个参数分配AVFormatContext(格式上下文)

参数1:AVFormatContext **ctx分配返回的地址

参数2:AVOutputFormat *oformat如果提供该参数则通过该参数分配结构体,如果是NULL则使用 const char *format_name, const char *filename分配结构体

参数3: const char *format_name音视频流的格式通常有flv与mpegts(ts)两种格式

参数4: const char *filename输出文件名称,这里分为输出到本地比如输出为ikun.ts ikun.flv文件,也可以输出到网络传输比如我们推流rtmp://192.168.1.21/live/mystream

返回值:函数返回一个整数值,用于指示操作的成功与否。如果成功,返回值大于或等于0;如果失败,返回一个负数的AVERROR错误码。

int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,

const char *format_name, const char *filename);

2.获取encoder编码器

这个api比较简单,就是根据enum AVCodecID id获取对应的编码器

如果成功则返回编码器地址,反之返回NULL

AVCodec *avcodec_find_encoder(enum AVCodecID id);

去库中可以查看AVCodecID的具体内容,其枚举了很多:

3.添加新的流AVStream

添加一个新的流,这个流可以是音频、视频、字幕流

参数1:AVFormatContext音视频上下文,这里是我要把流添加到哪个上下文

参数2:添加流的编码器,通过这个编码器找添加什么样的流(如果这里的编码器设置为NULL的时候不会设定编码器上下文的参数,需要后面再次设定编码器上下文的信息)

成功后返回流地址,反之返回NULL

AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);

4.分配编码器上下文

通过编码器const AVCodec *codec来分配编码器上下文,如果我们在上面添加流时候没有设置第二个参数,那么我们需要在这里手动配置流中的编码器上下文

成功返回编码器上下文地址,反之返回NULL

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

5.关联编码器和编码器上下文

初始化一个编解码器上下文(AVCodecContext),使其准备好进行编码或解码操作。

通常编码器上下文会配置音频、视频的一些参数(采样率帧数等),如果我们绑定上下文和编码器,那么相当于告诉上下文以后的编码工作由指定的编码器来做

参数1:编码器上下文(配置参数)

参数2:编码器(find的)

参数3:可以填NULL

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

6.分配多媒体数据包AVPacket

类似于malloc,这里我们如何理解包和流的关系呢?

我认为包是一个处理音视频数据的基本元,比如我们接收一帧的数据是接收到一个packet即一个包,然后把包写入到流中,流相当于是很多个包,通过av_interleaved_write_frame 函数将包写入到流中

AVPacket *av_packet_alloc(void);

7.编码器上下文参数复制

如果配置好了上下文codec,但是并不是我们实际的编码器上下文使用该函数复制类似于mmcpy

int avcodec_parameters_from_context(AVCodecParameters *par,

const AVCodecContext *codec);

把codec的参数复制到par

使用实例如下: avcodec_parameters_from_context(videostream->codecpar, c);

即把配置好的编码器上下文参数复制到videostream->codecpar,这里videostream是AVStream类型。

8.输入输出日志打印

用于打印关于输入或输出格式的详细信息。这包括持续时间、比特率、流、容器格式、程序、元数据、边数据、编解码器和时间基准等信息。该函数通常用于调试或当用户需要详细了解媒体文件的情况。

参数1:打印哪个音视频上下文信息

参数2:打印什么信息-1是所有信息

参数3:音视频上下文设置的地址,即本地存储or网络传输

参数4:这个音视频上下文是输入还是输出,输入(0)还是输出(1)

void av_dump_format(AVFormatContext *ic,int index, const char *url,int is_output);

9.初始化配置

当前面的编码器、编码器上下文、等都配置好后使用该函数对整体进行初始化

参数1:初始化的音视频上下文

参数2:选项,可以填NULL

int avformat_write_header(AVFormatContext *s, AVDictionary **options);

实战合成音视频流程中,新建的音视频流的时间基准在这个函数后变为合成流时间基准

---------------------------上面的是一系列的配置函数,下面是实际的功能函数---------------------------------

10.时间戳比较

参数1:a的时间戳

参数2:a的时间基准

参数3:b的时间戳

参数4:b的时间基准

时间戳×时间基就是时间

返回值:-1,a在b前 ;0相同;1,a在b后

int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b);

11.变换时间戳

参数1:变换谁的时间戳

参数2:源时间戳

参数3:目标时间戳

void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);

通常pkt的时间戳是音频or视频的,然后我们把其原时间戳转化为合成流时间戳

12.把处理好的包放入合成流

这一步是最重要的,是把pkt(转换好时间基的包)放入oc,oc就是我们合成流的上下文

参数1:写到哪?

参数2:写谁?

这个函数的好处是会交替的写

int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);

-----------------------------------------一些出口函数--------------------------------------------------------------

与linux驱动内容一样,我们定义了很多入口函数(初始化函数),那我们需要定义对应的出口函数(释放资源),避免内存的泄露

这些函数就不一一介绍了:

编码器上下文释放、buf释放、packet释放、音视频上下文释放、等等......

相关推荐
量子-Alex1 小时前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
mo47764 小时前
Webrtc音频模块(四) 音频采集
音视频·webrtc
icy、泡芙5 小时前
T527-----音频调试
linux·驱动开发·音视频
易我数据恢复大师5 小时前
怎么提取音频保存到本地?电脑音频提取方法
音视频·软件·音频提取
野蛮的大西瓜5 小时前
开源呼叫中心中,如何将ASR与IVR菜单结合,实现动态的IVR交互
人工智能·机器人·自动化·音视频·信息与通信
嘟嘟实验室7 小时前
微信小程序xr-frame透明视频实现
微信小程序·ffmpeg·音视频·xr
红米饭配南瓜汤8 小时前
WebRTC服务质量(09)- Pacer机制(01) 流程概述
网络·音视频·webrtc
是十一月末11 小时前
Python进阶之opencv图片和视频基本读取关闭
python·opencv·音视频·cv2
泰勒朗斯11 小时前
如何编译Opencv +ffmpeg linux 明明安装了ffmpeg但是opencv就是找不到
linux·opencv·ffmpeg
gomogomono14 小时前
HDR视频技术之十一:HEVCH.265 的 HDR 编码方案
音视频·h.265·hdr·yuv