[vlc-commits] codec: add tx3g encoder

Francois Cartegnie git at videolan.org
Wed Jan 17 20:28:07 CET 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Jan  9 11:33:27 2018 +0100| [8d23d9d398a2bd8d0ff7b77701098f6a5043d7ee] | committer: Francois Cartegnie

codec: add tx3g encoder

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

 modules/MODULES_LIST     |   2 +-
 modules/codec/substx3g.c | 206 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 194 insertions(+), 14 deletions(-)

diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST
index e855fa462a..95ebac1183 100644
--- a/modules/MODULES_LIST
+++ b/modules/MODULES_LIST
@@ -394,7 +394,7 @@ $Id$
  * stream_out_transcode: audio & video transcoder
  * subsdec: a codec to output textual subtitles
  * subsdelay: subtitles delay filter
- * substx3g: tx3g styled subtitles decoder
+ * substx3g: tx3g styled subtitles encoder and decoder
  * subsusf: a demuxer for USF subtitles
  * subtitle: a demuxer for subtitle files
  * svcdsub: SVCD subtitles decoder
diff --git a/modules/codec/substx3g.c b/modules/codec/substx3g.c
index 4f1623a09e..8904d200a6 100644
--- a/modules/codec/substx3g.c
+++ b/modules/codec/substx3g.c
@@ -34,9 +34,13 @@
 /*****************************************************************************
  * Module descriptor.
  *****************************************************************************/
-static int Open ( vlc_object_t * );
-static void Close ( vlc_object_t * );
+static int OpenDecoder ( vlc_object_t * );
+static void CloseDecoder ( vlc_object_t * );
 static int Decode( decoder_t *, block_t * );
+#ifdef ENABLE_SOUT
+static int OpenEncoder ( vlc_object_t * );
+static block_t * Encode( encoder_t *, subpicture_t * );
+#endif
 
 vlc_module_begin ()
     set_description( N_("tx3g subtitles decoder") )
@@ -44,7 +48,14 @@ vlc_module_begin ()
     set_capability( "spu decoder", 100 )
     set_category( CAT_INPUT )
     set_subcategory( SUBCAT_INPUT_SCODEC )
-    set_callbacks( Open, Close )
+    set_callbacks( OpenDecoder, CloseDecoder )
+#ifdef ENABLE_SOUT
+    add_submodule ()
+        set_description( N_("tx3g subtitles encoder") )
+        set_shortname( N_("tx3g subtitles encoder") )
+        set_capability( "encoder", 101 )
+        set_callbacks( OpenEncoder, NULL )
+#endif
 vlc_module_end ()
 
 /****************************************************************************
@@ -59,7 +70,7 @@ vlc_module_end ()
 #define FONT_FACE_ITALIC    0x2
 #define FONT_FACE_UNDERLINE 0x4
 
-static int ConvertFlags( int i_atomflags )
+static int ConvertToVLCFlags( int i_atomflags )
 {
     int i_vlcstyles_flags = 0;
     if ( i_atomflags & FONT_FACE_BOLD )
@@ -379,7 +390,7 @@ static int Decode( decoder_t *p_dec, block_t *p_block )
                     text_style_t *p_style = text_style_Create( STYLE_NO_DEFAULTS );
                     if( p_style )
                     {
-                        if( (p_style->i_style_flags = ConvertFlags( it.p_payload[6] )) )
+                        if( (p_style->i_style_flags = ConvertToVLCFlags( it.p_payload[6] )) )
                             p_style->i_features |= STYLE_HAS_FLAGS;
                         p_style->i_font_size = it.p_payload[7];
                         p_style->i_font_color = GetDWBE(&it.p_payload[8]) >> 8;// RGBA -> RGB
@@ -456,7 +467,7 @@ static void ParseExtradataTx3g( decoder_t *p_dec )
     /* BoxRecord @10 */
 
     /* StyleRecord @18 */
-    p_style->i_style_flags = ConvertFlags( p_extra[24] );
+    p_style->i_style_flags = ConvertToVLCFlags( p_extra[24] );
     if( p_style->i_style_flags )
         p_style->i_features |= STYLE_HAS_FLAGS;
     p_style->i_font_size = p_extra[25];
@@ -489,7 +500,7 @@ static void ParseExtradataTextMedia( decoder_t *p_dec )
     /* Font # @30 */
 
     /* Font Face @32 */
-    p_style->i_style_flags = ConvertFlags( GetWBE(&p_extra[32]) );
+    p_style->i_style_flags = ConvertToVLCFlags( GetWBE(&p_extra[32]) );
     if( p_style->i_style_flags )
         p_style->i_features |= STYLE_HAS_FLAGS;
     /* Reserved 8 @34 */
@@ -503,18 +514,15 @@ static void ParseExtradataTextMedia( decoder_t *p_dec )
     /* FontName Pascal (8 + string) @43 */
 }
 /*****************************************************************************
- * Close: clean decoder
+ * Decoder entry/exit points
  *****************************************************************************/
-static void Close( vlc_object_t *p_this )
+static void CloseDecoder( vlc_object_t *p_this )
 {
     decoder_t     *p_dec = (decoder_t *) p_this;
     text_style_Delete( (text_style_t *) p_dec->p_sys );
 }
 
-/*****************************************************************************
- * Open: probe the decoder and return score
- *****************************************************************************/
-static int Open( vlc_object_t *p_this )
+static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t     *p_dec = (decoder_t *) p_this;
 
@@ -537,3 +545,175 @@ static int Open( vlc_object_t *p_this )
 
     return VLC_SUCCESS;
 }
+
+/*****************************************************************************
+ * Encoder entry/exit
+ *****************************************************************************/
+#ifdef ENABLE_SOUT
+static void FillExtradataTx3g( void **pp_extra, int *pi_extra )
+{
+    size_t i_extra = 32 + 37;
+    uint8_t *p_extra = calloc( 1, i_extra );
+    if( p_extra )
+    {
+        SetDWBE( &p_extra[6],  0x000000FFU ); /* bgcolor */
+        p_extra[25] = STYLE_DEFAULT_FONT_SIZE;
+        SetDWBE( &p_extra[26], 0xFFFFFFFFU ); /* fgcolor */
+
+        /* FontTableBox */
+        SetDWBE(&p_extra[32], 8 + 2 + 6 + 11 + 10);
+        memcpy(&p_extra[36], "ftab", 4);
+
+        SetWBE(&p_extra[40], 3); /* entry count */
+        /* Font Record 0 */
+        p_extra[41] = 5;
+        memcpy(&p_extra[42], "Serif", 5);
+        /* Font Record 1 */
+        p_extra[47] = 10;
+        memcpy(&p_extra[48], "Sans-serif", 10);
+        /* Font Record 2 */
+        p_extra[58] = 9;
+        memcpy(&p_extra[59], "Monospace", 9);
+
+        *pp_extra = p_extra;
+        *pi_extra = i_extra;
+    }
+}
+
+static int OpenEncoder( vlc_object_t *p_this )
+{
+    encoder_t *p_enc = (encoder_t *)p_this;
+
+    if( p_enc->fmt_out.i_codec != VLC_CODEC_TX3G )
+        return VLC_EGENERIC;
+
+    p_enc->fmt_in.i_codec = VLC_CODEC_TEXT;
+
+    p_enc->p_sys = NULL;
+
+    p_enc->pf_encode_sub = Encode;
+    p_enc->fmt_out.i_cat = SPU_ES;
+
+    if( !p_enc->fmt_out.i_extra )
+        FillExtradataTx3g( &p_enc->fmt_out.p_extra, &p_enc->fmt_out.i_extra );
+
+    return VLC_SUCCESS;
+}
+
+static int ConvertFromVLCFlags( const text_style_t *p_style )
+{
+    int i_atomflags = 0;
+    if( p_style->i_features & STYLE_HAS_FLAGS )
+    {
+        if ( p_style->i_style_flags & STYLE_BOLD )
+            i_atomflags |= FONT_FACE_BOLD;
+        if ( p_style->i_style_flags & STYLE_ITALIC )
+            i_atomflags |= FONT_FACE_ITALIC;
+        if ( p_style->i_style_flags & STYLE_UNDERLINE )
+            i_atomflags |= FONT_FACE_UNDERLINE;
+    }
+    return i_atomflags;
+}
+
+static uint32_t ConvertFromVLCColor( const text_style_t *p_style )
+{
+    uint32_t rgba = 0;
+    if( p_style->i_features & STYLE_HAS_FONT_COLOR )
+        rgba = ((uint32_t)p_style->i_font_color) << 8;
+    else
+        rgba = 0xFFFFFF00U;
+    if( p_style->i_features & STYLE_HAS_FONT_ALPHA )
+        rgba |= p_style->i_font_alpha;
+    else
+        rgba |= 0xFF;
+    return rgba;
+}
+
+static bool NeedStyling( const text_segment_t *p_segment )
+{
+    const text_style_t *p_style = p_segment->style;
+    if( !p_style )
+        return false;
+
+    if( p_style->i_features & STYLE_HAS_FLAGS )
+    {
+        if( p_style->i_style_flags & (STYLE_BOLD|STYLE_ITALIC|STYLE_UNDERLINE) )
+            return true;
+    }
+
+    if( p_style->i_features & (STYLE_HAS_FONT_COLOR|STYLE_HAS_FONT_ALPHA) )
+        return true;
+
+    return false;
+}
+
+static block_t *GetStylBlock( const text_segment_t *p_segment, size_t i_styles )
+{
+    size_t i_start = 0;
+    block_t *p_styl = block_Alloc( 10 + 12 * i_styles );
+    if( p_styl )
+    {
+        SetDWBE( p_styl->p_buffer, p_styl->i_buffer );
+        memcpy( &p_styl->p_buffer[4], "styl", 4 );
+        SetWBE( &p_styl->p_buffer[8], i_styles );
+        p_styl->i_buffer = 10;
+        for( ; p_segment; p_segment = p_segment->p_next )
+        {
+            size_t i_len = str8len( p_segment->psz_text );
+            if( NeedStyling( p_segment ) )
+            {
+                uint8_t *p = &p_styl->p_buffer[p_styl->i_buffer];
+                SetWBE( &p[0], i_start );
+                SetWBE( &p[2], i_start + i_len );
+                SetWBE( &p[4], 0 );
+                p[6] = ConvertFromVLCFlags( p_segment->style );
+                p[7] = STYLE_DEFAULT_FONT_SIZE;
+                SetDWBE(&p[8], ConvertFromVLCColor( p_segment->style ) );
+                p_styl->i_buffer += 12;
+            }
+            i_start += i_len;
+        }
+    }
+    return p_styl;
+}
+
+static block_t * Encode( encoder_t *p_enc, subpicture_t *p_spu )
+{
+    VLC_UNUSED(p_enc);
+    const text_segment_t *p_segments = (p_spu->p_region)
+                                     ? p_spu->p_region->p_text
+                                     : NULL;
+    size_t i_len = 0;
+    size_t i_styles = 0;
+
+    for(const text_segment_t  *p_segment = p_segments;
+                               p_segment; p_segment = p_segment->p_next )
+    {
+        if( p_segment->style )
+            i_styles++;
+        i_len += strlen( p_segment->psz_text );
+    }
+
+    block_t *p_block = block_Alloc( i_len + 2 );
+    if( p_block )
+    {
+        SetWBE(p_block->p_buffer, i_len);
+        p_block->i_buffer = 2;
+        for(const text_segment_t  *p_segment = p_segments;
+                                   p_segment; p_segment = p_segment->p_next )
+        {
+            size_t i_seglen = strlen(p_segment->psz_text);
+            memcpy(&p_block->p_buffer[p_block->i_buffer],
+                    p_segment->psz_text, i_seglen);
+            p_block->i_buffer += i_seglen;
+        }
+        p_block->i_dts = p_block->i_pts = p_spu->i_start;
+        p_block->i_length = p_spu->i_stop - p_spu->i_start;
+
+        if( i_styles > 0 )
+            p_block->p_next = GetStylBlock( p_segments, i_styles );
+    }
+
+    return block_ChainGather( p_block );
+}
+#endif



More information about the vlc-commits mailing list