[vlc-commits] libmp4: add TfrfBox and TfxdBox parsing

Frédéric Yhuel git at videolan.org
Fri Mar 23 12:02:26 CET 2012


vlc | branch: master | Frédéric Yhuel <fyhuel at viotech.net> | Fri Mar 23 10:40:17 2012 +0100| [d1c96ead108c36dd69f91abc9e89c0b3f642ab31] | committer: Jean-Baptiste Kempf

libmp4: add TfrfBox and TfxdBox parsing

These are Smooth Streaming specific boxes, which provide duration and
time offset of subsequent(s) fragment(s), thus allowing us to avoid
manifest polling in "live" mode.

See the following file for reference:
http://download.microsoft.com/download/B/0/B/B0B199DB-41E6-400F-90CD-C350D0C14A53/%5BMS-SSTR%5D.pdf

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>

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

 modules/demux/mp4/libmp4.c |  117 ++++++++++++++++++++++++++++++++++++++++++++
 modules/demux/mp4/libmp4.h |   30 +++++++++++
 2 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index 9faf92d..38a6bf9 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -139,6 +139,11 @@ static inline void GetUUID( UUID_t *p_uuid, const uint8_t *p_buff )
     memcpy( p_uuid, p_buff, 16 );
 }
 
+static inline int CmpUUID( const UUID_t *u1, const UUID_t *u2 )
+{
+    return memcmp( u1, u2, 16 );
+}
+
 static void CreateUUID( UUID_t *p_uuid, uint32_t i_fourcc )
 {
     /* made by 0xXXXXXXXX-0011-0010-8000-00aa00389b71
@@ -148,6 +153,14 @@ static void CreateUUID( UUID_t *p_uuid, uint32_t i_fourcc )
     (void)i_fourcc;
 }
 
+const UUID_t TfrfBoxUUID = { .b =
+                { 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
+                  0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f } };
+
+const UUID_t TfxdBoxUUID = { .b =
+                { 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
+                  0x80, 0xe2, 0x14, 0x1b, 0xaf, 0xf7, 0x57, 0xb2 } };
+
 /* convert 16.16 fixed point to floating point */
 static double conv_fx( int32_t fx ) {
     double fp = fx;
@@ -501,6 +514,109 @@ static int MP4_ReadBox_mfhd(  stream_t *p_stream, MP4_Box_t *p_box )
     MP4_READBOX_EXIT( 1 );
 }
 
+static int MP4_ReadBox_tfxd(  stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_tfxd_t );
+
+    MP4_Box_data_tfxd_t *p_tfxd_data = p_box->data.p_tfxd;
+    MP4_GETVERSIONFLAGS( p_tfxd_data );
+
+    if( p_tfxd_data->i_version == 0 )
+    {
+        MP4_GET4BYTES( p_tfxd_data->i_fragment_abs_time );
+        MP4_GET4BYTES( p_tfxd_data->i_fragment_duration );
+    }
+    else
+    {
+        MP4_GET8BYTES( p_tfxd_data->i_fragment_abs_time );
+        MP4_GET8BYTES( p_tfxd_data->i_fragment_duration );
+    }
+
+#ifdef MP4_VERBOSE
+    msg_Dbg( p_stream, "read box: \"tfxd\" version %d, flags 0x%x, "\
+            "fragment duration %"PRIu64", fragment abs time %"PRIu64,
+                p_tfxd_data->i_version,
+                p_tfxd_data->i_flags,
+                p_tfxd_data->i_fragment_duration,
+                p_tfxd_data->i_fragment_abs_time
+           );
+#endif
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_tfrf(  stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_tfxd_t );
+
+    MP4_Box_data_tfrf_t *p_tfrf_data = p_box->data.p_tfrf;
+    MP4_GETVERSIONFLAGS( p_tfrf_data );
+
+    MP4_GET1BYTE( p_tfrf_data->i_fragment_count );
+
+    p_tfrf_data->p_tfrf_data_fields = calloc( p_tfrf_data->i_fragment_count,
+                                              sizeof( TfrfBoxDataFields_t ) );
+    if( !p_tfrf_data->p_tfrf_data_fields )
+        MP4_READBOX_EXIT( 0 );
+
+    for( uint8_t i = 0; i < p_tfrf_data->i_fragment_count; i++ )
+    {
+        TfrfBoxDataFields_t *TfrfBoxDataField = &p_tfrf_data->p_tfrf_data_fields[i];
+        if( p_tfrf_data->i_version == 0 )
+        {
+            MP4_GET4BYTES( TfrfBoxDataField->i_fragment_abs_time );
+            MP4_GET4BYTES( TfrfBoxDataField->i_fragment_duration );
+        }
+        else
+        {
+            MP4_GET8BYTES( TfrfBoxDataField->i_fragment_abs_time );
+            MP4_GET8BYTES( TfrfBoxDataField->i_fragment_duration );
+        }
+    }
+
+#ifdef MP4_VERBOSE
+    msg_Dbg( p_stream, "read box: \"tfrf\" version %d, flags 0x%x, "\
+            "fragment count %"PRIu8, p_tfrf_data->i_version,
+                p_tfrf_data->i_flags, p_tfrf_data->i_fragment_count );
+
+    for( uint8_t i = 0; i < p_tfrf_data->i_fragment_count; i++ )
+    {
+        TfrfBoxDataFields_t *TfrfBoxDataField = &p_tfrf_data->p_tfrf_data_fields[i];
+        msg_Dbg( p_stream, "\"tfrf\" fragment duration %"PRIu64", "\
+                                    "fragment abs time %"PRIu64,
+                    TfrfBoxDataField->i_fragment_duration,
+                    TfrfBoxDataField->i_fragment_abs_time );
+    }
+
+#endif
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static void MP4_FreeBox_tfrf( MP4_Box_t *p_box )
+{
+    FREENULL( p_box->data.p_tfrf->p_tfrf_data_fields );
+}
+
+static int MP4_ReadBox_uuid( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    if( !CmpUUID( &p_box->i_uuid, &TfrfBoxUUID ) )
+        return MP4_ReadBox_tfrf( p_stream, p_box );
+    if( !CmpUUID( &p_box->i_uuid, &TfxdBoxUUID ) )
+        return MP4_ReadBox_tfxd( p_stream, p_box );
+
+    msg_Warn( p_stream, "Unknown uuid type box" );
+    return 1;
+}
+
+static void MP4_FreeBox_uuid( MP4_Box_t *p_box )
+{
+    if( !CmpUUID( &p_box->i_uuid, &TfrfBoxUUID ) )
+        return MP4_FreeBox_tfrf( p_box );
+    if( !CmpUUID( &p_box->i_uuid, &TfxdBoxUUID ) )
+        return MP4_FreeBox_Common( p_box );
+}
+
 static int MP4_ReadBox_sidx(  stream_t *p_stream, MP4_Box_t *p_box )
 {
     MP4_READBOX_ENTER( MP4_Box_data_sidx_t );
@@ -3303,6 +3419,7 @@ static const struct
     { ATOM_sdtp,    MP4_ReadBox_sdtp,         MP4_FreeBox_sdtp },
     { ATOM_tfra,    MP4_ReadBox_tfra,         MP4_FreeBox_tfra },
     { ATOM_mfro,    MP4_ReadBox_mfro,         MP4_FreeBox_Common },
+    { ATOM_uuid,    MP4_ReadBox_uuid,         MP4_FreeBox_uuid },
 
     /* Last entry */
     { 0,              MP4_ReadBox_default,      NULL }
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index 40eb70c..ddb90be 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -260,6 +260,33 @@ typedef struct UUID_s
 
 /* specific structure for all boxes */
 
+typedef struct MP4_Box_data_tfxd_s
+{
+    uint8_t  i_version;
+    uint32_t i_flags;
+
+    uint64_t i_fragment_duration;
+    uint64_t i_fragment_abs_time;
+
+} MP4_Box_data_tfxd_t;
+
+typedef struct TfrfBoxDataFields_s
+{
+    uint64_t i_fragment_duration;
+    uint64_t i_fragment_abs_time;
+
+} TfrfBoxDataFields_t;
+
+typedef struct MP4_Box_data_tfrf_s
+{
+    uint8_t  i_version;
+    uint8_t  i_fragment_count;
+    uint32_t i_flags;
+
+    TfrfBoxDataFields_t *p_tfrf_data_fields;
+
+} MP4_Box_data_tfrf_t;
+
 typedef struct MP4_Box_data_ftyp_s
 {
     uint32_t i_major_brand;
@@ -1158,6 +1185,9 @@ typedef union MP4_Box_data_s
     MP4_Box_data_tref_generic_t *p_tref_generic;
     MP4_Box_data_name_t *p_name;
 
+    MP4_Box_data_tfrf_t *p_tfrf;
+    MP4_Box_data_tfxd_t *p_tfxd;
+
     void                *p_data; /* for unknow type */
 } MP4_Box_data_t;
 



More information about the vlc-commits mailing list