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