编解码相关

一、AVPacket

AVPacket保存一个NAL单元的解码前数据,该结构本身不直接包含数据,其有一个指向数据域的指针。

传递给avcodec_send_packet函数的AVPacket结构体data中的数据前面是00 00 00 01开头,说明是NALU格式的数据。

00 00 00 01 67 42 00 2a 96 35 40 f0 04 4f cb 37 01 01 01 40 00 01 c2 00 00 57 e4  
01 00 00 00 01 68 ce 3c 80 00 00 00 01 06 e5 01 ef 80 00 00 03 00 00 00 01 65 b8  
00 00 52 58 00 00 27 f5 d4 48 7e b4 41 07 24 60 95 2c 92 37 68 75 63 4c ad 3f b1 

很显然,67是SPS,68是PPS,然后65是关键帧。

av_packet_unref : 解引用整个包,释放内存并对对所有的量都置空,单独置buf、data、size为空之后还调了 av_init_packet 初始化其他变量为空。

av_free_packet:释放内存,清空buf,data和size, 没有清空AVPacket 里面的如pts,dts,streamIndex 等变量的值。

av_init_packet:AVPacket 对象已经有的情况下,初始化除了data和size外的其他值。

av_packet_alloc:AVPacket对象还没有的情况下,产生AVPacket对象,并调av_packet_unref 初始化所有量。

av_new_packet:带size参数,在AVPacket 对象已有的情况下,按指定size分配AVPacket的buf,并初始化所有量,也调用了av_init_packet 。

二、编码参数

qp值(qmin,qmax,qdiff):此值范围为0~51 。值越小,量化步长越小,量化的精度就越高,意味着同样画质的情况下,产生的数据量可能会更大。数值越大,图像越模糊,CPU使用率越低;
编码预设模式 “preset” (编码速度)
指定编码速度,速度越慢,画质越好,cpu占用越高,可取值:

ultrafast, superfast, veryfast, faster, fast,  medium, slow, slower, veryslow, placebo

调用方法:

x264_param_default_preset

x264 编码档次
在 H.264 中定义了编码的档次 Profile,表示一组编码算法的集合,以及对编码参数施加的一定限制。在 H.264 标准中定义的档次主要有以下几项:

baseline; constrained baseline;
main; extended;
high; high10; high422; high444predictive;
high10intra; high422intra; high444intra; cavlc444intra;
在 x264 中可配置的 profile 参数并未支持 H.264 中的所有配置,仅实现了其中若干个最常用的选项。通过帮助文档可知,x264 可设置的编码 profile 有 baseline、main、high、high10、high422、high444 六种

特别场景参数 tune
同预设模式 ”preset“ 类似,每一个配置代表了适用于一个场景的若干个配置项。与 ”preset“ 不同的是,特备场景参数 ”tune“ 所指代的配置选项的主要目的并不是对编码的速度或压缩率做出分级,而是专门针对某种场景预定义的配置选项组合。

film:电影片源;
animation:动画片源;
grain:胶片颗粒噪声场景;
stillimage:静态图像;
psnr:峰值信噪比参数优先;
ssim:结构相似性优先;
fastdecode:优先保证解码速度;
zerolatency:低延迟,适用于直播等场景;
帧类型
I 帧(可参考,关键帧,帧内编码)是一个自足的帧。
IDR帧(Instantaneous Decoding Refresh picture, 即时解码刷新帧)是一种特殊的I帧。IDR帧来的时候需要清空参考帧列表,I帧不需要。I帧后面的帧需要参考I帧之前的帧,IDR帧后面的帧不需要参考IDR帧之前的帧;
P 帧:当前的画面几乎总能使用对前一帧的引用和差值进行渲染;
B 帧:引用前面和后面的帧去做更好的压缩;

强制输入I帧:
x264编码器:
_pic->i_type = X264_TYPE_KEYFRAME; //_pic要编码的YUV数据,i_type表示要求编码器编出的帧类型,取值:X264_TYPE_KEYFRAME,X264_TYPE_AUTO;
x264_encoder_encode(_encoder, &nal, &i_nal,_pic, &pic_out);
FFmpeg编码器:
pFrame->pict_type = AV_PICTURE_TYPE_I; 
avcodec_encode_video2(pCodecCtx, &pkt,pFrame, &got_picture);
I帧越大,P帧越小;I帧越小P帧越大
I帧大小取决于图像本身内容,和压缩算法的空间部分
P帧的大小取决于图像变化的剧烈程度
P帧是预测来的,如果变化大,那么变化大,P帧就大
CBR和VBR下P帧的大小策略会不同,CBR时P帧大小基本恒定
最后一点可以了解到音视频中的码率控制再进行了解
GOP 的最大长度,默认为250帧

在H264(AVC)中,一个GOP是以IDR帧开头的一组图像,一个GOP可能包含有多个I帧。一个GOP的编解码只在其组内进行参考,不会跨GOP参考,因为IDR出现的时候会清空参考帧列表。
在H265(HEVC)中,一个GOP不一定是以I帧开头,编解码是可以跨GOP参考。H265的一个GOP只是代表并行编码时的一个并行处理单元。需要刷新参考帧列表时可以通过设置刷新周期参数。

