美文网首页
FFmpeg总结

FFmpeg总结

作者: Johnny_Wu | 来源:发表于2021-09-30 16:48 被阅读0次

一、概述

本文会讲到的内容:
1、FFmpeg结构
2、FFmpeg解码
3、FFmpeg的时间timebase
4、FFmpeg编码
5、FFmpeg封装mp4

二、FFmpeg结构

image.png

AVFormatContext:文件信息上下文,其中就包含了流信息结构AVStream

AVStream:流信息,其中就包含具体的音视频格式信息AVCodecContext

AVCodecContext:具体的音视频格式信息。要解码音视频,需要从这里拿到相关信息,比如AVCodecID

AVPacket:未解码的音视频内容。比如视频的每一帧数据,就体现在一个packet中

AVFrame:解码后的音视频内容。

通过FFmpeg解析mp4的过程来理解:

image.png
思考
1、如何得到音频的编码格式?
AVFormatContext->AVStream->AVCodecContext->AVCodecID

2、如何得到这个mp4的总时间?
AVFormatContext->duration

3、如何得到视频的分辨率?
AVCodecContext->width、height

三、FFmpeg解码

1、解码H264(Annex-B)

Annex-B:H264其中一种表示格式。一般运用在网络传输中。

一般是以0x00000001或者0x000001开头,视频帧分为I、P、B帧。
I帧还会带上sps,pps信息,有这两个信息才可以正常解码。
0000000167+(SPS的内容)+0000000168+(PPS的内容)+0000000165+(IDR主帧的内容):
标志位计算公式:code&0x1F,通过公式计算,得到:
SPS:0x07
PPS:0x08
IDR:0x05
0x67 & 0x1F = 0x07,所以0x67是sps的标志位。

哪天你看到0000000127,标志位为0x27,0x27&0x1F = 0x07,所以它也是sps的标志。 image.gif

解码的部分代码:

image.png

思考
这里的解码器AVCodecContext不需要配置参数就可以解码成功,为什么?
1、可以得到具体的NAL
2、可以得到解码需要的信息
因为前面提到的sps,pps已经携带了解码的一些信息,比如分辨率,格式等等。FFmpeg会自动解析,然后进行解码。
p2p流通过Annex-B这种格式传H264。好处是每一个主帧都是独立的,就算前面的主帧携带的sps、pps有错,导致解码失败。后面的主帧也不受影响,还是可以解码成功。这样的容错性就更好。

2、解码H264(AVCC)

AVCC:H264其中一种表示格式。一般运用在mp4封装格式中。
与Annex-B区别有两点:一个是参数集(SPS, PPS)组织格式,一个是分隔。
Annex-B:使用start code分隔NAL(start code为三字节或四字节,0x000001或0x00000001,一般是四字节);SPS和PPS按流的方式写在头部。

AVCC:使用NALU长度(固定字节,通常为4字节)分隔NAL,在头部包含extradata(或sequence header)的结构体。 image.png
组成:

extradata+NAL长度+NAL+NAL长度+NAL。。。
NAL长度所占字节、SPS与PPS等包含在extradata中

extradata格式:

image.jpeg

举个例子:


image.png image.png

思考
FFmpeg如何解码AVCC格式的H264?
解码的两大条件:
1、可以得到具体的NAL
2、可以得到解码需要的信息
前面提到了。必现要有extradata。才可以得到拆分出具体的NAL,并且extradata也包含了sps,pps等的解码需要的信息。

解码AVCC的H264:

image.png

3、如何得到extradata

a、从mp4文件中解析得到
AVFormatContext->AVStream->AVCodecContext->extradata

b、自己构造
(1)、直接构造extradata


image.png

(2)、先创建Annex-B格式的extradata,再通过ffmpeg自带函数转成AVCC的extradata
-先构造Annex-B方式的extradata:


image.png

-extradata(Annex-B) ----> extradata(AVCC)


image.png

四、timebase

timebase:视频处理中的一种时间单位
基本的时间单位:时、分、秒、毫秒

视频中最小单位为帧,帧都是毫秒级别
帧率为15,那么每帧时间为:1000/15=66.6666毫秒

1、不用浮点型
2、精度更高

只能扩大倍速了,比如扩大100倍,那么每一帧就是6666,这时候就得定义一种新的单位,可以转换为我们认知的时间:秒。

最终的数值都可以转化为秒。

比如,100毫秒,就是0.1秒
100*(1/1000) = 0.1秒

