]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
mp4: Remove member moov_read of struct mp4ff.
[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_offset = mp4ff_position(f) - header_size;
1293                         f->moov_size = size;
1294                 }
1295
1296                 /* parse subatoms */
1297                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1298                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1299                 } else if (atom_type < SUBATOMIC) {
1300                         parse_sub_atoms(f, size - header_size, meta_only);
1301                 } else {
1302                         /* skip this atom */
1303                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1304                 }
1305         }
1306
1307         return 0;
1308 }
1309
1310 void mp4ff_get_decoder_config(const mp4ff_t * f, const int track,
1311                                  unsigned char **ppBuf, unsigned int *pBufSize)
1312 {
1313         if (track >= f->total_tracks) {
1314                 *ppBuf = NULL;
1315                 *pBufSize = 0;
1316                 return;
1317         }
1318
1319         if (f->track[track]->decoderConfig == NULL
1320                 || f->track[track]->decoderConfigLen == 0) {
1321                 *ppBuf = NULL;
1322                 *pBufSize = 0;
1323         } else {
1324                 *ppBuf = malloc(f->track[track]->decoderConfigLen);
1325                 if (*ppBuf == NULL) {
1326                         *pBufSize = 0;
1327                         return;
1328                 }
1329                 memcpy(*ppBuf, f->track[track]->decoderConfig,
1330                         f->track[track]->decoderConfigLen);
1331                 *pBufSize = f->track[track]->decoderConfigLen;
1332         }
1333 }
1334
1335 mp4ff_t *mp4ff_open_read(mp4ff_callback_t * f)
1336 {
1337         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
1338
1339         memset(ff, 0, sizeof (mp4ff_t));
1340
1341         ff->stream = f;
1342
1343         parse_atoms(ff, 0);
1344
1345         if (ff->error) {
1346                 free(ff);
1347                 ff = NULL;
1348         }
1349
1350         return ff;
1351 }
1352
1353 static int32_t mp4ff_tag_delete(mp4ff_metadata_t * tags)
1354 {
1355         uint32_t i;
1356
1357         for (i = 0; i < tags->count; i++) {
1358                 if (tags->tags[i].item)
1359                         free(tags->tags[i].item);
1360                 if (tags->tags[i].value)
1361                         free(tags->tags[i].value);
1362         }
1363
1364         if (tags->tags)
1365                 free(tags->tags);
1366
1367         tags->tags = NULL;
1368         tags->count = 0;
1369
1370         return 0;
1371 }
1372
1373 void mp4ff_close(mp4ff_t * ff)
1374 {
1375         int32_t i;
1376
1377         for (i = 0; i < ff->total_tracks; i++) {
1378                 if (ff->track[i]) {
1379                         if (ff->track[i]->stsz_table)
1380                                 free(ff->track[i]->stsz_table);
1381                         if (ff->track[i]->stts_sample_count)
1382                                 free(ff->track[i]->stts_sample_count);
1383                         if (ff->track[i]->stts_sample_delta)
1384                                 free(ff->track[i]->stts_sample_delta);
1385                         if (ff->track[i]->stsc_first_chunk)
1386                                 free(ff->track[i]->stsc_first_chunk);
1387                         if (ff->track[i]->stsc_samples_per_chunk)
1388                                 free(ff->track[i]->stsc_samples_per_chunk);
1389                         if (ff->track[i]->stsc_sample_desc_index)
1390                                 free(ff->track[i]->stsc_sample_desc_index);
1391                         if (ff->track[i]->stco_chunk_offset)
1392                                 free(ff->track[i]->stco_chunk_offset);
1393                         if (ff->track[i]->decoderConfig)
1394                                 free(ff->track[i]->decoderConfig);
1395                         if (ff->track[i]->ctts_sample_count)
1396                                 free(ff->track[i]->ctts_sample_count);
1397                         if (ff->track[i]->ctts_sample_offset)
1398                                 free(ff->track[i]->ctts_sample_offset);
1399                         free(ff->track[i]);
1400                 }
1401         }
1402
1403         mp4ff_tag_delete(&(ff->tags));
1404
1405         if (ff)
1406                 free(ff);
1407 }
1408
1409 static int32_t mp4ff_chunk_of_sample(const mp4ff_t * f, const int32_t track,
1410                 const int32_t sample, int32_t * chunk_sample, int32_t * chunk)
1411 {
1412         int32_t total_entries = 0;
1413         int32_t chunk2entry;
1414         int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
1415
1416         *chunk_sample = 0;
1417         *chunk = 1;
1418         if (f->track[track] == NULL) {
1419                 return -1;
1420         }
1421
1422         total_entries = f->track[track]->stsc_entry_count;
1423
1424         chunk1 = 1;
1425         chunk1samples = 0;
1426         chunk2entry = 0;
1427
1428         do {
1429                 chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
1430                 *chunk = chunk2 - chunk1;
1431                 range_samples = *chunk * chunk1samples;
1432
1433                 if (sample < total + range_samples)
1434                         break;
1435
1436                 chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
1437                 chunk1 = chunk2;
1438
1439                 if (chunk2entry < total_entries) {
1440                         chunk2entry++;
1441                         total += range_samples;
1442                 }
1443         } while (chunk2entry < total_entries);
1444
1445         if (chunk1samples)
1446                 *chunk = (sample - total) / chunk1samples + chunk1;
1447         else
1448                 *chunk = 1;
1449
1450         *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
1451
1452         return 0;
1453 }
1454
1455 static int32_t mp4ff_chunk_to_offset(const mp4ff_t * f, const int32_t track,
1456                 const int32_t chunk)
1457 {
1458         const mp4ff_track_t *p_track = f->track[track];
1459
1460         if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) {
1461                 return p_track->stco_chunk_offset[p_track->stco_entry_count -
1462                                                   1];
1463         } else if (p_track->stco_entry_count) {
1464                 return p_track->stco_chunk_offset[chunk - 1];
1465         } else {
1466                 return 8;
1467         }
1468
1469         return 0;
1470 }
1471
1472 static int32_t mp4ff_sample_range_size(const mp4ff_t * f, const int32_t track,
1473                 const int32_t chunk_sample, const int32_t sample)
1474 {
1475         int32_t i, total;
1476         const mp4ff_track_t *p_track = f->track[track];
1477
1478         if (p_track->stsz_sample_size) {
1479                 return (sample - chunk_sample) * p_track->stsz_sample_size;
1480         } else {
1481                 if (sample >= p_track->stsz_sample_count)
1482                         return 0;       //error
1483
1484                 for (i = chunk_sample, total = 0; i < sample; i++) {
1485                         total += p_track->stsz_table[i];
1486                 }
1487         }
1488
1489         return total;
1490 }
1491 static int32_t mp4ff_sample_to_offset(const mp4ff_t * f, const int32_t track,
1492                 const int32_t sample)
1493 {
1494         int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
1495
1496         mp4ff_chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
1497
1498         chunk_offset1 = mp4ff_chunk_to_offset(f, track, chunk);
1499         chunk_offset2 = chunk_offset1 + mp4ff_sample_range_size(f,
1500                 track, chunk_sample, sample);
1501         return chunk_offset2;
1502 }
1503
1504 void mp4ff_set_sample_position(mp4ff_t *f, const int32_t track,
1505                 const int32_t sample)
1506 {
1507         int32_t offset = mp4ff_sample_to_offset(f, track, sample);
1508         mp4ff_set_position(f, offset);
1509 }
1510
1511 int32_t mp4ff_get_sample_size(const mp4ff_t *f, int track, int sample)
1512 {
1513         const mp4ff_track_t *t = f->track[track];
1514
1515         if (t->stsz_sample_size != 0)
1516                 return t->stsz_sample_size;
1517         return t->stsz_table[sample];
1518 }
1519
1520 uint32_t mp4ff_get_sample_rate(const mp4ff_t * f, const int32_t track)
1521 {
1522         return f->track[track]->sampleRate;
1523 }
1524
1525 uint32_t mp4ff_get_channel_count(const mp4ff_t * f, const int32_t track)
1526 {
1527         return f->track[track]->channelCount;
1528 }
1529
1530 int32_t mp4ff_num_samples(const mp4ff_t * f, const int32_t track)
1531 {
1532         int32_t i;
1533         int32_t total = 0;
1534
1535         for (i = 0; i < f->track[track]->stts_entry_count; i++) {
1536                 total += f->track[track]->stts_sample_count[i];
1537         }
1538         return total;
1539 }
1540
1541 mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t * f)
1542 {
1543         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
1544
1545         memset(ff, 0, sizeof (mp4ff_t));
1546
1547         ff->stream = f;
1548
1549         parse_atoms(ff, 1);
1550
1551         if (ff->error) {
1552                 free(ff);
1553                 ff = NULL;
1554         }
1555
1556         return ff;
1557 }
1558
1559 int32_t mp4ff_meta_get_num_items(const mp4ff_t * f)
1560 {
1561         return f->tags.count;
1562 }
1563
1564 int32_t mp4ff_meta_get_by_index(const mp4ff_t * f, uint32_t index,
1565                                 char **item, char **value)
1566 {
1567         if (index >= f->tags.count) {
1568                 *item = NULL;
1569                 *value = NULL;
1570                 return 0;
1571         } else {
1572                 *item = strdup(f->tags.tags[index].item);
1573                 *value = strdup(f->tags.tags[index].value);
1574                 return 1;
1575         }
1576 }
1577
1578 static uint32_t find_atom(mp4ff_t * f, uint64_t base, uint32_t size,
1579                           const char *name)
1580 {
1581         uint32_t remaining = size;
1582         uint64_t atom_offset = base;
1583         for (;;) {
1584                 char atom_name[4];
1585                 uint32_t atom_size;
1586
1587                 mp4ff_set_position(f, atom_offset);
1588
1589                 if (remaining < 8)
1590                         break;
1591                 atom_size = mp4ff_read_int32(f);
1592                 if (atom_size > remaining || atom_size < 8)
1593                         break;
1594                 mp4ff_read_data(f, atom_name, 4);
1595
1596                 if (!memcmp(atom_name, name, 4)) {
1597                         mp4ff_set_position(f, atom_offset);
1598                         return 1;
1599                 }
1600
1601                 remaining -= atom_size;
1602                 atom_offset += atom_size;
1603         }
1604         return 0;
1605 }
1606 static uint32_t find_atom_v2(mp4ff_t * f, uint64_t base, uint32_t size,
1607                 const char *name, uint32_t extraheaders, const char *name_inside)
1608 {
1609         uint64_t first_base = (uint64_t) (-1);
1610         while (find_atom(f, base, size, name))  //try to find atom <name> with atom <name_inside> in it
1611         {
1612                 uint64_t mybase = mp4ff_position(f);
1613                 uint32_t mysize = mp4ff_read_int32(f);
1614
1615                 if (first_base == (uint64_t) (-1))
1616                         first_base = mybase;
1617
1618                 if (mysize < 8 + extraheaders)
1619                         break;
1620
1621                 if (find_atom (f, mybase + (8 + extraheaders),
1622                                 mysize - (8 + extraheaders), name_inside)) {
1623                         mp4ff_set_position(f, mybase);
1624                         return 2;
1625                 }
1626                 base += mysize;
1627                 if (size <= mysize) {
1628                         size = 0;
1629                         break;
1630                 }
1631                 size -= mysize;
1632         }
1633
1634         if (first_base != (uint64_t) (-1))      //wanted atom inside not found
1635         {
1636                 mp4ff_set_position(f, first_base);
1637                 return 1;
1638         } else
1639                 return 0;
1640 }
1641
1642 typedef struct {
1643         void *data;
1644         unsigned written;
1645         unsigned allocated;
1646         unsigned error;
1647 } membuffer;
1648
1649 #define stricmp strcasecmp
1650
1651 static membuffer *membuffer_create(void)
1652 {
1653         const unsigned initial_size = 256;
1654
1655         membuffer *buf = (membuffer *) malloc(sizeof (membuffer));
1656         buf->data = malloc(initial_size);
1657         buf->written = 0;
1658         buf->allocated = initial_size;
1659         buf->error = buf->data == 0 ? 1 : 0;
1660
1661         return buf;
1662 }
1663
1664 static unsigned membuffer_write(membuffer * buf, const void *ptr, unsigned bytes)
1665 {
1666         unsigned dest_size = buf->written + bytes;
1667
1668         if (buf->error)
1669                 return 0;
1670         if (dest_size > buf->allocated) {
1671                 do {
1672                         buf->allocated <<= 1;
1673                 } while (dest_size > buf->allocated);
1674
1675                 {
1676                         void *newptr = realloc(buf->data, buf->allocated);
1677                         if (newptr == 0) {
1678                                 free(buf->data);
1679                                 buf->data = 0;
1680                                 buf->error = 1;
1681                                 return 0;
1682                         }
1683                         buf->data = newptr;
1684                 }
1685         }
1686
1687         if (ptr)
1688                 memcpy((char *) buf->data + buf->written, ptr, bytes);
1689         buf->written += bytes;
1690         return bytes;
1691 }
1692
1693 static unsigned membuffer_write_atom_name(membuffer * buf, const char *data)
1694 {
1695         return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
1696 }
1697
1698 static unsigned membuffer_write_int16(membuffer * buf, uint16_t data)
1699 {
1700         uint8_t temp[2] = { (uint8_t) (data >> 8), (uint8_t) data };
1701         return membuffer_write(buf, temp, 2);
1702 }
1703
1704 static unsigned membuffer_write_int32(membuffer * buf, uint32_t data)
1705 {
1706         uint8_t temp[4] = { (uint8_t) (data >> 24), (uint8_t) (data >> 16),
1707                 (uint8_t) (data >> 8), (uint8_t) data };
1708         return membuffer_write(buf, temp, 4);
1709 }
1710
1711 static void membuffer_write_track_tag(membuffer * buf, const char *name,
1712                 uint32_t index, uint32_t total)
1713 {
1714         membuffer_write_int32(buf,
1715                 8 /*atom header */  + 8 /*data atom header */  +
1716                 8 /*flags + reserved */  + 8 /*actual data */ );
1717         membuffer_write_atom_name(buf, name);
1718         membuffer_write_int32(buf,
1719                 8 /*data atom header */  +
1720                 8 /*flags + reserved */  + 8 /*actual data */ );
1721         membuffer_write_atom_name(buf, "data");
1722         membuffer_write_int32(buf, 0);  //flags
1723         membuffer_write_int32(buf, 0);  //reserved
1724         membuffer_write_int16(buf, 0);
1725         membuffer_write_int16(buf, (uint16_t) index);   //track number
1726         membuffer_write_int16(buf, (uint16_t) total);   //total tracks
1727         membuffer_write_int16(buf, 0);
1728 }
1729
1730 static void membuffer_write_int16_tag(membuffer * buf, const char *name,
1731                 uint16_t value)
1732 {
1733         membuffer_write_int32(buf,
1734                 8 /*atom header */  + 8 /*data atom header */  +
1735                 8 /*flags + reserved */  + 2 /*actual data */ );
1736         membuffer_write_atom_name(buf, name);
1737         membuffer_write_int32(buf,
1738                 8 /*data atom header */  +
1739                 8 /*flags + reserved */  + 2 /*actual data */ );
1740         membuffer_write_atom_name(buf, "data");
1741         membuffer_write_int32(buf, 0);  //flags
1742         membuffer_write_int32(buf, 0);  //reserved
1743         membuffer_write_int16(buf, value);      //value
1744 }
1745
1746 static uint32_t myatoi(const char *param)
1747 {
1748         return param ? atoi(param) : 0;
1749 }
1750
1751 static uint32_t mp4ff_meta_genre_to_index(const char *genrestr)
1752 {
1753         unsigned n;
1754         for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
1755                 if (!stricmp(genrestr, ID3v1GenreList[n]))
1756                         return n + 1;
1757         }
1758         return 0;
1759 }
1760
1761 typedef struct {
1762         const char *atom;
1763         const char *name;
1764 } stdmeta_entry;
1765
1766 static stdmeta_entry stdmetas[] = {
1767         {"\xA9" "nam", "title"},
1768         {"\xA9" "ART", "artist"},
1769         {"\xA9" "wrt", "writer"},
1770         {"\xA9" "alb", "album"},
1771         {"\xA9" "day", "date"},
1772         {"\xA9" "too", "tool"},
1773         {"\xA9" "cmt", "comment"},
1774         {"cpil", "compilation"},
1775         {"covr", "cover"},
1776         {"aART", "album_artist"},
1777 };
1778
1779 static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
1780 {
1781         unsigned n;
1782         for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
1783                 if (!stricmp(name, stdmetas[n].name))
1784                         return stdmetas[n].atom;
1785         }
1786         return 0;
1787 }
1788
1789 static void membuffer_write_std_tag(membuffer * buf, const char *name,
1790                 const char *value)
1791 {
1792         uint32_t flags = 1;
1793
1794         /* special check for compilation flag */
1795         if (strcmp(name, "cpil") == 0) {
1796                 flags = 21;
1797         }
1798
1799         membuffer_write_int32(buf,
1800                 8 /*atom header */  + 8 /*data atom header */  +
1801                 8 /*flags + reserved */  + strlen(value));
1802         membuffer_write_atom_name(buf, name);
1803         membuffer_write_int32(buf,
1804                 8 /*data atom header */  +
1805                 8 /*flags + reserved */  + strlen(value));
1806         membuffer_write_atom_name(buf, "data");
1807         membuffer_write_int32(buf, flags);      //flags
1808         membuffer_write_int32(buf, 0);  //reserved
1809         membuffer_write(buf, value, strlen(value));
1810 }
1811
1812 static void membuffer_write_custom_tag(membuffer * buf, const char *name,
1813                 const char *value)
1814 {
1815         membuffer_write_int32(buf,
1816                 8 /*atom header */  +
1817                 0x1C /*weirdo itunes atom */  +
1818                 12 /*name atom header */  + strlen(name) +
1819                 16 /*data atom header + flags */  + strlen(value));
1820         membuffer_write_atom_name(buf, "----");
1821         membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
1822         membuffer_write_atom_name(buf, "mean");
1823         membuffer_write_int32(buf, 0);
1824         membuffer_write(buf, "com.apple.iTunes", 16);
1825         membuffer_write_int32(buf, 12 + strlen(name));
1826         membuffer_write_atom_name(buf, "name");
1827         membuffer_write_int32(buf, 0);
1828         membuffer_write(buf, name, strlen(name));
1829         membuffer_write_int32(buf,
1830                 8 /*data atom header */  +
1831                 8 /*flags + reserved */  + strlen(value));
1832         membuffer_write_atom_name(buf, "data");
1833         membuffer_write_int32(buf, 1);  //flags
1834         membuffer_write_int32(buf, 0);  //reserved
1835         membuffer_write(buf, value, strlen(value));
1836 }
1837
1838 static unsigned membuffer_error(const membuffer * buf)
1839 {
1840         return buf->error;
1841 }
1842
1843 static void membuffer_free(membuffer * buf)
1844 {
1845         if (buf->data)
1846                 free(buf->data);
1847         free(buf);
1848 }
1849
1850 static unsigned membuffer_get_size(const membuffer * buf)
1851 {
1852         return buf->written;
1853 }
1854
1855 static void *membuffer_detach(membuffer * buf)
1856 {
1857         void *ret;
1858
1859         if (buf->error)
1860                 return 0;
1861
1862         ret = realloc(buf->data, buf->written);
1863
1864         if (ret == 0)
1865                 free(buf->data);
1866
1867         buf->data = 0;
1868         buf->error = 1;
1869
1870         return ret;
1871 }
1872
1873 static uint32_t create_ilst(const mp4ff_metadata_t * data, void **out_buffer,
1874                 uint32_t * out_size)
1875 {
1876         membuffer *buf = membuffer_create();
1877         unsigned metaptr;
1878         char *mask = (char *) malloc(data->count);
1879         memset(mask, 0, data->count);
1880
1881         {
1882                 const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1883                 const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1884                 const char *genre_ptr = 0, *tempo_ptr = 0;
1885                 for (metaptr = 0; metaptr < data->count; metaptr++) {
1886                         mp4ff_tag_t *tag = &data->tags[metaptr];
1887                         if (!stricmp(tag->item, "tracknumber") || !stricmp(tag->item, "track")) {
1888                                 if (tracknumber_ptr == 0)
1889                                         tracknumber_ptr = tag->value;
1890                                 mask[metaptr] = 1;
1891                         } else if (!stricmp(tag->item, "totaltracks")) {
1892                                 if (totaltracks_ptr == 0)
1893                                         totaltracks_ptr = tag->value;
1894                                 mask[metaptr] = 1;
1895                         } else if (!stricmp(tag->item, "discnumber")
1896                                         || !stricmp(tag->item, "disc")) {
1897                                 if (discnumber_ptr == 0)
1898                                         discnumber_ptr = tag->value;
1899                                 mask[metaptr] = 1;
1900                         } else if (!stricmp(tag->item, "totaldiscs")) {
1901                                 if (totaldiscs_ptr == 0)
1902                                         totaldiscs_ptr = tag->value;
1903                                 mask[metaptr] = 1;
1904                         } else if (!stricmp(tag->item, "genre")) {
1905                                 if (genre_ptr == 0)
1906                                         genre_ptr = tag->value;
1907                                 mask[metaptr] = 1;
1908                         } else if (!stricmp(tag->item, "tempo")) {
1909                                 if (tempo_ptr == 0)
1910                                         tempo_ptr = tag->value;
1911                                 mask[metaptr] = 1;
1912                         }
1913
1914                 }
1915
1916                 if (tracknumber_ptr)
1917                         membuffer_write_track_tag(buf, "trkn",
1918                                                   myatoi(tracknumber_ptr),
1919                                                   myatoi(totaltracks_ptr));
1920                 if (discnumber_ptr)
1921                         membuffer_write_track_tag(buf, "disk",
1922                                                   myatoi(discnumber_ptr),
1923                                                   myatoi(totaldiscs_ptr));
1924                 if (tempo_ptr)
1925                         membuffer_write_int16_tag(buf, "tmpo",
1926                                                   (uint16_t) myatoi(tempo_ptr));
1927
1928                 if (genre_ptr) {
1929                         uint32_t index = mp4ff_meta_genre_to_index(genre_ptr);
1930                         if (index == 0)
1931                                 membuffer_write_std_tag(buf, "©gen",
1932                                                         genre_ptr);
1933                         else
1934                                 membuffer_write_int16_tag(buf, "gnre",
1935                                                           (uint16_t) index);
1936                 }
1937         }
1938
1939         for (metaptr = 0; metaptr < data->count; metaptr++) {
1940                 if (!mask[metaptr]) {
1941                         mp4ff_tag_t *tag = &data->tags[metaptr];
1942                         const char *std_meta_atom = find_standard_meta(tag->item);
1943                         if (std_meta_atom) {
1944                                 membuffer_write_std_tag(buf, std_meta_atom,
1945                                                         tag->value);
1946                         } else {
1947                                 membuffer_write_custom_tag(buf, tag->item,
1948                                         tag->value);
1949                         }
1950                 }
1951         }
1952
1953         free(mask);
1954
1955         if (membuffer_error(buf)) {
1956                 membuffer_free(buf);
1957                 return 0;
1958         }
1959
1960         *out_size = membuffer_get_size(buf);
1961         *out_buffer = membuffer_detach(buf);
1962         membuffer_free(buf);
1963
1964         return 1;
1965 }
1966
1967 static void membuffer_write_atom(membuffer * buf, const char *name, unsigned size,
1968                           const void *data)
1969 {
1970         membuffer_write_int32(buf, size + 8);
1971         membuffer_write_atom_name(buf, name);
1972         membuffer_write(buf, data, size);
1973 }
1974
1975 static void *membuffer_get_ptr(const membuffer * buf)
1976 {
1977         return buf->data;
1978 }
1979
1980 static void membuffer_set_error(membuffer * buf)
1981 {
1982         buf->error = 1;
1983 }
1984
1985 static unsigned membuffer_transfer_from_file(membuffer * buf, mp4ff_t * src,
1986                 unsigned bytes)
1987 {
1988         unsigned oldsize;
1989         void *bufptr;
1990
1991         oldsize = membuffer_get_size(buf);
1992         if (membuffer_write(buf, 0, bytes) != bytes)
1993                 return 0;
1994
1995         bufptr = membuffer_get_ptr(buf);
1996         if (bufptr == 0)
1997                 return 0;
1998
1999         if ((unsigned) mp4ff_read_data(src, (char *) bufptr + oldsize, bytes) !=
2000                 bytes) {
2001                 membuffer_set_error(buf);
2002                 return 0;
2003         }
2004
2005         return bytes;
2006 }
2007
2008 static uint32_t create_meta(const mp4ff_metadata_t * data, void **out_buffer,
2009                 uint32_t * out_size)
2010 {
2011         membuffer *buf;
2012         uint32_t ilst_size;
2013         void *ilst_buffer;
2014
2015         if (!create_ilst(data, &ilst_buffer, &ilst_size))
2016                 return 0;
2017
2018         buf = membuffer_create();
2019
2020         membuffer_write_int32(buf, 0);
2021         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
2022         free(ilst_buffer);
2023
2024         *out_size = membuffer_get_size(buf);
2025         *out_buffer = membuffer_detach(buf);
2026         membuffer_free(buf);
2027         return 1;
2028 }
2029
2030 static uint32_t create_udta(const mp4ff_metadata_t * data, void **out_buffer,
2031 uint32_t * out_size)
2032 {
2033         membuffer *buf;
2034         uint32_t meta_size;
2035         void *meta_buffer;
2036
2037         if (!create_meta(data, &meta_buffer, &meta_size))
2038                 return 0;
2039
2040         buf = membuffer_create();
2041
2042         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
2043
2044         free(meta_buffer);
2045
2046         *out_size = membuffer_get_size(buf);
2047         *out_buffer = membuffer_detach(buf);
2048         membuffer_free(buf);
2049         return 1;
2050 }
2051
2052 static uint32_t fix_byte_order_32(uint32_t src)
2053 {
2054         uint32_t result;
2055         uint32_t a, b, c, d;
2056         int8_t data[4];
2057
2058         memcpy(data, &src, sizeof (src));
2059         a = (uint8_t) data[0];
2060         b = (uint8_t) data[1];
2061         c = (uint8_t) data[2];
2062         d = (uint8_t) data[3];
2063
2064         result = (a << 24) | (b << 16) | (c << 8) | d;
2065         return (uint32_t) result;
2066 }
2067
2068 static uint32_t modify_moov(mp4ff_t * f, const mp4ff_metadata_t * data,
2069                 void **out_buffer, uint32_t * out_size)
2070 {
2071         uint64_t total_base = f->moov_offset + 8;
2072         uint32_t total_size = (uint32_t) (f->moov_size - 8);
2073
2074         uint64_t udta_offset, meta_offset, ilst_offset;
2075         uint32_t udta_size, meta_size, ilst_size;
2076
2077         uint32_t new_ilst_size;
2078         void *new_ilst_buffer;
2079
2080         uint8_t *p_out;
2081         int32_t size_delta;
2082
2083         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
2084                 membuffer *buf;
2085                 void *new_udta_buffer;
2086                 uint32_t new_udta_size;
2087                 if (!create_udta(data, &new_udta_buffer, &new_udta_size))
2088                         return 0;
2089
2090                 buf = membuffer_create();
2091                 mp4ff_set_position(f, total_base);
2092                 membuffer_transfer_from_file(buf, f, total_size);
2093
2094                 membuffer_write_atom(buf, "udta", new_udta_size,
2095                         new_udta_buffer);
2096
2097                 free(new_udta_buffer);
2098
2099                 *out_size = membuffer_get_size(buf);
2100                 *out_buffer = membuffer_detach(buf);
2101                 membuffer_free(buf);
2102                 return 1;
2103         } else {
2104                 udta_offset = mp4ff_position(f);
2105                 udta_size = mp4ff_read_int32(f);
2106                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
2107                         membuffer *buf;
2108                         void *new_meta_buffer;
2109                         uint32_t new_meta_size;
2110                         if (!create_meta(data, &new_meta_buffer, &new_meta_size))
2111                                 return 0;
2112
2113                         buf = membuffer_create();
2114                         mp4ff_set_position(f, total_base);
2115                         membuffer_transfer_from_file(buf, f,
2116                                 (uint32_t)(udta_offset - total_base));
2117
2118                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
2119                         membuffer_write_atom_name(buf, "udta");
2120                         membuffer_transfer_from_file(buf, f, udta_size);
2121
2122                         membuffer_write_atom(buf, "meta", new_meta_size,
2123                                 new_meta_buffer);
2124                         free(new_meta_buffer);
2125
2126                         *out_size = membuffer_get_size(buf);
2127                         *out_buffer = membuffer_detach(buf);
2128                         membuffer_free(buf);
2129                         return 1;
2130                 }
2131                 meta_offset = mp4ff_position(f);
2132                 meta_size = mp4ff_read_int32(f);
2133                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
2134                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
2135                 ilst_offset = mp4ff_position(f);
2136                 ilst_size = mp4ff_read_int32(f);
2137
2138                 if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
2139                         return 0;
2140
2141                 size_delta = new_ilst_size - (ilst_size - 8);
2142
2143                 *out_size = total_size + size_delta;
2144                 *out_buffer = malloc(*out_size);
2145                 if (*out_buffer == 0) {
2146                         free(new_ilst_buffer);
2147                         return 0;
2148                 }
2149
2150                 p_out = (uint8_t *) * out_buffer;
2151
2152                 mp4ff_set_position(f, total_base);
2153                 mp4ff_read_data(f, p_out,
2154                                 (uint32_t) (udta_offset - total_base));
2155                 p_out += (uint32_t) (udta_offset - total_base);
2156                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2157                 p_out += 4;
2158                 mp4ff_read_data(f, p_out, 4);
2159                 p_out += 4;
2160                 mp4ff_read_data(f, p_out,
2161                                 (uint32_t) (meta_offset - udta_offset - 8));
2162                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
2163                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2164                 p_out += 4;
2165                 mp4ff_read_data(f, p_out, 4);
2166                 p_out += 4;
2167                 mp4ff_read_data(f, p_out,
2168                                 (uint32_t) (ilst_offset - meta_offset - 8));
2169                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
2170                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2171                 p_out += 4;
2172                 mp4ff_read_data(f, p_out, 4);
2173                 p_out += 4;
2174
2175                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
2176                 p_out += new_ilst_size;
2177
2178                 mp4ff_set_position(f, ilst_offset + ilst_size);
2179                 mp4ff_read_data(f, p_out, (uint32_t) (total_size
2180                         - (ilst_offset - total_base) - ilst_size));
2181
2182                 free(new_ilst_buffer);
2183         }
2184         return 1;
2185 }
2186
2187 static int32_t mp4ff_write_data(mp4ff_t * f, void *data, uint32_t size)
2188 {
2189         int32_t result = 1;
2190
2191         result = f->stream->write(f->stream->user_data, data, size);
2192
2193         f->current_position += size;
2194
2195         return result;
2196 }
2197
2198 static int32_t mp4ff_write_int32(mp4ff_t * f, const uint32_t data)
2199 {
2200         uint32_t result;
2201         uint32_t a, b, c, d;
2202         int8_t temp[4];
2203
2204         *(uint32_t *) temp = data;
2205         a = (uint8_t) temp[0];
2206         b = (uint8_t) temp[1];
2207         c = (uint8_t) temp[2];
2208         d = (uint8_t) temp[3];
2209
2210         result = (a << 24) | (b << 16) | (c << 8) | d;
2211
2212         return mp4ff_write_data(f, (uint8_t *) & result, sizeof (result));
2213 }
2214
2215 static int32_t mp4ff_truncate(mp4ff_t * f)
2216 {
2217         return f->stream->truncate(f->stream->user_data);
2218 }
2219
2220 int32_t mp4ff_meta_update(mp4ff_callback_t * f, const mp4ff_metadata_t * data)
2221 {
2222         void *new_moov_data;
2223         uint32_t new_moov_size;
2224
2225         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
2226
2227         memset(ff, 0, sizeof (mp4ff_t));
2228         ff->stream = f;
2229         mp4ff_set_position(ff, 0);
2230
2231         parse_atoms(ff, 1);
2232
2233         if (!modify_moov(ff, data, &new_moov_data, &new_moov_size)) {
2234                 mp4ff_close(ff);
2235                 return 0;
2236         }
2237
2238         /* copy moov atom to end of the file */
2239         if (ff->last_atom != ATOM_MOOV) {
2240                 char *free_data = "free";
2241
2242                 /* rename old moov to free */
2243                 mp4ff_set_position(ff, ff->moov_offset + 4);
2244                 mp4ff_write_data(ff, free_data, 4);
2245
2246                 mp4ff_set_position(ff, ff->file_size);
2247                 mp4ff_write_int32(ff, new_moov_size + 8);
2248                 mp4ff_write_data(ff, "moov", 4);
2249                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2250         } else {
2251                 mp4ff_set_position(ff, ff->moov_offset);
2252                 mp4ff_write_int32(ff, new_moov_size + 8);
2253                 mp4ff_write_data(ff, "moov", 4);
2254                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2255         }
2256
2257         mp4ff_truncate(ff);
2258
2259         mp4ff_close(ff);
2260         return 1;
2261 }
2262
2263 /* find a metadata item by name */
2264 /* returns 0 if item found, 1 if no such item */
2265 static int32_t mp4ff_meta_find_by_name(const mp4ff_t * f, const char *item,
2266                 char **value)
2267 {
2268         uint32_t i;
2269
2270         for (i = 0; i < f->tags.count; i++) {
2271                 if (!stricmp(f->tags.tags[i].item, item)) {
2272                         *value = strdup(f->tags.tags[i].value);
2273                         return 1;
2274                 }
2275         }
2276
2277         *value = NULL;
2278
2279         /* not found */
2280         return 0;
2281 }
2282
2283 int32_t mp4ff_meta_get_artist(const mp4ff_t * f, char **value)
2284 {
2285         return mp4ff_meta_find_by_name(f, "artist", value);
2286 }
2287
2288 int32_t mp4ff_meta_get_title(const mp4ff_t * f, char **value)
2289 {
2290         return mp4ff_meta_find_by_name(f, "title", value);
2291 }
2292
2293 int32_t mp4ff_meta_get_date(const mp4ff_t * f, char **value)
2294 {
2295         return mp4ff_meta_find_by_name(f, "date", value);
2296 }
2297
2298 int32_t mp4ff_meta_get_album(const mp4ff_t * f, char **value)
2299 {
2300         return mp4ff_meta_find_by_name(f, "album", value);
2301 }
2302
2303 int32_t mp4ff_meta_get_comment(const mp4ff_t * f, char **value)
2304 {
2305         return mp4ff_meta_find_by_name(f, "comment", value);
2306 }