[vlc-commits] demux: mp4: read covr atoms (fix #8091)

Francois Cartegnie git at videolan.org
Wed Mar 26 07:43:38 CET 2014


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Mar 26 07:37:56 2014 +0100| [c9cce4e91f34b96b2cbaa9b39aadb6a65852e674] | committer: Francois Cartegnie

demux: mp4: read covr atoms (fix #8091)

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

 modules/demux/mp4/libmp4.c |   25 ++++++++++++++
 modules/demux/mp4/libmp4.h |    9 ++++++
 modules/demux/mp4/mp4.c    |   77 +++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index ab6edc8..52ae9ca 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -2622,6 +2622,29 @@ static void MP4_FreeBox_name( MP4_Box_t *p_box )
     FREENULL( p_box->data.p_name->psz_text );
 }
 
+static int MP4_ReadBox_data( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_data_t );
+
+    /* What's that header ?? */
+    if ( i_read <= 8 )
+        MP4_READBOX_EXIT( 0 );
+
+    p_box->data.p_data->p_blob = malloc( i_read - 8 );
+    if ( !p_box->data.p_data->p_blob )
+        MP4_READBOX_EXIT( 0 );
+
+    p_box->data.p_data->i_blob = i_read - 8;
+    memcpy( p_box->data.p_data->p_blob, p_peek + 8, i_read - 8 );
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static void MP4_FreeBox_data( MP4_Box_t *p_box )
+{
+    free( p_box->data.p_data->p_blob );
+}
+
 static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
 {
     uint16_t i16;
@@ -3380,6 +3403,8 @@ static const struct
     /* iTunes/Quicktime meta info */
     { ATOM_meta,    MP4_ReadBox_meta,         MP4_FreeBox_Common },
     { ATOM_name,    MP4_ReadBox_name,         MP4_FreeBox_name },
+    { ATOM_covr,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
+    { ATOM_data,    MP4_ReadBox_data,         MP4_FreeBox_data },
 
     /* found in smoothstreaming */
     { ATOM_traf,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index c6c0aaf..aac5e3f 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -261,6 +261,7 @@
 
 #define ATOM_meta VLC_FOURCC( 'm', 'e', 't', 'a' )
 #define ATOM_ilst VLC_FOURCC( 'i', 'l', 's', 't' )
+#define ATOM_covr VLC_FOURCC( 'c', 'o', 'v', 'r' )
 
 #define ATOM_chap VLC_FOURCC( 'c', 'h', 'a', 'p' )
 
@@ -1164,6 +1165,12 @@ typedef struct
     uint8_t *p_hvcC;
 } MP4_Box_data_hvcC_t;
 
+typedef struct
+{
+    uint8_t *p_blob;
+    uint32_t i_blob;
+} MP4_Box_data_data_t;
+
 /*
 typedef struct MP4_Box_data__s
 {
@@ -1250,6 +1257,8 @@ typedef union MP4_Box_data_s
     MP4_Box_data_tfxd_t *p_tfxd;
     MP4_Box_data_hvcC_t *p_hvcC;
 
+    MP4_Box_data_data_t *p_data;
+
     void                *p_payload; /* for unknow type */
 } MP4_Box_data_t;
 
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 99435b5..c3038f4 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -952,19 +952,89 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             *pf = p_sys->f_fps;
             return VLC_SUCCESS;
 
+        case DEMUX_GET_ATTACHMENTS:
+        {
+            input_attachment_t ***ppp_attach = va_arg( args, input_attachment_t*** );
+            int *pi_int = va_arg( args, int * );
+
+            MP4_Box_t  *p_covr = MP4_BoxGet( p_sys->p_root, "/moov/udta/meta/ilst/covr" );
+            if ( !p_covr ) return VLC_EGENERIC;
+            MP4_Box_t  *p_box;
+            int i_count = 0;
+
+            for( p_box = p_covr->p_first; p_box != NULL; p_box = p_box->p_next )
+            {
+                if ( p_box->i_type == ATOM_data && p_box->data.p_data->i_blob >= 16 )
+                    i_count++;
+            }
+
+            if ( i_count == 0 )
+                return VLC_EGENERIC;
+
+            *ppp_attach = (input_attachment_t**)
+                    malloc( sizeof(input_attachment_t*) * i_count );
+            if( !(*ppp_attach) ) return VLC_ENOMEM;
+            char *psz_mime;
+            char *psz_filename;
+            i_count = 0;
+            for( p_box = p_covr->p_first; p_box != NULL; p_box = p_box->p_next )
+            {
+                if ( p_box->i_type != ATOM_data || p_box->data.p_data->i_blob < 16 )
+                    continue;
+
+                if ( !memcmp( p_box->data.p_data->p_blob,
+                              "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8 ) )
+                {
+                    psz_mime = strdup( "image/png" );
+                }
+                else if ( !memcmp( p_box->data.p_data->p_blob, "\xFF\xD8", 2 ) )
+                {
+                    psz_mime = strdup( "image/jpeg" );
+                }
+                else
+                {
+                    continue;
+                }
+
+                if ( asprintf( &psz_filename, "picture%u", i_count ) >= 0 )
+                {
+                    (*ppp_attach)[i_count++] =
+                        vlc_input_attachment_New( psz_filename, psz_mime, NULL,
+                            p_box->data.p_data->p_blob, p_box->data.p_data->i_blob );
+                    free( psz_filename );
+                }
+
+                free( psz_mime );
+            }
+
+            if ( i_count == 0 )
+            {
+                free( *ppp_attach );
+                return VLC_EGENERIC;
+            }
+
+            *pi_int = i_count;
+
+            return VLC_SUCCESS;
+        }
+
         case DEMUX_GET_META:
         {
             vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t*);
             MP4_Box_t  *p_0xa9xxx;
 
+            MP4_Box_t *p_covr = MP4_BoxGet( p_sys->p_root, "/moov/udta/meta/ilst/covr/data[0]" );
+            if ( p_covr )
+                vlc_meta_SetArtURL( p_meta, "attachment://picture0" );
+
             MP4_Box_t  *p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta/meta/ilst" );
             if( p_udta == NULL )
             {
                 p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
-                if( p_udta == NULL )
-                {
+                if( p_udta == NULL && p_covr == NULL )
                     return VLC_EGENERIC;
-                }
+                else
+                    return VLC_SUCCESS;
             }
 
             for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
@@ -1146,7 +1216,6 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
         case DEMUX_SET_NEXT_DEMUX_TIME:
         case DEMUX_SET_GROUP:
         case DEMUX_HAS_UNSUPPORTED_META:
-        case DEMUX_GET_ATTACHMENTS:
         case DEMUX_GET_PTS_DELAY:
         case DEMUX_CAN_RECORD:
             return VLC_EGENERIC;



More information about the vlc-commits mailing list