博客
关于我
【十五】【vlc-android】vlc-sout流媒体输出端源码实现分析【Part 2】【03】
阅读量:664 次
发布时间:2019-03-15

本文共 2512 字,大约阅读时间需要 8 分钟。

H264解码器实现分析

以下是关于vlc中h264解码器实现的详细分析,涵盖关键函数和模块的功能原理。

10.1.5、bs_read_ue实现分析

bs_read_ue 是一个用于读取指数哥伦布编码的函数,该编码算法在H264和AVS组丝中广泛应用。其主要作用是从H264片数据中读取指数哥伦布码,解码为真实的32位无符号整数值。

函数实现逻辑如下:

  • 初始化变量:unsigned i = 0;
  • 进入while循环,逐个读取比特直到读到1或结束数据读取:
    • bs_read1(s) 读取一个比特值,返回其二进制形式的无符号整数值。由于指数哥伦布编码特点,读取的多个0会被跳过。
    • 如果读取的比特值为0且当前数据指针未达到末尾且i<31,则i++
  • 在读取完0的次数i后,调用bs_read(s, i),将i个比特转换为整数值,并右移i位,得到最终的无符号整数值。
  • 返回结果:return ((1U << i) - 1) + bs_read(s, i);
  • 该函数的核心在于正确解码哥伦布码,通过 blob_size 及读取的位置来确定最终的整数值。


    10.1.6、bs_read_se实现分析

    bs_read_se 是一个用于读取有符号指数哥伦布码的函数。该函数与bs_read_ue类似,但会额外处理读取到的二进制位的最低位,以转换为有符号整数。

    实现逻辑如下:

  • 调用bs_read_ue(s),读取指数哥伦布码对应的无符号整数值val
  • 检查val的最低有效位(LSB):
    • 如果为1,返回(val + 1) / 2
    • 如果为0,返回-(val / 2)
  • 该函数主要用于解码压缩的有符号整数,适用于closer编码后的恢复过程。


    10.2、ActivateSets实现分析

    ActivateSets 模块用于激活H264解码器的图像参数集(PPS/S PS)和序列参数集(SPS)。其主要职责包括:

  • 根据SPS中的参数设置解码器输出格式(包括帧率、分辨率、色彩空间等)。
  • 处理VUI参数,获取采样比(SAR)和其他辅助信息。
  • 查询或创建最新的PPS和SPS参数集,并将其存储到输出格式中。
  • 核心实现包括:

    • 调用h264_get_picture_size获取分辨率信息。
    • 确立帧率估算公式,结合time_scalenum_units_in_tick
    • 处理YUV基色以及色彩范围转换矩阵,存储到输出格式中。
    • 将SPS和PPS数据添加到输出额外数据中,准备供下一阶段使用。

    10.2.1、h264_get_picture_size实现分析

    h264_get_picture_size 用于根据SPS参数计算图像的实际显示尺寸。其主要逻辑包括:

  • 根据frame_mbs_only_flag确定裁剪单位(默认为1或2)。
  • 计算临时宽高值裁剪单位,处理色度平面解码后的特殊情况。
  • 根据SPS指定的宽度和高度(单位为宏块),计算实际像素尺寸。
  • 根据帧剪标志(frame_cropping_flag),确定实际显示宽高。
  • 函数输出包括原始宽高和可见宽高,以及调整后的实际显示尺寸。


    10.2.2、h264_get_colorimetry实现分析

    h264_get_colorimetry 功能负责从SPS中提取色彩基底参数,主要包括:

  • 解码色彩基底类型(YUV到RGB)。
  • 转换色彩空间参数,包括色彩特征坐标和转换矩阵。
  • 处理亮度范围控制以及色域扩展信息。
  • 核心实现依赖于codec提供的转换函数,确保颜色相关数据准确传递到输出格式中。


    10.3、IsFirstVCLNALUnit实现分析

    IsFirstVCLNALUnit 用于检测解码流中是否为主编码图像的第一个VCL NAL单元。其判断条件包括:

    • 帧序号(frame_num)变化。
    • PPS/S PS ID不一致。
    • 场类型(field_pic_flag)变化。
    • NAL参考ID变化。

    上述条件中的任意一个发生时,均视为新序列图像的开始。


    10.4、HxxxParse_AnnexB_SEI实现分析

    HxxxParse_AnnexB_SEI 函数负责解析H.264扩展A部分的SEI(场信息)数据,具体包括:

  • 种Sei类型(如ADI、FR)解码。
  • 处理恢复点信息,调整帧计数。
  • 解析顾客计数(ITU-T.35)。
  • 核心实现逻辑包括:

    • 初始化码流对象,读取SEI类型和大小。
    • 根据类型执行对应的解码操作。
    • 调用用户自定义回调函数进行数据处理。

    支持多种SEI类型,包括时间信息、用户数据、帧包装布局等。


    10.4.1、bs_aligned实现分析

    bs_aligned 函数用于判断码流每个字节的可读比特数是否为8的倍数。这用于确保数据读取正确无偏移。

    实现逻辑单行判断:

    • 返回 (s->i_left % 8) == 0;

    该函数在数据处理前的关键验证步骤,确保字节对齐,避免数据读取错误。


    10.5、ParseSeiCallback实现分析

    ParseSeiCallback 是一个用户定义的回调函数,用于处理解码后的SEI数据。其主要职责包括:

  • 根据SEI类型(如FR、ADI)调用相应处理函数。
  • 更新解码器状态,触发必要的上下文切换。
  • 核心脚本实现包括:

    • 根据数据类型设置相应的SEI参数。
    • 调整视频设置(如多视图模式、颜色范围等)。
    • 标记恢复点状态。

    10.6、OutputPicture实现分析

    OutputPicture 是解码完成后将原始图像数据打包成输出格式的核心函数。其主要步骤包括:

  • 重建NAL序列,插入必要的PPS和SPS参数。
  • 调整 PTS 和 DTS 时间戳,并修正丢失的时间戳。
  • 处理多场(包括 Ordered Fields)和预滚(Preroll)场景。
  • 关键实现步骤:

    • 检查和修复丢失的时间戳。
    • 处理 PICTIMEOUT 帧及恢复点信息。
    • 调整图像分辨率和尺寸,确保输出格式正确。

    该函数为后续模块的播放提供准确的图像数据和时钟信息,保证播放流畅。


    以上是vlc中H264解码器关键模块的实现分析,涵盖了从基本编码解码到参数设置和数据打包的完整流程。

    转载地址:http://wopmz.baihongyu.com/

    你可能感兴趣的文章
    nacos集群搭建
    查看>>
    Navicat for MySQL 查看BLOB字段内容
    查看>>
    Neo4j电影关系图Cypher
    查看>>
    Neo4j的安装与使用
    查看>>
    Neo4j(2):环境搭建
    查看>>
    Neo私链
    查看>>
    nessus快速安装使用指南(非常详细)零基础入门到精通,收藏这一篇就够了
    查看>>
    Nessus漏洞扫描教程之配置Nessus
    查看>>
    Nest.js 6.0.0 正式版发布,基于 TypeScript 的 Node.js 框架
    查看>>
    NetApp凭借领先的混合云数据与服务把握数字化转型机遇
    查看>>
    NetBeans IDE8.0需要JDK1.7及以上版本
    查看>>
    netcat的端口转发功能的实现
    查看>>
    netfilter应用场景
    查看>>
    netlink2.6.32内核实现源码
    查看>>
    Netpas:不一样的SD-WAN+ 保障网络通讯品质
    查看>>
    NetScaler的常用配置
    查看>>
    netsh advfirewall
    查看>>
    NETSH WINSOCK RESET这条命令的含义和作用?
    查看>>
    Netty WebSocket客户端
    查看>>
    netty 主要组件+黏包半包+rpc框架+源码透析
    查看>>