From 14c5e914ffb2ca51676a2d6c6b081a8e324fe47e Mon Sep 17 00:00:00 2001 From: Damien Fouilleul Date: Thu, 1 Mar 2007 16:52:12 +0000 Subject: [PATCH] - mp4 demux: support for iTunes/Quicktime META info --- modules/demux/mp4/libmp4.c | 66 +++++++++++++++++++++++++++++++++++++- modules/demux/mp4/libmp4.h | 3 ++ modules/demux/mp4/mp4.c | 18 ++++++++--- 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c index 4d5def51eb..ab57e652ae 100644 --- a/modules/demux/mp4/libmp4.c +++ b/modules/demux/mp4/libmp4.c @@ -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 } }; diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h index b56be3b943..33f091fc5a 100644 --- a/modules/demux/mp4/libmp4.h +++ b/modules/demux/mp4/libmp4.h @@ -209,6 +209,9 @@ #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 diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c index 7f9b5875c0..18ca1cc2a8 100644 --- a/modules/demux/mp4/mp4.c +++ b/modules/demux/mp4/mp4.c @@ -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 */ -- 2.39.2