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

Rémi Denis-Courmont remi at remlab.net
Tue Feb 7 14:22:27 CET 2017


On February 7, 2017 2:15:21 PM GMT+02:00, "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.html#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;
>+}
>+
> 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

Hello,

AFAIK, the first block is not necessarily the one with the smalledt PTS and the smallest DTS. There might not even be such a block.

So I guess, this patch may cause negative timestamps in certain corner cases.
-- 
Rémi Denis-Courmont


More information about the vlc-devel mailing list