[vlc-commits] demux: webvtt: add cue stream demuxer

Francois Cartegnie git at videolan.org
Fri Nov 3 17:46:50 CET 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Nov  3 12:43:29 2017 +0100| [6b6d31cb6a2e43ce0e5d8d935522d9c08114fdd9] | committer: Francois Cartegnie

demux: webvtt: add cue stream demuxer

Different demux, no cues preloading.
Allows chaining WEBVTT for HLS split segments.

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

 modules/codec/webvtt/webvtt.c |   8 +++
 modules/codec/webvtt/webvtt.h |   1 +
 modules/demux/webvtt.c        | 161 +++++++++++++++++++++++++++++++++++-------
 3 files changed, 146 insertions(+), 24 deletions(-)

diff --git a/modules/codec/webvtt/webvtt.c b/modules/codec/webvtt/webvtt.c
index dda86edaa9..8172c1cf1c 100644
--- a/modules/codec/webvtt/webvtt.c
+++ b/modules/codec/webvtt/webvtt.c
@@ -50,6 +50,14 @@ vlc_module_begin ()
         set_subcategory( SUBCAT_INPUT_DEMUX )
         set_callbacks( OpenDemux, CloseDemux )
         add_shortcut( "webvtt" )
+    add_submodule()
+        set_shortname( "WEBVTT" )
+        set_description( N_("WEBVTT subtitles parser") )
+        set_capability( "demux", 0 )
+        set_category( CAT_INPUT )
+        set_subcategory( SUBCAT_INPUT_DEMUX )
+        set_callbacks( OpenDemuxStream, CloseDemux )
+        add_shortcut( "webvttstream" )
 vlc_module_end ()
 
 struct webvtt_text_parser_t
diff --git a/modules/codec/webvtt/webvtt.h b/modules/codec/webvtt/webvtt.h
index a8a5158c84..1337be41be 100644
--- a/modules/codec/webvtt/webvtt.h
+++ b/modules/codec/webvtt/webvtt.h
@@ -24,6 +24,7 @@ int  OpenDecoder   ( vlc_object_t * );
 void CloseDecoder  ( vlc_object_t * );
 
 int  OpenDemux     ( vlc_object_t * );
+int  OpenDemuxStream (vlc_object_t *);
 void CloseDemux    ( vlc_object_t * );
 
 typedef struct webvtt_text_parser_t webvtt_text_parser_t;
diff --git a/modules/demux/webvtt.c b/modules/demux/webvtt.c
index 3f95b57187..6ad9226f42 100644
--- a/modules/demux/webvtt.c
+++ b/modules/demux/webvtt.c
@@ -57,10 +57,9 @@ struct demux_sys_t
         size_t  i_count;
         size_t  i_current;
     } cues;
-};
 
-static int Demux( demux_t * );
-static int Control( demux_t *, int, va_list );
+    webvtt_text_parser_t *p_streamparser;
+};
 
 /*****************************************************************************
  *
@@ -169,6 +168,9 @@ static void memstream_Grab( struct vlc_memstream *ms, void **pp, size_t *pi )
     }
 }
 
+/*****************************************************************************
+ * Seekable demux Open() parser callbacks
+ *****************************************************************************/
 struct callback_ctx
 {
     demux_t *p_demux;
@@ -232,6 +234,44 @@ static void ParserHeaderHandler( void *priv, enum webvtt_header_line_e s,
         memstream_Append( &ctx->regions, psz_line );
 }
 
+/*****************************************************************************
+ * Streamed cues DemuxStream() parser callbacks
+ *****************************************************************************/
+
+static webvtt_cue_t * StreamParserGetCueHandler( void *priv )
+{
+    VLC_UNUSED(priv);
+    return malloc( sizeof(webvtt_cue_t) );
+}
+
+static void StreamParserCueDoneHandler( void *priv, webvtt_cue_t *p_cue )
+{
+    demux_t *p_demux = (demux_t *) priv;
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    if( p_cue->psz_text )
+    {
+        block_t *p_block = ConvertWEBVTT( p_cue, true );
+        if( p_block )
+        {
+            if ( p_sys->b_first_time )
+            {
+                es_out_SetPCR( p_demux->out, p_cue->i_start + VLC_TS_0 );
+                p_sys->b_first_time = false;
+            }
+            p_sys->i_next_demux_time = p_cue->i_start;
+            p_block->i_dts =
+                    p_block->i_pts = VLC_TS_0 + p_cue->i_start;
+            if( p_cue->i_stop >= 0 && p_cue->i_stop >= p_cue->i_start )
+                p_block->i_length = p_cue->i_stop - p_cue->i_start;
+            es_out_Send( p_demux->out, p_sys->es, p_block );
+            es_out_SetPCR( p_demux->out, p_cue->i_start + VLC_TS_0 );
+        }
+    }
+    webvtt_cue_Clean( p_cue );
+    free( p_cue );
+}
+
 static int ReadWEBVTT( demux_t *p_demux )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
@@ -366,6 +406,27 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
     return VLC_EGENERIC;
 }
 
+static int ControlStream( demux_t *p_demux, int i_query, va_list args )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    int64_t *pi64;
+
+    switch( i_query )
+    {
+        case DEMUX_GET_TIME:
+            pi64 = va_arg( args, int64_t * );
+            if( p_sys->i_next_demux_time != VLC_TS_INVALID )
+            {
+                *pi64 = p_sys->i_next_demux_time;
+                return VLC_SUCCESS;
+            }
+        default:
+            break;
+    }
+
+    return VLC_EGENERIC;
+}
+
 /*****************************************************************************
  * Demux: Send subtitle to decoder
  *****************************************************************************/
@@ -419,15 +480,21 @@ static int Demux( demux_t *p_demux )
     return VLC_DEMUXER_SUCCESS;
 }
 
+static int DemuxStream( demux_t *p_demux )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    char *psz_line = vlc_stream_ReadLine( p_demux->s );
+    webvtt_text_parser_Feed( p_sys->p_streamparser, psz_line );
+
+    return ( psz_line == NULL ) ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS;
+}
 
 /*****************************************************************************
- * Module initializer
+ * Module initializers common
  *****************************************************************************/
-int OpenDemux ( vlc_object_t *p_this )
+static int ProbeWEBVTT( demux_t *p_demux )
 {
-    demux_t        *p_demux = (demux_t*)p_this;
-    demux_sys_t    *p_sys;
-
     const uint8_t *p_peek;
     size_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 16 );
     if( i_peek < 16 )
@@ -447,27 +514,28 @@ int OpenDemux ( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Module initializers
+ *****************************************************************************/
+int OpenDemux ( vlc_object_t *p_this )
+{
+    demux_t        *p_demux = (demux_t*)p_this;
+    demux_sys_t    *p_sys;
+
+    int i_ret = ProbeWEBVTT( p_demux );
+    if( i_ret != VLC_SUCCESS )
+        return i_ret;
+
     p_demux->pf_demux = Demux;
     p_demux->pf_control = Control;
-    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
+
+    p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
     if( p_sys == NULL )
         return VLC_ENOMEM;
 
-    p_sys->i_next_block_flags = 0;
-    p_sys->i_next_demux_time = 0;
-    p_sys->i_length = 0;
-    p_sys->b_slave = false;
-
-    p_sys->regions_headers.p_data = NULL;
-    p_sys->regions_headers.i_data = 0;
-    p_sys->styles_headers.p_data = NULL;
-    p_sys->styles_headers.i_data = 0;
-
-    p_sys->cues.i_count = 0;
-    p_sys->cues.i_alloc = 0;
-    p_sys->cues.p_array = NULL;
-    p_sys->cues.i_current = 0;
-
     if( ReadWEBVTT( p_demux ) != VLC_SUCCESS )
     {
         CloseDemux( p_this );
@@ -490,6 +558,45 @@ int OpenDemux ( vlc_object_t *p_this )
     return VLC_SUCCESS;
 }
 
+int OpenDemuxStream ( vlc_object_t *p_this )
+{
+    demux_t        *p_demux = (demux_t*)p_this;
+    demux_sys_t    *p_sys;
+
+    int i_ret = ProbeWEBVTT( p_demux );
+    if( i_ret != VLC_SUCCESS )
+        return i_ret;
+
+    p_demux->pf_demux = DemuxStream;
+    p_demux->pf_control = ControlStream;
+
+    p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
+    if( p_sys == NULL )
+        return VLC_ENOMEM;
+
+    p_sys->p_streamparser = webvtt_text_parser_New( p_demux,
+                                          StreamParserGetCueHandler,
+                                          StreamParserCueDoneHandler,
+                                          NULL );
+    if( !p_sys->p_streamparser )
+    {
+        CloseDemux( p_this );
+        return VLC_EGENERIC;
+    }
+
+    es_format_t fmt;
+    es_format_Init( &fmt, SPU_ES, VLC_CODEC_WEBVTT );
+    p_sys->es = es_out_Add( p_demux->out, &fmt );
+    es_format_Clean( &fmt );
+    if( p_sys->es == NULL )
+    {
+        CloseDemux( p_this );
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
 /*****************************************************************************
  * Close: Close subtitle demux
  *****************************************************************************/
@@ -502,5 +609,11 @@ void CloseDemux( vlc_object_t *p_this )
         webvtt_cue_Clean( &p_sys->cues.p_array[i] );
     free( p_sys->cues.p_array );
 
+    if( p_sys->p_streamparser )
+    {
+        webvtt_text_parser_Feed( p_sys->p_streamparser, NULL );
+        webvtt_text_parser_Delete( p_sys->p_streamparser );
+    }
+
     free( p_sys );
 }



More information about the vlc-commits mailing list