[FFmpeg-devel] [PATCH] Add AVIO_FLAG_DIRECT.

Reimar Döffinger Reimar.Doeffinger at gmx.de
Wed Mar 28 22:26:35 CEST 2012


Allows avoiding the buffer when using avio read and write functions.
The test does not work: It works for testing reading, but for
writing avio_flags never gets set in the ffmpeg.c part of the change.

Signed-off-by: Reimar Döffinger <Reimar.Doeffinger at gmx.de>
---
 ffmpeg.c                    |    2 +-
 libavformat/avformat.h      |    2 ++
 libavformat/avio.h          |   13 +++++++++++++
 libavformat/aviobuf.c       |   31 ++++++++++++++++++++++---------
 libavformat/options_table.h |    2 ++
 libavformat/utils.c         |    2 +-
 tests/fate/demux.mak        |    3 +++
 7 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index d5e789e..1cba743 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -4542,7 +4542,7 @@ static void opt_output_file(void *optctx, const char *filename)
         assert_file_overwrite(filename);
 
         /* open the file */
-        if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
+        if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE | oc->avio_flags,
                               &oc->interrupt_callback,
                               &output_files[nb_output_files - 1].opts)) < 0) {
             print_error(filename, err);
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 7c307a7..5a11fdc 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 95f9558..b4c975f 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -121,6 +121,12 @@ typedef struct {
      * This field is internal to libavformat and access from outside is not allowed.
      */
      int64_t maxsize;
+
+     /**
+      * avoi_read and avio_write should if possible be satisfied directly
+      * instead of going through a buffer.
+      */
+     int direct;
 } AVIOContext;
 
 /* unbuffered I/O */
@@ -320,6 +326,13 @@ int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);
 #define AVIO_FLAG_NONBLOCK 8
 
 /**
+ * Use direct mode.
+ * avoi_read and avio_write should if possible be satisfied directly
+ * instead of going through a buffer.
+ */
+#define AVIO_FLAG_DIRECT 0x8000
+
+/**
  * Create and initialize a AVIOContext for accessing the
  * resource indicated by url.
  * @note When the resource indicated by url has been opened in
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index d1520ed..5e777fa 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) {
+        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 &&
         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 &&
               (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 0313839..8d57c27 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 0f8b940..3d0d989 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 5e5c8e1..5d3ad44 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
 
-- 
1.7.9.1



More information about the ffmpeg-devel mailing list