当前位置: 首页 > news >正文

FFmpeg源码:avio_r8、avio_rl16、avio_rl24、avio_rl32、avio_rl64函数分析

一、引言

AVIOContext是FFmpeg(本文演示用的FFmpeg源码版本为5.0.3)中的字节流上下文结构体,用来管理输入输出数据。打开一个媒体文件的时候,需要先把数据从硬盘读到缓冲区,然后会用到AVIOContext中的如下成员:

typedef struct AVIOContext {
//.../** The following shows the relationship between buffer, buf_ptr,* buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing* (since AVIOContext is used for both):************************************************************************************                                   READING************************************************************************************                            |              buffer_size              |*                            |---------------------------------------|*                            |                                       |**                         buffer          buf_ptr       buf_end*                            +---------------+-----------------------+*                            |/ / / / / / / /|/ / / / / / /|         |*  read buffer:              |/ / consumed / | to be read /|         |*                            |/ / / / / / / /|/ / / / / / /|         |*                            +---------------+-----------------------+**                                                         pos*              +-------------------------------------------+-----------------+*  input file: |                                           |                 |*              +-------------------------------------------+-----------------+*************************************************************************************                                   WRITING************************************************************************************                             |          buffer_size                 |*                             |--------------------------------------|*                             |                                      |**                                                buf_ptr_max*                          buffer                 (buf_ptr)       buf_end*                             +-----------------------+--------------+*                             |/ / / / / / / / / / / /|              |*  write buffer:              | / / to be flushed / / |              |*                             |/ / / / / / / / / / / /|              |*                             +-----------------------+--------------+*                               buf_ptr can be in this*                               due to a backward seek**                            pos*               +-------------+----------------------------------------------+*  output file: |             |                                              |*               +-------------+----------------------------------------------+**/unsigned char *buffer;  /**< Start of the buffer. */int buffer_size;        /**< Maximum buffer size */unsigned char *buf_ptr; /**< Current position in the buffer */unsigned char *buf_end; /**< End of the data, may be less thanbuffer+buffer_size if the read function returnedless data than requested, e.g. for streams whereno more data has been received yet. */
//...int64_t pos;            /**< position in the file of the current buffer */
//...
} AVIOContext;

从输入缓冲区读取数据的时候,

成员变量buffer:恒指向输入缓冲区的开头。

成员变量buffer_size:成员buffer指向的缓冲区的大小,单位为字节。

成员变量buf_ptr:指向输入缓冲区中当前读取到的位置。

成员变量buf_end:恒指向输入缓冲区的末尾。

简单来讲:

     *                                   READING************************************************************************************                            |              buffer_size              |*                            |---------------------------------------|*                            |                                       |**                         buffer          buf_ptr       buf_end*                            +---------------+-----------------------+*                            |/ / / / / / / /|/ / / / / / /|         |*  read buffer:              |/ / consumed / | to be read /|         |*                            |/ / / / / / / /|/ / / / / / /|         |*                            +---------------+-----------------------+

FFmpeg源码中通过下面函数读取AVIOContext结构体中成员变量buffer指向的输入缓冲区的数据。这些函数都声明在FFmpeg源码的头文件libavformat/avio.h中:

/*** @name Functions for reading from AVIOContext* @{** @note return 0 if EOF, so you cannot use it if EOF handling is*       necessary*/
int          avio_r8  (AVIOContext *s);
unsigned int avio_rl16(AVIOContext *s);
unsigned int avio_rl24(AVIOContext *s);
unsigned int avio_rl32(AVIOContext *s);
uint64_t     avio_rl64(AVIOContext *s);
unsigned int avio_rb16(AVIOContext *s);
unsigned int avio_rb24(AVIOContext *s);
unsigned int avio_rb32(AVIOContext *s);
uint64_t     avio_rb64(AVIOContext *s);

二、avio_r8函数的定义

avio_r8函数定义在FFmpeg源码的源文件libavformat/aviobuf.c中:


/* XXX: put an inline version */
int avio_r8(AVIOContext *s)
{if (s->buf_ptr >= s->buf_end)fill_buffer(s);if (s->buf_ptr < s->buf_end)return *s->buf_ptr++;return 0;
}

该函数作用是:如果还没有读取到输入缓冲区的结尾,返回读取到的该输入缓冲区中的一个字节数据,也就是返回s->buf_ptr指向的一个字节数据,然后让s->buf_ptr指向下一个字节数据。如果已经读取到输入缓冲区的末尾,返回0。注意:读取到缓冲区的结尾时,该函数返回0,所以不能同时用它来读取ASCII值为0的字节并且判断是否读到了结尾,否则会冲突。也就是说avio_r8函数要么只能读取字符串但可以判断是否到了结尾,要么能读取二进制数据但不能判断是否到了结尾。一般来讲选择后者的用法,即用它读取二进制数据(包含ASCII值为0的数据)但不判断是否到了结尾。