这里的timebase = 1/1000,表示 1秒=1000 毫秒。所以timebase包含了与秒的对应关系。

思考
1、刚才的6666,它的timebase是多少呢?
6666*timebase = 0.066秒
timebase = 1/100000

image.png

2、上面的pkt_pts_time是怎么得出来的?
timebase = 1/15360
pts = 1024
pts_time = 1024 * (1/15360) = 0.066667

五、FFmpeg编码

YUV 编码为 H264

编码代码: image.png
解码代码: image.png

是否这样就可以编码成功了呢?像解码一样,不需要参数?

引出的编码相关的问题:
1、每一帧压缩百分比多少,即编码大小未知
2、每一帧的分辨率未知
3、每一帧的原图片格式未知。YUV420? YUV422
所以这些东西都需要配置。

AVCodecContext的编码参数配置:

image.png

思考
1、如果编码的分辨率不按图片的分辨率设置会怎样?
设置多少,编码多少。如果图片分辨率1600X1200,我设置成800X600。结果如下:

image.png
2、如何控制编码后帧的大小?
a、通过修改码流参数,bit_rate
有时候你会发现,码流改小了很多,但编码后的大小变化不大

b、设置正确的timebase值

只有设置了正确的timebase,在改变bit_rate后,编码后的大小才能正确改变。
可以根据AVFrame中的timebase,具体你可以看它的pts值,推断大概的timebase。
比如:
你以帧率为15来算,那么每一帧的时间为1/15秒
1、比如第二帧 pts为1,那么1xtimebase = 1/15,所以timebase为(AVRational){1, 15}
2、比如第二帧pts为1024,同理1024xtimebase = 1/15,所以timebase为1/15除以1024,所以为(AVRational){1, 15360}

六、FFmpeg封装mp4

image.png
重点1:AVCodecContext的配置
需要配置正确的AVCodecContext->extradata
1、Annex-B的H264,配置对应的extradata(解码时候有提到)
2、AVCC的H264,配置对应的extradata

重点2:配置正确的timebase
如果合成的mp4播放速度不对,很大概率都是timebase设置错误了。
控制倍速播放等等,也通过修改timebase值,达到修改了每一帧的展示时间。

思考
timebase由1/15 改成 1/30,会怎样?

原本某帧的pts=30,30(1/15) = 2,就是这帧在第2秒才展示
30
(1/30) = 1,这帧变为第1秒展示,所以播放速度快了一倍

相关文章

  • 后端开发 - 收藏集 - 掘金

    FFmpeg 总结(十二)用 ffmpeg 与 nginx 实现直播多路流并发播放 - Android - 掘金图...

  • 使用ffmpeg或者java录制音频总结

    使用ffmpeg或者java录制音频总结 系统环境 Ubuntu,MacOS 几种方式 使用FFMPEG 使用JD...

  • ffmpeg基础使用

    参考ffmpeg常用命令ffmpeg参数中文详细解释[总结]FFMPEG视音频编解码零基础学习方法 一、安装 打开...

  • FFmpeg总结

    一、概述 本文会讲到的内容:1、FFmpeg结构2、FFmpeg解码3、FFmpeg的时间timebase4、FF...

  • Python 调用 FFmpeg 报错 module ‘ffmp

    在使用python中的ffmpeg-python时候遇到了几个问题,在此总结一下1、调用 FFmpeg 报错 mo...

  • Android FFmpeg 相关资料

    大神 雷霄骅的博客 [总结]FFMPEG视音频编解码零基础学习方法 如何在Android用FFmpeg解码图像 f...

  • 教程

    [总结]FFMPEG视音频编解码零基础学习方法 用FFmpeg获取视频流+音频流的信息(编码格式、分辨率、帧率、播...

  • FFmpeg C++多线程解码音频数据

    1. C++多线程解码音频数据 之前总结过一篇 FFMpeg 解码流程的博客FFMpeg 解码流程 接下来,对照着...

  • ffmpeg使用总结

    需求:实现Android上使用ffmpeg进行视频裁剪,压缩功能 使用到相关技术: 1FFmpeg实现录制视频 采...

  • FFmpeg基础总结

    FFmpeg 环境准备以及编译 FFMPEG常用命令 分解/复用 原始数据 滤镜对解码后的数据帧过滤,对过滤后的数...

网友评论

      本文标题:FFmpeg总结

      本文链接:https://www.haomeiwen.com/subject/dimidktx.html