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