FFMPEG中AVIO读函数

读函数的基本单位是每次读取一个字节

FFMPEG版本3.2release,文件位于libavformat/aviobuf.c函数

读一个字节函数 avio_r8()

int avio_r8(AVIOContext *s)
{
    if (s->buf_ptr >= s->buf_end)
        fill_buffer(s);
    if (s->buf_ptr < s->buf_end)
        return *s->buf_ptr++;
    return 0;
}

 

读两个字节函数avio_rl16()和avio_rb16()

avio_rl16()

unsigned int avio_rl16(AVIOContext *s)
{
    unsigned int val;
    val = avio_r8(s);
    val |= avio_r8(s) << 8;
    return val;
}

avio_rb16()

unsigned int avio_rb16(AVIOContext *s)
{
    unsigned int val;
    val = avio_r8(s) << 8;
    val |= avio_r8(s);
    return val;
}

函数avio_rl16()和avio_rb16()内容相同ui

 

读三个字节函数avio_rl24()和avio_rb24()

avio_rl24()

unsigned int avio_rl24(AVIOContext *s)
{
    unsigned int val;
    val = avio_rl16(s);
    val |= avio_r8(s) << 16;
    return val;
}

avio_rb24()

unsigned int avio_rb24(AVIOContext *s)
{
    unsigned int val;
    val = avio_rb16(s) << 8;
    val |= avio_r8(s);
    return val;
}

函数avio_rl24()和avio_rb24()内容相同spa

读四字节函数avio_rl32()和avio_rb32()

avio_rl32()

unsigned int avio_rl32(AVIOContext *s)
{
    unsigned int val;
    val = avio_rl16(s);
    val |= avio_rl16(s) << 16;
    return val;
}

avio_rb32()

unsigned int avio_rb32(AVIOContext *s)
{
    unsigned int val;
    val = avio_rb16(s) << 16;
    val |= avio_rb16(s);
    return val;
}

函数avio_rl32()和avio_rb32()内容相同code

读八字节函数avio_rl64()

uint64_t avio_rl64(AVIOContext *s)
{
    uint64_t val;
    val = (uint64_t)avio_rl32(s);
    val |= (uint64_t)avio_rl32(s) << 32;
    return val;
}

 

函数avio_read()读size大小的数据到buf

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 || s->write_flag) {
            if((s->direct || size > s->buffer_size) && !s->update_checksum) {
                // bypass the buffer and read data directly into buf
                if(s->read_packet)
                    len = s->read_packet(s->opaque, buf, size);

                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;
                    break;
                } else {
                    s->pos += len;
                    s->bytes_read += len;
                    size -= len;
                    buf += len;
                    // reset the buffer
                    s->buf_ptr = s->buffer;
                    s->buf_end = s->buffer/* + len*/;
                }
            } else {
                fill_buffer(s);
                len = s->buf_end - s->buf_ptr;
                if (len == 0)
                    break;
            }
        } else {
            memcpy(buf, s->buf_ptr, len);
            buf += len;
            s->buf_ptr += len;
            size -= len;
        }
    }
    if (size1 == size) {
        if (s->error)      return s->error;
        if (avio_feof(s))  return AVERROR_EOF;
    }
    return size1 - size;
}

 

avio_read()函数执行流程:

以首次调用av_probe_input_buffer2()函数为例,avio_read(pb, buf + buf_offset,probe_size - buf_offset);buf的大小为2048+32,buf_offset大小为0,probe_size大小为2048.orm

执行函数fill_buffer()

由于初始化后,s->buf_end 和 s->buf_ptr相等,size为2048,因此len值为0,又由于s->direct和s->update_checksum值都为0,因此执行函数fill_buffer()。经过函数fill_buffer(),将数据复制到AVIOContext *buffer中,并获得len的值为s->buf_end - s->buf_ptr.input

执行函数memcpy()

下一次while循环,len的大小为s->buf_end - s->buf_ptr和2048取最小值,并执行memcpy,将数据复制到buf。it

反复执行,直到读取2048个字节的内容为止,则跳出循环,io

相关文章
相关标签/搜索