[vlc-commits] [Git][videolan/vlc][master] 4 commits: sout: duplicate: simplify dup creation err handling

Steve Lhomme (@robUx4) gitlab at videolan.org
Sat Nov 18 08:38:51 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
fb079def by Alaric Senat at 2023-11-18T08:23:57+00:00
sout: duplicate: simplify dup creation err handling

Early continuing reduce scope nesting.

No functional changes.

- - - - -
cded8406 by Alaric Senat at 2023-11-18T08:23:57+00:00
sout: duplicate: fix leak on dup creation failure

- - - - -
3b1d63cc by Alaric Senat at 2023-11-18T08:23:57+00:00
sout: duplicate: early set stream sys

This avoid some code duplication in both the success and error handling
paths.

- - - - -
04844123 by Alaric Senat at 2023-11-18T08:23:57+00:00
sout: duplicate: forward a correct PCR to sink

duplicate modules can sink back to the main pipeline which was causing
duplicated and inconsistent PCR in the main pipeline.
An example duplicate module with a sink:
`#duplicate{dst=...,dst=...}:std{...}`

To fix the issue this patch add an endpoint to each duplicated sout
chains before they sink back to the main pipeline. We use it to regroup
PCR from each chains and select the lowest to forward it to the sink.

- - - - -


1 changed file:

- modules/stream_out/duplicate.c


Changes:

=====================================
modules/stream_out/duplicate.c
=====================================
@@ -67,6 +67,14 @@ typedef struct {
     sout_stream_t *stream;
     char *select_chain;
     char *es_id_suffix;
+
+    /* Reference on the PCR selector of the duplicated sout chain.
+     * Used in the PCR selector callbacks to distinguish from the other
+     * duplicated streams since the context is shared between all selectors. */
+    sout_stream_t *pcr_selector_ref;
+    /* Last PCR forwarded at the end of the stream chain or VLC_TICK_MIN when
+     * unset. */
+    vlc_tick_t pcr;
 } duplicated_stream_t;
 
 typedef struct
@@ -89,6 +97,85 @@ typedef struct
 static bool ESSelected( struct vlc_logger *, const es_format_t *fmt,
                         char *psz_select );
 
+/*****************************************************************************
+ * PCR Selector
+ *
+ * The PCR selector is the endpoint of each duplicated sout chains before they
+ * are linked back to the main pipeline. It is used to regroup PCR from each
+ * duplicated stream and select the lowest to forward it to the sink.
+ *****************************************************************************/
+
+static void *PCRSelectorAdd( sout_stream_t *stream, 
+                             const es_format_t *fmt,
+                             const char *es_id )
+{
+    return sout_StreamIdAdd( stream->p_next, fmt, es_id );
+}
+static void PCRSelectorDel( sout_stream_t *stream, void *id )
+{
+    sout_StreamIdDel( stream->p_next, id );
+}
+static int PCRSelectorControl( sout_stream_t *stream, int query, va_list args )
+{
+    return sout_StreamControlVa( stream->p_next, query, args );
+}
+static int PCRSelectorSend( sout_stream_t *stream,
+                            void *id,
+                            vlc_frame_t *frame )
+{
+    return sout_StreamIdSend( stream->p_next, id, frame );
+}
+static void PCRSelectorFlush( sout_stream_t *stream, void *id )
+{
+    sout_StreamFlush( stream->p_next, id );
+}
+static void PCRSelectorSetPCR( sout_stream_t *stream, vlc_tick_t pcr )
+{
+    sout_stream_sys_t *sys = stream->p_sys;
+
+    vlc_tick_t min_pcr = pcr;
+    duplicated_stream_t *dup;
+    vlc_vector_foreach_ref( dup, &sys->streams )
+    {
+        if( dup->pcr_selector_ref == stream )
+            dup->pcr = pcr;
+        else
+            min_pcr = __MIN( min_pcr, dup->pcr );
+    }
+
+    /* One of the selector has not received a PCR yet and was defaulted to
+     * VLC_TICK_MIN. */
+    if( min_pcr == VLC_TICK_MIN )
+        return;
+
+    sout_StreamSetPCR( stream->p_next, min_pcr );
+
+    /* Reset all selectors PCR values. */
+    vlc_vector_foreach_ref( dup, &sys->streams )
+        dup->pcr = VLC_TICK_MIN;
+}
+
+static sout_stream_t *PCRSelectorNew( sout_stream_t *parent )
+{
+    sout_stream_t *selector =
+        sout_StreamNew( VLC_OBJECT(parent), "duplicate-pcr-select{}" );
+    if( unlikely(selector == NULL) )
+        return NULL;
+    
+    static const struct sout_stream_operations ops = {
+        .add = PCRSelectorAdd,
+        .del = PCRSelectorDel,
+        .control = PCRSelectorControl,
+        .send = PCRSelectorSend,
+        .flush = PCRSelectorFlush,
+        .set_pcr = PCRSelectorSetPCR,
+    };
+    selector->ops = &ops;
+    selector->p_sys = parent->p_sys;
+    
+    return selector;
+}
+
 /*****************************************************************************
  * Control
  *****************************************************************************/
