type
status
date
slug
summary
tags
category
icon
password
Property
Mar 20, 2023 02:19 AM

基础知识

流媒体编解码流程

  • ⾳视频编码在流媒体和⽹络领域占有重要地位;流媒体编解码流程⼤致如下图所示:
notion image

H.264

H.264 简介

notion image

H.264 编码原理

notion image
notion image

H.264 编码结构解析

notion image

GOP

notion image

I、P、B帧

  • 压缩方式:
    • notion image
notion image
notion image
  • I 帧:
    • notion image
  • P 帧:
    • notion image
  • B 帧:
    • notion image

IDR 帧

  • IDR(Instantaneous Decoding Refresh,即时解码刷新):
    • notion image
      notion image
  • 直播一般不插入B帧(以1秒25帧为例),下图情况B帧将产生160ms的延迟:
    • notion image

NALU

NALU 简介

NALU(Network Abstract Layer Unit) 是用于视频编码的一种数据格式,主要用于 H.264(也称为 AVC)和 H.265(也称为 HEVC)编码标准中。它是视频编码器输出的基本单位,也是视频解码器输入的基本单位。
notion image
  • 若码流中间有改变(如分辨率发生变化):需要重新发送 SPS 和 PPS,否则码流会解析不出来

NALU 结构

notion image
notion image
  • FFmpeg 中
    • notion image

解析 NALU

notion image
notion image
notion image
notion image
  • 对于NALU分析主要关注5/6/7/8 四种类型。

H.264 两种封装模式

  • annexb 模式和 mp4 模式:
    • notion image
    • ES是Elementary Stream的缩写,即基本流或基本码流。在音视频领域中,通常将音频或视频的数据流称为Elementary Stream。 ES 是指不带有容器(如MP4、FLV等)或不包含其他流(如字幕、元数据等)的音视频数据流,是音视频数据的最基本形式。一个ES中只包含一种媒体(音频或视频)的数据,而且不包含容器格式和文件头等信息,只包含编码后的压缩数据。 ES 通常会进行编码和解码,然后通过其他方法将其打包到容器中(如MP4、FLV等),以实现文件的存储和传输。
  • FFmpeg 实现 mp4 格式转换为 annexb 格式:

    提取 H.264 代码

    FFmpeg 实现从 MP4 上提取 H.264 的 NALU

    过滤器相关 API 解析

    • av_bsf_get_by_name :是用于获取指定名称的 AVBitStreamFilter 过滤器的函数。该函数的作用是在 FFmpeg 中注册的过滤器列表中查找指定名称的过滤器,并返回一个指向 AVBitStreamFilter 结构体的指针。如果找到了指定名称的过滤器,则返回该指针;否则,返回 NULL。
      • 函数原型如下:
        • 函数参数 name 是一个字符串,表示要查找的过滤器的名称。在 FFmpeg 中,已经注册的过滤器名称都是唯一的,因此可以根据名称来精确查找指定的过滤器。
    • av_bsf_alloc :是用于创建 AVBSFContext 上下文结构体的函数,用于进行音视频码流的转换和处理。该函数会根据指定的过滤器创建一个 AVBSFContext 结构体,并对其进行初始化和配置,以便后续进行音视频码流的转换处理操作。
      • 函数原型如下:
        • 函数参数 filter 是一个指向 AVBitStreamFilter 结构体的指针,表示要使用的过滤器。参数 ctx 是一个指向 AVBSFContext 结构体指针的指针,表示创建的 AVBSFContext 上下文结构体的地址。函数返回值为整数类型,表示函数的执行状态,如果执行成功,则返回 0;否则,返回负数表示执行出错。
    • avcodec_parameters_copy :用于将一个 AVCodecParameters 结构体的值复制到另一个 AVCodecParameters 结构体中。AVCodecParameters 结构体用于描述编解码器的参数,包括编码格式、视频宽高、帧率、音频采样率、声道数等信息。在进行音视频编解码时,需要根据输入或输出媒体文件的编码格式和参数,对编解码器进行初始化,因此需要用到 AVCodecParameters 结构体。
      • 函数原型如下:
        • 该函数接收两个参数:dst src,分别表示目标和源 AVCodecParameters 结构体。函数的作用是将源 AVCodecParameters 结构体中的值复制到目标 AVCodecParameters 结构体中。如果复制成功,则返回 0,否则返回一个负数错误代码表示执行出错。
    • av_bsf_init :用于初始化一个比特流过滤器(Bitstream Filter)上下文。比特流过滤器是用于对编码数据进行处理的组件,可以用于压缩格式转换、增加或删除视频/音频流等。在进行音视频编解码时,经常需要对输入或输出数据进行比特流过滤,因此需要用到比特流过滤器。
      • 函数原型如下:
        • 该函数接收一个 AVBSFContext 结构体指针作为参数,表示需要初始化的比特流过滤器上下文。如果初始化成功,则返回 0,否则返回一个负数错误代码表示执行出错。
    • av_bsf_send_packet :用于向比特流过滤器发送待处理的音视频数据。它用于将需要进行处理的音视频帧数据送入过滤器链中,让过滤器对数据进行处理。
      • 函数原型如下:
        • 该函数接收两个参数,第一个参数 ctx 是一个指向 AVBSFContext 结构体的指针,表示需要处理的比特流过滤器上下文。第二个参数 pkt 是一个指向 AVPacket 结构体的指针,表示待处理的音视频帧数据。如果发送成功,则返回 0,否则返回一个负数错误代码表示执行错。
    • av_bsf_receive_packet用于从比特流过滤器接收处理后的音视频帧数据。它用于从过滤器链中读取经过处理的音视频帧数据。
      • 函数原型如下:
        • 该函数接收两个参数,第一个参数 ctx 是一个指向 AVBSFContext 结构体的指针,表示需要处理的比特流过滤器上下文。第二个参数 pkt 是一个指向 AVPacket 结构体的指针,表示接收到的经过处理后的音视频帧数据。如果成功读取到了数据,则返回 0,否则返回一个负数错误代码表示执行出错。
      • 为什么需要多次调用 av_bsf_receive_packet
        • AVBSFContext结构体中可能会包含多个AVPacket数据包,因此av_bsf_receive_packet函数可以被调用多次,以从AVBSFContext中接收所有数据包。每次调用该函数时,它将尝试接收并返回一个AVPacket数据包。如果该数据包包含完整的数据,则函数将返回1。如果数据包只包含部分数据,则函数将返回0。如果在数据包的结尾处没有更多数据,则函数将返回AVERROR_EOF。
        • 在你的代码中,可能存在一些情况导致一次调用av_bsf_receive_packet函数无法接收到所有数据。例如,如果输入文件的大小不是数据包大小的整数倍,则最后一个数据包可能不完整,并且需要在下一次读取时才能完成。此外,如果输出文件的写入速度低于输入文件的读取速度,则会导致AVBSFContext中的缓冲区被填满,从而需要多次调用av_bsf_receive_packet函数才能接收所有数据包。因此,为了正确地处理所有数据,你需要在循环中多次调用av_bsf_receive_packet函数,直到它返回AVERROR_EOF。
    FLV 媒体封装格式分析AAC 音频编码格式分析