]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
aac: Let mp4ff_set_sample_position() return void.
[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 static int32_t mp4ff_audio_frame_size(const mp4ff_t * f, const int32_t track,
1513                 const int32_t sample)
1514 {
1515         int32_t bytes;
1516         const mp4ff_track_t *p_track = f->track[track];
1517
1518         if (p_track->stsz_sample_size) {
1519                 bytes = p_track->stsz_sample_size;
1520         } else {
1521                 bytes = p_track->stsz_table[sample];
1522         }
1523
1524         return bytes;
1525 }
1526
1527 int32_t mp4ff_read_sample_getsize(mp4ff_t * f, const int track,
1528                                   const int sample)
1529 {
1530         int32_t temp = mp4ff_audio_frame_size(f, track, sample);
1531         if (temp < 0)
1532                 temp = 0;
1533         return temp;
1534 }
1535
1536 uint32_t mp4ff_get_sample_rate(const mp4ff_t * f, const int32_t track)
1537 {
1538         return f->track[track]->sampleRate;
1539 }
1540
1541 uint32_t mp4ff_get_channel_count(const mp4ff_t * f, const int32_t track)
1542 {
1543         return f->track[track]->channelCount;
1544 }
1545
1546 int32_t mp4ff_num_samples(const mp4ff_t * f, const int32_t track)
1547 {
1548         int32_t i;
1549         int32_t total = 0;
1550
1551         for (i = 0; i < f->track[track]->stts_entry_count; i++) {
1552                 total += f->track[track]->stts_sample_count[i];
1553         }
1554         return total;
1555 }
1556
1557 mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t * f)
1558 {
1559         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
1560
1561         memset(ff, 0, sizeof (mp4ff_t));
1562
1563         ff->stream = f;
1564
1565         parse_atoms(ff, 1);
1566
1567         if (ff->error) {
1568                 free(ff);
1569                 ff = NULL;
1570         }
1571
1572         return ff;
1573 }
1574
1575 int32_t mp4ff_meta_get_num_items(const mp4ff_t * f)
1576 {
1577         return f->tags.count;
1578 }
1579
1580 int32_t mp4ff_meta_get_by_index(const mp4ff_t * f, uint32_t index,
1581                                 char **item, char **value)
1582 {
1583         if (index >= f->tags.count) {
1584                 *item = NULL;
1585                 *value = NULL;
1586                 return 0;
1587         } else {
1588                 *item = strdup(f->tags.tags[index].item);
1589                 *value = strdup(f->tags.tags[index].value);
1590                 return 1;
1591         }
1592 }
1593
1594 static uint32_t find_atom(mp4ff_t * f, uint64_t base, uint32_t size,
1595                           const char *name)
1596 {
1597         uint32_t remaining = size;
1598         uint64_t atom_offset = base;
1599         for (;;) {
1600                 char atom_name[4];
1601                 uint32_t atom_size;
1602
1603                 mp4ff_set_position(f, atom_offset);
1604
1605                 if (remaining < 8)
1606                         break;
1607                 atom_size = mp4ff_read_int32(f);
1608                 if (atom_size > remaining || atom_size < 8)
1609                         break;
1610                 mp4ff_read_data(f, atom_name, 4);
1611
1612                 if (!memcmp(atom_name, name, 4)) {
1613                         mp4ff_set_position(f, atom_offset);
1614                         return 1;
1615                 }
1616
1617                 remaining -= atom_size;
1618                 atom_offset += atom_size;
1619         }
1620         return 0;
1621 }
1622 static uint32_t find_atom_v2(mp4ff_t * f, uint64_t base, uint32_t size,
1623                 const char *name, uint32_t extraheaders, const char *name_inside)
1624 {
1625         uint64_t first_base = (uint64_t) (-1);
1626         while (find_atom(f, base, size, name))  //try to find atom <name> with atom <name_inside> in it
1627         {
1628                 uint64_t mybase = mp4ff_position(f);
1629                 uint32_t mysize = mp4ff_read_int32(f);
1630
1631                 if (first_base == (uint64_t) (-1))
1632                         first_base = mybase;
1633
1634                 if (mysize < 8 + extraheaders)
1635                         break;
1636
1637                 if (find_atom (f, mybase + (8 + extraheaders),
1638                                 mysize - (8 + extraheaders), name_inside)) {
1639                         mp4ff_set_position(f, mybase);
1640                         return 2;
1641                 }
1642                 base += mysize;
1643                 if (size <= mysize) {
1644                         size = 0;
1645                         break;
1646                 }
1647                 size -= mysize;
1648         }
1649
1650         if (first_base != (uint64_t) (-1))      //wanted atom inside not found
1651         {
1652                 mp4ff_set_position(f, first_base);
1653                 return 1;
1654         } else
1655                 return 0;
1656 }
1657
1658 typedef struct {
1659         void *data;
1660         unsigned written;
1661         unsigned allocated;
1662         unsigned error;
1663 } membuffer;
1664
1665 #define stricmp strcasecmp
1666
1667 static membuffer *membuffer_create(void)
1668 {
1669         const unsigned initial_size = 256;
1670
1671         membuffer *buf = (membuffer *) malloc(sizeof (membuffer));
1672         buf->data = malloc(initial_size);
1673         buf->written = 0;
1674         buf->allocated = initial_size;
1675         buf->error = buf->data == 0 ? 1 : 0;
1676
1677         return buf;
1678 }
1679
1680 static unsigned membuffer_write(membuffer * buf, const void *ptr, unsigned bytes)
1681 {
1682         unsigned dest_size = buf->written + bytes;
1683
1684         if (buf->error)
1685                 return 0;
1686         if (dest_size > buf->allocated) {
1687                 do {
1688                         buf->allocated <<= 1;
1689                 } while (dest_size > buf->allocated);
1690
1691                 {
1692                         void *newptr = realloc(buf->data, buf->allocated);
1693                         if (newptr == 0) {
1694                                 free(buf->data);
1695                                 buf->data = 0;
1696                                 buf->error = 1;
1697                                 return 0;
1698                         }
1699                         buf->data = newptr;
1700                 }
1701         }
1702
1703         if (ptr)
1704                 memcpy((char *) buf->data + buf->written, ptr, bytes);
1705         buf->written += bytes;
1706         return bytes;
1707 }
1708
1709 static unsigned membuffer_write_atom_name(membuffer * buf, const char *data)
1710 {
1711         return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
1712 }
1713
1714 static unsigned membuffer_write_int16(membuffer * buf, uint16_t data)
1715 {
1716         uint8_t temp[2] = { (uint8_t) (data >> 8), (uint8_t) data };
1717         return membuffer_write(buf, temp, 2);
1718 }
1719
1720 static unsigned membuffer_write_int32(membuffer * buf, uint32_t data)
1721 {
1722         uint8_t temp[4] = { (uint8_t) (data >> 24), (uint8_t) (data >> 16),
1723                 (uint8_t) (data >> 8), (uint8_t) data };
1724         return membuffer_write(buf, temp, 4);
1725 }
1726
1727 static void membuffer_write_track_tag(membuffer * buf, const char *name,
1728                 uint32_t index, uint32_t total)
1729 {
1730         membuffer_write_int32(buf,
1731                 8 /*atom header */  + 8 /*data atom header */  +
1732                 8 /*flags + reserved */  + 8 /*actual data */ );
1733         membuffer_write_atom_name(buf, name);
1734         membuffer_write_int32(buf,
1735                 8 /*data atom header */  +
1736                 8 /*flags + reserved */  + 8 /*actual data */ );
1737         membuffer_write_atom_name(buf, "data");
1738         membuffer_write_int32(buf, 0);  //flags
1739         membuffer_write_int32(buf, 0);  //reserved
1740         membuffer_write_int16(buf, 0);
1741         membuffer_write_int16(buf, (uint16_t) index);   //track number
1742         membuffer_write_int16(buf, (uint16_t) total);   //total tracks
1743         membuffer_write_int16(buf, 0);
1744 }
1745
1746 static void membuffer_write_int16_tag(membuffer * buf, const char *name,
1747                 uint16_t value)
1748 {
1749         membuffer_write_int32(buf,
1750                 8 /*atom header */  + 8 /*data atom header */  +
1751                 8 /*flags + reserved */  + 2 /*actual data */ );
1752         membuffer_write_atom_name(buf, name);
1753         membuffer_write_int32(buf,
1754                 8 /*data atom header */  +
1755                 8 /*flags + reserved */  + 2 /*actual data */ );
1756         membuffer_write_atom_name(buf, "data");
1757         membuffer_write_int32(buf, 0);  //flags
1758         membuffer_write_int32(buf, 0);  //reserved
1759         membuffer_write_int16(buf, value);      //value
1760 }
1761
1762 static uint32_t myatoi(const char *param)
1763 {
1764         return param ? atoi(param) : 0;
1765 }
1766
1767 static uint32_t mp4ff_meta_genre_to_index(const char *genrestr)
1768 {
1769         unsigned n;
1770         for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
1771                 if (!stricmp(genrestr, ID3v1GenreList[n]))
1772                         return n + 1;
1773         }
1774         return 0;
1775 }
1776
1777 typedef struct {
1778         const char *atom;
1779         const char *name;
1780 } stdmeta_entry;
1781
1782 static stdmeta_entry stdmetas[] = {
1783         {"\xA9" "nam", "title"},
1784         {"\xA9" "ART", "artist"},
1785         {"\xA9" "wrt", "writer"},
1786         {"\xA9" "alb", "album"},
1787         {"\xA9" "day", "date"},
1788         {"\xA9" "too", "tool"},
1789         {"\xA9" "cmt", "comment"},
1790         {"cpil", "compilation"},
1791         {"covr", "cover"},
1792         {"aART", "album_artist"},
1793 };
1794
1795 static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
1796 {
1797         unsigned n;
1798         for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
1799                 if (!stricmp(name, stdmetas[n].name))
1800                         return stdmetas[n].atom;
1801         }
1802         return 0;
1803 }
1804
1805 static void membuffer_write_std_tag(membuffer * buf, const char *name,
1806                 const char *value)
1807 {
1808         uint32_t flags = 1;
1809
1810         /* special check for compilation flag */
1811         if (strcmp(name, "cpil") == 0) {
1812                 flags = 21;
1813         }
1814
1815         membuffer_write_int32(buf,
1816                 8 /*atom header */  + 8 /*data atom header */  +
1817                 8 /*flags + reserved */  + strlen(value));
1818         membuffer_write_atom_name(buf, name);
1819         membuffer_write_int32(buf,
1820                 8 /*data atom header */  +
1821                 8 /*flags + reserved */  + strlen(value));
1822         membuffer_write_atom_name(buf, "data");
1823         membuffer_write_int32(buf, flags);      //flags
1824         membuffer_write_int32(buf, 0);  //reserved
1825         membuffer_write(buf, value, strlen(value));
1826 }
1827
1828 static void membuffer_write_custom_tag(membuffer * buf, const char *name,
1829                 const char *value)
1830 {
1831         membuffer_write_int32(buf,
1832                 8 /*atom header */  +
1833                 0x1C /*weirdo itunes atom */  +
1834                 12 /*name atom header */  + strlen(name) +
1835                 16 /*data atom header + flags */  + strlen(value));
1836         membuffer_write_atom_name(buf, "----");
1837         membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
1838         membuffer_write_atom_name(buf, "mean");
1839         membuffer_write_int32(buf, 0);
1840         membuffer_write(buf, "com.apple.iTunes", 16);
1841         membuffer_write_int32(buf, 12 + strlen(name));
1842         membuffer_write_atom_name(buf, "name");
1843         membuffer_write_int32(buf, 0);
1844         membuffer_write(buf, name, strlen(name));
1845         membuffer_write_int32(buf,
1846                 8 /*data atom header */  +
1847                 8 /*flags + reserved */  + strlen(value));
1848         membuffer_write_atom_name(buf, "data");
1849         membuffer_write_int32(buf, 1);  //flags
1850         membuffer_write_int32(buf, 0);  //reserved
1851         membuffer_write(buf, value, strlen(value));
1852 }
1853
1854 static unsigned membuffer_error(const membuffer * buf)
1855 {
1856         return buf->error;
1857 }
1858
1859 static void membuffer_free(membuffer * buf)
1860 {
1861         if (buf->data)
1862                 free(buf->data);
1863         free(buf);
1864 }
1865
1866 static unsigned membuffer_get_size(const membuffer * buf)
1867 {
1868         return buf->written;
1869 }
1870
1871 static void *membuffer_detach(membuffer * buf)
1872 {
1873         void *ret;
1874
1875         if (buf->error)
1876                 return 0;
1877
1878         ret = realloc(buf->data, buf->written);
1879
1880         if (ret == 0)
1881                 free(buf->data);
1882
1883         buf->data = 0;
1884         buf->error = 1;
1885
1886         return ret;
1887 }
1888
1889 static uint32_t create_ilst(const mp4ff_metadata_t * data, void **out_buffer,
1890                 uint32_t * out_size)
1891 {
1892         membuffer *buf = membuffer_create();
1893         unsigned metaptr;
1894         char *mask = (char *) malloc(data->count);
1895         memset(mask, 0, data->count);
1896
1897         {
1898                 const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1899                 const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1900                 const char *genre_ptr = 0, *tempo_ptr = 0;
1901                 for (metaptr = 0; metaptr < data->count; metaptr++) {
1902                         mp4ff_tag_t *tag = &data->tags[metaptr];
1903                         if (!stricmp(tag->item, "tracknumber") || !stricmp(tag->item, "track")) {
1904                                 if (tracknumber_ptr == 0)
1905                                         tracknumber_ptr = tag->value;
1906                                 mask[metaptr] = 1;
1907                         } else if (!stricmp(tag->item, "totaltracks")) {
1908                                 if (totaltracks_ptr == 0)
1909                                         totaltracks_ptr = tag->value;
1910                                 mask[metaptr] = 1;
1911                         } else if (!stricmp(tag->item, "discnumber")
1912                                         || !stricmp(tag->item, "disc")) {
1913                                 if (discnumber_ptr == 0)
1914                                         discnumber_ptr = tag->value;
1915                                 mask[metaptr] = 1;
1916                         } else if (!stricmp(tag->item, "totaldiscs")) {
1917                                 if (totaldiscs_ptr == 0)
1918                                         totaldiscs_ptr = tag->value;
1919                                 mask[metaptr] = 1;
1920                         } else if (!stricmp(tag->item, "genre")) {
1921                                 if (genre_ptr == 0)
1922                                         genre_ptr = tag->value;
1923                                 mask[metaptr] = 1;
1924                         } else if (!stricmp(tag->item, "tempo")) {
1925                                 if (tempo_ptr == 0)
1926                                         tempo_ptr = tag->value;
1927                                 mask[metaptr] = 1;
1928                         }
1929
1930                 }
1931
1932                 if (tracknumber_ptr)
1933                         membuffer_write_track_tag(buf, "trkn",
1934                                                   myatoi(tracknumber_ptr),
1935                                                   myatoi(totaltracks_ptr));
1936                 if (discnumber_ptr)
1937                         membuffer_write_track_tag(buf, "disk",
1938                                                   myatoi(discnumber_ptr),
1939                                                   myatoi(totaldiscs_ptr));
1940                 if (tempo_ptr)
1941                         membuffer_write_int16_tag(buf, "tmpo",
1942                                                   (uint16_t) myatoi(tempo_ptr));
1943
1944                 if (genre_ptr) {
1945                         uint32_t index = mp4ff_meta_genre_to_index(genre_ptr);
1946                         if (index == 0)
1947                                 membuffer_write_std_tag(buf, "©gen",
1948                                                         genre_ptr);
1949                         else
1950                                 membuffer_write_int16_tag(buf, "gnre",
1951                                                           (uint16_t) index);
1952                 }
1953         }
1954
1955         for (metaptr = 0; metaptr < data->count; metaptr++) {
1956                 if (!mask[metaptr]) {
1957                         mp4ff_tag_t *tag = &data->tags[metaptr];
1958                         const char *std_meta_atom = find_standard_meta(tag->item);
1959                         if (std_meta_atom) {
1960                                 membuffer_write_std_tag(buf, std_meta_atom,
1961                                                         tag->value);
1962                         } else {
1963                                 membuffer_write_custom_tag(buf, tag->item,
1964                                         tag->value);
1965                         }
1966                 }
1967         }
1968
1969         free(mask);
1970
1971         if (membuffer_error(buf)) {
1972                 membuffer_free(buf);
1973                 return 0;
1974         }
1975
1976         *out_size = membuffer_get_size(buf);
1977         *out_buffer = membuffer_detach(buf);
1978         membuffer_free(buf);
1979
1980         return 1;
1981 }
1982
1983 static void membuffer_write_atom(membuffer * buf, const char *name, unsigned size,
1984                           const void *data)
1985 {
1986         membuffer_write_int32(buf, size + 8);
1987         membuffer_write_atom_name(buf, name);
1988         membuffer_write(buf, data, size);
1989 }
1990
1991 static void *membuffer_get_ptr(const membuffer * buf)
1992 {
1993         return buf->data;
1994 }
1995
1996 static void membuffer_set_error(membuffer * buf)
1997 {
1998         buf->error = 1;
1999 }
2000
2001 static unsigned membuffer_transfer_from_file(membuffer * buf, mp4ff_t * src,
2002                 unsigned bytes)
2003 {
2004         unsigned oldsize;
2005         void *bufptr;
2006
2007         oldsize = membuffer_get_size(buf);
2008         if (membuffer_write(buf, 0, bytes) != bytes)
2009                 return 0;
2010
2011         bufptr = membuffer_get_ptr(buf);
2012         if (bufptr == 0)
2013                 return 0;
2014
2015         if ((unsigned) mp4ff_read_data(src, (char *) bufptr + oldsize, bytes) !=
2016                 bytes) {
2017                 membuffer_set_error(buf);
2018                 return 0;
2019         }
2020
2021         return bytes;
2022 }
2023
2024 static uint32_t create_meta(const mp4ff_metadata_t * data, void **out_buffer,
2025                 uint32_t * out_size)
2026 {
2027         membuffer *buf;
2028         uint32_t ilst_size;
2029         void *ilst_buffer;
2030
2031         if (!create_ilst(data, &ilst_buffer, &ilst_size))
2032                 return 0;
2033
2034         buf = membuffer_create();
2035
2036         membuffer_write_int32(buf, 0);
2037         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
2038         free(ilst_buffer);
2039
2040         *out_size = membuffer_get_size(buf);
2041         *out_buffer = membuffer_detach(buf);
2042         membuffer_free(buf);
2043         return 1;
2044 }
2045
2046 static uint32_t create_udta(const mp4ff_metadata_t * data, void **out_buffer,
2047 uint32_t * out_size)
2048 {
2049         membuffer *buf;
2050         uint32_t meta_size;
2051         void *meta_buffer;
2052
2053         if (!create_meta(data, &meta_buffer, &meta_size))
2054                 return 0;
2055
2056         buf = membuffer_create();
2057
2058         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
2059
2060         free(meta_buffer);
2061
2062         *out_size = membuffer_get_size(buf);
2063         *out_buffer = membuffer_detach(buf);
2064         membuffer_free(buf);
2065         return 1;
2066 }
2067
2068 static uint32_t fix_byte_order_32(uint32_t src)
2069 {
2070         uint32_t result;
2071         uint32_t a, b, c, d;
2072         int8_t data[4];
2073
2074         memcpy(data, &src, sizeof (src));
2075         a = (uint8_t) data[0];
2076         b = (uint8_t) data[1];
2077         c = (uint8_t) data[2];
2078         d = (uint8_t) data[3];
2079
2080         result = (a << 24) | (b << 16) | (c << 8) | d;
2081         return (uint32_t) result;
2082 }
2083
2084 static uint32_t modify_moov(mp4ff_t * f, const mp4ff_metadata_t * data,
2085                 void **out_buffer, uint32_t * out_size)
2086 {
2087         uint64_t total_base = f->moov_offset + 8;
2088         uint32_t total_size = (uint32_t) (f->moov_size - 8);
2089
2090         uint64_t udta_offset, meta_offset, ilst_offset;
2091         uint32_t udta_size, meta_size, ilst_size;
2092
2093         uint32_t new_ilst_size;
2094         void *new_ilst_buffer;
2095
2096         uint8_t *p_out;
2097         int32_t size_delta;
2098
2099         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
2100                 membuffer *buf;
2101                 void *new_udta_buffer;
2102                 uint32_t new_udta_size;
2103                 if (!create_udta(data, &new_udta_buffer, &new_udta_size))
2104                         return 0;
2105
2106                 buf = membuffer_create();
2107                 mp4ff_set_position(f, total_base);
2108                 membuffer_transfer_from_file(buf, f, total_size);
2109
2110                 membuffer_write_atom(buf, "udta", new_udta_size,
2111                         new_udta_buffer);
2112
2113                 free(new_udta_buffer);
2114
2115                 *out_size = membuffer_get_size(buf);
2116                 *out_buffer = membuffer_detach(buf);
2117                 membuffer_free(buf);
2118                 return 1;
2119         } else {
2120                 udta_offset = mp4ff_position(f);
2121                 udta_size = mp4ff_read_int32(f);
2122                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
2123                         membuffer *buf;
2124                         void *new_meta_buffer;
2125                         uint32_t new_meta_size;
2126                         if (!create_meta(data, &new_meta_buffer, &new_meta_size))
2127                                 return 0;
2128
2129                         buf = membuffer_create();
2130                         mp4ff_set_position(f, total_base);
2131                         membuffer_transfer_from_file(buf, f,
2132                                 (uint32_t)(udta_offset - total_base));
2133
2134                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
2135                         membuffer_write_atom_name(buf, "udta");
2136                         membuffer_transfer_from_file(buf, f, udta_size);
2137
2138                         membuffer_write_atom(buf, "meta", new_meta_size,
2139                                 new_meta_buffer);
2140                         free(new_meta_buffer);
2141
2142                         *out_size = membuffer_get_size(buf);
2143                         *out_buffer = membuffer_detach(buf);
2144                         membuffer_free(buf);
2145                         return 1;
2146                 }
2147                 meta_offset = mp4ff_position(f);
2148                 meta_size = mp4ff_read_int32(f);
2149                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
2150                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
2151                 ilst_offset = mp4ff_position(f);
2152                 ilst_size = mp4ff_read_int32(f);
2153
2154                 if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
2155                         return 0;
2156
2157                 size_delta = new_ilst_size - (ilst_size - 8);
2158
2159                 *out_size = total_size + size_delta;
2160                 *out_buffer = malloc(*out_size);
2161                 if (*out_buffer == 0) {
2162                         free(new_ilst_buffer);
2163                         return 0;
2164                 }
2165
2166                 p_out = (uint8_t *) * out_buffer;
2167
2168                 mp4ff_set_position(f, total_base);
2169                 mp4ff_read_data(f, p_out,
2170                                 (uint32_t) (udta_offset - total_base));
2171                 p_out += (uint32_t) (udta_offset - total_base);
2172                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2173                 p_out += 4;
2174                 mp4ff_read_data(f, p_out, 4);
2175                 p_out += 4;
2176                 mp4ff_read_data(f, p_out,
2177                                 (uint32_t) (meta_offset - udta_offset - 8));
2178                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
2179                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2180                 p_out += 4;
2181                 mp4ff_read_data(f, p_out, 4);
2182                 p_out += 4;
2183                 mp4ff_read_data(f, p_out,
2184                                 (uint32_t) (ilst_offset - meta_offset - 8));
2185                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
2186                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2187                 p_out += 4;
2188                 mp4ff_read_data(f, p_out, 4);
2189                 p_out += 4;
2190
2191                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
2192                 p_out += new_ilst_size;
2193
2194                 mp4ff_set_position(f, ilst_offset + ilst_size);
2195                 mp4ff_read_data(f, p_out, (uint32_t) (total_size
2196                         - (ilst_offset - total_base) - ilst_size));
2197
2198                 free(new_ilst_buffer);
2199         }
2200         return 1;
2201 }
2202
2203 static int32_t mp4ff_write_data(mp4ff_t * f, void *data, uint32_t size)
2204 {
2205         int32_t result = 1;
2206
2207         result = f->stream->write(f->stream->user_data, data, size);
2208
2209         f->current_position += size;
2210
2211         return result;
2212 }
2213
2214 static int32_t mp4ff_write_int32(mp4ff_t * f, const uint32_t data)
2215 {
2216         uint32_t result;
2217         uint32_t a, b, c, d;
2218         int8_t temp[4];
2219
2220         *(uint32_t *) temp = data;
2221         a = (uint8_t) temp[0];
2222         b = (uint8_t) temp[1];
2223         c = (uint8_t) temp[2];
2224         d = (uint8_t) temp[3];
2225
2226         result = (a << 24) | (b << 16) | (c << 8) | d;
2227
2228         return mp4ff_write_data(f, (uint8_t *) & result, sizeof (result));
2229 }
2230
2231 static int32_t mp4ff_truncate(mp4ff_t * f)
2232 {
2233         return f->stream->truncate(f->stream->user_data);
2234 }
2235
2236 int32_t mp4ff_meta_update(mp4ff_callback_t * f, const mp4ff_metadata_t * data)
2237 {
2238         void *new_moov_data;
2239         uint32_t new_moov_size;
2240
2241         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
2242
2243         memset(ff, 0, sizeof (mp4ff_t));
2244         ff->stream = f;
2245         mp4ff_set_position(ff, 0);
2246
2247         parse_atoms(ff, 1);
2248
2249         if (!modify_moov(ff, data, &new_moov_data, &new_moov_size)) {
2250                 mp4ff_close(ff);
2251                 return 0;
2252         }
2253
2254         /* copy moov atom to end of the file */
2255         if (ff->last_atom != ATOM_MOOV) {
2256                 char *free_data = "free";
2257
2258                 /* rename old moov to free */
2259                 mp4ff_set_position(ff, ff->moov_offset + 4);
2260                 mp4ff_write_data(ff, free_data, 4);
2261
2262                 mp4ff_set_position(ff, ff->file_size);
2263                 mp4ff_write_int32(ff, new_moov_size + 8);
2264                 mp4ff_write_data(ff, "moov", 4);
2265                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2266         } else {
2267                 mp4ff_set_position(ff, ff->moov_offset);
2268                 mp4ff_write_int32(ff, new_moov_size + 8);
2269                 mp4ff_write_data(ff, "moov", 4);
2270                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2271         }
2272
2273         mp4ff_truncate(ff);
2274
2275         mp4ff_close(ff);
2276         return 1;
2277 }
2278
2279 /* find a metadata item by name */
2280 /* returns 0 if item found, 1 if no such item */
2281 static int32_t mp4ff_meta_find_by_name(const mp4ff_t * f, const char *item,
2282                 char **value)
2283 {
2284         uint32_t i;
2285
2286         for (i = 0; i < f->tags.count; i++) {
2287                 if (!stricmp(f->tags.tags[i].item, item)) {
2288                         *value = strdup(f->tags.tags[i].value);
2289                         return 1;
2290                 }
2291         }
2292
2293         *value = NULL;
2294
2295         /* not found */
2296         return 0;
2297 }
2298
2299 int32_t mp4ff_meta_get_artist(const mp4ff_t * f, char **value)
2300 {
2301         return mp4ff_meta_find_by_name(f, "artist", value);
2302 }
2303
2304 int32_t mp4ff_meta_get_title(const mp4ff_t * f, char **value)
2305 {
2306         return mp4ff_meta_find_by_name(f, "title", value);
2307 }
2308
2309 int32_t mp4ff_meta_get_date(const mp4ff_t * f, char **value)
2310 {
2311         return mp4ff_meta_find_by_name(f, "date", value);
2312 }
2313
2314 int32_t mp4ff_meta_get_album(const mp4ff_t * f, char **value)
2315 {
2316         return mp4ff_meta_find_by_name(f, "album", value);
2317 }
2318
2319 int32_t mp4ff_meta_get_comment(const mp4ff_t * f, char **value)
2320 {
2321         return mp4ff_meta_find_by_name(f, "comment", value);
2322 }