[vlc-commits] demux: libmp4: read iloc

Francois Cartegnie git at videolan.org
Tue Mar 13 19:09:32 CET 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at 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;



More information about the vlc-commits mailing list