FFmpeg源码:file_read、file_write、file_seek函数分析

一、file_read函数

file_read函数定义在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的源文件libavformat/file.c中:

#define FFMIN(a,b) ((a) > (b) ? (b) : (a))

static int file_read(URLContext *h, unsigned char *buf, int size)
{
    FileContext *c = h->priv_data;
    int ret;
    size = FFMIN(size, c->blocksize);
    ret = read(c->fd, buf, size);
    if (ret == 0 && c->follow)
        return AVERROR(EAGAIN);
    if (ret == 0)
        return AVERROR_EOF;
    return (ret == -1) ? AVERROR(errno) : ret;
}

该函数的作用是:读取文件描述符为h->priv_data->fd的文件内容,存入形参buf指向的空间中。可以看到该函数内部调用C语言的read函数来读取文件内容。

形参h:输入型参数。 指向一个url(Uniform Resource Locator)上下文结构体。

形参buf:输出型参数。读上来的数据保存在缓冲区buf中。

形参size:输入型参数。要读取的字节数。

返回值:返回实际读取到的字节数。返回AVERROR_EOF表示调用该函数前已到达文件末尾,返回AVERROR(errno)表示出错。

二、file_write函数

file_write函数定义在源文件libavformat/file.c中:

#define FFMIN(a,b) ((a) > (b) ? (b) : (a))

static int file_write(URLContext *h, const unsigned char *buf, int size)
{
    FileContext *c = h->priv_data;
    int ret;
    size = FFMIN(size, c->blocksize);
    ret = write(c->fd, buf, size);
    return (ret == -1) ? AVERROR(errno) : ret;
}

该函数的作用是:将数据写入文件描述符为h->priv_data->fd的文件内。可以看到该函数内部调用了C语言的write函数来将数据写入文件。

形参h:输入型参数。 指向一个url(Uniform Resource Locator)上下文结构体。

形参buf:输入型参数。指向“存放需要写入到文件或网络流中的数据的缓冲区”。

形参size:输入型参数。要写入文件的字节数。

返回值:返回一个非负数表示写入成功,此时返回实际写入文件的字节数;返回AVERROR(errno)表示出错。

三、file_seek函数

(一)file_seek函数的定义

file_seek函数定义在源文件libavformat/file.c中:

/* XXX: use llseek */
static int64_t file_seek(URLContext *h, int64_t pos, int whence)
{
    FileContext *c = h->priv_data;
    int64_t ret;

    if (whence == AVSEEK_SIZE) {
        struct stat st;
        ret = fstat(c->fd, &st);
        return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 : st.st_size);
    }

    ret = lseek(c->fd, pos, whence);

    return ret < 0 ? AVERROR(errno) : ret;
}

该函数的作用是:

情况1,whence的值等于AVSEEK_SIZE时, 返回文件描述符为h->priv_data->fd的文件的大小但不改变读写位置。

情况2,whence的值不等于AVSEEK_SIZE时,改变读写一个文件时读写指针位置。每一个已打开的文件都有一个读写位置,当打开文件时通常其读写位置是指向文件开头,若是以附加的方式打开文件(如O_APPEND),则读写位置会指向文件尾。当read()或write()时,读写位置会随之增加,file_seek函数中使用了lseek()函数来控制该文件的读写位置。

形参h:输入型参数。 指向一个url(Uniform Resource Locator)上下文结构体。

形参pos:输入型参数。仅当whence的值不等于AVSEEK_SIZE时有意义,为偏移量,即每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。

形参whence:输入型参数。whence为下列其中一种:

/**
 * ORing this as the "whence" parameter to a seek function causes it to
 * return the filesize without seeking anywhere. Supporting this is optional.
 * If it is not supported then the seek function will return <0.
 */
#define AVSEEK_SIZE 0x10000

/* The possibilities for the third argument to `fseek'.
   These values should not be changed.  */
#define SEEK_SET	0	/* Seek from beginning of file.  */
#define SEEK_CUR	1	/* Seek from current position.  */
#define SEEK_END	2	/* Seek from end of file.  */

AVSEEK_SIZE:表示不改变读写位置,仅获取文件大小。

SEEK_SET:将读写位置指向文件头后再增加offset个位移量。

SEEK_CUR:以目前的读写位置往后增加offset个位移量。

SEEK_END:将读写位置指向文件尾后再增加offset个位移量。

当whence值为SEEK_CUR或SEEK_END时,参数offet允许负值的出现。

返回值:

whence的值等于AVSEEK_SIZE时,返回文件描述符为h->priv_data->fd的文件的大小,返回AVERROR(errno)表示出错;

whence的值不等于AVSEEK_SIZE时,返回非负数为目前的读写位置,也就是距离文件开头多少个字节,返回AVERROR(errno)表示出错。

(二)file_seek函数的用法示例

file_seek(h,0,AVSEEK_SIZE):不改变读写位置,返回文件描述符为h->priv_data->fd的文件的大小;

file_seek(h,0,SEEK_SET):将读写位置移到文件描述符为h->priv_data->fd的文件的开头,此时返回0;

file_seek(h,0,SEEK_END):将读写位置移到文件尾,此时返回文件描述符为h->priv_data->fd的文件的大小;

file_seek(h,0,SEEK_CUR):取得目前文件位置。此时返回当前读写位置距离文件开头多少个字节;

四、参考

lseek 360百科

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值