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