@@ -159,15 +246,27 @@ static int Open( vlc_object_t *p_this )
 
     vlc_vector_init( &p_sys->streams );
 
+    p_stream->p_sys = p_sys;
+
     for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
     {
         if( !strncmp( p_cfg->psz_name, "dst", strlen( "dst" ) ) )
         {
-            duplicated_stream_t dup_stream = {0};
+            duplicated_stream_t dup_stream = { .pcr = VLC_TICK_MIN };
+
+            sout_stream_t *sink = NULL;
+            if( p_stream->p_next != NULL )
+            {
+                sink = PCRSelectorNew( p_stream );
+                if ( unlikely(sink == NULL) )
+                    goto nomem;
+                sink->p_next = p_stream->p_next;
+                dup_stream.pcr_selector_ref = sink;
+            }
 
             msg_Dbg( p_stream, " * adding `%s'", p_cfg->psz_value );
             dup_stream.stream = sout_StreamChainNew(
-                VLC_OBJECT(p_stream), p_cfg->psz_value, p_stream->p_next );
+                VLC_OBJECT(p_stream), p_cfg->psz_value, sink );
 
             if( dup_stream.stream != NULL )
             {
@@ -230,11 +329,9 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    p_stream->p_sys = p_sys;
     p_stream->ops = &ops;
     return VLC_SUCCESS;
 nomem:
-    p_stream->p_sys = p_sys;
     Close( p_stream );
     return VLC_ENOMEM;
 }
@@ -294,23 +391,24 @@ Add( sout_stream_t *p_stream, const es_format_t *p_fmt, const char *es_id )
 
             void *next_id = sout_StreamIdAdd( dup_stream->stream,
                                               p_fmt, dup_es_id );
-            if( next_id != NULL )
+            if( next_id == NULL )
             {
-                msg_Dbg( p_stream, "    - added for output %zu", idx );
-                const duplicated_id_t dup_id = {.id = next_id,
-                                                .es_id = dup_es_id,
-                                                .stream_owner =
-                                                    dup_stream->stream};
-                if( !vlc_vector_push(&id->dup_ids, dup_id) )
-                {
-                    sout_StreamIdDel( dup_stream->stream, next_id );
-                    free( dup_id.es_id );
-                    goto error;
-                }
+                free(dup_es_id);
+                msg_Dbg( p_stream, "    - failed for output %zu", idx);
+                continue;
             }
-            else
+
+            msg_Dbg( p_stream, "    - added for output %zu", idx );
+            const duplicated_id_t dup_id = {
+                .id = next_id,
+                .es_id = dup_es_id,
+                .stream_owner = dup_stream->stream,
+            };
+            if( !vlc_vector_push(&id->dup_ids, dup_id) )
             {
-                msg_Dbg( p_stream, "    - failed for output %zu", idx);
+                sout_StreamIdDel( dup_stream->stream, next_id );
+                free( dup_id.es_id );
+                goto error;
             }
         }
         else



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2baa2908b695b6db1c25e3596f579f75487c26f6...048441238c958be3ceaf1417eb1d0b198e3284fe

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2baa2908b695b6db1c25e3596f579f75487c26f6...048441238c958be3ceaf1417eb1d0b198e3284fe
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