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