]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
mp4: Use a for-loop in mp4ff_parse_tag().
[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 int32_t mp4ff_parse_tag(mp4ff_t * f, const uint8_t parent_atom_type,
956                 const int32_t size)
957 {
958         uint8_t atom_type;
959         uint8_t header_size = 0;
960         uint64_t subsize, sumsize;
961         char *name = NULL;
962         char *data = NULL;
963         uint32_t done = 0;
964         uint32_t len = 0;
965         uint64_t destpos;
966
967         for (
968                 sumsize = 0;
969                 sumsize < size && !f->stream->read_error; /* CVE-2017-9222 */
970                 mp4ff_set_position(f, destpos), sumsize += subsize
971         ) {
972                 subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
973                 destpos = mp4ff_position(f) + subsize - header_size;
974                 if (done)
975                         continue;
976                 if (atom_type == ATOM_DATA) {
977                         mp4ff_read_char(f);     /* version */
978                         mp4ff_read_int24(f);    /* flags */
979                         mp4ff_read_int32(f);    /* reserved */
980
981                         /* some need special attention */
982                         if (parent_atom_type == ATOM_GENRE2 || parent_atom_type == ATOM_TEMPO) {
983                                 if (subsize - header_size >= 8 + 2) {
984                                         uint16_t val = mp4ff_read_int16(f);
985
986                                         if (parent_atom_type == ATOM_TEMPO) {
987                                                 char temp[16];
988                                                 sprintf(temp,
989                                                         "%.5u BPM",
990                                                         val);
991                                                 mp4ff_tag_add_field(&(f-> tags), "tempo", temp, -1);
992                                         } else {
993                                                 const char *temp = mp4ff_meta_index_to_genre(val);
994                                                 if (temp) {
995                                                         mp4ff_tag_add_field (&(f->tags), "genre", temp, -1);
996                                                 }
997                                         }
998                                         done = 1;
999                                 }
1000                         } else if (parent_atom_type == ATOM_TRACK || parent_atom_type == ATOM_DISC) {
1001                                 if (!done && (subsize - header_size) >= (sizeof (char) + sizeof (uint8_t) * 3 + sizeof (uint32_t) +     /* version + flags + reserved */
1002                                                                          +(parent_atom_type == ATOM_TRACK ? sizeof (uint16_t) : 0)      /* leading uint16_t if ATOM_TRACK */
1003                                                                          +sizeof (uint16_t)     /* track / disc */
1004                                                                          +sizeof (uint16_t))    /* totaltracks / totaldiscs */) {
1005                                         uint16_t index, total;
1006                                         char temp[32];
1007                                         mp4ff_read_int16(f);
1008                                         index = mp4ff_read_int16(f);
1009                                         total = mp4ff_read_int16(f);
1010                                         if (parent_atom_type == ATOM_TRACK)
1011                                                 mp4ff_read_int16(f);
1012
1013                                         sprintf(temp, "%d", index);
1014                                         mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ?
1015                                                 "track" : "disc", temp, -1);
1016                                         if (total > 0) {
1017                                                 sprintf(temp, "%d",
1018                                                         total);
1019                                                 mp4ff_tag_add_field(& (f-> tags),
1020                                                         parent_atom_type == ATOM_TRACK?
1021                                                         "totaltracks" : "totaldiscs", temp, -1);
1022                                         }
1023                                         done = 1;
1024                                 }
1025                         } else {
1026                                 free(data);
1027                                 data = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 8)));
1028                                 len = (uint32_t) (subsize - (header_size + 8));
1029                         }
1030                 } else if (atom_type == ATOM_NAME) {
1031                         if (!done) {
1032                                 mp4ff_read_char(f);     /* version */
1033                                 mp4ff_read_int24(f);    /* flags */
1034                                 free(name);
1035                                 name = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 4)));
1036                         }
1037                 }
1038         }
1039
1040         if (data) {
1041                 if (!done) {
1042                         if (name == NULL)
1043                                 mp4ff_set_metadata_name(parent_atom_type, &name);
1044                         if (name)
1045                                 mp4ff_tag_add_field(&(f->tags), name, data, len);
1046                 }
1047
1048                 free(data);
1049         }
1050         free(name);
1051         return 1;
1052 }
1053
1054 static int32_t mp4ff_read_mdhd(mp4ff_t * f)
1055 {
1056         uint32_t version;
1057
1058         /* CVE-2017-9221 */
1059         if (f->total_tracks == 0)
1060                 return f->error++;
1061
1062         version = mp4ff_read_int32(f);
1063         if (version == 1) {
1064                 mp4ff_read_int64(f);    //creation-time
1065                 mp4ff_read_int64(f);    //modification-time
1066                 f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f); //timescale
1067                 f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);  //duration
1068         } else                  //version == 0
1069         {
1070                 uint32_t temp;
1071
1072                 mp4ff_read_int32(f);    //creation-time
1073                 mp4ff_read_int32(f);    //modification-time
1074                 f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f); //timescale
1075                 temp = mp4ff_read_int32(f);
1076                 f->track[f->total_tracks - 1]->duration = (temp == (uint32_t) (-1)) ? (uint64_t) (-1) : (uint64_t) (temp);
1077         }
1078         mp4ff_read_int16(f);
1079         mp4ff_read_int16(f);
1080         return 1;
1081 }
1082
1083 static int32_t mp4ff_parse_metadata(mp4ff_t * f, const int32_t size)
1084 {
1085         uint64_t subsize, sumsize = 0;
1086         uint8_t atom_type;
1087         uint8_t header_size = 0;
1088
1089         while (sumsize < size) {
1090                 subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
1091                 if (subsize == 0)
1092                         break;
1093                 mp4ff_parse_tag(f, atom_type,
1094                                 (uint32_t) (subsize - header_size));
1095                 sumsize += subsize;
1096         }
1097
1098         return 0;
1099 }
1100
1101 static int32_t mp4ff_read_meta(mp4ff_t * f, const uint64_t size)
1102 {
1103         uint64_t subsize, sumsize = 0;
1104         uint8_t atom_type;
1105         uint8_t header_size = 0;
1106
1107         mp4ff_read_char(f);     /* version */
1108         mp4ff_read_int24(f);    /* flags */
1109
1110         while (sumsize < (size - (header_size + 4))) {
1111                 subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
1112                 if (subsize <= header_size + 4)
1113                         return 1;
1114                 if (atom_type == ATOM_ILST) {
1115                         mp4ff_parse_metadata(f, (uint32_t) (subsize - (header_size + 4)));
1116                 } else {
1117                         mp4ff_set_position(f, mp4ff_position(f) + subsize - header_size);
1118                 }
1119                 sumsize += subsize;
1120         }
1121
1122         return 0;
1123 }
1124
1125 static int32_t mp4ff_atom_read(mp4ff_t * f, const int32_t size,
1126                         const uint8_t atom_type)
1127 {
1128         uint64_t dest_position = mp4ff_position(f) + size - 8;
1129         if (atom_type == ATOM_STSZ) {
1130                 /* sample size box */
1131                 mp4ff_read_stsz(f);
1132         } else if (atom_type == ATOM_STTS) {
1133                 /* time to sample box */
1134                 mp4ff_read_stts(f);
1135         } else if (atom_type == ATOM_CTTS) {
1136                 /* composition offset box */
1137                 mp4ff_read_ctts(f);
1138         } else if (atom_type == ATOM_STSC) {
1139                 /* sample to chunk box */
1140                 mp4ff_read_stsc(f);
1141         } else if (atom_type == ATOM_STCO) {
1142                 /* chunk offset box */
1143                 mp4ff_read_stco(f);
1144         } else if (atom_type == ATOM_STSD) {
1145                 /* sample description box */
1146                 mp4ff_read_stsd(f);
1147         } else if (atom_type == ATOM_MVHD) {
1148                 /* movie header box */
1149                 mp4ff_read_mvhd(f);
1150         } else if (atom_type == ATOM_MDHD) {
1151                 /* track header */
1152                 mp4ff_read_mdhd(f);
1153         } else if (atom_type == ATOM_META) {
1154                 /* iTunes Metadata box */
1155                 mp4ff_read_meta(f, size);
1156         }
1157
1158         mp4ff_set_position(f, dest_position);
1159         return 0;
1160 }
1161
1162 /* parse atoms that are sub atoms of other atoms */
1163 static int32_t parse_sub_atoms(mp4ff_t * f, const uint64_t total_size, int meta_only)
1164 {
1165         uint64_t size;
1166         uint8_t atom_type = 0;
1167         uint64_t counted_size = 0;
1168         uint8_t header_size = 0;
1169
1170         while (counted_size < total_size) {
1171                 size = mp4ff_atom_read_header(f, &atom_type, &header_size);
1172                 counted_size += size;
1173
1174                 /* check for end of file */
1175                 if (size == 0)
1176                         break;
1177
1178                 /* we're starting to read a new track, update index,
1179                  * so that all data and tables get written in the right place
1180                  */
1181                 if (atom_type == ATOM_TRAK) {
1182                         mp4ff_track_add(f);
1183                 }
1184
1185                 /* parse subatoms */
1186                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1187                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1188                 } else if (atom_type < SUBATOMIC) {
1189                         parse_sub_atoms(f, size - header_size, meta_only);
1190                 } else {
1191                         mp4ff_atom_read(f, (uint32_t) size, atom_type);
1192                 }
1193         }
1194
1195         return 0;
1196 }
1197
1198 /* parse root atoms */
1199 static int32_t parse_atoms(mp4ff_t * f, int meta_only)
1200 {
1201         uint64_t size;
1202         uint8_t atom_type = 0;
1203         uint8_t header_size = 0;
1204
1205         f->file_size = 0;
1206         f->stream->read_error = 0;
1207
1208         while ((size =
1209                 mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0) {
1210                 f->file_size += size;
1211                 f->last_atom = atom_type;
1212
1213                 if (atom_type == ATOM_MOOV && size > header_size) {
1214                         f->moov_offset = mp4ff_position(f) - header_size;
1215                         f->moov_size = size;
1216                 }
1217
1218                 /* parse subatoms */
1219                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1220                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1221                 } else if (atom_type < SUBATOMIC) {
1222                         parse_sub_atoms(f, size - header_size, meta_only);
1223                 } else {
1224                         /* skip this atom */
1225                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1226                 }
1227         }
1228
1229         return 0;
1230 }
1231
1232 void mp4ff_get_decoder_config(const mp4ff_t * f, const int track,
1233                                  unsigned char **ppBuf, unsigned int *pBufSize)
1234 {
1235         if (track >= f->total_tracks) {
1236                 *ppBuf = NULL;
1237                 *pBufSize = 0;
1238                 return;
1239         }
1240
1241         if (f->track[track]->decoderConfig == NULL
1242                 || f->track[track]->decoderConfigLen == 0) {
1243                 *ppBuf = NULL;
1244                 *pBufSize = 0;
1245         } else {
1246                 *ppBuf = para_malloc(f->track[track]->decoderConfigLen);
1247                 memcpy(*ppBuf, f->track[track]->decoderConfig,
1248                         f->track[track]->decoderConfigLen);
1249                 *pBufSize = f->track[track]->decoderConfigLen;
1250         }
1251 }
1252
1253 mp4ff_t *mp4ff_open_read(mp4ff_callback_t * f)
1254 {
1255         mp4ff_t *ff = para_calloc(sizeof(mp4ff_t));
1256
1257         ff->stream = f;
1258
1259         parse_atoms(ff, 0);
1260
1261         if (ff->error) {
1262                 free(ff);
1263                 ff = NULL;
1264         }
1265
1266         return ff;
1267 }
1268
1269 static int32_t mp4ff_tag_delete(mp4ff_metadata_t * tags)
1270 {
1271         uint32_t i;
1272
1273         for (i = 0; i < tags->count; i++) {
1274                 free(tags->tags[i].item);
1275                 free(tags->tags[i].value);
1276         }
1277         free(tags->tags);
1278         tags->tags = NULL;
1279         tags->count = 0;
1280
1281         return 0;
1282 }
1283
1284 void mp4ff_close(mp4ff_t * ff)
1285 {
1286         int32_t i;
1287
1288         for (i = 0; i < ff->total_tracks; i++) {
1289                 if (ff->track[i]) {
1290                         free(ff->track[i]->stsz_table);
1291                         free(ff->track[i]->stts_sample_count);
1292                         free(ff->track[i]->stts_sample_delta);
1293                         free(ff->track[i]->stsc_first_chunk);
1294                         free(ff->track[i]->stsc_samples_per_chunk);
1295                         free(ff->track[i]->stsc_sample_desc_index);
1296                         free(ff->track[i]->stco_chunk_offset);
1297                         free(ff->track[i]->decoderConfig);
1298                         free(ff->track[i]->ctts_sample_count);
1299                         free(ff->track[i]->ctts_sample_offset);
1300                         free(ff->track[i]);
1301                 }
1302         }
1303
1304         mp4ff_tag_delete(&(ff->tags));
1305         free(ff);
1306 }
1307
1308 static int32_t mp4ff_chunk_of_sample(const mp4ff_t * f, const int32_t track,
1309                 const int32_t sample, int32_t * chunk_sample, int32_t * chunk)
1310 {
1311         int32_t total_entries = 0;
1312         int32_t chunk2entry;
1313         int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
1314
1315         *chunk_sample = 0;
1316         *chunk = 1;
1317         if (f->track[track] == NULL) {
1318                 return -1;
1319         }
1320
1321         total_entries = f->track[track]->stsc_entry_count;
1322
1323         chunk1 = 1;
1324         chunk1samples = 0;
1325         chunk2entry = 0;
1326
1327         do {
1328                 chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
1329                 *chunk = chunk2 - chunk1;
1330                 range_samples = *chunk * chunk1samples;
1331
1332                 if (sample < total + range_samples)
1333                         break;
1334
1335                 chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
1336                 chunk1 = chunk2;
1337
1338                 if (chunk2entry < total_entries) {
1339                         chunk2entry++;
1340                         total += range_samples;
1341                 }
1342         } while (chunk2entry < total_entries);
1343
1344         if (chunk1samples)
1345                 *chunk = (sample - total) / chunk1samples + chunk1;
1346         else
1347                 *chunk = 1;
1348
1349         *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
1350
1351         return 0;
1352 }
1353
1354 static int32_t mp4ff_chunk_to_offset(const mp4ff_t * f, const int32_t track,
1355                 const int32_t chunk)
1356 {
1357         const mp4ff_track_t *p_track = f->track[track];
1358
1359         if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) {
1360                 return p_track->stco_chunk_offset[p_track->stco_entry_count -
1361                                                   1];
1362         } else if (p_track->stco_entry_count) {
1363                 return p_track->stco_chunk_offset[chunk - 1];
1364         } else {
1365                 return 8;
1366         }
1367
1368         return 0;
1369 }
1370
1371 static int32_t mp4ff_sample_range_size(const mp4ff_t * f, const int32_t track,
1372                 const int32_t chunk_sample, const int32_t sample)
1373 {
1374         int32_t i, total;
1375         const mp4ff_track_t *p_track = f->track[track];
1376
1377         if (p_track->stsz_sample_size) {
1378                 return (sample - chunk_sample) * p_track->stsz_sample_size;
1379         } else {
1380                 if (sample >= p_track->stsz_sample_count)
1381                         return 0;       //error
1382
1383                 for (i = chunk_sample, total = 0; i < sample; i++) {
1384                         total += p_track->stsz_table[i];
1385                 }
1386         }
1387
1388         return total;
1389 }
1390 static int32_t mp4ff_sample_to_offset(const mp4ff_t * f, const int32_t track,
1391                 const int32_t sample)
1392 {
1393         int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
1394
1395         mp4ff_chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
1396
1397         chunk_offset1 = mp4ff_chunk_to_offset(f, track, chunk);
1398         chunk_offset2 = chunk_offset1 + mp4ff_sample_range_size(f,
1399                 track, chunk_sample, sample);
1400         return chunk_offset2;
1401 }
1402
1403 void mp4ff_set_sample_position(mp4ff_t *f, const int32_t track,
1404                 const int32_t sample)
1405 {
1406         int32_t offset = mp4ff_sample_to_offset(f, track, sample);
1407         mp4ff_set_position(f, offset);
1408 }
1409
1410 int32_t mp4ff_get_sample_size(const mp4ff_t *f, int track, int sample)
1411 {
1412         const mp4ff_track_t *t = f->track[track];
1413
1414         if (t->stsz_sample_size != 0)
1415                 return t->stsz_sample_size;
1416         return t->stsz_table[sample];
1417 }
1418
1419 uint32_t mp4ff_get_sample_rate(const mp4ff_t * f, const int32_t track)
1420 {
1421         return f->track[track]->sampleRate;
1422 }
1423
1424 uint32_t mp4ff_get_channel_count(const mp4ff_t * f, const int32_t track)
1425 {
1426         return f->track[track]->channelCount;
1427 }
1428
1429 int32_t mp4ff_num_samples(const mp4ff_t * f, const int32_t track)
1430 {
1431         int32_t i;
1432         int32_t total = 0;
1433
1434         for (i = 0; i < f->track[track]->stts_entry_count; i++) {
1435                 total += f->track[track]->stts_sample_count[i];
1436         }
1437         return total;
1438 }
1439
1440 mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t * f)
1441 {
1442         mp4ff_t *ff = para_calloc(sizeof(mp4ff_t));
1443
1444         ff->stream = f;
1445
1446         parse_atoms(ff, 1);
1447
1448         if (ff->error) {
1449                 free(ff);
1450                 ff = NULL;
1451         }
1452
1453         return ff;
1454 }
1455
1456 int32_t mp4ff_meta_get_num_items(const mp4ff_t * f)
1457 {
1458         return f->tags.count;
1459 }
1460
1461 int32_t mp4ff_meta_get_by_index(const mp4ff_t * f, uint32_t index,
1462                                 char **item, char **value)
1463 {
1464         if (index >= f->tags.count) {
1465                 *item = NULL;
1466                 *value = NULL;
1467                 return 0;
1468         } else {
1469                 *item = para_strdup(f->tags.tags[index].item);
1470                 *value = para_strdup(f->tags.tags[index].value);
1471                 return 1;
1472         }
1473 }
1474
1475 static uint32_t find_atom(mp4ff_t * f, uint64_t base, uint32_t size,
1476                           const char *name)
1477 {
1478         uint32_t remaining = size;
1479         uint64_t atom_offset = base;
1480         for (;;) {
1481                 char atom_name[4];
1482                 uint32_t atom_size;
1483
1484                 mp4ff_set_position(f, atom_offset);
1485
1486                 if (remaining < 8)
1487                         break;
1488                 atom_size = mp4ff_read_int32(f);
1489                 if (atom_size > remaining || atom_size < 8)
1490                         break;
1491                 mp4ff_read_data(f, atom_name, 4);
1492
1493                 if (!memcmp(atom_name, name, 4)) {
1494                         mp4ff_set_position(f, atom_offset);
1495                         return 1;
1496                 }
1497
1498                 remaining -= atom_size;
1499                 atom_offset += atom_size;
1500         }
1501         return 0;
1502 }
1503 static uint32_t find_atom_v2(mp4ff_t * f, uint64_t base, uint32_t size,
1504                 const char *name, uint32_t extraheaders, const char *name_inside)
1505 {
1506         uint64_t first_base = (uint64_t) (-1);
1507         while (find_atom(f, base, size, name))  //try to find atom <name> with atom <name_inside> in it
1508         {
1509                 uint64_t mybase = mp4ff_position(f);
1510                 uint32_t mysize = mp4ff_read_int32(f);
1511
1512                 if (first_base == (uint64_t) (-1))
1513                         first_base = mybase;
1514
1515                 if (mysize < 8 + extraheaders)
1516                         break;
1517
1518                 if (find_atom (f, mybase + (8 + extraheaders),
1519                                 mysize - (8 + extraheaders), name_inside)) {
1520                         mp4ff_set_position(f, mybase);
1521                         return 2;
1522                 }
1523                 base += mysize;
1524                 if (size <= mysize) {
1525                         size = 0;
1526                         break;
1527                 }
1528                 size -= mysize;
1529         }
1530
1531         if (first_base != (uint64_t) (-1))      //wanted atom inside not found
1532         {
1533                 mp4ff_set_position(f, first_base);
1534                 return 1;
1535         } else
1536                 return 0;
1537 }
1538
1539 typedef struct {
1540         void *data;
1541         unsigned written;
1542         unsigned allocated;
1543         unsigned error;
1544 } membuffer;
1545
1546 #define stricmp strcasecmp
1547
1548 static membuffer *membuffer_create(void)
1549 {
1550         const unsigned initial_size = 256;
1551
1552         membuffer *buf = para_malloc(sizeof (membuffer));
1553         buf->data = para_malloc(initial_size);
1554         buf->written = 0;
1555         buf->allocated = initial_size;
1556         buf->error = buf->data == 0 ? 1 : 0;
1557
1558         return buf;
1559 }
1560
1561 static unsigned membuffer_write(membuffer * buf, const void *ptr, unsigned bytes)
1562 {
1563         unsigned dest_size = buf->written + bytes;
1564
1565         if (buf->error)
1566                 return 0;
1567         if (dest_size > buf->allocated) {
1568                 do {
1569                         buf->allocated <<= 1;
1570                 } while (dest_size > buf->allocated);
1571
1572                 {
1573                         void *newptr = realloc(buf->data, buf->allocated);
1574                         if (newptr == 0) {
1575                                 free(buf->data);
1576                                 buf->data = 0;
1577                                 buf->error = 1;
1578                                 return 0;
1579                         }
1580                         buf->data = newptr;
1581                 }
1582         }
1583
1584         if (ptr)
1585                 memcpy((char *) buf->data + buf->written, ptr, bytes);
1586         buf->written += bytes;
1587         return bytes;
1588 }
1589
1590 static unsigned membuffer_write_atom_name(membuffer * buf, const char *data)
1591 {
1592         return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
1593 }
1594
1595 static unsigned membuffer_write_int16(membuffer * buf, uint16_t data)
1596 {
1597         uint8_t temp[2] = { (uint8_t) (data >> 8), (uint8_t) data };
1598         return membuffer_write(buf, temp, 2);
1599 }
1600
1601 static unsigned membuffer_write_int32(membuffer * buf, uint32_t data)
1602 {
1603         uint8_t temp[4] = { (uint8_t) (data >> 24), (uint8_t) (data >> 16),
1604                 (uint8_t) (data >> 8), (uint8_t) data };
1605         return membuffer_write(buf, temp, 4);
1606 }
1607
1608 static void membuffer_write_track_tag(membuffer * buf, const char *name,
1609                 uint32_t index, uint32_t total)
1610 {
1611         membuffer_write_int32(buf,
1612                 8 /*atom header */  + 8 /*data atom header */  +
1613                 8 /*flags + reserved */  + 8 /*actual data */ );
1614         membuffer_write_atom_name(buf, name);
1615         membuffer_write_int32(buf,
1616                 8 /*data atom header */  +
1617                 8 /*flags + reserved */  + 8 /*actual data */ );
1618         membuffer_write_atom_name(buf, "data");
1619         membuffer_write_int32(buf, 0);  //flags
1620         membuffer_write_int32(buf, 0);  //reserved
1621         membuffer_write_int16(buf, 0);
1622         membuffer_write_int16(buf, (uint16_t) index);   //track number
1623         membuffer_write_int16(buf, (uint16_t) total);   //total tracks
1624         membuffer_write_int16(buf, 0);
1625 }
1626
1627 static void membuffer_write_int16_tag(membuffer * buf, const char *name,
1628                 uint16_t value)
1629 {
1630         membuffer_write_int32(buf,
1631                 8 /*atom header */  + 8 /*data atom header */  +
1632                 8 /*flags + reserved */  + 2 /*actual data */ );
1633         membuffer_write_atom_name(buf, name);
1634         membuffer_write_int32(buf,
1635                 8 /*data atom header */  +
1636                 8 /*flags + reserved */  + 2 /*actual data */ );
1637         membuffer_write_atom_name(buf, "data");
1638         membuffer_write_int32(buf, 0);  //flags
1639         membuffer_write_int32(buf, 0);  //reserved
1640         membuffer_write_int16(buf, value);      //value
1641 }
1642
1643 static uint32_t myatoi(const char *param)
1644 {
1645         return param ? atoi(param) : 0;
1646 }
1647
1648 static uint32_t mp4ff_meta_genre_to_index(const char *genrestr)
1649 {
1650         unsigned n;
1651         for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
1652                 if (!stricmp(genrestr, ID3v1GenreList[n]))
1653                         return n + 1;
1654         }
1655         return 0;
1656 }
1657
1658 typedef struct {
1659         const char *atom;
1660         const char *name;
1661 } stdmeta_entry;
1662
1663 static stdmeta_entry stdmetas[] = {
1664         {"\xA9" "nam", "title"},
1665         {"\xA9" "ART", "artist"},
1666         {"\xA9" "wrt", "writer"},
1667         {"\xA9" "alb", "album"},
1668         {"\xA9" "day", "date"},
1669         {"\xA9" "too", "tool"},
1670         {"\xA9" "cmt", "comment"},
1671         {"cpil", "compilation"},
1672         {"covr", "cover"},
1673         {"aART", "album_artist"},
1674 };
1675
1676 static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
1677 {
1678         unsigned n;
1679         for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
1680                 if (!stricmp(name, stdmetas[n].name))
1681                         return stdmetas[n].atom;
1682         }
1683         return 0;
1684 }
1685
1686 static void membuffer_write_std_tag(membuffer * buf, const char *name,
1687                 const char *value)
1688 {
1689         uint32_t flags = 1;
1690
1691         /* special check for compilation flag */
1692         if (strcmp(name, "cpil") == 0) {
1693                 flags = 21;
1694         }
1695
1696         membuffer_write_int32(buf,
1697                 8 /*atom header */  + 8 /*data atom header */  +
1698                 8 /*flags + reserved */  + strlen(value));
1699         membuffer_write_atom_name(buf, name);
1700         membuffer_write_int32(buf,
1701                 8 /*data atom header */  +
1702                 8 /*flags + reserved */  + strlen(value));
1703         membuffer_write_atom_name(buf, "data");
1704         membuffer_write_int32(buf, flags);      //flags
1705         membuffer_write_int32(buf, 0);  //reserved
1706         membuffer_write(buf, value, strlen(value));
1707 }
1708
1709 static void membuffer_write_custom_tag(membuffer * buf, const char *name,
1710                 const char *value)
1711 {
1712         membuffer_write_int32(buf,
1713                 8 /*atom header */  +
1714                 0x1C /*weirdo itunes atom */  +
1715                 12 /*name atom header */  + strlen(name) +
1716                 16 /*data atom header + flags */  + strlen(value));
1717         membuffer_write_atom_name(buf, "----");
1718         membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
1719         membuffer_write_atom_name(buf, "mean");
1720         membuffer_write_int32(buf, 0);
1721         membuffer_write(buf, "com.apple.iTunes", 16);
1722         membuffer_write_int32(buf, 12 + strlen(name));
1723         membuffer_write_atom_name(buf, "name");
1724         membuffer_write_int32(buf, 0);
1725         membuffer_write(buf, name, strlen(name));
1726         membuffer_write_int32(buf,
1727                 8 /*data atom header */  +
1728                 8 /*flags + reserved */  + strlen(value));
1729         membuffer_write_atom_name(buf, "data");
1730         membuffer_write_int32(buf, 1);  //flags
1731         membuffer_write_int32(buf, 0);  //reserved
1732         membuffer_write(buf, value, strlen(value));
1733 }
1734
1735 static unsigned membuffer_error(const membuffer * buf)
1736 {
1737         return buf->error;
1738 }
1739
1740 static void membuffer_free(membuffer * buf)
1741 {
1742         free(buf->data);
1743         free(buf);
1744 }
1745
1746 static unsigned membuffer_get_size(const membuffer * buf)
1747 {
1748         return buf->written;
1749 }
1750
1751 static void *membuffer_detach(membuffer * buf)
1752 {
1753         void *ret;
1754
1755         if (buf->error)
1756                 return 0;
1757
1758         ret = realloc(buf->data, buf->written);
1759
1760         if (ret == 0)
1761                 free(buf->data);
1762
1763         buf->data = 0;
1764         buf->error = 1;
1765
1766         return ret;
1767 }
1768
1769 static uint32_t create_ilst(const mp4ff_metadata_t * data, void **out_buffer,
1770                 uint32_t * out_size)
1771 {
1772         membuffer *buf = membuffer_create();
1773         unsigned metaptr;
1774         char *mask = para_calloc(data->count);
1775         {
1776                 const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1777                 const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1778                 const char *genre_ptr = 0, *tempo_ptr = 0;
1779                 for (metaptr = 0; metaptr < data->count; metaptr++) {
1780                         mp4ff_tag_t *tag = &data->tags[metaptr];
1781                         if (!stricmp(tag->item, "tracknumber") || !stricmp(tag->item, "track")) {
1782                                 if (tracknumber_ptr == 0)
1783                                         tracknumber_ptr = tag->value;
1784                                 mask[metaptr] = 1;
1785                         } else if (!stricmp(tag->item, "totaltracks")) {
1786                                 if (totaltracks_ptr == 0)
1787                                         totaltracks_ptr = tag->value;
1788                                 mask[metaptr] = 1;
1789                         } else if (!stricmp(tag->item, "discnumber")
1790                                         || !stricmp(tag->item, "disc")) {
1791                                 if (discnumber_ptr == 0)
1792                                         discnumber_ptr = tag->value;
1793                                 mask[metaptr] = 1;
1794                         } else if (!stricmp(tag->item, "totaldiscs")) {
1795                                 if (totaldiscs_ptr == 0)
1796                                         totaldiscs_ptr = tag->value;
1797                                 mask[metaptr] = 1;
1798                         } else if (!stricmp(tag->item, "genre")) {
1799                                 if (genre_ptr == 0)
1800                                         genre_ptr = tag->value;
1801                                 mask[metaptr] = 1;
1802                         } else if (!stricmp(tag->item, "tempo")) {
1803                                 if (tempo_ptr == 0)
1804                                         tempo_ptr = tag->value;
1805                                 mask[metaptr] = 1;
1806                         }
1807
1808                 }
1809
1810                 if (tracknumber_ptr)
1811                         membuffer_write_track_tag(buf, "trkn",
1812                                                   myatoi(tracknumber_ptr),
1813                                                   myatoi(totaltracks_ptr));
1814                 if (discnumber_ptr)
1815                         membuffer_write_track_tag(buf, "disk",
1816                                                   myatoi(discnumber_ptr),
1817                                                   myatoi(totaldiscs_ptr));
1818                 if (tempo_ptr)
1819                         membuffer_write_int16_tag(buf, "tmpo",
1820                                                   (uint16_t) myatoi(tempo_ptr));
1821
1822                 if (genre_ptr) {
1823                         uint32_t index = mp4ff_meta_genre_to_index(genre_ptr);
1824                         if (index == 0)
1825                                 membuffer_write_std_tag(buf, "©gen",
1826                                                         genre_ptr);
1827                         else
1828                                 membuffer_write_int16_tag(buf, "gnre",
1829                                                           (uint16_t) index);
1830                 }
1831         }
1832
1833         for (metaptr = 0; metaptr < data->count; metaptr++) {
1834                 if (!mask[metaptr]) {
1835                         mp4ff_tag_t *tag = &data->tags[metaptr];
1836                         const char *std_meta_atom = find_standard_meta(tag->item);
1837                         if (std_meta_atom) {
1838                                 membuffer_write_std_tag(buf, std_meta_atom,
1839                                                         tag->value);
1840                         } else {
1841                                 membuffer_write_custom_tag(buf, tag->item,
1842                                         tag->value);
1843                         }
1844                 }
1845         }
1846
1847         free(mask);
1848
1849         if (membuffer_error(buf)) {
1850                 membuffer_free(buf);
1851                 return 0;
1852         }
1853
1854         *out_size = membuffer_get_size(buf);
1855         *out_buffer = membuffer_detach(buf);
1856         membuffer_free(buf);
1857
1858         return 1;
1859 }
1860
1861 static void membuffer_write_atom(membuffer * buf, const char *name, unsigned size,
1862                           const void *data)
1863 {
1864         membuffer_write_int32(buf, size + 8);
1865         membuffer_write_atom_name(buf, name);
1866         membuffer_write(buf, data, size);
1867 }
1868
1869 static void *membuffer_get_ptr(const membuffer * buf)
1870 {
1871         return buf->data;
1872 }
1873
1874 static void membuffer_set_error(membuffer * buf)
1875 {
1876         buf->error = 1;
1877 }
1878
1879 static unsigned membuffer_transfer_from_file(membuffer * buf, mp4ff_t * src,
1880                 unsigned bytes)
1881 {
1882         unsigned oldsize;
1883         void *bufptr;
1884
1885         oldsize = membuffer_get_size(buf);
1886         if (membuffer_write(buf, 0, bytes) != bytes)
1887                 return 0;
1888
1889         bufptr = membuffer_get_ptr(buf);
1890         if (bufptr == 0)
1891                 return 0;
1892
1893         if ((unsigned) mp4ff_read_data(src, (char *) bufptr + oldsize, bytes) !=
1894                 bytes) {
1895                 membuffer_set_error(buf);
1896                 return 0;
1897         }
1898
1899         return bytes;
1900 }
1901
1902 static uint32_t create_meta(const mp4ff_metadata_t * data, void **out_buffer,
1903                 uint32_t * out_size)
1904 {
1905         membuffer *buf;
1906         uint32_t ilst_size;
1907         void *ilst_buffer;
1908
1909         if (!create_ilst(data, &ilst_buffer, &ilst_size))
1910                 return 0;
1911
1912         buf = membuffer_create();
1913
1914         membuffer_write_int32(buf, 0);
1915         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
1916         free(ilst_buffer);
1917
1918         *out_size = membuffer_get_size(buf);
1919         *out_buffer = membuffer_detach(buf);
1920         membuffer_free(buf);
1921         return 1;
1922 }
1923
1924 static uint32_t create_udta(const mp4ff_metadata_t * data, void **out_buffer,
1925 uint32_t * out_size)
1926 {
1927         membuffer *buf;
1928         uint32_t meta_size;
1929         void *meta_buffer;
1930
1931         if (!create_meta(data, &meta_buffer, &meta_size))
1932                 return 0;
1933
1934         buf = membuffer_create();
1935
1936         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
1937
1938         free(meta_buffer);
1939
1940         *out_size = membuffer_get_size(buf);
1941         *out_buffer = membuffer_detach(buf);
1942         membuffer_free(buf);
1943         return 1;
1944 }
1945
1946 static uint32_t fix_byte_order_32(uint32_t src)
1947 {
1948         uint32_t result;
1949         uint32_t a, b, c, d;
1950         int8_t data[4];
1951
1952         memcpy(data, &src, sizeof (src));
1953         a = (uint8_t) data[0];
1954         b = (uint8_t) data[1];
1955         c = (uint8_t) data[2];
1956         d = (uint8_t) data[3];
1957
1958         result = (a << 24) | (b << 16) | (c << 8) | d;
1959         return (uint32_t) result;
1960 }
1961
1962 static uint32_t modify_moov(mp4ff_t * f, const mp4ff_metadata_t * data,
1963                 void **out_buffer, uint32_t * out_size)
1964 {
1965         uint64_t total_base = f->moov_offset + 8;
1966         uint32_t total_size = (uint32_t) (f->moov_size - 8);
1967
1968         uint64_t udta_offset, meta_offset, ilst_offset;
1969         uint32_t udta_size, meta_size, ilst_size;
1970
1971         uint32_t new_ilst_size;
1972         void *new_ilst_buffer;
1973
1974         uint8_t *p_out;
1975         int32_t size_delta;
1976
1977         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
1978                 membuffer *buf;
1979                 void *new_udta_buffer;
1980                 uint32_t new_udta_size;
1981                 if (!create_udta(data, &new_udta_buffer, &new_udta_size))
1982                         return 0;
1983
1984                 buf = membuffer_create();
1985                 mp4ff_set_position(f, total_base);
1986                 membuffer_transfer_from_file(buf, f, total_size);
1987
1988                 membuffer_write_atom(buf, "udta", new_udta_size,
1989                         new_udta_buffer);
1990
1991                 free(new_udta_buffer);
1992
1993                 *out_size = membuffer_get_size(buf);
1994                 *out_buffer = membuffer_detach(buf);
1995                 membuffer_free(buf);
1996                 return 1;
1997         } else {
1998                 udta_offset = mp4ff_position(f);
1999                 udta_size = mp4ff_read_int32(f);
2000                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
2001                         membuffer *buf;
2002                         void *new_meta_buffer;
2003                         uint32_t new_meta_size;
2004                         if (!create_meta(data, &new_meta_buffer, &new_meta_size))
2005                                 return 0;
2006
2007                         buf = membuffer_create();
2008                         mp4ff_set_position(f, total_base);
2009                         membuffer_transfer_from_file(buf, f,
2010                                 (uint32_t)(udta_offset - total_base));
2011
2012                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
2013                         membuffer_write_atom_name(buf, "udta");
2014                         membuffer_transfer_from_file(buf, f, udta_size);
2015
2016                         membuffer_write_atom(buf, "meta", new_meta_size,
2017                                 new_meta_buffer);
2018                         free(new_meta_buffer);
2019
2020                         *out_size = membuffer_get_size(buf);
2021                         *out_buffer = membuffer_detach(buf);
2022                         membuffer_free(buf);
2023                         return 1;
2024                 }
2025                 meta_offset = mp4ff_position(f);
2026                 meta_size = mp4ff_read_int32(f);
2027                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
2028                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
2029                 ilst_offset = mp4ff_position(f);
2030                 ilst_size = mp4ff_read_int32(f);
2031
2032                 if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
2033                         return 0;
2034
2035                 size_delta = new_ilst_size - (ilst_size - 8);
2036
2037                 *out_size = total_size + size_delta;
2038                 *out_buffer = para_malloc(*out_size);
2039                 p_out = (uint8_t *) * out_buffer;
2040
2041                 mp4ff_set_position(f, total_base);
2042                 mp4ff_read_data(f, p_out,
2043                                 (uint32_t) (udta_offset - total_base));
2044                 p_out += (uint32_t) (udta_offset - total_base);
2045                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2046                 p_out += 4;
2047                 mp4ff_read_data(f, p_out, 4);
2048                 p_out += 4;
2049                 mp4ff_read_data(f, p_out,
2050                                 (uint32_t) (meta_offset - udta_offset - 8));
2051                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
2052                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2053                 p_out += 4;
2054                 mp4ff_read_data(f, p_out, 4);
2055                 p_out += 4;
2056                 mp4ff_read_data(f, p_out,
2057                                 (uint32_t) (ilst_offset - meta_offset - 8));
2058                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
2059                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2060                 p_out += 4;
2061                 mp4ff_read_data(f, p_out, 4);
2062                 p_out += 4;
2063
2064                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
2065                 p_out += new_ilst_size;
2066
2067                 mp4ff_set_position(f, ilst_offset + ilst_size);
2068                 mp4ff_read_data(f, p_out, (uint32_t) (total_size
2069                         - (ilst_offset - total_base) - ilst_size));
2070
2071                 free(new_ilst_buffer);
2072         }
2073         return 1;
2074 }
2075
2076 static int32_t mp4ff_write_data(mp4ff_t * f, void *data, uint32_t size)
2077 {
2078         int32_t result = 1;
2079
2080         result = f->stream->write(f->stream->user_data, data, size);
2081
2082         f->current_position += size;
2083
2084         return result;
2085 }
2086
2087 static int32_t mp4ff_write_int32(mp4ff_t * f, const uint32_t data)
2088 {
2089         uint32_t result;
2090         uint32_t a, b, c, d;
2091         int8_t temp[4];
2092
2093         *(uint32_t *) temp = data;
2094         a = (uint8_t) temp[0];
2095         b = (uint8_t) temp[1];
2096         c = (uint8_t) temp[2];
2097         d = (uint8_t) temp[3];
2098
2099         result = (a << 24) | (b << 16) | (c << 8) | d;
2100
2101         return mp4ff_write_data(f, (uint8_t *) & result, sizeof (result));
2102 }
2103
2104 static int32_t mp4ff_truncate(mp4ff_t * f)
2105 {
2106         return f->stream->truncate(f->stream->user_data);
2107 }
2108
2109 int32_t mp4ff_meta_update(mp4ff_callback_t * f, const mp4ff_metadata_t * data)
2110 {
2111         void *new_moov_data;
2112         uint32_t new_moov_size;
2113
2114         mp4ff_t *ff = para_calloc(sizeof(mp4ff_t));
2115         ff->stream = f;
2116         mp4ff_set_position(ff, 0);
2117
2118         parse_atoms(ff, 1);
2119
2120         if (!modify_moov(ff, data, &new_moov_data, &new_moov_size)) {
2121                 mp4ff_close(ff);
2122                 return 0;
2123         }
2124
2125         /* copy moov atom to end of the file */
2126         if (ff->last_atom != ATOM_MOOV) {
2127                 char *free_data = "free";
2128
2129                 /* rename old moov to free */
2130                 mp4ff_set_position(ff, ff->moov_offset + 4);
2131                 mp4ff_write_data(ff, free_data, 4);
2132
2133                 mp4ff_set_position(ff, ff->file_size);
2134                 mp4ff_write_int32(ff, new_moov_size + 8);
2135                 mp4ff_write_data(ff, "moov", 4);
2136                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2137         } else {
2138                 mp4ff_set_position(ff, ff->moov_offset);
2139                 mp4ff_write_int32(ff, new_moov_size + 8);
2140                 mp4ff_write_data(ff, "moov", 4);
2141                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2142         }
2143
2144         mp4ff_truncate(ff);
2145
2146         mp4ff_close(ff);
2147         return 1;
2148 }
2149
2150 /* find a metadata item by name */
2151 /* returns 0 if item found, 1 if no such item */
2152 static int32_t mp4ff_meta_find_by_name(const mp4ff_t * f, const char *item,
2153                 char **value)
2154 {
2155         uint32_t i;
2156
2157         for (i = 0; i < f->tags.count; i++) {
2158                 if (!stricmp(f->tags.tags[i].item, item)) {
2159                         *value = para_strdup(f->tags.tags[i].value);
2160                         return 1;
2161                 }
2162         }
2163
2164         *value = NULL;
2165
2166         /* not found */
2167         return 0;
2168 }
2169
2170 int32_t mp4ff_meta_get_artist(const mp4ff_t * f, char **value)
2171 {
2172         return mp4ff_meta_find_by_name(f, "artist", value);
2173 }
2174
2175 int32_t mp4ff_meta_get_title(const mp4ff_t * f, char **value)
2176 {
2177         return mp4ff_meta_find_by_name(f, "title", value);
2178 }
2179
2180 int32_t mp4ff_meta_get_date(const mp4ff_t * f, char **value)
2181 {
2182         return mp4ff_meta_find_by_name(f, "date", value);
2183 }
2184
2185 int32_t mp4ff_meta_get_album(const mp4ff_t * f, char **value)
2186 {
2187         return mp4ff_meta_find_by_name(f, "album", value);
2188 }
2189
2190 int32_t mp4ff_meta_get_comment(const mp4ff_t * f, char **value)
2191 {
2192         return mp4ff_meta_find_by_name(f, "comment", value);
2193 }