=================================================================
AVIOContext结构体和其相关的函数分析:
FFmpeg源码:avio_r8、avio_rl16、avio_rl24、avio_rl32、avio_rl64函数分析
FFmpeg源码:read_packet_wrapper、fill_buffer函数分析
FFmpeg源码:ffurl_seek2、ffurl_seek、avio_size函数分析
FFmpeg源码:avio_read_partial函数分析
FFmpeg源码:ffio_read_indirect函数分析
=================================================================
一、ffio_read_indirect函数的声明
ffio_read_indirect函数声明在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavformat/avio_internal.h.h中:
cpp
/**
* Read size bytes from AVIOContext, returning a pointer.
* Note that the data pointed at by the returned pointer is only
* valid until the next call that references the same IO context.
* @param s IO context
* @param buf pointer to buffer into which to assemble the requested
* data if it is not available in contiguous addresses in the
* underlying buffer
* @param size number of bytes requested
* @param data address at which to store pointer: this will be a
* a direct pointer into the underlying buffer if the requested
* number of bytes are available at contiguous addresses, otherwise
* will be a copy of buf
* @return number of bytes read or AVERROR
*/
int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data);
该函数的作用是:
情况一:如果AVIOContext输入缓冲区中还未被读取的数据量(s->buf_end - s->buf_ptr)不小于计划要读取的字节数(size),并且该媒体文件被打开是不是为了写入的(!s->write_flag为真),让"*data"指向"输入缓冲区中当前读取到的位置(s->buf_ptr)",然后让s->buf_ptr指向原来的位置之后的size个字节的位置。也就是说,如果AVIOContext输入缓冲区中的数据足够,直接从输入缓冲区中读取数据。
情况二:如果不满足"情况一"的条件(AVIOContext输入缓冲区中的数据不足),首先尝试从输入缓冲区中读取size个字节数据,如果输入缓冲区中没有数据或者数据已被读完或者读完后还不够size个字节,通过文件描述符去读取本地媒体文件中的数据或者通过socket接收网络流中的数据,直到读取到总共size个字节为止(除非出错)。将读取到的数据保存到形参buf指向的缓冲区中,让"*data"指向buf。
形参s:既是输入型参数也是输出型参数。指向一个AVIOContext(字节流上下文结构体)变量。执行ffio_read_indirect函数后,s->buf_ptr等成员会发生相应变化。
形参buf:输出型参数。仅当符合上述"情况二"的条件时有意义,保存读上来的数据的缓冲区。
形参size:输入型参数。要读取的字节数。
形参data:输出型参数。"情况一"和"情况二"时皆有意义,"*data"指向保存读上来的数据的缓冲区。
返回值:返回一个非负数表示成功,此时返回实际读取到的字节数;返回一个负数表示出错。
二、ffio_read_indirect函数的定义
ffio_read_indirect函数定义在源文件libavformat/aviobuf.c中:
cpp
int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data)
{
if (s->buf_end - s->buf_ptr >= size && !s->write_flag) {
*data = s->buf_ptr;
s->buf_ptr += size;
return size;
} else {
*data = buf;
return avio_read(s, buf, size);
}
}
可以看到该函数内部调用了avio_read函数,可以看作是对avio_read函数的封装。