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