mirror of https://github.com/FFmpeg/FFmpeg.git
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.
415 lines
9.4 KiB
415 lines
9.4 KiB
/* |
|
* Buffered I/O for ffmpeg system |
|
* Copyright (c) 2000,2001 Gerard Lantau |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; either version 2 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
*/ |
|
#include "avformat.h" |
|
|
|
#define IO_BUFFER_SIZE 32768 |
|
|
|
int init_put_byte(ByteIOContext *s, |
|
unsigned char *buffer, |
|
int buffer_size, |
|
int write_flag, |
|
void *opaque, |
|
int (*read_packet)(void *opaque, UINT8 *buf, int buf_size), |
|
void (*write_packet)(void *opaque, UINT8 *buf, int buf_size), |
|
int (*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_packet = write_packet; |
|
s->read_packet = read_packet; |
|
s->seek = seek; |
|
s->pos = 0; |
|
s->must_flush = 0; |
|
s->eof_reached = 0; |
|
s->is_streamed = 0; |
|
s->packet_size = 1; |
|
return 0; |
|
} |
|
|
|
|
|
static void flush_buffer(ByteIOContext *s) |
|
{ |
|
if (s->buf_ptr > s->buffer) { |
|
if (s->write_packet) |
|
s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); |
|
s->pos += s->buf_ptr - s->buffer; |
|
} |
|
s->buf_ptr = s->buffer; |
|
} |
|
|
|
void put_byte(ByteIOContext *s, int b) |
|
{ |
|
*(s->buf_ptr)++ = b; |
|
if (s->buf_ptr >= s->buf_end) |
|
flush_buffer(s); |
|
} |
|
|
|
void put_buffer(ByteIOContext *s, unsigned char *buf, int size) |
|
{ |
|
int len; |
|
|
|
while (size > 0) { |
|
len = (s->buf_end - s->buf_ptr); |
|
if (len > size) |
|
len = size; |
|
memcpy(s->buf_ptr, buf, len); |
|
s->buf_ptr += len; |
|
|
|
if (s->buf_ptr >= s->buf_end) |
|
flush_buffer(s); |
|
|
|
buf += len; |
|
size -= len; |
|
} |
|
} |
|
|
|
void put_flush_packet(ByteIOContext *s) |
|
{ |
|
flush_buffer(s); |
|
s->must_flush = 0; |
|
} |
|
|
|
offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence) |
|
{ |
|
offset_t offset1; |
|
|
|
if (whence != SEEK_CUR && whence != SEEK_SET) |
|
return -EINVAL; |
|
|
|
if (s->write_flag) { |
|
if (whence == SEEK_CUR) { |
|
offset1 = s->pos + (s->buf_ptr - s->buffer); |
|
if (offset == 0) |
|
return offset1; |
|
offset += offset1; |
|
} |
|
offset1 = offset - s->pos; |
|
if (!s->must_flush && |
|
offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) { |
|
/* can do the seek inside the buffer */ |
|
s->buf_ptr = s->buffer + offset1; |
|
} else { |
|
if (!s->seek) |
|
return -EPIPE; |
|
flush_buffer(s); |
|
s->must_flush = 1; |
|
s->buf_ptr = s->buffer; |
|
s->seek(s->opaque, offset, SEEK_SET); |
|
s->pos = offset; |
|
} |
|
} else { |
|
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)) { |
|
/* can do the seek inside the buffer */ |
|
s->buf_ptr = s->buffer + offset1; |
|
} else { |
|
if (!s->seek) |
|
return -EPIPE; |
|
s->buf_ptr = s->buffer; |
|
s->buf_end = s->buffer; |
|
s->eof_reached = 0; |
|
s->seek(s->opaque, offset, SEEK_SET); |
|
s->pos = offset; |
|
} |
|
} |
|
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); |
|
} |
|
|
|
int url_feof(ByteIOContext *s) |
|
{ |
|
return s->eof_reached; |
|
} |
|
|
|
void put_le32(ByteIOContext *s, unsigned int val) |
|
{ |
|
put_byte(s, val); |
|
put_byte(s, val >> 8); |
|
put_byte(s, val >> 16); |
|
put_byte(s, val >> 24); |
|
} |
|
|
|
void put_be32(ByteIOContext *s, unsigned int val) |
|
{ |
|
put_byte(s, val >> 24); |
|
put_byte(s, val >> 16); |
|
put_byte(s, val >> 8); |
|
put_byte(s, val); |
|
} |
|
|
|
void put_le64(ByteIOContext *s, UINT64 val) |
|
{ |
|
put_le32(s, (UINT32)(val & 0xffffffff)); |
|
put_le32(s, (UINT32)(val >> 32)); |
|
} |
|
|
|
void put_be64(ByteIOContext *s, UINT64 val) |
|
{ |
|
put_be32(s, (UINT32)(val >> 32)); |
|
put_be32(s, (UINT32)(val & 0xffffffff)); |
|
} |
|
|
|
void put_le16(ByteIOContext *s, unsigned int val) |
|
{ |
|
put_byte(s, val); |
|
put_byte(s, val >> 8); |
|
} |
|
|
|
void put_be16(ByteIOContext *s, unsigned int val) |
|
{ |
|
put_byte(s, val >> 8); |
|
put_byte(s, val); |
|
} |
|
|
|
void put_tag(ByteIOContext *s, char *tag) |
|
{ |
|
while (*tag) { |
|
put_byte(s, *tag++); |
|
} |
|
} |
|
|
|
/* Input stream */ |
|
|
|
static void fill_buffer(ByteIOContext *s) |
|
{ |
|
int len; |
|
|
|
len = s->read_packet(s->opaque, s->buffer, s->buffer_size); |
|
s->pos += len; |
|
s->buf_ptr = s->buffer; |
|
s->buf_end = s->buffer + len; |
|
if (len == 0) { |
|
s->eof_reached = 1; |
|
} |
|
} |
|
|
|
int get_byte(ByteIOContext *s) |
|
{ |
|
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; |
|
} |
|
} |
|
|
|
int get_buffer(ByteIOContext *s, unsigned char *buf, int size) |
|
{ |
|
int len, size1; |
|
|
|
size1 = size; |
|
while (size > 0) { |
|
len = s->buf_end - s->buf_ptr; |
|
if (len > size) |
|
len = size; |
|
if (len == 0) { |
|
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; |
|
} |
|
|
|
unsigned int get_le16(ByteIOContext *s) |
|
{ |
|
unsigned int val; |
|
val = get_byte(s); |
|
val |= get_byte(s) << 8; |
|
return val; |
|
} |
|
|
|
unsigned int get_le32(ByteIOContext *s) |
|
{ |
|
unsigned int val; |
|
val = get_byte(s); |
|
val |= get_byte(s) << 8; |
|
val |= get_byte(s) << 16; |
|
val |= get_byte(s) << 24; |
|
return val; |
|
} |
|
|
|
UINT64 get_le64(ByteIOContext *s) |
|
{ |
|
UINT64 val; |
|
val = (UINT64)get_le32(s); |
|
val |= (UINT64)get_le32(s) << 32; |
|
return val; |
|
} |
|
|
|
unsigned int get_be16(ByteIOContext *s) |
|
{ |
|
unsigned int val; |
|
val = get_byte(s) << 8; |
|
val |= get_byte(s); |
|
return val; |
|
} |
|
|
|
unsigned int get_be32(ByteIOContext *s) |
|
{ |
|
unsigned int val; |
|
val = get_byte(s) << 24; |
|
val |= get_byte(s) << 16; |
|
val |= get_byte(s) << 8; |
|
val |= get_byte(s); |
|
return val; |
|
} |
|
|
|
UINT64 get_be64(ByteIOContext *s) |
|
{ |
|
UINT64 val; |
|
val = (UINT64)get_be32(s) << 32; |
|
val |= (UINT64)get_be32(s); |
|
return val; |
|
} |
|
|
|
/* link with avio functions */ |
|
|
|
void url_write_packet(void *opaque, UINT8 *buf, int buf_size) |
|
{ |
|
URLContext *h = opaque; |
|
url_write(h, buf, buf_size); |
|
} |
|
|
|
int url_read_packet(void *opaque, UINT8 *buf, int buf_size) |
|
{ |
|
URLContext *h = opaque; |
|
return url_read(h, buf, buf_size); |
|
} |
|
|
|
int url_seek_packet(void *opaque, INT64 offset, int whence) |
|
{ |
|
URLContext *h = opaque; |
|
url_seek(h, offset, whence); |
|
return 0; |
|
} |
|
|
|
int url_fdopen(ByteIOContext *s, URLContext *h) |
|
{ |
|
UINT8 *buffer; |
|
int buffer_size; |
|
|
|
buffer_size = (IO_BUFFER_SIZE / h->packet_size) * h->packet_size; |
|
buffer = av_malloc(buffer_size); |
|
if (!buffer) |
|
return -ENOMEM; |
|
|
|
if (init_put_byte(s, buffer, buffer_size, |
|
(h->flags & URL_WRONLY) != 0, h, |
|
url_read_packet, url_write_packet, url_seek_packet) < 0) { |
|
av_free(buffer); |
|
return -EIO; |
|
} |
|
s->is_streamed = h->is_streamed; |
|
s->packet_size = h->packet_size; |
|
return 0; |
|
} |
|
|
|
/* XXX: must be called before any I/O */ |
|
int url_setbufsize(ByteIOContext *s, int buf_size) |
|
{ |
|
UINT8 *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; |
|
} |
|
|
|
int url_fopen(ByteIOContext *s, const char *filename, int flags) |
|
{ |
|
URLContext *h; |
|
int err; |
|
|
|
err = url_open(&h, filename, flags); |
|
if (err < 0) |
|
return err; |
|
err = url_fdopen(s, h); |
|
if (err < 0) { |
|
url_close(h); |
|
return err; |
|
} |
|
return 0; |
|
} |
|
|
|
int url_fclose(ByteIOContext *s) |
|
{ |
|
URLContext *h = s->opaque; |
|
|
|
av_free(s->buffer); |
|
memset(s, 0, sizeof(ByteIOContext)); |
|
return url_close(h); |
|
} |
|
|
|
URLContext *url_fileno(ByteIOContext *s) |
|
{ |
|
return s->opaque; |
|
} |
|
|
|
/* buffer handling */ |
|
int url_open_buf(ByteIOContext *s, UINT8 *buf, int buf_size, int flags) |
|
{ |
|
return init_put_byte(s, buf, buf_size, |
|
(flags & URL_WRONLY) != 0, NULL, NULL, NULL, NULL); |
|
} |
|
|
|
/* return the written or read size */ |
|
int url_close_buf(ByteIOContext *s) |
|
{ |
|
return s->buf_ptr - s->buffer; |
|
}
|
|
|