三、avio_rl16函数的定义

avio_rl16函数定义在FFmpeg源码的源文件libavformat/aviobuf.c中:

unsigned int avio_rl16(AVIOContext *s)
{unsigned int val;val = avio_r8(s);val |= avio_r8(s) << 8;return val;
}

该函数作用是:如果还没有读取到输入缓冲区的结尾,返回按照小端模式读取到的该输入缓冲区中的二个字节数据,然后让s->buf_ptr指向下下个字节的数据。如果已经读取到输入缓冲区的末尾,返回0。注意:该函数跟avio_r8函数一样,一般用它来读取二进制数据(包含ASCII值为0的数据)但不判断是否到了结尾。

四、其它相关函数

同理:

avio_rl24函数:如果还没有读取到输入缓冲区的结尾,返回按照小端模式读取到的该输入缓冲区中的三个字节数据,然后让s->buf_ptr的值+3。如果已经读取到输入缓冲区的末尾,返回0。

avio_rl32函数:如果还没有读取到输入缓冲区的结尾,返回按照小端模式读取到的该输入缓冲区中的四个字节数据,然后让s->buf_ptr的值+4。如果已经读取到输入缓冲区的末尾,返回0。

avio_rl64函数:如果还没有读取到输入缓冲区的结尾,返回按照小端模式读取到的该输入缓冲区中的八个字节数据,然后让s->buf_ptr的值+8。如果已经读取到输入缓冲区的末尾,返回0。

avio_rb16函数:如果还没有读取到输入缓冲区的结尾,返回按照大端模式读取到的该输入缓冲区中的二个字节数据,然后让s->buf_ptr的值+2。如果已经读取到输入缓冲区的末尾,返回0。

avio_rb24函数:如果还没有读取到输入缓冲区的结尾,返回按照大端模式读取到的该输入缓冲区中的三个字节数据,然后让s->buf_ptr的值+3。如果已经读取到输入缓冲区的末尾,返回0。

avio_rb32函数:如果还没有读取到输入缓冲区的结尾,返回按照大端模式读取到的该输入缓冲区中的四个字节数据,然后让s->buf_ptr的值+4。如果已经读取到输入缓冲区的末尾,返回0。

avio_rb64函数:如果还没有读取到输入缓冲区的结尾,返回按照大端模式读取到的该输入缓冲区中的八个字节数据,然后让s->buf_ptr的值+8。如果已经读取到输入缓冲区的末尾,返回0。

所有函数跟avio_r8函数一样,一般用它们来读取二进制数据(包含ASCII值为0的数据)但不判断是否到了结尾。

http://www.lryc.cn/news/410038.html

相关文章:

  • 如何使用 API 查看极狐GitLab 镜像仓库中的镜像?
  • 软件-vscode-plantUML-IDEA
  • ES6语法详解,面试必会,通俗易懂版
  • CTFshow--Web--代码审计
  • Java语言程序设计——篇十(1)
  • Qt对比MFC优势
  • RuntimeError: No CUDA GPUs are available
  • URL参数中携带中文?分享 1 段优质 JS 代码片段!
  • sass的使用
  • 【足球走地软件】走地数据分析预测【大模型篇】走地预测软件实战分享
  • 现在有什么赛道可以干到退休?
  • c程序杂谈系列(职责链模式与if_else)
  • 前端开发技术之CSS(层叠样式表)
  • go语言day20 使用gin框架获取参数 使用自定义的logger记录日志
  • DHCP笔记
  • TCP为什么需要四次挥手?
  • MySQL 索引相关基本概念
  • Neutralinojs教程项目实战初体验(踩坑指南),干翻 electron
  • 【轻松拿捏】Java-List、Set、Map 之间的区别是什么?
  • 用户史订单查询业务
  • 第8节课:CSS布局与样式——掌握盒模型与定位的艺术
  • electron 主进程和渲染进程
  • redis的高可用及性能管理和雪崩
  • php基础语法
  • js抓取短信验证码发送
  • 视频怎么加密?常见的四种视频加密方法和软件
  • 聚焦全局应用可用性的提升策略,详解GLSB是什么
  • 无水印下载视频2——基于tkinter完成头条视频的下载
  • Java学习Day17:基础篇7
  • Vue3 Pinia的创建与使用代替Vuex 全局数据共享 同步异步