]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
mp4: Drop metadata parameter from mp4_meta_update().
[paraslash.git] / mp4.c
1 /*
2  * Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
3  * FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
4  *
5  * See file COPYING.
6  */
7
8 #include <regex.h>
9
10 #include "para.h"
11 #include "portable_io.h"
12 #include "string.h"
13 #include "mp4.h"
14
15 struct mp4_track {
16         bool is_audio;
17         int32_t channelCount;
18         uint16_t sampleRate;
19
20         /* stsz */
21         int32_t stsz_sample_size;
22         int32_t stsz_sample_count;
23         int32_t *stsz_table;
24
25         /* stts */
26         int32_t stts_entry_count;
27         int32_t *stts_sample_count;
28         int32_t *stts_sample_delta;
29
30         /* stsc */
31         int32_t stsc_entry_count;
32         int32_t *stsc_first_chunk;
33         int32_t *stsc_samples_per_chunk;
34         int32_t *stsc_sample_desc_index;
35
36         /* stsc */
37         int32_t stco_entry_count;
38         int32_t *stco_chunk_offset;
39
40         uint32_t timeScale;
41         uint64_t duration;
42 };
43
44 #define MAX_TRACKS 1024
45
46 struct mp4 {
47         const struct mp4_callback *cb;
48         int64_t current_position;
49
50         uint64_t moov_offset;
51         uint64_t moov_size;
52         uint8_t last_atom;
53         uint64_t file_size;
54
55         uint32_t read_error;
56         uint32_t error;
57
58         /* incremental track index while reading the file */
59         int32_t total_tracks;
60
61         /* track data */
62         struct mp4_track *track[MAX_TRACKS];
63
64         /* metadata */
65         struct mp4_metadata tags;
66 };
67
68 int32_t mp4_total_tracks(const struct mp4 *f)
69 {
70         return f->total_tracks;
71 }
72
73 static int32_t read_data(struct mp4 *f, void *data, uint32_t size)
74 {
75         int32_t result = 1;
76
77         result = f->cb->read(f->cb->user_data, data, size);
78
79         if (result < size)
80                 f->read_error++;
81
82         f->current_position += size;
83
84         return result;
85 }
86
87 static uint64_t read_int64(struct mp4 *f)
88 {
89         uint8_t data[8];
90
91         read_data(f, data, 8);
92         return read_u64_be(data);
93 }
94
95 static bool atom_compare(int8_t a1, int8_t b1, int8_t c1, int8_t d1,
96                 int8_t a2, int8_t b2, int8_t c2, int8_t d2)
97 {
98         return a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2;
99 }
100 enum atoms {
101         /* atoms with subatoms */
102         ATOM_MOOV = 1,
103         ATOM_TRAK = 2,
104         ATOM_EDTS = 3,
105         ATOM_MDIA = 4,
106         ATOM_MINF = 5,
107         ATOM_STBL = 6,
108         ATOM_UDTA = 7,
109         ATOM_ILST = 8, /* iTunes Metadata list */
110         ATOM_TITLE = 9,
111         ATOM_ARTIST = 10,
112         ATOM_WRITER = 11,
113         ATOM_ALBUM = 12,
114         ATOM_DATE = 13,
115         ATOM_TOOL = 14,
116         ATOM_COMMENT = 15,
117         ATOM_GENRE1 = 16,
118         ATOM_TRACK = 17,
119         ATOM_DISC = 18,
120         ATOM_COMPILATION = 19,
121         ATOM_GENRE2 = 20,
122         ATOM_TEMPO = 21,
123         ATOM_COVER = 22,
124         ATOM_DRMS = 23,
125         ATOM_SINF = 24,
126         ATOM_SCHI = 25,
127
128         SUBATOMIC = 128,
129
130         /* atoms without subatoms */
131         ATOM_FTYP = 129,
132         ATOM_MDAT = 130,
133         ATOM_MVHD = 131,
134         ATOM_TKHD = 132,
135         ATOM_TREF = 133,
136         ATOM_MDHD = 134,
137         ATOM_VMHD = 135,
138         ATOM_SMHD = 136,
139         ATOM_HMHD = 137,
140         ATOM_STSD = 138,
141         ATOM_STTS = 139,
142         ATOM_STSZ = 140,
143         ATOM_STZ2 = 141,
144         ATOM_STCO = 142,
145         ATOM_STSC = 143,
146         ATOM_MP4A = 144,
147         ATOM_MP4V = 145,
148         ATOM_MP4S = 146,
149         ATOM_ESDS = 147,
150         ATOM_META = 148, /* iTunes Metadata box */
151         ATOM_NAME = 149, /* iTunes Metadata name box */
152         ATOM_DATA = 150, /* iTunes Metadata data box */
153         ATOM_CTTS = 151,
154         ATOM_FRMA = 152,
155         ATOM_IVIV = 153,
156         ATOM_PRIV = 154,
157         ATOM_USER = 155,
158         ATOM_KEY = 156,
159         ATOM_ALBUM_ARTIST = 157,
160         ATOM_CONTENTGROUP = 158,
161         ATOM_LYRICS = 159,
162         ATOM_DESCRIPTION = 160,
163         ATOM_NETWORK = 161,
164         ATOM_SHOW = 162,
165         ATOM_EPISODENAME = 163,
166         ATOM_SORTTITLE = 164,
167         ATOM_SORTALBUM = 165,
168         ATOM_SORTARTIST = 166,
169         ATOM_SORTALBUMARTIST = 167,
170         ATOM_SORTWRITER = 168,
171         ATOM_SORTSHOW = 169,
172         ATOM_SEASON = 170,
173         ATOM_EPISODE = 171,
174         ATOM_PODCAST = 172,
175
176         ATOM_UNKNOWN = 255
177 };
178
179 #define ATOM_FREE ATOM_UNKNOWN
180 #define ATOM_SKIP ATOM_UNKNOWN
181
182 #define COPYRIGHT_SYMBOL ((int8_t)0xA9)
183
184 static uint8_t atom_name_to_type(int8_t a, int8_t b, int8_t c, int8_t d)
185 {
186         if (a == 'm') {
187                 if (atom_compare(a, b, c, d, 'm', 'o', 'o', 'v'))
188                         return ATOM_MOOV;
189                 else if (atom_compare(a, b, c, d, 'm', 'i', 'n', 'f'))
190                         return ATOM_MINF;
191                 else if (atom_compare(a, b, c, d, 'm', 'd', 'i', 'a'))
192                         return ATOM_MDIA;
193                 else if (atom_compare(a, b, c, d, 'm', 'd', 'a', 't'))
194                         return ATOM_MDAT;
195                 else if (atom_compare(a, b, c, d, 'm', 'd', 'h', 'd'))
196                         return ATOM_MDHD;
197                 else if (atom_compare(a, b, c, d, 'm', 'v', 'h', 'd'))
198                         return ATOM_MVHD;
199                 else if (atom_compare(a, b, c, d, 'm', 'p', '4', 'a'))
200                         return ATOM_MP4A;
201                 else if (atom_compare(a, b, c, d, 'm', 'p', '4', 'v'))
202                         return ATOM_MP4V;
203                 else if (atom_compare(a, b, c, d, 'm', 'p', '4', 's'))
204                         return ATOM_MP4S;
205                 else if (atom_compare(a, b, c, d, 'm', 'e', 't', 'a'))
206                         return ATOM_META;
207         } else if (a == 't') {
208                 if (atom_compare(a, b, c, d, 't', 'r', 'a', 'k'))
209                         return ATOM_TRAK;
210                 else if (atom_compare(a, b, c, d, 't', 'k', 'h', 'd'))
211                         return ATOM_TKHD;
212                 else if (atom_compare(a, b, c, d, 't', 'r', 'e', 'f'))
213                         return ATOM_TREF;
214                 else if (atom_compare(a, b, c, d, 't', 'r', 'k', 'n'))
215                         return ATOM_TRACK;
216                 else if (atom_compare(a, b, c, d, 't', 'm', 'p', 'o'))
217                         return ATOM_TEMPO;
218                 else if (atom_compare(a, b, c, d, 't', 'v', 'n', 'n'))
219                         return ATOM_NETWORK;
220                 else if (atom_compare(a, b, c, d, 't', 'v', 's', 'h'))
221                         return ATOM_SHOW;
222                 else if (atom_compare(a, b, c, d, 't', 'v', 'e', 'n'))
223                         return ATOM_EPISODENAME;
224                 else if (atom_compare(a, b, c, d, 't', 'v', 's', 'n'))
225                         return ATOM_SEASON;
226                 else if (atom_compare(a, b, c, d, 't', 'v', 'e', 's'))
227                         return ATOM_EPISODE;
228         } else if (a == 's') {
229                 if (atom_compare(a, b, c, d, 's', 't', 'b', 'l'))
230                         return ATOM_STBL;
231                 else if (atom_compare(a, b, c, d, 's', 'm', 'h', 'd'))
232                         return ATOM_SMHD;
233                 else if (atom_compare(a, b, c, d, 's', 't', 's', 'd'))
234                         return ATOM_STSD;
235                 else if (atom_compare(a, b, c, d, 's', 't', 't', 's'))
236                         return ATOM_STTS;
237                 else if (atom_compare(a, b, c, d, 's', 't', 'c', 'o'))
238                         return ATOM_STCO;
239                 else if (atom_compare(a, b, c, d, 's', 't', 's', 'c'))
240                         return ATOM_STSC;
241                 else if (atom_compare(a, b, c, d, 's', 't', 's', 'z'))
242                         return ATOM_STSZ;
243                 else if (atom_compare(a, b, c, d, 's', 't', 'z', '2'))
244                         return ATOM_STZ2;
245                 else if (atom_compare(a, b, c, d, 's', 'k', 'i', 'p'))
246                         return ATOM_SKIP;
247                 else if (atom_compare(a, b, c, d, 's', 'i', 'n', 'f'))
248                         return ATOM_SINF;
249                 else if (atom_compare(a, b, c, d, 's', 'c', 'h', 'i'))
250                         return ATOM_SCHI;
251                 else if (atom_compare(a, b, c, d, 's', 'o', 'n', 'm'))
252                         return ATOM_SORTTITLE;
253                 else if (atom_compare(a, b, c, d, 's', 'o', 'a', 'l'))
254                         return ATOM_SORTALBUM;
255                 else if (atom_compare(a, b, c, d, 's', 'o', 'a', 'r'))
256                         return ATOM_SORTARTIST;
257                 else if (atom_compare(a, b, c, d, 's', 'o', 'a', 'a'))
258                         return ATOM_SORTALBUMARTIST;
259                 else if (atom_compare(a, b, c, d, 's', 'o', 'c', 'o'))
260                         return ATOM_SORTWRITER;
261                 else if (atom_compare(a, b, c, d, 's', 'o', 's', 'n'))
262                         return ATOM_SORTSHOW;
263         } else if (a == COPYRIGHT_SYMBOL) {
264                 if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'n', 'a', 'm'))
265                         return ATOM_TITLE;
266                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'A', 'R', 'T'))
267                         return ATOM_ARTIST;
268                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'w', 'r', 't'))
269                         return ATOM_WRITER;
270                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'a', 'l', 'b'))
271                         return ATOM_ALBUM;
272                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'd', 'a', 'y'))
273                         return ATOM_DATE;
274                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 't', 'o', 'o'))
275                         return ATOM_TOOL;
276                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'c', 'm', 't'))
277                         return ATOM_COMMENT;
278                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'g', 'e', 'n'))
279                         return ATOM_GENRE1;
280                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'g', 'r', 'p'))
281                         return ATOM_CONTENTGROUP;
282                 else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'l', 'y', 'r'))
283                         return ATOM_LYRICS;
284         }
285
286         if (atom_compare(a, b, c, d, 'e', 'd', 't', 's'))
287                 return ATOM_EDTS;
288         else if (atom_compare(a, b, c, d, 'e', 's', 'd', 's'))
289                 return ATOM_ESDS;
290         else if (atom_compare(a, b, c, d, 'f', 't', 'y', 'p'))
291                 return ATOM_FTYP;
292         else if (atom_compare(a, b, c, d, 'f', 'r', 'e', 'e'))
293                 return ATOM_FREE;
294         else if (atom_compare(a, b, c, d, 'h', 'm', 'h', 'd'))
295                 return ATOM_HMHD;
296         else if (atom_compare(a, b, c, d, 'v', 'm', 'h', 'd'))
297                 return ATOM_VMHD;
298         else if (atom_compare(a, b, c, d, 'u', 'd', 't', 'a'))
299                 return ATOM_UDTA;
300         else if (atom_compare(a, b, c, d, 'i', 'l', 's', 't'))
301                 return ATOM_ILST;
302         else if (atom_compare(a, b, c, d, 'n', 'a', 'm', 'e'))
303                 return ATOM_NAME;
304         else if (atom_compare(a, b, c, d, 'd', 'a', 't', 'a'))
305                 return ATOM_DATA;
306         else if (atom_compare(a, b, c, d, 'd', 'i', 's', 'k'))
307                 return ATOM_DISC;
308         else if (atom_compare(a, b, c, d, 'g', 'n', 'r', 'e'))
309                 return ATOM_GENRE2;
310         else if (atom_compare(a, b, c, d, 'c', 'o', 'v', 'r'))
311                 return ATOM_COVER;
312         else if (atom_compare(a, b, c, d, 'c', 'p', 'i', 'l'))
313                 return ATOM_COMPILATION;
314         else if (atom_compare(a, b, c, d, 'c', 't', 't', 's'))
315                 return ATOM_CTTS;
316         else if (atom_compare(a, b, c, d, 'd', 'r', 'm', 's'))
317                 return ATOM_DRMS;
318         else if (atom_compare(a, b, c, d, 'f', 'r', 'm', 'a'))
319                 return ATOM_FRMA;
320         else if (atom_compare(a, b, c, d, 'p', 'r', 'i', 'v'))
321                 return ATOM_PRIV;
322         else if (atom_compare(a, b, c, d, 'i', 'v', 'i', 'v'))
323                 return ATOM_IVIV;
324         else if (atom_compare(a, b, c, d, 'u', 's', 'e', 'r'))
325                 return ATOM_USER;
326         else if (atom_compare(a, b, c, d, 'k', 'e', 'y', ' '))
327                 return ATOM_KEY;
328         else if (atom_compare(a, b, c, d, 'a', 'A', 'R', 'T'))
329                 return ATOM_ALBUM_ARTIST;
330         else if (atom_compare(a, b, c, d, 'd', 'e', 's', 'c'))
331                 return ATOM_DESCRIPTION;
332         else if (atom_compare(a, b, c, d, 'p', 'c', 's', 't'))
333                 return ATOM_PODCAST;
334         else
335                 return ATOM_UNKNOWN;
336 }
337
338 /* read atom header, return atom size, atom size is with header included */
339 static uint64_t atom_read_header(struct mp4 *f, uint8_t * atom_type,
340                                 uint8_t * header_size)
341 {
342         uint64_t size;
343         int32_t ret;
344         int8_t atom_header[8];
345
346         ret = read_data(f, atom_header, 8);
347         if (ret != 8)
348                 return 0;
349
350         size = read_u32_be(atom_header);
351         *header_size = 8;
352
353         /* check for 64 bit atom size */
354         if (size == 1) {
355                 *header_size = 16;
356                 size = read_int64(f);
357         }
358         *atom_type = atom_name_to_type(atom_header[4], atom_header[5],
359                 atom_header[6], atom_header[7]);
360         return size;
361 }
362
363 static int64_t get_position(const struct mp4 *f)
364 {
365         return f->current_position;
366 }
367
368 static int need_parse_when_meta_only(uint8_t atom_type)
369 {
370         switch (atom_type) {
371         case ATOM_EDTS:
372         case ATOM_DRMS:
373         case ATOM_SINF:
374         case ATOM_SCHI:
375         case ATOM_STTS:
376         case ATOM_STSZ:
377         case ATOM_STZ2:
378         case ATOM_STCO:
379         case ATOM_STSC:
380         case ATOM_FRMA:
381         case ATOM_IVIV:
382         case ATOM_PRIV:
383                 return 0;
384         default:
385                 return 1;
386         }
387 }
388
389 static int32_t set_position(struct mp4 *f, int64_t position)
390 {
391         f->cb->seek(f->cb->user_data, position);
392         f->current_position = position;
393
394         return 0;
395 }
396
397 static void track_add(struct mp4 *f)
398 {
399         f->total_tracks++;
400
401         if (f->total_tracks > MAX_TRACKS) {
402                 f->total_tracks = 0;
403                 f->error++;
404                 return;
405         }
406         f->track[f->total_tracks - 1] = para_calloc(sizeof(struct mp4_track));
407 }
408
409 static uint8_t read_char(struct mp4 *f)
410 {
411         uint8_t output;
412         read_data(f, &output, 1);
413         return output;
414 }
415
416 static uint32_t read_int24(struct mp4 *f)
417 {
418         int8_t data[4];
419
420         read_data(f, data, 3);
421         return read_u24_be(data);
422 }
423
424 static uint32_t read_int32(struct mp4 *f)
425 {
426         int8_t data[4];
427
428         read_data(f, data, 4);
429         return read_u32_be(data);
430 }
431
432 static int32_t read_stsz(struct mp4 *f)
433 {
434         int32_t i;
435         struct mp4_track *t;
436
437         if (f->total_tracks == 0)
438                 return f->error++;
439         t = f->track[f->total_tracks - 1];
440         read_char(f);   /* version */
441         read_int24(f);  /* flags */
442         t->stsz_sample_size = read_int32(f);
443         t->stsz_sample_count = read_int32(f);
444         if (t->stsz_sample_size != 0)
445                 return 0;
446         t->stsz_table = para_malloc(t->stsz_sample_count * sizeof(int32_t));
447         for (i = 0; i < t->stsz_sample_count && !f->read_error; i++)
448                 t->stsz_table[i] = read_int32(f);
449         return 0;
450 }
451
452 static int32_t read_stts(struct mp4 *f)
453 {
454         int32_t i;
455         struct mp4_track *t;
456
457         /* CVE-2017-9223 */
458         if (f->total_tracks == 0)
459                 return f->error++;
460         t = f->track[f->total_tracks - 1];
461         if (t->stts_entry_count)
462                 return 0;
463         read_char(f);   /* version */
464         read_int24(f);  /* flags */
465         t->stts_entry_count = read_int32(f);
466
467         t->stts_sample_count = para_malloc(t->stts_entry_count
468                 * sizeof(int32_t));
469         t->stts_sample_delta = para_malloc(t->stts_entry_count
470                 * sizeof (int32_t));
471         /* CVE-2017-9254 */
472         for (i = 0; i < t->stts_entry_count && !f->read_error; i++) {
473                 t->stts_sample_count[i] = read_int32(f);
474                 t->stts_sample_delta[i] = read_int32(f);
475         }
476         return 1;
477 }
478
479 static int32_t read_stsc(struct mp4 *f)
480 {
481         int32_t i;
482         struct mp4_track *t;
483
484         if (f->total_tracks == 0)
485                 return f->error++;
486         t = f->track[f->total_tracks - 1];
487
488         read_char(f);   /* version */
489         read_int24(f);  /* flags */
490         t->stsc_entry_count = read_int32(f);
491         t->stsc_first_chunk = para_malloc(t->stsc_entry_count * sizeof(int32_t));
492         t->stsc_samples_per_chunk = para_malloc(t->stsc_entry_count
493                 * sizeof (int32_t));
494         t->stsc_sample_desc_index = para_malloc(t->stsc_entry_count *
495                 sizeof (int32_t));
496
497         /* CVE-2017-9255 */
498         for (i = 0; i < t->stsc_entry_count && !f->read_error; i++) {
499                 t->stsc_first_chunk[i] = read_int32(f);
500                 t->stsc_samples_per_chunk[i] = read_int32(f);
501                 t->stsc_sample_desc_index[i] = read_int32(f);
502         }
503         return 0;
504 }
505
506 static int32_t read_stco(struct mp4 *f)
507 {
508         int32_t i;
509         struct mp4_track *t;
510
511         if (f->total_tracks == 0)
512                 return f->error++;
513         t = f->track[f->total_tracks - 1];
514
515         read_char(f);   /* version */
516         read_int24(f);  /* flags */
517         t->stco_entry_count = read_int32(f);
518         t->stco_chunk_offset = para_malloc(t->stco_entry_count
519                 * sizeof(int32_t));
520         /* CVE-2017-9256 */
521         for (i = 0; i < t->stco_entry_count && !f->read_error; i++)
522                 t->stco_chunk_offset[i] = read_int32(f);
523         return 0;
524 }
525
526 static uint16_t read_int16(struct mp4 *f)
527 {
528         int8_t data[2];
529
530         read_data(f, data, 2);
531         return read_u16_be(data);
532 }
533
534 static int32_t read_mp4a(struct mp4 *f)
535 {
536         int32_t i;
537         uint8_t atom_type = 0;
538         uint8_t header_size = 0;
539         struct mp4_track *t;
540
541         if (f->total_tracks == 0)
542                 return f->error++;
543         t = f->track[f->total_tracks - 1];
544
545         for (i = 0; i < 6; i++) {
546                 read_char(f);   /* reserved */
547         }
548         /* data_reference_index */ read_int16(f);
549
550         read_int32(f);  /* reserved */
551         read_int32(f);  /* reserved */
552
553         t->channelCount = read_int16(f);
554         read_int16(f);
555
556         read_int16(f);
557         read_int16(f);
558
559         t->sampleRate = read_int16(f);
560
561         read_int16(f);
562
563         atom_read_header(f, &atom_type, &header_size);
564         return 0;
565 }
566
567 static int32_t read_stsd(struct mp4 *f)
568 {
569         int32_t i, entry_count;
570         uint8_t header_size = 0;
571         struct mp4_track *t;
572
573         /* CVE-2017-9218 */
574         if (f->total_tracks == 0)
575                 return f->error++;
576         t = f->track[f->total_tracks - 1];
577
578         read_char(f);   /* version */
579         read_int24(f);  /* flags */
580
581         entry_count = read_int32(f);
582
583         /* CVE-2017-9253 */
584         for (i = 0; i < entry_count && !f->read_error; i++) {
585                 uint64_t skip = get_position(f);
586                 uint64_t size;
587                 uint8_t atom_type = 0;
588                 size = atom_read_header(f, &atom_type, &header_size);
589                 skip += size;
590                 t->is_audio = atom_type == ATOM_MP4A;
591                 if (t->is_audio)
592                         read_mp4a(f);
593                 set_position(f, skip);
594         }
595
596         return 0;
597 }
598
599 static int32_t tag_add_field(struct mp4_metadata *tags, const char *item,
600                 const char *value, int32_t len)
601 {
602         tags->tags = para_realloc(tags->tags,
603                 (tags->count + 1) * sizeof(struct mp4_tag));
604         tags->tags[tags->count].item = para_strdup(item);
605         tags->tags[tags->count].len = len;
606         if (len >= 0) {
607                 tags->tags[tags->count].value = para_malloc(len + 1);
608                 memcpy(tags->tags[tags->count].value, value, len);
609                 tags->tags[tags->count].value[len] = 0;
610         } else {
611                 tags->tags[tags->count].value = para_strdup(value);
612         }
613         tags->count++;
614         return 1;
615 }
616
617 static const char *ID3v1GenreList[] = {
618         "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
619         "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
620         "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
621         "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
622         "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal",
623         "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid",
624         "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
625         "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
626         "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
627         "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
628         "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40",
629         "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
630         "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
631         "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
632         "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk",
633         "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic",
634         "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock",
635         "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
636         "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
637         "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
638         "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
639         "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
640         "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
641         "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
642         "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
643         "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover",
644         "Contemporary C", "Christian Rock", "Merengue", "Salsa", "Thrash Metal",
645         "Anime", "JPop", "SynthPop",
646 };
647
648 static char *read_string(struct mp4 *f, uint32_t length)
649 {
650         char *str = para_malloc(length + 1);
651         if ((uint32_t)read_data(f, str, length) != length) {
652                 free(str);
653                 str = NULL;
654         } else
655                 str[length] = 0;
656         return str;
657 }
658
659 static const char *get_metadata_name(uint8_t atom_type)
660 {
661         switch (atom_type) {
662         case ATOM_TITLE: return "title";
663         case ATOM_ARTIST: return "artist";
664         case ATOM_ALBUM: return "album";
665         case ATOM_DATE: return "date";
666         case ATOM_COMMENT: return "comment";
667         default: return "unknown";
668         }
669 }
670
671 static void parse_tag(struct mp4 *f, uint8_t parent, int32_t size)
672 {
673         uint64_t subsize, sumsize;
674         char *data = NULL;
675         uint32_t len = 0;
676         uint64_t destpos;
677
678         for (
679                 sumsize = 0;
680                 sumsize < size && !f->read_error; /* CVE-2017-9222 */
681                 set_position(f, destpos), sumsize += subsize
682         ) {
683                 uint8_t atom_type;
684                 uint8_t header_size = 0;
685                 subsize = atom_read_header(f, &atom_type, &header_size);
686                 destpos = get_position(f) + subsize - header_size;
687                 if (atom_type != ATOM_DATA)
688                         continue;
689                 read_char(f);   /* version */
690                 read_int24(f);  /* flags */
691                 read_int32(f);  /* reserved */
692                 free(data);
693                 data = read_string(f, subsize - (header_size + 8));
694                 len = subsize - (header_size + 8);
695         }
696         if (!data)
697                 return;
698         tag_add_field(&f->tags, get_metadata_name(parent), data, len);
699         free(data);
700 }
701
702 static int32_t read_mdhd(struct mp4 *f)
703 {
704         uint32_t version;
705         struct mp4_track *t;
706
707         /* CVE-2017-9221 */
708         if (f->total_tracks == 0)
709                 return f->error++;
710         t = f->track[f->total_tracks - 1];
711
712         version = read_int32(f);
713         if (version == 1) {
714                 read_int64(f); //creation-time
715                 read_int64(f); //modification-time
716                 t->timeScale = read_int32(f); //timescale
717                 t->duration = read_int64(f); //duration
718         } else { //version == 0
719                 uint32_t temp;
720
721                 read_int32(f);  //creation-time
722                 read_int32(f);  //modification-time
723                 t->timeScale = read_int32(f); //timescale
724                 temp = read_int32(f);
725                 t->duration = (temp == (uint32_t) (-1))?
726                         (uint64_t) (-1) : (uint64_t) (temp);
727         }
728         read_int16(f);
729         read_int16(f);
730         return 1;
731 }
732
733 static int32_t parse_metadata(struct mp4 *f, int32_t size)
734 {
735         uint64_t sumsize = 0;
736
737         while (sumsize < size) {
738                 uint8_t atom_type;
739                 uint64_t subsize, destpos;
740                 uint8_t header_size = 0;
741                 subsize = atom_read_header(f, &atom_type, &header_size);
742                 if (subsize == 0)
743                         break;
744                 destpos = get_position(f) + subsize - header_size;
745                 switch (atom_type) {
746                 case ATOM_ARTIST:
747                 case ATOM_TITLE:
748                 case ATOM_ALBUM:
749                 case ATOM_COMMENT:
750                 case ATOM_DATE:
751                         parse_tag(f, atom_type, subsize - header_size);
752                 }
753                 set_position(f, destpos);
754                 sumsize += subsize;
755         }
756
757         return 0;
758 }
759
760 static int32_t read_meta(struct mp4 *f, uint64_t size)
761 {
762         uint64_t subsize, sumsize = 0;
763         uint8_t atom_type;
764         uint8_t header_size = 0;
765
766         read_char(f);   /* version */
767         read_int24(f);  /* flags */
768
769         while (sumsize < (size - (header_size + 4))) {
770                 subsize = atom_read_header(f, &atom_type, &header_size);
771                 if (subsize <= header_size + 4)
772                         return 1;
773                 if (atom_type == ATOM_ILST) {
774                         parse_metadata(f, (uint32_t) (subsize - (header_size + 4)));
775                 } else {
776                         set_position(f, get_position(f) + subsize - header_size);
777                 }
778                 sumsize += subsize;
779         }
780
781         return 0;
782 }
783
784 static int32_t atom_read(struct mp4 *f, int32_t size, uint8_t atom_type)
785 {
786         uint64_t dest_position = get_position(f) + size - 8;
787         if (atom_type == ATOM_STSZ) {
788                 /* sample size box */
789                 read_stsz(f);
790         } else if (atom_type == ATOM_STTS) {
791                 /* time to sample box */
792                 read_stts(f);
793         } else if (atom_type == ATOM_STSC) {
794                 /* sample to chunk box */
795                 read_stsc(f);
796         } else if (atom_type == ATOM_STCO) {
797                 /* chunk offset box */
798                 read_stco(f);
799         } else if (atom_type == ATOM_STSD) {
800                 /* sample description box */
801                 read_stsd(f);
802         } else if (atom_type == ATOM_MDHD) {
803                 /* track header */
804                 read_mdhd(f);
805         } else if (atom_type == ATOM_META) {
806                 /* iTunes Metadata box */
807                 read_meta(f, size);
808         }
809
810         set_position(f, dest_position);
811         return 0;
812 }
813
814 /* parse atoms that are sub atoms of other atoms */
815 static int32_t parse_sub_atoms(struct mp4 *f, uint64_t total_size, int meta_only)
816 {
817         uint64_t size;
818         uint8_t atom_type = 0;
819         uint64_t counted_size = 0;
820         uint8_t header_size = 0;
821
822         while (counted_size < total_size) {
823                 size = atom_read_header(f, &atom_type, &header_size);
824                 counted_size += size;
825
826                 /* check for end of file */
827                 if (size == 0)
828                         break;
829
830                 /* we're starting to read a new track, update index,
831                  * so that all data and tables get written in the right place
832                  */
833                 if (atom_type == ATOM_TRAK)
834                         track_add(f);
835                 /* parse subatoms */
836                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
837                         set_position(f, get_position(f) + size - header_size);
838                 } else if (atom_type < SUBATOMIC) {
839                         parse_sub_atoms(f, size - header_size, meta_only);
840                 } else {
841                         atom_read(f, (uint32_t) size, atom_type);
842                 }
843         }
844
845         return 0;
846 }
847
848 /* parse root atoms */
849 static int32_t parse_atoms(struct mp4 *f, int meta_only)
850 {
851         uint64_t size;
852         uint8_t atom_type = 0;
853         uint8_t header_size = 0;
854
855         f->file_size = 0;
856         f->read_error = 0;
857
858         while ((size =
859                 atom_read_header(f, &atom_type, &header_size)) != 0) {
860                 f->file_size += size;
861                 f->last_atom = atom_type;
862
863                 if (atom_type == ATOM_MOOV && size > header_size) {
864                         f->moov_offset = get_position(f) - header_size;
865                         f->moov_size = size;
866                 }
867
868                 /* parse subatoms */
869                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
870                         set_position(f, get_position(f) + size - header_size);
871                 } else if (atom_type < SUBATOMIC) {
872                         parse_sub_atoms(f, size - header_size, meta_only);
873                 } else {
874                         /* skip this atom */
875                         set_position(f, get_position(f) + size - header_size);
876                 }
877         }
878
879         return 0;
880 }
881
882 struct mp4 *mp4_open_read(const struct mp4_callback *cb)
883 {
884         struct mp4 *f = para_calloc(sizeof(struct mp4));
885
886         f->cb = cb;
887         parse_atoms(f, 0);
888         if (f->error) {
889                 free(f);
890                 f = NULL;
891         }
892         return f;
893 }
894
895 static int32_t tag_delete(struct mp4_metadata *tags)
896 {
897         uint32_t i;
898
899         for (i = 0; i < tags->count; i++) {
900                 free(tags->tags[i].item);
901                 free(tags->tags[i].value);
902         }
903         free(tags->tags);
904         tags->tags = NULL;
905         tags->count = 0;
906
907         return 0;
908 }
909
910 void mp4_close(struct mp4 *f)
911 {
912         int32_t i;
913
914         for (i = 0; i < f->total_tracks; i++) {
915                 if (f->track[i]) {
916                         free(f->track[i]->stsz_table);
917                         free(f->track[i]->stts_sample_count);
918                         free(f->track[i]->stts_sample_delta);
919                         free(f->track[i]->stsc_first_chunk);
920                         free(f->track[i]->stsc_samples_per_chunk);
921                         free(f->track[i]->stsc_sample_desc_index);
922                         free(f->track[i]->stco_chunk_offset);
923                         free(f->track[i]);
924                 }
925         }
926
927         tag_delete(&(f->tags));
928         free(f);
929 }
930
931 static int32_t chunk_of_sample(const struct mp4 *f, int32_t track,
932                 int32_t sample, int32_t *chunk_sample, int32_t *chunk)
933 {
934         int32_t total_entries = 0;
935         int32_t chunk2entry;
936         int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
937
938         *chunk_sample = 0;
939         *chunk = 1;
940         if (f->track[track] == NULL) {
941                 return -1;
942         }
943
944         total_entries = f->track[track]->stsc_entry_count;
945
946         chunk1 = 1;
947         chunk1samples = 0;
948         chunk2entry = 0;
949
950         do {
951                 chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
952                 *chunk = chunk2 - chunk1;
953                 range_samples = *chunk * chunk1samples;
954
955                 if (sample < total + range_samples)
956                         break;
957
958                 chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
959                 chunk1 = chunk2;
960
961                 if (chunk2entry < total_entries) {
962                         chunk2entry++;
963                         total += range_samples;
964                 }
965         } while (chunk2entry < total_entries);
966
967         if (chunk1samples)
968                 *chunk = (sample - total) / chunk1samples + chunk1;
969         else
970                 *chunk = 1;
971
972         *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
973
974         return 0;
975 }
976
977 static int32_t chunk_to_offset(const struct mp4 *f, int32_t track,
978                 int32_t chunk)
979 {
980         const struct mp4_track *p_track = f->track[track];
981
982         if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) {
983                 return p_track->stco_chunk_offset[p_track->stco_entry_count -
984                                                   1];
985         } else if (p_track->stco_entry_count) {
986                 return p_track->stco_chunk_offset[chunk - 1];
987         } else {
988                 return 8;
989         }
990
991         return 0;
992 }
993
994 static int32_t sample_range_size(const struct mp4 *f, int32_t track,
995                 int32_t chunk_sample, int32_t sample)
996 {
997         int32_t i, total;
998         const struct mp4_track *p_track = f->track[track];
999
1000         if (p_track->stsz_sample_size) {
1001                 return (sample - chunk_sample) * p_track->stsz_sample_size;
1002         } else {
1003                 if (sample >= p_track->stsz_sample_count)
1004                         return 0;       //error
1005
1006                 for (i = chunk_sample, total = 0; i < sample; i++) {
1007                         total += p_track->stsz_table[i];
1008                 }
1009         }
1010
1011         return total;
1012 }
1013
1014 static int32_t sample_to_offset(const struct mp4 *f, int32_t track,
1015                 int32_t sample)
1016 {
1017         int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
1018
1019         chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
1020
1021         chunk_offset1 = chunk_to_offset(f, track, chunk);
1022         chunk_offset2 = chunk_offset1 + sample_range_size(f,
1023                 track, chunk_sample, sample);
1024         return chunk_offset2;
1025 }
1026
1027 /**
1028  * Return the number of milliseconds of the given track.
1029  *
1030  * \param f As returned by \ref mp4_open_read(), must not be NULL.
1031  * \param track Between zero and the value returned by \ref mp4_total_tracks().
1032  *
1033  * The function returns zero if the audio file is of zero length or contains a
1034  * corrupt track header.
1035  */
1036 uint64_t mp4_get_duration(const struct mp4 *f, int32_t track)
1037 {
1038         const struct mp4_track *t = f->track[track];
1039
1040         if (t->timeScale == 0)
1041                 return 0;
1042         return t->duration * 1000 / t->timeScale;
1043 }
1044
1045 /**
1046  * Check whether the given track number corresponds to an audio track.
1047  *
1048  * \param f See \ref mp4_get_duration().
1049  * \param track See \ref mp4_get_duration().
1050  *
1051  * Besides audio tracks, an mp4 file may contain video and system tracks. For
1052  * those the function returns false.
1053  */
1054 bool mp4_is_audio_track(const struct mp4 *f, int32_t track)
1055 {
1056         return f->track[track]->is_audio;
1057 }
1058
1059 void mp4_set_sample_position(struct mp4 *f, int32_t track, int32_t sample)
1060 {
1061         int32_t offset = sample_to_offset(f, track, sample);
1062         set_position(f, offset);
1063 }
1064
1065 int32_t mp4_get_sample_size(const struct mp4 *f, int track, int sample)
1066 {
1067         const struct mp4_track *t = f->track[track];
1068
1069         if (t->stsz_sample_size != 0)
1070                 return t->stsz_sample_size;
1071         return t->stsz_table[sample];
1072 }
1073
1074 uint32_t mp4_get_sample_rate(const struct mp4 *f, int32_t track)
1075 {
1076         return f->track[track]->sampleRate;
1077 }
1078
1079 uint32_t mp4_get_channel_count(const struct mp4 *f, int32_t track)
1080 {
1081         return f->track[track]->channelCount;
1082 }
1083
1084 int32_t mp4_num_samples(const struct mp4 *f, int32_t track)
1085 {
1086         int32_t i;
1087         int32_t total = 0;
1088
1089         for (i = 0; i < f->track[track]->stts_entry_count; i++) {
1090                 total += f->track[track]->stts_sample_count[i];
1091         }
1092         return total;
1093 }
1094
1095 struct mp4 *mp4_open_meta(const struct mp4_callback *cb)
1096 {
1097         struct mp4 *f = para_calloc(sizeof(struct mp4));
1098
1099         f->cb = cb;
1100         parse_atoms(f, 1);
1101         if (f->error) {
1102                 free(f);
1103                 f = NULL;
1104         }
1105         return f;
1106 }
1107
1108 /**
1109  * Return the metadata of an mp4 file.
1110  *
1111  * \param f As returned by either \ref mp4_open_read() or \ref mp4_open_meta().
1112  *
1113  * The caller is allowed to add, delete or modify the entries of the returned
1114  * structure in order to pass the modified version to \ref mp4_meta_update().
1115  */
1116 struct mp4_metadata *mp4_get_meta(struct mp4 *f)
1117 {
1118         return &f->tags;
1119 }
1120
1121 static uint32_t find_atom(struct mp4 *f, uint64_t base, uint32_t size,
1122                           const char *name)
1123 {
1124         uint32_t remaining = size;
1125         uint64_t atom_offset = base;
1126         for (;;) {
1127                 char atom_name[4];
1128                 uint32_t atom_size;
1129
1130                 set_position(f, atom_offset);
1131
1132                 if (remaining < 8)
1133                         break;
1134                 atom_size = read_int32(f);
1135                 if (atom_size > remaining || atom_size < 8)
1136                         break;
1137                 read_data(f, atom_name, 4);
1138
1139                 if (!memcmp(atom_name, name, 4)) {
1140                         set_position(f, atom_offset);
1141                         return 1;
1142                 }
1143
1144                 remaining -= atom_size;
1145                 atom_offset += atom_size;
1146         }
1147         return 0;
1148 }
1149
1150 static uint32_t find_atom_v2(struct mp4 *f, uint64_t base, uint32_t size,
1151                 const char *name, uint32_t extraheaders, const char *name_inside)
1152 {
1153         uint64_t first_base = (uint64_t) (-1);
1154         while (find_atom(f, base, size, name))  //try to find atom <name> with atom <name_inside> in it
1155         {
1156                 uint64_t mybase = get_position(f);
1157                 uint32_t mysize = read_int32(f);
1158
1159                 if (first_base == (uint64_t) (-1))
1160                         first_base = mybase;
1161
1162                 if (mysize < 8 + extraheaders)
1163                         break;
1164
1165                 if (find_atom (f, mybase + (8 + extraheaders),
1166                                 mysize - (8 + extraheaders), name_inside)) {
1167                         set_position(f, mybase);
1168                         return 2;
1169                 }
1170                 base += mysize;
1171                 if (size <= mysize) {
1172                         size = 0;
1173                         break;
1174                 }
1175                 size -= mysize;
1176         }
1177
1178         if (first_base != (uint64_t) (-1))      //wanted atom inside not found
1179         {
1180                 set_position(f, first_base);
1181                 return 1;
1182         } else
1183                 return 0;
1184 }
1185
1186 struct membuffer {
1187         void *data;
1188         unsigned written;
1189         unsigned allocated;
1190         unsigned error;
1191 };
1192
1193 static struct membuffer *membuffer_create(void)
1194 {
1195         const unsigned initial_size = 256;
1196
1197         struct membuffer *buf = para_malloc(sizeof(*buf));
1198         buf->data = para_malloc(initial_size);
1199         buf->written = 0;
1200         buf->allocated = initial_size;
1201         buf->error = buf->data == 0 ? 1 : 0;
1202
1203         return buf;
1204 }
1205
1206 static unsigned membuffer_write(struct membuffer *buf, const void *ptr, unsigned bytes)
1207 {
1208         unsigned dest_size = buf->written + bytes;
1209
1210         if (buf->error)
1211                 return 0;
1212         if (dest_size > buf->allocated) {
1213                 do {
1214                         buf->allocated <<= 1;
1215                 } while (dest_size > buf->allocated);
1216                 buf->data = para_realloc(buf->data, buf->allocated);
1217         }
1218
1219         if (ptr)
1220                 memcpy((char *) buf->data + buf->written, ptr, bytes);
1221         buf->written += bytes;
1222         return bytes;
1223 }
1224
1225 static unsigned membuffer_write_atom_name(struct membuffer *buf, const char *data)
1226 {
1227         return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
1228 }
1229
1230 static unsigned membuffer_write_int16(struct membuffer *buf, uint16_t data)
1231 {
1232         uint8_t temp[2];
1233
1234         write_u16_be(temp, data);
1235         return membuffer_write(buf, temp, 2);
1236 }
1237
1238 static unsigned membuffer_write_int32(struct membuffer *buf, uint32_t data)
1239 {
1240         uint8_t temp[4];
1241         write_u32_be(temp, data);
1242         return membuffer_write(buf, temp, 4);
1243 }
1244
1245 static void membuffer_write_track_tag(struct membuffer *buf, const char *name,
1246                 uint32_t index, uint32_t total)
1247 {
1248         membuffer_write_int32(buf,
1249                 8 /*atom header */  + 8 /*data atom header */  +
1250                 8 /*flags + reserved */  + 8 /*actual data */ );
1251         membuffer_write_atom_name(buf, name);
1252         membuffer_write_int32(buf,
1253                 8 /*data atom header */  +
1254                 8 /*flags + reserved */  + 8 /*actual data */ );
1255         membuffer_write_atom_name(buf, "data");
1256         membuffer_write_int32(buf, 0);  //flags
1257         membuffer_write_int32(buf, 0);  //reserved
1258         membuffer_write_int16(buf, 0);
1259         membuffer_write_int16(buf, (uint16_t) index);   //track number
1260         membuffer_write_int16(buf, (uint16_t) total);   //total tracks
1261         membuffer_write_int16(buf, 0);
1262 }
1263
1264 static void membuffer_write_int16_tag(struct membuffer *buf, const char *name,
1265                 uint16_t value)
1266 {
1267         membuffer_write_int32(buf,
1268                 8 /*atom header */  + 8 /*data atom header */  +
1269                 8 /*flags + reserved */  + 2 /*actual data */ );
1270         membuffer_write_atom_name(buf, name);
1271         membuffer_write_int32(buf,
1272                 8 /*data atom header */  +
1273                 8 /*flags + reserved */  + 2 /*actual data */ );
1274         membuffer_write_atom_name(buf, "data");
1275         membuffer_write_int32(buf, 0);  //flags
1276         membuffer_write_int32(buf, 0);  //reserved
1277         membuffer_write_int16(buf, value);      //value
1278 }
1279
1280 static uint32_t myatoi(const char *param)
1281 {
1282         return param ? atoi(param) : 0;
1283 }
1284
1285 static uint32_t meta_genre_to_index(const char *genrestr)
1286 {
1287         unsigned n;
1288         for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
1289                 if (!strcasecmp(genrestr, ID3v1GenreList[n]))
1290                         return n + 1;
1291         }
1292         return 0;
1293 }
1294
1295 struct stdmeta_entry {
1296         const char *atom;
1297         const char *name;
1298 };
1299
1300 struct stdmeta_entry stdmetas[] = {
1301         {"\xA9" "nam", "title"},
1302         {"\xA9" "ART", "artist"},
1303         {"\xA9" "wrt", "writer"},
1304         {"\xA9" "alb", "album"},
1305         {"\xA9" "day", "date"},
1306         {"\xA9" "too", "tool"},
1307         {"\xA9" "cmt", "comment"},
1308         {"cpil", "compilation"},
1309         {"covr", "cover"},
1310         {"aART", "album_artist"},
1311 };
1312
1313 static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
1314 {
1315         unsigned n;
1316         for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
1317                 if (!strcasecmp(name, stdmetas[n].name))
1318                         return stdmetas[n].atom;
1319         }
1320         return 0;
1321 }
1322
1323 static void membuffer_write_std_tag(struct membuffer *buf, const char *name,
1324                 const char *value)
1325 {
1326         uint32_t flags = 1;
1327
1328         /* special check for compilation flag */
1329         if (strcmp(name, "cpil") == 0) {
1330                 flags = 21;
1331         }
1332
1333         membuffer_write_int32(buf,
1334                 8 /*atom header */  + 8 /*data atom header */  +
1335                 8 /*flags + reserved */  + strlen(value));
1336         membuffer_write_atom_name(buf, name);
1337         membuffer_write_int32(buf,
1338                 8 /*data atom header */  +
1339                 8 /*flags + reserved */  + strlen(value));
1340         membuffer_write_atom_name(buf, "data");
1341         membuffer_write_int32(buf, flags);      //flags
1342         membuffer_write_int32(buf, 0);  //reserved
1343         membuffer_write(buf, value, strlen(value));
1344 }
1345
1346 static void membuffer_write_custom_tag(struct membuffer *buf, const char *name,
1347                 const char *value)
1348 {
1349         membuffer_write_int32(buf,
1350                 8 /*atom header */  +
1351                 0x1C /*weirdo itunes atom */  +
1352                 12 /*name atom header */  + strlen(name) +
1353                 16 /*data atom header + flags */  + strlen(value));
1354         membuffer_write_atom_name(buf, "----");
1355         membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
1356         membuffer_write_atom_name(buf, "mean");
1357         membuffer_write_int32(buf, 0);
1358         membuffer_write(buf, "com.apple.iTunes", 16);
1359         membuffer_write_int32(buf, 12 + strlen(name));
1360         membuffer_write_atom_name(buf, "name");
1361         membuffer_write_int32(buf, 0);
1362         membuffer_write(buf, name, strlen(name));
1363         membuffer_write_int32(buf,
1364                 8 /*data atom header */  +
1365                 8 /*flags + reserved */  + strlen(value));
1366         membuffer_write_atom_name(buf, "data");
1367         membuffer_write_int32(buf, 1);  //flags
1368         membuffer_write_int32(buf, 0);  //reserved
1369         membuffer_write(buf, value, strlen(value));
1370 }
1371
1372 static unsigned membuffer_error(const struct membuffer *buf)
1373 {
1374         return buf->error;
1375 }
1376
1377 static void membuffer_free(struct membuffer *buf)
1378 {
1379         free(buf->data);
1380         free(buf);
1381 }
1382
1383 static unsigned membuffer_get_size(const struct membuffer *buf)
1384 {
1385         return buf->written;
1386 }
1387
1388 static void *membuffer_detach(struct membuffer *buf)
1389 {
1390         void *ret;
1391
1392         if (buf->error)
1393                 return 0;
1394         ret = para_realloc(buf->data, buf->written);
1395         buf->data = 0;
1396         buf->error = 1;
1397         return ret;
1398 }
1399
1400 static uint32_t create_ilst(const struct mp4_metadata *data, void **out_buffer,
1401                 uint32_t * out_size)
1402 {
1403         struct membuffer *buf = membuffer_create();
1404         unsigned metaptr;
1405         char *mask = para_calloc(data->count);
1406         const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1407         const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1408         const char *genre_ptr = 0, *tempo_ptr = 0;
1409
1410         for (metaptr = 0; metaptr < data->count; metaptr++) {
1411                 struct mp4_tag *tag = &data->tags[metaptr];
1412                 if (!strcasecmp(tag->item, "tracknumber")
1413                                 || !strcasecmp(tag->item, "track")) {
1414                         if (tracknumber_ptr == 0)
1415                                 tracknumber_ptr = tag->value;
1416                         mask[metaptr] = 1;
1417                 } else if (!strcasecmp(tag->item, "totaltracks")) {
1418                         if (totaltracks_ptr == 0)
1419                                 totaltracks_ptr = tag->value;
1420                         mask[metaptr] = 1;
1421                 } else if (!strcasecmp(tag->item, "discnumber")
1422                                 || !strcasecmp(tag->item, "disc")) {
1423                         if (discnumber_ptr == 0)
1424                                 discnumber_ptr = tag->value;
1425                         mask[metaptr] = 1;
1426                 } else if (!strcasecmp(tag->item, "totaldiscs")) {
1427                         if (totaldiscs_ptr == 0)
1428                                 totaldiscs_ptr = tag->value;
1429                         mask[metaptr] = 1;
1430                 } else if (!strcasecmp(tag->item, "genre")) {
1431                         if (genre_ptr == 0)
1432                                 genre_ptr = tag->value;
1433                         mask[metaptr] = 1;
1434                 } else if (!strcasecmp(tag->item, "tempo")) {
1435                         if (tempo_ptr == 0)
1436                                 tempo_ptr = tag->value;
1437                         mask[metaptr] = 1;
1438                 }
1439         }
1440
1441         if (tracknumber_ptr)
1442                 membuffer_write_track_tag(buf, "trkn", myatoi(tracknumber_ptr),
1443                          myatoi(totaltracks_ptr));
1444         if (discnumber_ptr)
1445                 membuffer_write_track_tag(buf, "disk", myatoi(discnumber_ptr),
1446                          myatoi(totaldiscs_ptr));
1447         if (tempo_ptr)
1448                 membuffer_write_int16_tag(buf, "tmpo", myatoi(tempo_ptr));
1449
1450         if (genre_ptr) {
1451                 uint32_t index = meta_genre_to_index(genre_ptr);
1452                 if (index == 0)
1453                         membuffer_write_std_tag(buf, "©gen", genre_ptr);
1454                 else
1455                         membuffer_write_int16_tag(buf, "gnre", index);
1456         }
1457         for (metaptr = 0; metaptr < data->count; metaptr++) {
1458                 struct mp4_tag *tag;
1459                 const char *std_meta_atom;
1460
1461                 if (mask[metaptr])
1462                         continue;
1463                 tag = &data->tags[metaptr];
1464                 std_meta_atom = find_standard_meta(tag->item);
1465                 if (std_meta_atom)
1466                         membuffer_write_std_tag(buf, std_meta_atom, tag->value);
1467                 else
1468                         membuffer_write_custom_tag(buf, tag->item, tag->value);
1469         }
1470         free(mask);
1471
1472         if (membuffer_error(buf)) {
1473                 membuffer_free(buf);
1474                 return 0;
1475         }
1476
1477         *out_size = membuffer_get_size(buf);
1478         *out_buffer = membuffer_detach(buf);
1479         membuffer_free(buf);
1480
1481         return 1;
1482 }
1483
1484 static void membuffer_write_atom(struct membuffer *buf, const char *name, unsigned size,
1485                           const void *data)
1486 {
1487         membuffer_write_int32(buf, size + 8);
1488         membuffer_write_atom_name(buf, name);
1489         membuffer_write(buf, data, size);
1490 }
1491
1492 static void *membuffer_get_ptr(const struct membuffer *buf)
1493 {
1494         return buf->data;
1495 }
1496
1497 static void membuffer_set_error(struct membuffer *buf)
1498 {
1499         buf->error = 1;
1500 }
1501
1502 static unsigned membuffer_transfer_from_file(struct membuffer *buf, struct mp4 *src,
1503                 unsigned bytes)
1504 {
1505         unsigned oldsize;
1506         void *bufptr;
1507
1508         oldsize = membuffer_get_size(buf);
1509         if (membuffer_write(buf, 0, bytes) != bytes)
1510                 return 0;
1511
1512         bufptr = membuffer_get_ptr(buf);
1513         if (bufptr == 0)
1514                 return 0;
1515
1516         if ((unsigned)read_data(src, (char *) bufptr + oldsize, bytes) !=
1517                 bytes) {
1518                 membuffer_set_error(buf);
1519                 return 0;
1520         }
1521
1522         return bytes;
1523 }
1524
1525 static uint32_t create_meta(const struct mp4_metadata *data, void **out_buffer,
1526                 uint32_t * out_size)
1527 {
1528         struct membuffer *buf;
1529         uint32_t ilst_size;
1530         void *ilst_buffer;
1531
1532         if (!create_ilst(data, &ilst_buffer, &ilst_size))
1533                 return 0;
1534
1535         buf = membuffer_create();
1536
1537         membuffer_write_int32(buf, 0);
1538         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
1539         free(ilst_buffer);
1540
1541         *out_size = membuffer_get_size(buf);
1542         *out_buffer = membuffer_detach(buf);
1543         membuffer_free(buf);
1544         return 1;
1545 }
1546
1547 static uint32_t create_udta(const struct mp4_metadata *data, void **out_buffer,
1548 uint32_t * out_size)
1549 {
1550         struct membuffer *buf;
1551         uint32_t meta_size;
1552         void *meta_buffer;
1553
1554         if (!create_meta(data, &meta_buffer, &meta_size))
1555                 return 0;
1556
1557         buf = membuffer_create();
1558
1559         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
1560
1561         free(meta_buffer);
1562
1563         *out_size = membuffer_get_size(buf);
1564         *out_buffer = membuffer_detach(buf);
1565         membuffer_free(buf);
1566         return 1;
1567 }
1568
1569 static uint32_t fix_byte_order_32(uint32_t src)
1570 {
1571         return read_u32_be(&src);
1572 }
1573
1574 static uint32_t modify_moov(struct mp4 *f, void **out_buffer,
1575                 uint32_t *out_size)
1576 {
1577         uint64_t total_base = f->moov_offset + 8;
1578         uint32_t total_size = (uint32_t) (f->moov_size - 8);
1579
1580         uint64_t udta_offset, meta_offset, ilst_offset;
1581         uint32_t udta_size, meta_size, ilst_size;
1582
1583         uint32_t new_ilst_size;
1584         void *new_ilst_buffer;
1585
1586         uint8_t *p_out;
1587         int32_t size_delta;
1588
1589         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
1590                 struct membuffer *buf;
1591                 void *new_udta_buffer;
1592                 uint32_t new_udta_size;
1593                 if (!create_udta(&f->tags, &new_udta_buffer, &new_udta_size))
1594                         return 0;
1595
1596                 buf = membuffer_create();
1597                 set_position(f, total_base);
1598                 membuffer_transfer_from_file(buf, f, total_size);
1599
1600                 membuffer_write_atom(buf, "udta", new_udta_size,
1601                         new_udta_buffer);
1602
1603                 free(new_udta_buffer);
1604
1605                 *out_size = membuffer_get_size(buf);
1606                 *out_buffer = membuffer_detach(buf);
1607                 membuffer_free(buf);
1608                 return 1;
1609         } else {
1610                 udta_offset = get_position(f);
1611                 udta_size = read_int32(f);
1612                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
1613                         struct membuffer *buf;
1614                         void *new_meta_buffer;
1615                         uint32_t new_meta_size;
1616
1617                         if (!create_meta(&f->tags, &new_meta_buffer, &new_meta_size))
1618                                 return 0;
1619
1620                         buf = membuffer_create();
1621                         set_position(f, total_base);
1622                         membuffer_transfer_from_file(buf, f,
1623                                 (uint32_t)(udta_offset - total_base));
1624
1625                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
1626                         membuffer_write_atom_name(buf, "udta");
1627                         membuffer_transfer_from_file(buf, f, udta_size);
1628
1629                         membuffer_write_atom(buf, "meta", new_meta_size,
1630                                 new_meta_buffer);
1631                         free(new_meta_buffer);
1632
1633                         *out_size = membuffer_get_size(buf);
1634                         *out_buffer = membuffer_detach(buf);
1635                         membuffer_free(buf);
1636                         return 1;
1637                 }
1638                 meta_offset = get_position(f);
1639                 meta_size = read_int32(f);
1640                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
1641                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
1642                 ilst_offset = get_position(f);
1643                 ilst_size = read_int32(f);
1644
1645                 if (!create_ilst(&f->tags, &new_ilst_buffer, &new_ilst_size))
1646                         return 0;
1647
1648                 size_delta = new_ilst_size - (ilst_size - 8);
1649
1650                 *out_size = total_size + size_delta;
1651                 *out_buffer = para_malloc(*out_size);
1652                 p_out = (uint8_t *) * out_buffer;
1653
1654                 set_position(f, total_base);
1655                 read_data(f, p_out,
1656                                 (uint32_t) (udta_offset - total_base));
1657                 p_out += (uint32_t) (udta_offset - total_base);
1658                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
1659                 p_out += 4;
1660                 read_data(f, p_out, 4);
1661                 p_out += 4;
1662                 read_data(f, p_out,
1663                                 (uint32_t) (meta_offset - udta_offset - 8));
1664                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
1665                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
1666                 p_out += 4;
1667                 read_data(f, p_out, 4);
1668                 p_out += 4;
1669                 read_data(f, p_out,
1670                                 (uint32_t) (ilst_offset - meta_offset - 8));
1671                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
1672                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
1673                 p_out += 4;
1674                 read_data(f, p_out, 4);
1675                 p_out += 4;
1676
1677                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
1678                 p_out += new_ilst_size;
1679
1680                 set_position(f, ilst_offset + ilst_size);
1681                 read_data(f, p_out, (uint32_t) (total_size
1682                         - (ilst_offset - total_base) - ilst_size));
1683
1684                 free(new_ilst_buffer);
1685         }
1686         return 1;
1687 }
1688
1689 static int32_t write_data(struct mp4 *f, void *data, uint32_t size)
1690 {
1691         int32_t result = 1;
1692
1693         result = f->cb->write(f->cb->user_data, data, size);
1694
1695         f->current_position += size;
1696
1697         return result;
1698 }
1699
1700 static int32_t write_int32(struct mp4 *f, uint32_t data)
1701 {
1702         int8_t temp[4];
1703         write_u32_be(temp, data);
1704         return write_data(f, temp, sizeof(temp));
1705 }
1706
1707 int32_t mp4_meta_update(struct mp4 *f)
1708 {
1709         void *new_moov_data;
1710         uint32_t new_moov_size;
1711
1712         set_position(f, 0);
1713         if (!modify_moov(f, &new_moov_data, &new_moov_size)) {
1714                 mp4_close(f);
1715                 return 0;
1716         }
1717         /* copy moov atom to end of the file */
1718         if (f->last_atom != ATOM_MOOV) {
1719                 char *free_data = "free";
1720
1721                 /* rename old moov to free */
1722                 set_position(f, f->moov_offset + 4);
1723                 write_data(f, free_data, 4);
1724
1725                 set_position(f, f->file_size);
1726                 write_int32(f, new_moov_size + 8);
1727                 write_data(f, "moov", 4);
1728                 write_data(f, new_moov_data, new_moov_size);
1729         } else {
1730                 set_position(f, f->moov_offset);
1731                 write_int32(f, new_moov_size + 8);
1732                 write_data(f, "moov", 4);
1733                 write_data(f, new_moov_data, new_moov_size);
1734         }
1735         free(new_moov_data);
1736         f->cb->truncate(f->cb->user_data);
1737         return 1;
1738 }
1739
1740 static char *meta_find_by_name(const struct mp4 *f, const char *item)
1741 {
1742         uint32_t i;
1743
1744         for (i = 0; i < f->tags.count; i++)
1745                 if (!strcasecmp(f->tags.tags[i].item, item))
1746                         return para_strdup(f->tags.tags[i].value);
1747         return NULL;
1748 }
1749
1750 /**
1751  * Return the value of the artist meta tag of an mp4 file.
1752  *
1753  * \param f Must not be NULL.
1754  *
1755  * \return If the file does not contain this metadata tag, the function returns
1756  * NULL. Otherwise, a copy of the tag value is returned. The caller should free
1757  * this memory when it is no longer needed.
1758  */
1759 char *mp4_meta_get_artist(const struct mp4 *f)
1760 {
1761         return meta_find_by_name(f, "artist");
1762 }
1763
1764 /**
1765  * Return the value of the title meta tag of an mp4 file.
1766  *
1767  * \param f See \ref mp4_meta_get_artist().
1768  * \return See \ref mp4_meta_get_artist().
1769  */
1770 char *mp4_meta_get_title(const struct mp4 *f)
1771 {
1772         return meta_find_by_name(f, "title");
1773 }
1774
1775 /**
1776  * Return the value of the date meta tag of an mp4 file.
1777  *
1778  * \param f See \ref mp4_meta_get_artist().
1779  * \return See \ref mp4_meta_get_artist().
1780  */
1781 char *mp4_meta_get_date(const struct mp4 *f)
1782 {
1783         return meta_find_by_name(f, "date");
1784 }
1785
1786 /**
1787  * Return the value of the album meta tag of an mp4 file.
1788  *
1789  * \param f See \ref mp4_meta_get_artist().
1790  * \return See \ref mp4_meta_get_artist().
1791  */
1792 char *mp4_meta_get_album(const struct mp4 *f)
1793 {
1794         return meta_find_by_name(f, "album");
1795 }
1796
1797 /**
1798  * Return the value of the comment meta tag of an mp4 file.
1799  *
1800  * \param f See \ref mp4_meta_get_artist().
1801  * \return See \ref mp4_meta_get_artist().
1802  */
1803 char *mp4_meta_get_comment(const struct mp4 *f)
1804 {
1805         return meta_find_by_name(f, "comment");
1806 }