视频文件解析前篇-MP4 文件的 Profile、Level 和 YUV

做过一段时间的音视频开发,逐渐知道 MP4 文件中的 MP4 只是一种封装格式,里面的音视频数据则一般实际上是 H264。

而 H264 其实也有很多种的版本,比如 H264 High、H264 Main、H264 Baseline,这些版本的区别在于支持的功能不同,比如 H264 Baseline 不支持 B 帧,H264 Main 支持 4:2:2 色彩取样格式,H264 High 支持 4:4:4 色彩取样格式。

在处理视频文件错误的过程中,也积累了一些经验,逐渐了解了 MP4 文件的 Profile 和 Level,以及 YUV 颜色空间的概念。

Profile 和 Level

**Profile(配置集)**表示编码器在生成视频流时所使用的压缩算法的集合。不同的Profile支持不同的功能和压缩效率。

在H.264中,一些常见的Profile有Baseline、Main和High等。

Baseline Profile 是最基本的 Profile,它提供了基本的视频压缩功能。此前在前面的文章中描述过,遇到视频使用 Baseline Profile 编码,导致视频只有一个关键帧,无法拖动进度条的问题。

Main Profile 在 Baseline 的基础上增加了一些高级功能,例如支持B帧和更复杂的编码。

High Profile 是最高级别的 Profile,它支持更多的功能和更高的压缩效率。

**Level(级别)**表示编码器生成的视频流的各种技术参数的限制。这些参数包括分辨率、帧率、比特率等。

Level 的目的是确保解码器能够正确解码和播放视频流,因为不同的设备和平台对视频流的解码能力有不同的限制。较高的Level通常意味着更高的分辨率、帧率和比特率。

常见的 Level 有 3.0、3.1、4.0、4.1、4.2 等。

可以使用 ffmpeg 命令将视频转为不同的 Profile 和 Level,比如:

shell 复制代码
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 base-3.0.mp4
ffmpeg -i input.mp4 -profile:v baseline -level 3.1 base-3.1.mp4
ffmpeg -i input.mp4 -profile:v main -level 3.1 main-3.1.mp4
ffmpeg -i input.mp4 -profile:v main -level 4.0 main-4.0.mp4
ffmpeg -i input.mp4 -profile:v high -level 4.0 high-4.0.mp4
ffmpeg -i input.mp4 -profile:v high -level 4.1 high-4.1.mp4
ffmpeg -i input.mp4 -profile:v high -level 4.2 high-4.2.mp4

YUV 颜色空间

YUV是一种常见的颜色空间,用于表示彩色图像。它将颜色信息分为亮度(Y)和色度(U和V)两个分量。

现在 YUV 一般都是指 YCbCr,其中 Y表示图像的亮度信息,而U和V表示图像的色度信息。在视频编码中,通常使用YUV颜色空间来表示原始图像数据,因为它可以更好地压缩和传输彩色图像。

YUV 和 RGB 可以相互转换。

RGB 转 YUV 的公式如下:

js 复制代码
Y =       (0.257 * R) + (0.504 * G) + (0.098 * B) +  16
Cr = V =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 

YUV 转 RGB 的公式如下:

js 复制代码
R = 1.164(Y - 16) + 1.596(V -128)
G = 1.164(Y - 16) - 0.813(V -128) - 0.391(U - 128)
B = 1.164(Y - 16) + 2.018(U - 128)

下面是 RGB 颜色空间和 YUV 颜色空间如果只有单分量的效果:

可以看到如果只有 Y 分量,那就相当于黑白图像,而 U、V 分量则是用来表示颜色的。

电视节目中的彩色图像通常使用YUV颜色空间来表示,可以兼容黑白电视和彩色电视。黑白电视只使用Y分量,而彩色电视使用YUV颜色空间的所有分量。

YUV420 YUV422 YUV444

根据 YUV 分量的取样方式,可以将 YUV 分为 YUV 4:4:4、YUV 4:2:2 和 YUV 4:2:0 三种,其中 YUV4:2:0 则是最常用的一种。

  • YUV 4:4:4采样,每一个Y对应一组UV分量。
  • YUV 4:2:2采样,每两个Y共用一组UV分量。
  • YUV 4:2:0采样,每四个Y共用一组UV分量。

我们有时候会看到 YUV420p 这样的描述,这里的 420 表示的就是 YUV420 的意思,p 表示的是 planar,也就是平面的意思,表示 Y、U、V 三个分量是分开存储的,而不是交叉存储的。

一般来说,YUV420p 和 YUV420 是一个意思。

与之不同的是 YUV420sp 和 YUV420i,但是不常用。其中 sp 表示的是 semi-planar,也就是半平面的意思,表示 Y 分量是单独存储的,而 U、V 分量是交叉存储的。i 表示的是 interleaved,也就是交叉的意思,表示 Y、U、V 三个分量是交叉存储的。

可以使用 ffmpeg 命令将视频转为不同的 YUV 格式,比如:

shell 复制代码
ffmpeg -i input.mp4 -pix_fmt yuv420p yuv420p.mp4
ffmpeg -i input.mp4 -pix_fmt yuv422p yuv422p.mp4
ffmpeg -i input.mp4 -pix_fmt yuv444p yuv444p.mp4

