[vlc-commits] mux: ogg: rewrite steam creation and ordering (fix #9731, fix #9732)

Francois Cartegnie git at videolan.org
Mon Nov 4 10:12:41 CET 2013


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Oct 25 17:24:07 2013 +0900| [8aa07faff01aa1ba560b1946230b4dcd03e7f335] | committer: Francois Cartegnie

mux: ogg: rewrite steam creation and ordering (fix #9731, fix #9732)

Ogg streams were invalid.
This patch ensures all streams have a way to end independently and
no other stream could start at arbitrary places. Also simplifies
a bit some code.

The ogg muxer suffers from an insufficient muxer cache value, and usually
starts streams before all streams have been declared.
The previous behaviour ( closing and restarting a new group of streams ) is kept
and fixed. But this is really not optimal.
We might need to consider increasing that cache for ogg.

It also handles correctly chained streams.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8aa07faff01aa1ba560b1946230b4dcd03e7f335
---

 modules/mux/ogg.c |  155 ++++++++++++++++++++++++++---------------------------
 1 file changed, 77 insertions(+), 78 deletions(-)

diff --git a/modules/mux/ogg.c b/modules/mux/ogg.c
index 37609aa..111c339 100644
--- a/modules/mux/ogg.c
+++ b/modules/mux/ogg.c
@@ -66,8 +66,7 @@ static int DelStream( sout_mux_t *, sout_input_t * );
 static int Mux      ( sout_mux_t * );
 static int MuxBlock ( sout_mux_t *, sout_input_t * );
 
-static block_t *OggCreateHeader( sout_mux_t * );
-static block_t *OggCreateFooter( sout_mux_t * );
+static block_t *OggCreateHeaders( sout_mux_t * );
 
 /*****************************************************************************
  * Misc declarations
@@ -147,6 +146,8 @@ typedef struct
 
     oggds_header_t *p_oggds_header;
     bool b_fisbone_done;
+    bool b_started;
+    bool b_finished;
 
 } ogg_stream_t;
 
@@ -159,6 +160,7 @@ struct sout_mux_sys_t
 
     /* number of logical streams pending to be added */
     int i_add_streams;
+    bool b_can_add_streams;
 
     /* logical streams pending to be deleted */
     int i_del_streams;
@@ -177,6 +179,7 @@ struct sout_mux_sys_t
 
 static void OggSetDate( block_t *, mtime_t , mtime_t  );
 static block_t *OggStreamFlush( sout_mux_t *, ogg_stream_state *, mtime_t );
+static block_t *OggCreateStreamFooter( sout_mux_t *p_mux, ogg_stream_t *p_stream );
 
 /*****************************************************************************
  * Open: Open muxer
@@ -193,6 +196,7 @@ static int Open( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_sys->i_streams      = 0;
     p_sys->i_add_streams  = 0;
+    p_sys->b_can_add_streams = true;
     p_sys->i_del_streams  = 0;
     p_sys->pp_del_streams = 0;
 
@@ -229,11 +233,16 @@ static void Close( vlc_object_t * p_this )
 
         /* Close the current ogg stream */
         msg_Dbg( p_mux, "writing footer" );
-        block_ChainAppend( &p_og, OggCreateFooter( p_mux ) );
+
+        for(int i = 0; i < p_mux->i_nb_inputs; i++ )
+        {
+            block_ChainAppend( &p_og, OggCreateStreamFooter( p_mux, (ogg_stream_t *) p_mux->pp_inputs[i]->p_sys ) );
+        }
 
         /* Remove deleted logical streams */
         for(int i = 0; i < p_sys->i_del_streams; i++ )
         {
+            block_ChainAppend( &p_og, OggCreateStreamFooter( p_mux, p_sys->pp_del_streams[i] ) );
             ogg_stream_clear( &p_sys->pp_del_streams[i]->os );
             FREENULL( p_sys->pp_del_streams[i]->p_oggds_header );
             FREENULL( p_sys->pp_del_streams[i] );
@@ -753,7 +762,7 @@ static int32_t OggFillDsHeader( uint8_t *p_buffer, oggds_header_t *p_oggds_heade
     return index;
 }
 
-static block_t *OggCreateHeader( sout_mux_t *p_mux )
+static block_t *OggCreateHeaders( sout_mux_t *p_mux )
 {
     block_t *p_hdr = NULL;
     block_t *p_og = NULL;
@@ -821,6 +830,7 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux )
             ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
             p_stream->b_new = false;
             p_stream->i_packet_no = 0;
+            p_stream->b_started = true;
 
             if( p_stream->i_fourcc == VLC_CODEC_VORBIS ||
                 p_stream->i_fourcc == VLC_CODEC_SPEEX ||
@@ -1047,66 +1057,30 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux )
     return p_hdr;
 }
 
-static block_t *OggCreateFooter( sout_mux_t *p_mux )
+static block_t *OggCreateStreamFooter( sout_mux_t *p_mux, ogg_stream_t *p_stream )
 {
-    sout_mux_sys_t *p_sys = p_mux->p_sys;
-    block_t *p_hdr = NULL;
-    block_t *p_og;
-    ogg_packet    op;
-    int     i;
-
-    /* flush all remaining data */
-    for( i = 0; i < p_mux->i_nb_inputs; i++ )
-    {
-        ogg_stream_t *p_stream = p_mux->pp_inputs[i]->p_sys;
-
-        p_stream->b_fisbone_done = false;
+    block_t *p_og, *p_hdr = NULL;
+    ogg_packet op;
 
-        /* skip newly added streams */
-        if( p_stream->b_new ) continue;
+    p_stream->b_fisbone_done = false;
 
-        if( ( p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ) ) )
-        {
-            OggSetDate( p_og, p_stream->i_dts, p_stream->i_length );
-            sout_AccessOutWrite( p_mux->p_access, p_og );
-        }
-    }
+    /* Write eos packet for stream. */
+    op.packet = NULL;
+    op.bytes  = 0;
+    op.b_o_s  = 0;
+    op.e_o_s  = 1;
+    op.granulepos = p_stream->u_last_granulepos;
+    op.packetno = p_stream->i_packet_no++;
+    ogg_stream_packetin( &p_stream->os, &op );
 
-    /* Write eos packets for each stream. */
-    for( i = 0; i < p_mux->i_nb_inputs; i++ )
+    /* flush it with all remaining data */
+    if( ( p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ) ) )
     {
-        ogg_stream_t *p_stream = p_mux->pp_inputs[i]->p_sys;
-
-        /* skip newly added streams */
-        if( p_stream->b_new ) continue;
-
-        op.packet = NULL;
-        op.bytes  = 0;
-        op.b_o_s  = 0;
-        op.e_o_s  = 1;
-        op.granulepos = p_stream->u_last_granulepos;
-        op.packetno = p_stream->i_packet_no++;
-        ogg_stream_packetin( &p_stream->os, &op );
-
-        p_og = OggStreamFlush( p_mux, &p_stream->os, 0 );
+        OggSetDate( p_og, p_stream->i_dts, p_stream->i_length );
         block_ChainAppend( &p_hdr, p_og );
-        ogg_stream_clear( &p_stream->os );
     }
 
-    for( i = 0; i < p_sys->i_del_streams; i++ )
-    {
-        op.packet = NULL;
-        op.bytes  = 0;
-        op.b_o_s  = 0;
-        op.e_o_s  = 1;
-        op.granulepos = p_sys->pp_del_streams[i]->u_last_granulepos;
-        op.packetno = p_sys->pp_del_streams[i]->i_packet_no++;
-        ogg_stream_packetin( &p_sys->pp_del_streams[i]->os, &op );
-
-        p_og = OggStreamFlush( p_mux, &p_sys->pp_del_streams[i]->os, 0 );
-        block_ChainAppend( &p_hdr, p_og );
-        ogg_stream_clear( &p_sys->pp_del_streams[i]->os );
-    }
+    ogg_stream_clear( &p_stream->os );
 
     return p_hdr;
 }
