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