Commit 3defabc0 authored by Luc Saillard's avatar Luc Saillard Committed by 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: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent c684f60a
......@@ -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 }
};
......
......@@ -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;
......
......@@ -368,9 +368,14 @@ static int Open( vlc_object_t * p_this )
if( !p_foov )
{
msg_Err( p_demux, "MP4 plugin discarded (no moov box)" );
/* 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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment