[vlc-commits] [Git][videolan/vlc][master] 11 commits: clock: rename private header guard

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Feb 3 17:09:24 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
a1bfd37c by Alaric Senat at 2023-02-03T16:55:34+00:00
clock: rename private header guard

This is an core internal header guard, its naming blocks a publicly
exposed header to have this standard name.

- - - - -
d9b23d6a by Alaric Senat at 2023-02-03T16:55:34+00:00
clock: publicly expose clock's typedefs

This is needed to expose a clock subset to stream outputs. It also
reduce the amount of redundant typedefs to the clock in the core
codebase.

- - - - -
831c91f7 by Alaric Senat at 2023-02-03T16:55:34+00:00
vlc_decoder: add the clock as parameter

Forwarding a valid clock instance is necessary for the aout/vout proper
synchronization.

- - - - -
13539bac by Alaric Senat at 2023-02-03T16:55:34+00:00
sout: expose a light clock API

Will provide a small subset of core's clock API to `display`.

- - - - -
fe9aa3cf by Alaric Senat at 2023-02-03T16:55:34+00:00
sout: display: fix formatting inconsistencies

This patches apply some formatting for consistency:
    - Sort the includes
    - Remove unrespected padding
    - correct curly-braces spacing to the original intent

No functional changes.

- - - - -
bdede41d by Alaric Senat at 2023-02-03T16:55:34+00:00
sout: display: wrap `id_sys_t` inside a structure

To allow owning more data. In occurrence, a clock in the next commit.

- - - - -
55823251 by Alaric Senat at 2023-02-03T16:55:34+00:00
sout: display: add clock support

Create a local clock context using the new `sout_Clock` API. This set
of clocks will be passed to the input decoder to have a synchronization
context local to the display module.

Currently, no master clock is selected for the sake of simplicity,
implicitly falling back to monotonic master.

Fixes #23220

- - - - -
100d9079 by Alaric Senat at 2023-02-03T16:55:34+00:00
sout: display: drop frames without PCR

Consider frames arriving without any first PCR being signaled as
invalid. We can't really render frames without calibrating the main
clock first via the initial SetPCR call.

- - - - -
1c6730b6 by Alaric Senat at 2023-02-03T16:55:34+00:00
input_decoder: publicly expose `ChangeDelay`

Will be needed in the `display` stream output for backward compatibility
with the VLC 3.0 `delay` option.

- - - - -
d915a378 by Alaric Senat at 2023-02-03T16:55:34+00:00
sout: display: fix delay handling

Use the 4.0 input decoder API to pass the delay to the output chain that
will properly apply the delay to the clocks internally.

- - - - -
45ee01f1 by Alaric Senat at 2023-02-03T16:55:34+00:00
sout: display: switch to `vlc_frame_t`

- - - - -


11 changed files:

- + include/vlc_clock.h
- include/vlc_decoder.h
- include/vlc_sout.h
- modules/stream_out/display.c
- src/Makefile.am
- src/clock/clock.h
- src/input/decoder.c
- src/input/decoder.h
- src/libvlccore.sym
- src/stream_output/stream_output.c
- src/video_output/vout_internal.h


Changes:

=====================================
include/vlc_clock.h
=====================================
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * vlc_clock.h: clock API
+ *****************************************************************************
+ * Copyright (C) 2023 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_CLOCK_H
+#define VLC_CLOCK_H 1
+
+/**
+ * The VLC clock API.
+ *
+ * The publicly exposed clock API is for now very restraint. For now, only a
+ * subset of the clock is exposed and simplified for stream output modules.
+ *
+ * The actual clock implementation is mostly private for now as no other use
+ * case is found.
+ */
+
+/**
+ * Opaques VLC Clock types.
+ */
+typedef struct vlc_clock_main_t vlc_clock_main_t;
+typedef struct vlc_clock_t vlc_clock_t;
+
+#endif


=====================================
include/vlc_decoder.h
=====================================
@@ -39,13 +39,16 @@ typedef struct vlc_input_decoder_t vlc_input_decoder_t;
 typedef struct input_resource_t input_resource_t;
 
 /* */
+struct vlc_clock_t;
 VLC_API vlc_input_decoder_t *
-vlc_input_decoder_Create( vlc_object_t *, const es_format_t *, input_resource_t * ) VLC_USED;
+vlc_input_decoder_Create( vlc_object_t *, const es_format_t *,
+                          struct vlc_clock_t *, input_resource_t * ) VLC_USED;
 VLC_API void vlc_input_decoder_Delete( vlc_input_decoder_t * );
 VLC_API void vlc_input_decoder_Decode( vlc_input_decoder_t *, block_t *, bool b_do_pace );
 VLC_API void vlc_input_decoder_Drain( vlc_input_decoder_t * );
 VLC_API void vlc_input_decoder_Flush( vlc_input_decoder_t * );
 VLC_API int  vlc_input_decoder_SetSpuHighlight( vlc_input_decoder_t *, const vlc_spu_highlight_t * );
+VLC_API void vlc_input_decoder_ChangeDelay( vlc_input_decoder_t *, vlc_tick_t i_delay );
 
 /**
  * It creates an empty input resource handler.


=====================================
include/vlc_sout.h
=====================================
@@ -33,6 +33,7 @@ extern "C" {
 
 #include <sys/types.h>
 #include <vlc_es.h>
+#include <vlc_clock.h>
 
 /**
  * \defgroup sout Stream output
@@ -204,6 +205,12 @@ VLC_API void sout_StreamFlush(sout_stream_t *s, void *id);
 VLC_API void sout_StreamSetPCR(sout_stream_t *s, vlc_tick_t pcr);
 VLC_API int sout_StreamControlVa(sout_stream_t *s, int i_query, va_list args);
 
+VLC_API vlc_clock_main_t *sout_ClockMainCreate(sout_stream_t *) VLC_USED;
+VLC_API void sout_ClockMainDelete(vlc_clock_main_t *);
+VLC_API void sout_ClockMainSetFirstPcr(vlc_clock_main_t *, vlc_tick_t pcr);
+VLC_API vlc_clock_t *sout_ClockCreate(vlc_clock_main_t *, const es_format_t *) VLC_USED;
+VLC_API void sout_ClockDelete(vlc_clock_t *);
+
 static inline int sout_StreamControl( sout_stream_t *s, int i_query, ... )
 {
     va_list args;


=====================================
modules/stream_out/display.c
=====================================
@@ -25,23 +25,24 @@
  *****************************************************************************/
 
 #ifdef HAVE_CONFIG_H
-# include "config.h"
+#include "config.h"
 #endif
 
 #include <vlc_common.h>
-#include <vlc_plugin.h>
+
 #include <vlc_decoder.h>
+#include <vlc_frame.h>
+#include <vlc_plugin.h>
 #include <vlc_sout.h>
-#include <vlc_block.h>
 
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
-#define AUDIO_TEXT N_("Enable audio")
+#define AUDIO_TEXT N_( "Enable audio" )
 #define AUDIO_LONGTEXT N_( "Enable/disable audio rendering." )
-#define VIDEO_TEXT N_("Enable video")
+#define VIDEO_TEXT N_( "Enable video" )
 #define VIDEO_LONGTEXT N_( "Enable/disable video rendering." )
-#define DELAY_TEXT N_("Delay (ms)")
+#define DELAY_TEXT N_( "Delay (ms)" )
 #define DELAY_LONGTEXT N_( "Introduces a delay in the display of the stream." )
 
 static int  Open ( vlc_object_t * );
@@ -49,8 +50,8 @@ static void Close( vlc_object_t * );
 
 #define SOUT_CFG_PREFIX "sout-display-"
 
-vlc_module_begin ()
-    set_shortname( N_("Display"))
+vlc_module_begin()
+    set_shortname( N_("Display") )
     set_description( N_("Display stream output") )
     set_capability( "sout output", 50 )
     add_shortcut( "display" )
@@ -63,7 +64,7 @@ vlc_module_begin ()
     add_integer( SOUT_CFG_PREFIX "delay", 100, DELAY_TEXT,
                  DELAY_LONGTEXT )
     set_callbacks( Open, Close )
-vlc_module_end ()
+vlc_module_end()
 
 
 /*****************************************************************************
@@ -75,67 +76,98 @@ static const char *const ppsz_sout_options[] = {
 
 typedef struct
 {
-    bool     b_audio;
-    bool     b_video;
+    bool b_audio;
+    bool b_video;
 
-    vlc_tick_t     i_delay;
+    vlc_tick_t i_delay;
     input_resource_t *p_resource;
+
+    vlc_clock_main_t *main_clock;
+    bool first_pcr_signaled;
+    bool error;
 } sout_stream_sys_t;
 
+typedef struct
+{
+    vlc_input_decoder_t *dec;
+    vlc_clock_t *clock;
+} sout_stream_id_sys_t;
+
 static void *Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
 
-    if( ( p_fmt->i_cat == AUDIO_ES && !p_sys->b_audio )||
-        ( p_fmt->i_cat == VIDEO_ES && !p_sys->b_video ) )
+    if( (p_fmt->i_cat == AUDIO_ES && !p_sys->b_audio) ||
+        (p_fmt->i_cat == VIDEO_ES && !p_sys->b_video) )
     {
         return NULL;
     }
 
-    vlc_input_decoder_t *p_dec =
-        vlc_input_decoder_Create( VLC_OBJECT(p_stream), p_fmt,
-                                  p_sys->p_resource );
-    if( p_dec == NULL )
+    sout_stream_id_sys_t *id = malloc( sizeof(*id) );
+    if( unlikely(id == NULL) )
+        return NULL;
+
+    id->clock = sout_ClockCreate( p_sys->main_clock, p_fmt );
+    if( unlikely(id->clock == NULL) )
+    {
+        free( id );
+        return NULL;
+    }
+
+    id->dec = vlc_input_decoder_Create(
+        VLC_OBJECT(p_stream), p_fmt, id->clock, p_sys->p_resource );
+    if( id->dec == NULL )
     {
         msg_Err( p_stream, "cannot create decoder for fcc=`%4.4s'",
                  (char*)&p_fmt->i_codec );
+        sout_ClockDelete( id->clock );
+        free( id );
         return NULL;
     }
-    return p_dec;
+
+    if( p_sys->i_delay != VLC_TICK_INVALID )
+        vlc_input_decoder_ChangeDelay( id->dec, p_sys->i_delay );
+
+    return id;
 }
 
 static void Del( sout_stream_t *p_stream, void *id )
 {
     (void) p_stream;
-    vlc_input_decoder_Delete( id );
+
+    sout_stream_id_sys_t *id_sys = id;
+    vlc_input_decoder_Delete( id_sys->dec );
+    sout_ClockDelete( id_sys->clock );
+    free( id_sys );
 }
 
-static int Send( sout_stream_t *p_stream, void *id, block_t *p_buffer )
+static int Send( sout_stream_t *p_stream, void *id, vlc_frame_t *frames )
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
+    sout_stream_id_sys_t *id_sys = id;
 
-    while( p_buffer )
+    if( !p_sys->first_pcr_signaled )
     {
-        block_t *p_next = p_buffer->p_next;
-
-        p_buffer->p_next = NULL;
-
-        if( id != NULL && p_buffer->i_buffer > 0 )
+        if( !p_sys->error )
         {
-            if( p_buffer->i_dts == VLC_TICK_INVALID )
-                p_buffer->i_dts = 0;
-            else
-                p_buffer->i_dts += p_sys->i_delay;
+            msg_Err( p_stream,
+                     "Missing first pcr event. Forced to drop early frames." );
+            p_sys->error = true;
+        }
+        vlc_frame_ChainRelease( frames );
+        return VLC_EGENERIC;
+    }
+
+    while( frames )
+    {
+        vlc_frame_t *p_next = frames->p_next;
 
-            if( p_buffer->i_pts == VLC_TICK_INVALID )
-                p_buffer->i_pts = 0;
-            else
-                p_buffer->i_pts += p_sys->i_delay;
+        frames->p_next = NULL;
 
-            vlc_input_decoder_Decode( id, p_buffer, false );
-        }
+        if( id != NULL && frames->i_buffer > 0 )
+            vlc_input_decoder_Decode( id_sys->dec, frames, false );
 
-        p_buffer = p_next;
+        frames = p_next;
     }
 
     return VLC_SUCCESS;
@@ -143,17 +175,17 @@ static int Send( sout_stream_t *p_stream, void *id, block_t *p_buffer )
 
 static int Control( sout_stream_t *p_stream, int i_query, va_list args )
 {
-    switch (i_query)
+    switch( i_query )
     {
         case SOUT_STREAM_ID_SPU_HIGHLIGHT:
         {
-            vlc_input_decoder_t *p_dec = va_arg(args, void *);
-            void *spu_hl = va_arg(args, void *);
+            vlc_input_decoder_t *p_dec = va_arg( args, void * );
+            void *spu_hl = va_arg( args, void * );
             return vlc_input_decoder_SetSpuHighlight( p_dec, spu_hl );
         }
 
         case SOUT_STREAM_IS_SYNCHRONOUS:
-            *va_arg(args, bool *) = true;
+            *va_arg( args, bool * ) = true;
             break;
 
         default:
@@ -163,8 +195,19 @@ static int Control( sout_stream_t *p_stream, int i_query, va_list args )
     return VLC_SUCCESS;
 }
 
+static void SetPCR( sout_stream_t *p_stream, vlc_tick_t pcr )
+{
+    sout_stream_sys_t *sys = p_stream->p_sys;
+
+    if( sys->first_pcr_signaled )
+        return;
+
+    sout_ClockMainSetFirstPcr( sys->main_clock, pcr );
+    sys->first_pcr_signaled = true;
+}
+
 static const struct sout_stream_operations ops = {
-    Add, Del, Send, Control, NULL, NULL
+    Add, Del, Send, Control, NULL, SetPCR
 };
 
 /*****************************************************************************
@@ -172,10 +215,10 @@ static const struct sout_stream_operations ops = {
  *****************************************************************************/
 static int Open( vlc_object_t *p_this )
 {
-    sout_stream_t     *p_stream = (sout_stream_t*)p_this;
+    sout_stream_t *p_stream = (sout_stream_t*)p_this;
     sout_stream_sys_t *p_sys;
 
-    p_sys = malloc( sizeof( sout_stream_sys_t ) );
+    p_sys = malloc( sizeof(sout_stream_sys_t) );
     if( p_sys == NULL )
         return VLC_ENOMEM;
 
@@ -186,15 +229,26 @@ static int Open( vlc_object_t *p_this )
         return VLC_ENOMEM;
     }
 
+    p_sys->main_clock = sout_ClockMainCreate(p_stream);
+    if( unlikely(p_sys->main_clock == NULL) )
+    {
+        input_resource_Release( p_sys->p_resource );
+        free( p_sys );
+        return VLC_ENOMEM;
+    }
+
     config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
-                   p_stream->p_cfg );
+                       p_stream->p_cfg );
 
-    p_sys->b_audio = var_GetBool( p_stream, SOUT_CFG_PREFIX"audio" );
+    p_sys->b_audio = var_GetBool( p_stream, SOUT_CFG_PREFIX "audio" );
     p_sys->b_video = var_GetBool( p_stream, SOUT_CFG_PREFIX "video" );
-    p_sys->i_delay = VLC_TICK_FROM_MS( var_GetInteger( p_stream, SOUT_CFG_PREFIX "delay" ) );
+    p_sys->i_delay =
+        VLC_TICK_FROM_MS( var_GetInteger(p_stream, SOUT_CFG_PREFIX "delay") );
+    p_sys->first_pcr_signaled = false;
+    p_sys->error = false;
 
     p_stream->ops = &ops;
-    p_stream->p_sys     = p_sys;
+    p_stream->p_sys = p_sys;
     return VLC_SUCCESS;
 }
 
@@ -203,9 +257,10 @@ static int Open( vlc_object_t *p_this )
  *****************************************************************************/
 static void Close( vlc_object_t * p_this )
 {
-    sout_stream_t     *p_stream = (sout_stream_t*)p_this;
+    sout_stream_t *p_stream = (sout_stream_t*)p_this;
     sout_stream_sys_t *p_sys = p_stream->p_sys;
 
     input_resource_Release( p_sys->p_resource );
+    sout_ClockMainDelete( p_sys->main_clock );
     free( p_sys );
 }


=====================================
src/Makefile.am
=====================================
@@ -43,6 +43,7 @@ pluginsinclude_HEADERS = \
 	../include/vlc_configuration.h \
 	../include/vlc_cpu.h \
 	../include/vlc_cxx_helpers.hpp \
+	../include/vlc_clock.h \
 	../include/vlc_decoder.h \
 	../include/vlc_demux.h \
 	../include/vlc_dialog.h \


=====================================
src/clock/clock.h
=====================================
@@ -17,8 +17,10 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
-#ifndef VLC_CLOCK_H
-#define VLC_CLOCK_H
+#ifndef CLOCK_H
+#define CLOCK_H
+
+#include <vlc_clock.h>
 
 enum vlc_clock_master_source
 {
@@ -28,9 +30,6 @@ enum vlc_clock_master_source
     VLC_CLOCK_MASTER_MONOTONIC,
 };
 
-typedef struct vlc_clock_main_t vlc_clock_main_t;
-typedef struct vlc_clock_t vlc_clock_t;
-
 /**
  * Callbacks for the owner of the main clock
  */
@@ -230,4 +229,4 @@ vlc_clock_ConvertToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
     return system;
 }
 
-#endif /*VLC_CLOCK_H*/
+#endif /*CLOCK_H*/


