diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c index 73618c1cfc..681b4f2708 100644 --- a/modules/demux/mp4/libmp4.c +++ b/modules/demux/mp4/libmp4.c @@ -4513,6 +4513,87 @@ static int MP4_ReadBox_ispe( stream_t *p_stream, MP4_Box_t *p_box ) MP4_READBOX_EXIT( 1 ); } +static void MP4_FreeBox_ipma( MP4_Box_t *p_box ) +{ + MP4_Box_data_ipma_t *p_data = p_box->data.p_ipma; + for( uint32_t i=0; ii_entry_count; i++ ) + free( p_data->p_entries[i].p_assocs ); + free( p_data->p_entries ); +} + +static int MP4_ReadBox_ipma( stream_t *p_stream, MP4_Box_t *p_box ) +{ + MP4_READBOX_ENTER( MP4_Box_data_ipma_t, MP4_FreeBox_ipma ); + MP4_Box_data_ipma_t *p_data = p_box->data.p_ipma; + + uint8_t i_version; + uint32_t i_flags; + MP4_GET1BYTE( i_version ); + MP4_GET3BYTES( i_flags ); + + MP4_GET4BYTES( p_data->i_entry_count ); + if( (i_read / ((i_version < 1) ? 3 : 5) < p_data->i_entry_count) ) + { + p_data->i_entry_count = 0; + MP4_READBOX_EXIT( 0 ); + } + + p_data->p_entries = malloc( sizeof(p_data->p_entries[0]) * p_data->i_entry_count ); + if( !p_data->p_entries ) + { + p_data->i_entry_count = 0; + MP4_READBOX_EXIT( 0 ); + } + + for( uint32_t i=0; ii_entry_count; i++ ) + { + if( i_read < ((i_version < 1) ? 3 : 5) ) + { + p_data->i_entry_count = i; + MP4_READBOX_EXIT( 0 ); + } + if( i_version < 1 ) + MP4_GET2BYTES( p_data->p_entries[i].i_item_id ); + else + MP4_GET4BYTES( p_data->p_entries[i].i_item_id ); + MP4_GET1BYTE( p_data->p_entries[i].i_association_count ); + + if( i_read / ((i_flags & 0x01) ? 2 : 1) < + p_data->p_entries[i].i_association_count ) + { + p_data->i_entry_count = i; + MP4_READBOX_EXIT( 0 ); + } + + p_data->p_entries[i].p_assocs = + malloc( sizeof(p_data->p_entries[i].p_assocs[0]) * + p_data->p_entries[i].i_association_count ); + if( !p_data->p_entries[i].p_assocs ) + { + p_data->p_entries[i].i_association_count = 0; + p_data->i_entry_count = i; + MP4_READBOX_EXIT( 0 ); + } + + for( uint8_t j=0; jp_entries[i].i_association_count; j++ ) + { + MP4_GET1BYTE( p_data->p_entries[i].p_assocs[j].i_property_index ); + p_data->p_entries[i].p_assocs[j].b_essential = + p_data->p_entries[i].p_assocs[j].i_property_index & 0x80; + p_data->p_entries[i].p_assocs[j].i_property_index &= 0x7F; + if( i_flags & 0x01 ) + { + p_data->p_entries[i].p_assocs[j].i_property_index <<= 8; + uint8_t i_low; + MP4_GET1BYTE( i_low ); + p_data->p_entries[i].p_assocs[j].i_property_index |= i_low; + } + } + } + + MP4_READBOX_EXIT( 1 ); +} + /* For generic */ static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box ) { @@ -5001,6 +5082,7 @@ static const struct { ATOM_iprp, MP4_ReadBoxContainer, ATOM_meta }, { ATOM_ipco, MP4_ReadBoxContainer, ATOM_iprp }, { ATOM_ispe, MP4_ReadBox_ispe, ATOM_ipco }, + { ATOM_ipma, MP4_ReadBox_ipma, ATOM_iprp }, /* Last entry */ { 0, MP4_ReadBox_default, 0 } diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h index 33993f6c6c..5561ad1058 100644 --- a/modules/demux/mp4/libmp4.h +++ b/modules/demux/mp4/libmp4.h @@ -405,6 +405,7 @@ typedef int64_t stime_t; #define ATOM_iprp VLC_FOURCC('i','p','r','p') #define ATOM_ipco VLC_FOURCC('i','p','c','o') #define ATOM_ispe VLC_FOURCC('i','s','p','e') +#define ATOM_ipma VLC_FOURCC('i','p','m','a') #define HANDLER_mdta VLC_FOURCC('m', 'd', 't', 'a') #define HANDLER_mdir VLC_FOURCC('m', 'd', 'i', 'r') @@ -1685,6 +1686,21 @@ typedef struct uint32_t i_height; } MP4_Box_data_ispe_t; +typedef struct +{ + uint32_t i_entry_count; + struct + { + uint32_t i_item_id; + uint8_t i_association_count; + struct + { + uint8_t b_essential; + uint16_t i_property_index; + } *p_assocs; + } *p_entries; +} MP4_Box_data_ipma_t; + /* typedef struct MP4_Box_data__s { @@ -1804,6 +1820,7 @@ typedef union MP4_Box_data_s MP4_Box_data_infe_t *p_infe; MP4_Box_data_pitm_t *p_pitm; MP4_Box_data_ispe_t *p_ispe; /* heif */ + MP4_Box_data_ipma_t *p_ipma; /* heif */ /* for generic handlers */ MP4_Box_data_binary_t *p_binary;