FFmpeg源码:avio_feof函数分析
=================================================================
AVIOContext结构体和其相关的函数分析:
FFmpeg源码:avio_r8、avio_rl16、avio_rl24、avio_rl32、avio_rl64函数分析
FFmpeg源码:read_packet_wrapper、fill_buffer函数分析
FFmpeg源码:avio_read函数分析
FFmpeg源码:avio_seek函数分析
FFmpeg源码:avio_skip函数分析
FFmpeg源码:avio_tell函数分析
FFmpeg源码:ffurl_seek2、ffurl_seek、avio_size函数分析
FFmpeg源码:avio_feof函数分析
=================================================================
一、avio_feof函数的声明
avio_feof函数声明在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavformat/avio.h中:
/**
* Similar to feof() but also returns nonzero on read errors.
* @return non zero if and only if at end of file or a read error happened when reading.
*/
int avio_feof(AVIOContext *s);
该函数可以看做是AVIOContext版本的feof函数,用来判断文件是否结束。准确地来讲,是用来判断是否是因为读取到文件末尾而结束的。
形参s:既是输入型参数也是输出型参数。指向一个AVIOContext(字节流上下文结构体)变量。关于AVIOContext结构体可以参考:《FFmpeg源码:avio_r8、avio_rl16、avio_rl24、avio_rl32、avio_rl64函数分析》。
返回值:返回0表示形参s为NULL或者文件还未结束;返回1表示读取到文件末尾而结束。
二、avio_feof函数的定义
avio_feof函数定义在源文件libavformat/aviobuf.c中:
int avio_feof(AVIOContext *s)
{
if(!s)
return 0;
if(s->eof_reached){
s->eof_reached=0;
fill_buffer(s);
}
return s->eof_reached;
}
三、avio_feof函数的内部实现分析
AVIOContext结构体内部有一个成员变量eof_reached用来标记文件是否已读到结尾。从《FFmpeg源码:read_packet_wrapper、fill_buffer函数分析》和《FFmpeg源码:avio_read函数分析》可以知道,执行fill_buffer和avio_read函数时,如果这两个函数发现已到达文件末尾,它们会把s->eof_reached置1:
typedef struct AVIOContext {
//...
int eof_reached; /**< true if was unable to read due to error or eof */
//...
}
avio_feof函数中,首先判断形参s是否为NULL。如果为NULL,直接返回0:
if(!s)
return 0;
avio_feof函数内部如果判断出表达式s->eof_reached为真,表示已读到文件结尾。这时先设置s->eof_reached为0,执行fill_buffer函数通过文件描述符去读取本地媒体文件中的数据,或者通过socket接收网络流中的数据。如果fill_buffer函数内部还是发现已读到文件结尾,fill_buffer会重新把s->eof_reached置1。所以avio_feof函数里面的fill_buffer函数是用来判断是否真的已读到文件结尾:
if(s->eof_reached){
s->eof_reached=0;
fill_buffer(s);
}
返回s->eof_reached的值:
return s->eof_reached;