]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
mp4: Open-code pointless truncate_stream().
[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         /* stream to read from */
48         struct mp4_callback *stream;
49         int64_t current_position;
50
51         uint64_t moov_offset;
52         uint64_t moov_size;
53         uint8_t last_atom;
54         uint64_t file_size;
55         uint32_t error;
56
57         /* incremental track index while reading the file */
58         int32_t total_tracks;
59
60         /* track data */
61         struct mp4_track *track[MAX_TRACKS];
62
63         /* metadata */
64         struct mp4_metadata tags;
65 };
66
67 int32_t mp4_total_tracks(const struct mp4 *f)
68 {
69         return f->total_tracks;
70 }
71
72 static int32_t read_data(struct mp4 *f, void *data, uint32_t size)
73 {
74         int32_t result = 1;
75
76         result = f->stream->read(f->stream->user_data, data, size);
77
78         if (result < size)
79                 f->stream->read_error++;
80
81         f->current_position += size;
82
83         return result;
84 }
85
86 static uint64_t read_int64(struct mp4 *f)
87 {
88         uint8_t data[8];
89
90         read_data(f, data, 8);
91         return read_u64_be(data);
92 }
93
94 static bool atom_compare(int8_t a1, int8_t b1, int8_t c1, int8_t d1,
95                 int8_t a2, int8_t b2, int8_t c2, int8_t d2)
96 {
97         return a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2;
98 }
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->stream->seek(f->stream->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->stream->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->stream->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->stream->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->stream->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->stream->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         if (!item || (item && !*item) || !value)
603                 return 0;
604         tags->tags = para_realloc(tags->tags,
605                 (tags->count + 1) * sizeof(struct mp4_tag));
606         tags->tags[tags->count].item = para_strdup(item);
607         tags->tags[tags->count].len = len;
608         if (len >= 0) {
609                 tags->tags[tags->count].value = para_malloc(len + 1);
610                 memcpy(tags->tags[tags->count].value, value, len);
611                 tags->tags[tags->count].value[len] = 0;
612         } else {
613                 tags->tags[tags->count].value = para_strdup(value);
614         }
615         tags->count++;
616         return 1;
617 }
618
619 static const char *ID3v1GenreList[] = {
620         "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
621         "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
622         "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
623         "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
624         "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal",
625         "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid",
626         "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
627         "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
628         "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
629         "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
630         "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40",
631         "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
632         "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
633         "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
634         "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk",
635         "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic",
636         "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock",
637         "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
638         "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
639         "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
640         "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
641         "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
642         "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
643         "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
644         "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
645         "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover",
646         "Contemporary C", "Christian Rock", "Merengue", "Salsa", "Thrash Metal",
647         "Anime", "JPop", "SynthPop",
648 };
649
650 static const char *meta_index_to_genre(uint32_t idx)
651 {
652         if (idx > 0 && idx <= sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0])) {
653                 return ID3v1GenreList[idx - 1];
654         } else {
655                 return 0;
656         }
657 }
658
659 static char *read_string(struct mp4 *f, uint32_t length)
660 {
661         char *str = para_malloc(length + 1);
662         if ((uint32_t)read_data(f, str, length) != length) {
663                 free(str);
664                 str = NULL;
665         } else
666                 str[length] = 0;
667         return str;
668 }
669
670 static int32_t set_metadata_name(uint8_t atom_type, char **name)
671 {
672         static char *tag_names[] = {
673                 "unknown", "title", "artist", "writer", "album",
674                 "date", "tool", "comment", "genre", "track",
675                 "disc", "compilation", "genre", "tempo", "cover",
676                 "album_artist", "contentgroup", "lyrics", "description",
677                 "network", "show", "episodename",
678                 "sorttitle", "sortalbum", "sortartist", "sortalbumartist",
679                 "sortwriter", "sortshow",
680                 "season", "episode", "podcast"
681         };
682         uint8_t tag_idx = 0;
683
684         switch (atom_type) {
685         case ATOM_TITLE:
686                 tag_idx = 1;
687                 break;
688         case ATOM_ARTIST:
689                 tag_idx = 2;
690                 break;
691         case ATOM_WRITER:
692                 tag_idx = 3;
693                 break;
694         case ATOM_ALBUM:
695                 tag_idx = 4;
696                 break;
697         case ATOM_DATE:
698                 tag_idx = 5;
699                 break;
700         case ATOM_TOOL:
701                 tag_idx = 6;
702                 break;
703         case ATOM_COMMENT:
704                 tag_idx = 7;
705                 break;
706         case ATOM_GENRE1:
707                 tag_idx = 8;
708                 break;
709         case ATOM_TRACK:
710                 tag_idx = 9;
711                 break;
712         case ATOM_DISC:
713                 tag_idx = 10;
714                 break;
715         case ATOM_COMPILATION:
716                 tag_idx = 11;
717                 break;
718         case ATOM_GENRE2:
719                 tag_idx = 12;
720                 break;
721         case ATOM_TEMPO:
722                 tag_idx = 13;
723                 break;
724         case ATOM_COVER:
725                 tag_idx = 14;
726                 break;
727         case ATOM_ALBUM_ARTIST:
728                 tag_idx = 15;
729                 break;
730         case ATOM_CONTENTGROUP:
731                 tag_idx = 16;
732                 break;
733         case ATOM_LYRICS:
734                 tag_idx = 17;
735                 break;
736         case ATOM_DESCRIPTION:
737                 tag_idx = 18;
738                 break;
739         case ATOM_NETWORK:
740                 tag_idx = 19;
741                 break;
742         case ATOM_SHOW:
743                 tag_idx = 20;
744                 break;
745         case ATOM_EPISODENAME:
746                 tag_idx = 21;
747                 break;
748         case ATOM_SORTTITLE:
749                 tag_idx = 22;
750                 break;
751         case ATOM_SORTALBUM:
752                 tag_idx = 23;
753                 break;
754         case ATOM_SORTARTIST:
755                 tag_idx = 24;
756                 break;
757         case ATOM_SORTALBUMARTIST:
758                 tag_idx = 25;
759                 break;
760         case ATOM_SORTWRITER:
761                 tag_idx = 26;
762                 break;
763         case ATOM_SORTSHOW:
764                 tag_idx = 27;
765                 break;
766         case ATOM_SEASON:
767                 tag_idx = 28;
768                 break;
769         case ATOM_EPISODE:
770                 tag_idx = 29;
771                 break;
772         case ATOM_PODCAST:
773                 tag_idx = 30;
774                 break;
775         default:
776                 tag_idx = 0;
777                 break;
778         }
779
780         *name = para_strdup(tag_names[tag_idx]);
781         return 0;
782 }
783
784 static uint32_t min_body_size(uint8_t atom_type)
785 {
786         switch(atom_type) {
787         case ATOM_GENRE2:
788         case ATOM_TEMPO:
789                 return 10;
790         case ATOM_TRACK:
791                 return sizeof (char) /* version */
792                         + sizeof(uint8_t) * 3 /* flags */
793                         + sizeof(uint32_t) /* reserved */
794                         + sizeof(uint16_t) /* leading uint16_t */
795                         + sizeof(uint16_t) /* track */
796                         + sizeof(uint16_t); /* totaltracks */
797         case ATOM_DISC:
798                 return sizeof (char) /* version */
799                         + sizeof(uint8_t) * 3 /* flags */
800                         + sizeof(uint32_t) /* reserved */
801                         + sizeof(uint16_t) /* disc */
802                         + sizeof(uint16_t); /* totaldiscs */
803         default: assert(false);
804         }
805 }
806
807 static int32_t parse_tag(struct mp4 *f, uint8_t parent, int32_t size)
808 {
809         uint8_t atom_type;
810         uint8_t header_size = 0;
811         uint64_t subsize, sumsize;
812         char *name = NULL;
813         char *data = NULL;
814         uint32_t done = 0;
815         uint32_t len = 0;
816         uint64_t destpos;
817
818         for (
819                 sumsize = 0;
820                 sumsize < size && !f->stream->read_error; /* CVE-2017-9222 */
821                 set_position(f, destpos), sumsize += subsize
822         ) {
823                 subsize = atom_read_header(f, &atom_type, &header_size);
824                 destpos = get_position(f) + subsize - header_size;
825                 if (done)
826                         continue;
827                 if (atom_type == ATOM_NAME) {
828                         read_char(f);   /* version */
829                         read_int24(f);  /* flags */
830                         free(name);
831                         name = read_string(f, subsize - (header_size + 4));
832                         continue;
833                 }
834                 if (atom_type != ATOM_DATA)
835                         continue;
836                 read_char(f);   /* version */
837                 read_int24(f);  /* flags */
838                 read_int32(f);  /* reserved */
839
840                 /* some need special attention */
841                 if (parent == ATOM_GENRE2 || parent == ATOM_TEMPO) {
842                         uint16_t val;
843                         if (subsize - header_size < min_body_size(parent))
844                                 continue;
845                         val = read_int16(f);
846                         if (parent == ATOM_TEMPO) {
847                                 char temp[16];
848                                 sprintf(temp, "%.5u BPM", val);
849                                 tag_add_field(&(f-> tags), "tempo",
850                                         temp, -1);
851                         } else {
852                                 const char *tmp = meta_index_to_genre(val);
853                                 if (tmp)
854                                         tag_add_field (&(f->tags),
855                                                 "genre", tmp, -1);
856                         }
857                         done = 1;
858                 } else if (parent == ATOM_TRACK || parent == ATOM_DISC) {
859                         uint16_t index, total;
860                         char temp[32];
861                         if (subsize - header_size < min_body_size(parent))
862                                 continue;
863                         read_int16(f);
864                         index = read_int16(f);
865                         total = read_int16(f);
866                         if (parent == ATOM_TRACK)
867                                 read_int16(f);
868                         sprintf(temp, "%d", index);
869                         tag_add_field(&(f->tags), parent == ATOM_TRACK?
870                                 "track" : "disc", temp, -1);
871                         if (total > 0) {
872                                 sprintf(temp, "%d", total);
873                                 tag_add_field(& (f-> tags),
874                                         parent == ATOM_TRACK?
875                                         "totaltracks" : "totaldiscs", temp, -1);
876                         }
877                         done = 1;
878                 } else {
879                         free(data);
880                         data = read_string(f, subsize - (header_size + 8));
881                         len = subsize - (header_size + 8);
882                 }
883         }
884         if (data) {
885                 if (!done) {
886                         if (name == NULL)
887                                 set_metadata_name(parent , &name);
888                         if (name)
889                                 tag_add_field(&(f->tags), name, data, len);
890                 }
891
892                 free(data);
893         }
894         free(name);
895         return 1;
896 }
897
898 static int32_t read_mdhd(struct mp4 *f)
899 {
900         uint32_t version;
901         struct mp4_track *t;
902
903         /* CVE-2017-9221 */
904         if (f->total_tracks == 0)
905                 return f->error++;
906         t = f->track[f->total_tracks - 1];
907
908         version = read_int32(f);
909         if (version == 1) {
910                 read_int64(f); //creation-time
911                 read_int64(f); //modification-time
912                 t->timeScale = read_int32(f); //timescale
913                 t->duration = read_int64(f); //duration
914         } else { //version == 0
915                 uint32_t temp;
916
917                 read_int32(f);  //creation-time
918                 read_int32(f);  //modification-time
919                 t->timeScale = read_int32(f); //timescale
920                 temp = read_int32(f);
921                 t->duration = (temp == (uint32_t) (-1))?
922                         (uint64_t) (-1) : (uint64_t) (temp);
923         }
924         read_int16(f);
925         read_int16(f);
926         return 1;
927 }
928
929 static int32_t parse_metadata(struct mp4 *f, int32_t size)
930 {
931         uint64_t subsize, sumsize = 0;
932         uint8_t atom_type;
933         uint8_t header_size = 0;
934
935         while (sumsize < size) {
936                 subsize = atom_read_header(f, &atom_type, &header_size);
937                 if (subsize == 0)
938                         break;
939                 parse_tag(f, atom_type, (uint32_t)(subsize - header_size));
940                 sumsize += subsize;
941         }
942
943         return 0;
944 }
945
946 static int32_t read_meta(struct mp4 *f, uint64_t size)
947 {
948         uint64_t subsize, sumsize = 0;
949         uint8_t atom_type;
950         uint8_t header_size = 0;
951
952         read_char(f);   /* version */
953         read_int24(f);  /* flags */
954
955         while (sumsize < (size - (header_size + 4))) {
956                 subsize = atom_read_header(f, &atom_type, &header_size);
957                 if (subsize <= header_size + 4)
958                         return 1;
959                 if (atom_type == ATOM_ILST) {
960                         parse_metadata(f, (uint32_t) (subsize - (header_size + 4)));
961                 } else {
962                         set_position(f, get_position(f) + subsize - header_size);
963                 }
964                 sumsize += subsize;
965         }
966
967         return 0;
968 }
969
970 static int32_t atom_read(struct mp4 *f, int32_t size, uint8_t atom_type)
971 {
972         uint64_t dest_position = get_position(f) + size - 8;
973         if (atom_type == ATOM_STSZ) {
974                 /* sample size box */
975                 read_stsz(f);
976         } else if (atom_type == ATOM_STTS) {
977                 /* time to sample box */
978                 read_stts(f);
979         } else if (atom_type == ATOM_STSC) {
980                 /* sample to chunk box */
981                 read_stsc(f);
982         } else if (atom_type == ATOM_STCO) {
983                 /* chunk offset box */
984                 read_stco(f);
985         } else if (atom_type == ATOM_STSD) {
986                 /* sample description box */
987                 read_stsd(f);
988         } else if (atom_type == ATOM_MDHD) {
989                 /* track header */
990                 read_mdhd(f);
991         } else if (atom_type == ATOM_META) {
992                 /* iTunes Metadata box */
993                 read_meta(f, size);
994         }
995
996         set_position(f, dest_position);
997         return 0;
998 }
999
1000 /* parse atoms that are sub atoms of other atoms */
1001 static int32_t parse_sub_atoms(struct mp4 *f, uint64_t total_size, int meta_only)
1002 {
1003         uint64_t size;
1004         uint8_t atom_type = 0;
1005         uint64_t counted_size = 0;
1006         uint8_t header_size = 0;
1007
1008         while (counted_size < total_size) {
1009                 size = atom_read_header(f, &atom_type, &header_size);
1010                 counted_size += size;
1011
1012                 /* check for end of file */
1013                 if (size == 0)
1014                         break;
1015
1016                 /* we're starting to read a new track, update index,
1017                  * so that all data and tables get written in the right place
1018                  */
1019                 if (atom_type == ATOM_TRAK)
1020                         track_add(f);
1021                 /* parse subatoms */
1022                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1023                         set_position(f, get_position(f) + size - header_size);
1024                 } else if (atom_type < SUBATOMIC) {
1025                         parse_sub_atoms(f, size - header_size, meta_only);
1026                 } else {
1027                         atom_read(f, (uint32_t) size, atom_type);
1028                 }
1029         }
1030
1031         return 0;
1032 }
1033
1034 /* parse root atoms */
1035 static int32_t parse_atoms(struct mp4 *f, int meta_only)
1036 {
1037         uint64_t size;
1038         uint8_t atom_type = 0;
1039         uint8_t header_size = 0;
1040
1041         f->file_size = 0;
1042         f->stream->read_error = 0;
1043
1044         while ((size =
1045                 atom_read_header(f, &atom_type, &header_size)) != 0) {
1046                 f->file_size += size;
1047                 f->last_atom = atom_type;
1048
1049                 if (atom_type == ATOM_MOOV && size > header_size) {
1050                         f->moov_offset = get_position(f) - header_size;
1051                         f->moov_size = size;
1052                 }
1053
1054                 /* parse subatoms */
1055                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1056                         set_position(f, get_position(f) + size - header_size);
1057                 } else if (atom_type < SUBATOMIC) {
1058                         parse_sub_atoms(f, size - header_size, meta_only);
1059                 } else {
1060                         /* skip this atom */
1061                         set_position(f, get_position(f) + size - header_size);
1062                 }
1063         }
1064
1065         return 0;
1066 }
1067
1068 struct mp4 *mp4_open_read(struct mp4_callback *f)
1069 {
1070         struct mp4 *ff = para_calloc(sizeof(struct mp4));
1071
1072         ff->stream = f;
1073
1074         parse_atoms(ff, 0);
1075
1076         if (ff->error) {
1077                 free(ff);
1078                 ff = NULL;
1079         }
1080
1081         return ff;
1082 }
1083
1084 static int32_t tag_delete(struct mp4_metadata *tags)
1085 {
1086         uint32_t i;
1087
1088         for (i = 0; i < tags->count; i++) {
1089                 free(tags->tags[i].item);
1090                 free(tags->tags[i].value);
1091         }
1092         free(tags->tags);
1093         tags->tags = NULL;
1094         tags->count = 0;
1095
1096         return 0;
1097 }
1098
1099 void mp4_close(struct mp4 *ff)
1100 {
1101         int32_t i;
1102
1103         for (i = 0; i < ff->total_tracks; i++) {
1104                 if (ff->track[i]) {
1105                         free(ff->track[i]->stsz_table);
1106                         free(ff->track[i]->stts_sample_count);
1107                         free(ff->track[i]->stts_sample_delta);
1108                         free(ff->track[i]->stsc_first_chunk);
1109                         free(ff->track[i]->stsc_samples_per_chunk);
1110                         free(ff->track[i]->stsc_sample_desc_index);
1111                         free(ff->track[i]->stco_chunk_offset);
1112                         free(ff->track[i]);
1113                 }
1114         }
1115
1116         tag_delete(&(ff->tags));
1117         free(ff);
1118 }
1119
1120 static int32_t chunk_of_sample(const struct mp4 *f, int32_t track,
1121                 int32_t sample, int32_t *chunk_sample, int32_t *chunk)
1122 {
1123         int32_t total_entries = 0;
1124         int32_t chunk2entry;
1125         int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
1126
1127         *chunk_sample = 0;
1128         *chunk = 1;
1129         if (f->track[track] == NULL) {
1130                 return -1;
1131         }
1132
1133         total_entries = f->track[track]->stsc_entry_count;
1134
1135         chunk1 = 1;
1136         chunk1samples = 0;
1137         chunk2entry = 0;
1138
1139         do {
1140                 chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
1141                 *chunk = chunk2 - chunk1;
1142                 range_samples = *chunk * chunk1samples;
1143
1144                 if (sample < total + range_samples)
1145                         break;
1146
1147                 chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
1148                 chunk1 = chunk2;
1149
1150                 if (chunk2entry < total_entries) {
1151                         chunk2entry++;
1152                         total += range_samples;
1153                 }
1154         } while (chunk2entry < total_entries);
1155
1156         if (chunk1samples)
1157                 *chunk = (sample - total) / chunk1samples + chunk1;
1158         else
1159                 *chunk = 1;
1160
1161         *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
1162
1163         return 0;
1164 }
1165
1166 static int32_t chunk_to_offset(const struct mp4 *f, int32_t track,
1167                 int32_t chunk)
1168 {
1169         const struct mp4_track *p_track = f->track[track];
1170
1171         if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) {
1172                 return p_track->stco_chunk_offset[p_track->stco_entry_count -
1173                                                   1];
1174         } else if (p_track->stco_entry_count) {
1175                 return p_track->stco_chunk_offset[chunk - 1];
1176         } else {
1177                 return 8;
1178         }
1179
1180         return 0;
1181 }
1182
1183 static int32_t sample_range_size(const struct mp4 *f, int32_t track,
1184                 int32_t chunk_sample, int32_t sample)
1185 {
1186         int32_t i, total;
1187         const struct mp4_track *p_track = f->track[track];
1188
1189         if (p_track->stsz_sample_size) {
1190                 return (sample - chunk_sample) * p_track->stsz_sample_size;
1191         } else {
1192                 if (sample >= p_track->stsz_sample_count)
1193                         return 0;       //error
1194
1195                 for (i = chunk_sample, total = 0; i < sample; i++) {
1196                         total += p_track->stsz_table[i];
1197                 }
1198         }
1199
1200         return total;
1201 }
1202
1203 static int32_t sample_to_offset(const struct mp4 *f, int32_t track,
1204                 int32_t sample)
1205 {
1206         int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
1207
1208         chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
1209
1210         chunk_offset1 = chunk_to_offset(f, track, chunk);
1211         chunk_offset2 = chunk_offset1 + sample_range_size(f,
1212                 track, chunk_sample, sample);
1213         return chunk_offset2;
1214 }
1215
1216 /**
1217  * Return the number of milliseconds of the given track.
1218  *
1219  * \param f As returned by \ref mp4_open_read(), must not be NULL.
1220  * \param track Between zero and the value returned by \ref mp4_total_tracks().
1221  *
1222  * The function returns zero if the audio file is of zero length or contains a
1223  * corrupt track header.
1224  */
1225 uint64_t mp4_get_duration(const struct mp4 *f, int32_t track)
1226 {
1227         const struct mp4_track *t = f->track[track];
1228
1229         if (t->timeScale == 0)
1230                 return 0;
1231         return t->duration * 1000 / t->timeScale;
1232 }
1233
1234 /**
1235  * Check whether the given track number corresponds to an audio track.
1236  *
1237  * \param f See \ref mp4_get_duration().
1238  * \param track See \ref mp4_get_duration().
1239  *
1240  * Besides audio tracks, an mp4 file may contain video and system tracks. For
1241  * those the function returns false.
1242  */
1243 bool mp4_is_audio_track(const struct mp4 *f, int32_t track)
1244 {
1245         return f->track[track]->is_audio;
1246 }
1247
1248 void mp4_set_sample_position(struct mp4 *f, int32_t track, int32_t sample)
1249 {
1250         int32_t offset = sample_to_offset(f, track, sample);
1251         set_position(f, offset);
1252 }
1253
1254 int32_t mp4_get_sample_size(const struct mp4 *f, int track, int sample)
1255 {
1256         const struct mp4_track *t = f->track[track];
1257
1258         if (t->stsz_sample_size != 0)
1259                 return t->stsz_sample_size;
1260         return t->stsz_table[sample];
1261 }
1262
1263 uint32_t mp4_get_sample_rate(const struct mp4 *f, int32_t track)
1264 {
1265         return f->track[track]->sampleRate;
1266 }
1267
1268 uint32_t mp4_get_channel_count(const struct mp4 *f, int32_t track)
1269 {
1270         return f->track[track]->channelCount;
1271 }
1272
1273 int32_t mp4_num_samples(const struct mp4 *f, int32_t track)
1274 {
1275         int32_t i;
1276         int32_t total = 0;
1277
1278         for (i = 0; i < f->track[track]->stts_entry_count; i++) {
1279                 total += f->track[track]->stts_sample_count[i];
1280         }
1281         return total;
1282 }
1283
1284 struct mp4 *mp4_open_meta(struct mp4_callback *f)
1285 {
1286         struct mp4 *ff = para_calloc(sizeof(struct mp4));
1287
1288         ff->stream = f;
1289
1290         parse_atoms(ff, 1);
1291
1292         if (ff->error) {
1293                 free(ff);
1294                 ff = NULL;
1295         }
1296
1297         return ff;
1298 }
1299
1300 int32_t mp4_meta_get_num_items(const struct mp4 *f)
1301 {
1302         return f->tags.count;
1303 }
1304
1305 int32_t mp4_meta_get_by_index(const struct mp4 *f, uint32_t index,
1306                                 char **item, char **value)
1307 {
1308         if (index >= f->tags.count) {
1309                 *item = NULL;
1310                 *value = NULL;
1311                 return 0;
1312         } else {
1313                 *item = para_strdup(f->tags.tags[index].item);
1314                 *value = para_strdup(f->tags.tags[index].value);
1315                 return 1;
1316         }
1317 }
1318
1319 static uint32_t find_atom(struct mp4 *f, uint64_t base, uint32_t size,
1320                           const char *name)
1321 {
1322         uint32_t remaining = size;
1323         uint64_t atom_offset = base;
1324         for (;;) {
1325                 char atom_name[4];
1326                 uint32_t atom_size;
1327
1328                 set_position(f, atom_offset);
1329
1330                 if (remaining < 8)
1331                         break;
1332                 atom_size = read_int32(f);
1333                 if (atom_size > remaining || atom_size < 8)
1334                         break;
1335                 read_data(f, atom_name, 4);
1336
1337                 if (!memcmp(atom_name, name, 4)) {
1338                         set_position(f, atom_offset);
1339                         return 1;
1340                 }
1341
1342                 remaining -= atom_size;
1343                 atom_offset += atom_size;
1344         }
1345         return 0;
1346 }
1347
1348 static uint32_t find_atom_v2(struct mp4 *f, uint64_t base, uint32_t size,
1349                 const char *name, uint32_t extraheaders, const char *name_inside)
1350 {
1351         uint64_t first_base = (uint64_t) (-1);
1352         while (find_atom(f, base, size, name))  //try to find atom <name> with atom <name_inside> in it
1353         {
1354                 uint64_t mybase = get_position(f);
1355                 uint32_t mysize = read_int32(f);
1356
1357                 if (first_base == (uint64_t) (-1))
1358                         first_base = mybase;
1359
1360                 if (mysize < 8 + extraheaders)
1361                         break;
1362
1363                 if (find_atom (f, mybase + (8 + extraheaders),
1364                                 mysize - (8 + extraheaders), name_inside)) {
1365                         set_position(f, mybase);
1366                         return 2;
1367                 }
1368                 base += mysize;
1369                 if (size <= mysize) {
1370                         size = 0;
1371                         break;
1372                 }
1373                 size -= mysize;
1374         }
1375
1376         if (first_base != (uint64_t) (-1))      //wanted atom inside not found
1377         {
1378                 set_position(f, first_base);
1379                 return 1;
1380         } else
1381                 return 0;
1382 }
1383
1384 struct membuffer {
1385         void *data;
1386         unsigned written;
1387         unsigned allocated;
1388         unsigned error;
1389 };
1390
1391 static struct membuffer *membuffer_create(void)
1392 {
1393         const unsigned initial_size = 256;
1394
1395         struct membuffer *buf = para_malloc(sizeof(*buf));
1396         buf->data = para_malloc(initial_size);
1397         buf->written = 0;
1398         buf->allocated = initial_size;
1399         buf->error = buf->data == 0 ? 1 : 0;
1400
1401         return buf;
1402 }
1403
1404 static unsigned membuffer_write(struct membuffer *buf, const void *ptr, unsigned bytes)
1405 {
1406         unsigned dest_size = buf->written + bytes;
1407
1408         if (buf->error)
1409                 return 0;
1410         if (dest_size > buf->allocated) {
1411                 do {
1412                         buf->allocated <<= 1;
1413                 } while (dest_size > buf->allocated);
1414                 buf->data = para_realloc(buf->data, buf->allocated);
1415         }
1416
1417         if (ptr)
1418                 memcpy((char *) buf->data + buf->written, ptr, bytes);
1419         buf->written += bytes;
1420         return bytes;
1421 }
1422
1423 static unsigned membuffer_write_atom_name(struct membuffer *buf, const char *data)
1424 {
1425         return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
1426 }
1427
1428 static unsigned membuffer_write_int16(struct membuffer *buf, uint16_t data)
1429 {
1430         uint8_t temp[2];
1431
1432         write_u16_be(temp, data);
1433         return membuffer_write(buf, temp, 2);
1434 }
1435
1436 static unsigned membuffer_write_int32(struct membuffer *buf, uint32_t data)
1437 {
1438         uint8_t temp[4];
1439         write_u32_be(temp, data);
1440         return membuffer_write(buf, temp, 4);
1441 }
1442
1443 static void membuffer_write_track_tag(struct membuffer *buf, const char *name,
1444                 uint32_t index, uint32_t total)
1445 {
1446         membuffer_write_int32(buf,
1447                 8 /*atom header */  + 8 /*data atom header */  +
1448                 8 /*flags + reserved */  + 8 /*actual data */ );
1449         membuffer_write_atom_name(buf, name);
1450         membuffer_write_int32(buf,
1451                 8 /*data atom header */  +
1452                 8 /*flags + reserved */  + 8 /*actual data */ );
1453         membuffer_write_atom_name(buf, "data");
1454         membuffer_write_int32(buf, 0);  //flags
1455         membuffer_write_int32(buf, 0);  //reserved
1456         membuffer_write_int16(buf, 0);
1457         membuffer_write_int16(buf, (uint16_t) index);   //track number
1458         membuffer_write_int16(buf, (uint16_t) total);   //total tracks
1459         membuffer_write_int16(buf, 0);
1460 }
1461
1462 static void membuffer_write_int16_tag(struct membuffer *buf, const char *name,
1463                 uint16_t value)
1464 {
1465         membuffer_write_int32(buf,
1466                 8 /*atom header */  + 8 /*data atom header */  +
1467                 8 /*flags + reserved */  + 2 /*actual data */ );
1468         membuffer_write_atom_name(buf, name);
1469         membuffer_write_int32(buf,
1470                 8 /*data atom header */  +
1471                 8 /*flags + reserved */  + 2 /*actual data */ );
1472         membuffer_write_atom_name(buf, "data");
1473         membuffer_write_int32(buf, 0);  //flags
1474         membuffer_write_int32(buf, 0);  //reserved
1475         membuffer_write_int16(buf, value);      //value
1476 }
1477
1478 static uint32_t myatoi(const char *param)
1479 {
1480         return param ? atoi(param) : 0;
1481 }
1482
1483 static uint32_t meta_genre_to_index(const char *genrestr)
1484 {
1485         unsigned n;
1486         for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
1487                 if (!strcasecmp(genrestr, ID3v1GenreList[n]))
1488                         return n + 1;
1489         }
1490         return 0;
1491 }
1492
1493 struct stdmeta_entry {
1494         const char *atom;
1495         const char *name;
1496 };
1497
1498 struct stdmeta_entry stdmetas[] = {
1499         {"\xA9" "nam", "title"},
1500         {"\xA9" "ART", "artist"},
1501         {"\xA9" "wrt", "writer"},
1502         {"\xA9" "alb", "album"},
1503         {"\xA9" "day", "date"},
1504         {"\xA9" "too", "tool"},
1505         {"\xA9" "cmt", "comment"},
1506         {"cpil", "compilation"},
1507         {"covr", "cover"},
1508         {"aART", "album_artist"},
1509 };
1510
1511 static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
1512 {
1513         unsigned n;
1514         for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
1515                 if (!strcasecmp(name, stdmetas[n].name))
1516                         return stdmetas[n].atom;
1517         }
1518         return 0;
1519 }
1520
1521 static void membuffer_write_std_tag(struct membuffer *buf, const char *name,
1522                 const char *value)
1523 {
1524         uint32_t flags = 1;
1525
1526         /* special check for compilation flag */
1527         if (strcmp(name, "cpil") == 0) {
1528                 flags = 21;
1529         }
1530
1531         membuffer_write_int32(buf,
1532                 8 /*atom header */  + 8 /*data atom header */  +
1533                 8 /*flags + reserved */  + strlen(value));
1534         membuffer_write_atom_name(buf, name);
1535         membuffer_write_int32(buf,
1536                 8 /*data atom header */  +
1537                 8 /*flags + reserved */  + strlen(value));
1538         membuffer_write_atom_name(buf, "data");
1539         membuffer_write_int32(buf, flags);      //flags
1540         membuffer_write_int32(buf, 0);  //reserved
1541         membuffer_write(buf, value, strlen(value));
1542 }
1543
1544 static void membuffer_write_custom_tag(struct membuffer *buf, const char *name,
1545                 const char *value)
1546 {
1547         membuffer_write_int32(buf,
1548                 8 /*atom header */  +
1549                 0x1C /*weirdo itunes atom */  +
1550                 12 /*name atom header */  + strlen(name) +
1551                 16 /*data atom header + flags */  + strlen(value));
1552         membuffer_write_atom_name(buf, "----");
1553         membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
1554         membuffer_write_atom_name(buf, "mean");
1555         membuffer_write_int32(buf, 0);
1556         membuffer_write(buf, "com.apple.iTunes", 16);
1557         membuffer_write_int32(buf, 12 + strlen(name));
1558         membuffer_write_atom_name(buf, "name");
1559         membuffer_write_int32(buf, 0);
1560         membuffer_write(buf, name, strlen(name));
1561         membuffer_write_int32(buf,
1562                 8 /*data atom header */  +
1563                 8 /*flags + reserved */  + strlen(value));
1564         membuffer_write_atom_name(buf, "data");
1565         membuffer_write_int32(buf, 1);  //flags
1566         membuffer_write_int32(buf, 0);  //reserved
1567         membuffer_write(buf, value, strlen(value));
1568 }
1569
1570 static unsigned membuffer_error(const struct membuffer *buf)
1571 {
1572         return buf->error;
1573 }
1574
1575 static void membuffer_free(struct membuffer *buf)
1576 {
1577         free(buf->data);
1578         free(buf);
1579 }
1580
1581 static unsigned membuffer_get_size(const struct membuffer *buf)
1582 {
1583         return buf->written;
1584 }
1585
1586 static void *membuffer_detach(struct membuffer *buf)
1587 {
1588         void *ret;
1589
1590         if (buf->error)
1591                 return 0;
1592         ret = para_realloc(buf->data, buf->written);
1593         buf->data = 0;
1594         buf->error = 1;
1595         return ret;
1596 }
1597
1598 static uint32_t create_ilst(const struct mp4_metadata *data, void **out_buffer,
1599                 uint32_t * out_size)
1600 {
1601         struct membuffer *buf = membuffer_create();
1602         unsigned metaptr;
1603         char *mask = para_calloc(data->count);
1604         const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1605         const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1606         const char *genre_ptr = 0, *tempo_ptr = 0;
1607
1608         for (metaptr = 0; metaptr < data->count; metaptr++) {
1609                 struct mp4_tag *tag = &data->tags[metaptr];
1610                 if (!strcasecmp(tag->item, "tracknumber")
1611                                 || !strcasecmp(tag->item, "track")) {
1612                         if (tracknumber_ptr == 0)
1613                                 tracknumber_ptr = tag->value;
1614                         mask[metaptr] = 1;
1615                 } else if (!strcasecmp(tag->item, "totaltracks")) {
1616                         if (totaltracks_ptr == 0)
1617                                 totaltracks_ptr = tag->value;
1618                         mask[metaptr] = 1;
1619                 } else if (!strcasecmp(tag->item, "discnumber")
1620                                 || !strcasecmp(tag->item, "disc")) {
1621                         if (discnumber_ptr == 0)
1622                                 discnumber_ptr = tag->value;
1623                         mask[metaptr] = 1;
1624                 } else if (!strcasecmp(tag->item, "totaldiscs")) {
1625                         if (totaldiscs_ptr == 0)
1626                                 totaldiscs_ptr = tag->value;
1627                         mask[metaptr] = 1;
1628                 } else if (!strcasecmp(tag->item, "genre")) {
1629                         if (genre_ptr == 0)
1630                                 genre_ptr = tag->value;
1631                         mask[metaptr] = 1;
1632                 } else if (!strcasecmp(tag->item, "tempo")) {
1633                         if (tempo_ptr == 0)
1634                                 tempo_ptr = tag->value;
1635                         mask[metaptr] = 1;
1636                 }
1637         }
1638
1639         if (tracknumber_ptr)
1640                 membuffer_write_track_tag(buf, "trkn", myatoi(tracknumber_ptr),
1641                          myatoi(totaltracks_ptr));
1642         if (discnumber_ptr)
1643                 membuffer_write_track_tag(buf, "disk", myatoi(discnumber_ptr),
1644                          myatoi(totaldiscs_ptr));
1645         if (tempo_ptr)
1646                 membuffer_write_int16_tag(buf, "tmpo", myatoi(tempo_ptr));
1647
1648         if (genre_ptr) {
1649                 uint32_t index = meta_genre_to_index(genre_ptr);
1650                 if (index == 0)
1651                         membuffer_write_std_tag(buf, "©gen", genre_ptr);
1652                 else
1653                         membuffer_write_int16_tag(buf, "gnre", index);
1654         }
1655         for (metaptr = 0; metaptr < data->count; metaptr++) {
1656                 struct mp4_tag *tag;
1657                 const char *std_meta_atom;
1658
1659                 if (mask[metaptr])
1660                         continue;
1661                 tag = &data->tags[metaptr];
1662                 std_meta_atom = find_standard_meta(tag->item);
1663                 if (std_meta_atom)
1664                         membuffer_write_std_tag(buf, std_meta_atom, tag->value);
1665                 else
1666                         membuffer_write_custom_tag(buf, tag->item, tag->value);
1667         }
1668         free(mask);
1669
1670         if (membuffer_error(buf)) {
1671                 membuffer_free(buf);
1672                 return 0;
1673         }
1674
1675         *out_size = membuffer_get_size(buf);
1676         *out_buffer = membuffer_detach(buf);
1677         membuffer_free(buf);
1678
1679         return 1;
1680 }
1681
1682 static void membuffer_write_atom(struct membuffer *buf, const char *name, unsigned size,
1683                           const void *data)
1684 {
1685         membuffer_write_int32(buf, size + 8);
1686         membuffer_write_atom_name(buf, name);
1687         membuffer_write(buf, data, size);
1688 }
1689
1690 static void *membuffer_get_ptr(const struct membuffer *buf)
1691 {
1692         return buf->data;
1693 }
1694
1695 static void membuffer_set_error(struct membuffer *buf)
1696 {
1697         buf->error = 1;
1698 }
1699
1700 static unsigned membuffer_transfer_from_file(struct membuffer *buf, struct mp4 *src,
1701                 unsigned bytes)
1702 {
1703         unsigned oldsize;
1704         void *bufptr;
1705
1706         oldsize = membuffer_get_size(buf);
1707         if (membuffer_write(buf, 0, bytes) != bytes)
1708                 return 0;
1709
1710         bufptr = membuffer_get_ptr(buf);
1711         if (bufptr == 0)
1712                 return 0;
1713
1714         if ((unsigned)read_data(src, (char *) bufptr + oldsize, bytes) !=
1715                 bytes) {
1716                 membuffer_set_error(buf);
1717                 return 0;
1718         }
1719
1720         return bytes;
1721 }
1722
1723 static uint32_t create_meta(const struct mp4_metadata *data, void **out_buffer,
1724                 uint32_t * out_size)
1725 {
1726         struct membuffer *buf;
1727         uint32_t ilst_size;
1728         void *ilst_buffer;
1729
1730         if (!create_ilst(data, &ilst_buffer, &ilst_size))
1731                 return 0;
1732
1733         buf = membuffer_create();
1734
1735         membuffer_write_int32(buf, 0);
1736         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
1737         free(ilst_buffer);
1738
1739         *out_size = membuffer_get_size(buf);
1740         *out_buffer = membuffer_detach(buf);
1741         membuffer_free(buf);
1742         return 1;
1743 }
1744
1745 static uint32_t create_udta(const struct mp4_metadata *data, void **out_buffer,
1746 uint32_t * out_size)
1747 {
1748         struct membuffer *buf;
1749         uint32_t meta_size;
1750         void *meta_buffer;
1751
1752         if (!create_meta(data, &meta_buffer, &meta_size))
1753                 return 0;
1754
1755         buf = membuffer_create();
1756
1757         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
1758
1759         free(meta_buffer);
1760
1761         *out_size = membuffer_get_size(buf);
1762         *out_buffer = membuffer_detach(buf);
1763         membuffer_free(buf);
1764         return 1;
1765 }
1766
1767 static uint32_t fix_byte_order_32(uint32_t src)
1768 {
1769         return read_u32_be(&src);
1770 }
1771
1772 static uint32_t modify_moov(struct mp4 *f, const struct mp4_metadata *data,
1773                 void **out_buffer, uint32_t * out_size)
1774 {
1775         uint64_t total_base = f->moov_offset + 8;
1776         uint32_t total_size = (uint32_t) (f->moov_size - 8);
1777
1778         uint64_t udta_offset, meta_offset, ilst_offset;
1779         uint32_t udta_size, meta_size, ilst_size;
1780
1781         uint32_t new_ilst_size;
1782         void *new_ilst_buffer;
1783
1784         uint8_t *p_out;
1785         int32_t size_delta;
1786
1787         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
1788                 struct membuffer *buf;
1789                 void *new_udta_buffer;
1790                 uint32_t new_udta_size;
1791                 if (!create_udta(data, &new_udta_buffer, &new_udta_size))
1792                         return 0;
1793
1794                 buf = membuffer_create();
1795                 set_position(f, total_base);
1796                 membuffer_transfer_from_file(buf, f, total_size);
1797
1798                 membuffer_write_atom(buf, "udta", new_udta_size,
1799                         new_udta_buffer);
1800
1801                 free(new_udta_buffer);
1802
1803                 *out_size = membuffer_get_size(buf);
1804                 *out_buffer = membuffer_detach(buf);
1805                 membuffer_free(buf);
1806                 return 1;
1807         } else {
1808                 udta_offset = get_position(f);
1809                 udta_size = read_int32(f);
1810                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
1811                         struct membuffer *buf;
1812                         void *new_meta_buffer;
1813                         uint32_t new_meta_size;
1814                         if (!create_meta(data, &new_meta_buffer, &new_meta_size))
1815                                 return 0;
1816
1817                         buf = membuffer_create();
1818                         set_position(f, total_base);
1819                         membuffer_transfer_from_file(buf, f,
1820                                 (uint32_t)(udta_offset - total_base));
1821
1822                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
1823                         membuffer_write_atom_name(buf, "udta");
1824                         membuffer_transfer_from_file(buf, f, udta_size);
1825
1826                         membuffer_write_atom(buf, "meta", new_meta_size,
1827                                 new_meta_buffer);
1828                         free(new_meta_buffer);
1829
1830                         *out_size = membuffer_get_size(buf);
1831                         *out_buffer = membuffer_detach(buf);
1832                         membuffer_free(buf);
1833                         return 1;
1834                 }
1835                 meta_offset = get_position(f);
1836                 meta_size = read_int32(f);
1837                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
1838                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
1839                 ilst_offset = get_position(f);
1840                 ilst_size = read_int32(f);
1841
1842                 if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
1843                         return 0;
1844
1845                 size_delta = new_ilst_size - (ilst_size - 8);
1846
1847                 *out_size = total_size + size_delta;
1848                 *out_buffer = para_malloc(*out_size);
1849                 p_out = (uint8_t *) * out_buffer;
1850
1851                 set_position(f, total_base);
1852                 read_data(f, p_out,
1853                                 (uint32_t) (udta_offset - total_base));
1854                 p_out += (uint32_t) (udta_offset - total_base);
1855                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
1856                 p_out += 4;
1857                 read_data(f, p_out, 4);
1858                 p_out += 4;
1859                 read_data(f, p_out,
1860                                 (uint32_t) (meta_offset - udta_offset - 8));
1861                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
1862                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
1863                 p_out += 4;
1864                 read_data(f, p_out, 4);
1865                 p_out += 4;
1866                 read_data(f, p_out,
1867                                 (uint32_t) (ilst_offset - meta_offset - 8));
1868                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
1869                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
1870                 p_out += 4;
1871                 read_data(f, p_out, 4);
1872                 p_out += 4;
1873
1874                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
1875                 p_out += new_ilst_size;
1876
1877                 set_position(f, ilst_offset + ilst_size);
1878                 read_data(f, p_out, (uint32_t) (total_size
1879                         - (ilst_offset - total_base) - ilst_size));
1880
1881                 free(new_ilst_buffer);
1882         }
1883         return 1;
1884 }
1885
1886 static int32_t write_data(struct mp4 *f, void *data, uint32_t size)
1887 {
1888         int32_t result = 1;
1889
1890         result = f->stream->write(f->stream->user_data, data, size);
1891
1892         f->current_position += size;
1893
1894         return result;
1895 }
1896
1897 static int32_t write_int32(struct mp4 *f, uint32_t data)
1898 {
1899         int8_t temp[4];
1900         write_u32_be(temp, data);
1901         return write_data(f, temp, sizeof(temp));
1902 }
1903
1904 int32_t mp4_meta_update(struct mp4_callback *f, const struct mp4_metadata *data)
1905 {
1906         void *new_moov_data;
1907         uint32_t new_moov_size;
1908
1909         struct mp4 *ff = para_calloc(sizeof(struct mp4));
1910         ff->stream = f;
1911         set_position(ff, 0);
1912
1913         parse_atoms(ff, 1);
1914
1915         if (!modify_moov(ff, data, &new_moov_data, &new_moov_size)) {
1916                 mp4_close(ff);
1917                 return 0;
1918         }
1919
1920         /* copy moov atom to end of the file */
1921         if (ff->last_atom != ATOM_MOOV) {
1922                 char *free_data = "free";
1923
1924                 /* rename old moov to free */
1925                 set_position(ff, ff->moov_offset + 4);
1926                 write_data(ff, free_data, 4);
1927
1928                 set_position(ff, ff->file_size);
1929                 write_int32(ff, new_moov_size + 8);
1930                 write_data(ff, "moov", 4);
1931                 write_data(ff, new_moov_data, new_moov_size);
1932         } else {
1933                 set_position(ff, ff->moov_offset);
1934                 write_int32(ff, new_moov_size + 8);
1935                 write_data(ff, "moov", 4);
1936                 write_data(ff, new_moov_data, new_moov_size);
1937         }
1938         f->truncate(f->user_data);
1939         mp4_close(ff);
1940         return 1;
1941 }
1942
1943 /* find a metadata item by name */
1944 /* returns 0 if item found, 1 if no such item */
1945 static int32_t meta_find_by_name(const struct mp4 *f, const char *item,
1946                 char **value)
1947 {
1948         uint32_t i;
1949
1950         for (i = 0; i < f->tags.count; i++) {
1951                 if (!strcasecmp(f->tags.tags[i].item, item)) {
1952                         *value = para_strdup(f->tags.tags[i].value);
1953                         return 1;
1954                 }
1955         }
1956
1957         *value = NULL;
1958
1959         /* not found */
1960         return 0;
1961 }
1962
1963 int32_t mp4_meta_get_artist(const struct mp4 *f, char **value)
1964 {
1965         return meta_find_by_name(f, "artist", value);
1966 }
1967
1968 int32_t mp4_meta_get_title(const struct mp4 *f, char **value)
1969 {
1970         return meta_find_by_name(f, "title", value);
1971 }
1972
1973 int32_t mp4_meta_get_date(const struct mp4 *f, char **value)
1974 {
1975         return meta_find_by_name(f, "date", value);
1976 }
1977
1978 int32_t mp4_meta_get_album(const struct mp4 *f, char **value)
1979 {
1980         return meta_find_by_name(f, "album", value);
1981 }
1982
1983 int32_t mp4_meta_get_comment(const struct mp4 *f, char **value)
1984 {
1985         return meta_find_by_name(f, "comment", value);
1986 }