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 */
30 static isom_data_t
*isom_add_metadata( lsmash_file_t
*file
,
31 lsmash_itunes_metadata_item item
,
32 char *meaning_string
, char *name_string
)
34 assert( LSMASH_IS_EXISTING_BOX( file
->moov
) );
35 if( ((item
== ITUNES_METADATA_ITEM_CUSTOM
) && (!meaning_string
|| !meaning_string
[0]) )
36 || (LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
)
37 && LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_udta( file
->moov
) ))
38 || (LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
->meta
)
39 && LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_meta( file
->moov
->udta
) ))
40 || (LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
->meta
->ilst
)
41 && LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_ilst( file
->moov
->udta
->meta
) )) )
43 if( LSMASH_IS_NON_EXISTING_BOX( file
->moov
->udta
->meta
->hdlr
) )
45 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_hdlr( file
->moov
->udta
->meta
) )
46 || isom_setup_handler_reference( file
->moov
->udta
->meta
->hdlr
, ISOM_META_HANDLER_TYPE_ITUNES_METADATA
) < 0 )
49 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
50 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_metaitem( ilst
, item
) ) )
52 isom_metaitem_t
*metaitem
= (isom_metaitem_t
*)ilst
->metaitem_list
.tail
->data
;
53 if( item
== ITUNES_METADATA_ITEM_CUSTOM
)
55 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_mean( metaitem
) ) )
57 isom_mean_t
*mean
= metaitem
->mean
;
58 mean
->meaning_string_length
= strlen( meaning_string
); /* No null terminator */
59 mean
->meaning_string
= lsmash_memdup( meaning_string
, mean
->meaning_string_length
);
60 if( !mean
->meaning_string
)
62 if( name_string
&& name_string
[0] )
64 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_name( metaitem
) ) )
66 isom_name_t
*name
= metaitem
->name
;
67 name
->name_length
= strlen( name_string
); /* No null terminator */
68 name
->name
= lsmash_memdup( name_string
, name
->name_length
);
73 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_data( metaitem
) ) )
75 return metaitem
->data
;
77 isom_remove_box_by_itself( metaitem
);
81 static int isom_set_itunes_metadata_string( lsmash_file_t
*file
,
82 lsmash_itunes_metadata_item item
,
83 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
85 uint32_t value_length
= strlen( value
.string
);
86 if( item
== ITUNES_METADATA_ITEM_DESCRIPTION
&& value_length
> 255 )
87 item
= ITUNES_METADATA_ITEM_LONG_DESCRIPTION
;
88 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
89 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
90 return LSMASH_ERR_NAMELESS
;
91 data
->type_code
= ITUNES_METADATA_SUBTYPE_UTF8
;
92 data
->value_length
= value_length
; /* No null terminator */
93 data
->value
= lsmash_memdup( value
.string
, data
->value_length
);
96 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
97 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
98 return LSMASH_ERR_MEMORY_ALLOC
;
103 static int isom_set_itunes_metadata_integer( lsmash_file_t
*file
,
104 lsmash_itunes_metadata_item item
,
105 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
109 lsmash_itunes_metadata_item item
;
111 } metadata_code_type_table
[] =
113 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID
, 1 },
114 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE
, 2 },
115 { ITUNES_METADATA_ITEM_CONTENT_RATING
, 1 },
116 { ITUNES_METADATA_ITEM_MEDIA_TYPE
, 1 },
117 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE
, 2 },
118 { ITUNES_METADATA_ITEM_TV_EPISODE
, 4 },
119 { ITUNES_METADATA_ITEM_TV_SEASON
, 4 },
120 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE
, 1 },
121 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID
, 4 },
122 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID
, 4 },
123 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID
, 4 },
124 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID
, 4 },
125 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID
, 8 },
126 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE
, 4 },
127 { ITUNES_METADATA_ITEM_CUSTOM
, 8 },
131 for( i
= 0; metadata_code_type_table
[i
].item
; i
++ )
132 if( item
== metadata_code_type_table
[i
].item
)
134 if( metadata_code_type_table
[i
].length
== 0 )
135 return LSMASH_ERR_NAMELESS
;
136 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
137 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
138 return LSMASH_ERR_NAMELESS
;
139 if( item
== ITUNES_METADATA_ITEM_PREDEFINED_GENRE
)
140 data
->type_code
= ITUNES_METADATA_SUBTYPE_IMPLICIT
;
142 data
->type_code
= ITUNES_METADATA_SUBTYPE_INTEGER
;
143 data
->value_length
= metadata_code_type_table
[i
].length
;
145 for( i
= 0; i
< data
->value_length
; i
++ )
147 int shift
= (data
->value_length
- i
- 1) * 8;
148 temp
[i
] = (value
.integer
>> shift
) & 0xff;
150 data
->value
= lsmash_memdup( temp
, data
->value_length
);
153 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
154 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
155 return LSMASH_ERR_MEMORY_ALLOC
;
160 static int isom_set_itunes_metadata_boolean( lsmash_file_t
*file
,
161 lsmash_itunes_metadata_item item
,
162 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
164 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
165 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
166 return LSMASH_ERR_NAMELESS
;
167 data
->type_code
= ITUNES_METADATA_SUBTYPE_INTEGER
;
168 data
->value_length
= 1;
169 uint8_t temp
= (uint8_t)value
.boolean
;
170 data
->value
= lsmash_memdup( &temp
, 1 );
173 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
174 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
175 return LSMASH_ERR_MEMORY_ALLOC
;
180 static int isom_set_itunes_metadata_binary( lsmash_file_t
*file
,
181 lsmash_itunes_metadata_item item
,
182 lsmash_itunes_metadata_value_t value
, char *meaning
, char *name
)
184 isom_data_t
*data
= isom_add_metadata( file
, item
, meaning
, name
);
185 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
186 return LSMASH_ERR_NAMELESS
;
189 case ITUNES_METADATA_ITEM_COVER_ART
:
190 if( value
.binary
.subtype
!= ITUNES_METADATA_SUBTYPE_JPEG
191 && value
.binary
.subtype
!= ITUNES_METADATA_SUBTYPE_PNG
192 && value
.binary
.subtype
!= ITUNES_METADATA_SUBTYPE_BMP
)
193 return LSMASH_ERR_FUNCTION_PARAM
;
195 case ITUNES_METADATA_ITEM_DISC_NUMBER
:
196 case ITUNES_METADATA_ITEM_TRACK_NUMBER
:
197 value
.binary
.subtype
= ITUNES_METADATA_SUBTYPE_IMPLICIT
;
202 switch( value
.binary
.subtype
)
204 case ITUNES_METADATA_SUBTYPE_UUID
:
205 if( value
.binary
.size
!= 16 )
206 return LSMASH_ERR_FUNCTION_PARAM
;
208 case ITUNES_METADATA_SUBTYPE_DURATION
:
209 if( value
.binary
.size
!= 4 )
210 return LSMASH_ERR_FUNCTION_PARAM
;
212 case ITUNES_METADATA_SUBTYPE_TIME
:
213 if( value
.binary
.size
!= 4 && value
.binary
.size
!= 8 )
214 return LSMASH_ERR_FUNCTION_PARAM
;
216 case ITUNES_METADATA_SUBTYPE_INTEGER
:
217 if( value
.binary
.size
!= 1 && value
.binary
.size
!= 2
218 && value
.binary
.size
!= 3 && value
.binary
.size
!= 4
219 && value
.binary
.size
!= 8 )
220 return LSMASH_ERR_FUNCTION_PARAM
;
222 case ITUNES_METADATA_SUBTYPE_RIAAPA
:
223 if( value
.binary
.size
!= 1 )
224 return LSMASH_ERR_FUNCTION_PARAM
;
229 data
->type_code
= value
.binary
.subtype
;
230 data
->value_length
= value
.binary
.size
;
231 data
->value
= lsmash_memdup( value
.binary
.data
, value
.binary
.size
);
234 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
235 isom_remove_box_by_itself( ilst
->metaitem_list
.tail
->data
);
236 return LSMASH_ERR_MEMORY_ALLOC
;
241 int lsmash_set_itunes_metadata( lsmash_root_t
*root
, lsmash_itunes_metadata_t metadata
)
243 if( isom_check_initializer_present( root
) < 0 )
244 return LSMASH_ERR_FUNCTION_PARAM
;
247 lsmash_itunes_metadata_item item
;
248 int (*func_set_itunes_metadata
)( lsmash_file_t
*, lsmash_itunes_metadata_item
, lsmash_itunes_metadata_value_t
, char *, char * );
249 } itunes_metadata_function_mapping
[] =
251 { ITUNES_METADATA_ITEM_ALBUM_NAME
, isom_set_itunes_metadata_string
},
252 { ITUNES_METADATA_ITEM_ARTIST
, isom_set_itunes_metadata_string
},
253 { ITUNES_METADATA_ITEM_USER_COMMENT
, isom_set_itunes_metadata_string
},
254 { ITUNES_METADATA_ITEM_RELEASE_DATE
, isom_set_itunes_metadata_string
},
255 { ITUNES_METADATA_ITEM_ENCODED_BY
, isom_set_itunes_metadata_string
},
256 { ITUNES_METADATA_ITEM_USER_GENRE
, isom_set_itunes_metadata_string
},
257 { ITUNES_METADATA_ITEM_GROUPING
, isom_set_itunes_metadata_string
},
258 { ITUNES_METADATA_ITEM_LYRICS
, isom_set_itunes_metadata_string
},
259 { ITUNES_METADATA_ITEM_TITLE
, isom_set_itunes_metadata_string
},
260 { ITUNES_METADATA_ITEM_TRACK_SUBTITLE
, isom_set_itunes_metadata_string
},
261 { ITUNES_METADATA_ITEM_ENCODING_TOOL
, isom_set_itunes_metadata_string
},
262 { ITUNES_METADATA_ITEM_COMPOSER
, isom_set_itunes_metadata_string
},
263 { ITUNES_METADATA_ITEM_ALBUM_ARTIST
, isom_set_itunes_metadata_string
},
264 { ITUNES_METADATA_ITEM_PODCAST_CATEGORY
, isom_set_itunes_metadata_string
},
265 { ITUNES_METADATA_ITEM_COPYRIGHT
, isom_set_itunes_metadata_string
},
266 { ITUNES_METADATA_ITEM_DESCRIPTION
, isom_set_itunes_metadata_string
},
267 { ITUNES_METADATA_ITEM_GROUPING_DRAFT
, isom_set_itunes_metadata_string
},
268 { ITUNES_METADATA_ITEM_PODCAST_KEYWORD
, isom_set_itunes_metadata_string
},
269 { ITUNES_METADATA_ITEM_LONG_DESCRIPTION
, isom_set_itunes_metadata_string
},
270 { ITUNES_METADATA_ITEM_PURCHASE_DATE
, isom_set_itunes_metadata_string
},
271 { ITUNES_METADATA_ITEM_TV_EPISODE_ID
, isom_set_itunes_metadata_string
},
272 { ITUNES_METADATA_ITEM_TV_NETWORK
, isom_set_itunes_metadata_string
},
273 { ITUNES_METADATA_ITEM_TV_SHOW_NAME
, isom_set_itunes_metadata_string
},
274 { ITUNES_METADATA_ITEM_ITUNES_PURCHASE_ACCOUNT_ID
, isom_set_itunes_metadata_string
},
275 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM
, isom_set_itunes_metadata_string
},
276 { ITUNES_METADATA_ITEM_ITUNES_SORT_ARTIST
, isom_set_itunes_metadata_string
},
277 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM_ARTIST
, isom_set_itunes_metadata_string
},
278 { ITUNES_METADATA_ITEM_ITUNES_SORT_COMPOSER
, isom_set_itunes_metadata_string
},
279 { ITUNES_METADATA_ITEM_ITUNES_SORT_NAME
, isom_set_itunes_metadata_string
},
280 { ITUNES_METADATA_ITEM_ITUNES_SORT_SHOW
, isom_set_itunes_metadata_string
},
281 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID
, isom_set_itunes_metadata_integer
},
282 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE
, isom_set_itunes_metadata_integer
},
283 { ITUNES_METADATA_ITEM_CONTENT_RATING
, isom_set_itunes_metadata_integer
},
284 { ITUNES_METADATA_ITEM_MEDIA_TYPE
, isom_set_itunes_metadata_integer
},
285 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE
, isom_set_itunes_metadata_integer
},
286 { ITUNES_METADATA_ITEM_TV_EPISODE
, isom_set_itunes_metadata_integer
},
287 { ITUNES_METADATA_ITEM_TV_SEASON
, isom_set_itunes_metadata_integer
},
288 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE
, isom_set_itunes_metadata_integer
},
289 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID
, isom_set_itunes_metadata_integer
},
290 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID
, isom_set_itunes_metadata_integer
},
291 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID
, isom_set_itunes_metadata_integer
},
292 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID
, isom_set_itunes_metadata_integer
},
293 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID
, isom_set_itunes_metadata_integer
},
294 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE
, isom_set_itunes_metadata_integer
},
295 { ITUNES_METADATA_ITEM_DISC_COMPILATION
, isom_set_itunes_metadata_boolean
},
296 { ITUNES_METADATA_ITEM_HIGH_DEFINITION_VIDEO
, isom_set_itunes_metadata_boolean
},
297 { ITUNES_METADATA_ITEM_PODCAST
, isom_set_itunes_metadata_boolean
},
298 { ITUNES_METADATA_ITEM_GAPLESS_PLAYBACK
, isom_set_itunes_metadata_boolean
},
299 { ITUNES_METADATA_ITEM_COVER_ART
, isom_set_itunes_metadata_binary
},
300 { ITUNES_METADATA_ITEM_DISC_NUMBER
, isom_set_itunes_metadata_binary
},
301 { ITUNES_METADATA_ITEM_TRACK_NUMBER
, isom_set_itunes_metadata_binary
},
304 lsmash_file_t
*file
= root
->file
;
305 for( int i
= 0; itunes_metadata_function_mapping
[i
].func_set_itunes_metadata
; i
++ )
306 if( metadata
.item
== itunes_metadata_function_mapping
[i
].item
)
307 return itunes_metadata_function_mapping
[i
].func_set_itunes_metadata( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
308 if( metadata
.item
== ITUNES_METADATA_ITEM_CUSTOM
)
309 switch( metadata
.type
)
311 case ITUNES_METADATA_TYPE_STRING
:
312 return isom_set_itunes_metadata_string( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
313 case ITUNES_METADATA_TYPE_INTEGER
:
314 return isom_set_itunes_metadata_integer( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
315 case ITUNES_METADATA_TYPE_BOOLEAN
:
316 return isom_set_itunes_metadata_boolean( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
317 case ITUNES_METADATA_TYPE_BINARY
:
318 return isom_set_itunes_metadata_binary( file
, metadata
.item
, metadata
.value
, metadata
.meaning
, metadata
.name
);
322 return LSMASH_ERR_FUNCTION_PARAM
;
325 static lsmash_itunes_metadata_type
isom_get_itunes_metadata_type( lsmash_itunes_metadata_item item
)
329 lsmash_itunes_metadata_item item
;
330 lsmash_itunes_metadata_type type
;
331 } itunes_metadata_item_type_mapping
[] =
333 { ITUNES_METADATA_ITEM_ALBUM_NAME
, ITUNES_METADATA_TYPE_STRING
},
334 { ITUNES_METADATA_ITEM_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
335 { ITUNES_METADATA_ITEM_USER_COMMENT
, ITUNES_METADATA_TYPE_STRING
},
336 { ITUNES_METADATA_ITEM_RELEASE_DATE
, ITUNES_METADATA_TYPE_STRING
},
337 { ITUNES_METADATA_ITEM_ENCODED_BY
, ITUNES_METADATA_TYPE_STRING
},
338 { ITUNES_METADATA_ITEM_USER_GENRE
, ITUNES_METADATA_TYPE_STRING
},
339 { ITUNES_METADATA_ITEM_GROUPING
, ITUNES_METADATA_TYPE_STRING
},
340 { ITUNES_METADATA_ITEM_LYRICS
, ITUNES_METADATA_TYPE_STRING
},
341 { ITUNES_METADATA_ITEM_TITLE
, ITUNES_METADATA_TYPE_STRING
},
342 { ITUNES_METADATA_ITEM_TRACK_SUBTITLE
, ITUNES_METADATA_TYPE_STRING
},
343 { ITUNES_METADATA_ITEM_ENCODING_TOOL
, ITUNES_METADATA_TYPE_STRING
},
344 { ITUNES_METADATA_ITEM_COMPOSER
, ITUNES_METADATA_TYPE_STRING
},
345 { ITUNES_METADATA_ITEM_ALBUM_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
346 { ITUNES_METADATA_ITEM_PODCAST_CATEGORY
, ITUNES_METADATA_TYPE_STRING
},
347 { ITUNES_METADATA_ITEM_COPYRIGHT
, ITUNES_METADATA_TYPE_STRING
},
348 { ITUNES_METADATA_ITEM_DESCRIPTION
, ITUNES_METADATA_TYPE_STRING
},
349 { ITUNES_METADATA_ITEM_GROUPING_DRAFT
, ITUNES_METADATA_TYPE_STRING
},
350 { ITUNES_METADATA_ITEM_PODCAST_KEYWORD
, ITUNES_METADATA_TYPE_STRING
},
351 { ITUNES_METADATA_ITEM_LONG_DESCRIPTION
, ITUNES_METADATA_TYPE_STRING
},
352 { ITUNES_METADATA_ITEM_PURCHASE_DATE
, ITUNES_METADATA_TYPE_STRING
},
353 { ITUNES_METADATA_ITEM_TV_EPISODE_ID
, ITUNES_METADATA_TYPE_STRING
},
354 { ITUNES_METADATA_ITEM_TV_NETWORK
, ITUNES_METADATA_TYPE_STRING
},
355 { ITUNES_METADATA_ITEM_TV_SHOW_NAME
, ITUNES_METADATA_TYPE_STRING
},
356 { ITUNES_METADATA_ITEM_ITUNES_PURCHASE_ACCOUNT_ID
, ITUNES_METADATA_TYPE_STRING
},
357 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM
, ITUNES_METADATA_TYPE_STRING
},
358 { ITUNES_METADATA_ITEM_ITUNES_SORT_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
359 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM_ARTIST
, ITUNES_METADATA_TYPE_STRING
},
360 { ITUNES_METADATA_ITEM_ITUNES_SORT_COMPOSER
, ITUNES_METADATA_TYPE_STRING
},
361 { ITUNES_METADATA_ITEM_ITUNES_SORT_NAME
, ITUNES_METADATA_TYPE_STRING
},
362 { ITUNES_METADATA_ITEM_ITUNES_SORT_SHOW
, ITUNES_METADATA_TYPE_STRING
},
363 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID
, ITUNES_METADATA_TYPE_INTEGER
},
364 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE
, ITUNES_METADATA_TYPE_INTEGER
},
365 { ITUNES_METADATA_ITEM_CONTENT_RATING
, ITUNES_METADATA_TYPE_INTEGER
},
366 { ITUNES_METADATA_ITEM_MEDIA_TYPE
, ITUNES_METADATA_TYPE_INTEGER
},
367 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE
, ITUNES_METADATA_TYPE_INTEGER
},
368 { ITUNES_METADATA_ITEM_TV_EPISODE
, ITUNES_METADATA_TYPE_INTEGER
},
369 { ITUNES_METADATA_ITEM_TV_SEASON
, ITUNES_METADATA_TYPE_INTEGER
},
370 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE
, ITUNES_METADATA_TYPE_INTEGER
},
371 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID
, ITUNES_METADATA_TYPE_INTEGER
},
372 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID
, ITUNES_METADATA_TYPE_INTEGER
},
373 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID
, ITUNES_METADATA_TYPE_INTEGER
},
374 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID
, ITUNES_METADATA_TYPE_INTEGER
},
375 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID
, ITUNES_METADATA_TYPE_INTEGER
},
376 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE
, ITUNES_METADATA_TYPE_INTEGER
},
377 { ITUNES_METADATA_ITEM_DISC_COMPILATION
, ITUNES_METADATA_TYPE_BOOLEAN
},
378 { ITUNES_METADATA_ITEM_HIGH_DEFINITION_VIDEO
, ITUNES_METADATA_TYPE_BOOLEAN
},
379 { ITUNES_METADATA_ITEM_PODCAST
, ITUNES_METADATA_TYPE_BOOLEAN
},
380 { ITUNES_METADATA_ITEM_GAPLESS_PLAYBACK
, ITUNES_METADATA_TYPE_BOOLEAN
},
381 { ITUNES_METADATA_ITEM_COVER_ART
, ITUNES_METADATA_TYPE_BINARY
},
382 { ITUNES_METADATA_ITEM_DISC_NUMBER
, ITUNES_METADATA_TYPE_BINARY
},
383 { ITUNES_METADATA_ITEM_TRACK_NUMBER
, ITUNES_METADATA_TYPE_BINARY
},
384 { 0, ITUNES_METADATA_TYPE_NONE
}
386 for( int i
= 0; itunes_metadata_item_type_mapping
[i
].type
!= ITUNES_METADATA_TYPE_NONE
; i
++ )
387 if( item
== itunes_metadata_item_type_mapping
[i
].item
)
388 return itunes_metadata_item_type_mapping
[i
].type
;
389 return ITUNES_METADATA_TYPE_NONE
;
392 int lsmash_get_itunes_metadata( lsmash_root_t
*root
, uint32_t metadata_number
, lsmash_itunes_metadata_t
*metadata
)
394 if( isom_check_initializer_present( root
) < 0 || !metadata
)
395 return LSMASH_ERR_FUNCTION_PARAM
;
396 lsmash_file_t
*file
= root
->file
->initializer
;
397 if( !file
->moov
->udta
->meta
->ilst
)
398 return LSMASH_ERR_NAMELESS
;
399 isom_ilst_t
*ilst
= file
->moov
->udta
->meta
->ilst
;
400 isom_metaitem_t
*metaitem
= (isom_metaitem_t
*)lsmash_list_get_entry_data( &ilst
->metaitem_list
, metadata_number
);
401 if( LSMASH_IS_NON_EXISTING_BOX( metaitem
)
402 || LSMASH_IS_NON_EXISTING_BOX( metaitem
->data
)
403 || metaitem
->data
->value
== NULL
404 || metaitem
->data
->value_length
== 0 )
405 return LSMASH_ERR_NAMELESS
;
406 metadata
->item
= metaitem
->type
.fourcc
;
407 metadata
->type
= isom_get_itunes_metadata_type( metadata
->item
);
409 int err
= LSMASH_ERR_MEMORY_ALLOC
;
410 isom_mean_t
*mean
= metaitem
->mean
;
411 if( LSMASH_IS_NON_EXISTING_BOX( mean
) )
413 uint8_t *temp
= lsmash_malloc( mean
->meaning_string_length
+ 1 );
416 memcpy( temp
, mean
->meaning_string
, mean
->meaning_string_length
);
417 temp
[ mean
->meaning_string_length
] = 0;
418 metadata
->meaning
= (char *)temp
;
421 metadata
->meaning
= NULL
;
423 isom_name_t
*name
= metaitem
->name
;
424 if( LSMASH_IS_NON_EXISTING_BOX( name
) )
426 uint8_t *temp
= lsmash_malloc( name
->name_length
+ 1 );
429 memcpy( temp
, name
->name
, name
->name_length
);
430 temp
[ name
->name_length
] = 0;
431 metadata
->name
= (char *)temp
;
434 metadata
->name
= NULL
;
436 isom_data_t
*data
= metaitem
->data
;
437 switch( metadata
->type
)
439 case ITUNES_METADATA_TYPE_STRING
:
441 uint8_t *temp
= lsmash_malloc( data
->value_length
+ 1 );
444 memcpy( temp
, data
->value
, data
->value_length
);
445 temp
[ data
->value_length
] = 0;
446 metadata
->value
.string
= (char *)temp
;
449 case ITUNES_METADATA_TYPE_INTEGER
:
450 if( data
->value_length
> 8 )
452 err
= LSMASH_ERR_INVALID_DATA
;
455 metadata
->value
.integer
= 0;
456 for( uint32_t i
= 0; i
< data
->value_length
; i
++ )
458 int shift
= (data
->value_length
- i
- 1) * 8;
459 metadata
->value
.integer
|= (uint64_t)data
->value
[i
] << shift
;
462 case ITUNES_METADATA_TYPE_BOOLEAN
:
463 metadata
->value
.boolean
= !!data
->value
[0];
466 metadata
->type
= ITUNES_METADATA_TYPE_BINARY
;
467 metadata
->value
.binary
.subtype
= data
->type_code
;
468 metadata
->value
.binary
.size
= data
->value_length
;
469 metadata
->value
.binary
.data
= lsmash_memdup( data
->value
, data
->value_length
);
470 if( !metadata
->value
.binary
.data
)
476 lsmash_freep( &metadata
->meaning
);
477 lsmash_freep( &metadata
->name
);
481 uint32_t lsmash_count_itunes_metadata( lsmash_root_t
*root
)
483 if( isom_check_initializer_present( root
) < 0
484 || !root
->file
->initializer
->moov
->udta
->meta
->ilst
)
486 return root
->file
->initializer
->moov
->udta
->meta
->ilst
->metaitem_list
.entry_count
;
489 void lsmash_cleanup_itunes_metadata( lsmash_itunes_metadata_t
*metadata
)
493 lsmash_freep( &metadata
->meaning
);
494 lsmash_freep( &metadata
->name
);
495 if( metadata
->type
== ITUNES_METADATA_TYPE_STRING
)
496 lsmash_freep( &metadata
->value
.string
);
497 else if( metadata
->type
== ITUNES_METADATA_TYPE_BINARY
)
498 lsmash_freep( &metadata
->value
.binary
.data
);