[FFmpeg-devel] [PATCH 2/2] lavf: allow grouping packets in chunks of a user specified size and duration. This is similar to MP4Boxs -inter

Michael Niedermayer michaelni at gmx.at
Wed Nov 30 00:29:14 CET 2011


Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
 libavformat/avformat.h |   19 +++++++++++++++++++
 libavformat/options.c  |    2 ++
 libavformat/utils.c    |   30 ++++++++++++++++++++++++++----
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index b281406..662ba49 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -700,6 +700,9 @@ typedef struct AVStream {
      */
     int stream_identifier;
 
+    int64_t interleaver_chunk_size;
+    int64_t interleaver_chunk_duration;
+
     /**
      * Stream informations used internally by av_find_stream_info()
      */
@@ -1086,6 +1089,22 @@ typedef struct AVFormatContext {
      */
     int audio_preload;
 
+    /**
+     * Max chunk time in micro seconds.
+     * Note, not all formats support this and unpredictable things may happen if its used when not supported.
+     * - encoding: Set by user via AVOptions (NO direct access)
+     * - decoding: unused
+     */
+    int max_chunk_duration;
+
+    /**
+     * Max chunk size in bytes
+     * Note, not all formats support this and unpredictable things may happen if its used when not supported.
+     * - encoding: Set by user via AVOptions (NO direct access)
+     * - decoding: unused
+     */
+    int max_chunk_size;
+
     /*****************************************************************
      * All fields below this line are not part of the public API. They
      * may not be used outside of libavformat and can be changed and
diff --git a/libavformat/options.c b/libavformat/options.c
index 144aa1a..2584153 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -117,6 +117,8 @@ static const AVOption options[]={
 {"explode", "abort decoding on error recognition", 0, AV_OPT_TYPE_CONST, {.dbl = FF_ER_EXPLODE }, INT_MIN, INT_MAX, D, "fer"},
 {"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.dbl = -1}, -1, INT_MAX-1, D},
 {"audio_preload", "microseconds by which audio packets should be interleaved earlier", OFFSET(audio_preload), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
+{"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
+{"chunk_size", "size in bytes for each chunk", OFFSET(max_chunk_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
 {NULL},
 };
 
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 633cf78..ec4d6b9 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -3260,10 +3260,14 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
     return ret;
 }
 
+#define CHUNK_START 0x1000
+
 int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
                               int (*compare)(AVFormatContext *, AVPacket *, AVPacket *))
 {
     AVPacketList **next_point, *this_pktl;
+    AVStream *st= s->streams[pkt->stream_index];
+    int chunked= s->max_chunk_size || s->max_chunk_duration;
 
     this_pktl = av_mallocz(sizeof(AVPacketList));
     if (!this_pktl)
@@ -3273,16 +3277,34 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
     av_dup_packet(&this_pktl->pkt);  // duplicate the packet if it uses non-alloced memory
 
     if(s->streams[pkt->stream_index]->last_in_packet_buffer){
-        next_point = &(s->streams[pkt->stream_index]->last_in_packet_buffer->next);
-    }else
+        next_point = &(st->last_in_packet_buffer->next);
+    }else{
         next_point = &s->packet_buffer;
+    }
 
     if(*next_point){
+        if(chunked){
+            int64_t max= av_rescale_q(s->max_chunk_duration, AV_TIME_BASE_Q, st->time_base);
+            if(   st->interleaver_chunk_size     + pkt->size     < s->max_chunk_size
+               && st->interleaver_chunk_duration + pkt->duration < max){
+                st->interleaver_chunk_size     += pkt->size;
+                st->interleaver_chunk_duration += pkt->duration;
+                goto next_non_null;
+            }else{
+                st->interleaver_chunk_size     =
+                st->interleaver_chunk_duration = 0;
+                this_pktl->pkt.flags |= CHUNK_START;
+            }
+        }
+
         if(compare(s, &s->packet_buffer_end->pkt, pkt)){
-            while(!compare(s, &(*next_point)->pkt, pkt)){
+            while(   *next_point
+                  && ((chunked && !((*next_point)->pkt.flags&CHUNK_START))
+                      || !compare(s, &(*next_point)->pkt, pkt))){
                 next_point= &(*next_point)->next;
             }
-            goto next_non_null;
+            if(*next_point)
+                goto next_non_null;
         }else{
             next_point = &(s->packet_buffer_end->next);
         }
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list