]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
mp4: Remove const qualifier from non-pointer function arguments.
[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 mp4ff_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 mp4ff {
64         /* stream to read from */
65         struct mp4ff_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 mp4ff_track *track[MAX_TRACKS];
83
84         /* metadata */
85         struct mp4ff_metadata tags;
86 };
87
88 int32_t mp4ff_total_tracks(const struct mp4ff *f)
89 {
90         return f->total_tracks;
91 }
92
93 static int32_t read_data(struct mp4ff *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 mp4ff *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 mp4ff *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 mp4ff *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 mp4ff *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 mp4ff *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 mp4ff_track));
439 }
440
441 static uint8_t read_char(struct mp4ff *f)
442 {
443         uint8_t output;
444         read_data(f, &output, 1);
445         return output;
446 }
447
448 static uint32_t read_int24(struct mp4ff *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 mp4ff *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 mp4ff *f)
465 {
466         int32_t i;
467         struct mp4ff_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 mp4ff *f)
485 {
486         int32_t i;
487         struct mp4ff_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 mp4ff *f)
512 {
513         int32_t i;
514         struct mp4ff_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 mp4ff *f)
540 {
541         int32_t i;
542         struct mp4ff_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 mp4ff *f)
567 {
568         int32_t i;
569         struct mp4ff_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 mp4ff *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 mp4ff *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 mp4ff *f)
609 {
610         uint8_t tag;
611         uint32_t temp;
612         struct mp4ff_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 mp4ff *f)
663 {
664         int32_t i;
665         uint8_t atom_type = 0;
666         uint8_t header_size = 0;
667         struct mp4ff_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 mp4ff *f)
698 {
699         int32_t i;
700         uint8_t header_size = 0;
701         struct mp4ff_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 mp4ff *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 mp4ff_metadata *tags, const char *item,
764                 const char *value, int32_t len)
765 {
766         void *backup = (void *) tags->tags;
767
768         if (!item || (item && !*item) || !value)
769                 return 0;
770
771         tags->tags = (struct mp4ff_tag *)realloc(tags->tags,
772                 (tags->count + 1) * sizeof(struct mp4ff_tag));
773         if (!tags->tags) {
774                 free(backup);
775                 return 0;
776         } else {
777                 tags->tags[tags->count].item = para_strdup(item);
778                 tags->tags[tags->count].len = len;
779                 if (len >= 0) {
780                         tags->tags[tags->count].value = para_malloc(len + 1);
781                         memcpy(tags->tags[tags->count].value, value, len);
782                         tags->tags[tags->count].value[len] = 0;
783                 } else {
784                         tags->tags[tags->count].value = para_strdup(value);
785                 }
786                 tags->count++;
787                 return 1;
788         }
789 }
790
791 static const char *ID3v1GenreList[] = {
792         "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
793         "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
794         "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
795         "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
796         "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal",
797         "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid",
798         "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
799         "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
800         "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
801         "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
802         "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40",
803         "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
804         "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
805         "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
806         "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk",
807         "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic",
808         "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock",
809         "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
810         "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
811         "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
812         "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
813         "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
814         "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
815         "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
816         "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
817         "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover",
818         "Contemporary C", "Christian Rock", "Merengue", "Salsa", "Thrash Metal",
819         "Anime", "JPop", "SynthPop",
820 };
821
822 static const char *meta_index_to_genre(uint32_t idx)
823 {
824         if (idx > 0 && idx <= sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0])) {
825                 return ID3v1GenreList[idx - 1];
826         } else {
827                 return 0;
828         }
829 }
830
831 static char *read_string(struct mp4ff *f, uint32_t length)
832 {
833         char *str = para_malloc(length + 1);
834         if ((uint32_t)read_data(f, str, length) != length) {
835                 free(str);
836                 str = NULL;
837         } else
838                 str[length] = 0;
839         return str;
840 }
841
842 static int32_t set_metadata_name(uint8_t atom_type, char **name)
843 {
844         static char *tag_names[] = {
845                 "unknown", "title", "artist", "writer", "album",
846                 "date", "tool", "comment", "genre", "track",
847                 "disc", "compilation", "genre", "tempo", "cover",
848                 "album_artist", "contentgroup", "lyrics", "description",
849                 "network", "show", "episodename",
850                 "sorttitle", "sortalbum", "sortartist", "sortalbumartist",
851                 "sortwriter", "sortshow",
852                 "season", "episode", "podcast"
853         };
854         uint8_t tag_idx = 0;
855
856         switch (atom_type) {
857         case ATOM_TITLE:
858                 tag_idx = 1;
859                 break;
860         case ATOM_ARTIST:
861                 tag_idx = 2;
862                 break;
863         case ATOM_WRITER:
864                 tag_idx = 3;
865                 break;
866         case ATOM_ALBUM:
867                 tag_idx = 4;
868                 break;
869         case ATOM_DATE:
870                 tag_idx = 5;
871                 break;
872         case ATOM_TOOL:
873                 tag_idx = 6;
874                 break;
875         case ATOM_COMMENT:
876                 tag_idx = 7;
877                 break;
878         case ATOM_GENRE1:
879                 tag_idx = 8;
880                 break;
881         case ATOM_TRACK:
882                 tag_idx = 9;
883                 break;
884         case ATOM_DISC:
885                 tag_idx = 10;
886                 break;
887         case ATOM_COMPILATION:
888                 tag_idx = 11;
889                 break;
890         case ATOM_GENRE2:
891                 tag_idx = 12;
892                 break;
893         case ATOM_TEMPO:
894                 tag_idx = 13;
895                 break;
896         case ATOM_COVER:
897                 tag_idx = 14;
898                 break;
899         case ATOM_ALBUM_ARTIST:
900                 tag_idx = 15;
901                 break;
902         case ATOM_CONTENTGROUP:
903                 tag_idx = 16;
904                 break;
905         case ATOM_LYRICS:
906                 tag_idx = 17;
907                 break;
908         case ATOM_DESCRIPTION:
909                 tag_idx = 18;
910                 break;
911         case ATOM_NETWORK:
912                 tag_idx = 19;
913                 break;
914         case ATOM_SHOW:
915                 tag_idx = 20;
916                 break;
917         case ATOM_EPISODENAME:
918                 tag_idx = 21;
919                 break;
920         case ATOM_SORTTITLE:
921                 tag_idx = 22;
922                 break;
923         case ATOM_SORTALBUM:
924                 tag_idx = 23;
925                 break;
926         case ATOM_SORTARTIST:
927                 tag_idx = 24;
928                 break;
929         case ATOM_SORTALBUMARTIST:
930                 tag_idx = 25;
931                 break;
932         case ATOM_SORTWRITER:
933                 tag_idx = 26;
934                 break;
935         case ATOM_SORTSHOW:
936                 tag_idx = 27;
937                 break;
938         case ATOM_SEASON:
939                 tag_idx = 28;
940                 break;
941         case ATOM_EPISODE:
942                 tag_idx = 29;
943                 break;
944         case ATOM_PODCAST:
945                 tag_idx = 30;
946                 break;
947         default:
948                 tag_idx = 0;
949                 break;
950         }
951
952         *name = para_strdup(tag_names[tag_idx]);
953         return 0;
954 }
955
956 static uint32_t min_body_size(uint8_t atom_type)
957 {
958         switch(atom_type) {
959         case ATOM_GENRE2:
960         case ATOM_TEMPO:
961                 return 10;
962         case ATOM_TRACK:
963                 return sizeof (char) /* version */
964                         + sizeof(uint8_t) * 3 /* flags */
965                         + sizeof(uint32_t) /* reserved */
966                         + sizeof(uint16_t) /* leading uint16_t */
967                         + sizeof(uint16_t) /* track */
968                         + sizeof(uint16_t); /* totaltracks */
969         case ATOM_DISC:
970                 return sizeof (char) /* version */
971                         + sizeof(uint8_t) * 3 /* flags */
972                         + sizeof(uint32_t) /* reserved */
973                         + sizeof(uint16_t) /* disc */
974                         + sizeof(uint16_t); /* totaldiscs */
975         default: assert(false);
976         }
977 }
978
979 static int32_t parse_tag(struct mp4ff *f, uint8_t parent, int32_t size)
980 {
981         uint8_t atom_type;
982         uint8_t header_size = 0;
983         uint64_t subsize, sumsize;
984         char *name = NULL;
985         char *data = NULL;
986         uint32_t done = 0;
987         uint32_t len = 0;
988         uint64_t destpos;
989
990         for (
991                 sumsize = 0;
992                 sumsize < size && !f->stream->read_error; /* CVE-2017-9222 */
993                 set_position(f, destpos), sumsize += subsize
994         ) {
995                 subsize = atom_read_header(f, &atom_type, &header_size);
996                 destpos = get_position(f) + subsize - header_size;
997                 if (done)
998                         continue;
999                 if (atom_type == ATOM_NAME) {
1000                         read_char(f);   /* version */
1001                         read_int24(f);  /* flags */
1002                         free(name);
1003                         name = read_string(f, subsize - (header_size + 4));
1004                         continue;
1005                 }
1006                 if (atom_type != ATOM_DATA)
1007                         continue;
1008                 read_char(f);   /* version */
1009                 read_int24(f);  /* flags */
1010                 read_int32(f);  /* reserved */
1011
1012                 /* some need special attention */
1013                 if (parent == ATOM_GENRE2 || parent == ATOM_TEMPO) {
1014                         uint16_t val;
1015                         if (subsize - header_size < min_body_size(parent))
1016                                 continue;
1017                         val = read_int16(f);
1018                         if (parent == ATOM_TEMPO) {
1019                                 char temp[16];
1020                                 sprintf(temp, "%.5u BPM", val);
1021                                 tag_add_field(&(f-> tags), "tempo",
1022                                         temp, -1);
1023                         } else {
1024                                 const char *tmp = meta_index_to_genre(val);
1025                                 if (tmp)
1026                                         tag_add_field (&(f->tags),
1027                                                 "genre", tmp, -1);
1028                         }
1029                         done = 1;
1030                 } else if (parent == ATOM_TRACK || parent == ATOM_DISC) {
1031                         uint16_t index, total;
1032                         char temp[32];
1033                         if (subsize - header_size < min_body_size(parent))
1034                                 continue;
1035                         read_int16(f);
1036                         index = read_int16(f);
1037                         total = read_int16(f);
1038                         if (parent == ATOM_TRACK)
1039                                 read_int16(f);
1040                         sprintf(temp, "%d", index);
1041                         tag_add_field(&(f->tags), parent == ATOM_TRACK?
1042                                 "track" : "disc", temp, -1);
1043                         if (total > 0) {
1044                                 sprintf(temp, "%d", total);
1045                                 tag_add_field(& (f-> tags),
1046                                         parent == ATOM_TRACK?
1047                                         "totaltracks" : "totaldiscs", temp, -1);
1048                         }
1049                         done = 1;
1050                 } else {
1051                         free(data);
1052                         data = read_string(f, subsize - (header_size + 8));
1053                         len = subsize - (header_size + 8);
1054                 }
1055         }
1056         if (data) {
1057                 if (!done) {
1058                         if (name == NULL)
1059                                 set_metadata_name(parent , &name);
1060                         if (name)
1061                                 tag_add_field(&(f->tags), name, data, len);
1062                 }
1063
1064                 free(data);
1065         }
1066         free(name);
1067         return 1;
1068 }
1069
1070 static int32_t read_mdhd(struct mp4ff *f)
1071 {
1072         uint32_t version;
1073         struct mp4ff_track *t;
1074
1075         /* CVE-2017-9221 */
1076         if (f->total_tracks == 0)
1077                 return f->error++;
1078         t = f->track[f->total_tracks - 1];
1079
1080         version = read_int32(f);
1081         if (version == 1) {
1082                 read_int64(f); //creation-time
1083                 read_int64(f); //modification-time
1084                 t->timeScale = read_int32(f); //timescale
1085                 t->duration = read_int64(f); //duration
1086         } else { //version == 0
1087                 uint32_t temp;
1088
1089                 read_int32(f);  //creation-time
1090                 read_int32(f);  //modification-time
1091                 t->timeScale = read_int32(f); //timescale
1092                 temp = read_int32(f);
1093                 t->duration = (temp == (uint32_t) (-1))?
1094                         (uint64_t) (-1) : (uint64_t) (temp);
1095         }
1096         read_int16(f);
1097         read_int16(f);
1098         return 1;
1099 }
1100
1101 static int32_t parse_metadata(struct mp4ff *f, int32_t size)
1102 {
1103         uint64_t subsize, sumsize = 0;
1104         uint8_t atom_type;
1105         uint8_t header_size = 0;
1106
1107         while (sumsize < size) {
1108                 subsize = atom_read_header(f, &atom_type, &header_size);
1109                 if (subsize == 0)
1110                         break;
1111                 parse_tag(f, atom_type, (uint32_t)(subsize - header_size));
1112                 sumsize += subsize;
1113         }
1114
1115         return 0;
1116 }
1117
1118 static int32_t read_meta(struct mp4ff *f, uint64_t size)
1119 {
1120         uint64_t subsize, sumsize = 0;
1121         uint8_t atom_type;
1122         uint8_t header_size = 0;
1123
1124         read_char(f);   /* version */
1125         read_int24(f);  /* flags */
1126
1127         while (sumsize < (size - (header_size + 4))) {
1128                 subsize = atom_read_header(f, &atom_type, &header_size);
1129                 if (subsize <= header_size + 4)
1130                         return 1;
1131                 if (atom_type == ATOM_ILST) {
1132                         parse_metadata(f, (uint32_t) (subsize - (header_size + 4)));
1133                 } else {
1134                         set_position(f, get_position(f) + subsize - header_size);
1135                 }
1136                 sumsize += subsize;
1137         }
1138
1139         return 0;
1140 }
1141
1142 static int32_t atom_read(struct mp4ff *f, int32_t size, uint8_t atom_type)
1143 {
1144         uint64_t dest_position = get_position(f) + size - 8;
1145         if (atom_type == ATOM_STSZ) {
1146                 /* sample size box */
1147                 read_stsz(f);
1148         } else if (atom_type == ATOM_STTS) {
1149                 /* time to sample box */
1150                 read_stts(f);
1151         } else if (atom_type == ATOM_CTTS) {
1152                 /* composition offset box */
1153                 read_ctts(f);
1154         } else if (atom_type == ATOM_STSC) {
1155                 /* sample to chunk box */
1156                 read_stsc(f);
1157         } else if (atom_type == ATOM_STCO) {
1158                 /* chunk offset box */
1159                 read_stco(f);
1160         } else if (atom_type == ATOM_STSD) {
1161                 /* sample description box */
1162                 read_stsd(f);
1163         } else if (atom_type == ATOM_MVHD) {
1164                 /* movie header box */
1165                 read_mvhd(f);
1166         } else if (atom_type == ATOM_MDHD) {
1167                 /* track header */
1168                 read_mdhd(f);
1169         } else if (atom_type == ATOM_META) {
1170                 /* iTunes Metadata box */
1171                 read_meta(f, size);
1172         }
1173
1174         set_position(f, dest_position);
1175         return 0;
1176 }
1177
1178 /* parse atoms that are sub atoms of other atoms */
1179 static int32_t parse_sub_atoms(struct mp4ff *f, uint64_t total_size, int meta_only)
1180 {
1181         uint64_t size;
1182         uint8_t atom_type = 0;
1183         uint64_t counted_size = 0;
1184         uint8_t header_size = 0;
1185
1186         while (counted_size < total_size) {
1187                 size = atom_read_header(f, &atom_type, &header_size);
1188                 counted_size += size;
1189
1190                 /* check for end of file */
1191                 if (size == 0)
1192                         break;
1193
1194                 /* we're starting to read a new track, update index,
1195                  * so that all data and tables get written in the right place
1196                  */
1197                 if (atom_type == ATOM_TRAK)
1198                         track_add(f);
1199                 /* parse subatoms */
1200                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1201                         set_position(f, get_position(f) + size - header_size);
1202                 } else if (atom_type < SUBATOMIC) {
1203                         parse_sub_atoms(f, size - header_size, meta_only);
1204                 } else {
1205                         atom_read(f, (uint32_t) size, atom_type);
1206                 }
1207         }
1208
1209         return 0;
1210 }
1211
1212 /* parse root atoms */
1213 static int32_t parse_atoms(struct mp4ff *f, int meta_only)
1214 {
1215         uint64_t size;
1216         uint8_t atom_type = 0;
1217         uint8_t header_size = 0;
1218
1219         f->file_size = 0;
1220         f->stream->read_error = 0;
1221
1222         while ((size =
1223                 atom_read_header(f, &atom_type, &header_size)) != 0) {
1224                 f->file_size += size;
1225                 f->last_atom = atom_type;
1226
1227                 if (atom_type == ATOM_MOOV && size > header_size) {
1228                         f->moov_offset = get_position(f) - header_size;
1229                         f->moov_size = size;
1230                 }
1231
1232                 /* parse subatoms */
1233                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1234                         set_position(f, get_position(f) + size - header_size);
1235                 } else if (atom_type < SUBATOMIC) {
1236                         parse_sub_atoms(f, size - header_size, meta_only);
1237                 } else {
1238                         /* skip this atom */
1239                         set_position(f, get_position(f) + size - header_size);
1240                 }
1241         }
1242
1243         return 0;
1244 }
1245
1246 void mp4ff_get_decoder_config(const struct mp4ff *f, int track,
1247                 unsigned char **ppBuf, unsigned int *pBufSize)
1248 {
1249         if (track >= f->total_tracks) {
1250                 *ppBuf = NULL;
1251                 *pBufSize = 0;
1252                 return;
1253         }
1254
1255         if (f->track[track]->decoderConfig == NULL
1256                 || f->track[track]->decoderConfigLen == 0) {
1257                 *ppBuf = NULL;
1258                 *pBufSize = 0;
1259         } else {
1260                 *ppBuf = para_malloc(f->track[track]->decoderConfigLen);
1261                 memcpy(*ppBuf, f->track[track]->decoderConfig,
1262                         f->track[track]->decoderConfigLen);
1263                 *pBufSize = f->track[track]->decoderConfigLen;
1264         }
1265 }
1266
1267 struct mp4ff *mp4ff_open_read(struct mp4ff_callback *f)
1268 {
1269         struct mp4ff *ff = para_calloc(sizeof(struct mp4ff));
1270
1271         ff->stream = f;
1272
1273         parse_atoms(ff, 0);
1274
1275         if (ff->error) {
1276                 free(ff);
1277                 ff = NULL;
1278         }
1279
1280         return ff;
1281 }
1282
1283 static int32_t tag_delete(struct mp4ff_metadata *tags)
1284 {
1285         uint32_t i;
1286
1287         for (i = 0; i < tags->count; i++) {
1288                 free(tags->tags[i].item);
1289                 free(tags->tags[i].value);
1290         }
1291         free(tags->tags);
1292         tags->tags = NULL;
1293         tags->count = 0;
1294
1295         return 0;
1296 }
1297
1298 void mp4ff_close(struct mp4ff *ff)
1299 {
1300         int32_t i;
1301
1302         for (i = 0; i < ff->total_tracks; i++) {
1303                 if (ff->track[i]) {
1304                         free(ff->track[i]->stsz_table);
1305                         free(ff->track[i]->stts_sample_count);
1306                         free(ff->track[i]->stts_sample_delta);
1307                         free(ff->track[i]->stsc_first_chunk);
1308                         free(ff->track[i]->stsc_samples_per_chunk);
1309                         free(ff->track[i]->stsc_sample_desc_index);
1310                         free(ff->track[i]->stco_chunk_offset);
1311                         free(ff->track[i]->decoderConfig);
1312                         free(ff->track[i]->ctts_sample_count);
1313                         free(ff->track[i]->ctts_sample_offset);
1314                         free(ff->track[i]);
1315                 }
1316         }
1317
1318         tag_delete(&(ff->tags));
1319         free(ff);
1320 }
1321
1322 static int32_t chunk_of_sample(const struct mp4ff *f, int32_t track,
1323                 int32_t sample, int32_t *chunk_sample, int32_t *chunk)
1324 {
1325         int32_t total_entries = 0;
1326         int32_t chunk2entry;
1327         int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
1328
1329         *chunk_sample = 0;
1330         *chunk = 1;
1331         if (f->track[track] == NULL) {
1332                 return -1;
1333         }
1334
1335         total_entries = f->track[track]->stsc_entry_count;
1336
1337         chunk1 = 1;
1338         chunk1samples = 0;
1339         chunk2entry = 0;
1340
1341         do {
1342                 chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
1343                 *chunk = chunk2 - chunk1;
1344                 range_samples = *chunk * chunk1samples;
1345
1346                 if (sample < total + range_samples)
1347                         break;
1348
1349                 chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
1350                 chunk1 = chunk2;
1351
1352                 if (chunk2entry < total_entries) {
1353                         chunk2entry++;
1354                         total += range_samples;
1355                 }
1356         } while (chunk2entry < total_entries);
1357
1358         if (chunk1samples)
1359                 *chunk = (sample - total) / chunk1samples + chunk1;
1360         else
1361                 *chunk = 1;
1362
1363         *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
1364
1365         return 0;
1366 }
1367
1368 static int32_t chunk_to_offset(const struct mp4ff *f, int32_t track,
1369                 int32_t chunk)
1370 {
1371         const struct mp4ff_track *p_track = f->track[track];
1372
1373         if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) {
1374                 return p_track->stco_chunk_offset[p_track->stco_entry_count -
1375                                                   1];
1376         } else if (p_track->stco_entry_count) {
1377                 return p_track->stco_chunk_offset[chunk - 1];
1378         } else {
1379                 return 8;
1380         }
1381
1382         return 0;
1383 }
1384
1385 static int32_t sample_range_size(const struct mp4ff *f, int32_t track,
1386                 int32_t chunk_sample, int32_t sample)
1387 {
1388         int32_t i, total;
1389         const struct mp4ff_track *p_track = f->track[track];
1390
1391         if (p_track->stsz_sample_size) {
1392                 return (sample - chunk_sample) * p_track->stsz_sample_size;
1393         } else {
1394                 if (sample >= p_track->stsz_sample_count)
1395                         return 0;       //error
1396
1397                 for (i = chunk_sample, total = 0; i < sample; i++) {
1398                         total += p_track->stsz_table[i];
1399                 }
1400         }
1401
1402         return total;
1403 }
1404
1405 static int32_t sample_to_offset(const struct mp4ff *f, int32_t track,
1406                 int32_t sample)
1407 {
1408         int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
1409
1410         chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
1411
1412         chunk_offset1 = chunk_to_offset(f, track, chunk);
1413         chunk_offset2 = chunk_offset1 + sample_range_size(f,
1414                 track, chunk_sample, sample);
1415         return chunk_offset2;
1416 }
1417
1418 void mp4ff_set_sample_position(struct mp4ff *f, int32_t track, int32_t sample)
1419 {
1420         int32_t offset = sample_to_offset(f, track, sample);
1421         set_position(f, offset);
1422 }
1423
1424 int32_t mp4ff_get_sample_size(const struct mp4ff *f, int track, int sample)
1425 {
1426         const struct mp4ff_track *t = f->track[track];
1427
1428         if (t->stsz_sample_size != 0)
1429                 return t->stsz_sample_size;
1430         return t->stsz_table[sample];
1431 }
1432
1433 uint32_t mp4ff_get_sample_rate(const struct mp4ff *f, int32_t track)
1434 {
1435         return f->track[track]->sampleRate;
1436 }
1437
1438 uint32_t mp4ff_get_channel_count(const struct mp4ff *f, int32_t track)
1439 {
1440         return f->track[track]->channelCount;
1441 }
1442
1443 int32_t mp4ff_num_samples(const struct mp4ff *f, int32_t track)
1444 {
1445         int32_t i;
1446         int32_t total = 0;
1447
1448         for (i = 0; i < f->track[track]->stts_entry_count; i++) {
1449                 total += f->track[track]->stts_sample_count[i];
1450         }
1451         return total;
1452 }
1453
1454 struct mp4ff *mp4ff_open_read_metaonly(struct mp4ff_callback *f)
1455 {
1456         struct mp4ff *ff = para_calloc(sizeof(struct mp4ff));
1457
1458         ff->stream = f;
1459
1460         parse_atoms(ff, 1);
1461
1462         if (ff->error) {
1463                 free(ff);
1464                 ff = NULL;
1465         }
1466
1467         return ff;
1468 }
1469
1470 int32_t mp4ff_meta_get_num_items(const struct mp4ff *f)
1471 {
1472         return f->tags.count;
1473 }
1474
1475 int32_t mp4ff_meta_get_by_index(const struct mp4ff *f, uint32_t index,
1476                                 char **item, char **value)
1477 {
1478         if (index >= f->tags.count) {
1479                 *item = NULL;
1480                 *value = NULL;
1481                 return 0;
1482         } else {
1483                 *item = para_strdup(f->tags.tags[index].item);
1484                 *value = para_strdup(f->tags.tags[index].value);
1485                 return 1;
1486         }
1487 }
1488
1489 static uint32_t find_atom(struct mp4ff *f, uint64_t base, uint32_t size,
1490                           const char *name)
1491 {
1492         uint32_t remaining = size;
1493         uint64_t atom_offset = base;
1494         for (;;) {
1495                 char atom_name[4];
1496                 uint32_t atom_size;
1497
1498                 set_position(f, atom_offset);
1499
1500                 if (remaining < 8)
1501                         break;
1502                 atom_size = read_int32(f);
1503                 if (atom_size > remaining || atom_size < 8)
1504                         break;
1505                 read_data(f, atom_name, 4);
1506
1507                 if (!memcmp(atom_name, name, 4)) {
1508                         set_position(f, atom_offset);
1509                         return 1;
1510                 }
1511
1512                 remaining -= atom_size;
1513                 atom_offset += atom_size;
1514         }
1515         return 0;
1516 }
1517
1518 static uint32_t find_atom_v2(struct mp4ff *f, uint64_t base, uint32_t size,
1519                 const char *name, uint32_t extraheaders, const char *name_inside)
1520 {
1521         uint64_t first_base = (uint64_t) (-1);
1522         while (find_atom(f, base, size, name))  //try to find atom <name> with atom <name_inside> in it
1523         {
1524                 uint64_t mybase = get_position(f);
1525                 uint32_t mysize = read_int32(f);
1526
1527                 if (first_base == (uint64_t) (-1))
1528                         first_base = mybase;
1529
1530                 if (mysize < 8 + extraheaders)
1531                         break;
1532
1533                 if (find_atom (f, mybase + (8 + extraheaders),
1534                                 mysize - (8 + extraheaders), name_inside)) {
1535                         set_position(f, mybase);
1536                         return 2;
1537                 }
1538                 base += mysize;
1539                 if (size <= mysize) {
1540                         size = 0;
1541                         break;
1542                 }
1543                 size -= mysize;
1544         }
1545
1546         if (first_base != (uint64_t) (-1))      //wanted atom inside not found
1547         {
1548                 set_position(f, first_base);
1549                 return 1;
1550         } else
1551                 return 0;
1552 }
1553
1554 struct membuffer {
1555         void *data;
1556         unsigned written;
1557         unsigned allocated;
1558         unsigned error;
1559 };
1560
1561 static struct membuffer *membuffer_create(void)
1562 {
1563         const unsigned initial_size = 256;
1564
1565         struct membuffer *buf = para_malloc(sizeof(*buf));
1566         buf->data = para_malloc(initial_size);
1567         buf->written = 0;
1568         buf->allocated = initial_size;
1569         buf->error = buf->data == 0 ? 1 : 0;
1570
1571         return buf;
1572 }
1573
1574 static unsigned membuffer_write(struct membuffer *buf, const void *ptr, unsigned bytes)
1575 {
1576         unsigned dest_size = buf->written + bytes;
1577
1578         if (buf->error)
1579                 return 0;
1580         if (dest_size > buf->allocated) {
1581                 do {
1582                         buf->allocated <<= 1;
1583                 } while (dest_size > buf->allocated);
1584
1585                 {
1586                         void *newptr = realloc(buf->data, buf->allocated);
1587                         if (newptr == 0) {
1588                                 free(buf->data);
1589                                 buf->data = 0;
1590                                 buf->error = 1;
1591                                 return 0;
1592                         }
1593                         buf->data = newptr;
1594                 }
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
1773         ret = realloc(buf->data, buf->written);
1774
1775         if (ret == 0)
1776                 free(buf->data);
1777
1778         buf->data = 0;
1779         buf->error = 1;
1780
1781         return ret;
1782 }
1783
1784 static uint32_t create_ilst(const struct mp4ff_metadata *data, void **out_buffer,
1785                 uint32_t * out_size)
1786 {
1787         struct membuffer *buf = membuffer_create();
1788         unsigned metaptr;
1789         char *mask = para_calloc(data->count);
1790         const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1791         const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1792         const char *genre_ptr = 0, *tempo_ptr = 0;
1793
1794         for (metaptr = 0; metaptr < data->count; metaptr++) {
1795                 struct mp4ff_tag *tag = &data->tags[metaptr];
1796                 if (!strcasecmp(tag->item, "tracknumber")
1797                                 || !strcasecmp(tag->item, "track")) {
1798                         if (tracknumber_ptr == 0)
1799                                 tracknumber_ptr = tag->value;
1800                         mask[metaptr] = 1;
1801                 } else if (!strcasecmp(tag->item, "totaltracks")) {
1802                         if (totaltracks_ptr == 0)
1803                                 totaltracks_ptr = tag->value;
1804                         mask[metaptr] = 1;
1805                 } else if (!strcasecmp(tag->item, "discnumber")
1806                                 || !strcasecmp(tag->item, "disc")) {
1807                         if (discnumber_ptr == 0)
1808                                 discnumber_ptr = tag->value;
1809                         mask[metaptr] = 1;
1810                 } else if (!strcasecmp(tag->item, "totaldiscs")) {
1811                         if (totaldiscs_ptr == 0)
1812                                 totaldiscs_ptr = tag->value;
1813                         mask[metaptr] = 1;
1814                 } else if (!strcasecmp(tag->item, "genre")) {
1815                         if (genre_ptr == 0)
1816                                 genre_ptr = tag->value;
1817                         mask[metaptr] = 1;
1818                 } else if (!strcasecmp(tag->item, "tempo")) {
1819                         if (tempo_ptr == 0)
1820                                 tempo_ptr = tag->value;
1821                         mask[metaptr] = 1;
1822                 }
1823         }
1824
1825         if (tracknumber_ptr)
1826                 membuffer_write_track_tag(buf, "trkn", myatoi(tracknumber_ptr),
1827                          myatoi(totaltracks_ptr));
1828         if (discnumber_ptr)
1829                 membuffer_write_track_tag(buf, "disk", myatoi(discnumber_ptr),
1830                          myatoi(totaldiscs_ptr));
1831         if (tempo_ptr)
1832                 membuffer_write_int16_tag(buf, "tmpo", myatoi(tempo_ptr));
1833
1834         if (genre_ptr) {
1835                 uint32_t index = meta_genre_to_index(genre_ptr);
1836                 if (index == 0)
1837                         membuffer_write_std_tag(buf, "©gen", genre_ptr);
1838                 else
1839                         membuffer_write_int16_tag(buf, "gnre", index);
1840         }
1841         for (metaptr = 0; metaptr < data->count; metaptr++) {
1842                 struct mp4ff_tag *tag;
1843                 const char *std_meta_atom;
1844
1845                 if (mask[metaptr])
1846                         continue;
1847                 tag = &data->tags[metaptr];
1848                 std_meta_atom = find_standard_meta(tag->item);
1849                 if (std_meta_atom)
1850                         membuffer_write_std_tag(buf, std_meta_atom, tag->value);
1851                 else
1852                         membuffer_write_custom_tag(buf, tag->item, tag->value);
1853         }
1854         free(mask);
1855
1856         if (membuffer_error(buf)) {
1857                 membuffer_free(buf);
1858                 return 0;
1859         }
1860
1861         *out_size = membuffer_get_size(buf);
1862         *out_buffer = membuffer_detach(buf);
1863         membuffer_free(buf);
1864
1865         return 1;
1866 }
1867
1868 static void membuffer_write_atom(struct membuffer *buf, const char *name, unsigned size,
1869                           const void *data)
1870 {
1871         membuffer_write_int32(buf, size + 8);
1872         membuffer_write_atom_name(buf, name);
1873         membuffer_write(buf, data, size);
1874 }
1875
1876 static void *membuffer_get_ptr(const struct membuffer *buf)
1877 {
1878         return buf->data;
1879 }
1880
1881 static void membuffer_set_error(struct membuffer *buf)
1882 {
1883         buf->error = 1;
1884 }
1885
1886 static unsigned membuffer_transfer_from_file(struct membuffer *buf, struct mp4ff *src,
1887                 unsigned bytes)
1888 {
1889         unsigned oldsize;
1890         void *bufptr;
1891
1892         oldsize = membuffer_get_size(buf);
1893         if (membuffer_write(buf, 0, bytes) != bytes)
1894                 return 0;
1895
1896         bufptr = membuffer_get_ptr(buf);
1897         if (bufptr == 0)
1898                 return 0;
1899
1900         if ((unsigned)read_data(src, (char *) bufptr + oldsize, bytes) !=
1901                 bytes) {
1902                 membuffer_set_error(buf);
1903                 return 0;
1904         }
1905
1906         return bytes;
1907 }
1908
1909 static uint32_t create_meta(const struct mp4ff_metadata *data, void **out_buffer,
1910                 uint32_t * out_size)
1911 {
1912         struct membuffer *buf;
1913         uint32_t ilst_size;
1914         void *ilst_buffer;
1915
1916         if (!create_ilst(data, &ilst_buffer, &ilst_size))
1917                 return 0;
1918
1919         buf = membuffer_create();
1920
1921         membuffer_write_int32(buf, 0);
1922         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
1923         free(ilst_buffer);
1924
1925         *out_size = membuffer_get_size(buf);
1926         *out_buffer = membuffer_detach(buf);
1927         membuffer_free(buf);
1928         return 1;
1929 }
1930
1931 static uint32_t create_udta(const struct mp4ff_metadata *data, void **out_buffer,
1932 uint32_t * out_size)
1933 {
1934         struct membuffer *buf;
1935         uint32_t meta_size;
1936         void *meta_buffer;
1937
1938         if (!create_meta(data, &meta_buffer, &meta_size))
1939                 return 0;
1940
1941         buf = membuffer_create();
1942
1943         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
1944
1945         free(meta_buffer);
1946
1947         *out_size = membuffer_get_size(buf);
1948         *out_buffer = membuffer_detach(buf);
1949         membuffer_free(buf);
1950         return 1;
1951 }
1952
1953 static uint32_t fix_byte_order_32(uint32_t src)
1954 {
1955         return read_u32_be(&src);
1956 }
1957
1958 static uint32_t modify_moov(struct mp4ff *f, const struct mp4ff_metadata *data,
1959                 void **out_buffer, uint32_t * out_size)
1960 {
1961         uint64_t total_base = f->moov_offset + 8;
1962         uint32_t total_size = (uint32_t) (f->moov_size - 8);
1963
1964         uint64_t udta_offset, meta_offset, ilst_offset;
1965         uint32_t udta_size, meta_size, ilst_size;
1966
1967         uint32_t new_ilst_size;
1968         void *new_ilst_buffer;
1969
1970         uint8_t *p_out;
1971         int32_t size_delta;
1972
1973         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
1974                 struct membuffer *buf;
1975                 void *new_udta_buffer;
1976                 uint32_t new_udta_size;
1977                 if (!create_udta(data, &new_udta_buffer, &new_udta_size))
1978                         return 0;
1979
1980                 buf = membuffer_create();
1981                 set_position(f, total_base);
1982                 membuffer_transfer_from_file(buf, f, total_size);
1983
1984                 membuffer_write_atom(buf, "udta", new_udta_size,
1985                         new_udta_buffer);
1986
1987                 free(new_udta_buffer);
1988
1989                 *out_size = membuffer_get_size(buf);
1990                 *out_buffer = membuffer_detach(buf);
1991                 membuffer_free(buf);
1992                 return 1;
1993         } else {
1994                 udta_offset = get_position(f);
1995                 udta_size = read_int32(f);
1996                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
1997                         struct membuffer *buf;
1998                         void *new_meta_buffer;
1999                         uint32_t new_meta_size;
2000                         if (!create_meta(data, &new_meta_buffer, &new_meta_size))
2001                                 return 0;
2002
2003                         buf = membuffer_create();
2004                         set_position(f, total_base);
2005                         membuffer_transfer_from_file(buf, f,
2006                                 (uint32_t)(udta_offset - total_base));
2007
2008                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
2009                         membuffer_write_atom_name(buf, "udta");
2010                         membuffer_transfer_from_file(buf, f, udta_size);
2011
2012                         membuffer_write_atom(buf, "meta", new_meta_size,
2013                                 new_meta_buffer);
2014                         free(new_meta_buffer);
2015
2016                         *out_size = membuffer_get_size(buf);
2017                         *out_buffer = membuffer_detach(buf);
2018                         membuffer_free(buf);
2019                         return 1;
2020                 }
2021                 meta_offset = get_position(f);
2022                 meta_size = read_int32(f);
2023                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
2024                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
2025                 ilst_offset = get_position(f);
2026                 ilst_size = read_int32(f);
2027
2028                 if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
2029                         return 0;
2030
2031                 size_delta = new_ilst_size - (ilst_size - 8);
2032
2033                 *out_size = total_size + size_delta;
2034                 *out_buffer = para_malloc(*out_size);
2035                 p_out = (uint8_t *) * out_buffer;
2036
2037                 set_position(f, total_base);
2038                 read_data(f, p_out,
2039                                 (uint32_t) (udta_offset - total_base));
2040                 p_out += (uint32_t) (udta_offset - total_base);
2041                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
2042                 p_out += 4;
2043                 read_data(f, p_out, 4);
2044                 p_out += 4;
2045                 read_data(f, p_out,
2046                                 (uint32_t) (meta_offset - udta_offset - 8));
2047                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
2048                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
2049                 p_out += 4;
2050                 read_data(f, p_out, 4);
2051                 p_out += 4;
2052                 read_data(f, p_out,
2053                                 (uint32_t) (ilst_offset - meta_offset - 8));
2054                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
2055                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
2056                 p_out += 4;
2057                 read_data(f, p_out, 4);
2058                 p_out += 4;
2059
2060                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
2061                 p_out += new_ilst_size;
2062
2063                 set_position(f, ilst_offset + ilst_size);
2064                 read_data(f, p_out, (uint32_t) (total_size
2065                         - (ilst_offset - total_base) - ilst_size));
2066
2067                 free(new_ilst_buffer);
2068         }
2069         return 1;
2070 }
2071
2072 static int32_t write_data(struct mp4ff *f, void *data, uint32_t size)
2073 {
2074         int32_t result = 1;
2075
2076         result = f->stream->write(f->stream->user_data, data, size);
2077
2078         f->current_position += size;
2079
2080         return result;
2081 }
2082
2083 static int32_t write_int32(struct mp4ff *f, uint32_t data)
2084 {
2085         int8_t temp[4];
2086         write_u32_be(temp, data);
2087         return write_data(f, temp, sizeof(temp));
2088 }
2089
2090 static int32_t truncate_stream(struct mp4ff *f)
2091 {
2092         return f->stream->truncate(f->stream->user_data);
2093 }
2094
2095 int32_t mp4ff_meta_update(struct mp4ff_callback *f, const struct mp4ff_metadata *data)
2096 {
2097         void *new_moov_data;
2098         uint32_t new_moov_size;
2099
2100         struct mp4ff *ff = para_calloc(sizeof(struct mp4ff));
2101         ff->stream = f;
2102         set_position(ff, 0);
2103
2104         parse_atoms(ff, 1);
2105
2106         if (!modify_moov(ff, data, &new_moov_data, &new_moov_size)) {
2107                 mp4ff_close(ff);
2108                 return 0;
2109         }
2110
2111         /* copy moov atom to end of the file */
2112         if (ff->last_atom != ATOM_MOOV) {
2113                 char *free_data = "free";
2114
2115                 /* rename old moov to free */
2116                 set_position(ff, ff->moov_offset + 4);
2117                 write_data(ff, free_data, 4);
2118
2119                 set_position(ff, ff->file_size);
2120                 write_int32(ff, new_moov_size + 8);
2121                 write_data(ff, "moov", 4);
2122                 write_data(ff, new_moov_data, new_moov_size);
2123         } else {
2124                 set_position(ff, ff->moov_offset);
2125                 write_int32(ff, new_moov_size + 8);
2126                 write_data(ff, "moov", 4);
2127                 write_data(ff, new_moov_data, new_moov_size);
2128         }
2129
2130         truncate_stream(ff);
2131
2132         mp4ff_close(ff);
2133         return 1;
2134 }
2135
2136 /* find a metadata item by name */
2137 /* returns 0 if item found, 1 if no such item */
2138 static int32_t meta_find_by_name(const struct mp4ff *f, const char *item,
2139                 char **value)
2140 {
2141         uint32_t i;
2142
2143         for (i = 0; i < f->tags.count; i++) {
2144                 if (!strcasecmp(f->tags.tags[i].item, item)) {
2145                         *value = para_strdup(f->tags.tags[i].value);
2146                         return 1;
2147                 }
2148         }
2149
2150         *value = NULL;
2151
2152         /* not found */
2153         return 0;
2154 }
2155
2156 int32_t mp4ff_meta_get_artist(const struct mp4ff *f, char **value)
2157 {
2158         return meta_find_by_name(f, "artist", value);
2159 }
2160
2161 int32_t mp4ff_meta_get_title(const struct mp4ff *f, char **value)
2162 {
2163         return meta_find_by_name(f, "title", value);
2164 }
2165
2166 int32_t mp4ff_meta_get_date(const struct mp4ff *f, char **value)
2167 {
2168         return meta_find_by_name(f, "date", value);
2169 }
2170
2171 int32_t mp4ff_meta_get_album(const struct mp4ff *f, char **value)
2172 {
2173         return meta_find_by_name(f, "album", value);
2174 }
2175
2176 int32_t mp4ff_meta_get_comment(const struct mp4ff *f, char **value)
2177 {
2178         return meta_find_by_name(f, "comment", value);
2179 }