Luca Barbato <[email protected]> writes:

> 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.
>
> Flush the packet queue if the packets in the queue have a delay
> larger than the max_delay.
>
> Original report of the issue and initial proposed solution by
> [email protected] on bug 31.
> ---
>  libavformat/avformat.h |    3 +++
>  libavformat/utils.c    |   36 +++++++++++++++++++++++++++++++-----
>  2 files changed, 34 insertions(+), 5 deletions(-)

The patch title could use quite a bit of improvement.

> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 5276af1..2f95405 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -887,6 +887,9 @@ typedef struct AVFormatContext {
>  #if FF_API_PRELOAD
>      attribute_deprecated int preload;
>  #endif
> +    /**
> +     * maximum muxing/demuxing delay in microseconds
> +     */
>      int max_delay;
>  
>  #if FF_API_LOOP_OUTPUT
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index b8262ec..93d2315 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -3140,19 +3140,45 @@ 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){
>          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;
> +    if (s->max_delay && s->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);

The formatting of this statement makes it almost impossible to read,
and the function call should not be done inside the FFMAX() macro anyway.
Please try to write it in a clearer way.

> +                stream_count++;
> +            }

Please add {} to the for() loop.  It looks weird without them.

> +        if (delta_dts > s->max_delay) {
> +            av_log(s, AV_LOG_DEBUG, "Sparse stream detected, forcing 
> flush\n");
> +            flush = 1;
> +        }

I hope flush here doesn't really mean flush but rather force output of
one packet.  Flushing the entire buffer would be disastrous.

> +    } else {
> +        for (i=0; i < s->nb_streams; i++)
> +            stream_count += !!s->streams[i]->last_in_packet_buffer;
> +    }
>  
> -    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;
>  
> -- 
> 1.7.8.rc1
>

-- 
Måns Rullgård
[email protected]
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to