[vlc-commits] ttml: fix bnf timing parsing

Francois Cartegnie git at videolan.org
Thu Mar 2 20:01:02 CET 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Mar  2 19:57:15 2017 +0100| [989bc9d662bc982613b3264e6ecf192687ba6a52] | committer: Francois Cartegnie

ttml: fix bnf timing parsing

"this is left as an exercise for the reader"

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

 modules/codec/ttml/ttml.c | 62 ++++++++++++++++++++++++++++++++++++++---------
 modules/codec/ttml/ttml.h | 12 ++++-----
 modules/demux/ttml.c      | 31 ++++++++++++++++++++----
 3 files changed, 83 insertions(+), 22 deletions(-)

diff --git a/modules/codec/ttml/ttml.c b/modules/codec/ttml/ttml.c
index 582cdb2..cb9b4b6 100644
--- a/modules/codec/ttml/ttml.c
+++ b/modules/codec/ttml/ttml.c
@@ -25,6 +25,7 @@
 #include <vlc_plugin.h>
 #include <vlc_xml.h>
 #include <vlc_strings.h>
+#include <vlc_charset.h>
 
 #include <assert.h>
 #include <stdlib.h>
@@ -71,9 +72,10 @@ bool tt_node_HasChild( const tt_node_t *p_node )
     return p_node->p_child;
 }
 
-static inline bool tt_ScanReset( unsigned *a, unsigned *b, unsigned *c, unsigned *d )
+static inline bool tt_ScanReset( unsigned *a, unsigned *b, unsigned *c,
+                                 char *d,  unsigned *e )
 {
-    *a = *b = *c = *d = 0;
+    *a = *b = *c = *d = *e = 0;
     return false;
 }
 
@@ -81,17 +83,55 @@ static tt_time_t tt_ParseTime( const char *s )
 {
     tt_time_t t = {-1, 0};
     unsigned h1 = 0, m1 = 0, s1 = 0, d1 = 0;
+    char c = 0;
 
-    if( sscanf( s, "%u:%u:%u%*[,.]%u", &h1, &m1, &s1, &d1 ) == 4 ||
-                         tt_ScanReset( &h1, &m1, &s1, &d1 )      ||
-        sscanf( s, "%u:%u:%u",         &h1, &m1, &s1      ) == 3 ||
-                         tt_ScanReset( &h1, &m1, &s1, &d1 )      ||
-        sscanf( s, "%u.%us",                     &s1, &d1 ) == 2 ||
-                         tt_ScanReset( &h1, &m1, &s1, &d1 )      ||
-        sscanf( s, "%us",                        &s1      ) == 1 )
+    /* Clock time */
+    if( sscanf( s, "%u:%u:%u%c%u",     &h1, &m1, &s1, &c, &d1 ) == 5 ||
+                         tt_ScanReset( &h1, &m1, &s1, &c, &d1 )      ||
+        sscanf( s, "%u:%u:%u",         &h1, &m1, &s1          ) == 3 ||
+                         tt_ScanReset( &h1, &m1, &s1, &c, &d1 ) )
     {
-        t.base = h1 * 3600 + m1 * 60 + s1;
-        t.frames = d1;
+        t.base = CLOCK_FREQ * (h1 * 3600 + m1 * 60 + s1);
+        if( c == '.' && d1 > 0 )
+        {
+            unsigned i_den = 1;
+            for( const char *p = strchr( s, '.' ) + 1; *p; p++ )
+                i_den *= 10;
+            t.base += CLOCK_FREQ * d1 / i_den;
+        }
+        else if( c == ':' )
+        {
+            t.frames = d1;
+        }
+    }
+    else /* Offset Time */
+    {
+        char *psz_end = (char *) s;
+        double v = us_strtod( s, &psz_end );
+        if( psz_end != s && *psz_end )
+        {
+            if( *psz_end == 'm' )
+            {
+                if( *(psz_end + 1) == 's' )
+                    t.base = 1000 * v;
+                else
+                    t.base = CLOCK_FREQ * 60 * v;
+            }
+            else if( *psz_end == 's' )
+            {
+                t.base = CLOCK_FREQ * v;
+            }
+            else if( *psz_end == 'h' )
+            {
+                t.base = CLOCK_FREQ * v * 3600;
+            }
+            else if( *psz_end == 'f' )
+            {
+                t.base = 0;
+                t.frames = v;
+            }
+            //else if( *psz_end == 't' );
+        }
     }
 
     return t;
diff --git a/modules/codec/ttml/ttml.h b/modules/codec/ttml/ttml.h
index c2dc4dc..94263ed 100644
--- a/modules/codec/ttml/ttml.h
+++ b/modules/codec/ttml/ttml.h
@@ -35,7 +35,7 @@ enum
 
 typedef struct
 {
-    time_t base;
+    int64_t base;
     unsigned frames;
     //unsigned ticks;
 } tt_time_t;
@@ -109,8 +109,8 @@ static inline void tt_time_Init( tt_time_t *t )
 static inline tt_time_t tt_time_Create( mtime_t i )
 {
     tt_time_t t;
-    t.base = i / CLOCK_FREQ;
-    t.frames = (i % CLOCK_FREQ) * TT_FRAME_RATE / CLOCK_FREQ;
+    t.base = i;
+    t.frames = 0;
     return t;
 }
 
@@ -124,7 +124,7 @@ static inline mtime_t tt_time_Convert( const tt_time_t *t )
     if( !tt_time_Valid( t ) )
         return -1;
     else
-        return CLOCK_FREQ * t->base + CLOCK_FREQ * t->frames / TT_FRAME_RATE;
+        return t->base + CLOCK_FREQ * t->frames / TT_FRAME_RATE;
 }
 
 static inline mtime_t tt_time_Compare( const tt_time_t *t1, const tt_time_t *t2 )
@@ -136,7 +136,7 @@ static inline tt_time_t tt_time_Add( tt_time_t t1, tt_time_t t2 )
 {
     t1.base += t2.base;
     t1.frames += t2.frames;
-    t1.base += t1.frames / TT_FRAME_RATE;
+    t1.base += CLOCK_FREQ * ( t1.frames / TT_FRAME_RATE );
     t1.frames = t1.frames % TT_FRAME_RATE;
     return t1;
 }
@@ -146,7 +146,7 @@ static inline tt_time_t tt_time_Sub( tt_time_t t1, tt_time_t t2 )
     if( t2.frames > t1.frames )
     {
         unsigned diff = 1 + (t2.frames - t1.frames) / TT_FRAME_RATE;
-        t1.base -= diff;
+        t1.base -= diff * CLOCK_FREQ;
         t1.frames += diff * TT_FRAME_RATE;
     }
     t1.frames -= t2.frames;
diff --git a/modules/demux/ttml.c b/modules/demux/ttml.c
index 2019586..f51569b 100644
--- a/modules/demux/ttml.c
+++ b/modules/demux/ttml.c
@@ -70,17 +70,38 @@ static char *tt_genTiming( tt_time_t t )
 {
     if( !tt_time_Valid( &t ) )
         t.base = 0;
-
+    unsigned f = t.base % CLOCK_FREQ;
+    t.base /= CLOCK_FREQ;
     unsigned h = t.base / 3600;
     unsigned m = t.base % 3600 / 60;
     unsigned s = t.base % 60;
 
+    int i_ret;
     char *psz;
-    if( asprintf( &psz, "%2.2u:%2.2u:%2.2u.%u",
-                        h, m, s, t.frames ) < 0 )
-        psz = NULL;
+    if( f )
+    {
+        const char *lz = "000000";
+        const char *psz_lz = &lz[6];
+        /* add leading zeroes */
+        for( unsigned i=10*f; i<CLOCK_FREQ; i *= 10 )
+            psz_lz--;
+        /* strip trailing zeroes */
+        for( ; f > 0 && (f % 10) == 0; f /= 10 );
+        i_ret = asprintf( &psz, "%02u:%02u:%02u.%s%u",
+                                 h, m, s, psz_lz, f );
+    }
+    else if( t.frames )
+    {
+        i_ret = asprintf( &psz, "%02u:%02u:%02u:%s%u",
+                                 h, m, s, t.frames < 10 ? "0" : "", t.frames );
+    }
+    else
+    {
+        i_ret = asprintf( &psz, "%02u:%02u:%02u",
+                                 h, m, s );
+    }
 
-    return psz;
+    return i_ret < 0 ? NULL : psz;
 }
 
 static void tt_node_AttributesToText( struct vlc_memstream *p_stream, const tt_node_t* p_node )



More information about the vlc-commits mailing list