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