vlc | branch: master | Francois Cartegnie <fcvlc...@free.fr> | Thu Mar 8 21:29:49 2018 +0100| [f29dbe1e6116a6e845cfcb8d29d5475840cd4214] | committer: Francois Cartegnie
demux: libmp4: read iloc > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f29dbe1e6116a6e845cfcb8d29d5475840cd4214 --- modules/demux/mp4/heif.c | 0 modules/demux/mp4/libmp4.c | 168 +++++++++++++++++++++++++++++++++++++++++++++ modules/demux/mp4/libmp4.h | 35 ++++++++++ 3 files changed, 203 insertions(+) diff --git a/modules/demux/mp4/heif.c b/modules/demux/mp4/heif.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c index 6440d2f009..b42f0993fa 100644 --- a/modules/demux/mp4/libmp4.c +++ b/modules/demux/mp4/libmp4.c @@ -4252,6 +4252,170 @@ static int MP4_ReadBox_SA3D( stream_t *p_stream, MP4_Box_t *p_box ) MP4_READBOX_EXIT( 1 ); } +static void MP4_FreeBox_iloc( MP4_Box_t *p_box ) +{ + MP4_Box_data_iloc_t *p_data = p_box->data.p_iloc; + for( uint32_t i=0; i<p_data->i_item_count; i++ ) + free( p_data->p_items[i].p_extents ); + free( p_data->p_items ); +} + +static int MP4_ReadBox_iloc( stream_t *p_stream, MP4_Box_t *p_box ) +{ + MP4_READBOX_ENTER( MP4_Box_data_iloc_t, MP4_FreeBox_iloc ); + MP4_Box_data_iloc_t *p_data = p_box->data.p_iloc; + + uint16_t i_foo; + + uint8_t i_version; + uint32_t i_flags; + MP4_GET1BYTE( i_version ); + MP4_GET3BYTES( i_flags ); + VLC_UNUSED(i_flags); + + MP4_GET1BYTE( p_data->i_offset_size ); + p_data->i_length_size = p_data->i_offset_size & 0x0F; + p_data->i_offset_size >>= 4; + MP4_GET1BYTE( p_data->i_base_offset_size ); + if( i_version == 0 ) + p_data->i_index_size = 0; + else + p_data->i_index_size = p_data->i_base_offset_size & 0x0F; + p_data->i_base_offset_size >>= 4; + + /* Only accept 0,4,8 */ + if( (p_data->i_offset_size & 0xF3) || p_data->i_offset_size > 8 || + (p_data->i_length_size & 0xF3) || p_data->i_length_size > 8 || + (p_data->i_base_offset_size & 0xF3) || p_data->i_base_offset_size > 8 || + (p_data->i_index_size & 0xF3) || p_data->i_index_size > 8 ) + MP4_READBOX_EXIT( 0 ); + + if( i_version < 2 ) + MP4_GET2BYTES( p_data->i_item_count ); + else if( i_version == 2 ) + MP4_GET4BYTES( p_data->i_item_count ); + else + MP4_READBOX_EXIT( 0 ); + + if( i_read / 6 < p_data->i_item_count ) + MP4_READBOX_EXIT( 0 ); + + p_data->p_items = malloc( p_data->i_item_count * sizeof(p_data->p_items[0]) ); + if( !p_data->p_items ) + MP4_READBOX_EXIT( 0 ); + + for( uint32_t i=0; i<p_data->i_item_count; i++ ) + { + if( i_version < 2 ) + MP4_GET2BYTES( p_data->p_items[i].i_item_id ); + else + MP4_GET4BYTES( p_data->p_items[i].i_item_id ); + + if( i_version > 0 ) + { + MP4_GET2BYTES( i_foo ); + p_data->p_items[i].i_construction_method = i_foo & 0x0F; + } + + MP4_GET2BYTES( p_data->p_items[i].i_data_reference_index ); + + switch( p_data->i_base_offset_size ) + { + case 4: MP4_GET4BYTES( p_data->p_items[i].i_base_offset ); break; + case 8: MP4_GET8BYTES( p_data->p_items[i].i_base_offset ); break; + default: break; + } + + MP4_GET2BYTES( p_data->p_items[i].i_extent_count ); + + uint64_t i_entrysize = (( i_version > 0 ) ? p_data->i_index_size : 0) + + p_data->i_offset_size + p_data->i_length_size; + if( i_read / i_entrysize < p_data->p_items[i].i_extent_count ) + { + p_data->i_item_count = i; + MP4_READBOX_EXIT( 0 ); + } + + p_data->p_items[i].p_extents = malloc( p_data->p_items[i].i_extent_count * + sizeof(p_data->p_items[i].p_extents[0]) ); + for( uint16_t j=0; j<p_data->p_items[i].i_extent_count; j++ ) + { + if( i_version > 0 ) + { + switch( p_data->i_index_size ) + { + case 4: MP4_GET4BYTES( p_data->p_items[i].p_extents[j].i_extent_index ); break; + case 8: MP4_GET8BYTES( p_data->p_items[i].p_extents[j].i_extent_index ); break; + default: break; + } + } + switch( p_data->i_offset_size ) + { + case 4: MP4_GET4BYTES( p_data->p_items[i].p_extents[j].i_extent_offset ); break; + case 8: MP4_GET8BYTES( p_data->p_items[i].p_extents[j].i_extent_offset ); break; + default: break; + } + switch( p_data->i_length_size ) + { + case 4: MP4_GET4BYTES( p_data->p_items[i].p_extents[j].i_extent_length ); break; + case 8: MP4_GET8BYTES( p_data->p_items[i].p_extents[j].i_extent_length ); break; + default: break; + } + } + } + + MP4_READBOX_EXIT( 1 ); +} + +static int MP4_ReadBox_iinf( stream_t *p_stream, MP4_Box_t *p_box ) +{ + const uint8_t *p_versionpeek; + size_t i_peek = vlc_stream_Peek( p_stream, &p_versionpeek, 9 ); + if( i_peek < 9 ) + return 0; + + size_t i_header = 12 + (( p_versionpeek[8] == 0 ) ? 2 : 4); + MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_iinf_t, i_header, NULL ); + if( i_read + 8 < i_header ) + MP4_READBOX_EXIT( 0 ); + + uint8_t i_version; + uint32_t i_flags; + MP4_GET1BYTE( i_version ); + MP4_GET3BYTES( i_flags ); VLC_UNUSED(i_flags); + if( i_version > 2 ) + MP4_READBOX_EXIT( 0 ); + + if( i_version == 0 ) + MP4_GET2BYTES( p_box->data.p_iinf->i_entry_count ); + else + MP4_GET4BYTES( p_box->data.p_iinf->i_entry_count ); + + assert( i_read == 0 ); + + uint32_t i = 0; + uint64_t i_remain = p_box->i_size - 16; + while ( i_remain > 8 && i < p_box->data.p_iinf->i_entry_count ) + { + MP4_Box_t *p_childbox = MP4_ReadBox( p_stream, p_box ); + if( !p_childbox || i_remain < p_childbox->i_size ) + { + MP4_BoxFree( p_childbox ); + p_box->data.p_iinf->i_entry_count = i; + break; + } + + MP4_BoxAddChild( p_box, p_childbox ); + i_remain -= p_childbox->i_size; + i++; + } + + if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) ) + MP4_READBOX_EXIT( 0 ); + + MP4_READBOX_EXIT( 1 ); +} + /* For generic */ static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box ) { @@ -4730,6 +4894,10 @@ static const struct /* Ambisonics */ { ATOM_SA3D, MP4_ReadBox_SA3D, 0 }, + /* iso4 brand meta references */ + { ATOM_iloc, MP4_ReadBox_iloc, ATOM_meta }, + { ATOM_iinf, MP4_ReadBox_iinf, ATOM_meta }, + /* Last entry */ { 0, MP4_ReadBox_default, 0 } }; diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h index f676dc0cac..b234138150 100644 --- a/modules/demux/mp4/libmp4.h +++ b/modules/demux/mp4/libmp4.h @@ -396,6 +396,10 @@ typedef int64_t stime_t; #define ATOM_SA3D VLC_FOURCC( 'S', 'A', '3', 'D' ) +/* iso4 meta references */ +#define ATOM_iloc VLC_FOURCC('i','l','o','c') +#define ATOM_iinf VLC_FOURCC('i','i','n','f') + #define HANDLER_mdta VLC_FOURCC('m', 'd', 't', 'a') #define HANDLER_mdir VLC_FOURCC('m', 'd', 'i', 'r') #define HANDLER_ID32 ATOM_ID32 @@ -1621,6 +1625,34 @@ typedef struct uint32_t i_num_channels; } MP4_Box_data_SA3D_t; +typedef struct +{ + uint8_t i_offset_size; + uint8_t i_length_size; + uint8_t i_base_offset_size; + uint8_t i_index_size; + uint32_t i_item_count; + struct + { + uint32_t i_item_id; + uint8_t i_construction_method; + uint16_t i_data_reference_index; + uint64_t i_base_offset; + uint16_t i_extent_count; + struct + { + uint64_t i_extent_index; + uint64_t i_extent_offset; + uint64_t i_extent_length; + } *p_extents; + } *p_items; +} MP4_Box_data_iloc_t; + +typedef struct +{ + uint32_t i_entry_count; +} MP4_Box_data_iinf_t; + /* typedef struct MP4_Box_data__s { @@ -1735,6 +1767,9 @@ typedef union MP4_Box_data_s MP4_Box_data_cbmp_t *p_cbmp; MP4_Box_data_SA3D_t *p_SA3D; + MP4_Box_data_iloc_t *p_iloc; + MP4_Box_data_iinf_t *p_iinf; + /* for generic handlers */ MP4_Box_data_binary_t *p_binary; MP4_Box_data_data_t *p_data; _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits