[09/11] movenc: Add an internal flag for writing samples interleaved within a fragment

Message ID 1381320210-79941-9-git-send-email-martin@martin.st
State Superseded
Headers show

Commit Message

Martin Storsjö Oct. 9, 2013, 12:03 p.m.
This makes the moof atoms much bigger and is in general more
inefficient, but is required in certain cases.

This isn't exposed as a public option (yet), since setting it
on its own doesn't make much sense.
---
 libavformat/movenc.c |   38 ++++++++++++++++++++++++++++++--------
 libavformat/movenc.h |    1 +
 2 files changed, 31 insertions(+), 8 deletions(-)

Patch

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index cd6a0b6..38ac13f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -2790,15 +2790,22 @@  static int mov_flush_fragment(AVFormatContext *s)
         return 0;
     }
 
+    if (mov->flags & FF_MOV_FLAG_FRAG_INTERLEAVED) {
+        if (!mov->mdat_buf)
+            return 0;
+        mdat_size = avio_tell(mov->mdat_buf);
+    }
+
     for (i = 0; i < mov->nb_streams; i++) {
         MOVTrack *track = &mov->tracks[i];
-        if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF)
+        if (mov->flags & (FF_MOV_FLAG_SEPARATE_MOOF | FF_MOV_FLAG_FRAG_INTERLEAVED))
             track->data_offset = 0;
         else
             track->data_offset = mdat_size;
-        if (!track->mdat_buf)
+        if (!track->entry)
             continue;
-        mdat_size += avio_tell(track->mdat_buf);
+        if (track->mdat_buf)
+            mdat_size += avio_tell(track->mdat_buf);
         if (first_track < 0)
             first_track = i;
     }
@@ -2853,10 +2860,17 @@  static int mov_flush_fragment(AVFormatContext *s)
         if (track->entry)
             track->frag_start += duration;
         track->entry = 0;
-        if (!track->mdat_buf)
-            continue;
-        buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
-        track->mdat_buf = NULL;
+        if (!(mov->flags & FF_MOV_FLAG_FRAG_INTERLEAVED)) {
+            if (!track->mdat_buf)
+                continue;
+            buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
+            track->mdat_buf = NULL;
+        } else {
+            if (!mov->mdat_buf)
+                continue;
+            buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
+            mov->mdat_buf = NULL;
+        }
 
         avio_write(s->pb, buf, buf_size);
         av_free(buf);
@@ -2880,7 +2894,7 @@  int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
         int ret;
-        if (mov->fragments > 0) {
+        if (mov->fragments > 0 && !(mov->flags & FF_MOV_FLAG_FRAG_INTERLEAVED)) {
             if (!trk->mdat_buf) {
                 if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
                     return ret;
@@ -3200,6 +3214,14 @@  static int mov_write_header(AVFormatContext *s)
         }
     }
 
+    if (mov->flags & FF_MOV_FLAG_FRAG_INTERLEAVED &&
+        mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
+        av_log(s, AV_LOG_ERROR,
+               "frag_interleaved and omit_tfhd_offset or separate_moof are "
+               "mutually exclusive\n");
+        return AVERROR(EINVAL);
+    }
+
     /* Non-seekable output is ok if using fragmentation. If ism_lookahead
      * is enabled, we don't support non-seekable output at all. */
     if (!s->pb->seekable &&
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index 1b669e8..0be14d3 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -170,6 +170,7 @@  typedef struct MOVMuxContext {
 #define FF_MOV_FLAG_ISML 64
 #define FF_MOV_FLAG_FASTSTART 128
 #define FF_MOV_FLAG_OMIT_TFHD_OFFSET 256
+#define FF_MOV_FLAG_FRAG_INTERLEAVED 512
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);