Commit b7c4b275 authored by Frédéric Yhuel's avatar Frédéric Yhuel Committed by Jean-Baptiste Kempf

demux/mp4: add parsing of mfra atom

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.
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 1b0ab501
......@@ -2796,6 +2796,158 @@ 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 );
uint32_t i_lengths = 0;
MP4_GET4BYTES( i_lengths );
MP4_GET4BYTES( p_tfra->i_number_of_entries );
i_number_of_entries = p_tfra->i_number_of_entries;
p_tfra->i_length_size_of_traf_num = i_lengths >> 4;
p_tfra->i_length_size_of_trun_num = ( i_lengths & 0x0c ) >> 2;
p_tfra->i_length_size_of_sample_num = 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 + p_tfra->i_length_size_of_traf_num; /* size in [|1, 4|] */
p_tfra->p_traf_number = calloc( i_number_of_entries, size );
size = 1 + p_tfra->i_length_size_of_trun_num;
p_tfra->p_trun_number = calloc( i_number_of_entries, size );
size = 1 + p_tfra->i_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 (p_tfra->i_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 (p_tfra->i_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 (p_tfra->i_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 +3211,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 }
......
......@@ -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,33 @@ 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_number_of_entries;
uint8_t i_length_size_of_traf_num;
uint8_t i_length_size_of_trun_num;
uint8_t i_length_size_of_sample_num;
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 +1094,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;
......
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