[vlc-devel] [PATCH] demux/mp4: add parsing of mfra atom

fyhuel at viotech.net fyhuel at viotech.net
Tue Nov 29 17:14:41 CET 2011


From: Frédéric Yhuel <fyhuel at viotech.net>

mfra atom contains two leaf atoms, 'tfra' and 'mfro'. The first one
provides file offsets of the chunks in a isml file.

mfra atom support will not help Smooth Streaming support in VLC (at
least for the client part), but can be useful for other
purposes, e.g. to enable VLC to play a "raw" isml file.
---
 modules/demux/mp4/libmp4.c |  154 ++++++++++++++++++++++++++++++++++++++++++++
 modules/demux/mp4/libmp4.h |   30 +++++++++
 2 files changed, 184 insertions(+), 0 deletions(-)

diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index aa83ac0..d55f7e8 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -2796,6 +2796,157 @@ static void MP4_FreeBox_sdtp( MP4_Box_t *p_box )
     FREENULL( p_box->data.p_sdtp->p_sample_table );
 }
 
+static int MP4_ReadBox_mfro( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_mfro_t );
+
+    MP4_GETVERSIONFLAGS( p_box->data.p_mfro );
+    MP4_GET4BYTES( p_box->data.p_mfro->i_size );
+
+#ifdef MP4_VERBOSE
+    msg_Dbg( p_stream,
+             "read box: \"mfro\" size: %"PRIu32"",
+             p_box->data.p_mfro->i_size);
+#endif
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_tfra( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    uint32_t i_number_of_entries;
+    MP4_READBOX_ENTER( MP4_Box_data_tfra_t );
+    MP4_Box_data_tfra_t *p_tfra = p_box->data.p_tfra;
+    MP4_GETVERSIONFLAGS( p_box->data.p_tfra );
+
+    MP4_GET4BYTES( p_tfra->i_track_ID );
+    MP4_GET4BYTES( p_tfra->i_lengths );
+    MP4_GET4BYTES( p_tfra->i_number_of_entries );
+    i_number_of_entries = p_tfra->i_number_of_entries;
+    uint8_t length_size_of_traf_num = p_tfra->i_lengths>>4;
+    uint8_t length_size_of_trun_num = ( p_tfra->i_lengths & 0x0c )>>2;
+    uint8_t length_size_of_sample_num = p_tfra->i_lengths & 0x03;
+
+    size_t size = 4 + 4*p_tfra->i_version; /* size in {4, 8} */
+    p_tfra->p_time = calloc( i_number_of_entries, size );
+    p_tfra->p_moof_offset = calloc( i_number_of_entries, size );
+
+    size = 1 + length_size_of_traf_num; /* size in [|1, 4|] */
+    p_tfra->p_traf_number = calloc( i_number_of_entries, size );
+    size = 1 + length_size_of_trun_num;
+    p_tfra->p_trun_number = calloc( i_number_of_entries, size );
+    size = 1 + length_size_of_sample_num;
+    p_tfra->p_sample_number = calloc( i_number_of_entries, size );
+
+    if( !p_tfra->p_time || !p_tfra->p_moof_offset || !p_tfra->p_traf_number
+                        || !p_tfra->p_trun_number || !p_tfra->p_sample_number )
+        goto error;
+
+    for( uint32_t i=0; i < i_number_of_entries; i++ )
+    {
+        if( p_tfra->i_version == 1 )
+        {
+            MP4_GET8BYTES( p_tfra->p_time[i*2] );
+            MP4_GET8BYTES( p_tfra->p_moof_offset[i*2] );
+        }
+        else
+        {
+            MP4_GET4BYTES( p_tfra->p_time[i] );
+            MP4_GET4BYTES( p_tfra->p_moof_offset[i] );
+        }
+        switch (length_size_of_traf_num)
+        {
+            case 0:
+                MP4_GET1BYTE( p_tfra->p_traf_number[i] );
+                break;
+            case 1:
+                MP4_GET2BYTES( p_tfra->p_traf_number[i*2] );
+                break;
+            case 2:
+                MP4_GET3BYTES( p_tfra->p_traf_number[i*3] );
+                break;
+            case 3:
+                MP4_GET4BYTES( p_tfra->p_traf_number[i*4] );
+                break;
+            default:
+                goto error;
+        }
+
+        switch (length_size_of_trun_num)
+        {
+            case 0:
+                MP4_GET1BYTE( p_tfra->p_trun_number[i] );
+                break;
+            case 1:
+                MP4_GET2BYTES( p_tfra->p_trun_number[i*2] );
+                break;
+            case 2:
+                MP4_GET3BYTES( p_tfra->p_trun_number[i*3] );
+                break;
+            case 3:
+                MP4_GET4BYTES( p_tfra->p_trun_number[i*4] );
+                break;
+            default:
+                goto error;
+        }
+
+        switch (length_size_of_sample_num)
+        {
+            case 0:
+                MP4_GET1BYTE( p_tfra->p_sample_number[i] );
+                break;
+            case 1:
+                MP4_GET2BYTES( p_tfra->p_sample_number[i*2] );
+                break;
+            case 2:
+                MP4_GET3BYTES( p_tfra->p_sample_number[i*3] );
+                break;
+            case 3:
+                MP4_GET4BYTES( p_tfra->p_sample_number[i*4] );
+                break;
+            default:
+                goto error;
+        }
+    }
+
+#ifdef MP4_VERBOSE
+    if( p_tfra->i_version == 0 )
+    {
+        msg_Dbg( p_stream, "time[0]: %"PRIu32", moof_offset[0]: %"PRIx32"",
+                         p_tfra->p_time[0], p_tfra->p_moof_offset[0] );
+
+        msg_Dbg( p_stream, "time[1]: %"PRIu32", moof_offset[1]: %"PRIx32"",
+                         p_tfra->p_time[1], p_tfra->p_moof_offset[1] );
+    }
+    else
+    {
+        msg_Dbg( p_stream, "time[0]: %"PRIu64", moof_offset[0]: %"PRIx64"",
+                ((uint64_t *)(p_tfra->p_time))[0],
+                ((uint64_t *)(p_tfra->p_moof_offset))[0] );
+
+        msg_Dbg( p_stream, "time[1]: %"PRIu64", moof_offset[1]: %"PRIx64"",
+                ((uint64_t *)(p_tfra->p_time))[1],
+                ((uint64_t *)(p_tfra->p_moof_offset))[1] );
+    }
+
+    msg_Info( p_stream, "number_of_entries is %"PRIu32"", i_number_of_entries );
+    msg_Info( p_stream, "track ID is: %"PRIu32"", p_tfra->i_track_ID );
+#endif
+
+    MP4_READBOX_EXIT( 1 );
+error:
+    MP4_READBOX_EXIT( 0 );
+}
+
+static void MP4_FreeBox_tfra( MP4_Box_t *p_box )
+{
+    FREENULL( p_box->data.p_tfra->p_time );
+    FREENULL( p_box->data.p_tfra->p_moof_offset );
+    FREENULL( p_box->data.p_tfra->p_traf_number );
+    FREENULL( p_box->data.p_tfra->p_trun_number );
+    FREENULL( p_box->data.p_tfra->p_sample_number );
+}
+
 
 /* For generic */
 static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
@@ -3059,12 +3210,15 @@ static const struct
 
     /* found in smoothstreaming */
     { ATOM_traf,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
+    { ATOM_mfra,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
     { ATOM_mfhd,    MP4_ReadBox_mfhd,         MP4_FreeBox_Common },
     { ATOM_tfhd,    MP4_ReadBox_tfhd,         MP4_FreeBox_Common },
     { ATOM_trun,    MP4_ReadBox_trun,         MP4_FreeBox_trun },
     { ATOM_trex,    MP4_ReadBox_trex,         MP4_FreeBox_Common },
     { ATOM_mehd,    MP4_ReadBox_mehd,         MP4_FreeBox_Common },
     { ATOM_sdtp,    MP4_ReadBox_sdtp,         MP4_FreeBox_sdtp },
+    { ATOM_tfra,    MP4_ReadBox_tfra,         MP4_FreeBox_tfra },
+    { ATOM_mfro,    MP4_ReadBox_mfro,         MP4_FreeBox_Common },
 
     /* Last entry */
     { 0,              MP4_ReadBox_default,      NULL }
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index aa016fe..91effd2 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -83,6 +83,9 @@
 #define ATOM_cprt VLC_FOURCC( 'c', 'p', 'r', 't' )
 #define ATOM_iods VLC_FOURCC( 'i', 'o', 'd', 's' )
 #define ATOM_pasp VLC_FOURCC( 'p', 'a', 's', 'p' )
+#define ATOM_mfra VLC_FOURCC( 'm', 'f', 'r', 'a' )
+#define ATOM_mfro VLC_FOURCC( 'm', 'f', 'r', 'o' )
+#define ATOM_tfra VLC_FOURCC( 't', 'f', 'r', 'a' )
 
 #define ATOM_nmhd VLC_FOURCC( 'n', 'm', 'h', 'd' )
 #define ATOM_mp2v VLC_FOURCC( 'm', 'p', '2', 'v' )
@@ -1018,6 +1021,30 @@ typedef struct
     uint8_t *p_sample_table;
 } MP4_Box_data_sdtp_t;
 
+typedef struct
+{
+    uint8_t  i_version;
+    uint32_t i_flags;
+
+    uint32_t i_size;
+} MP4_Box_data_mfro_t;
+
+typedef struct
+{
+    uint8_t  i_version;
+    uint32_t i_flags;
+
+    uint32_t i_track_ID;
+    uint32_t i_lengths;
+    uint32_t i_number_of_entries;
+
+    uint32_t *p_time;
+    uint32_t *p_moof_offset;
+    uint8_t *p_traf_number;
+    uint8_t *p_trun_number;
+    uint8_t *p_sample_number;
+} MP4_Box_data_tfra_t;
+
 /*
 typedef struct MP4_Box_data__s
 {
@@ -1064,6 +1091,9 @@ typedef union MP4_Box_data_s
     MP4_Box_data_mehd_t *p_mehd;
     MP4_Box_data_sdtp_t *p_sdtp;
 
+    MP4_Box_data_tfra_t *p_tfra;
+    MP4_Box_data_mfro_t *p_mfro;
+
     MP4_Box_data_stsz_t *p_stsz;
     MP4_Box_data_stz2_t *p_stz2;
     MP4_Box_data_stsc_t *p_stsc;
-- 
1.7.4.1




More information about the vlc-devel mailing list