[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