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