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