]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
mp4: Whitespace and indentation cleanups for create_ilst().
[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 static struct membuffer *membuffer_create(void)
1568 {
1569         const unsigned initial_size = 256;
1570
1571         struct membuffer *buf = para_malloc(sizeof(*buf));
1572         buf->data = para_malloc(initial_size);
1573         buf->written = 0;
1574         buf->allocated = initial_size;
1575         buf->error = buf->data == 0 ? 1 : 0;
1576
1577         return buf;
1578 }
1579
1580 static unsigned membuffer_write(struct membuffer *buf, const void *ptr, unsigned bytes)
1581 {
1582         unsigned dest_size = buf->written + bytes;
1583
1584         if (buf->error)
1585                 return 0;
1586         if (dest_size > buf->allocated) {
1587                 do {
1588                         buf->allocated <<= 1;
1589                 } while (dest_size > buf->allocated);
1590
1591                 {
1592                         void *newptr = realloc(buf->data, buf->allocated);
1593                         if (newptr == 0) {
1594                                 free(buf->data);
1595                                 buf->data = 0;
1596                                 buf->error = 1;
1597                                 return 0;
1598                         }
1599                         buf->data = newptr;
1600                 }
1601         }
1602
1603         if (ptr)
1604                 memcpy((char *) buf->data + buf->written, ptr, bytes);
1605         buf->written += bytes;
1606         return bytes;
1607 }
1608
1609 static unsigned membuffer_write_atom_name(struct membuffer *buf, const char *data)
1610 {
1611         return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
1612 }
1613
1614 static unsigned membuffer_write_int16(struct membuffer *buf, uint16_t data)
1615 {
1616         uint8_t temp[2];
1617
1618         write_u16_be(temp, data);
1619         return membuffer_write(buf, temp, 2);
1620 }
1621
1622 static unsigned membuffer_write_int32(struct membuffer *buf, uint32_t data)
1623 {
1624         uint8_t temp[4];
1625         write_u32_be(temp, data);
1626         return membuffer_write(buf, temp, 4);
1627 }
1628
1629 static void membuffer_write_track_tag(struct membuffer *buf, const char *name,
1630                 uint32_t index, uint32_t total)
1631 {
1632         membuffer_write_int32(buf,
1633                 8 /*atom header */  + 8 /*data atom header */  +
1634                 8 /*flags + reserved */  + 8 /*actual data */ );
1635         membuffer_write_atom_name(buf, name);
1636         membuffer_write_int32(buf,
1637                 8 /*data atom header */  +
1638                 8 /*flags + reserved */  + 8 /*actual data */ );
1639         membuffer_write_atom_name(buf, "data");
1640         membuffer_write_int32(buf, 0);  //flags
1641         membuffer_write_int32(buf, 0);  //reserved
1642         membuffer_write_int16(buf, 0);
1643         membuffer_write_int16(buf, (uint16_t) index);   //track number
1644         membuffer_write_int16(buf, (uint16_t) total);   //total tracks
1645         membuffer_write_int16(buf, 0);
1646 }
1647
1648 static void membuffer_write_int16_tag(struct membuffer *buf, const char *name,
1649                 uint16_t value)
1650 {
1651         membuffer_write_int32(buf,
1652                 8 /*atom header */  + 8 /*data atom header */  +
1653                 8 /*flags + reserved */  + 2 /*actual data */ );
1654         membuffer_write_atom_name(buf, name);
1655         membuffer_write_int32(buf,
1656                 8 /*data atom header */  +
1657                 8 /*flags + reserved */  + 2 /*actual data */ );
1658         membuffer_write_atom_name(buf, "data");
1659         membuffer_write_int32(buf, 0);  //flags
1660         membuffer_write_int32(buf, 0);  //reserved
1661         membuffer_write_int16(buf, value);      //value
1662 }
1663
1664 static uint32_t myatoi(const char *param)
1665 {
1666         return param ? atoi(param) : 0;
1667 }
1668
1669 static uint32_t meta_genre_to_index(const char *genrestr)
1670 {
1671         unsigned n;
1672         for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
1673                 if (!strcasecmp(genrestr, ID3v1GenreList[n]))
1674                         return n + 1;
1675         }
1676         return 0;
1677 }
1678
1679 struct stdmeta_entry {
1680         const char *atom;
1681         const char *name;
1682 };
1683
1684 struct stdmeta_entry stdmetas[] = {
1685         {"\xA9" "nam", "title"},
1686         {"\xA9" "ART", "artist"},
1687         {"\xA9" "wrt", "writer"},
1688         {"\xA9" "alb", "album"},
1689         {"\xA9" "day", "date"},
1690         {"\xA9" "too", "tool"},
1691         {"\xA9" "cmt", "comment"},
1692         {"cpil", "compilation"},
1693         {"covr", "cover"},
1694         {"aART", "album_artist"},
1695 };
1696
1697 static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
1698 {
1699         unsigned n;
1700         for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
1701                 if (!strcasecmp(name, stdmetas[n].name))
1702                         return stdmetas[n].atom;
1703         }
1704         return 0;
1705 }
1706
1707 static void membuffer_write_std_tag(struct membuffer *buf, const char *name,
1708                 const char *value)
1709 {
1710         uint32_t flags = 1;
1711
1712         /* special check for compilation flag */
1713         if (strcmp(name, "cpil") == 0) {
1714                 flags = 21;
1715         }
1716
1717         membuffer_write_int32(buf,
1718                 8 /*atom header */  + 8 /*data atom header */  +
1719                 8 /*flags + reserved */  + strlen(value));
1720         membuffer_write_atom_name(buf, name);
1721         membuffer_write_int32(buf,
1722                 8 /*data atom header */  +
1723                 8 /*flags + reserved */  + strlen(value));
1724         membuffer_write_atom_name(buf, "data");
1725         membuffer_write_int32(buf, flags);      //flags
1726         membuffer_write_int32(buf, 0);  //reserved
1727         membuffer_write(buf, value, strlen(value));
1728 }
1729
1730 static void membuffer_write_custom_tag(struct membuffer *buf, const char *name,
1731                 const char *value)
1732 {
1733         membuffer_write_int32(buf,
1734                 8 /*atom header */  +
1735                 0x1C /*weirdo itunes atom */  +
1736                 12 /*name atom header */  + strlen(name) +
1737                 16 /*data atom header + flags */  + strlen(value));
1738         membuffer_write_atom_name(buf, "----");
1739         membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
1740         membuffer_write_atom_name(buf, "mean");
1741         membuffer_write_int32(buf, 0);
1742         membuffer_write(buf, "com.apple.iTunes", 16);
1743         membuffer_write_int32(buf, 12 + strlen(name));
1744         membuffer_write_atom_name(buf, "name");
1745         membuffer_write_int32(buf, 0);
1746         membuffer_write(buf, name, strlen(name));
1747         membuffer_write_int32(buf,
1748                 8 /*data atom header */  +
1749                 8 /*flags + reserved */  + strlen(value));
1750         membuffer_write_atom_name(buf, "data");
1751         membuffer_write_int32(buf, 1);  //flags
1752         membuffer_write_int32(buf, 0);  //reserved
1753         membuffer_write(buf, value, strlen(value));
1754 }
1755
1756 static unsigned membuffer_error(const struct membuffer *buf)
1757 {
1758         return buf->error;
1759 }
1760
1761 static void membuffer_free(struct membuffer *buf)
1762 {
1763         free(buf->data);
1764         free(buf);
1765 }
1766
1767 static unsigned membuffer_get_size(const struct membuffer *buf)
1768 {
1769         return buf->written;
1770 }
1771
1772 static void *membuffer_detach(struct membuffer *buf)
1773 {
1774         void *ret;
1775
1776         if (buf->error)
1777                 return 0;
1778
1779         ret = realloc(buf->data, buf->written);
1780
1781         if (ret == 0)
1782                 free(buf->data);
1783
1784         buf->data = 0;
1785         buf->error = 1;
1786
1787         return ret;
1788 }
1789
1790 static uint32_t create_ilst(const struct mp4ff_metadata *data, void **out_buffer,
1791                 uint32_t * out_size)
1792 {
1793         struct membuffer *buf = membuffer_create();
1794         unsigned metaptr;
1795         char *mask = para_calloc(data->count);
1796         const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1797         const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1798         const char *genre_ptr = 0, *tempo_ptr = 0;
1799
1800         for (metaptr = 0; metaptr < data->count; metaptr++) {
1801                 struct mp4ff_tag *tag = &data->tags[metaptr];
1802                 if (!strcasecmp(tag->item, "tracknumber")
1803                                 || !strcasecmp(tag->item, "track")) {
1804                         if (tracknumber_ptr == 0)
1805                                 tracknumber_ptr = tag->value;
1806                         mask[metaptr] = 1;
1807                 } else if (!strcasecmp(tag->item, "totaltracks")) {
1808                         if (totaltracks_ptr == 0)
1809                                 totaltracks_ptr = tag->value;
1810                         mask[metaptr] = 1;
1811                 } else if (!strcasecmp(tag->item, "discnumber")
1812                                 || !strcasecmp(tag->item, "disc")) {
1813                         if (discnumber_ptr == 0)
1814                                 discnumber_ptr = tag->value;
1815                         mask[metaptr] = 1;
1816                 } else if (!strcasecmp(tag->item, "totaldiscs")) {
1817                         if (totaldiscs_ptr == 0)
1818                                 totaldiscs_ptr = tag->value;
1819                         mask[metaptr] = 1;
1820                 } else if (!strcasecmp(tag->item, "genre")) {
1821                         if (genre_ptr == 0)
1822                                 genre_ptr = tag->value;
1823                         mask[metaptr] = 1;
1824                 } else if (!strcasecmp(tag->item, "tempo")) {
1825                         if (tempo_ptr == 0)
1826                                 tempo_ptr = tag->value;
1827                         mask[metaptr] = 1;
1828                 }
1829         }
1830
1831         if (tracknumber_ptr)
1832                 membuffer_write_track_tag(buf, "trkn", myatoi(tracknumber_ptr),
1833                          myatoi(totaltracks_ptr));
1834         if (discnumber_ptr)
1835                 membuffer_write_track_tag(buf, "disk", myatoi(discnumber_ptr),
1836                          myatoi(totaldiscs_ptr));
1837         if (tempo_ptr)
1838                 membuffer_write_int16_tag(buf, "tmpo", myatoi(tempo_ptr));
1839
1840         if (genre_ptr) {
1841                 uint32_t index = meta_genre_to_index(genre_ptr);
1842                 if (index == 0)
1843                         membuffer_write_std_tag(buf, "©gen", genre_ptr);
1844                 else
1845                         membuffer_write_int16_tag(buf, "gnre", index);
1846         }
1847         for (metaptr = 0; metaptr < data->count; metaptr++) {
1848                 struct mp4ff_tag *tag;
1849                 const char *std_meta_atom;
1850
1851                 if (mask[metaptr])
1852                         continue;
1853                 tag = &data->tags[metaptr];
1854                 std_meta_atom = find_standard_meta(tag->item);
1855                 if (std_meta_atom)
1856                         membuffer_write_std_tag(buf, std_meta_atom, tag->value);
1857                 else
1858                         membuffer_write_custom_tag(buf, tag->item, tag->value);
1859         }
1860         free(mask);
1861
1862         if (membuffer_error(buf)) {
1863                 membuffer_free(buf);
1864                 return 0;
1865         }
1866
1867         *out_size = membuffer_get_size(buf);
1868         *out_buffer = membuffer_detach(buf);
1869         membuffer_free(buf);
1870
1871         return 1;
1872 }
1873
1874 static void membuffer_write_atom(struct membuffer *buf, const char *name, unsigned size,
1875                           const void *data)
1876 {
1877         membuffer_write_int32(buf, size + 8);
1878         membuffer_write_atom_name(buf, name);
1879         membuffer_write(buf, data, size);
1880 }
1881
1882 static void *membuffer_get_ptr(const struct membuffer *buf)
1883 {
1884         return buf->data;
1885 }
1886
1887 static void membuffer_set_error(struct membuffer *buf)
1888 {
1889         buf->error = 1;
1890 }
1891
1892 static unsigned membuffer_transfer_from_file(struct membuffer *buf, struct mp4ff *src,
1893                 unsigned bytes)
1894 {
1895         unsigned oldsize;
1896         void *bufptr;
1897
1898         oldsize = membuffer_get_size(buf);
1899         if (membuffer_write(buf, 0, bytes) != bytes)
1900                 return 0;
1901
1902         bufptr = membuffer_get_ptr(buf);
1903         if (bufptr == 0)
1904                 return 0;
1905
1906         if ((unsigned)read_data(src, (char *) bufptr + oldsize, bytes) !=
1907                 bytes) {
1908                 membuffer_set_error(buf);
1909                 return 0;
1910         }
1911
1912         return bytes;
1913 }
1914
1915 static uint32_t create_meta(const struct mp4ff_metadata *data, void **out_buffer,
1916                 uint32_t * out_size)
1917 {
1918         struct membuffer *buf;
1919         uint32_t ilst_size;
1920         void *ilst_buffer;
1921
1922         if (!create_ilst(data, &ilst_buffer, &ilst_size))
1923                 return 0;
1924
1925         buf = membuffer_create();
1926
1927         membuffer_write_int32(buf, 0);
1928         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
1929         free(ilst_buffer);
1930
1931         *out_size = membuffer_get_size(buf);
1932         *out_buffer = membuffer_detach(buf);
1933         membuffer_free(buf);
1934         return 1;
1935 }
1936
1937 static uint32_t create_udta(const struct mp4ff_metadata *data, void **out_buffer,
1938 uint32_t * out_size)
1939 {
1940         struct membuffer *buf;
1941         uint32_t meta_size;
1942         void *meta_buffer;
1943
1944         if (!create_meta(data, &meta_buffer, &meta_size))
1945                 return 0;
1946
1947         buf = membuffer_create();
1948
1949         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
1950
1951         free(meta_buffer);
1952
1953         *out_size = membuffer_get_size(buf);
1954         *out_buffer = membuffer_detach(buf);
1955         membuffer_free(buf);
1956         return 1;
1957 }
1958
1959 static uint32_t fix_byte_order_32(uint32_t src)
1960 {
1961         return read_u32_be(&src);
1962 }
1963
1964 static uint32_t modify_moov(struct mp4ff *f, const struct mp4ff_metadata *data,
1965                 void **out_buffer, uint32_t * out_size)
1966 {
1967         uint64_t total_base = f->moov_offset + 8;
1968         uint32_t total_size = (uint32_t) (f->moov_size - 8);
1969
1970         uint64_t udta_offset, meta_offset, ilst_offset;
1971         uint32_t udta_size, meta_size, ilst_size;
1972
1973         uint32_t new_ilst_size;
1974         void *new_ilst_buffer;
1975
1976         uint8_t *p_out;
1977         int32_t size_delta;
1978
1979         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
1980                 struct membuffer *buf;
1981                 void *new_udta_buffer;
1982                 uint32_t new_udta_size;
1983                 if (!create_udta(data, &new_udta_buffer, &new_udta_size))
1984                         return 0;
1985
1986                 buf = membuffer_create();
1987                 set_position(f, total_base);
1988                 membuffer_transfer_from_file(buf, f, total_size);
1989
1990                 membuffer_write_atom(buf, "udta", new_udta_size,
1991                         new_udta_buffer);
1992
1993                 free(new_udta_buffer);
1994
1995                 *out_size = membuffer_get_size(buf);
1996                 *out_buffer = membuffer_detach(buf);
1997                 membuffer_free(buf);
1998                 return 1;
1999         } else {
2000                 udta_offset = get_position(f);
2001                 udta_size = read_int32(f);
2002                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
2003                         struct membuffer *buf;
2004                         void *new_meta_buffer;
2005                         uint32_t new_meta_size;
2006                         if (!create_meta(data, &new_meta_buffer, &new_meta_size))
2007                                 return 0;
2008
2009                         buf = membuffer_create();
2010                         set_position(f, total_base);
2011                         membuffer_transfer_from_file(buf, f,
2012                                 (uint32_t)(udta_offset - total_base));
2013
2014                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
2015                         membuffer_write_atom_name(buf, "udta");
2016                         membuffer_transfer_from_file(buf, f, udta_size);
2017
2018                         membuffer_write_atom(buf, "meta", new_meta_size,
2019                                 new_meta_buffer);
2020                         free(new_meta_buffer);
2021
2022                         *out_size = membuffer_get_size(buf);
2023                         *out_buffer = membuffer_detach(buf);
2024                         membuffer_free(buf);
2025                         return 1;
2026                 }
2027                 meta_offset = get_position(f);
2028                 meta_size = read_int32(f);
2029                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
2030                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
2031                 ilst_offset = get_position(f);
2032                 ilst_size = read_int32(f);
2033
2034                 if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
2035                         return 0;
2036
2037                 size_delta = new_ilst_size - (ilst_size - 8);
2038
2039                 *out_size = total_size + size_delta;
2040                 *out_buffer = para_malloc(*out_size);
2041                 p_out = (uint8_t *) * out_buffer;
2042
2043                 set_position(f, total_base);
2044                 read_data(f, p_out,
2045                                 (uint32_t) (udta_offset - total_base));
2046                 p_out += (uint32_t) (udta_offset - total_base);
2047                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
2048                 p_out += 4;
2049                 read_data(f, p_out, 4);
2050                 p_out += 4;
2051                 read_data(f, p_out,
2052                                 (uint32_t) (meta_offset - udta_offset - 8));
2053                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
2054                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
2055                 p_out += 4;
2056                 read_data(f, p_out, 4);
2057                 p_out += 4;
2058                 read_data(f, p_out,
2059                                 (uint32_t) (ilst_offset - meta_offset - 8));
2060                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
2061                 *(uint32_t *) p_out = fix_byte_order_32(read_int32(f) + size_delta);
2062                 p_out += 4;
2063                 read_data(f, p_out, 4);
2064                 p_out += 4;
2065
2066                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
2067                 p_out += new_ilst_size;
2068
2069                 set_position(f, ilst_offset + ilst_size);
2070                 read_data(f, p_out, (uint32_t) (total_size
2071                         - (ilst_offset - total_base) - ilst_size));
2072
2073                 free(new_ilst_buffer);
2074         }
2075         return 1;
2076 }
2077
2078 static int32_t write_data(struct mp4ff *f, void *data, uint32_t size)
2079 {
2080         int32_t result = 1;
2081
2082         result = f->stream->write(f->stream->user_data, data, size);
2083
2084         f->current_position += size;
2085
2086         return result;
2087 }
2088
2089 static int32_t write_int32(struct mp4ff *f, const uint32_t data)
2090 {
2091         int8_t temp[4];
2092         write_u32_be(temp, data);
2093         return write_data(f, temp, sizeof(temp));
2094 }
2095
2096 static int32_t truncate_stream(struct mp4ff *f)
2097 {
2098         return f->stream->truncate(f->stream->user_data);
2099 }
2100
2101 int32_t mp4ff_meta_update(struct mp4ff_callback *f, const struct mp4ff_metadata *data)
2102 {
2103         void *new_moov_data;
2104         uint32_t new_moov_size;
2105
2106         struct mp4ff *ff = para_calloc(sizeof(struct mp4ff));
2107         ff->stream = f;
2108         set_position(ff, 0);
2109
2110         parse_atoms(ff, 1);
2111
2112         if (!modify_moov(ff, data, &new_moov_data, &new_moov_size)) {
2113                 mp4ff_close(ff);
2114                 return 0;
2115         }
2116
2117         /* copy moov atom to end of the file */
2118         if (ff->last_atom != ATOM_MOOV) {
2119                 char *free_data = "free";
2120
2121                 /* rename old moov to free */
2122                 set_position(ff, ff->moov_offset + 4);
2123                 write_data(ff, free_data, 4);
2124
2125                 set_position(ff, ff->file_size);
2126                 write_int32(ff, new_moov_size + 8);
2127                 write_data(ff, "moov", 4);
2128                 write_data(ff, new_moov_data, new_moov_size);
2129         } else {
2130                 set_position(ff, ff->moov_offset);
2131                 write_int32(ff, new_moov_size + 8);
2132                 write_data(ff, "moov", 4);
2133                 write_data(ff, new_moov_data, new_moov_size);
2134         }
2135
2136         truncate_stream(ff);
2137
2138         mp4ff_close(ff);
2139         return 1;
2140 }
2141
2142 /* find a metadata item by name */
2143 /* returns 0 if item found, 1 if no such item */
2144 static int32_t meta_find_by_name(const struct mp4ff *f, const char *item,
2145                 char **value)
2146 {
2147         uint32_t i;
2148
2149         for (i = 0; i < f->tags.count; i++) {
2150                 if (!strcasecmp(f->tags.tags[i].item, item)) {
2151                         *value = para_strdup(f->tags.tags[i].value);
2152                         return 1;
2153                 }
2154         }
2155
2156         *value = NULL;
2157
2158         /* not found */
2159         return 0;
2160 }
2161
2162 int32_t mp4ff_meta_get_artist(const struct mp4ff *f, char **value)
2163 {
2164         return meta_find_by_name(f, "artist", value);
2165 }
2166
2167 int32_t mp4ff_meta_get_title(const struct mp4ff *f, char **value)
2168 {
2169         return meta_find_by_name(f, "title", value);
2170 }
2171
2172 int32_t mp4ff_meta_get_date(const struct mp4ff *f, char **value)
2173 {
2174         return meta_find_by_name(f, "date", value);
2175 }
2176
2177 int32_t mp4ff_meta_get_album(const struct mp4ff *f, char **value)
2178 {
2179         return meta_find_by_name(f, "album", value);
2180 }
2181
2182 int32_t mp4ff_meta_get_comment(const struct mp4ff *f, char **value)
2183 {
2184         return meta_find_by_name(f, "comment", value);
2185 }