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