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