[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