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 );
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 );
}
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 )
{
{ 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 },
{ 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 }
};
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 );
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 );
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 */