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