]> git.sesse.net Git - vlc/commitdiff
- mp4 demux: support for iTunes/Quicktime META info
authorDamien Fouilleul <damienf@videolan.org>
Thu, 1 Mar 2007 16:52:12 +0000 (16:52 +0000)
committerDamien Fouilleul <damienf@videolan.org>
Thu, 1 Mar 2007 16:52:12 +0000 (16:52 +0000)
modules/demux/mp4/libmp4.c
modules/demux/mp4/libmp4.h
modules/demux/mp4/mp4.c

index 4d5def51eb8ca38d700b0718610ab4d4e233ddcf..ab57e652ae2e2e957faeea484ba25cd601c06c07 100644 (file)
@@ -2087,10 +2087,10 @@ static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
     p_box->data.p_0xa9xxx->psz_text = NULL;
 
     MP4_GET2BYTES( i_length );
-    MP4_GET2BYTES( i_dummy );
 
     if( i_length > 0 )
     {
+        MP4_GET2BYTES( i_dummy );
         if( i_length > i_read ) i_length = i_read;
 
         p_box->data.p_0xa9xxx->psz_text = malloc( i_length + 1 );
@@ -2106,6 +2106,47 @@ static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
                  p_box->data.p_0xa9xxx->psz_text );
 #endif
     }
+    else
+    {
+        /* try iTune/Quicktime format, rewind to start */
+        p_peek -= 2; i_read += 2;
+        // we are expecting a 'data' box
+        uint32_t i_data_len;
+        uint32_t i_data_tag;
+
+        MP4_GET4BYTES( i_data_len );
+        if( i_data_len > i_read ) i_data_len = i_read;
+        MP4_GETFOURCC( i_data_tag );
+        if( (i_data_len > 0) && (i_data_tag == VLC_FOURCC('d', 'a', 't', 'a')) )
+        {
+            /* data box contains a version/flags field */
+            uint32_t i_version;
+            uint32_t i_reserved;
+            MP4_GET4BYTES( i_version );
+            MP4_GET4BYTES( i_reserved );
+            // version should be 0, flags should be 1 for text, 0 for data
+            if( i_version == 0x00000001 )
+            {
+                // the rest is the text
+                i_data_len -= 12;
+                p_box->data.p_0xa9xxx->psz_text = malloc( i_data_len + 1 );
+
+                memcpy( p_box->data.p_0xa9xxx->psz_text,
+                        p_peek, i_data_len );
+                p_box->data.p_0xa9xxx->psz_text[i_data_len] = '\0';
+#ifdef MP4_VERBOSE
+        msg_Dbg( p_stream,
+                 "read box: \"%4.4s\" text=`%s'",
+                 (char*)&p_box->i_type,
+                 p_box->data.p_0xa9xxx->psz_text );
+#endif
+            }
+            else
+            {
+                // TODO: handle data values for ID3 tag values, track num or cover art,etc...
+            }
+        }
+    }
 
     MP4_READBOX_EXIT( 1 );
 }
@@ -2114,6 +2155,25 @@ static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
     FREENULL( p_box->data.p_0xa9xxx->psz_text );
 }
 
+static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    uint8_t meta_data[8];
+    int i_actually_read;
+
+    // skip over box header
+    i_actually_read = stream_Read( p_stream, meta_data, 8 );
+    if( i_actually_read < 8 )
+        return 0;
+
+    /* meta content starts with a 4 byte version/flags value (should be 0) */
+    i_actually_read = stream_Read( p_stream, meta_data, 4 );
+    if( i_actually_read < 4 )
+        return 0;
+
+    /* then it behaves like a container */
+    return MP4_ReadBoxContainerRaw( p_stream, p_box );
+}
+
 /* For generic */
 static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
 {
@@ -2184,6 +2244,7 @@ static struct
     { FOURCC_tref,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
     { FOURCC_gmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
     { FOURCC_wave,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
+    { FOURCC_ilst,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
 
     /* specific box */
     { FOURCC_ftyp,  MP4_ReadBox_ftyp,       MP4_FreeBox_ftyp },
@@ -2338,6 +2399,9 @@ static struct
     { FOURCC_0xa9ope,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
     { FOURCC_0xa9com,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
 
+    /* iTunes/Quicktime meta info */
+    { FOURCC_meta,  MP4_ReadBox_meta,       MP4_FreeBox_Common },
+
     /* Last entry */
     { 0,             MP4_ReadBox_default,       NULL }
 };
index b56be3b9437f796069ea738d1c05448d1f0110a1..33f091fc5a0b1c448fcd2d8cc282465eace44027 100644 (file)
 #define FOURCC_0xa9gen VLC_FOURCC( 0xa9, 'g', 'e', 'n' )
 #define FOURCC_WLOC VLC_FOURCC( 'W', 'L', 'O', 'C' )
 
+#define FOURCC_meta VLC_FOURCC( 'm', 'e', 't', 'a' )
+#define FOURCC_ilst VLC_FOURCC( 'i', 'l', 's', 't' )
+
 /* Do you want some debug information on all read boxes ? */
 #define MP4_VERBOSE  1
 
index 7f9b5875c091f885bde10e7ba9c5034cb45eac34..18ca1cc2a843801b9d330f30ddee760ebbe7159e 100644 (file)
@@ -783,16 +783,23 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
         case DEMUX_GET_META:
         {
             vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t*);
-            MP4_Box_t  *p_udta   = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
             MP4_Box_t  *p_0xa9xxx;
+
+            MP4_Box_t  *p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta/meta/ilst" );
             if( p_udta == NULL )
             {
-                return VLC_EGENERIC;
+                p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
+                if( p_udta == NULL )
+                {
+                    return VLC_EGENERIC;
+                }
             }
+
             for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
                  p_0xa9xxx = p_0xa9xxx->p_next )
             {
                 char *psz_utf;
+
                 if( !p_0xa9xxx || !p_0xa9xxx->data.p_0xa9xxx )
                     continue;
                 psz_utf = strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text );
@@ -805,7 +812,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
                 switch( p_0xa9xxx->i_type )
                 {
                 case FOURCC_0xa9nam: /* Full name */
-                    vlc_meta_SetArtist( p_meta, psz_utf );
+                    vlc_meta_SetTitle( p_meta, psz_utf );
                     break;
                 case FOURCC_0xa9aut:
                     vlc_meta_SetArtist( p_meta, psz_utf );
@@ -826,9 +833,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
                     vlc_meta_SetGenre( p_meta, psz_utf );
                     break;
 
+                case FOURCC_0xa9alb: /* Album */
+                    vlc_meta_SetAlbum( p_meta, psz_utf );
+                    break;
+
                 case FOURCC_0xa9swr:
                 case FOURCC_0xa9inf: /* Information */
-                case FOURCC_0xa9alb: /* Album */
                 case FOURCC_0xa9dir: /* Director */
                 case FOURCC_0xa9dis: /* Disclaimer */
                 case FOURCC_0xa9enc: /* Encoded By */