[vlc-commits] add support for parsing moof box in libmp4
Luc Saillard
git at videolan.org
Fri Jul 22 02:15:42 CEST 2011
vlc | branch: master | Luc Saillard <luc.saillard at sfr.com> | Wed Jul 20 18:13:04 2011 +0200| [3defabc04f3c4b492358bd4c8b183a06516c7ae8] | committer: Jean-Baptiste Kempf
add support for parsing moof box in libmp4
moof box is a new box mainly used to produce fragmented mp4 movie.
Smoothstreaming is known to used this format.
Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3defabc04f3c4b492358bd4c8b183a06516c7ae8
---
modules/demux/mp4/libmp4.c | 124 ++++++++++++++++++++++++++++++++++++++++++++
modules/demux/mp4/libmp4.h | 60 +++++++++++++++++++++
modules/demux/mp4/mp4.c | 9 +++-
3 files changed, 191 insertions(+), 2 deletions(-)
diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index 7eb900a..51efe16 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -476,6 +476,124 @@ static int MP4_ReadBox_mvhd( stream_t *p_stream, MP4_Box_t *p_box )
MP4_READBOX_EXIT( 1 );
}
+static int MP4_ReadBox_mfhd( stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_mfhd_t );
+
+ MP4_GET4BYTES( p_box->data.p_mfhd->i_sequence_number );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream, "read box: \"mfhd\" sequence number %d",
+ p_box->data.p_mfhd->i_sequence_number );
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_tfhd( stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_tfhd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_tfhd );
+
+ MP4_GET4BYTES( p_box->data.p_tfhd->i_track_ID );
+
+ if( p_box->data.p_tfhd->i_version == 0 )
+ {
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_BASE_DATA_OFFSET )
+ MP4_GET8BYTES( p_box->data.p_tfhd->i_base_data_offset );
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_SAMPLE_DESC_INDEX )
+ MP4_GET4BYTES( p_box->data.p_tfhd->i_sample_description_index );
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_DURATION )
+ MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_duration );
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_SIZE )
+ MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_size );
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_FLAGS )
+ MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_flags );
+
+#ifdef MP4_VERBOSE
+ char psz_base[128] = "\0";
+ char psz_desc[128] = "\0";
+ char psz_dura[128] = "\0";
+ char psz_size[128] = "\0";
+ char psz_flag[128] = "\0";
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_BASE_DATA_OFFSET )
+ snprintf(psz_base, sizeof(psz_base), "base offset %lld", p_box->data.p_tfhd->i_base_data_offset);
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_SAMPLE_DESC_INDEX )
+ snprintf(psz_desc, sizeof(psz_desc), "sample description index %d", p_box->data.p_tfhd->i_sample_description_index);
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_DURATION )
+ snprintf(psz_dura, sizeof(psz_dura), "sample duration %d", p_box->data.p_tfhd->i_default_sample_duration);
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_SIZE )
+ snprintf(psz_size, sizeof(psz_size), "sample size %d", p_box->data.p_tfhd->i_default_sample_size);
+ if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_FLAGS )
+ snprintf(psz_flag, sizeof(psz_flag), "sample flags 0x%x", p_box->data.p_tfhd->i_default_sample_flags);
+
+ msg_Dbg( p_stream, "read box: \"tfhd\" version %d flags 0x%x track ID %d %s %s %s %s %s",
+ p_box->data.p_tfhd->i_version,
+ p_box->data.p_tfhd->i_flags,
+ p_box->data.p_tfhd->i_track_ID,
+ psz_base, psz_desc, psz_dura, psz_size, psz_flag );
+#endif
+ }
+
+ MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_trun( stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_trun_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_trun );
+
+ MP4_GET4BYTES( p_box->data.p_trun->i_sample_count );
+
+ if( p_box->data.p_trun->i_flags & MP4_TRUN_DATA_OFFSET )
+ MP4_GET8BYTES( p_box->data.p_trun->i_data_offset );
+ if( p_box->data.p_trun->i_flags & MP4_TRUN_FIRST_FLAGS )
+ MP4_GET4BYTES( p_box->data.p_trun->i_first_sample_flags );
+
+ p_box->data.p_trun->p_samples =
+ calloc( p_box->data.p_trun->i_sample_count, sizeof(MP4_descriptor_trun_sample_t) );
+ if ( p_box->data.p_trun->p_samples == NULL )
+ MP4_READBOX_EXIT( 0 );
+
+ for( unsigned int i = 0; i<p_box->data.p_trun->i_sample_count; i++ )
+ {
+ MP4_descriptor_trun_sample_t *p_sample = &p_box->data.p_trun->p_samples[i];
+ if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_DURATION )
+ MP4_GET4BYTES( p_sample->i_duration );
+ if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_SIZE )
+ MP4_GET4BYTES( p_sample->i_size );
+ if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_FLAGS )
+ MP4_GET4BYTES( p_sample->i_flags );
+ if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_TIME_OFFSET )
+ MP4_GET4BYTES( p_sample->i_composition_time_offset );
+ }
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream, "read box: \"trun\" version %d flags 0x%x sample count %d",
+ p_box->data.p_trun->i_version,
+ p_box->data.p_trun->i_flags,
+ p_box->data.p_trun->i_sample_count );
+
+ for( unsigned int i = 0; i<p_box->data.p_trun->i_sample_count; i++ )
+ {
+ MP4_descriptor_trun_sample_t *p_sample = &p_box->data.p_trun->p_samples[i];
+ msg_Dbg( p_stream, "read box: \"trun\" sample %4.4d flags 0x%x duration %d size %d composition time offset %d",
+ i, p_sample->i_flags, p_sample->i_duration,
+ p_sample->i_size, p_sample->i_composition_time_offset );
+ }
+#endif
+
+ MP4_READBOX_EXIT( 1 );
+}
+
+static void MP4_FreeBox_trun( MP4_Box_t *p_box )
+{
+ FREENULL( p_box->data.p_trun->p_samples );
+}
+
+
+
static int MP4_ReadBox_tkhd( stream_t *p_stream, MP4_Box_t *p_box )
{
unsigned int i;
@@ -2782,6 +2900,12 @@ static const struct
/* iTunes/Quicktime meta info */
{ FOURCC_meta, MP4_ReadBox_meta, MP4_FreeBox_Common },
+ /* found in smoothstreaming */
+ { FOURCC_traf, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_mfhd, MP4_ReadBox_mfhd, MP4_FreeBox_Common },
+ { FOURCC_tfhd, MP4_ReadBox_tfhd, MP4_FreeBox_Common },
+ { FOURCC_trun, MP4_ReadBox_trun, MP4_FreeBox_trun },
+
/* Last entry */
{ 0, MP4_ReadBox_default, NULL }
};
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index 5e2181a..89a5dc1 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -821,6 +821,63 @@ typedef struct
} MP4_Box_data_rmqu_t;
+typedef struct MP4_Box_data_mfhd_s
+{
+ uint32_t i_sequence_number;
+
+ uint8_t *p_vendor_extension;
+
+} MP4_Box_data_mfhd_t;
+
+#define MP4_TFHD_BASE_DATA_OFFSET (1LL<<0)
+#define MP4_TFHD_SAMPLE_DESC_INDEX (1LL<<1)
+#define MP4_TFHD_DFLT_SAMPLE_DURATION (1LL<<3)
+#define MP4_TFHD_DFLT_SAMPLE_SIZE (1LL<<4)
+#define MP4_TFHD_DFLT_SAMPLE_FLAGS (1LL<<5)
+typedef struct MP4_Box_data_tfhd_s
+{
+ uint8_t i_version;
+ uint32_t i_flags;
+ uint32_t i_track_ID;
+
+ /* optional fields */
+ uint64_t i_base_data_offset;
+ uint32_t i_sample_description_index;
+ uint32_t i_default_sample_duration;
+ uint32_t i_default_sample_size;
+ uint32_t i_default_sample_flags;
+
+} MP4_Box_data_tfhd_t;
+
+#define MP4_TRUN_DATA_OFFSET (1<<0)
+#define MP4_TRUN_FIRST_FLAGS (1<<2)
+#define MP4_TRUN_SAMPLE_DURATION (1<<8)
+#define MP4_TRUN_SAMPLE_SIZE (1<<9)
+#define MP4_TRUN_SAMPLE_FLAGS (1<<10)
+#define MP4_TRUN_SAMPLE_TIME_OFFSET (1<<11)
+typedef struct MP4_descriptor_trun_sample_t
+{
+ uint32_t i_duration;
+ uint32_t i_size;
+ uint32_t i_flags;
+ uint32_t i_composition_time_offset;
+} MP4_descriptor_trun_sample_t;
+
+typedef struct MP4_Box_data_trun_s
+{
+ uint8_t i_version;
+ uint32_t i_flags;
+ uint32_t i_sample_count;
+
+ /* optional fields */
+ uint32_t i_data_offset;
+ uint32_t i_first_sample_flags;
+
+ MP4_descriptor_trun_sample_t *p_samples;
+
+} MP4_Box_data_trun_t;
+
+
typedef struct
{
char *psz_text;
@@ -916,6 +973,9 @@ typedef union MP4_Box_data_s
{
MP4_Box_data_ftyp_t *p_ftyp;
MP4_Box_data_mvhd_t *p_mvhd;
+ MP4_Box_data_mfhd_t *p_mfhd;
+ MP4_Box_data_tfhd_t *p_tfhd;
+ MP4_Box_data_trun_t *p_trun;
MP4_Box_data_tkhd_t *p_tkhd;
MP4_Box_data_mdhd_t *p_mdhd;
MP4_Box_data_hdlr_t *p_hdlr;
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 562a18d..b4f99f4 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -368,8 +368,13 @@ static int Open( vlc_object_t * p_this )
if( !p_foov )
{
- msg_Err( p_demux, "MP4 plugin discarded (no moov box)" );
- goto error;
+ /* search also for moof box used by smoothstreaming */
+ p_foov = MP4_BoxGet( p_sys->p_root, "/moof" );
+ if( !p_foov )
+ {
+ msg_Err( p_demux, "MP4 plugin discarded (no moov,foov,moof box)" );
+ goto error;
+ }
}
/* we have a free box as a moov, rename it */
p_foov->i_type = FOURCC_moov;
More information about the vlc-commits
mailing list