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