Introduce max_streams_delay and flush the packet queue if the packets in the queue have a delay larger than the max_streams_delay.
av_interleave_packet_per_dts waits untill it gets a frame for each stream before outputting packets in interleaved order. Sparse streams tend to add up latency and in specific cases end up allocating a large amount of memory. Original report of the issue and initial proposed solution by [email protected] on bug 31. --- libavformat/avformat.h | 4 ++++ libavformat/utils.c | 34 +++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 33e820e..7845c84 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1005,6 +1005,9 @@ typedef struct AVFormatContext { */ AVIOInterruptCB interrupt_callback; + /* av_interleave_packet_per_dts() support */ + int64_t max_streams_delay; + /***************************************************************** * 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 @@ -1040,6 +1043,7 @@ typedef struct AVFormatContext { /* av_seek_frame() support */ int64_t data_offset; /**< offset of the first packet */ + #endif } AVFormatContext; diff --git a/libavformat/utils.c b/libavformat/utils.c index b8262ec..e8c17be 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3140,19 +3140,39 @@ static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacke return comp > 0; } -int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){ +int av_interleave_packet_per_dts(AVFormatContext *s, + AVPacket *out, AVPacket *pkt, int flush) +{ + AVPacket *last_pkt; AVPacketList *pktl; - int stream_count=0; + int stream_count = 0; + int64_t delta_dts = INT64_MIN; + int64_t last_dts; int i; - if(pkt){ + if (pkt) { ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts); } - for(i=0; i < s->nb_streams; i++) - stream_count+= !!s->streams[i]->last_in_packet_buffer; + last_pkt = &s->packet_buffer->pkt; + last_dts = av_rescale_q(last_pkt->dts, + s->streams[last_pkt->stream_index]->time_base, + AV_TIME_BASE_Q); + + for (i=0; i < s->nb_streams; i++) + if (s->streams[i]->last_in_packet_buffer) { + delta_dts = FFMAX(delta_dts, + av_rescale_q(s->streams[i]->last_in_packet_buffer->pkt.dts, + s->streams[i]->time_base, + AV_TIME_BASE_Q) - last_dts); + stream_count++; + } + if (s->max_streams_delay && delta_dts > s->max_streams_delay) { + av_log(s, AV_LOG_DEBUG, "Sparse stream detected, forcing flush\n"); + flush = 1; + } - if(stream_count && (s->nb_streams == stream_count || flush)){ + if (stream_count && (s->nb_streams == stream_count || flush)) { pktl= s->packet_buffer; *out= pktl->pkt; @@ -3164,7 +3184,7 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk s->streams[out->stream_index]->last_in_packet_buffer= NULL; av_freep(&pktl); return 1; - }else{ + } else { av_init_packet(out); return 0; } -- 1.7.8.rc1 _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
