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

基础知识

AVIO 简介

AVIO 是 FFmpeg 提供的一组 I/O 库函数,用于处理多媒体数据的输入输出操作,支持各种输入输出方式,如文件、内存等。它包括了 AVIOContext 结构体和一组函数,可以实现读写操作、网络流传输、HTTP 传输等。
AVIOContext 结构体代表了一个 AVIO 流,其中包含了读写缓存、读写函数指针、读写偏移量等信息。AVIO 可以用于从文件、内存、网络、命名管道和其他数据源读取和写入数据。它还支持自定义协议,可以访问一些不支持标准 I/O 函数的数据源,例如通过 HTTP 或 FTP 下载的文件。
使用 AVIO 的好处之一是它可以提供高度定制化的 I/O 操作。例如,您可以实现自己的协议,或者通过实现自己的读写回调函数来处理数据。此外,AVIO 还提供了一些高级功能,例如缓冲和自动重试,以便更好地管理数据流。
  • 处理自定义协议
    • AVIO 提供了自定义协议的支持,可以通过自己实现回调函数来处理特定的数据源。这些回调函数包括打开 URL、关闭 URL、读取数据、写入数据、移动数据指针等,通过实现这些函数,可以实现对各种类型的数据源的读写操作。
      notion image

AVIO 相关 API

  • av_malloc() :用于分配内存空间
    • av_malloc() 函数的原型如下:
      其中,size_t 类型的 size 参数表示要分配的内存空间大小,函数返回一个 void 指针,指向新分配的内存空间的起始地址。
  • avio_alloc_context() :用于分配并初始化AVIOContext结构体,该结构体提供了输入/输出缓冲区的管理和读写操作。AVIOContext结构体包含了许多字段,包括输入/输出缓冲区指针、缓冲区大小、当前缓冲区位置、读写操作的回调函数等。avio_alloc_context()函数会根据传入的参数分配一段内存用于存储AVIOContext结构体,并设置其各个字段的初值,返回指向该结构体的指针
    • avio_alloc_context()函数的原型如下:
      参数说明:
    • buffer:指向输入/输出缓冲区的指针。如果为 NULL,则 avio_alloc_context() 函数会自动分配一段缓冲区内存
      • buffer ⽤作FFmpeg输⼊时,由用户负责向 buffer 中填充数据,FFmpeg取⾛数据
      • buffer ⽤作FFmpeg输出时,由FFmpeg负责向 buffer 中填充数据,⽤户取⾛数据
    • buffer_size:缓冲区大小。每次读取的 buffer_size 会比这里的 buffer_size 小
      • notion image
        AVIOContext结构体内部有一个环形缓存区。这个环形缓存区在实际读写数据时会被使用。
        AVIOContext结构体中的环形缓存区可以通过成员变量buffer和buffer_size来访问。它的作用是在读写数据时,将数据暂时存储在缓冲区中,以提高读写效率。当缓冲区满了或者需要刷新缓冲区时,缓冲区中的数据会被写入到实际的存储设备中。因此,环形缓存区在数据读写过程中发挥了重要的作用。
    • write_flag:是缓冲区读写标志,读写的主语是指FFmpeg
      • write_flag 为1时, buffer ⽤于写,即作为FFmpeg输出
      • write_flag 为0时, buffer ⽤于读,即作为FFmpeg输⼊
    • opaque:不透明指针,是 read_packet / write_packet 的第⼀个参数,用于传递给读写操作的回调函数,一般用于传递用户自定义数据
    • read_packet:读操作回调函数指针
    • write_packet:写操作回调函数指针
    • seek:定位操作回调函数指针,需要⽀持seek时使⽤,可以类比fseek的机制
    • 注意:AVIOContext结构体是FFmpeg库中的一个重要数据结构,用于管理输入/输出缓冲区。在使用FFmpeg库进行音视频处理时,往往需要使用avio_alloc_context()函数来分配并初始化AVIOContext结构体,以便进行文件读写等操作
  • avcodec_find_decoder() :用于查找特定编解码器的解码器
    • 该函数的作用是根据编解码器的ID或名称,查找FFmpeg库中对应的解码器。它的参数通常是一个编解码器的ID或名称,函数会返回一个指向该解码器结构体的指针
  • av_read_frame() :用于读取媒体文件中下一个数据包(packet)。通常,使用该函数读取的数据包需要被解码(demux)才能被播放器播放。因此,读取数据包后需要调用其他函数,例如 avcodec_send_packet() 将数据包发送到解码器中进行解码。
    • 函数参数:
    • s:输入参数,指向已打开的媒体文件的 AVFormatContext 上下文
    • pkt:输出参数,用于存储读取到的数据包
    • 函数返回值:
    • 成功返回 0
    • 如果到达文件结尾或发生其他错误,返回一个负数

利用 AVIO 对 AAC 码流解码

总体流程

notion image

代码实现

 
  • 使用了uint8_t类型来定义io_buffer的指针变量
    • 是因为在FFmpeg多媒体框架中,经常需要处理二进制数据,例如音视频数据、图片数据等。这些数据通常是以字节为单位进行处理和传输的
    • uint8_t是一个定义在stdint.h标准头文件中的无符号8位整数类型,它的取值范围是0-255。使用uint8_t类型定义io_buffer的指针变量,可以确保我们处理的数据是以字节为单位的,而且数据中每个字节的取值范围是0-255,非常适合处理二进制数据
    • 在实际开发中,如果需要处理其他类型的数据,例如16位整数、32位整数、浮点数等,可以使用不同的类型定义指针变量,例如uint16_t、uint32_t、float等
  • opaque 中的数据是如何传递到 read_packet() 中的
    • avio_alloc_context() 中会调用 ffio_init_context()
      • notion image
    • ffio_init_context() 中会将函数参数的值都复制给 AVIOContext 的成员变量
      • notion image
    • 在使用FFmpeg库进行解码或编码操作时,通常会通过 avformat_open_input() avformat_alloc_context() 等函数创建一个 AVFormatContext 结构体,该结构体中包含了读取媒体数据所需的各种信息,如音视频流信息、文件格式信息等。在打开输入文件时,可以通过设置 AVFormatContext pb 字段为一个 AVIOContext 实例来指定数据读取的来源,而在创建 AVIOContext 实例时,可以通过设置 opaque 字段来传递不透明数据
    • 调用 read_packet() 时,FFmpeg 将传递 AVFormatContext 结构体中的 opaque 字段作为回调函数的参数
FFmpeg 音频基础之音频重采样FFmpeg 解封装 MP4 媒体文件