Profile 和 YUV 颜色空间的关系

虽然Profile和YUV颜色空间是两个不同的概念,但它们在视频编码中是相关的。

在视频编码过程中,编码器将原始的RGB图像转换为YUV颜色空间,然后根据所选的 Profile 对YUV数据进行压缩编码。

因此,Profile 决定了编码器使用的压缩算法和功能,而YUV颜色空间则是表示原始图像数据的一种格式。

一般来说,Profile 和 YUV 颜色空间是一一对应的,比如 H264 Baseline Profile 只支持 YUV420p,H264 Main Profile 一般支持 YUV420p,只有 H264 High Profile 支持 YUV420p、YUV422p 和 YUV444p。

下面是一个视频的 Profile 和 YUV 数据示例:

基于 mp4box.js 读取 MP4 文件的 Profile 和 Level

使用 mp4box.js 分析 MP4 文件,得到视频文件的 moov box 之后,就可以从中读取 Profile 和 Level 了。

这些数据存储在moov(Movie Box)box中的trak(Track Box)box中的mdia(Media Box)box中的minf(Media Information Box)box中的stbl(Sample Table Box)box中的stsd(Sample Description Box)box中的avc1(AVC Sample Entry)box中。

具体来说,avc1 box 中的 avcC(AVC Configuration Box)box 中的 AVCProfileIndication 和 AVCLevelIndication 字段就是 Profile 和 Level 的值。

AVCProfileIndication 一般取值为 66、77、88、100、110、122、244,对应的 Profile 分别是 Baseline、Main、Extended、High、High10、High422、High444。

AVCLevelIndication 一般取值为 30、31、32、40、41、42、50、51、52,对应的 Level 分别是 3.0、3.1、3.2、4.0、4.1、4.2、5.0、5.1、5.2。

js 复制代码
const ProfileMap = {
  66: "Baseline",
  77: "Main",
  88: "Extended",
  100: "High",
  110: "High10",
  122: "High422",
  244: "High444",
};

const ColorSpaceMap = {
  66: "YUV4:2:0",
  77: "YUV4:2:0",
  88: "YUV4:2:0",
  100: "YUV4:2:0",
  110: "YUV4:2:0",
  122: "YUV4:2:2",
  244: "YUV4:4:4",
};

下面是读取 Profile 和 Level 的代码:

js 复制代码
const videoTrackId = info.videoTracks[0].id;
const moovVideoTrack = mp4box.moov.traks.find((track) => track.tkhd.track_id === videoTrackId);
const entries = get(moovVideoTrack, "mdia.minf.stbl.stsd.entries", []);

const profileName = avcC?.AVCProfileIndication &&
              `${ProfileMap[avcC.AVCProfileIndication]}@L${(avcC.AVCLevelIndication / 10).toFixed(1)}`;

const colorSpace = avcC?.AVCProfileIndication && ColorSpaceMap[avcC.AVCProfileIndication]

当前主流浏览器支持的视频编码格式中,除了 H264 之外,另一个则是 AV1。

AV1 编码格式

我们知道现在视频常用的编码格式依然是 H264,但是 H264 已经有十多年的历史了,最高只支持 4K 分辨率,而且压缩率也不高,所以需要新的编码格式来取代 H264。

而 H265 由于专利费的原因,没有被广泛使用,基本没有多少硬件支持 H265 编码,需要播放 H265 编码的视频,都需要软件解码,对电脑 CPU 占用很高。

而 Google 推出的 VP8 和 VP9 编码格式,虽然免费,但是没有被广泛支持,所以也没有取代 H264 的趋势。

所以 AV1 成为了最有可能取代 H264 的编码格式。AV1 即 AOMedia Video 1,是由 AOMedia 开发的开源视频编码格式,它的目标是取代 H264 和 VP9,成为下一代的视频编码格式。

AOMedia 是一个由多家科技公司组成的联盟,旨在开发开放、免版权的音视频编码技术。该联盟的创始成员包括谷歌、苹果、亚马逊、Facebook、微软等。

AV1 相比 H264,有着更高的压缩率,可以减少 30% 的码率,同时保持相同的视频质量。相比 H265,AV1 则是免费的,没有专利费,各大厂商也愿意支持 AV1。

但目前 AV1 的硬件支持还不够,所以 AV1 的编码速度比较慢,而且 AV1 的解码速度也比较慢,在国内并没有被广泛支持。

参考资料

相关推荐
让开,我要吃人了2 小时前
HarmonyOS开发实战(5.0)实现二楼上划进入首页效果详解
前端·华为·程序员·移动开发·harmonyos·鸿蒙·鸿蒙系统
everyStudy3 小时前
前端五种排序
前端·算法·排序算法
甜兒.4 小时前
鸿蒙小技巧
前端·华为·typescript·harmonyos
Jiaberrr7 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy8 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白8 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、8 小时前
Web Worker 简单使用
前端
web_learning_3218 小时前
信息收集常用指令
前端·搜索引擎
tabzzz8 小时前
Webpack 概念速通:从入门到掌握构建工具的精髓
前端·webpack
200不是二百8 小时前
Vuex详解
前端·javascript·vue.js