From ec20fc15818598aaf83232db3df2c85b1752c49a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 30 Nov 2011 00:21:00 +0100 Subject: [PATCH] lavf: allow grouping packets in chunks of a user specified size and duration. This is similar to MP4Boxs -inter Signed-off-by: Michael Niedermayer --- libavformat/avformat.h | 19 +++++++++++++++++++ libavformat/options.c | 2 ++ libavformat/utils.c | 30 ++++++++++++++++++++++++++---- libavformat/version.h | 2 +- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 156e83c668..f1c701d03f 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 microseconds. + * Note, not all formats support this and unpredictable things may happen if it is 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 it is 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 144aa1a123..2584153b91 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 5a4b364f47..1493f278ab 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3263,10 +3263,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) @@ -3276,16 +3280,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){ + uint64_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-1U + && st->interleaver_chunk_duration + pkt->duration <= max-1U){ + 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); } diff --git a/libavformat/version.h b/libavformat/version.h index 73acf6cb03..844cd64464 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -24,7 +24,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 53 -#define LIBAVFORMAT_VERSION_MINOR 23 +#define LIBAVFORMAT_VERSION_MINOR 24 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \