码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 音视频入门基础:H.264专题(5)——FFmpeg源码中 解析NALU Header的函数分析


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

    音视频入门基础: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官方文档的描述符

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

    一、引言

    FFmpeg源码中 通过h264_parse_nal_header函数将H.264码流的NALU Header解析出来。下面对h264_parse_nal_header函数进行分析。


     

    二、h264_parse_nal_header函数定义

    h264_parse_nal_header函数定义在FFmpeg源码(下面演示的FFmpeg源码版本是5.0.3)的源文件libavcodec/h2645_parse.c 中:

    1. static int h264_parse_nal_header(H2645NAL *nal, void *logctx)
    2. {
    3. GetBitContext *gb = &nal->gb;
    4. if (get_bits1(gb) != 0)
    5. return AVERROR_INVALIDDATA;
    6. nal->ref_idc = get_bits(gb, 2);
    7. nal->type = get_bits(gb, 5);
    8. av_log(logctx, AV_LOG_DEBUG,
    9. "nal_unit_type: %d(%s), nal_ref_idc: %d\n",
    10. nal->type, h264_nal_unit_name(nal->type), nal->ref_idc);
    11. return 0;
    12. }

    该函数作用是:将NALU Header解析出来,由形参nal返回。

    形参nal:

    nal->gb:输入型参数。(&(nal->gb))->buffer指向存放NALU Header + RBSP 的缓冲区。

    nal->ref_idc:输出型参数。执行h264_parse_nal_header函数后,nal->ref_idc的值为NALU Header中的nal_ref_idc。

    nal->type:输出型参数。执行h264_parse_nal_header函数后,nal->type的值为NALU Header中的nal_unit_type。

    形参logctx:输入型参数。用来输出日志,可以忽略。

    返回值:解析NALU Header成功返回0。失败返回AVERROR_INVALIDDATA。

    三、h264_parse_nal_header函数的内部实现原理

    h264_parse_nal_header函数中,首先通过语句get_bits1(gb);拿到NALU Header中forbidden_zero_bit。关于get_bits1用法可以参考:《FFmpeg中位操作相关的源码:GetBitContext结构体,init_get_bits函数、get_bits1函数和get_bits函数分析》。

    由于forbidden_zero_bit 的值应为0,如果它的值为1,则意味着比特流语法出错了,也就是FFmpeg头文件libavutil/error.h里面定义的“Invalid data found when processing input”:

    #define AVERROR_INVALIDDATA        FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input

    所以如果forbidden_zero_bit的值不为0,返回AVERROR_INVALIDDATA。

    所以有下面语句:

    1. if (get_bits1(gb) != 0)
    2. return AVERROR_INVALIDDATA;

    然后通过下面语句,读取NALU Header中的nal_ref_idc和nal_unit_type,分别保存到nal->ref_idc和nal->type中。

    1. nal->ref_idc = get_bits(gb, 2);
    2. nal->type = get_bits(gb, 5);

    最后通过

    1. av_log(logctx, AV_LOG_DEBUG,
    2. "nal_unit_type: %d(%s), nal_ref_idc: %d\n",
    3. nal->type, h264_nal_unit_name(nal->type), nal->ref_idc);

    日志输出NALU Header的信息。

    h264_nal_unit_name函数是用来得到nal_unit_type的名称。其定义如下:

    1. static const char *const h264_nal_type_name[32] = {
    2. "Unspecified 0", //H264_NAL_UNSPECIFIED
    3. "Coded slice of a non-IDR picture", // H264_NAL_SLICE
    4. "Coded slice data partition A", // H264_NAL_DPA
    5. "Coded slice data partition B", // H264_NAL_DPB
    6. "Coded slice data partition C", // H264_NAL_DPC
    7. "IDR", // H264_NAL_IDR_SLICE
    8. "SEI", // H264_NAL_SEI
    9. "SPS", // H264_NAL_SPS
    10. "PPS", // H264_NAL_PPS
    11. "AUD", // H264_NAL_AUD
    12. "End of sequence", // H264_NAL_END_SEQUENCE
    13. "End of stream", // H264_NAL_END_STREAM
    14. "Filler data", // H264_NAL_FILLER_DATA
    15. "SPS extension", // H264_NAL_SPS_EXT
    16. "Prefix", // H264_NAL_PREFIX
    17. "Subset SPS", // H264_NAL_SUB_SPS
    18. "Depth parameter set", // H264_NAL_DPS
    19. "Reserved 17", // H264_NAL_RESERVED17
    20. "Reserved 18", // H264_NAL_RESERVED18
    21. "Auxiliary coded picture without partitioning", // H264_NAL_AUXILIARY_SLICE
    22. "Slice extension", // H264_NAL_EXTEN_SLICE
    23. "Slice extension for a depth view or a 3D-AVC texture view", // H264_NAL_DEPTH_EXTEN_SLICE
    24. "Reserved 22", // H264_NAL_RESERVED22
    25. "Reserved 23", // H264_NAL_RESERVED23
    26. "Unspecified 24", // H264_NAL_UNSPECIFIED24
    27. "Unspecified 25", // H264_NAL_UNSPECIFIED25
    28. "Unspecified 26", // H264_NAL_UNSPECIFIED26
    29. "Unspecified 27", // H264_NAL_UNSPECIFIED27
    30. "Unspecified 28", // H264_NAL_UNSPECIFIED28
    31. "Unspecified 29", // H264_NAL_UNSPECIFIED29
    32. "Unspecified 30", // H264_NAL_UNSPECIFIED30
    33. "Unspecified 31", // H264_NAL_UNSPECIFIED31
    34. };
    35. static const char *h264_nal_unit_name(int nal_type)
    36. {
    37. av_assert0(nal_type >= 0 && nal_type < 32);
    38. return h264_nal_type_name[nal_type];
    39. }

    可以看到h264_nal_unit_name函数内部通过nal_unit_type拿到数组h264_nal_type_name中对应的字符串(名称)。

    h264_nal_type_name数组跟H.264官方文档《T-REC-H.264-202108-I!!PDF-E.pdf》第65页描述的nal_unit_type对应:

  • 相关阅读:
    JavaScript基础
    OpenHarmony自定义构建函数:@Builder装饰器
    图解 JVM 内存结构
    [OpenCV] Install OpenCV 3.3 with DNN
    Neoj4 cypher脚本基本操作
    bp神经网络怎么看结果,bp神经网络结果不一样
    RCNN算法思想简单讲解概述————(究极简单的讲述和理解)
    【微软漏洞分析】MS15-010 CNG 安全功能绕过漏洞 - CVE-2015-0010
    实现CenterNet图像分割算法模型的转换和量化(SDK0301-转ONNX编译)
    openGL通过点绘制图形
  • 原文地址:https://blog.csdn.net/u014552102/article/details/139958165
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号