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

相關文章
相關標籤/搜索