You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
7.6 KiB

/*
** 有缓存的广义文件 ByteIOContext 相关的文件操作
** ByteIOContext和URLContext的不同在于,ByteIOContext是带缓存的,即ByteIOContext的操作都是基于缓存的而不是基于文件描述符
** 可以这样理解URLContext读取出来的数据交给ByteIOContext管理,因此URLContext在ByteIOContext的下面,是ByteIOContext的底层
*/
#include "../berrno.h"
#include "avformat.h"
#include "avio.h"
#include <stdarg.h>
/* 最大的缓存长度 */
#define IO_BUFFER_SIZE 32768
/*
** 初始化 ByteIOContext 结构
*/
int init_put_byte(ByteIOContext *s,
unsigned char *buffer,
int buffer_size,
int write_flag,
void *opaque,
int(*read_buf)(void *opaque, uint8_t *buf, int buf_size),
int(*write_buf)(void *opaque, uint8_t *buf, int buf_size),
offset_t(*seek)(void *opaque, offset_t offset, int whence))
{
s->buffer = buffer;
s->buffer_size = buffer_size;
s->buf_ptr = buffer;
s->write_flag = write_flag;
if (!s->write_flag)
s->buf_end = buffer;
else
s->buf_end = buffer + buffer_size;
s->opaque = opaque;
s->write_buf = write_buf;
s->read_buf = read_buf;
s->seek = seek;
s->pos = 0;
s->must_flush = 0;
s->eof_reached = 0;
s->error = 0;
s->max_packet_size = 0;
return 0;
}
/*
** 广义文件 ByteIOContext 的 seek 操作
*/
offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)
{
offset_t offset1;
if (whence != SEEK_CUR && whence != SEEK_SET)
return - EINVAL;
if (whence == SEEK_CUR)
{
offset1 = s->pos - (s->buf_end - s->buffer) + (s->buf_ptr - s->buffer);
if (offset == 0)
return offset1;
offset += offset1;
}
offset1 = offset - (s->pos - (s->buf_end - s->buffer));
if (offset1 >= 0 && offset1 <= (s->buf_end - s->buffer))
{
s->buf_ptr = s->buffer + offset1; // can do the seek inside the buffer
}
else
{
if (!s->seek)
return - EPIPE;
s->buf_ptr = s->buffer;
s->buf_end = s->buffer;
if (s->seek(s->opaque, offset, SEEK_SET) == (offset_t) - EPIPE)
return - EPIPE;
s->pos = offset;
}
s->eof_reached = 0;
return offset;
}
/* 跳转 */
void url_fskip(ByteIOContext *s, offset_t offset)
{
url_fseek(s, offset, SEEK_CUR);
}
/* 获取长度 */
offset_t url_ftell(ByteIOContext *s)
{
return url_fseek(s, 0, SEEK_CUR);
}
/* 文件大小 */
offset_t url_fsize(ByteIOContext *s)
{
offset_t size;
if (!s->seek)
return - EPIPE;
size = s->seek(s->opaque, - 1, SEEK_END) + 1;
s->seek(s->opaque, s->pos, SEEK_SET);
return size;
}
/* 是否到达文件尾 */
int url_feof(ByteIOContext *s)
{
return s->eof_reached;
}
/* 错误码 */
int url_ferror(ByteIOContext *s)
{
return s->error;
}
// Input stream
/* 填充buffer,也是一个读取文件的操作 */
static void fill_buffer(ByteIOContext *s)
{
int len;
if (s->eof_reached)
return ;
len = s->read_buf(s->opaque, s->buffer, s->buffer_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;
}
else
{
s->pos += len;
s->buf_ptr = s->buffer;
s->buf_end = s->buffer + len;
}
}
/* 读取一个字节 */
int get_byte(ByteIOContext *s) // NOTE: return 0 if EOF, so you cannot use it if EOF handling is necessary
{
if (s->buf_ptr < s->buf_end)
{
return *s->buf_ptr++;
}
else
{
// 读取数据
fill_buffer(s);
if (s->buf_ptr < s->buf_end)
return *s->buf_ptr++;
else
return 0;
}
}
/* 从广义文件 ByteIOContext 中以小端方式读取两个字节,实现代码充分复用 get_byte()函数 */
unsigned int get_le16(ByteIOContext *s)
{
unsigned int val;
val = get_byte(s);
val |= get_byte(s) << 8;
return val;
}
/* 从广义文件 ByteIOContext 中以小端方式读取四个字节,实现代码充分复用 get_le16()函数 */
unsigned int get_le32(ByteIOContext *s)
{
unsigned int val;
val = get_le16(s);
val |= get_le16(s) << 16;
return val;
}
#define url_write_buf NULL
/* 简单中转读操作函数 */
static int url_read_buf(void *opaque, uint8_t *buf, int buf_size)
{
URLContext *h = opaque;
return url_read(h, buf, buf_size);
}
/* 简单中转 seek 操作函数 */
static offset_t url_seek_buf(void *opaque, offset_t offset, int whence)
{
URLContext *h = opaque;
return url_seek(h, offset, whence);
}
/* 设置并分配广义文件 ByteIOContext 内部缓存的大小,更多的应用在修改内部缓存大小场合 */
int url_setbufsize(ByteIOContext *s, int buf_size) // must be called before any I/O
{
uint8_t *buffer;
buffer = av_malloc(buf_size);
if (!buffer)
return - ENOMEM;
av_free(s->buffer);
s->buffer = buffer;
s->buffer_size = buf_size;
s->buf_ptr = buffer;
if (!s->write_flag)
s->buf_end = buffer;
else
s->buf_end = buffer + buf_size;
return 0;
}
/* 打开广义文件 ByteIOContext */
int url_fopen(ByteIOContext *s, const char *filename, int flags)
{
URLContext *h;
uint8_t *buffer;
int buffer_size, max_packet_size;
int err;
err = url_open(&h, filename, flags);
if (err < 0)
return err;
max_packet_size = url_get_max_packet_size(h);
if (max_packet_size)
{
buffer_size = max_packet_size; // no need to bufferize more than one packet
}
else
{
buffer_size = IO_BUFFER_SIZE;
}
buffer = av_malloc(buffer_size);
if (!buffer)
{
url_close(h);
return - ENOMEM;
}
if (init_put_byte(s,
buffer,
buffer_size,
(h->flags & URL_WRONLY || h->flags & URL_RDWR),
h,
url_read_buf,
url_write_buf,
url_seek_buf) < 0)
{
url_close(h);
av_free(buffer);
return AVERROR_IO;
}
s->max_packet_size = max_packet_size;
return 0;
}
/* 关闭广义文件 ByteIOContext */
int url_fclose(ByteIOContext *s)
{
URLContext *h = s->opaque;
av_free(s->buffer);
memset(s, 0, sizeof(ByteIOContext));
return url_close(h);
}
/* 广义文件 ByteIOContext 读操作 */
int url_fread(ByteIOContext *s, unsigned char *buf, int size) // get_buffer
{
int len, size1;
size1 = size;
while (size > 0)
{
len = s->buf_end - s->buf_ptr;
if (len > size)
len = size;
if (len == 0)
{
if (size > s->buffer_size)
{
len = s->read_buf(s->opaque, buf, size);
if (len <= 0)
{
s->eof_reached = 1;
if (len < 0)
s->error = len;
break;
}
else
{
s->pos += len;
size -= len;
buf += len;
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;
}
}
return size1 - size;
}