音视频开发14 FFmpeg 视频 相关格式分析 -- H264 NALU格式分析

H264简介-也叫做 AVC

H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC

主要作用是 : 将 AVFrame 编码成 AVPakcet。

为什么要编码?

原始数据YUV,RGB为什么要编码-知道就行

在⾳视频传输过程中,视频⽂件的传输是⼀个极⼤的问题;⼀段分辨率为1920*1080,每个像素点为RGB占⽤3个字节,帧率是25的视频,对于传输带宽的要求是:

1920x1080x3x25/1024/1024=148.315MB/s, 这个是每秒的 bytes 数

换成bps则意味着视频每秒带宽为 148.315MB/s x 8 = 1186.523Mbps

1186.523Mbps,这样的速率对于⽹络存储是不可接受的。因此视频压缩和编码技术应运⽽⽣。

H264 就是一种编码技术。x264只支持原始格式为YUV420P的图片

这种技术很多源码都实现了,用的比较多开源技术是x264.

虽然H.264标准理论上支持多种YUV格式(如YUV422、YUV444等),但多数开源编码器(如x264/x265)默认或仅支持YUV420P格式‌5。例如,x264编码库明确要求输入为YUV420P平面格式‌

也就是说。我们从原始的 YUV420P文件中 读取到 一帧原始YUV420数据(一般会用AVFrame 结构体来保存这一帧数据),然后通过lib264 库 编码成为 一帧 AVPacket。

那么这个avpacket 数据结构和 NALU 数据结构的关系是怎么样的呢?

在后面的学习可以知道,对于h264的一帧avpacket,是包含着一个或者多个NALU的。

那么这个avpacket 数据结构和 NALU 数据结构是如何结合起来的呢?

结论:avpacket中的 uint8_t *data 中存储的一个一个的NALU单元。

我们回想一下将avframe 编码成 avpacket后,是如何存储的呢?

参见重要的一句               avpacketofs.write((char*)avpacket->data, avpacket->size);

这个 avpacketofs 是 xxx.h264 的 文件句柄。

也就是说:我们存储的 avpacketofs 本质上是存储的 avpacket->data,大小是avpacket->size

ret = avcodec_send_frame(encoderAVCodecContext,  avframe);
         if (ret < 0) {
             cout << "avcodec_send_frame error" << endl;
            PrintErr(ret);
          }

         //我们看到,如果只有一帧的情况下,avcodec_receive_packet的返回值就是
         ret = avcodec_receive_packet(encoderAVCodecContext, avpacket);
         if (ret < 0) {

             cout << "avcodec_receive_packet error ret = " << ret << endl;
             PrintErr(ret);
             // log如下
             //avcodec_receive_packet error ret = -11
             //Resource temporarily unavailable
             //av_packet_unref(avpacket);
             times--;
         }
         else if (ret == 0) {
             avpacketofs.write((char*)avpacket->data, avpacket->size);
             cerr << "avcodec_receive_packet good good godd  ret = " << ret << "   av_buffer_get_ref_count(avpacket->buf) = " << av_buffer_get_ref_count(avpacket->buf) << endl;
         }

那么这就是说:一个h264 视频文件 中存储的就是每一帧编码后的 avpacket->data。

而从后面我们学习到的 h264的编码结构 可以知道:

                H.264原始码流(裸流)是由⼀个接⼀个NALU组成。

那么我们就可以从 一帧avpacket 的data 中,获取 这个NALU 单元,然后解析。

H264编码原理

帧内压缩

对于视频⽂件来说,视频由单张图⽚帧所组成,⽐如每秒25帧,但是图⽚帧的像素块之间存在

相似性,因此视频帧图像可以进⾏图像压缩;H264采⽤了16*16的分块⼤⼩对,视频帧图像

进⾏相似⽐较和压缩编码。如下图所示:

帧间压缩

H264采⽤了独特的I帧、P帧和B帧策略 来实现,连续帧之间的压缩;

H264 编码结构解析
H264 除了实现了对视频的压缩处理之外,为了⽅便⽹络传输,提供了对应的视频编码和分⽚
策略;类似于⽹络数据封装成 IP 帧,在 H264 中将其称为组 ( GOP , group of pictures) 、⽚
slice )、宏块( Macroblock )这些⼀起组成了 H264 的码流分层结构; H264 将其组织成为
序列 (GOP) 、图⽚ (pictrue) 、⽚ (Slice) 、宏块 (Macroblock) 、⼦块 (subblock) 五个层次。
GOP (图像组)主要⽤作形容⼀个 IDR 帧 到下⼀个 IDR 帧之间的间隔了多少个帧。

H264将视频分为连续的帧进⾏传输,在连续的帧之间使⽤I帧、P帧和B帧。

同时对于帧内⽽⾔,将图像分块为⽚、宏块和字块进⾏分⽚传输;通过这个过程实现对视频⽂件的压缩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值