[vlc-devel] [PATCH] mux/avformat: normalize pts and dts in AVPacket

Tristan Matthews tmatth at videolan.org
Tue Feb 7 16:00:33 CET 2017


Hi,

On Tue, Feb 7, 2017 at 1:15 PM, Filip Roséen <filip at atch.se> wrote:

> According to the ffmpeg documentation of AVPacket when used in muxing,
> pkt.{pts,dts} are absolute values for when a packet is to be
> interpreted, where the first packet shall start at zero.
>
> As the pts/dts in VLC are all relative to the PCR, those timestamps
> are not guaranteed to start at zero; which means that we would confuse
> avformat in scenarios where it heavily depends on zero-based pts/dts.
>
> These changes make sure that we start all timestamps at zero by
> normalizing each outgoing timestamp to the relative distance from the
> first entity received for each stream.
>
> fixes #17988
>
> --
>
>  Ticket:
>      - https://trac.videolan.org/vlc/ticket/17988
>
>  Relevant part of ffmpeg mkv mux (explains why the duration becomes wrong):
>      - https://www.ffmpeg.org/doxygen/3.2/matroskaenc_8c_source.htm
> l#l02148
>
>  AVPacket documentation:
>      - https://www.ffmpeg.org/doxygen/3.2/structAVPacket.htmi
> ---
>  modules/demux/avformat/mux.c | 48 ++++++++++++++++++++++++++++++
> ++++----------
>  1 file changed, 37 insertions(+), 11 deletions(-)
>
> diff --git a/modules/demux/avformat/mux.c b/modules/demux/avformat/mux.c
> index 9072c2f8e1..b2b7bb467d 100644
> --- a/modules/demux/avformat/mux.c
> +++ b/modules/demux/avformat/mux.c
> @@ -66,6 +66,18 @@ struct sout_mux_sys_t
>  #endif
>  };
>
> +typedef struct
> +{
> +    int i_stream;
> +
> +    struct {
> +        mtime_t i_pts;
> +        mtime_t i_dts;
> +    } base_ts;
> +
> +} sout_input_sys_t;
> +
> +
>  /**********************************************************
> *******************
>   * Local prototypes
>   ************************************************************
> *****************/
> @@ -221,11 +233,14 @@ static int AddStream( sout_mux_t *p_mux,
> sout_input_t *p_input )
>      }
>
>      /* */
> -    p_input->p_sys = malloc( sizeof( int ) );
> -    if( unlikely(p_input->p_sys == NULL) )
> +    sout_input_sys_t* p_input_sys = malloc( sizeof *p_input_sys );
> +    if( unlikely( p_input_sys == NULL ) )
>          return VLC_ENOMEM;
>
> -    *((int *)p_input->p_sys) = p_sys->oc->nb_streams;
> +    p_input->p_sys = p_input_sys;
> +    p_input_sys->i_stream = p_sys->oc->nb_streams;
> +    p_input_sys->base_ts.i_pts = VLC_TS_INVALID;
> +    p_input_sys->base_ts.i_dts = VLC_TS_INVALID;
>
>      /* */
>      stream = avformat_new_stream( p_sys->oc, NULL);
> @@ -322,11 +337,21 @@ static void DelStream( sout_mux_t *p_mux,
> sout_input_t *p_input )
>      free( p_input->p_sys );
>  }
>
> +static mtime_t NormalizeTS( mtime_t *base, AVStream* p_stream, mtime_t
> timestamp )
> +{
> +    if( *base == VLC_TS_INVALID )
> +        *base = timestamp;
> +
> +    return ( timestamp - *base ) * p_stream->time_base.den /
> +           CLOCK_FREQ / p_stream->time_base.num;
>

If you can avoid integer overflow, you may want to do a multiplication
instead of a second division here:
( timestamp - *base ) * p_stream->time_base.den / (CLOCK_FREQ *
p_stream->time_base.num);

Disclaimer: have not tested or profiled this (hence the "may").

Best,
Tristan

+}
> +
>  static int MuxBlock( sout_mux_t *p_mux, sout_input_t *p_input )
>  {
>      sout_mux_sys_t *p_sys = p_mux->p_sys;
> +    sout_input_sys_t *p_input_sys = p_input->p_sys;
>      block_t *p_data = block_FifoGet( p_input->p_fifo );
> -    int i_stream = *((int *)p_input->p_sys);
> +    int i_stream = p_input_sys->i_stream;
>      AVStream *p_stream = p_sys->oc->streams[i_stream];
>      AVPacket pkt;
>
> @@ -350,15 +375,16 @@ static int MuxBlock( sout_mux_t *p_mux, sout_input_t
> *p_input )
>      }
>
>      if( p_data->i_pts > 0 )
> -        pkt.pts = p_data->i_pts * p_stream->time_base.den /
> -            CLOCK_FREQ / p_stream->time_base.num;
> +        pkt.pts = NormalizeTS( &p_input_sys->base_ts.i_pts,
> +                                p_stream, p_data->i_pts );
> +
>      if( p_data->i_dts > 0 )
> -        pkt.dts = p_data->i_dts * p_stream->time_base.den /
> -            CLOCK_FREQ / p_stream->time_base.num;
> +        pkt.dts = NormalizeTS( &p_input_sys->base_ts.i_dts,
> +                                p_stream, p_data->i_dts );
>
> -    /* this is another hack to prevent libavformat from triggering the
> "non monotone timestamps" check in avformat/utils.c */
> -    p_stream->cur_dts = ( p_data->i_dts * p_stream->time_base.den /
> -            CLOCK_FREQ / p_stream->time_base.num ) - 1;
> +    /* This is another hack to prevent libavformat from triggering the
> +     * "non monotone timestamps" check in avformat/utils.c */
> +    p_stream->cur_dts = pkt.dts;
>
>      if( av_write_frame( p_sys->oc, &pkt ) < 0 )
>      {
> --
> 2.11.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20170207/e9d98e84/attachment.html>


More information about the vlc-devel mailing list