From a45605a1ba3126c4d8314886d90326a7ffe746ff Mon Sep 17 00:00:00 2001 From: Reimar Döffinger Date: Sun, 25 Mar 2012 11:58:55 +0200 Subject: Add AVIO_FLAG_DIRECT. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows avoiding the buffer when using avio read, write and seek functions. When using the ffmpeg executable -avioflags direct can be used to enable this mode for input files, but has no effect on output files. Signed-off-by: Reimar Döffinger --- libavformat/avformat.h | 2 ++ libavformat/avio.h | 15 +++++++++++++++ libavformat/aviobuf.c | 31 ++++++++++++++++++++++--------- libavformat/options_table.h | 2 ++ libavformat/utils.c | 2 +- tests/fate/demux.mak | 3 +++ 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 7c307a7db2..5a11fdcc9f 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1083,6 +1083,8 @@ typedef struct AVFormatContext { */ #define RAW_PACKET_BUFFER_SIZE 2500000 int raw_packet_buffer_remaining_size; + + int avio_flags; } AVFormatContext; typedef struct AVPacketList { diff --git a/libavformat/avio.h b/libavformat/avio.h index 95f9558c87..0e923fe443 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -121,6 +121,13 @@ typedef struct { * This field is internal to libavformat and access from outside is not allowed. */ int64_t maxsize; + + /** + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ + int direct; } AVIOContext; /* unbuffered I/O */ @@ -319,6 +326,14 @@ int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); */ #define AVIO_FLAG_NONBLOCK 8 +/** + * Use direct mode. + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ +#define AVIO_FLAG_DIRECT 0x8000 + /** * Create and initialize a AVIOContext for accessing the * resource indicated by url. diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index f6349d6009..2f57c55e5b 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -80,6 +80,7 @@ int ffio_init_context(AVIOContext *s, s->buffer_size = buffer_size; s->buf_ptr = buffer; s->opaque = opaque; + s->direct = 0; url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); s->write_packet = write_packet; s->read_packet = read_packet; @@ -117,20 +118,25 @@ AVIOContext *avio_alloc_context( return s; } +static void writeout(AVIOContext *s, const uint8_t *data, int len) +{ + if (s->write_packet && !s->error){ + int ret= s->write_packet(s->opaque, data, len); + if(ret < 0){ + s->error = ret; + } + } + s->pos += len; +} + static void flush_buffer(AVIOContext *s) { if (s->buf_ptr > s->buffer) { - if (s->write_packet && !s->error){ - int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); - if(ret < 0){ - s->error = ret; - } - } + writeout(s, s->buffer, s->buf_ptr - s->buffer); if(s->update_checksum){ s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); s->checksum_ptr= s->buffer; } - s->pos += s->buf_ptr - s->buffer; } s->buf_ptr = s->buffer; } @@ -158,6 +164,11 @@ void ffio_fill(AVIOContext *s, int b, int count) void avio_write(AVIOContext *s, const unsigned char *buf, int size) { + if (s->direct && !s->update_checksum) { + avio_flush(s); + writeout(s, buf, size); + return; + } while (size > 0) { int len = FFMIN(s->buf_end - s->buf_ptr, size); memcpy(s->buf_ptr, buf, len); @@ -199,13 +210,14 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) offset += offset1; } offset1 = offset - pos; - if (!s->must_flush && + if (!s->must_flush && (!s->direct || !s->seek) && offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) { /* can do the seek inside the buffer */ s->buf_ptr = s->buffer + offset1; } else if ((!s->seekable || offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) && !s->write_flag && offset1 >= 0 && + (!s->direct || !s->seek) && (whence != SEEK_END || force)) { while(s->pos < offset && !s->eof_reached) fill_buffer(s); @@ -458,7 +470,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) if (len > size) len = size; if (len == 0) { - if(size > s->buffer_size && !s->update_checksum){ + if((s->direct || size > s->buffer_size) && !s->update_checksum){ if(s->read_packet) len = s->read_packet(s->opaque, buf, size); if (len <= 0) { @@ -670,6 +682,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) av_free(buffer); return AVERROR(ENOMEM); } + (*s)->direct = h->flags & AVIO_FLAG_DIRECT; (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL; (*s)->max_packet_size = max_packet_size; if(h->prot) { diff --git a/libavformat/options_table.h b/libavformat/options_table.h index 0313839046..8d57c273e3 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -28,6 +28,8 @@ #define D AV_OPT_FLAG_DECODING_PARAM static const AVOption options[]={ +{"avioflags", NULL, OFFSET(avio_flags), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, INT_MIN, INT_MAX, D|E, "avioflags"}, +{"direct", "reduce buffering", 0, AV_OPT_TYPE_CONST, {.dbl = AVIO_FLAG_DIRECT }, INT_MIN, INT_MAX, D|E, "avioflags"}, {"probesize", "set probing size", OFFSET(probesize), AV_OPT_TYPE_INT, {.dbl = 5000000 }, 32, INT_MAX, D}, {"packetsize", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, INT_MAX, E}, {"fflags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, INT_MIN, INT_MAX, D|E, "fflags"}, diff --git a/libavformat/utils.c b/libavformat/utils.c index 5c5e24ca48..0bf3e2bdd5 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -543,7 +543,7 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0)))) return 0; - if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ, + if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags, &s->interrupt_callback, options)) < 0) return ret; if (s->iformat) diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index 5e5c8e14fc..5d3ad4491a 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -1,3 +1,6 @@ +FATE_DEMUX += fate-avio-direct +fate-avio-direct: CMD = framecrc -avioflags direct -i $(SAMPLES)/fraps/fraps-v5-bouncing-balls-partial.avi -avioflags direct + FATE_DEMUX += fate-adts-demux fate-adts-demux: CMD = crc -i $(SAMPLES)/aac/ct_faac-adts.aac -acodec copy -- cgit v1.2.3