美文网首页
Android 音视频开发四 H264详解

Android 音视频开发四 H264详解

作者: Kael_Zhang的安卓笔记 | 来源:发表于2023-02-26 11:42 被阅读0次

    概述

    前面的章节已经详细介绍了YUV到H264的过程,那么H264究竟什么样子?本文详细介绍一下

    H264定义的几种帧

    • I帧:完整编码的帧叫I帧
    • P帧:参考之前的I帧生成的只包含差异部分编码的帧叫P帧
    • B帧:参考前后的帧编码的帧叫B帧
    • IDR帧:GOP序列是在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,一个序列的第一个图像叫做 IDR 图像(立即刷新图像,即刷新参考帧,将参考帧队列清空,避免上一个GOP参考出错引起的错误蔓延),IDR 图像都是 I 帧图像

    Slice

    • Slice 其实是为了并行编码设计的,一般来说是为了提高编码速度的,将一帧图像划分成几个 Slice
    • Slice 之间相互独立、互不依赖、独立编码。所以帧内预测时候,不能跨Slice预测,所以一帧图像包含一或者若干个slice,一个slice包含若干个宏块
    • Slice数据包含了Slice Header、Slice payload ,Slice Header 中存放了这个 Slice 会用到的参数项,而 payload 中则存放了真正的图像信息,即具体的宏块数据。Slice header主要是当前Slice包含的宏块的一些基本的数据,例如Slice的类型,Slice属于的那一帧的信息,以及当前Slice使用的图像序列参数以及量化参数等信息
    • I Slice:仅包含I宏块
      P Slice:包含P宏块和I宏块
      B Slice:包含B宏块和I宏块
      SP Slice:包含B宏块和I宏块,用于使编码流之间容易交换
      SI Slice:包含SI宏块(一种特殊的编码宏块),用于使编码流之间容易交换

    SPS(序列参数集)和PPS(图像参数集)

    • 它们虽然数据量不大可是来头可不小,没有他们,码流根本无法解码,其中,SPS 主要包含的是图像的宽、高、YUV 格式和位深等基本信息;PPS 则主要包含熵编码类型、基础 QP 和最大参考帧数量等基本编码信息。
    • 简而言之,H264 的码流主要是由 SPS、PPS、I Slice、P Slice和B Slice 组成的。

    H.264分层设计

    • VCL:(Video Coding Layer)视频编码层,负责高效的内容表示。
    • NAL:(Network Abstraction Layer)网络抽象层,负责以网络所要求的恰当的方式对数据进行打包和传送,NAL设计的目的,是根据不同的网络把数据打包成相应的格式,将VCL产生的比特字符串适配到各种各样的网络和多元环境中。

    NALU

    • NALU是NAL的基本单元,NAL是将一个Slice或者PPS或者SPS数据写入到一个NAL单元中,进行传输或存储的,所以一个Slice或者PPS或者SPS,统称为RBSP单元(Raw Byte Sequence Payload),都是一个NALU payload

    • NALU包含NALU Header、NALU payload,NALU Header通常为00 00 00 01、00 00 01开始,作为一个新的NALU的起始标识

    • NALU起始码

      1. 两种,3字节0x000001单帧多Slice(即单帧多个NALU)之间间隔,4字节0x00000001 帧之间,或者SPS、PPS等之前,起始码字节用来分割NALU。
      2. 问题来了,如果RBSP中也包括了起始码(0x000001或0x00000001)怎么办呢?所以,就有了防止竞争字节(0x03),具体做法:编码时,扫描RBSP,如果遇到连续两个0x00字节,就在后面添加防止竞争字节(0x03),解码时逆向操作即可
      3. 简而言之 NALU 寻找帧间隔就找0x00000001, 寻找Slice间隔就找 0x000001,帧间隔包含sps、pps
        起始码
    • NALU header

      1. 由1 bit的禁止位forbidden_zero_bit、2 bit重要性nal_ref_idc以及5 bits的nal_unit_type组成,
      2. NALU header forbidden_zero_bit 禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。
      3. NALU header 后两位为 nal_ref_idc nal_ref_idc 代表 NALU 的重要性。值越大说明约重要。取值范围0~3,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。当前的 NAL 是参考帧,序列集参数集或图像集重要数据时必须大于0。
      4. 最后五位为 nal_unit_type 指的是当前 NAL 的类型
    • nal_unit_type


      nal_unit_type
      1. 其中0x67的二进制码为:0110 0111
        4-8为00111,转为十进制7,参考图:7对应序列参数集SPS

      2. 其中0x68的二进制码为:0110 1000
        4-8为01000,转为十进制8,参考图:8对应图像参数集PPS

      3. 其中0x65的二进制码为:0110 0101
        4-8为00101,转为十进制5,参考图:5对应IDR图像中的片(I帧)

      4. 其中0x41的二进制码为:0100 0001
        4-8为00001,转为十进制1,参考图:1对应非IDR图像中的片(这里指的是P帧)

      5. 其中0x61的二进制码为:0110 0001
        4-8为00001,转为十进制1,参考图:1对应非IDR图像中的片(同上,为P帧,仅仅是重要性不同)

      6. 其中0x06的二进制码为:0000 0100
        4-8为00100,转为十进制6,参考图:6对应SEI

    H264图例

    H264结构

    总结

    这几个章节从下到上详细描述了H264的码流,最基础的宏块讲起,多个宏块又组成了Slice,Slice和PPS和SPS又组成了一个NALU payload,NALU payload 又和NALU header 组成了一个完整的NALU,NALU和起始码最终组成完整的码流,在网络中传输,也可以是保存在存储介质中

    相关文章

      网友评论

          本文标题:Android 音视频开发四 H264详解

          本文链接:https://www.haomeiwen.com/subject/bqegkdtx.html