场景切换 scenecut
设定I/IDR帧位置的阈值(场景变更侦测)。
x264为每一帧计算一个度量值,来估计与前一帧的不同程度。如果该值低于scenecut,则算侦测到一个“场景变更”。如果此时与最近一个IDR帧的距离低于--min-keyint,则放置一个I帧,否则放置一个IDR帧。 越大的scenecut值会增加侦测到场景变更的数目。

keyint、min-keyint:x264输出的数据流之最大和最小IDR帧间隔。

slices
设定每帧的切片数,而且强制为矩形切片(会被--slice-max-size或--slice-max-mbs覆写)。

码率

使用 x264 码率控制大致可分为指定码率、指定质量和指定 QP三大类,分别可使用一个选项实现:

-B 或 –bitrate :指定编码视频流的输出码率,单位为 kbit/s;
–crf :质量优先的编码率模式,默认值为 23;
-q 或 –qp :指定恒定量化参数,可选范围为[0, 81],选择 0 表示无损编码;
编码参数详解参考 : (80条消息) 【技术解决方案】优化FFmpeg编码器参数设置_ffmpeg gop_size_༄yi笑奈何的博客-优快云博客

三、SPS和PPS

含后面一个GOP的共享信息

在每个关键帧之前发送的头信息,分开两个RTP发过来,可以认为是I帧的一部分,是两个独立的NALU,只有header,没有body,类似的NALU还有分界符NALU,放在PES和ES中间作为PES和ES的分隔点。

四、YUV

YUV:不是一种色彩空间,只是一种色彩编码形式。图像显示的时候仍然是按RGB来显示的。

YUV的色彩编码方式是为了压缩数据。

Y:亮度,U:Cb 蓝色色度,V:红色Cr色度。

YUV和RGB的转换公式:

Y= 0.299*R + 0.587*G + 0.114*B

U= -0.147*R - 0.289*G + 0.436*B

V= 0.615*R - 0.515*G - 0.100*B

采样RGB之后通过公式转换为YUV,传输之后,另一端接收后可转换为RGB

YUV420中4指的是没4个Y,20指的是Jab二次采样时按4x2矩阵采样在水平方向的色度和亮度的比例。

 YUV420P中的P是Planar(水平),指的是YUV各分量的存储方式,按水平方向平铺存储,如:YYYYYYYYYYYYYYYYUUUUVVVV,YUV420P也叫i420

RGB一个像素3个分量,一个分量一个字节,一个像素需要3个字节,一幅WxH的图像,需要3*W*H个字节。

YUV一个像素一个Y分量,没4个像素一个U分量,没4个像素一个V分量,一个WxH图像的图像,W*H个Y+W*H/4个U+W*H/4个V=3*W*H/2个字节,节省一半的数据量。

存储格式

 每4个Y使用1个U对应1个V。

总量:U+V=Y/2,Y=w*h

一张w*h的图像,有w*h个像素。每个像素都需要按特定的编码方式来编码,YUV是其中一种编码方式,每个图像像素都有1个Y分量,所以一张图像的Y分量为w*h个。没4个像素共用一个U和V分量,所以UV分量都为w*h/4。

图像第n行的,Y:w*n,U:w*n/4,V:w*n/4 .

YUV 4:4:4,每一个 Y 分量对于一对 UV 分量,每像素占用 (Y + U + V = 8 + 8 + 8 = 24bits)3 字节;
YUV 4:2:2,每两个 Y 分量共用一对 UV 分量,每像素占用 (Y + 0.5U + 0.5V = 8 + 4 + 4 = 16bits)2 字节;
YUV 4:2:0,每四个 Y 分量共用一对 UV 分量,每像素占用 (Y + 0.25U + 0.25V = 8 + 2 + 2 = 12bits)1.5 字节;
七、补充增强信息SEI
Supplemental Enhancement InformationFFmpeg从入门到精通——进阶篇,SEI那些事儿 - 简书 (jianshu.com)

五、FFMPEG 多线程解码

多线程软解,thread_count不修改的话默认值是1,使用单个线程进行解码,遇到一些大文件,比如4K,30帧以上的视频流时,解码速度是跟不上的,有两种方案:多线程软解或者硬件解码。

thread_count为0,表示由ffmpeg调用最大线程数来进行软解,6核12线程的电脑,被创建了13个线程进行解码,实际上这会资源过剩,可以根据实际使用情况设置指定线程数量进行解码。

在设置thread_count大于1的值时,一定要把 thread_safe_callbacks 设置为1,否则的话会产生崩溃。默认时 thread_safe_callbacks 是0,thread_count是1或者0的时候,都不需要这个标记。

当一个进程线程数大于1000后,该进程将被系统自动杀死。

设置 pCodecCtx->thread_type = FF_THREAD_SLICE 后,反而多线程无效,注释掉后多线程解码生效,性能飙升。

   if(!avctx->thread_count) {
        avctx->thread_count = av_cpu_count();
        avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tangcpp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值