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