[vlc-commits] demux: subtitle: add support for SCC

Francois Cartegnie git at videolan.org
Tue Aug 29 08:42:45 CEST 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Aug 28 21:34:57 2017 +0200| [f97ba7b82dcf3b2964d8e990398f94ba43b93369] | committer: Francois Cartegnie

demux: subtitle: add support for SCC

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

 NEWS                     |   1 +
 include/vlc_input_item.h |   3 +-
 modules/demux/subtitle.c | 133 +++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 115 insertions(+), 22 deletions(-)

diff --git a/NEWS b/NEWS
index 9eece2102a..fd309e300b 100644
--- a/NEWS
+++ b/NEWS
@@ -129,6 +129,7 @@ Demuxers:
  * Support multi-channel WAV without channel-maps
  * Rewrite MKV seeking
  * Support for TTML and WebVTT in ISOBMF/MP4 and DASH
+ * Support for Scenarist Closed Caption
  * Fix Quicktime Mp4 inside MKV and unpacketized VC1
  * Support for isofLaC
  * Improved fLaC seeking
diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h
index d820a9fc95..5656dc6c2c 100644
--- a/include/vlc_input_item.h
+++ b/include/vlc_input_item.h
@@ -149,7 +149,8 @@ enum slave_priority
     "usf", "jss",  "cdg", \
     "psb", "mpsub","mpl2", \
     "pjs", "dks", "stl", \
-    "vtt", "sbv", "ttml"
+    "vtt", "sbv", "ttml" \
+    "scc"
 #define SLAVE_AUDIO_EXTENSIONS \
     "ac3", "m4a", "aac", \
     "eac3",  "dtshd", "flac", \
diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c
index fd3b7b77a2..fbd6ef4b6d 100644
--- a/modules/demux/subtitle.c
+++ b/modules/demux/subtitle.c
@@ -115,7 +115,8 @@ enum subtitle_type_e
     SUB_TYPE_SUBVIEW1, /* SUBVIEWER 1 - mplayer calls it subrip09,
                          and Gnome subtitles SubViewer 1.0 */
     SUB_TYPE_VTT,
-    SUB_TYPE_SBV
+    SUB_TYPE_SBV,
+    SUB_TYPE_SCC,      /* Scenarist Closed Caption */
 };
 
 typedef struct
@@ -181,6 +182,8 @@ struct demux_sys_t
 
     /* */
     subs_properties_t props;
+
+    block_t * (*pf_convert)( const subtitle_t * );
 };
 
 static int  ParseMicroDvd   ( vlc_object_t *, subs_properties_t *, text_t *, subtitle_t *, size_t );
@@ -200,6 +203,7 @@ static int  ParseRealText   ( vlc_object_t *, subs_properties_t *, text_t *, sub
 static int  ParseDKS        ( vlc_object_t *, subs_properties_t *, text_t *, subtitle_t *, size_t );
 static int  ParseSubViewer1 ( vlc_object_t *, subs_properties_t *, text_t *, subtitle_t *, size_t );
 static int  ParseCommonVTTSBV( vlc_object_t *, subs_properties_t *, text_t *, subtitle_t *, size_t );
+static int  ParseSCC        ( vlc_object_t *, subs_properties_t *, text_t *, subtitle_t *, size_t );
 
 static const struct
 {
@@ -229,6 +233,7 @@ static const struct
     { "subviewer1", SUB_TYPE_SUBVIEW1,    "Subviewer 1", ParseSubViewer1 },
     { "text/vtt",   SUB_TYPE_VTT,         "WebVTT",      ParseCommonVTTSBV },
     { "sbv",        SUB_TYPE_SBV,         "SBV",         ParseCommonVTTSBV },
+    { "scc",        SUB_TYPE_SCC,         "SCC",         ParseSCC },
     { NULL,         SUB_TYPE_UNKNOWN,     "Unknown",     NULL }
 };
 /* When adding support for more formats, be sure to add their file extension
@@ -242,6 +247,52 @@ static void Fix( demux_t * );
 static char * get_language_from_filename( const char * );
 
 /*****************************************************************************
+ * Decoder format output function
+ *****************************************************************************/
+
+static block_t *ToTextBlock( const subtitle_t *p_subtitle )
+{
+    block_t *p_block;
+    size_t i_len = strlen( p_subtitle->psz_text ) + 1;
+
+    if( i_len <= 1 || !(p_block = block_Alloc( i_len )) )
+        return NULL;
+
+    memcpy( p_block->p_buffer, p_subtitle->psz_text, i_len );
+
+    return p_block;
+}
+
+static block_t *ToEIA608Block( const subtitle_t *p_subtitle )
+{
+    block_t *p_block;
+    const size_t i_len = strlen( p_subtitle->psz_text );
+    const size_t i_block = (1 + i_len / 5) * 3;
+
+    if( i_len < 4 || !(p_block = block_Alloc( i_block )) )
+        return NULL;
+
+    p_block->i_buffer = 0;
+
+    char *saveptr = NULL;
+    char *psz_tok = strtok_r( p_subtitle->psz_text, " ", &saveptr );
+    unsigned a, b;
+    while( psz_tok &&
+           sscanf( psz_tok, "%2x%2x", &a, &b ) == 2 &&
+           i_block - p_block->i_buffer >= 3 )
+    {
+        uint8_t *p_data = &p_block->p_buffer[p_block->i_buffer];
+        p_data[0] = 0xFC;
+        p_data[1] = a;
+        p_data[2] = b;
+        p_block->i_buffer += 3;
+        psz_tok = strtok_r( NULL, " ", &saveptr );
+    }
+
+    return p_block;
+}
+
+/*****************************************************************************
  * Module initializer
  *****************************************************************************/
 static int Open ( vlc_object_t *p_this )
@@ -269,6 +320,8 @@ static int Open ( vlc_object_t *p_this )
     p_sys->b_first_time = true;
     p_sys->i_next_demux_date = 0;
 
+    p_sys->pf_convert = ToTextBlock;
+
     p_sys->subtitles.i_current= 0;
     p_sys->subtitles.i_count  = 0;
     p_sys->subtitles.p_array  = NULL;
@@ -565,6 +618,12 @@ static int Open ( vlc_object_t *p_this )
                 p_sys->props.i_type = SUB_TYPE_VTT;
                 break;
             }
+            else if( !strncasecmp( s, "Scenarist_SCC V1.0", 18 ) )
+            {
+                p_sys->props.i_type = SUB_TYPE_SCC;
+                p_sys->pf_convert = ToEIA608Block;
+                break;
+            }
 
             free( s );
             s = NULL;
@@ -653,6 +712,10 @@ static int Open ( vlc_object_t *p_this )
         Fix( p_demux );
         es_format_Init( &fmt, SPU_ES, VLC_CODEC_SSA );
     }
+    else if( p_sys->props.i_type == SUB_TYPE_SCC )
+    {
+        es_format_Init( &fmt, SPU_ES, VLC_CODEC_EIA608_1 );
+    }
     else
         es_format_Init( &fmt, SPU_ES, VLC_CODEC_SUBT );
 
@@ -816,30 +879,20 @@ static int Demux( demux_t *p_demux )
             p_sys->b_first_time = false;
         }
 
-        block_t *p_block;
-        size_t i_len = strlen( p_subtitle->psz_text ) + 1;
-
-        if( i_len <= 1 || p_subtitle->i_start < 0 )
+        if( p_subtitle->i_start >= 0 )
         {
-            p_sys->subtitles.i_current++;
-            continue;
-        }
+            block_t *p_block = p_sys->pf_convert( p_subtitle );
+            if( p_block )
+            {
+                p_block->i_dts =
+                p_block->i_pts = VLC_TS_0 + p_subtitle->i_start;
+                if( p_subtitle->i_stop >= 0 && p_subtitle->i_stop >= p_subtitle->i_start )
+                    p_block->i_length = p_subtitle->i_stop - p_subtitle->i_start;
 
-        if( ( p_block = block_Alloc( i_len ) ) == NULL )
-        {
-            p_sys->subtitles.i_current++;
-            continue;
+                es_out_Send( p_demux->out, p_sys->es, p_block );
+            }
         }
 
-        p_block->i_dts =
-        p_block->i_pts = VLC_TS_0 + p_subtitle->i_start;
-        if( p_subtitle->i_stop >= 0 && p_subtitle->i_stop >= p_subtitle->i_start )
-            p_block->i_length = p_subtitle->i_stop - p_subtitle->i_start;
-
-        memcpy( p_block->p_buffer, p_subtitle->psz_text, i_len );
-
-        es_out_Send( p_demux->out, p_sys->es, p_block );
-
         p_sys->subtitles.i_current++;
     }
 
@@ -2355,6 +2408,44 @@ static int ParseCommonVTTSBV( vlc_object_t *p_obj, subs_properties_t *p_props,
     }
 }
 
+static int ParseSCC( vlc_object_t *p_obj, subs_properties_t *p_props,
+                     text_t *txt, subtitle_t *p_subtitle, size_t i_idx )
+{
+    VLC_UNUSED(p_obj);
+    VLC_UNUSED( i_idx );
+    VLC_UNUSED( p_props );
+
+    for( ;; )
+    {
+        const char *psz_line = TextGetLine( txt );
+        if( !psz_line )
+            return VLC_EGENERIC;
+
+        unsigned h, m, s, f;
+        if( sscanf( psz_line, "%u:%u:%u:%u ", &h, &m, &s, &f ) != 4 )
+            continue;
+
+        p_subtitle->i_start = CLOCK_FREQ * ( h * 3600 + m * 60 + s ) +
+                              f * p_props->i_microsecperframe;
+        p_subtitle->i_stop = -1;
+
+        const char *psz_text = strchr( psz_line, '\t' );
+        if( !psz_text && !(psz_text = strchr( psz_line, ' ' )) )
+            continue;
+
+        if ( psz_text[1] == '\0' )
+            continue;
+
+        p_subtitle->psz_text = strdup( psz_text + 1 );
+        if( !p_subtitle->psz_text )
+            return VLC_ENOMEM;
+
+        break;
+    }
+
+    return VLC_SUCCESS;
+}
+
 /* Matches filename.xx.srt */
 static char * get_language_from_filename( const char * psz_sub_file )
 {



More information about the vlc-commits mailing list