音视频入门基础:H.264专题(17)——FFmpeg源码中,获取H.264视频的profile的实现

=================================================================

音视频入门基础:H.264专题系列文章:

音视频入门基础:H.264专题(1)------H.264官方文档下载

音视频入门基础:H.264专题(2)------使用FFmpeg命令生成H.264裸流文件

音视频入门基础:H.264专题(3)------EBSP, RBSP和SODB

音视频入门基础:H.264专题(4)------NALU Header:forbidden_zero_bit、nal_ref_idc、nal_unit_type简介

音视频入门基础:H.264专题(5)------FFmpeg源码中 解析NALU Header的函数分析

音视频入门基础:H.264专题(6)------FFmpeg源码:从H.264码流中提取NALU Header、EBSP、RBSP和SODB

音视频入门基础:H.264专题(7)------FFmpeg源码中 指数哥伦布编码的解码实现

音视频入门基础:H.264专题(8)------H.264官方文档的描述符

音视频入门基础:H.264专题(9)------SPS简介

音视频入门基础:H.264专题(10)------FFmpeg源码中,存放SPS属性的结构体和解码SPS的函数分析

音视频入门基础:H.264专题(11)------计算视频分辨率的公式

音视频入门基础:H.264专题(12)------FFmpeg源码中通过SPS属性计算视频分辨率的实现

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

音视频入门基础:H.264专题(14)------计算视频帧率的公式

音视频入门基础:H.264专题(15)------FFmpeg源码中通过SPS属性获取视频帧率的实现

音视频入门基础:H.264专题(16)------FFmpeg源码中,判断某文件是否为H.264裸流文件的实现

音视频入门基础:H.264专题(17)------FFmpeg源码中,获取H.264视频的profile的实现

音视频入门基础:H.264专题(18)------FFmpeg源码获取H.264裸流文件信息(视频压缩编码格式、色彩格式、视频分辨率、帧率)的总流程

音视频入门基础:H.264专题(19)------AVCDecoderConfigurationRecord简介

音视频入门基础:H.264专题(20)------FFmpeg源码中,获取avcC封装的H.264码流中每个NALU的长度的实现

音视频入门基础:H.264专题(21)------FFmpeg源码中,解码AVCDecoderConfigurationRecord的实现

音视频入门基础:H.264专题(22)------通过FFprobe显示H.264裸流每个packet的信息

=================================================================

一、引言

通过FFmpeg命令可以查看到H.264视频的profile(规格):

cpp 复制代码
./ffmpeg -i XXX

这个profile是通过解码SPS的profile_idc属性获取到的。profile_idc属性固定占1字节,表示当前这路H.264码流的编码档次:

比如,profile_idc的值为66表示是Baseline profile:

profile_idc的值为77表示是Main profile:

profile_idc的值为88表示是Extended profile:

profile_idc的值为100表示是High profile:

除此之外,还有其它profile,具体可以查阅H.264官方文档《T-REC-H.264-202108-I!!PDF-E.pdf》。

二、FFmpeg源码中,获取H.264视频的profile的实现

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

ff_h264_decode_seq_parameter_set函数中通过下面代码解析出SPS中的profile_idc属性, 存贮到sps->profile_idc中:

cpp 复制代码
int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,
                                     H264ParamSets *ps, int ignore_truncation)
{
//...
    profile_idc           = get_bits(gb, 8);
//...
    sps->profile_idc          = profile_idc;
//...
}

然后在libavcodec/h264_parser.c的parse_nal_units函数中,通过下面代码将profile_idc属性赋值给AVCodecContext的profile:

cpp 复制代码
static inline int parse_nal_units(AVCodecParserContext *s,
                                  AVCodecContext *avctx,
                                  const uint8_t * const buf, int buf_size)
{
//...
    avctx->profile = ff_h264_get_profile(sps);
//...
}

ff_h264_get_profile函数定义在libavcodec/h264_parse.c中,该函数是用来计算SPS的profile_idc属性和constraint_set?_flags属性的:

cpp 复制代码
/**
 * Compute profile from profile_idc and constraint_set?_flags.
 *
 * @param sps SPS
 *
 * @return profile as defined by AV_PROFILE_H264_*
 */
int ff_h264_get_profile(const SPS *sps)
{
    int profile = sps->profile_idc;

    switch (sps->profile_idc) {
    case AV_PROFILE_H264_BASELINE:
        // constraint_set1_flag set to 1
        profile |= (sps->constraint_set_flags & 1 << 1) ? AV_PROFILE_H264_CONSTRAINED : 0;
        break;
    case AV_PROFILE_H264_HIGH_10:
    case AV_PROFILE_H264_HIGH_422:
    case AV_PROFILE_H264_HIGH_444_PREDICTIVE:
        // constraint_set3_flag set to 1
        profile |= (sps->constraint_set_flags & 1 << 3) ? AV_PROFILE_H264_INTRA : 0;
        break;
    }

    return profile;
}

最后在dump_stream_format函数中,通过avcodec_string函数中的语句:profile = avcodec_profile_name(enc->codec_id, enc->profile)拿到上一步得到的AVCodecContext的profile。再在dump_stream_format函数中将profile打印出来:

cpp 复制代码
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
{
//...
    profile = avcodec_profile_name(enc->codec_id, enc->profile);
//...
}
相关推荐
lzptouch2 小时前
数据预处理(音频/图像/视频/文字)及多模态统一大模型输入方案
人工智能·音视频
casdfxx4 小时前
捡到h3开发板,做了个视频小车(二),御游追风plus做遥控器
音视频
mortimer5 小时前
FFmpeg 音画同步实践记录:从切片、变速到拼接,彻底搞定时间轴
ffmpeg
给大佬递杯卡布奇诺5 小时前
FFmpeg 基本API avcodec_send_packet函数内部调用流程分析
c++·ffmpeg·音视频
酌量6 小时前
从 ROS 订阅视频话题到本地可视化与 RTMP 推流全流程实战
经验分享·笔记·ffmpeg·音视频·ros
给大佬递杯卡布奇诺7 小时前
FFmpeg 基本API av_seek_frame函数内部调用流程分析
c++·ffmpeg·音视频
音视频牛哥11 小时前
从“小而美”到“大而强”:音视频直播SDK的技术进化逻辑
机器学习·计算机视觉·音视频·大牛直播sdk·人工智能+·rtsp播放器rtmp播放器·rtmp同屏推流
碎像11 小时前
ffmpeg下载和实战获取音视频时长
ffmpeg
空影星11 小时前
GridPlayer,一个好用的多视频同步播放器
python·flask·电脑·音视频
哲学七13 小时前
Springboot3.5.x版本引入javaCv相关库版本问题以及精简引入包
java·ffmpeg