@@ -1144,51 +1118,76 @@ static int Mux( sout_mux_t *p_mux )
     block_t        *p_og = NULL;
     mtime_t        i_dts;
 
-    if( p_sys->i_add_streams || p_sys->i_del_streams )
+    /* End any stream that ends in that group */
+    if ( p_sys->i_del_streams )
     {
-        /* Open new ogg stream */
-        if( sout_MuxGetStream( p_mux, 1, &i_dts) < 0 )
+        /* Remove deleted logical streams */
+        for( int i = 0; i < p_sys->i_del_streams; i++ )
         {
-            msg_Dbg( p_mux, "waiting for data..." );
-            return VLC_SUCCESS;
+            block_ChainAppend( &p_og, OggCreateStreamFooter( p_mux, p_sys->pp_del_streams[i] ) );
+            FREENULL( p_sys->pp_del_streams[i]->p_oggds_header );
+            FREENULL( p_sys->pp_del_streams[i] );
         }
+        FREENULL( p_sys->pp_del_streams );
+    }
 
-        if( p_sys->i_streams )
-        {
-            /* Close current ogg stream */
-            int i;
+    if ( p_sys->i_streams == 0 )
+    {
+        /* All streams have been deleted, or none have ever been created
+           From this point, we are allowed to start a new group of logical streams */
+        p_sys->skeleton.b_head_done = false;
+        p_sys->b_can_add_streams = true;
+    }
 
+    if ( p_sys->i_add_streams )
+    {
+        if ( !p_sys->b_can_add_streams )
+        {
+            msg_Warn( p_mux, "Can't add new stream: Considerer increasing sout-mux-caching variable");
+            msg_Warn( p_mux, "Resetting and setting new identity to current streams");
             p_sys->skeleton.b_head_done = false;
-
-            msg_Dbg( p_mux, "writing footer" );
-            block_ChainAppend( &p_og, OggCreateFooter( p_mux ) );
-
-            /* Remove deleted logical streams */
-            for( i = 0; i < p_sys->i_del_streams; i++ )
+            /* resetting all active streams */
+            for ( int i=0; i < p_mux->p_sys->i_streams; i++ )
             {
-                FREENULL( p_sys->pp_del_streams[i]->p_oggds_header );
-                FREENULL( p_sys->pp_del_streams[i] );
+                ogg_stream_t * p_stream = (ogg_stream_t *) p_mux->pp_inputs[i]->p_sys;
+                if ( p_stream->b_finished || !p_stream->b_started ) continue;
+                block_ChainAppend( &p_og, OggCreateStreamFooter( p_mux, p_stream ) );
+                p_stream->i_serial_no = p_sys->i_next_serial_no++;
+                p_stream->i_packet_no = 0;
+                p_stream->b_finished = true;
             }
-            FREENULL( p_sys->pp_del_streams );
-            p_sys->i_streams = 0;
+            p_sys->b_can_add_streams = true;
+            sout_AccessOutWrite( p_mux->p_access, p_og );
+            p_og = NULL;
         }
 
-        msg_Dbg( p_mux, "writing header" );
+        /* Open new ogg stream */
+        if( sout_MuxGetStream( p_mux, 1, &i_dts) < 0 )
+        {
+            msg_Dbg( p_mux, "waiting for data..." );
+            return VLC_SUCCESS;
+        }
+        msg_Dbg( p_mux, "writing streams headers" );
         p_sys->i_start_dts = i_dts;
         p_sys->i_streams = p_mux->i_nb_inputs;
         p_sys->i_del_streams = 0;
         p_sys->i_add_streams = 0;
-        block_t *p_header = OggCreateHeader( p_mux );
+        block_t *p_header = OggCreateHeaders( p_mux );
         if( !p_header )
             return VLC_ENOMEM;
         block_ChainAppend( &p_og, p_header );
 
-        /* Write header and/or footer */
+        /* Since we started sending secondaryheader or data pages,
+             * we're no longer allowed to create new streams, until all streams end */
+        p_sys->b_can_add_streams = false;
+
+        /* Write header */
         OggSetDate( p_og, i_dts, 0 );
         sout_AccessOutWrite( p_mux->p_access, p_og );
         p_og = NULL;
     }
 
+    /* Do the regular data mux thing */
     for( ;; )
     {
         int i_stream = sout_MuxGetStream( p_mux, 1, NULL );



More information about the vlc-commits mailing list