1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2012-2017 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
29 #include "box_default.h"
31 static isom_data_t
*isom_add_metadata( lsmash_file_t
*file
,
32 lsmash_itunes_metadata_item item
,
33 char *meaning_string
, char *name_string
)
35 assert( LSMASH_IS_EXISTING_BOX( file
->moov
) );
36 if( ((item
== ITUNES_METADATA_ITEM_CUSTOM
) && (!meaning_string
|| !meaning_string
[0]) )
37 || (LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
)
38 && LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_udta( file
->moov
) ))
39 || (LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
->meta
)
40 && LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_meta( file
->moov
->udta
) ))
41 || (LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
->meta
->ilst
)
42 && LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_ilst( file
->moov
->udta
->meta
) )) )
43 return isom_non_existing_data();
44 if( LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
->meta
->hdlr
) )
46 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_hdlr( file
->moov
->udta
->meta
) )
47 || isom_setup_handler_reference( file
->moov
->udta
->meta
->hdlr
, ISOM_META_HANDLER_TYPE_ITUNES_METADATA
) < 0 )
48 return isom_non_existing_data();
50 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
51 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_metaitem( ilst
, item
) ) )
52 return isom_non_existing_data();
53 isom_metaitem_t
*metaitem
= (isom_metaitem_t
*)ilst
->metaitem_list
.tail
->data
;
54 if( item
== ITUNES_METADATA_ITEM_CUSTOM
)
56 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_mean( metaitem
) ) )
58 isom_mean_t
*mean
= metaitem
->mean
;
59 mean
->meaning_string_length
= strlen( meaning_string
); /* No null terminator */
60 mean
->meaning_string
= lsmash_memdup( meaning_string
, mean
->meaning_string_length
);
61 if( !mean
->meaning_string
)
63 if( name_string
&& name_string
[0] )
65 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_name( metaitem
) ) )
67 isom_name_t
*name
= metaitem
->name
;
68 name
->name_length
= strlen( name_string
); /* No null terminator */
69 name
->name
= lsmash_memdup( name_string
, name
->name_length
);
74 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_data( metaitem
) ) )
76 return metaitem
->data
;
78 isom_remove_box_by_itself( metaitem
);
79 return isom_non_existing_data();
82 static int isom_set_itunes_metadata_string( lsmash_file_t
*file
,
83 lsmash_itunes_metadata_item item
,
84 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
86 uint32_t value_length
= strlen( value
.string
);
87 if( item
== ITUNES_METADATA_ITEM_DESCRIPTION
&& value_length
> 255 )
88 item
= ITUNES_METADATA_ITEM_LONG_DESCRIPTION
;
89 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
90 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
91 return LSMASH_ERR_NAMELESS
;
92 data
->type_code
= ITUNES_METADATA_SUBTYPE_UTF8
;
93 data
->value_length
= value_length
; /* No null terminator */
94 data
->value
= lsmash_memdup( value
.string
, data
->value_length
);
97 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
98 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
99 return LSMASH_ERR_MEMORY_ALLOC
;
104 static int isom_set_itunes_metadata_integer( lsmash_file_t
*file
,
105 lsmash_itunes_metadata_item item
,
106 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
110 lsmash_itunes_metadata_item item
;
112 } metadata_code_type_table
[] =
114 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID
, 1 },
115 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE
, 2 },
116 { ITUNES_METADATA_ITEM_CONTENT_RATING
, 1 },
117 { ITUNES_METADATA_ITEM_MEDIA_TYPE
, 1 },
118 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE
, 2 },
119 { ITUNES_METADATA_ITEM_TV_EPISODE
, 4 },
120 { ITUNES_METADATA_ITEM_TV_SEASON
, 4 },
121 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE
, 1 },
122 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID
, 4 },
123 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID
, 4 },
124 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID
, 4 },
125 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID
, 4 },
126 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID
, 8 },
127 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE
, 4 },
128 { ITUNES_METADATA_ITEM_CUSTOM
, 8 },
132 for( i
= 0; metadata_code_type_table
[i
].item
; i
++ )
133 if( item
== metadata_code_type_table
[i
].item
)
135 if( metadata_code_type_table
[i
].length
== 0 )
136 return LSMASH_ERR_NAMELESS
;
137 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
138 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
139 return LSMASH_ERR_NAMELESS
;
140 if( item
== ITUNES_METADATA_ITEM_PREDEFINED_GENRE
)
141 data
->type_code
= ITUNES_METADATA_SUBTYPE_IMPLICIT
;
143 data
->type_code
= ITUNES_METADATA_SUBTYPE_INTEGER
;
144 data
->value_length
= metadata_code_type_table
[i
].length
;
146 for( i
= 0; i
< data
->value_length
; i
++ )
148 int shift
= (data
->value_length
- i
- 1) * 8;
149 temp
[i
] = (value
.integer
>> shift
) & 0xff;
151 data
->value
= lsmash_memdup( temp
, data
->value_length
);
154 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
155 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
156 return LSMASH_ERR_MEMORY_ALLOC
;
161 static int isom_set_itunes_metadata_boolean( lsmash_file_t
*file
,
162 lsmash_itunes_metadata_item item
,
163 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
165 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
166 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
167 return LSMASH_ERR_NAMELESS
;
168 data
->type_code
= ITUNES_METADATA_SUBTYPE_INTEGER
;
169 data
->value_length
= 1;
170 uint8_t temp
= (uint8_t)value
.boolean
;
171 data
->value
= lsmash_memdup( &temp
, 1 );
174 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
175 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
176 return LSMASH_ERR_MEMORY_ALLOC
;
181 static int isom_set_itunes_metadata_binary( lsmash_file_t
*file
,
182 lsmash_itunes_metadata_item item
,
183 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
185 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
186 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
187 return LSMASH_ERR_NAMELESS
;
190 case ITUNES_METADATA_ITEM_COVER_ART
:
191 if( value
.binary
.subtype
!= ITUNES_METADATA_SUBTYPE_JPEG
192 && value
.binary
.subtype
!= ITUNES_METADATA_SUBTYPE_PNG
193 && value
.binary
.subtype
!= ITUNES_METADATA_SUBTYPE_BMP
)
194 return LSMASH_ERR_FUNCTION_PARAM
;
196 case ITUNES_METADATA_ITEM_DISC_NUMBER
:
197 case ITUNES_METADATA_ITEM_TRACK_NUMBER
:
198 value
.binary
.subtype
= ITUNES_METADATA_SUBTYPE_IMPLICIT
;
203 switch( value
.binary
.subtype
)
205 case ITUNES_METADATA_SUBTYPE_UUID
:
206 if( value
.binary
.size
!= 16 )
207 return LSMASH_ERR_FUNCTION_PARAM
;
209 case ITUNES_METADATA_SUBTYPE_DURATION
:
210 if( value
.binary
.size
!= 4 )
211 return LSMASH_ERR_FUNCTION_PARAM
;
213 case ITUNES_METADATA_SUBTYPE_TIME
:
214 if( value
.binary
.size
!= 4 && value
.binary
.size
!= 8 )
215 return LSMASH_ERR_FUNCTION_PARAM
;
217 case ITUNES_METADATA_SUBTYPE_INTEGER
:
218 if( value
.binary
.size
!= 1 && value
.binary
.size
!= 2
219 && value
.binary
.size
!= 3 && value
.binary
.size
!= 4
220 && value
.binary
.size
!= 8 )
221 return LSMASH_ERR_FUNCTION_PARAM
;
223 case ITUNES_METADATA_SUBTYPE_RIAAPA
:
224 if( value
.binary
.size
!= 1 )
225 return LSMASH_ERR_FUNCTION_PARAM
;
230 data
->type_code
= value
.binary
.subtype
;
231 data
->value_length
= value
.binary
.size
;
232 data
->value
= lsmash_memdup( value
.binary
.data
, value
.binary
.size
);
235 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
236 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
237 return LSMASH_ERR_MEMORY_ALLOC
;
242 int lsmash_set_itunes_metadata( lsmash_root_t
*root
, lsmash_itunes_metadata_t metadata
)
244 if( isom_check_initializer_present( root
) < 0 )
245 return LSMASH_ERR_FUNCTION_PARAM
;
248 lsmash_itunes_metadata_item item
;
249 int (*func_set_itunes_metadata
)( lsmash_file_t
*, lsmash_itunes_metadata_item
, lsmash_itunes_metadata_value_t
, char *, char * );
250 } itunes_metadata_function_mapping
[] =
252 { ITUNES_METADATA_ITEM_ALBUM_NAME
, isom_set_itunes_metadata_string
},
253 { ITUNES_METADATA_ITEM_ARTIST
, isom_set_itunes_metadata_string
},
254 { ITUNES_METADATA_ITEM_USER_COMMENT
, isom_set_itunes_metadata_string
},
255 { ITUNES_METADATA_ITEM_RELEASE_DATE
, isom_set_itunes_metadata_string
},
256 { ITUNES_METADATA_ITEM_ENCODED_BY
, isom_set_itunes_metadata_string
},
257 { ITUNES_METADATA_ITEM_USER_GENRE
, isom_set_itunes_metadata_string
},
258 { ITUNES_METADATA_ITEM_GROUPING
, isom_set_itunes_metadata_string
},
259 { ITUNES_METADATA_ITEM_LYRICS
, isom_set_itunes_metadata_string
},
260 { ITUNES_METADATA_ITEM_TITLE
, isom_set_itunes_metadata_string
},
261 { ITUNES_METADATA_ITEM_TRACK_SUBTITLE
, isom_set_itunes_metadata_string
},
262 { ITUNES_METADATA_ITEM_ENCODING_TOOL
, isom_set_itunes_metadata_string
},
263 { ITUNES_METADATA_ITEM_COMPOSER
, isom_set_itunes_metadata_string
},
264 { ITUNES_METADATA_ITEM_ALBUM_ARTIST
, isom_set_itunes_metadata_string
},
265 { ITUNES_METADATA_ITEM_PODCAST_CATEGORY
, isom_set_itunes_metadata_string
},
266 { ITUNES_METADATA_ITEM_COPYRIGHT
, isom_set_itunes_metadata_string
},
267 { ITUNES_METADATA_ITEM_DESCRIPTION
, isom_set_itunes_metadata_string
},
268 { ITUNES_METADATA_ITEM_GROUPING_DRAFT
, isom_set_itunes_metadata_string
},
269 { ITUNES_METADATA_ITEM_PODCAST_KEYWORD
, isom_set_itunes_metadata_string
},
270 { ITUNES_METADATA_ITEM_LONG_DESCRIPTION
, isom_set_itunes_metadata_string
},
271 { ITUNES_METADATA_ITEM_PURCHASE_DATE
, isom_set_itunes_metadata_string
},
272 { ITUNES_METADATA_ITEM_TV_EPISODE_ID
, isom_set_itunes_metadata_string
},
273 { ITUNES_METADATA_ITEM_TV_NETWORK
, isom_set_itunes_metadata_string
},
274 { ITUNES_METADATA_ITEM_TV_SHOW_NAME
, isom_set_itunes_metadata_string
},
275 { ITUNES_METADATA_ITEM_ITUNES_PURCHASE_ACCOUNT_ID
, isom_set_itunes_metadata_string
},
276 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM
, isom_set_itunes_metadata_string
},
277 { ITUNES_METADATA_ITEM_ITUNES_SORT_ARTIST
, isom_set_itunes_metadata_string
},
278 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM_ARTIST
, isom_set_itunes_metadata_string
},
279 { ITUNES_METADATA_ITEM_ITUNES_SORT_COMPOSER
, isom_set_itunes_metadata_string
},
280 { ITUNES_METADATA_ITEM_ITUNES_SORT_NAME
, isom_set_itunes_metadata_string
},
281 { ITUNES_METADATA_ITEM_ITUNES_SORT_SHOW
, isom_set_itunes_metadata_string
},
282 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID
, isom_set_itunes_metadata_integer
},
283 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE
, isom_set_itunes_metadata_integer
},
284 { ITUNES_METADATA_ITEM_CONTENT_RATING
, isom_set_itunes_metadata_integer
},
285 { ITUNES_METADATA_ITEM_MEDIA_TYPE
, isom_set_itunes_metadata_integer
},
286 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE
, isom_set_itunes_metadata_integer
},
287 { ITUNES_METADATA_ITEM_TV_EPISODE
, isom_set_itunes_metadata_integer
},
288 { ITUNES_METADATA_ITEM_TV_SEASON
, isom_set_itunes_metadata_integer
},
289 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE
, isom_set_itunes_metadata_integer
},
290 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID
, isom_set_itunes_metadata_integer
},
291 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID
, isom_set_itunes_metadata_integer
},
292 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID
, isom_set_itunes_metadata_integer
},
293 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID
, isom_set_itunes_metadata_integer
},
294 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID
, isom_set_itunes_metadata_integer
},
295 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE
, isom_set_itunes_metadata_integer
},
296 { ITUNES_METADATA_ITEM_DISC_COMPILATION
, isom_set_itunes_metadata_boolean
},
297 { ITUNES_METADATA_ITEM_HIGH_DEFINITION_VIDEO
, isom_set_itunes_metadata_boolean
},
298 { ITUNES_METADATA_ITEM_PODCAST
, isom_set_itunes_metadata_boolean
},
299 { ITUNES_METADATA_ITEM_GAPLESS_PLAYBACK
, isom_set_itunes_metadata_boolean
},
300 { ITUNES_METADATA_ITEM_COVER_ART
, isom_set_itunes_metadata_binary
},
301 { ITUNES_METADATA_ITEM_DISC_NUMBER
, isom_set_itunes_metadata_binary
},
302 { ITUNES_METADATA_ITEM_TRACK_NUMBER
, isom_set_itunes_metadata_binary
},
305 lsmash_file_t
*file
= root
->file
;
306 for( int i
= 0; itunes_metadata_function_mapping
[i
].func_set_itunes_metadata
; i
++ )
307 if( metadata
.item
== itunes_metadata_function_mapping
[i
].item
)
308 return itunes_metadata_function_mapping
[i
].func_set_itunes_metadata( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
309 if( metadata
.item
== ITUNES_METADATA_ITEM_CUSTOM
)
310 switch( metadata
.type
)
312 case ITUNES_METADATA_TYPE_STRING
:
313 return isom_set_itunes_metadata_string( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
314 case ITUNES_METADATA_TYPE_INTEGER
:
315 return isom_set_itunes_metadata_integer( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
316 case ITUNES_METADATA_TYPE_BOOLEAN
:
317 return isom_set_itunes_metadata_boolean( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
318 case ITUNES_METADATA_TYPE_BINARY
:
319 return isom_set_itunes_metadata_binary( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
323 return LSMASH_ERR_FUNCTION_PARAM
;
326 static lsmash_itunes_metadata_type
isom_get_itunes_metadata_type( lsmash_itunes_metadata_item item
)
330 lsmash_itunes_metadata_item item
;
331 lsmash_itunes_metadata_type type
;
332 } itunes_metadata_item_type_mapping
[] =
334 { ITUNES_METADATA_ITEM_ALBUM_NAME
, ITUNES_METADATA_TYPE_STRING
},
335 { ITUNES_METADATA_ITEM_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
336 { ITUNES_METADATA_ITEM_USER_COMMENT
, ITUNES_METADATA_TYPE_STRING
},
337 { ITUNES_METADATA_ITEM_RELEASE_DATE
, ITUNES_METADATA_TYPE_STRING
},
338 { ITUNES_METADATA_ITEM_ENCODED_BY
, ITUNES_METADATA_TYPE_STRING
},
339 { ITUNES_METADATA_ITEM_USER_GENRE
, ITUNES_METADATA_TYPE_STRING
},
340 { ITUNES_METADATA_ITEM_GROUPING
, ITUNES_METADATA_TYPE_STRING
},
341 { ITUNES_METADATA_ITEM_LYRICS
, ITUNES_METADATA_TYPE_STRING
},
342 { ITUNES_METADATA_ITEM_TITLE
, ITUNES_METADATA_TYPE_STRING
},
343 { ITUNES_METADATA_ITEM_TRACK_SUBTITLE
, ITUNES_METADATA_TYPE_STRING
},
344 { ITUNES_METADATA_ITEM_ENCODING_TOOL
, ITUNES_METADATA_TYPE_STRING
},
345 { ITUNES_METADATA_ITEM_COMPOSER
, ITUNES_METADATA_TYPE_STRING
},
346 { ITUNES_METADATA_ITEM_ALBUM_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
347 { ITUNES_METADATA_ITEM_PODCAST_CATEGORY
, ITUNES_METADATA_TYPE_STRING
},
348 { ITUNES_METADATA_ITEM_COPYRIGHT
, ITUNES_METADATA_TYPE_STRING
},
349 { ITUNES_METADATA_ITEM_DESCRIPTION
, ITUNES_METADATA_TYPE_STRING
},
350 { ITUNES_METADATA_ITEM_GROUPING_DRAFT
, ITUNES_METADATA_TYPE_STRING
},
351 { ITUNES_METADATA_ITEM_PODCAST_KEYWORD
, ITUNES_METADATA_TYPE_STRING
},
352 { ITUNES_METADATA_ITEM_LONG_DESCRIPTION
, ITUNES_METADATA_TYPE_STRING
},
353 { ITUNES_METADATA_ITEM_PURCHASE_DATE
, ITUNES_METADATA_TYPE_STRING
},
354 { ITUNES_METADATA_ITEM_TV_EPISODE_ID
, ITUNES_METADATA_TYPE_STRING
},
355 { ITUNES_METADATA_ITEM_TV_NETWORK
, ITUNES_METADATA_TYPE_STRING
},
356 { ITUNES_METADATA_ITEM_TV_SHOW_NAME
, ITUNES_METADATA_TYPE_STRING
},
357 { ITUNES_METADATA_ITEM_ITUNES_PURCHASE_ACCOUNT_ID
, ITUNES_METADATA_TYPE_STRING
},
358 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM
, ITUNES_METADATA_TYPE_STRING
},
359 { ITUNES_METADATA_ITEM_ITUNES_SORT_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
360 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
361 { ITUNES_METADATA_ITEM_ITUNES_SORT_COMPOSER
, ITUNES_METADATA_TYPE_STRING
},
362 { ITUNES_METADATA_ITEM_ITUNES_SORT_NAME
, ITUNES_METADATA_TYPE_STRING
},
363 { ITUNES_METADATA_ITEM_ITUNES_SORT_SHOW
, ITUNES_METADATA_TYPE_STRING
},
364 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID
, ITUNES_METADATA_TYPE_INTEGER
},
365 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE
, ITUNES_METADATA_TYPE_INTEGER
},
366 { ITUNES_METADATA_ITEM_CONTENT_RATING
, ITUNES_METADATA_TYPE_INTEGER
},
367 { ITUNES_METADATA_ITEM_MEDIA_TYPE
, ITUNES_METADATA_TYPE_INTEGER
},
368 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE
, ITUNES_METADATA_TYPE_INTEGER
},
369 { ITUNES_METADATA_ITEM_TV_EPISODE
, ITUNES_METADATA_TYPE_INTEGER
},
370 { ITUNES_METADATA_ITEM_TV_SEASON
, ITUNES_METADATA_TYPE_INTEGER
},
371 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE
, ITUNES_METADATA_TYPE_INTEGER
},
372 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID
, ITUNES_METADATA_TYPE_INTEGER
},
373 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID
, ITUNES_METADATA_TYPE_INTEGER
},
374 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID
, ITUNES_METADATA_TYPE_INTEGER
},
375 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID
, ITUNES_METADATA_TYPE_INTEGER
},
376 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID
, ITUNES_METADATA_TYPE_INTEGER
},
377 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE
, ITUNES_METADATA_TYPE_INTEGER
},
378 { ITUNES_METADATA_ITEM_DISC_COMPILATION
, ITUNES_METADATA_TYPE_BOOLEAN
},
379 { ITUNES_METADATA_ITEM_HIGH_DEFINITION_VIDEO
, ITUNES_METADATA_TYPE_BOOLEAN
},
380 { ITUNES_METADATA_ITEM_PODCAST
, ITUNES_METADATA_TYPE_BOOLEAN
},
381 { ITUNES_METADATA_ITEM_GAPLESS_PLAYBACK
, ITUNES_METADATA_TYPE_BOOLEAN
},
382 { ITUNES_METADATA_ITEM_COVER_ART
, ITUNES_METADATA_TYPE_BINARY
},
383 { ITUNES_METADATA_ITEM_DISC_NUMBER
, ITUNES_METADATA_TYPE_BINARY
},
384 { ITUNES_METADATA_ITEM_TRACK_NUMBER
, ITUNES_METADATA_TYPE_BINARY
},
385 { 0, ITUNES_METADATA_TYPE_NONE
}
387 for( int i
= 0; itunes_metadata_item_type_mapping
[i
].type
!= ITUNES_METADATA_TYPE_NONE
; i
++ )
388 if( item
== itunes_metadata_item_type_mapping
[i
].item
)
389 return itunes_metadata_item_type_mapping
[i
].type
;
390 return ITUNES_METADATA_TYPE_NONE
;
393 int lsmash_get_itunes_metadata( lsmash_root_t
*root
, uint32_t metadata_number
, lsmash_itunes_metadata_t
*metadata
)
395 if( isom_check_initializer_present( root
) < 0 || !metadata
)
396 return LSMASH_ERR_FUNCTION_PARAM
;
397 lsmash_file_t
*file
= root
->file
->initializer
;
398 if( !file
->moov
->udta
->meta
->ilst
)
399 return LSMASH_ERR_NAMELESS
;
400 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
401 isom_metaitem_t
*metaitem
= (isom_metaitem_t
*)lsmash_list_get_entry_data( &ilst
->metaitem_list
, metadata_number
);
402 if( LSMASH_IS_NON_EXISTING_BOX( metaitem
)
403 || LSMASH_IS_NON_EXISTING_BOX( metaitem
->data
)
404 || metaitem
->data
->value
== NULL
405 || metaitem
->data
->value_length
== 0 )
406 return LSMASH_ERR_NAMELESS
;
407 metadata
->item
= metaitem
->type
.fourcc
;
408 metadata
->type
= isom_get_itunes_metadata_type( metadata
->item
);
410 int err
= LSMASH_ERR_MEMORY_ALLOC
;
411 isom_mean_t
*mean
= metaitem
->mean
;
412 if( LSMASH_IS_NON_EXISTING_BOX( mean
) )
414 uint8_t *temp
= lsmash_malloc( mean
->meaning_string_length
+ 1 );
417 memcpy( temp
, mean
->meaning_string
, mean
->meaning_string_length
);
418 temp
[ mean
->meaning_string_length
] = 0;
419 metadata
->meaning
= (char *)temp
;
422 metadata
->meaning
= NULL
;
424 isom_name_t
*name
= metaitem
->name
;
425 if( LSMASH_IS_NON_EXISTING_BOX( name
) )
427 uint8_t *temp
= lsmash_malloc( name
->name_length
+ 1 );
430 memcpy( temp
, name
->name
, name
->name_length
);
431 temp
[ name
->name_length
] = 0;
432 metadata
->name
= (char *)temp
;
435 metadata
->name
= NULL
;
437 isom_data_t
*data
= metaitem
->data
;
438 switch( metadata
->type
)
440 case ITUNES_METADATA_TYPE_STRING
:
442 uint8_t *temp
= lsmash_malloc( data
->value_length
+ 1 );
445 memcpy( temp
, data
->value
, data
->value_length
);
446 temp
[ data
->value_length
] = 0;
447 metadata
->value
.string
= (char *)temp
;
450 case ITUNES_METADATA_TYPE_INTEGER
:
451 if( data
->value_length
> 8 )
453 err
= LSMASH_ERR_INVALID_DATA
;
456 metadata
->value
.integer
= 0;
457 for( uint32_t i
= 0; i
< data
->value_length
; i
++ )
459 int shift
= (data
->value_length
- i
- 1) * 8;
460 metadata
->value
.integer
|= (uint64_t)data
->value
[i
] << shift
;
463 case ITUNES_METADATA_TYPE_BOOLEAN
:
464 metadata
->value
.boolean
= !!data
->value
[0];
467 metadata
->type
= ITUNES_METADATA_TYPE_BINARY
;
468 metadata
->value
.binary
.subtype
= data
->type_code
;
469 metadata
->value
.binary
.size
= data
->value_length
;
470 metadata
->value
.binary
.data
= lsmash_memdup( data
->value
, data
->value_length
);
471 if( !metadata
->value
.binary
.data
)
477 lsmash_freep( &metadata
->meaning
);
478 lsmash_freep( &metadata
->name
);
482 uint32_t lsmash_count_itunes_metadata( lsmash_root_t
*root
)
484 if( isom_check_initializer_present( root
) < 0
485 || LSMASH_IS_NON_EXISTING_BOX( root
->file
->initializer
->moov
->udta
->meta
->ilst
) )
487 return root
->file
->initializer
->moov
->udta
->meta
->ilst
->metaitem_list
.entry_count
;
490 void lsmash_cleanup_itunes_metadata( lsmash_itunes_metadata_t
*metadata
)
494 lsmash_freep( &metadata
->meaning
);
495 lsmash_freep( &metadata
->name
);
496 if( metadata
->type
== ITUNES_METADATA_TYPE_STRING
)
497 lsmash_freep( &metadata
->value
.string
);
498 else if( metadata
->type
== ITUNES_METADATA_TYPE_BINARY
)
499 lsmash_freep( &metadata
->value
.binary
.data
);