From a42a858010bd9b4fc299930ac7031ae8ce63e2d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Yhuel?= <fyhuel@viotech.net>
Date: Tue, 29 Nov 2011 10:14:41 +0100
Subject: [PATCH] demux/mp4: add parsing of some atoms

Atoms mvex, mehd, trex and sdtp are found at least in PIFF (isml) files.
This a first step towards Smooth Streaming support in VLC.
---
 modules/demux/mp4/libmp4.c |   79 ++++++++++++++++++++++++++++++++++++++++++++
 modules/demux/mp4/libmp4.h |   33 ++++++++++++++++++
 modules/demux/mp4/mp4.c    |    3 ++
 3 files changed, 115 insertions(+), 0 deletions(-)

diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index 3e257df..aa83ac0 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -2721,6 +2721,81 @@ static int MP4_ReadBox_pasp( stream_t *p_stream, MP4_Box_t *p_box )
     MP4_READBOX_EXIT( 1 );
 }
 
+static int MP4_ReadBox_mehd( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_mehd_t );
+
+    MP4_GETVERSIONFLAGS( p_box->data.p_mehd );
+    if( p_box->data.p_mehd->i_version == 1 )
+        MP4_GET8BYTES( p_box->data.p_mehd->i_fragment_duration );
+    else /* version == 0 */
+        MP4_GET4BYTES( p_box->data.p_mehd->i_fragment_duration );
+
+#ifdef MP4_VERBOSE
+    msg_Dbg( p_stream,
+             "read box: \"mehd\" frag dur. %"PRIu64"",
+             p_box->data.p_mehd->i_fragment_duration );
+#endif
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_trex( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_trex_t );
+    MP4_GETVERSIONFLAGS( p_box->data.p_trex );
+
+    MP4_GET4BYTES( p_box->data.p_trex->i_track_ID );
+    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_description_index );
+    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_duration );
+    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_size );
+    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_flags );
+
+#ifdef MP4_VERBOSE
+    msg_Dbg( p_stream,
+             "read box: \"trex\" trackID: %"PRIu32"",
+             p_box->data.p_trex->i_track_ID );
+#endif
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_sdtp( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    uint32_t i_sample_count;
+    MP4_READBOX_ENTER( MP4_Box_data_sdtp_t );
+    MP4_Box_data_sdtp_t *p_sdtp = p_box->data.p_sdtp;
+    MP4_GETVERSIONFLAGS( p_box->data.p_sdtp );
+    i_sample_count = i_read;
+
+    p_sdtp->p_sample_table = calloc( i_sample_count, 1 );
+
+    if( !p_sdtp->p_sample_table )
+        goto error;
+
+    for( uint32_t i=0; i < i_sample_count; i++ )
+        MP4_GET1BYTE( p_sdtp->p_sample_table[i] );
+
+#ifdef MP4_VERBOSE
+    msg_Info( p_stream, "i_sample_count is %"PRIu32"", i_sample_count );
+    msg_Dbg( p_stream,
+             "read box: \"sdtp\" head: %"PRIx8" %"PRIx8" %"PRIx8" %"PRIx8"",
+                 p_sdtp->p_sample_table[0],
+                 p_sdtp->p_sample_table[1],
+                 p_sdtp->p_sample_table[2],
+                 p_sdtp->p_sample_table[3] );
+#endif
+
+    MP4_READBOX_EXIT( 1 );
+error:
+    MP4_READBOX_EXIT( 0 );
+}
+
+static void MP4_FreeBox_sdtp( MP4_Box_t *p_box )
+{
+    FREENULL( p_box->data.p_sdtp->p_sample_table );
+}
+
 
 /* For generic */
 static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
@@ -2799,6 +2874,7 @@ static const struct
     { ATOM_gmhd,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
     { ATOM_wave,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
     { ATOM_ilst,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
+    { ATOM_mvex,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
 
     /* specific box */
     { ATOM_ftyp,    MP4_ReadBox_ftyp,         MP4_FreeBox_ftyp },
@@ -2986,6 +3062,9 @@ static const struct
     { 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 },
 
     /* Last entry */
     { 0,              MP4_ReadBox_default,      NULL }
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index c4d2c82..aa016fe 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -73,7 +73,9 @@
 #define ATOM_edts VLC_FOURCC( 'e', 'd', 't', 's' )
 #define ATOM_elst VLC_FOURCC( 'e', 'l', 's', 't' )
 #define ATOM_mvex VLC_FOURCC( 'm', 'v', 'e', 'x' )
+#define ATOM_sdtp VLC_FOURCC( 's', 'd', 't', 'p' )
 #define ATOM_trex VLC_FOURCC( 't', 'r', 'e', 'x' )
+#define ATOM_mehd VLC_FOURCC( 'm', 'e', 'h', 'd' )
 #define ATOM_mfhd VLC_FOURCC( 'm', 'f', 'h', 'd' )
 #define ATOM_traf VLC_FOURCC( 't', 'r', 'a', 'f' )
 #define ATOM_tfhd VLC_FOURCC( 't', 'f', 'h', 'd' )
@@ -988,6 +990,34 @@ typedef struct
     uint32_t i_vertical_spacing;
 } MP4_Box_data_pasp_t;
 
+typedef struct
+{
+    uint8_t  i_version;
+    uint32_t i_flags;
+
+    uint64_t i_fragment_duration;
+} MP4_Box_data_mehd_t;
+
+typedef struct
+{
+    uint8_t  i_version;
+    uint32_t i_flags;
+
+    uint32_t i_track_ID;
+    uint32_t i_default_sample_description_index;
+    uint32_t i_default_sample_duration;
+    uint32_t i_default_sample_size;
+    uint32_t i_default_sample_flags;
+} MP4_Box_data_trex_t;
+
+typedef struct
+{
+    uint8_t  i_version;
+    uint32_t i_flags;
+
+    uint8_t *p_sample_table;
+} MP4_Box_data_sdtp_t;
+
 /*
 typedef struct MP4_Box_data__s
 {
@@ -1030,6 +1060,9 @@ typedef union MP4_Box_data_s
     MP4_Box_data_trkn_t *p_trkn;
     MP4_Box_data_iods_t *p_iods;
     MP4_Box_data_pasp_t *p_pasp;
+    MP4_Box_data_trex_t *p_trex;
+    MP4_Box_data_mehd_t *p_mehd;
+    MP4_Box_data_sdtp_t *p_sdtp;
 
     MP4_Box_data_stsz_t *p_stsz;
     MP4_Box_data_stz2_t *p_stz2;
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 9561d0f..ee26870 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -346,6 +346,9 @@ static int Open( vlc_object_t * p_this )
             case( VLC_FOURCC( 'q', 't', ' ', ' ') ):
                 msg_Dbg( p_demux, "Apple QuickTime file" );
                 break;
+            case( VLC_FOURCC( 'i', 's', 'm', 'l') ):
+                msg_Dbg( p_demux, "PIFF (= isml = fMP4) file" );
+                break;
             default:
                 msg_Dbg( p_demux,
                          "unrecognized major file specification (%4.4s).",
-- 
1.7.4.1

