Commit b0ad53b6 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: mp4: rewrite meta handling

Follow the spec and correctly handle text encoding
parent 84726b40
......@@ -193,7 +193,7 @@ libmp4_plugin_la_SOURCES = demux/mp4/mp4.c demux/mp4/mp4.h \
demux/mp4/libmp4.c demux/mp4/libmp4.h \
demux/mp4/id3genres.h demux/mp4/languages.h \
demux/asf/asfpacket.c demux/asf/asfpacket.h \
demux/mp4/essetup.c
demux/mp4/essetup.c demux/mp4/meta.c
libmp4_plugin_la_LIBADD = $(LIBM)
libmp4_plugin_la_LDFLAGS = $(AM_LDFLAGS)
if HAVE_ZLIB
......
......@@ -2967,89 +2967,62 @@ static void MP4_FreeBox_data( MP4_Box_t *p_box )
free( p_box->data.p_data->p_blob );
}
static int MP4_ReadBox_Metadata( stream_t *p_stream, MP4_Box_t *p_box )
{
const uint8_t *p_peek;
if ( stream_Peek( p_stream, &p_peek, 16 ) < 16 )
return 0;
if ( stream_Read( p_stream, NULL, 8 ) < 8 )
return 0;
return MP4_ReadBoxContainerChildren( p_stream, p_box, ATOM_data );
}
static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
{
uint16_t i16;
return MP4_ReadBox_Metadata( p_stream, p_box );
MP4_READBOX_ENTER( MP4_Box_data_string_t );
/* FIXME: find out what was that 2 bytes sized atom and its own handler */
// if ( GetWBE( &p_peek[8] ) > 0 )
// uint16_t i16;
p_box->data.p_string->psz_text = NULL;
// MP4_READBOX_ENTER( MP4_Box_data_string_t );
MP4_GET2BYTES( i16 );
// p_box->data.p_string->psz_text = NULL;
if( i16 > 0 )
{
int i_length = i16;
// MP4_GET2BYTES( i16 );
MP4_GET2BYTES( i16 );
if( i_length >= i_read ) i_length = i_read + 1;
// if( i16 > 0 )
// {
// int i_length = i16;
p_box->data.p_string->psz_text = malloc( i_length );
if( p_box->data.p_string->psz_text == NULL )
MP4_READBOX_EXIT( 0 );
// MP4_GET2BYTES( i16 );
// if( i_length >= i_read ) i_length = i_read + 1;
i_length--;
memcpy( p_box->data.p_string->psz_text,
p_peek, i_length );
p_box->data.p_string->psz_text[i_length] = '\0';
// p_box->data.p_string->psz_text = malloc( i_length );
// if( p_box->data.p_string->psz_text == NULL )
// MP4_READBOX_EXIT( 0 );
#ifdef MP4_VERBOSE
msg_Dbg( p_stream,
"read box: \"c%3.3s\" text=`%s'",
((char*)&p_box->i_type + 1),
p_box->data.p_string->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;
// i_length--;
// memcpy( p_box->data.p_string->psz_text,
// p_peek, i_length );
// p_box->data.p_string->psz_text[i_length] = '\0';
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 == ATOM_data) )
{
/* data box contains a version/flags field */
uint32_t i_version;
uint32_t i_reserved;
VLC_UNUSED(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 ) && (i_data_len >= 12 ) )
{
// the rest is the text
i_data_len -= 12;
p_box->data.p_string->psz_text = malloc( i_data_len + 1 );
if( p_box->data.p_string->psz_text == NULL )
MP4_READBOX_EXIT( 0 );
memcpy( p_box->data.p_string->psz_text,
p_peek, i_data_len );
p_box->data.p_string->psz_text[i_data_len] = '\0';
#ifdef MP4_VERBOSE
msg_Dbg( p_stream,
"read box: \"c%3.3s\" text=`%s'",
((char*)&p_box->i_type+1),
p_box->data.p_string->psz_text );
#endif
}
else
{
// TODO: handle data values for ID3 tag values, track num or cover art,etc...
}
}
}
//#ifdef MP4_VERBOSE
// msg_Dbg( p_stream,
// "read box: \"c%3.3s\" text=`%s'",
// ((char*)&p_box->i_type + 1),
// p_box->data.p_string->psz_text );
//#endif
// }
// else
MP4_READBOX_EXIT( 1 );
// MP4_READBOX_EXIT( 1 );
}
static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
{
FREENULL( p_box->data.p_string->psz_text );
/* If Meta, that box should be empty /common */
if( p_box->data.p_string )
FREENULL( p_box->data.p_string->psz_text );
}
/* Chapter support */
......
This diff is collapsed.
......@@ -34,13 +34,10 @@
#include <vlc_demux.h>
#include <vlc_charset.h> /* EnsureUTF8 */
#include <vlc_meta.h> /* vlc_meta_t, vlc_meta_ */
#include <vlc_input.h>
#include <vlc_aout.h>
#include <assert.h>
#include "id3genres.h" /* for ATOM_gnre */
/*****************************************************************************
* Module descriptor
*****************************************************************************/
......@@ -1528,149 +1525,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
if( p_udta == NULL && p_data == NULL )
return VLC_EGENERIC;
for( const MP4_Box_t * p_string = p_udta->p_first; p_string != NULL;
p_string = p_string->p_next )
{
if( !p_string || !BOXDATA(p_string) ) /* !WARN could be data atoms ! */
continue;
/* FIXME FIXME: should convert from whatever the character
* encoding of MP4 meta data is to UTF-8. */
#define SET(fct) do { char *psz_utf = strdup( BOXDATA(p_string)->psz_text ? BOXDATA(p_string)->psz_text : "" ); \
if( psz_utf ) { EnsureUTF8( psz_utf ); \
fct( p_meta, psz_utf ); free( psz_utf ); } } while(0)
/* XXX Becarefull p_udta can have box that are not 0xa9xx */
switch( p_string->i_type )
{
case ATOM_0xa9nam: /* Full name */
SET( vlc_meta_SetTitle );
break;
case ATOM_0xa9aut:
SET( vlc_meta_SetArtist );
break;
case ATOM_0xa9ART:
SET( vlc_meta_SetArtist );
break;
case ATOM_0xa9cpy:
SET( vlc_meta_SetCopyright );
break;
case ATOM_0xa9day: /* Creation Date */
SET( vlc_meta_SetDate );
break;
case ATOM_0xa9des: /* Description */
SET( vlc_meta_SetDescription );
break;
case ATOM_0xa9gen: /* Genre */
SET( vlc_meta_SetGenre );
break;
case ATOM_gnre:
if( p_string->data.p_gnre->i_genre <= NUM_GENRES )
vlc_meta_SetGenre( p_meta, ppsz_genres[p_string->data.p_gnre->i_genre - 1] );
break;
case ATOM_0xa9alb: /* Album */
SET( vlc_meta_SetAlbum );
break;
case ATOM_0xa9trk: /* Track */
SET( vlc_meta_SetTrackNum );
break;
case ATOM_trkn:
{
char psz_trck[11];
snprintf( psz_trck, sizeof( psz_trck ), "%i",
p_string->data.p_trkn->i_track_number );
vlc_meta_SetTrackNum( p_meta, psz_trck );
if( p_string->data.p_trkn->i_track_total > 0 )
{
snprintf( psz_trck, sizeof( psz_trck ), "%i",
p_string->data.p_trkn->i_track_total );
vlc_meta_Set( p_meta, vlc_meta_TrackTotal, psz_trck );
}
break;
}
case ATOM_0xa9cmt: /* Commment */
SET( vlc_meta_SetDescription );
break;
case ATOM_0xa9url: /* URL */
SET( vlc_meta_SetURL );
break;
case ATOM_0xa9too: /* Encoder Tool */
case ATOM_0xa9enc: /* Encoded By */
SET( vlc_meta_SetEncodedBy );
break;
case ATOM_0xa9pub:
SET( vlc_meta_SetPublisher );
break;
SetupMeta( p_meta, p_udta );
case ATOM_0xa9dir:
SET( vlc_meta_SetDirector );
break;
default:
break;
}
#undef SET
static const struct { uint32_t xa9_type; char metadata[25]; } xa9typetoextrameta[] =
{
{ ATOM_0xa9wrt, N_("Writer") },
{ ATOM_0xa9com, N_("Composer") },
{ ATOM_0xa9prd, N_("Producer") },
{ ATOM_0xa9inf, N_("Information") },
{ ATOM_0xa9dis, N_("Disclaimer") },
{ ATOM_0xa9req, N_("Requirements") },
{ ATOM_0xa9fmt, N_("Original Format") },
{ ATOM_0xa9dsa, N_("Display Source As") },
{ ATOM_0xa9hst, N_("Host Computer") },
{ ATOM_0xa9prf, N_("Performers") },
{ ATOM_0xa9ope, N_("Original Performer") },
{ ATOM_0xa9src, N_("Providers Source Content") },
{ ATOM_0xa9wrn, N_("Warning") },
{ ATOM_0xa9swr, N_("Software") },
{ ATOM_0xa9lyr, N_("Lyrics") },
{ ATOM_0xa9mak, N_("Record Company") },
{ ATOM_0xa9mod, N_("Model") },
{ ATOM_0xa9PRD, N_("Product") },
{ ATOM_0xa9grp, N_("Grouping") },
{ ATOM_0xa9gen, N_("Genre") },
{ ATOM_0xa9st3, N_("Sub-Title") },
{ ATOM_0xa9arg, N_("Arranger") },
{ ATOM_0xa9ard, N_("Art Director") },
{ ATOM_0xa9cak, N_("Copyright Acknowledgement") },
{ ATOM_0xa9con, N_("Conductor") },
{ ATOM_0xa9des, N_("Song Description") },
{ ATOM_0xa9lnt, N_("Liner Notes") },
{ ATOM_0xa9phg, N_("Phonogram Rights") },
{ ATOM_0xa9pub, N_("Publisher") },
{ ATOM_0xa9sne, N_("Sound Engineer") },
{ ATOM_0xa9sol, N_("Soloist") },
{ ATOM_0xa9thx, N_("Thanks") },
{ ATOM_0xa9xpd, N_("Executive Producer") },
{ ATOM_vndr, N_("Vendor") },
{ 0, "" },
};
for( unsigned i = 0; xa9typetoextrameta[i].xa9_type; i++ )
{
if( p_string->i_type == xa9typetoextrameta[i].xa9_type )
{
assert( BOXDATA(p_string) );
char *psz_utf = strdup( BOXDATA(p_string)->psz_text ? BOXDATA(p_string)->psz_text : "" );
if( psz_utf )
{
EnsureUTF8( psz_utf );
vlc_meta_AddExtra( p_meta, _(xa9typetoextrameta[i].metadata), psz_utf );
free( psz_utf );
}
break;
}
}
}
return VLC_SUCCESS;
}
......
......@@ -155,4 +155,5 @@ struct mp4_fragment_t
int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample );
int SetupAudioES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample );
int SetupSpuES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample );
void SetupMeta( vlc_meta_t *p_meta, MP4_Box_t *p_udta );
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment