当前位置: 首页 > news >正文

音视频入门基础:H.264专题(13)——FFmpeg源码中通过SPS属性获取视频色彩格式的实现

一、引言

通过FFmpeg命令可以获取到H.264裸流文件的色彩格式(又译作色度采样结构、像素格式):

在vlc中也可以获取到色彩格式(vlc底层也使用了FFmpeg进行解码):

这个色彩格式就是之前的文章《音视频入门基础:像素格式专题(4)——YUV简介》中描述的像素格式。所以FFmpeg和vlc是怎样获取到H.264编码的视频的色彩格式呢?它们其实是通过SPS中的属性chroma_format_idc获取的。

二、H.264官方文档对chroma_format_idc的描述

chroma_format_idc属性在H.264官方文档《T-REC-H.264-202108-I!!PDF-E.pdf》第44页中定义:

根据H.264官方文档《T-REC-H.264-202108-I!!PDF-E.pdf》第22页,当chroma_format_idc = 0时,色彩格式为单色;chroma_format_idc = 1时,色彩格式为YUV 4:2:0;chroma_format_idc = 2时,色彩格式为YUV 4:2:2;chroma_format_idc = 3时,色彩格式为YUV 4:4:4:

根据H.264官方文档第74页,chroma_format_idc的值应该在0到3的范围内(包括0和3)。当chroma_format_idc不存在时,应推断其值为1(4:2:0的色度格式)。

也就是说,只有当profile_idc等于下面红框里的这些值时,chroma_format_idc才会存在。如果profile_idc不是这些值,chroma_format_idc的值就是1,表示色彩格式为YUV 4:2:0:

三、计算色彩格式的例子

下面以某个视频文件为例,讲述怎么计算它的色彩格式。用Elecard Stream Analyzer工具打开一个用H.264编码的视频文件,看到其profile_idc值为77。由于profile_idc不是上图红框里的那些值,所以chroma_format_idc值为1,所以该视频的色彩格式为YUV 4:2:0:

用Elecard StreamEye工具可以看到该视频的色彩格式确实为YUV 4:2:0,证明我们的计算是正确的:

四、FFmpeg源码中获取色彩格式的实现

从文章《音视频入门基础:H.264专题(10)——FFmpeg源码中,存放SPS属性的结构体和解码SPS的函数分析》中,我们可以知道,FFmpeg源码中通过ff_h264_decode_seq_parameter_set函数解码SPS,从而拿到SPS中的属性。

在ff_h264_decode_seq_parameter_set函数中有如下代码,通过下面的这部分代码拿到SPS中的chroma_format_idc:

int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,H264ParamSets *ps, int ignore_truncation)
{//...if (sps->profile_idc == 100 ||  // High profilesps->profile_idc == 110 ||  // High10 profilesps->profile_idc == 122 ||  // High422 profilesps->profile_idc == 244 ||  // High444 Predictive profilesps->profile_idc ==  44 ||  // Cavlc444 profilesps->profile_idc ==  83 ||  // Scalable Constrained High profile (SVC)sps->profile_idc ==  86 ||  // Scalable High Intra profile (SVC)sps->profile_idc == 118 ||  // Stereo High profile (MVC)sps->profile_idc == 128 ||  // Multiview High profile (MVC)sps->profile_idc == 138 ||  // Multiview Depth High profile (MVCD)sps->profile_idc == 144) {  // old High444 profilesps->chroma_format_idc = get_ue_golomb_31(gb);//...}else {sps->chroma_format_idc = 1;//...}//...
}

然后在FFmpeg源码的源文件libavcodec/h264_parser.c的parse_nal_units函数中,通过如下代码,得到色彩格式:

static inline int parse_nal_units(AVCodecParserContext *s,AVCodecContext *avctx,const uint8_t * const buf, int buf_size)
{//...for (;;) {switch (nal.type) {case H264_NAL_SPS:ff_h264_decode_seq_parameter_set(&nal.gb, avctx, &p->ps, 0);break;//...case H264_NAL_IDR_SLICE://...switch (sps->bit_depth_luma) {case 9:if (sps->chroma_format_idc == 3)      s->format = AV_PIX_FMT_YUV444P9;else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P9;else                                  s->format = AV_PIX_FMT_YUV420P9;break;case 10:if (sps->chroma_format_idc == 3)      s->format = AV_PIX_FMT_YUV444P10;else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P10;else                                  s->format = AV_PIX_FMT_YUV420P10;break;case 8:if (sps->chroma_format_idc == 3)      s->format = AV_PIX_FMT_YUV444P;else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P;else                                  s->format = AV_PIX_FMT_YUV420P;break;default:s->format = AV_PIX_FMT_NONE;}//... }//...}
}

相关文章:

  • PyTorch张量创建和随机数生成器算法
  • 【区块链 + 智慧政务】区块链 +ETC 下一代公路联网收费关键技术优化项目 | FISCO BCOS应用案例
  • 去除重复数字
  • 浅聊授权-spring security和oauth2
  • K8S系列-Kubernetes基本概念及Pod、Deployment、Service的使用
  • 新增支持GIS地图、数据模型引擎升级、增强数据分析处理能力
  • 内网安全:权限维持的各种姿势
  • GaussDB DWS 详解
  • 基坑安全:自动化监测系统的革新力量
  • 对于远程仓库, 只给出了下载安装包的选项没有给出克隆虚的相关代码怎么办?
  • 【Python】ftplib的使用
  • pico+unity3d运行测试方法
  • 昇思25天学习打卡营第7天 | MindNLP ChatGLM-6B StreamChat
  • Redis的配置优化、数据类型、消息队列
  • springboot 程序运行一段时间后收不到redis订阅的消息
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • Android Studio:GIT提交项目到远程仓库
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • Vue.js源码(2):初探List Rendering
  • Vue全家桶实现一个Web App
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 前端知识点整理(待续)
  • 区块链共识机制优缺点对比都是什么
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 微信小程序设置上一页数据
  • 小而合理的前端理论:rscss和rsjs
  • 用 Swift 编写面向协议的视图
  • 原生 js 实现移动端 Touch 滑动反弹
  • zabbix3.2监控linux磁盘IO
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • # 利刃出鞘_Tomcat 核心原理解析(二)
  • $.ajax()参数及用法
  • (4)事件处理——(7)简单事件(Simple events)
  • (C语言)fgets与fputs函数详解
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (推荐)叮当——中文语音对话机器人
  • (译)2019年前端性能优化清单 — 下篇
  • (原创)可支持最大高度的NestedScrollView
  • (转) RFS+AutoItLibrary测试web对话框
  • .NET gRPC 和RESTful简单对比
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET技术成长路线架构图
  • @Documented注解的作用
  • @RestControllerAdvice异常统一处理类失效原因
  • [ C++ ] STL_list 使用及其模拟实现
  • [2021ICPC济南 L] Strange Series (Bell 数 多项式exp)
  • [ACM独立出版] 2024年虚拟现实、图像和信号处理国际学术会议(VRISP 2024,8月2日-4)
  • [AI]文心一言爆火的同时,ChatGPT带来了这么多的开源项目你了解吗
  • [ASP.NET MVC]Ajax与CustomErrors的尴尬
  • [autojs]逍遥模拟器和vscode对接
  • [BeginCTF]真龙之力
  • [BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务