缓冲IO --- AVIOContext

1 AVIOContext
URLContext它是一个不带缓冲的IO 结构体,读取实际是调用底层的IO 接口, 只仅仅统一不同文件IO API 而已。 AVIOContext 是一个在URLContext 基础上,带缓冲的结构体, 这样做的好处是加快IO 效率, 减少IO 次数。假设网络数据,只仅仅读取一个字节,也要发起一次网络请求的话难免会降低效率。 假设先预先申请一块buff ,当请求的数据,小于buff 缓存的数据,那么直接在buff 中memcpy 就好了, 这样会极大的提高处理性能。下面我们将介绍它是如何实现缓冲功能的。

2 avio_open()
avio_open(AVIOContext **s, const char *filename, int flags) ,它初始化AVIOContext 一些变量, open 底层文件,申请缓冲buff 的大小。当我们调用avio_open()函数时,它将call 到ffio_fdopen() , 这函数完成缓冲buff 的申请。

int ffio_fdopen(AVIOContext **s, URLContext *h)
{
.........
    max_packet_size = h->max_packet_size;
    if (max_packet_size) {
        buffer_size = max_packet_size; /* 如果底层IO 有指定size , 就alloc 底层指定的大小的buff */
    } else {
        buffer_size = IO_BUFFER_SIZE;//没有指定的话, alloc 默认size 32768
    }
    buffer = av_malloc(buffer_size); // alloc 缓冲buff
	.......... 
}

3 avio_read()
如下图,乃是AVIOContext 自带的注解,
在这里插入图片描述
typedef struct AVIOContext {

unsigned char *buffer; /**buffer 的起始位置 /
int buffer_size; /
alloc缓冲buffer 的size */
unsigned char buf_ptr; / 当前读到的位置 /
unsigned char buf_end; / 缓存数据的尾端
/
int64_t pos; // 底层IO 函数 真正读取到的位置

}
下面我们在来分析下avio_read() 函数实现

int avio_read(AVIOContext *s, unsigned char *buf, int size)
{
    int len, size1;

    size1 = size;
    while (size > 0) {
        len = FFMIN(s->buf_end - s->buf_ptr, size);
        if (len == 0 ) {
            if((s->direct || size > s->buffer_size) && !s->update_checksum) {
                len = read_packet_wrapper(s, buf, size);//len 值等于0, 请求read size 大于buff size 时,向底层发起IO 请求,一次性读完申请的size
            } else {
                fill_buffer(s);//len 值等于0,请求read size 小于buff size 时,将buff 读满
                len = s->buf_end - s->buf_ptr;//修改此时的数据长度
                if (len == 0)
                    break;
            }
        } else {
            memcpy(buf, s->buf_ptr, len);//当size 不为0 时, 先从缓冲buff 里面读取数据
            buf += len;
            s->buf_ptr += len;
            size -= len;
        }
    }
	.........
    return size1 - size;
}

4 avio_write()
这是带缓冲的写函数,实现也比较简单,当写到缓冲buff 的数据满了时,就flush buffer。 将数据通过底层IO 函数写到文件中。

void avio_write(AVIOContext *s, const unsigned char *buf, int size)
{
..........
    while (size > 0) {
        int len = FFMIN(s->buf_end - s->buf_ptr, size);
        memcpy(s->buf_ptr, buf, len);  //先将数据写到缓冲buff
        s->buf_ptr += len;

        if (s->buf_ptr >= s->buf_end)  //当缓冲buff 满了时, 通过底层IO 函数flush 到文件中去
            flush_buffer(s);

        buf += len;
        size -= len;
    }
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值