博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FFMPEG函数fill_buffer()
阅读量:6938 次
发布时间:2019-06-27

本文共 5322 字,大约阅读时间需要 17 分钟。

hot3.png

FFMPEG 版本3.2 release。

 

函数fill_buffer(AVIOContext *s)

static void fill_buffer(AVIOContext *s){    int max_buffer_size = s->max_packet_size ?                          s->max_packet_size : IO_BUFFER_SIZE;    uint8_t *dst        = s->buf_end - s->buffer + max_buffer_size < s->buffer_size ?                          s->buf_end : s->buffer;    int len             = s->buffer_size - (dst - s->buffer);    /* can't fill the buffer without read_packet, just set EOF if appropriate */    if (!s->read_packet && s->buf_ptr >= s->buf_end)        s->eof_reached = 1;    /* no need to do anything if EOF already reached */    if (s->eof_reached)        return;    if (s->update_checksum && dst == s->buffer) {        if (s->buf_end > s->checksum_ptr)            s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,                                             s->buf_end - s->checksum_ptr);        s->checksum_ptr = s->buffer;    }    /* make buffer smaller in case it ended up large after probing */    if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) {        if (dst == s->buffer) {            int ret = ffio_set_buf_size(s, s->orig_buffer_size);            if (ret < 0)                av_log(s, AV_LOG_WARNING, "Failed to decrease buffer size\n");            s->checksum_ptr = dst = s->buffer;        }        av_assert0(len >= s->orig_buffer_size);        len = s->orig_buffer_size;    }    if (s->read_packet)        len = s->read_packet(s->opaque, dst, len);    else        len = 0;    if (len <= 0) {        /* do not modify buffer if EOF reached so that a seek back can           be done without rereading data */        s->eof_reached = 1;        if (len < 0)            s->error = len;    } else {        s->pos += len;        s->buf_ptr = dst;        s->buf_end = dst + len;        s->bytes_read += len;    }}

 

函数fill_buffer()的作用

从file或者网络流等读数据到AVIOContext *s的buf。

 

如果先调用函数ffio_fdopen(),再调用函数fill_buffer()为例,并且假设read_packet()指向函数io_read_packet(),则执行过程如下:

 

执行函数s->read_packet(s->opaque, dst, len)

该函数的作用为通过指针s->opaque指向的结构体中的变量,获取数据流并复制到dst。

例如:read_packet()指向函数io_read_packet().

函数io_read_packet()位于libavformat/aviobuf.c。

函数ffurl_read()位于libavformat/avio.c

函数retry_transfer_wrapper()位于libavformat/avio.c

如果输入的是文件,例如test.flv,则函数transfer_func(h, buf + len, size - len)指向file_read()。

static int io_read_packet(void *opaque, uint8_t *buf, int buf_size){    AVIOInternal *internal = opaque;    return ffurl_read(internal->h, buf, buf_size);}int ffurl_read(URLContext *h, unsigned char *buf, int size){    if (!(h->flags & AVIO_FLAG_READ))        return AVERROR(EIO);    return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read);}static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,                                         int size, int size_min,                                         int (*transfer_func)(URLContext *h,                                                              uint8_t *buf,                                                              int size)){    int ret, len;    int fast_retries = 5;    int64_t wait_since = 0;    len = 0;    while (len < size_min) {        if (ff_check_interrupt(&h->interrupt_callback))            return AVERROR_EXIT;        ret = transfer_func(h, buf + len, size - len);        if (ret == AVERROR(EINTR))            continue;        if (h->flags & AVIO_FLAG_NONBLOCK)            return ret;        if (ret == AVERROR(EAGAIN)) {            ret = 0;            if (fast_retries) {                fast_retries--;            } else {                if (h->rw_timeout) {                    if (!wait_since)                        wait_since = av_gettime_relative();                    else if (av_gettime_relative() > wait_since + h->rw_timeout)                        return AVERROR(EIO);                }                av_usleep(1000);            }        } else if (ret < 1)            return (ret < 0 && ret != AVERROR_EOF) ? ret : len;        if (ret) {            fast_retries = FFMAX(fast_retries, 2);            wait_since = 0;        }        len += ret;    }    return len;}

 

输入文件transfer_func()回调函数file_read()

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);    return (ret == -1) ? AVERROR(errno) : ret;}

输入是rtmp协议流transfer_func()回调函数rtmp_read()

libavformat/rtmpproto.c

static int rtmp_read(URLContext *s, uint8_t *buf, int size){    RTMPContext *rt = s->priv_data;    int orig_size = size;    int ret;    while (size > 0) {        int data_left = rt->flv_size - rt->flv_off;        if (data_left >= size) {            memcpy(buf, rt->flv_data + rt->flv_off, size);            rt->flv_off += size;            return orig_size;        }        if (data_left > 0) {            memcpy(buf, rt->flv_data + rt->flv_off, data_left);            buf  += data_left;            size -= data_left;            rt->flv_off = rt->flv_size;            return data_left;        }        if ((ret = get_packet(s, 0)) < 0)           return ret;    }    return orig_size;}

 

更新AVIOContext *s有关buf的指针

从数据流中获取数据后,更新AVIOContext *s中的指针,如     s->pos,s->buf_ptr,s->buf_end = dst,s->bytes_read 。

转载于:https://my.oschina.net/u/2326611/blog/805347

你可能感兴趣的文章
生成动态验证码的jsp
查看>>
SJCL:斯坦福大学JS加密库
查看>>
SharpWebMail介绍和安装(转)
查看>>
装好Centos7后提示Initial setup of CentOS Linux 7 (core)
查看>>
mysql + Fluently NHibernate + WebAPI + Autofac
查看>>
返回顶部及去底部
查看>>
Unity镜子效果的实现(无需镜子Shader)
查看>>
删除一个数的K位使原数变得最小
查看>>
牛客小白月赛6 水题 求n!在m进制下末尾0的个数 数论
查看>>
ACM_贪心法_queue_Fence Repair
查看>>
各大公司Java面试题超详细总结
查看>>
函数练习
查看>>
python学习第一天 -----2019年4月15日
查看>>
如何用node命令和webpack命令传递参数 转载
查看>>
51nod 1105:第K大的数
查看>>
POJ 3368 Frequent values 线段树区间合并
查看>>
Ubuntu Linux 下优化 swap 交换分区及调整swap大小
查看>>
“undefined reference to JNI_GetCreatedJavaVM”和“File format not recognized”错误原因分析...
查看>>
Spring定时任务的配置
查看>>
了解清除警告
查看>>