]> git.tuebingen.mpg.de Git - paraslash.git/blob - mp4.c
d04137a911cebf83f516a1b5abce3732b080c845
[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 int32_t mp4ff_read_data(mp4ff_t * f, int8_t * 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 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 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 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 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 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 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 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 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 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         uint64_t size;
728         int32_t i;
729         uint8_t atom_type = 0;
730         uint8_t header_size = 0;
731
732         if (f->total_tracks == 0)
733                 return f->error++;
734
735         for (i = 0; i < 6; i++) {
736                 mp4ff_read_char(f);     /* reserved */
737         }
738         /* data_reference_index */ mp4ff_read_int16(f);
739
740         mp4ff_read_int32(f);    /* reserved */
741         mp4ff_read_int32(f);    /* reserved */
742
743         f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f);
744         f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f);
745
746         mp4ff_read_int16(f);
747         mp4ff_read_int16(f);
748
749         f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f);
750
751         mp4ff_read_int16(f);
752
753         size = mp4ff_atom_read_header(f, &atom_type, &header_size);
754         if (atom_type == ATOM_ESDS) {
755                 mp4ff_read_esds(f);
756         }
757
758         return 0;
759 }
760
761 static int32_t mp4ff_read_stsd(mp4ff_t * f)
762 {
763         int32_t i;
764         uint8_t header_size = 0;
765
766         /* CVE-2017-9218 */
767         if (f->total_tracks == 0)
768                 return f->error++;
769
770         mp4ff_read_char(f);     /* version */
771         mp4ff_read_int24(f);    /* flags */
772
773         f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f);
774
775         for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count && !f->stream->read_error; i++) {       /* CVE-2017-9253 */
776                 uint64_t skip = mp4ff_position(f);
777                 uint64_t size;
778                 uint8_t atom_type = 0;
779                 size = mp4ff_atom_read_header(f, &atom_type, &header_size);
780                 skip += size;
781
782                 if (atom_type == ATOM_MP4A) {
783                         f->track[f->total_tracks - 1]->type = TRACK_AUDIO;
784                         mp4ff_read_mp4a(f);
785                 } else if (atom_type == ATOM_MP4V) {
786                         f->track[f->total_tracks - 1]->type = TRACK_VIDEO;
787                 } else if (atom_type == ATOM_MP4S) {
788                         f->track[f->total_tracks - 1]->type = TRACK_SYSTEM;
789                 } else {
790                         f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN;
791                 }
792
793                 mp4ff_set_position(f, skip);
794         }
795
796         return 0;
797 }
798
799 static int32_t mp4ff_read_mvhd(mp4ff_t * f)
800 {
801         int32_t i;
802
803         mp4ff_read_char(f);     /* version */
804         mp4ff_read_int24(f);    /* flags */
805         /* creation_time */ mp4ff_read_int32(f);
806         /* modification_time */ mp4ff_read_int32(f);
807         f->time_scale = mp4ff_read_int32(f);
808         f->duration = mp4ff_read_int32(f);
809                                                         /* preferred_rate */ mp4ff_read_int32(f);
810                                                         /*mp4ff_read_fixed32(f); */
811                                                         /* preferred_volume */ mp4ff_read_int16(f);
812                                                         /*mp4ff_read_fixed16(f); */
813         for (i = 0; i < 10; i++) {
814                 /* reserved */ mp4ff_read_char(f);
815         }
816         for (i = 0; i < 9; i++) {
817                 mp4ff_read_int32(f);    /* matrix */
818         }
819         /* preview_time */ mp4ff_read_int32(f);
820         /* preview_duration */ mp4ff_read_int32(f);
821         /* poster_time */ mp4ff_read_int32(f);
822         /* selection_time */ mp4ff_read_int32(f);
823         /* selection_duration */ mp4ff_read_int32(f);
824         /* current_time */ mp4ff_read_int32(f);
825         /* next_track_id */ mp4ff_read_int32(f);
826
827         return 0;
828 }
829
830 static int32_t mp4ff_tag_add_field(mp4ff_metadata_t * tags, const char *item,
831                  char *value, int32_t len)
832 {
833         void *backup = (void *) tags->tags;
834
835         if (!item || (item && !*item) || !value)
836                 return 0;
837
838         tags->tags = (mp4ff_tag_t *) realloc(tags->tags,
839                 (tags->count + 1) * sizeof (mp4ff_tag_t));
840         if (!tags->tags) {
841                 if (backup)
842                         free(backup);
843                 return 0;
844         } else {
845                 tags->tags[tags->count].item = strdup(item);
846                 tags->tags[tags->count].len = len;
847                 if (len >= 0) {
848                         tags->tags[tags->count].value = malloc(len + 1);
849                         if (tags->tags[tags->count].value != NULL) {
850                                 memcpy(tags->tags[tags->count].value, value, len);
851                                 tags->tags[tags->count].value[len] = 0;
852                         }
853                 } else {
854                         tags->tags[tags->count].value = strdup(value);
855                 }
856
857                 if (!tags->tags[tags->count].item || !tags->tags[tags->count].value) {
858                         if (!tags->tags[tags->count].item)
859                                 free(tags->tags[tags->count].item);
860                         if (!tags->tags[tags->count].value)
861                                 free(tags->tags[tags->count].value);
862                         tags->tags[tags->count].item = NULL;
863                         tags->tags[tags->count].value = NULL;
864                         tags->tags[tags->count].len = 0;
865                         return 0;
866                 }
867
868                 tags->count++;
869                 return 1;
870         }
871 }
872
873 static const char *ID3v1GenreList[] = {
874         "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
875         "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
876         "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
877         "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
878         "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal",
879         "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid",
880         "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
881         "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
882         "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
883         "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
884         "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40",
885         "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
886         "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
887         "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
888         "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk",
889         "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic",
890         "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock",
891         "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
892         "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
893         "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
894         "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
895         "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
896         "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
897         "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
898         "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
899         "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover",
900         "Contemporary C", "Christian Rock", "Merengue", "Salsa", "Thrash Metal",
901         "Anime", "JPop", "SynthPop",
902 };
903
904 const char *mp4ff_meta_index_to_genre(uint32_t idx)
905 {
906         if (idx > 0 && idx <= sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0])) {
907                 return ID3v1GenreList[idx - 1];
908         } else {
909                 return 0;
910         }
911 }
912
913 char *mp4ff_read_string(mp4ff_t * f, uint32_t length)
914 {
915         char *str = (char *) malloc(length + 1);
916         if (str != 0) {
917                 if ((uint32_t) mp4ff_read_data(f, str, length) != length) {
918                         free(str);
919                         str = 0;
920                 } else {
921                         str[length] = 0;
922                 }
923         }
924         return str;
925 }
926
927 static int32_t mp4ff_set_metadata_name(mp4ff_t * f, const uint8_t atom_type,
928                 char **name)
929 {
930         static char *tag_names[] = {
931                 "unknown", "title", "artist", "writer", "album",
932                 "date", "tool", "comment", "genre", "track",
933                 "disc", "compilation", "genre", "tempo", "cover",
934                 "album_artist", "contentgroup", "lyrics", "description",
935                 "network", "show", "episodename",
936                 "sorttitle", "sortalbum", "sortartist", "sortalbumartist",
937                 "sortwriter", "sortshow",
938                 "season", "episode", "podcast"
939         };
940         uint8_t tag_idx = 0;
941
942         switch (atom_type) {
943         case ATOM_TITLE:
944                 tag_idx = 1;
945                 break;
946         case ATOM_ARTIST:
947                 tag_idx = 2;
948                 break;
949         case ATOM_WRITER:
950                 tag_idx = 3;
951                 break;
952         case ATOM_ALBUM:
953                 tag_idx = 4;
954                 break;
955         case ATOM_DATE:
956                 tag_idx = 5;
957                 break;
958         case ATOM_TOOL:
959                 tag_idx = 6;
960                 break;
961         case ATOM_COMMENT:
962                 tag_idx = 7;
963                 break;
964         case ATOM_GENRE1:
965                 tag_idx = 8;
966                 break;
967         case ATOM_TRACK:
968                 tag_idx = 9;
969                 break;
970         case ATOM_DISC:
971                 tag_idx = 10;
972                 break;
973         case ATOM_COMPILATION:
974                 tag_idx = 11;
975                 break;
976         case ATOM_GENRE2:
977                 tag_idx = 12;
978                 break;
979         case ATOM_TEMPO:
980                 tag_idx = 13;
981                 break;
982         case ATOM_COVER:
983                 tag_idx = 14;
984                 break;
985         case ATOM_ALBUM_ARTIST:
986                 tag_idx = 15;
987                 break;
988         case ATOM_CONTENTGROUP:
989                 tag_idx = 16;
990                 break;
991         case ATOM_LYRICS:
992                 tag_idx = 17;
993                 break;
994         case ATOM_DESCRIPTION:
995                 tag_idx = 18;
996                 break;
997         case ATOM_NETWORK:
998                 tag_idx = 19;
999                 break;
1000         case ATOM_SHOW:
1001                 tag_idx = 20;
1002                 break;
1003         case ATOM_EPISODENAME:
1004                 tag_idx = 21;
1005                 break;
1006         case ATOM_SORTTITLE:
1007                 tag_idx = 22;
1008                 break;
1009         case ATOM_SORTALBUM:
1010                 tag_idx = 23;
1011                 break;
1012         case ATOM_SORTARTIST:
1013                 tag_idx = 24;
1014                 break;
1015         case ATOM_SORTALBUMARTIST:
1016                 tag_idx = 25;
1017                 break;
1018         case ATOM_SORTWRITER:
1019                 tag_idx = 26;
1020                 break;
1021         case ATOM_SORTSHOW:
1022                 tag_idx = 27;
1023                 break;
1024         case ATOM_SEASON:
1025                 tag_idx = 28;
1026                 break;
1027         case ATOM_EPISODE:
1028                 tag_idx = 29;
1029                 break;
1030         case ATOM_PODCAST:
1031                 tag_idx = 30;
1032                 break;
1033         default:
1034                 tag_idx = 0;
1035                 break;
1036         }
1037
1038         *name = strdup(tag_names[tag_idx]);
1039
1040         return 0;
1041 }
1042
1043 static int32_t mp4ff_parse_tag(mp4ff_t * f, const uint8_t parent_atom_type,
1044                 const int32_t size)
1045 {
1046         uint8_t atom_type;
1047         uint8_t header_size = 0;
1048         uint64_t subsize, sumsize = 0;
1049         char *name = NULL;
1050         char *data = NULL;
1051         uint32_t done = 0;
1052         uint32_t len = 0;
1053
1054         while (sumsize < size && !f->stream->read_error) {      /* CVE-2017-9222 */
1055                 uint64_t destpos;
1056                 subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
1057                 destpos = mp4ff_position(f) + subsize - header_size;
1058                 if (!done) {
1059                         if (atom_type == ATOM_DATA) {
1060                                 mp4ff_read_char(f);     /* version */
1061                                 mp4ff_read_int24(f);    /* flags */
1062                                 mp4ff_read_int32(f);    /* reserved */
1063
1064                                 /* some need special attention */
1065                                 if (parent_atom_type == ATOM_GENRE2 || parent_atom_type == ATOM_TEMPO) {
1066                                         if (subsize - header_size >= 8 + 2) {
1067                                                 uint16_t val = mp4ff_read_int16(f);
1068
1069                                                 if (parent_atom_type == ATOM_TEMPO) {
1070                                                         char temp[16];
1071                                                         sprintf(temp,
1072                                                                 "%.5u BPM",
1073                                                                 val);
1074                                                         mp4ff_tag_add_field(&(f-> tags), "tempo", temp, -1);
1075                                                 } else {
1076                                                         const char *temp = mp4ff_meta_index_to_genre(val);
1077                                                         if (temp) {
1078                                                                 mp4ff_tag_add_field (&(f->tags), "genre", temp, -1);
1079                                                         }
1080                                                 }
1081                                                 done = 1;
1082                                         }
1083                                 } else if (parent_atom_type == ATOM_TRACK || parent_atom_type == ATOM_DISC) {
1084                                         /* if (!done && subsize - header_size >= 8 + 8) */
1085                                         /* modified by AJS */
1086                                         if (!done && (subsize - header_size) >= (sizeof (char) + sizeof (uint8_t) * 3 + sizeof (uint32_t) +     /* version + flags + reserved */
1087                                                                                  +(parent_atom_type == ATOM_TRACK ? sizeof (uint16_t) : 0)      /* leading uint16_t if ATOM_TRACK */
1088                                                                                  +sizeof (uint16_t)     /* track / disc */
1089                                                                                  +sizeof (uint16_t))    /* totaltracks / totaldiscs */) {
1090                                                 uint16_t index, total;
1091                                                 char temp[32];
1092                                                 mp4ff_read_int16(f);
1093                                                 index = mp4ff_read_int16(f);
1094                                                 total = mp4ff_read_int16(f);
1095                                                 if (parent_atom_type == ATOM_TRACK)
1096                                                         mp4ff_read_int16(f);
1097
1098                                                 sprintf(temp, "%d", index);
1099                                                 mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ?
1100                                                         "track" : "disc", temp, -1);
1101                                                 if (total > 0) {
1102                                                         sprintf(temp, "%d",
1103                                                                 total);
1104                                                         mp4ff_tag_add_field(& (f-> tags),
1105                                                                 parent_atom_type == ATOM_TRACK?
1106                                                                 "totaltracks" : "totaldiscs", temp, -1);
1107                                                 }
1108                                                 done = 1;
1109                                         }
1110                                 } else {
1111                                         if (data) {
1112                                                 free(data);
1113                                                 data = NULL;
1114                                         }
1115                                         data = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 8)));
1116                                         len = (uint32_t) (subsize - (header_size + 8));
1117                                 }
1118                         } else if (atom_type == ATOM_NAME) {
1119                                 if (!done) {
1120                                         mp4ff_read_char(f);     /* version */
1121                                         mp4ff_read_int24(f);    /* flags */
1122                                         if (name)
1123                                                 free(name);
1124                                         name = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 4)));
1125                                 }
1126                         }
1127                         mp4ff_set_position(f, destpos);
1128                         sumsize += subsize;
1129                 }
1130         }
1131
1132         if (data) {
1133                 if (!done) {
1134                         if (name == NULL)
1135                                 mp4ff_set_metadata_name(f, parent_atom_type,
1136                                                         &name);
1137                         if (name)
1138                                 mp4ff_tag_add_field(&(f->tags), name, data, len);
1139                 }
1140
1141                 free(data);
1142         }
1143         if (name)
1144                 free(name);
1145         return 1;
1146 }
1147 static int32_t mp4ff_read_mdhd(mp4ff_t * f)
1148 {
1149         uint32_t version;
1150
1151         /* CVE-2017-9221 */
1152         if (f->total_tracks == 0)
1153                 return f->error++;
1154
1155         version = mp4ff_read_int32(f);
1156         if (version == 1) {
1157                 mp4ff_read_int64(f);    //creation-time
1158                 mp4ff_read_int64(f);    //modification-time
1159                 f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f); //timescale
1160                 f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);  //duration
1161         } else                  //version == 0
1162         {
1163                 uint32_t temp;
1164
1165                 mp4ff_read_int32(f);    //creation-time
1166                 mp4ff_read_int32(f);    //modification-time
1167                 f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f); //timescale
1168                 temp = mp4ff_read_int32(f);
1169                 f->track[f->total_tracks - 1]->duration = (temp == (uint32_t) (-1)) ? (uint64_t) (-1) : (uint64_t) (temp);
1170         }
1171         mp4ff_read_int16(f);
1172         mp4ff_read_int16(f);
1173         return 1;
1174 }
1175
1176 int32_t mp4ff_parse_metadata(mp4ff_t * f, const int32_t size)
1177 {
1178         uint64_t subsize, sumsize = 0;
1179         uint8_t atom_type;
1180         uint8_t header_size = 0;
1181
1182         while (sumsize < size) {
1183                 subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
1184                 if (subsize == 0)
1185                         break;
1186                 mp4ff_parse_tag(f, atom_type,
1187                                 (uint32_t) (subsize - header_size));
1188                 sumsize += subsize;
1189         }
1190
1191         return 0;
1192 }
1193
1194 static int32_t mp4ff_read_meta(mp4ff_t * f, const uint64_t size)
1195 {
1196         uint64_t subsize, sumsize = 0;
1197         uint8_t atom_type;
1198         uint8_t header_size = 0;
1199
1200         mp4ff_read_char(f);     /* version */
1201         mp4ff_read_int24(f);    /* flags */
1202
1203         while (sumsize < (size - (header_size + 4))) {
1204                 subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
1205                 if (subsize <= header_size + 4)
1206                         return 1;
1207                 if (atom_type == ATOM_ILST) {
1208                         mp4ff_parse_metadata(f, (uint32_t) (subsize - (header_size + 4)));
1209                 } else {
1210                         mp4ff_set_position(f, mp4ff_position(f) + subsize - header_size);
1211                 }
1212                 sumsize += subsize;
1213         }
1214
1215         return 0;
1216 }
1217
1218 int32_t mp4ff_atom_read(mp4ff_t * f, const int32_t size,
1219                         const uint8_t atom_type)
1220 {
1221         uint64_t dest_position = mp4ff_position(f) + size - 8;
1222         if (atom_type == ATOM_STSZ) {
1223                 /* sample size box */
1224                 mp4ff_read_stsz(f);
1225         } else if (atom_type == ATOM_STTS) {
1226                 /* time to sample box */
1227                 mp4ff_read_stts(f);
1228         } else if (atom_type == ATOM_CTTS) {
1229                 /* composition offset box */
1230                 mp4ff_read_ctts(f);
1231         } else if (atom_type == ATOM_STSC) {
1232                 /* sample to chunk box */
1233                 mp4ff_read_stsc(f);
1234         } else if (atom_type == ATOM_STCO) {
1235                 /* chunk offset box */
1236                 mp4ff_read_stco(f);
1237         } else if (atom_type == ATOM_STSD) {
1238                 /* sample description box */
1239                 mp4ff_read_stsd(f);
1240         } else if (atom_type == ATOM_MVHD) {
1241                 /* movie header box */
1242                 mp4ff_read_mvhd(f);
1243         } else if (atom_type == ATOM_MDHD) {
1244                 /* track header */
1245                 mp4ff_read_mdhd(f);
1246 #ifdef USE_TAGGING
1247         } else if (atom_type == ATOM_META) {
1248                 /* iTunes Metadata box */
1249                 mp4ff_read_meta(f, size);
1250 #endif
1251         }
1252
1253         mp4ff_set_position(f, dest_position);
1254         return 0;
1255 }
1256
1257 /* parse atoms that are sub atoms of other atoms */
1258 int32_t parse_sub_atoms(mp4ff_t * f, const uint64_t total_size, int meta_only)
1259 {
1260         uint64_t size;
1261         uint8_t atom_type = 0;
1262         uint64_t counted_size = 0;
1263         uint8_t header_size = 0;
1264
1265         while (counted_size < total_size) {
1266                 size = mp4ff_atom_read_header(f, &atom_type, &header_size);
1267                 counted_size += size;
1268
1269                 /* check for end of file */
1270                 if (size == 0)
1271                         break;
1272
1273                 /* we're starting to read a new track, update index,
1274                  * so that all data and tables get written in the right place
1275                  */
1276                 if (atom_type == ATOM_TRAK) {
1277                         mp4ff_track_add(f);
1278                 }
1279
1280                 /* parse subatoms */
1281                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1282                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1283                 } else if (atom_type < SUBATOMIC) {
1284                         parse_sub_atoms(f, size - header_size, meta_only);
1285                 } else {
1286                         mp4ff_atom_read(f, (uint32_t) size, atom_type);
1287                 }
1288         }
1289
1290         return 0;
1291 }
1292
1293 /* parse root atoms */
1294 int32_t parse_atoms(mp4ff_t * f, int meta_only)
1295 {
1296         uint64_t size;
1297         uint8_t atom_type = 0;
1298         uint8_t header_size = 0;
1299
1300         f->file_size = 0;
1301         f->stream->read_error = 0;
1302
1303         while ((size =
1304                 mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0) {
1305                 f->file_size += size;
1306                 f->last_atom = atom_type;
1307
1308                 if (atom_type == ATOM_MDAT && f->moov_read) {
1309                         /* moov atom is before mdat, we can stop reading when mdat is encountered */
1310                         /* file position will stay at beginning of mdat data */
1311 //            break;
1312                 }
1313
1314                 if (atom_type == ATOM_MOOV && size > header_size) {
1315                         f->moov_read = 1;
1316                         f->moov_offset = mp4ff_position(f) - header_size;
1317                         f->moov_size = size;
1318                 }
1319
1320                 /* parse subatoms */
1321                 if (meta_only && !need_parse_when_meta_only(atom_type)) {
1322                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1323                 } else if (atom_type < SUBATOMIC) {
1324                         parse_sub_atoms(f, size - header_size, meta_only);
1325                 } else {
1326                         /* skip this atom */
1327                         mp4ff_set_position(f, mp4ff_position(f) + size - header_size);
1328                 }
1329         }
1330
1331         return 0;
1332 }
1333
1334 int32_t mp4ff_get_decoder_config(const mp4ff_t * f, const int track,
1335                                  unsigned char **ppBuf, unsigned int *pBufSize)
1336 {
1337         if (track >= f->total_tracks) {
1338                 *ppBuf = NULL;
1339                 *pBufSize = 0;
1340                 return 1;
1341         }
1342
1343         if (f->track[track]->decoderConfig == NULL
1344                 || f->track[track]->decoderConfigLen == 0) {
1345                 *ppBuf = NULL;
1346                 *pBufSize = 0;
1347         } else {
1348                 *ppBuf = malloc(f->track[track]->decoderConfigLen);
1349                 if (*ppBuf == NULL) {
1350                         *pBufSize = 0;
1351                         return 1;
1352                 }
1353                 memcpy(*ppBuf, f->track[track]->decoderConfig,
1354                         f->track[track]->decoderConfigLen);
1355                 *pBufSize = f->track[track]->decoderConfigLen;
1356         }
1357 }
1358
1359 mp4ff_t *mp4ff_open_read(mp4ff_callback_t * f)
1360 {
1361         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
1362
1363         memset(ff, 0, sizeof (mp4ff_t));
1364
1365         ff->stream = f;
1366
1367         parse_atoms(ff, 0);
1368
1369         if (ff->error) {
1370                 free(ff);
1371                 ff = NULL;
1372         }
1373
1374         return ff;
1375 }
1376
1377 int32_t mp4ff_tag_delete(mp4ff_metadata_t * tags)
1378 {
1379         uint32_t i;
1380
1381         for (i = 0; i < tags->count; i++) {
1382                 if (tags->tags[i].item)
1383                         free(tags->tags[i].item);
1384                 if (tags->tags[i].value)
1385                         free(tags->tags[i].value);
1386         }
1387
1388         if (tags->tags)
1389                 free(tags->tags);
1390
1391         tags->tags = NULL;
1392         tags->count = 0;
1393
1394         return 0;
1395 }
1396
1397 void mp4ff_close(mp4ff_t * ff)
1398 {
1399         int32_t i;
1400
1401         for (i = 0; i < ff->total_tracks; i++) {
1402                 if (ff->track[i]) {
1403                         if (ff->track[i]->stsz_table)
1404                                 free(ff->track[i]->stsz_table);
1405                         if (ff->track[i]->stts_sample_count)
1406                                 free(ff->track[i]->stts_sample_count);
1407                         if (ff->track[i]->stts_sample_delta)
1408                                 free(ff->track[i]->stts_sample_delta);
1409                         if (ff->track[i]->stsc_first_chunk)
1410                                 free(ff->track[i]->stsc_first_chunk);
1411                         if (ff->track[i]->stsc_samples_per_chunk)
1412                                 free(ff->track[i]->stsc_samples_per_chunk);
1413                         if (ff->track[i]->stsc_sample_desc_index)
1414                                 free(ff->track[i]->stsc_sample_desc_index);
1415                         if (ff->track[i]->stco_chunk_offset)
1416                                 free(ff->track[i]->stco_chunk_offset);
1417                         if (ff->track[i]->decoderConfig)
1418                                 free(ff->track[i]->decoderConfig);
1419                         if (ff->track[i]->ctts_sample_count)
1420                                 free(ff->track[i]->ctts_sample_count);
1421                         if (ff->track[i]->ctts_sample_offset)
1422                                 free(ff->track[i]->ctts_sample_offset);
1423 #ifdef ITUNES_DRM
1424                         if (ff->track[i]->p_drms)
1425                                 drms_free(ff->track[i]->p_drms);
1426 #endif
1427                         free(ff->track[i]);
1428                 }
1429         }
1430
1431 #ifdef USE_TAGGING
1432         mp4ff_tag_delete(&(ff->tags));
1433 #endif
1434
1435         if (ff)
1436                 free(ff);
1437 }
1438
1439 static int32_t mp4ff_chunk_of_sample(const mp4ff_t * f, const int32_t track,
1440                 const int32_t sample, int32_t * chunk_sample, int32_t * chunk)
1441 {
1442         int32_t total_entries = 0;
1443         int32_t chunk2entry;
1444         int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
1445
1446         if (f->track[track] == NULL) {
1447                 return -1;
1448         }
1449
1450         total_entries = f->track[track]->stsc_entry_count;
1451
1452         chunk1 = 1;
1453         chunk1samples = 0;
1454         chunk2entry = 0;
1455
1456         do {
1457                 chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
1458                 *chunk = chunk2 - chunk1;
1459                 range_samples = *chunk * chunk1samples;
1460
1461                 if (sample < total + range_samples)
1462                         break;
1463
1464                 chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
1465                 chunk1 = chunk2;
1466
1467                 if (chunk2entry < total_entries) {
1468                         chunk2entry++;
1469                         total += range_samples;
1470                 }
1471         } while (chunk2entry < total_entries);
1472
1473         if (chunk1samples)
1474                 *chunk = (sample - total) / chunk1samples + chunk1;
1475         else
1476                 *chunk = 1;
1477
1478         *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
1479
1480         return 0;
1481 }
1482
1483 static int32_t mp4ff_chunk_to_offset(const mp4ff_t * f, const int32_t track,
1484                 const int32_t chunk)
1485 {
1486         const mp4ff_track_t *p_track = f->track[track];
1487
1488         if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) {
1489                 return p_track->stco_chunk_offset[p_track->stco_entry_count -
1490                                                   1];
1491         } else if (p_track->stco_entry_count) {
1492                 return p_track->stco_chunk_offset[chunk - 1];
1493         } else {
1494                 return 8;
1495         }
1496
1497         return 0;
1498 }
1499
1500 static int32_t mp4ff_sample_range_size(const mp4ff_t * f, const int32_t track,
1501                 const int32_t chunk_sample, const int32_t sample)
1502 {
1503         int32_t i, total;
1504         const mp4ff_track_t *p_track = f->track[track];
1505
1506         if (p_track->stsz_sample_size) {
1507                 return (sample - chunk_sample) * p_track->stsz_sample_size;
1508         } else {
1509                 if (sample >= p_track->stsz_sample_count)
1510                         return 0;       //error
1511
1512                 for (i = chunk_sample, total = 0; i < sample; i++) {
1513                         total += p_track->stsz_table[i];
1514                 }
1515         }
1516
1517         return total;
1518 }
1519 static int32_t mp4ff_sample_to_offset(const mp4ff_t * f, const int32_t track,
1520                 const int32_t sample)
1521 {
1522         int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
1523
1524         mp4ff_chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
1525
1526         chunk_offset1 = mp4ff_chunk_to_offset(f, track, chunk);
1527         chunk_offset2 = chunk_offset1 + mp4ff_sample_range_size(f,
1528                 track, chunk_sample, sample);
1529         return chunk_offset2;
1530 }
1531
1532 int32_t mp4ff_set_sample_position(mp4ff_t * f, const int32_t track,
1533                                   const int32_t sample)
1534 {
1535         int32_t offset;
1536
1537         offset = mp4ff_sample_to_offset(f, track, sample);
1538         mp4ff_set_position(f, offset);
1539
1540         return 0;
1541 }
1542
1543 int32_t mp4ff_audio_frame_size(const mp4ff_t * f, const int32_t track,
1544                 const int32_t sample)
1545 {
1546         int32_t bytes;
1547         const mp4ff_track_t *p_track = f->track[track];
1548
1549         if (p_track->stsz_sample_size) {
1550                 bytes = p_track->stsz_sample_size;
1551         } else {
1552                 bytes = p_track->stsz_table[sample];
1553         }
1554
1555         return bytes;
1556 }
1557
1558 int32_t mp4ff_read_sample_getsize(mp4ff_t * f, const int track,
1559                                   const int sample)
1560 {
1561         int32_t temp = mp4ff_audio_frame_size(f, track, sample);
1562         if (temp < 0)
1563                 temp = 0;
1564         return temp;
1565 }
1566
1567 uint32_t mp4ff_get_sample_rate(const mp4ff_t * f, const int32_t track)
1568 {
1569         return f->track[track]->sampleRate;
1570 }
1571
1572 uint32_t mp4ff_get_channel_count(const mp4ff_t * f, const int32_t track)
1573 {
1574         return f->track[track]->channelCount;
1575 }
1576
1577 int32_t mp4ff_num_samples(const mp4ff_t * f, const int32_t track)
1578 {
1579         int32_t i;
1580         int32_t total = 0;
1581
1582         for (i = 0; i < f->track[track]->stts_entry_count; i++) {
1583                 total += f->track[track]->stts_sample_count[i];
1584         }
1585         return total;
1586 }
1587
1588 mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t * f)
1589 {
1590         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
1591
1592         memset(ff, 0, sizeof (mp4ff_t));
1593
1594         ff->stream = f;
1595
1596         parse_atoms(ff, 1);
1597
1598         if (ff->error) {
1599                 free(ff);
1600                 ff = NULL;
1601         }
1602
1603         return ff;
1604 }
1605
1606 int32_t mp4ff_meta_get_num_items(const mp4ff_t * f)
1607 {
1608         return f->tags.count;
1609 }
1610
1611 int32_t mp4ff_meta_get_by_index(const mp4ff_t * f, uint32_t index,
1612                                 char **item, char **value)
1613 {
1614         if (index >= f->tags.count) {
1615                 *item = NULL;
1616                 *value = NULL;
1617                 return 0;
1618         } else {
1619                 *item = strdup(f->tags.tags[index].item);
1620                 *value = strdup(f->tags.tags[index].value);
1621                 return 1;
1622         }
1623 }
1624
1625 static uint32_t find_atom(mp4ff_t * f, uint64_t base, uint32_t size,
1626                           const char *name)
1627 {
1628         uint32_t remaining = size;
1629         uint64_t atom_offset = base;
1630         for (;;) {
1631                 char atom_name[4];
1632                 uint32_t atom_size;
1633
1634                 mp4ff_set_position(f, atom_offset);
1635
1636                 if (remaining < 8)
1637                         break;
1638                 atom_size = mp4ff_read_int32(f);
1639                 if (atom_size > remaining || atom_size < 8)
1640                         break;
1641                 mp4ff_read_data(f, atom_name, 4);
1642
1643                 if (!memcmp(atom_name, name, 4)) {
1644                         mp4ff_set_position(f, atom_offset);
1645                         return 1;
1646                 }
1647
1648                 remaining -= atom_size;
1649                 atom_offset += atom_size;
1650         }
1651         return 0;
1652 }
1653 static uint32_t find_atom_v2(mp4ff_t * f, uint64_t base, uint32_t size,
1654                 const char *name, uint32_t extraheaders, const char *name_inside)
1655 {
1656         uint64_t first_base = (uint64_t) (-1);
1657         while (find_atom(f, base, size, name))  //try to find atom <name> with atom <name_inside> in it
1658         {
1659                 uint64_t mybase = mp4ff_position(f);
1660                 uint32_t mysize = mp4ff_read_int32(f);
1661
1662                 if (first_base == (uint64_t) (-1))
1663                         first_base = mybase;
1664
1665                 if (mysize < 8 + extraheaders)
1666                         break;
1667
1668                 if (find_atom (f, mybase + (8 + extraheaders),
1669                                 mysize - (8 + extraheaders), name_inside)) {
1670                         mp4ff_set_position(f, mybase);
1671                         return 2;
1672                 }
1673                 base += mysize;
1674                 if (size <= mysize) {
1675                         size = 0;
1676                         break;
1677                 }
1678                 size -= mysize;
1679         }
1680
1681         if (first_base != (uint64_t) (-1))      //wanted atom inside not found
1682         {
1683                 mp4ff_set_position(f, first_base);
1684                 return 1;
1685         } else
1686                 return 0;
1687 }
1688
1689 typedef struct {
1690         void *data;
1691         unsigned written;
1692         unsigned allocated;
1693         unsigned error;
1694 } membuffer;
1695
1696 #define stricmp strcasecmp
1697
1698 membuffer *membuffer_create()
1699 {
1700         const unsigned initial_size = 256;
1701
1702         membuffer *buf = (membuffer *) malloc(sizeof (membuffer));
1703         buf->data = malloc(initial_size);
1704         buf->written = 0;
1705         buf->allocated = initial_size;
1706         buf->error = buf->data == 0 ? 1 : 0;
1707
1708         return buf;
1709 }
1710
1711 unsigned membuffer_write(membuffer * buf, const void *ptr, unsigned bytes)
1712 {
1713         unsigned dest_size = buf->written + bytes;
1714
1715         if (buf->error)
1716                 return 0;
1717         if (dest_size > buf->allocated) {
1718                 do {
1719                         buf->allocated <<= 1;
1720                 } while (dest_size > buf->allocated);
1721
1722                 {
1723                         void *newptr = realloc(buf->data, buf->allocated);
1724                         if (newptr == 0) {
1725                                 free(buf->data);
1726                                 buf->data = 0;
1727                                 buf->error = 1;
1728                                 return 0;
1729                         }
1730                         buf->data = newptr;
1731                 }
1732         }
1733
1734         if (ptr)
1735                 memcpy((char *) buf->data + buf->written, ptr, bytes);
1736         buf->written += bytes;
1737         return bytes;
1738 }
1739
1740 #define membuffer_write_data membuffer_write
1741
1742 unsigned membuffer_write_atom_name(membuffer * buf, const char *data)
1743 {
1744         return membuffer_write_data(buf, data, 4) == 4 ? 1 : 0;
1745 }
1746
1747 unsigned membuffer_write_int16(membuffer * buf, uint16_t data)
1748 {
1749         uint8_t temp[2] = { (uint8_t) (data >> 8), (uint8_t) data };
1750         return membuffer_write_data(buf, temp, 2);
1751 }
1752
1753 unsigned membuffer_write_int32(membuffer * buf, uint32_t data)
1754 {
1755         uint8_t temp[4] = { (uint8_t) (data >> 24), (uint8_t) (data >> 16),
1756                 (uint8_t) (data >> 8), (uint8_t) data };
1757         return membuffer_write_data(buf, temp, 4);
1758 }
1759
1760 static void membuffer_write_track_tag(membuffer * buf, const char *name,
1761                 uint32_t index, uint32_t total)
1762 {
1763         membuffer_write_int32(buf,
1764                 8 /*atom header */  + 8 /*data atom header */  +
1765                 8 /*flags + reserved */  + 8 /*actual data */ );
1766         membuffer_write_atom_name(buf, name);
1767         membuffer_write_int32(buf,
1768                 8 /*data atom header */  +
1769                 8 /*flags + reserved */  + 8 /*actual data */ );
1770         membuffer_write_atom_name(buf, "data");
1771         membuffer_write_int32(buf, 0);  //flags
1772         membuffer_write_int32(buf, 0);  //reserved
1773         membuffer_write_int16(buf, 0);
1774         membuffer_write_int16(buf, (uint16_t) index);   //track number
1775         membuffer_write_int16(buf, (uint16_t) total);   //total tracks
1776         membuffer_write_int16(buf, 0);
1777 }
1778
1779 static void membuffer_write_int16_tag(membuffer * buf, const char *name,
1780                 uint16_t value)
1781 {
1782         membuffer_write_int32(buf,
1783                 8 /*atom header */  + 8 /*data atom header */  +
1784                 8 /*flags + reserved */  + 2 /*actual data */ );
1785         membuffer_write_atom_name(buf, name);
1786         membuffer_write_int32(buf,
1787                 8 /*data atom header */  +
1788                 8 /*flags + reserved */  + 2 /*actual data */ );
1789         membuffer_write_atom_name(buf, "data");
1790         membuffer_write_int32(buf, 0);  //flags
1791         membuffer_write_int32(buf, 0);  //reserved
1792         membuffer_write_int16(buf, value);      //value
1793 }
1794
1795 static uint32_t myatoi(const char *param)
1796 {
1797         return param ? atoi(param) : 0;
1798 }
1799
1800 uint32_t mp4ff_meta_genre_to_index(const char *genrestr)
1801 {
1802         unsigned n;
1803         for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
1804                 if (!stricmp(genrestr, ID3v1GenreList[n]))
1805                         return n + 1;
1806         }
1807         return 0;
1808 }
1809
1810 typedef struct {
1811         const char *atom;
1812         const char *name;
1813 } stdmeta_entry;
1814
1815 static stdmeta_entry stdmetas[] = {
1816         {"\xA9" "nam", "title"},
1817         {"\xA9" "ART", "artist"},
1818         {"\xA9" "wrt", "writer"},
1819         {"\xA9" "alb", "album"},
1820         {"\xA9" "day", "date"},
1821         {"\xA9" "too", "tool"},
1822         {"\xA9" "cmt", "comment"},
1823 //      {"\xA9" "gen","genre"},
1824         {"cpil", "compilation"},
1825 //      {"trkn","track"},
1826 //      {"disk","disc"},
1827 //      {"gnre","genre"},
1828         {"covr", "cover"},
1829         /* added by AJS */
1830         {"aART", "album_artist"},
1831 };
1832
1833 static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
1834 {
1835         unsigned n;
1836         for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
1837                 if (!stricmp(name, stdmetas[n].name))
1838                         return stdmetas[n].atom;
1839         }
1840         return 0;
1841 }
1842
1843 static void membuffer_write_std_tag(membuffer * buf, const char *name,
1844                 const char *value)
1845 {
1846         /* added by AJS */
1847         uint32_t flags = 1;
1848
1849         /* special check for compilation flag */
1850         if (strcmp(name, "cpil") == 0) {
1851                 flags = 21;
1852         }
1853
1854         membuffer_write_int32(buf,
1855                 8 /*atom header */  + 8 /*data atom header */  +
1856                 8 /*flags + reserved */  + strlen(value));
1857         membuffer_write_atom_name(buf, name);
1858         membuffer_write_int32(buf,
1859                 8 /*data atom header */  +
1860                 8 /*flags + reserved */  + strlen(value));
1861         membuffer_write_atom_name(buf, "data");
1862         membuffer_write_int32(buf, flags);      //flags
1863         membuffer_write_int32(buf, 0);  //reserved
1864         membuffer_write_data(buf, value, strlen(value));
1865 }
1866
1867 static void membuffer_write_custom_tag(membuffer * buf, const char *name,
1868                 const char *value)
1869 {
1870         membuffer_write_int32(buf,
1871                 8 /*atom header */  +
1872                 0x1C /*weirdo itunes atom */  +
1873                 12 /*name atom header */  + strlen(name) +
1874                 16 /*data atom header + flags */  + strlen(value));
1875         membuffer_write_atom_name(buf, "----");
1876         membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
1877         membuffer_write_atom_name(buf, "mean");
1878         membuffer_write_int32(buf, 0);
1879         membuffer_write_data(buf, "com.apple.iTunes", 16);
1880         membuffer_write_int32(buf, 12 + strlen(name));
1881         membuffer_write_atom_name(buf, "name");
1882         membuffer_write_int32(buf, 0);
1883         membuffer_write_data(buf, name, strlen(name));
1884         membuffer_write_int32(buf,
1885                 8 /*data atom header */  +
1886                 8 /*flags + reserved */  + strlen(value));
1887         membuffer_write_atom_name(buf, "data");
1888         membuffer_write_int32(buf, 1);  //flags
1889         membuffer_write_int32(buf, 0);  //reserved
1890         membuffer_write_data(buf, value, strlen(value));
1891 }
1892
1893 unsigned membuffer_error(const membuffer * buf)
1894 {
1895         return buf->error;
1896 }
1897
1898 void membuffer_free(membuffer * buf)
1899 {
1900         if (buf->data)
1901                 free(buf->data);
1902         free(buf);
1903 }
1904
1905 unsigned membuffer_get_size(const membuffer * buf)
1906 {
1907         return buf->written;
1908 }
1909
1910 void *membuffer_detach(membuffer * buf)
1911 {
1912         void *ret;
1913
1914         if (buf->error)
1915                 return 0;
1916
1917         ret = realloc(buf->data, buf->written);
1918
1919         if (ret == 0)
1920                 free(buf->data);
1921
1922         buf->data = 0;
1923         buf->error = 1;
1924
1925         return ret;
1926 }
1927
1928 static uint32_t create_ilst(const mp4ff_metadata_t * data, void **out_buffer,
1929                 uint32_t * out_size)
1930 {
1931         membuffer *buf = membuffer_create();
1932         unsigned metaptr;
1933         char *mask = (char *) malloc(data->count);
1934         memset(mask, 0, data->count);
1935
1936         {
1937                 const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
1938                 const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
1939                 const char *genre_ptr = 0, *tempo_ptr = 0;
1940                 for (metaptr = 0; metaptr < data->count; metaptr++) {
1941                         mp4ff_tag_t *tag = &data->tags[metaptr];
1942                         if (!stricmp(tag->item, "tracknumber") || !stricmp(tag->item, "track")) {
1943                                 if (tracknumber_ptr == 0)
1944                                         tracknumber_ptr = tag->value;
1945                                 mask[metaptr] = 1;
1946                         } else if (!stricmp(tag->item, "totaltracks")) {
1947                                 if (totaltracks_ptr == 0)
1948                                         totaltracks_ptr = tag->value;
1949                                 mask[metaptr] = 1;
1950                         } else if (!stricmp(tag->item, "discnumber")
1951                                         || !stricmp(tag->item, "disc")) {
1952                                 if (discnumber_ptr == 0)
1953                                         discnumber_ptr = tag->value;
1954                                 mask[metaptr] = 1;
1955                         } else if (!stricmp(tag->item, "totaldiscs")) {
1956                                 if (totaldiscs_ptr == 0)
1957                                         totaldiscs_ptr = tag->value;
1958                                 mask[metaptr] = 1;
1959                         } else if (!stricmp(tag->item, "genre")) {
1960                                 if (genre_ptr == 0)
1961                                         genre_ptr = tag->value;
1962                                 mask[metaptr] = 1;
1963                         } else if (!stricmp(tag->item, "tempo")) {
1964                                 if (tempo_ptr == 0)
1965                                         tempo_ptr = tag->value;
1966                                 mask[metaptr] = 1;
1967                         }
1968
1969                 }
1970
1971                 if (tracknumber_ptr)
1972                         membuffer_write_track_tag(buf, "trkn",
1973                                                   myatoi(tracknumber_ptr),
1974                                                   myatoi(totaltracks_ptr));
1975                 if (discnumber_ptr)
1976                         membuffer_write_track_tag(buf, "disk",
1977                                                   myatoi(discnumber_ptr),
1978                                                   myatoi(totaldiscs_ptr));
1979                 if (tempo_ptr)
1980                         membuffer_write_int16_tag(buf, "tmpo",
1981                                                   (uint16_t) myatoi(tempo_ptr));
1982
1983                 if (genre_ptr) {
1984                         uint32_t index = mp4ff_meta_genre_to_index(genre_ptr);
1985                         if (index == 0)
1986                                 membuffer_write_std_tag(buf, "©gen",
1987                                                         genre_ptr);
1988                         else
1989                                 membuffer_write_int16_tag(buf, "gnre",
1990                                                           (uint16_t) index);
1991                 }
1992         }
1993
1994         for (metaptr = 0; metaptr < data->count; metaptr++) {
1995                 if (!mask[metaptr]) {
1996                         mp4ff_tag_t *tag = &data->tags[metaptr];
1997                         const char *std_meta_atom = find_standard_meta(tag->item);
1998                         if (std_meta_atom) {
1999                                 membuffer_write_std_tag(buf, std_meta_atom,
2000                                                         tag->value);
2001                         } else {
2002                                 membuffer_write_custom_tag(buf, tag->item,
2003                                         tag->value);
2004                         }
2005                 }
2006         }
2007
2008         free(mask);
2009
2010         if (membuffer_error(buf)) {
2011                 membuffer_free(buf);
2012                 return 0;
2013         }
2014
2015         *out_size = membuffer_get_size(buf);
2016         *out_buffer = membuffer_detach(buf);
2017         membuffer_free(buf);
2018
2019         return 1;
2020 }
2021
2022 void membuffer_write_atom(membuffer * buf, const char *name, unsigned size,
2023                           const void *data)
2024 {
2025         membuffer_write_int32(buf, size + 8);
2026         membuffer_write_atom_name(buf, name);
2027         membuffer_write_data(buf, data, size);
2028 }
2029
2030 void *membuffer_get_ptr(const membuffer * buf)
2031 {
2032         return buf->data;
2033 }
2034
2035 void membuffer_set_error(membuffer * buf)
2036 {
2037         buf->error = 1;
2038 }
2039
2040 unsigned membuffer_transfer_from_file(membuffer * buf, mp4ff_t * src,
2041                 unsigned bytes)
2042 {
2043         unsigned oldsize;
2044         void *bufptr;
2045
2046         oldsize = membuffer_get_size(buf);
2047         if (membuffer_write_data(buf, 0, bytes) != bytes)
2048                 return 0;
2049
2050         bufptr = membuffer_get_ptr(buf);
2051         if (bufptr == 0)
2052                 return 0;
2053
2054         if ((unsigned) mp4ff_read_data(src, (char *) bufptr + oldsize, bytes) !=
2055                 bytes) {
2056                 membuffer_set_error(buf);
2057                 return 0;
2058         }
2059
2060         return bytes;
2061 }
2062
2063 static uint32_t create_meta(const mp4ff_metadata_t * data, void **out_buffer,
2064                 uint32_t * out_size)
2065 {
2066         membuffer *buf;
2067         uint32_t ilst_size;
2068         void *ilst_buffer;
2069
2070         if (!create_ilst(data, &ilst_buffer, &ilst_size))
2071                 return 0;
2072
2073         buf = membuffer_create();
2074
2075         membuffer_write_int32(buf, 0);
2076         membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
2077         free(ilst_buffer);
2078
2079         *out_size = membuffer_get_size(buf);
2080         *out_buffer = membuffer_detach(buf);
2081         membuffer_free(buf);
2082         return 1;
2083 }
2084
2085 static uint32_t create_udta(const mp4ff_metadata_t * data, void **out_buffer,
2086 uint32_t * out_size)
2087 {
2088         membuffer *buf;
2089         uint32_t meta_size;
2090         void *meta_buffer;
2091
2092         if (!create_meta(data, &meta_buffer, &meta_size))
2093                 return 0;
2094
2095         buf = membuffer_create();
2096
2097         membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
2098
2099         free(meta_buffer);
2100
2101         *out_size = membuffer_get_size(buf);
2102         *out_buffer = membuffer_detach(buf);
2103         membuffer_free(buf);
2104         return 1;
2105 }
2106
2107 static uint32_t fix_byte_order_32(uint32_t src)
2108 {
2109         uint32_t result;
2110         uint32_t a, b, c, d;
2111         int8_t data[4];
2112
2113         memcpy(data, &src, sizeof (src));
2114         a = (uint8_t) data[0];
2115         b = (uint8_t) data[1];
2116         c = (uint8_t) data[2];
2117         d = (uint8_t) data[3];
2118
2119         result = (a << 24) | (b << 16) | (c << 8) | d;
2120         return (uint32_t) result;
2121 }
2122
2123 static uint32_t modify_moov(mp4ff_t * f, const mp4ff_metadata_t * data,
2124                 void **out_buffer, uint32_t * out_size)
2125 {
2126         uint64_t total_base = f->moov_offset + 8;
2127         uint32_t total_size = (uint32_t) (f->moov_size - 8);
2128
2129         uint64_t udta_offset, meta_offset, ilst_offset;
2130         uint32_t udta_size, meta_size, ilst_size;
2131
2132         uint32_t new_ilst_size;
2133         void *new_ilst_buffer;
2134
2135         uint8_t *p_out;
2136         int32_t size_delta;
2137
2138         if (!find_atom_v2(f, total_base, total_size, "udta", 0, "meta")) {
2139                 membuffer *buf;
2140                 void *new_udta_buffer;
2141                 uint32_t new_udta_size;
2142                 if (!create_udta(data, &new_udta_buffer, &new_udta_size))
2143                         return 0;
2144
2145                 buf = membuffer_create();
2146                 mp4ff_set_position(f, total_base);
2147                 membuffer_transfer_from_file(buf, f, total_size);
2148
2149                 membuffer_write_atom(buf, "udta", new_udta_size,
2150                         new_udta_buffer);
2151
2152                 free(new_udta_buffer);
2153
2154                 *out_size = membuffer_get_size(buf);
2155                 *out_buffer = membuffer_detach(buf);
2156                 membuffer_free(buf);
2157                 return 1;
2158         } else {
2159                 udta_offset = mp4ff_position(f);
2160                 udta_size = mp4ff_read_int32(f);
2161                 if (!find_atom_v2 (f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst")) {
2162                         membuffer *buf;
2163                         void *new_meta_buffer;
2164                         uint32_t new_meta_size;
2165                         if (!create_meta(data, &new_meta_buffer, &new_meta_size))
2166                                 return 0;
2167
2168                         buf = membuffer_create();
2169                         mp4ff_set_position(f, total_base);
2170                         membuffer_transfer_from_file(buf, f,
2171                                 (uint32_t)(udta_offset - total_base));
2172
2173                         membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
2174                         membuffer_write_atom_name(buf, "udta");
2175                         membuffer_transfer_from_file(buf, f, udta_size);
2176
2177                         membuffer_write_atom(buf, "meta", new_meta_size,
2178                                 new_meta_buffer);
2179                         free(new_meta_buffer);
2180
2181                         *out_size = membuffer_get_size(buf);
2182                         *out_buffer = membuffer_detach(buf);
2183                         membuffer_free(buf);
2184                         return 1;
2185                 }
2186                 meta_offset = mp4ff_position(f);
2187                 meta_size = mp4ff_read_int32(f);
2188                 if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst"))
2189                         return 0;       //shouldn't happen, find_atom_v2 above takes care of it
2190                 ilst_offset = mp4ff_position(f);
2191                 ilst_size = mp4ff_read_int32(f);
2192
2193                 if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
2194                         return 0;
2195
2196                 size_delta = new_ilst_size - (ilst_size - 8);
2197
2198                 *out_size = total_size + size_delta;
2199                 *out_buffer = malloc(*out_size);
2200                 if (*out_buffer == 0) {
2201                         free(new_ilst_buffer);
2202                         return 0;
2203                 }
2204
2205                 p_out = (uint8_t *) * out_buffer;
2206
2207                 mp4ff_set_position(f, total_base);
2208                 mp4ff_read_data(f, p_out,
2209                                 (uint32_t) (udta_offset - total_base));
2210                 p_out += (uint32_t) (udta_offset - total_base);
2211                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2212                 p_out += 4;
2213                 mp4ff_read_data(f, p_out, 4);
2214                 p_out += 4;
2215                 mp4ff_read_data(f, p_out,
2216                                 (uint32_t) (meta_offset - udta_offset - 8));
2217                 p_out += (uint32_t) (meta_offset - udta_offset - 8);
2218                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2219                 p_out += 4;
2220                 mp4ff_read_data(f, p_out, 4);
2221                 p_out += 4;
2222                 mp4ff_read_data(f, p_out,
2223                                 (uint32_t) (ilst_offset - meta_offset - 8));
2224                 p_out += (uint32_t) (ilst_offset - meta_offset - 8);
2225                 *(uint32_t *) p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta);
2226                 p_out += 4;
2227                 mp4ff_read_data(f, p_out, 4);
2228                 p_out += 4;
2229
2230                 memcpy(p_out, new_ilst_buffer, new_ilst_size);
2231                 p_out += new_ilst_size;
2232
2233                 mp4ff_set_position(f, ilst_offset + ilst_size);
2234                 mp4ff_read_data(f, p_out, (uint32_t) (total_size
2235                         - (ilst_offset - total_base) - ilst_size));
2236
2237                 free(new_ilst_buffer);
2238         }
2239         return 1;
2240 }
2241
2242 int32_t mp4ff_write_data(mp4ff_t * f, int8_t * data, uint32_t size)
2243 {
2244         int32_t result = 1;
2245
2246         result = f->stream->write(f->stream->user_data, data, size);
2247
2248         f->current_position += size;
2249
2250         return result;
2251 }
2252
2253 int32_t mp4ff_write_int32(mp4ff_t * f, const uint32_t data)
2254 {
2255         uint32_t result;
2256         uint32_t a, b, c, d;
2257         int8_t temp[4];
2258
2259         *(uint32_t *) temp = data;
2260         a = (uint8_t) temp[0];
2261         b = (uint8_t) temp[1];
2262         c = (uint8_t) temp[2];
2263         d = (uint8_t) temp[3];
2264
2265         result = (a << 24) | (b << 16) | (c << 8) | d;
2266
2267         return mp4ff_write_data(f, (uint8_t *) & result, sizeof (result));
2268 }
2269
2270 int32_t mp4ff_truncate(mp4ff_t * f)
2271 {
2272         return f->stream->truncate(f->stream->user_data);
2273 }
2274
2275 int32_t mp4ff_meta_update(mp4ff_callback_t * f, const mp4ff_metadata_t * data)
2276 {
2277         void *new_moov_data;
2278         uint32_t new_moov_size;
2279
2280         mp4ff_t *ff = malloc(sizeof (mp4ff_t));
2281
2282         memset(ff, 0, sizeof (mp4ff_t));
2283         ff->stream = f;
2284         mp4ff_set_position(ff, 0);
2285
2286         parse_atoms(ff, 1);
2287
2288         if (!modify_moov(ff, data, &new_moov_data, &new_moov_size)) {
2289                 mp4ff_close(ff);
2290                 return 0;
2291         }
2292
2293         /* copy moov atom to end of the file */
2294         if (ff->last_atom != ATOM_MOOV) {
2295                 char *free_data = "free";
2296
2297                 /* rename old moov to free */
2298                 mp4ff_set_position(ff, ff->moov_offset + 4);
2299                 mp4ff_write_data(ff, free_data, 4);
2300
2301                 mp4ff_set_position(ff, ff->file_size);
2302                 mp4ff_write_int32(ff, new_moov_size + 8);
2303                 mp4ff_write_data(ff, "moov", 4);
2304                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2305         } else {
2306                 mp4ff_set_position(ff, ff->moov_offset);
2307                 mp4ff_write_int32(ff, new_moov_size + 8);
2308                 mp4ff_write_data(ff, "moov", 4);
2309                 mp4ff_write_data(ff, new_moov_data, new_moov_size);
2310         }
2311
2312         mp4ff_truncate(ff);
2313
2314         mp4ff_close(ff);
2315         return 1;
2316 }
2317
2318 /* find a metadata item by name */
2319 /* returns 0 if item found, 1 if no such item */
2320 static int32_t mp4ff_meta_find_by_name(const mp4ff_t * f, const char *item,
2321                 char **value)
2322 {
2323         uint32_t i;
2324
2325         for (i = 0; i < f->tags.count; i++) {
2326                 if (!stricmp(f->tags.tags[i].item, item)) {
2327                         *value = strdup(f->tags.tags[i].value);
2328                         return 1;
2329                 }
2330         }
2331
2332         *value = NULL;
2333
2334         /* not found */
2335         return 0;
2336 }
2337
2338 int32_t mp4ff_meta_get_artist(const mp4ff_t * f, char **value)
2339 {
2340         return mp4ff_meta_find_by_name(f, "artist", value);
2341 }
2342
2343 int32_t mp4ff_meta_get_title(const mp4ff_t * f, char **value)
2344 {
2345         return mp4ff_meta_find_by_name(f, "title", value);
2346 }
2347
2348 int32_t mp4ff_meta_get_date(const mp4ff_t * f, char **value)
2349 {
2350         return mp4ff_meta_find_by_name(f, "date", value);
2351 }
2352
2353 int32_t mp4ff_meta_get_album(const mp4ff_t * f, char **value)
2354 {
2355         return mp4ff_meta_find_by_name(f, "album", value);
2356 }
2357
2358 int32_t mp4ff_meta_get_comment(const mp4ff_t * f, char **value)
2359 {
2360         return mp4ff_meta_find_by_name(f, "comment", value);
2361 }