[vlc-commits] demux: libmp4: always check meta atom header

Francois Cartegnie git at videolan.org
Mon Sep 5 10:36:30 CEST 2016


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Sep  5 09:42:58 2016 +0200| [7f70e1cd7e6b1a7223c45f30d5e1d4b5fe6ee6b8] | committer: Francois Cartegnie

demux: libmp4: always check meta atom header

As in qtff && iso specs, should always be w/header.
Some incorrect meta atoms have none.
Simplifies both cases.

refs MP4-Tags-Sample.mp4, 6_Channel_ID.mov

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7f70e1cd7e6b1a7223c45f30d5e1d4b5fe6ee6b8
---

 modules/demux/mp4/libmp4.c | 47 +++++++++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index 807680e..ad8fdfe 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -3558,40 +3558,53 @@ static int MP4_ReadBox_colr( stream_t *p_stream, MP4_Box_t *p_box )
 
 static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
 {
-    uint8_t meta_data[8];
-    int i_actually_read;
+    const uint8_t *p_peek;
     const size_t i_headersize = mp4_box_headersize( p_box );
 
-    if( p_box->i_size < 8 || p_box->i_size - i_headersize < 4 )
+    if( p_box->i_size < 16 || p_box->i_size - i_headersize < 8 )
+        return 0;
+
+    /* skip over box header */
+    if( vlc_stream_Read( p_stream, NULL, i_headersize ) < (ssize_t) i_headersize )
         return 0;
 
-    // skip over box header
-    i_actually_read = vlc_stream_Read( p_stream, meta_data, i_headersize );
-    if( i_actually_read < i_headersize )
+    /* meta content starts with a 4 byte version/flags value (should be 0) */
+    if( vlc_stream_Peek( p_stream, &p_peek, 8 ) < 8 )
         return 0;
 
-    if ( p_box->p_father && p_box->p_father->i_type == ATOM_udta ) /* itunes udta/meta */
+    if( !memcmp( p_peek, "\0\0\0", 4 ) ) /* correct header case */
     {
-        /* meta content starts with a 4 byte version/flags value (should be 0) */
-        i_actually_read = vlc_stream_Read( p_stream, meta_data, 4 );
-        if( i_actually_read < 4 || memcmp( meta_data, "\0\0\0", 4 ) )
+        if( vlc_stream_Read( p_stream, NULL, 4 ) < 4 )
             return 0;
     }
+    else if( memcmp( &p_peek[4], "hdlr", 4 ) ) /* Broken, headerless ones */
+    {
+       return 0;
+    }
 
+    /* load child atoms up to the handler (which should be next anyway) */
     const uint32_t stoplist[] = { ATOM_hdlr, 0 };
     if ( !MP4_ReadBoxContainerChildren( p_stream, p_box, stoplist ) )
         return 0;
 
     /* Mandatory */
     const MP4_Box_t *p_hdlr = MP4_BoxGet( p_box, "hdlr" );
-    if ( !p_hdlr || !BOXDATA(p_hdlr) ||
-         ( BOXDATA(p_hdlr)->i_handler_type != HANDLER_mdta &&
-           BOXDATA(p_hdlr)->i_handler_type != HANDLER_mdir ) ||
-         BOXDATA(p_hdlr)->i_version != 0 )
-        return 0;
+    if ( p_hdlr && BOXDATA(p_hdlr) && BOXDATA(p_hdlr)->i_version == 0 )
+    {
+        p_box->i_handler = BOXDATA(p_hdlr)->i_handler_type;
+        switch( p_box->i_handler )
+        {
+            case HANDLER_mdta:
+            case HANDLER_mdir:
+                /* then it behaves like a container */
+                return MP4_ReadBoxContainerChildren( p_stream, p_box, NULL );
+            default:
+                /* skip parsing, will be seen as empty container */
+                break;
+        }
+    }
 
-    /* then it behaves like a container */
-    return MP4_ReadBoxContainerChildren( p_stream, p_box, NULL );
+    return 1;
 }
 
 static int MP4_ReadBox_iods( stream_t *p_stream, MP4_Box_t *p_box )



More information about the vlc-commits mailing list