=====================================
src/input/decoder.c
=====================================
@@ -2195,12 +2195,12 @@ vlc_input_decoder_New( vlc_object_t *parent, const struct vlc_input_decoder_cfg
  */
 vlc_input_decoder_t *
 vlc_input_decoder_Create( vlc_object_t *p_parent, const es_format_t *fmt,
-                          input_resource_t *p_resource )
+                          struct vlc_clock_t *clock, input_resource_t *p_resource )
 {
     const struct vlc_input_decoder_cfg cfg = {
         .fmt = fmt,
         .str_id = NULL,
-        .clock = NULL,
+        .clock = clock,
         .resource = p_resource,
         .sout = NULL,
         .input_type = INPUT_TYPE_NONE,


=====================================
src/input/decoder.h
=====================================
@@ -82,11 +82,6 @@ void vlc_input_decoder_ChangePause( vlc_input_decoder_t *, bool b_paused, vlc_ti
  */
 void vlc_input_decoder_ChangeRate( vlc_input_decoder_t *dec, float rate );
 
-/**
- * This function changes the delay.
- */
-void vlc_input_decoder_ChangeDelay( vlc_input_decoder_t *, vlc_tick_t i_delay );
-
 /**
  * This function makes the decoder start waiting for a valid data block from its fifo.
  */


=====================================
src/libvlccore.sym
=====================================
@@ -180,6 +180,7 @@ vlc_input_decoder_Decode
 vlc_input_decoder_Drain
 vlc_input_decoder_Flush
 vlc_input_decoder_SetSpuHighlight
+vlc_input_decoder_ChangeDelay
 input_item_AddInfo
 input_item_AddOption
 input_item_AddOptions
@@ -359,6 +360,11 @@ sout_StreamIdSend
 sout_StreamFlush
 sout_StreamSetPCR
 sout_StreamControlVa
+sout_ClockMainCreate
+sout_ClockMainDelete
+sout_ClockMainSetFirstPcr
+sout_ClockCreate
+sout_ClockDelete
 spu_Create
 spu_Destroy
 spu_PutSubpicture


=====================================
src/stream_output/stream_output.c
=====================================
@@ -49,6 +49,8 @@
 
 #include "input/input_interface.h"
 
+#include "clock/clock.h"
+
 #undef DEBUG_BUFFER
 /*****************************************************************************
  * Local prototypes
@@ -771,6 +773,35 @@ static void sout_StreamDelete( sout_stream_t *p_stream )
     vlc_object_delete(p_stream);
 }
 
+vlc_clock_main_t *sout_ClockMainCreate( sout_stream_t *p_stream )
+{
+    struct vlc_tracer *tracer = vlc_object_get_tracer( &p_stream->obj );
+    return vlc_clock_main_New( p_stream->obj.logger, tracer );
+}
+
+void sout_ClockMainDelete( vlc_clock_main_t *main_clock )
+{
+    vlc_clock_main_Delete( main_clock );
+}
+
+void sout_ClockMainSetFirstPcr( vlc_clock_main_t *main_clock, vlc_tick_t pcr )
+{
+    vlc_clock_main_Reset( main_clock );
+    vlc_clock_main_SetFirstPcr( main_clock, vlc_tick_now(), pcr );
+}
+
+vlc_clock_t *sout_ClockCreate( vlc_clock_main_t *main_clock,
+                               const es_format_t *fmt )
+{
+    return vlc_clock_main_CreateSlave( main_clock, NULL, fmt->i_cat,
+                                       NULL, NULL );
+}
+
+void sout_ClockDelete( vlc_clock_t *clock )
+{
+    vlc_clock_Delete( clock );
+}
+
 /* Destroy a "stream_out" modules chain
  *
  * p_first is the first module to be destroyed in the chain


=====================================
src/video_output/vout_internal.h
=====================================
@@ -25,9 +25,9 @@
 #define LIBVLC_VOUT_INTERNAL_H 1
 
 #include <vlc_vout_display.h>
+#include <vlc_clock.h>
 
 typedef struct input_thread_t input_thread_t;
-typedef struct vlc_clock_t vlc_clock_t;
 
 /* It should be high enough to absorbe jitter due to difficult picture(s)
  * to decode but not too high as memory is not that cheap.



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d9e8ad8b02452fc5c601e96e70233458562c4ee9...45ee01f158e92b28e4d2843b3337a09984637fd0

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d9e8ad8b02452fc5c601e96e70233458562c4ee9...45ee01f158e92b28e4d2843b3337a09984637fd0
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list