mov.c 63.9 KB
Newer Older
1
/*
2
 * MOV demuxer
Fabrice Bellard's avatar
Fabrice Bellard committed
3
 * Copyright (c) 2001 Fabrice Bellard.
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
Fabrice Bellard's avatar
Fabrice Bellard committed
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Fabrice Bellard's avatar
Fabrice Bellard committed
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
16
 *
Fabrice Bellard's avatar
Fabrice Bellard committed
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21 22

#include <limits.h>
23

Baptiste Coudurier's avatar
Baptiste Coudurier committed
24
//#define DEBUG
25

26
#include "avformat.h"
27
#include "riff.h"
28
#include "isom.h"
29
#include "dv.h"
30

31 32 33 34
#ifdef CONFIG_ZLIB
#include <zlib.h>
#endif

35 36
/*
 * First version by Francois Revol revol@free.fr
37
 * Seek function by Gael Chardon gael.dev@4now.net
38
 *
39
 * Features and limitations:
40
 * - reads most of the QT files I have (at least the structure),
41 42
 *   Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
 * - the code is quite ugly... maybe I won't do it recursive next time :-)
43
 *
44 45
 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
 * when coding this :) (it's a writer anyway)
46
 *
47 48 49
 * Reference documents:
 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
 * Apple:
Gael Chardon's avatar
Gael Chardon committed
50
 *  http://developer.apple.com/documentation/QuickTime/QTFF/
51
 *  http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf
52 53 54
 * QuickTime is a trademark of Apple (AFAIK :))
 */

55 56
#include "qtpalette.h"

Gael Chardon's avatar
Gael Chardon committed
57

58 59 60
#undef NDEBUG
#include <assert.h>

61 62 63 64 65
/* the QuickTime file format is quite convoluted...
 * it has lots of index tables, each indexing something in another one...
 * Here we just use what is needed to read the chunks
 */

66
typedef struct {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
67 68 69
    int first;
    int count;
    int id;
70
} MOV_stsc_t;
71

72 73 74 75 76
typedef struct {
    uint32_t type;
    char *path;
} MOV_dref_t;

77 78 79 80 81 82
typedef struct {
    uint32_t type;
    int64_t offset;
    int64_t size; /* total size (excluding the size and type fields) */
} MOV_atom_t;

83 84
struct MOVParseTableEntry;

Baptiste Coudurier's avatar
Baptiste Coudurier committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
typedef struct {
    unsigned track_id;
    uint64_t base_data_offset;
    uint64_t moof_offset;
    unsigned stsd_id;
    unsigned duration;
    unsigned size;
    unsigned flags;
} MOVFragment;

typedef struct {
    unsigned track_id;
    unsigned stsd_id;
    unsigned duration;
    unsigned size;
    unsigned flags;
} MOVTrackExt;

103
typedef struct MOVStreamContext {
104
    ByteIOContext *pb;
105
    int ffindex; /* the ffmpeg stream id */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
106
    int next_chunk;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
107
    unsigned int chunk_count;
108
    int64_t *chunk_offsets;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
109
    unsigned int stts_count;
110
    MOV_stts_t *stts_data;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
111
    unsigned int ctts_count;
112
    MOV_stts_t *ctts_data;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
113 114
    unsigned int edit_count; /* number of 'edit' (elst atom) */
    unsigned int sample_to_chunk_sz;
115
    MOV_stsc_t *sample_to_chunk;
Michael Niedermayer's avatar
Michael Niedermayer committed
116 117
    int sample_to_ctime_index;
    int sample_to_ctime_sample;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
118 119
    unsigned int sample_size;
    unsigned int sample_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
120
    int *sample_sizes;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
121
    unsigned int keyframe_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
122
    int *keyframes;
123
    int time_scale;
124
    int time_rate;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
125
    int current_sample;
126 127
    unsigned int bytes_per_frame;
    unsigned int samples_per_frame;
128
    int dv_audio_container;
129
    int pseudo_stream_id;
130
    int16_t audio_cid; ///< stsd audio compression id
131 132 133
    unsigned drefs_count;
    MOV_dref_t *drefs;
    int dref_id;
134 135 136 137
} MOVStreamContext;

typedef struct MOVContext {
    AVFormatContext *fc;
138
    int time_scale;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
139
    int64_t duration; /* duration of the longest track */
140 141
    int found_moov; /* when both 'moov' and 'mdat' sections has been found */
    int found_mdat; /* we suppose we have enough data to read the file */
142
    AVPaletteControl palette_control;
143 144
    DVDemuxContext *dv_demux;
    AVFormatContext *dv_fctx;
145
    int isom; /* 1 if file is ISO Media (mp4/3gp) */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
146 147 148
    MOVFragment fragment; ///< current fragment in moof atom
    MOVTrackExt *trex_data;
    unsigned trex_count;
149 150 151 152 153 154 155
} MOVContext;


/* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */

/* those functions parse an atom */
/* return code:
Baptiste Coudurier's avatar
Baptiste Coudurier committed
156 157
  1: found what I wanted, exit
  0: continue to parse next atom
Diego Biurrun's avatar
Diego Biurrun committed
158
 <0: error occurred, exit
Baptiste Coudurier's avatar
Baptiste Coudurier committed
159
*/
160 161
/* links atom IDs to parse functions */
typedef struct MOVParseTableEntry {
162
    uint32_t type;
163
    int (*parse)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
164 165
} MOVParseTableEntry;

166 167
static const MOVParseTableEntry mov_default_parse_table[];

168
static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
169
{
170
    int64_t total_size = 0;
171
    MOV_atom_t a;
172 173
    int i;
    int err = 0;
174 175

    a.offset = atom.offset;
176

177
    if (atom.size < 0)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
178
        atom.size = INT64_MAX;
179
    while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
180
        a.size = atom.size;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
181
        a.type=0;
182
        if(atom.size >= 8) {
183
            a.size = get_be32(pb);
184
            a.type = get_le32(pb);
185
        }
186
        total_size += 8;
187
        a.offset += 8;
188 189
        dprintf(c->fc, "type: %08x  %.4s  sz: %"PRIx64"  %"PRIx64"   %"PRIx64"\n",
                a.type, (char*)&a.type, a.size, atom.size, total_size);
190
        if (a.size == 1) { /* 64 bit extended size */
191
            a.size = get_be64(pb) - 8;
192 193
            a.offset += 8;
            total_size += 8;
194
        }
195 196 197
        if (a.size == 0) {
            a.size = atom.size - total_size;
            if (a.size <= 8)
198
                break;
199 200
        }
        a.size -= 8;
201
        if(a.size < 0)
202
            break;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
203
        a.size = FFMIN(a.size, atom.size - total_size);
204

Baptiste Coudurier's avatar
Baptiste Coudurier committed
205
        for (i = 0; mov_default_parse_table[i].type != 0
206
             && mov_default_parse_table[i].type != a.type; i++)
207 208
            /* empty */;

209
        if (mov_default_parse_table[i].type == 0) { /* skip leaf atoms data */
210
            url_fskip(pb, a.size);
211
        } else {
212 213
            offset_t start_pos = url_ftell(pb);
            int64_t left;
214
            err = mov_default_parse_table[i].parse(c, pb, a);
215
            if (url_is_streamed(pb) && c->found_moov && c->found_mdat)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
216
                break;
217 218 219
            left = a.size - url_ftell(pb) + start_pos;
            if (left > 0) /* skip garbage at atom end */
                url_fskip(pb, left);
220
        }
221

222
        a.offset += a.size;
223
        total_size += a.size;
224 225
    }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
226
    if (!err && total_size < atom.size && atom.size < 0x7ffff)
227
        url_fskip(pb, atom.size - total_size);
228

229 230 231
    return err;
}

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
    MOVStreamContext *sc = st->priv_data;
    int entries, i, j;

    get_be32(pb); // version + flags
    entries = get_be32(pb);
    if (entries >= UINT_MAX / sizeof(*sc->drefs))
        return -1;
    sc->drefs_count = entries;
    sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));

    for (i = 0; i < sc->drefs_count; i++) {
        MOV_dref_t *dref = &sc->drefs[i];
        uint32_t size = get_be32(pb);
        offset_t next = url_ftell(pb) + size - 4;

        dref->type = get_le32(pb);
        get_be32(pb); // version + flags
        dprintf(c->fc, "type %.4s size %d\n", (char*)&dref->type, size);

        if (dref->type == MKTAG('a','l','i','s') && size > 150) {
            /* macintosh alias record */
            uint16_t volume_len, len;
            char volume[28];
            int16_t type;

            url_fskip(pb, 10);

            volume_len = get_byte(pb);
            volume_len = FFMIN(volume_len, 27);
            get_buffer(pb, volume, 27);
            volume[volume_len] = 0;
            av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", volume, volume_len);

            url_fskip(pb, 112);

            for (type = 0; type != -1 && url_ftell(pb) < next; ) {
                type = get_be16(pb);
                len = get_be16(pb);
                av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
                if (len&1)
                    len += 1;
                if (type == 2) { // absolute path
277
                    av_free(dref->path);
278
                    dref->path = av_mallocz(len+1);
279 280
                    if (!dref->path)
                        return AVERROR(ENOMEM);
281
                    get_buffer(pb, dref->path, len);
282
                    if (len > volume_len && !strncmp(dref->path, volume, volume_len)) {
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
                        len -= volume_len;
                        memmove(dref->path, dref->path+volume_len, len);
                        dref->path[len] = 0;
                    }
                    for (j = 0; j < len; j++)
                        if (dref->path[j] == ':')
                            dref->path[j] = '/';
                    av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
                } else
                    url_fskip(pb, len);
            }
        }
        url_fseek(pb, next, SEEK_SET);
    }
    return 0;
}

300
static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
301
{
302
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
303 304
    uint32_t type;
    uint32_t ctype;
305

306
    get_byte(pb); /* version */
307
    get_be24(pb); /* flags */
308 309 310 311 312

    /* component type */
    ctype = get_le32(pb);
    type = get_le32(pb); /* component subtype */

313 314 315 316
    dprintf(c->fc, "ctype= %c%c%c%c (0x%08x)\n", *((char *)&ctype), ((char *)&ctype)[1],
            ((char *)&ctype)[2], ((char *)&ctype)[3], (int) ctype);
    dprintf(c->fc, "stype= %c%c%c%c\n",
            *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
317 318
    if(!ctype)
        c->isom = 1;
319 320 321 322
    if(type == MKTAG('v', 'i', 'd', 'e'))
        st->codec->codec_type = CODEC_TYPE_VIDEO;
    else if(type == MKTAG('s', 'o', 'u', 'n'))
        st->codec->codec_type = CODEC_TYPE_AUDIO;
323 324
    else if(type == MKTAG('m', '1', 'a', ' '))
        st->codec->codec_id = CODEC_ID_MP2;
325 326 327
    else if(type == MKTAG('s', 'u', 'b', 'p')) {
        st->codec->codec_type = CODEC_TYPE_SUBTITLE;
    }
328 329 330 331
    get_be32(pb); /* component  manufacture */
    get_be32(pb); /* component flags */
    get_be32(pb); /* component flags mask */

332
    if(atom.size <= 24)
333
        return 0; /* nothing left to read */
334

335
    url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
336 337 338
    return 0;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
339
static int mp4_read_descr_len(ByteIOContext *pb)
340
{
341
    int len = 0;
342 343
    int count = 4;
    while (count--) {
344
        int c = get_byte(pb);
345 346 347
        len = (len << 7) | (c & 0x7f);
        if (!(c & 0x80))
            break;
348 349 350 351
    }
    return len;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
352
static int mp4_read_descr(MOVContext *c, ByteIOContext *pb, int *tag)
353 354 355
{
    int len;
    *tag = get_byte(pb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
356
    len = mp4_read_descr_len(pb);
Michel Bardiaux's avatar
Michel Bardiaux committed
357
    dprintf(c->fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
358 359 360
    return len;
}

361 362 363 364
#define MP4ESDescrTag                   0x03
#define MP4DecConfigDescrTag            0x04
#define MP4DecSpecificDescrTag          0x05

365
static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
366 367 368
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
    int tag, len;
369

370
    get_be32(pb); /* version + flags */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
371
    len = mp4_read_descr(c, pb, &tag);
372
    if (tag == MP4ESDescrTag) {
373 374
        get_be16(pb); /* ID */
        get_byte(pb); /* priority */
375
    } else
376
        get_be16(pb); /* ID */
377

Baptiste Coudurier's avatar
Baptiste Coudurier committed
378
    len = mp4_read_descr(c, pb, &tag);
379
    if (tag == MP4DecConfigDescrTag) {
380 381 382 383 384 385 386 387
        int object_type_id = get_byte(pb);
        get_byte(pb); /* stream type */
        get_be24(pb); /* buffer size db */
        get_be32(pb); /* max bitrate */
        get_be32(pb); /* avg bitrate */

        st->codec->codec_id= codec_get_id(ff_mp4_obj_type, object_type_id);
        dprintf(c->fc, "esds object type id %d\n", object_type_id);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
388
        len = mp4_read_descr(c, pb, &tag);
389
        if (tag == MP4DecSpecificDescrTag) {
Michel Bardiaux's avatar
Michel Bardiaux committed
390
            dprintf(c->fc, "Specific MPEG4 header len=%d\n", len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
391 392
            if((uint64_t)len > (1<<30))
                return -1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
393
            st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
394 395
            if (!st->codec->extradata)
                return AVERROR(ENOMEM);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
396 397 398 399 400 401
            get_buffer(pb, st->codec->extradata, len);
            st->codec->extradata_size = len;
            /* from mplayer */
            if ((*st->codec->extradata >> 3) == 29) {
                st->codec->codec_id = CODEC_ID_MP3ON4;
            }
402
        }
403 404 405 406
    }
    return 0;
}

407 408
/* this atom contains actual media data */
static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
409
{
410 411 412 413 414 415
    if(atom.size == 0) /* wrong one (MP4) */
        return 0;
    c->found_mdat=1;
    return 0; /* now go for moov */
}

416 417 418 419
static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    uint32_t type = get_le32(pb);

420 421
    if (type != MKTAG('q','t',' ',' '))
        c->isom = 1;
422
    av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
423 424 425 426 427
    get_be32(pb); /* minor version */
    url_fskip(pb, atom.size - 8);
    return 0;
}

428 429 430
/* this atom should contain all header atoms */
static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
431 432
    if (mov_read_default(c, pb, atom) < 0)
        return -1;
433 434 435 436 437 438
    /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
    /* so we don't parse the whole file if over a network */
    c->found_moov=1;
    return 0; /* now go for mdat */
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
439 440 441 442 443 444
static int mov_read_moof(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    c->fragment.moof_offset = url_ftell(pb) - 8;
    dprintf(c->fc, "moof offset %llx\n", c->fragment.moof_offset);
    return mov_read_default(c, pb, atom);
}
445 446 447

static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
Baptiste Coudurier's avatar
clean  
Baptiste Coudurier committed
448
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
449
    MOVStreamContext *sc = st->priv_data;
Baptiste Coudurier's avatar
clean  
Baptiste Coudurier committed
450
    int version = get_byte(pb);
451
    int lang;
452

453 454
    if (version > 1)
        return 1; /* unsupported */
455

456
    get_be24(pb); /* flags */
Baptiste Coudurier's avatar
clean  
Baptiste Coudurier committed
457 458 459 460 461 462 463
    if (version == 1) {
        get_be64(pb);
        get_be64(pb);
    } else {
        get_be32(pb); /* creation time */
        get_be32(pb); /* modification time */
    }
464

Baptiste Coudurier's avatar
clean  
Baptiste Coudurier committed
465 466
    sc->time_scale = get_be32(pb);
    st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
467

468
    lang = get_be16(pb); /* language */
Baptiste Coudurier's avatar
clean  
Baptiste Coudurier committed
469
    ff_mov_lang_to_iso639(lang, st->language);
470 471 472 473 474 475 476
    get_be16(pb); /* quality */

    return 0;
}

static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
477
    int version = get_byte(pb); /* version */
478
    get_be24(pb); /* flags */
479

480 481 482 483 484 485 486
    if (version == 1) {
        get_be64(pb);
        get_be64(pb);
    } else {
        get_be32(pb); /* creation time */
        get_be32(pb); /* modification time */
    }
487
    c->time_scale = get_be32(pb); /* time scale */
488 489 490

    dprintf(c->fc, "time scale = %i\n", c->time_scale);

491
    c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
    get_be32(pb); /* preferred scale */

    get_be16(pb); /* preferred volume */

    url_fskip(pb, 10); /* reserved */

    url_fskip(pb, 36); /* display matrix */

    get_be32(pb); /* preview time */
    get_be32(pb); /* preview duration */
    get_be32(pb); /* poster time */
    get_be32(pb); /* selection time */
    get_be32(pb); /* selection duration */
    get_be32(pb); /* current time */
    get_be32(pb); /* next track ID */

    return 0;
}

511 512 513 514
static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];

515 516
    if((uint64_t)atom.size > (1<<30))
        return -1;
517

518 519
    // currently SVQ3 decoder expect full STSD header - so let's fake it
    // this should be fixed and just SMI header should be passed
520
    av_free(st->codec->extradata);
521 522 523
    st->codec->extradata = av_mallocz(atom.size + 0x5a + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!st->codec->extradata)
        return AVERROR(ENOMEM);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
524 525 526 527
    st->codec->extradata_size = 0x5a + atom.size;
    memcpy(st->codec->extradata, "SVQ3", 4); // fake
    get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
    dprintf(c->fc, "Reading SMI %"PRId64"  %s\n", atom.size, st->codec->extradata + 0x5a);
528 529
    return 0;
}
530

531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
    int little_endian = get_be16(pb);

    if (little_endian) {
        switch (st->codec->codec_id) {
        case CODEC_ID_PCM_S24BE:
            st->codec->codec_id = CODEC_ID_PCM_S24LE;
            break;
        case CODEC_ID_PCM_S32BE:
            st->codec->codec_id = CODEC_ID_PCM_S32LE;
            break;
        default:
            break;
        }
    }
    return 0;
}

551 552
/* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */
static int mov_read_extradata(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
553 554
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
555 556 557
    uint64_t size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE;
    uint8_t *buf;
    if(size > INT_MAX || (uint64_t)atom.size > INT_MAX)
558
        return -1;
559 560 561 562 563 564 565 566 567
    buf= av_realloc(st->codec->extradata, size);
    if(!buf)
        return -1;
    st->codec->extradata= buf;
    buf+= st->codec->extradata_size;
    st->codec->extradata_size= size - FF_INPUT_BUFFER_PADDING_SIZE;
    AV_WB32(       buf    , atom.size + 8);
    AV_WL32(       buf + 4, atom.type);
    get_buffer(pb, buf + 8, atom.size);
568 569 570
    return 0;
}

Roberto Togni's avatar
Roberto Togni committed
571 572 573 574 575 576
static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];

    if((uint64_t)atom.size > (1<<30))
        return -1;
577

578 579 580
    if (st->codec->codec_id == CODEC_ID_QDM2) {
        // pass all frma atom to codec, needed at least for QDM2
        av_free(st->codec->extradata);
581 582 583
        st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);
        if (!st->codec->extradata)
            return AVERROR(ENOMEM);
584
        st->codec->extradata_size = atom.size;
585
        get_buffer(pb, st->codec->extradata, atom.size);
586
    } else if (atom.size > 8) { /* to read frma, esds atoms */
587 588
        if (mov_read_default(c, pb, atom) < 0)
            return -1;
589
    } else
590
        url_fskip(pb, atom.size);
Roberto Togni's avatar
Roberto Togni committed
591 592 593
    return 0;
}

594 595 596 597 598
/**
 * This function reads atom content and puts data in extradata without tag
 * nor size unlike mov_read_extradata.
 */
static int mov_read_glbl(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
599 600 601
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];

602 603 604
    if((uint64_t)atom.size > (1<<30))
        return -1;

605
    av_free(st->codec->extradata);
606 607 608
    st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!st->codec->extradata)
        return AVERROR(ENOMEM);
609
    st->codec->extradata_size = atom.size;
610
    get_buffer(pb, st->codec->extradata, atom.size);
611 612 613
    return 0;
}

614 615 616
static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
617
    MOVStreamContext *sc = st->priv_data;
618
    unsigned int i, entries;
619 620

    get_byte(pb); /* version */
621
    get_be24(pb); /* flags */
622 623

    entries = get_be32(pb);
624

625 626
    if(entries >= UINT_MAX/sizeof(int64_t))
        return -1;
627

628
    sc->chunk_count = entries;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
629
    sc->chunk_offsets = av_malloc(entries * sizeof(int64_t));
630 631 632 633 634 635 636 637 638 639 640 641
    if (!sc->chunk_offsets)
        return -1;
    if (atom.type == MKTAG('s', 't', 'c', 'o')) {
        for(i=0; i<entries; i++) {
            sc->chunk_offsets[i] = get_be32(pb);
        }
    } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
        for(i=0; i<entries; i++) {
            sc->chunk_offsets[i] = get_be64(pb);
        }
    } else
        return -1;
642

643 644 645 646 647 648
    return 0;
}

static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
649
    MOVStreamContext *sc = st->priv_data;
650 651
    int entries, frames_per_sample;
    uint32_t format;
652
    uint8_t codec_name[32];
653

654
    /* for palette traversal */
655 656 657 658
    unsigned int color_depth;
    unsigned int color_start;
    unsigned int color_count;
    unsigned int color_end;
659 660 661
    int color_index;
    int color_dec;
    int color_greyscale;
662
    const uint8_t *color_table;
663
    int j, pseudo_stream_id;
664 665
    unsigned char r, g, b;

666
    get_byte(pb); /* version */
667
    get_be24(pb); /* flags */
668 669 670

    entries = get_be32(pb);

671 672
    for(pseudo_stream_id=0; pseudo_stream_id<entries; pseudo_stream_id++) {
        //Parsing Sample description table
673
        enum CodecID id;
674
        int dref_id;
675
        MOV_atom_t a = { 0, 0, 0 };
676
        offset_t start_pos = url_ftell(pb);
677
        int size = get_be32(pb); /* size */
678
        format = get_le32(pb); /* data format */
679

680 681
        get_be32(pb); /* reserved */
        get_be16(pb); /* reserved */
682
        dref_id = get_be16(pb);
683

684 685 686 687
        if (st->codec->codec_tag &&
            (c->fc->video_codec_id ? codec_get_id(codec_movvideo_tags, format) != c->fc->video_codec_id
                                   : st->codec->codec_tag != MKTAG('j', 'p', 'e', 'g'))
           ){
Diego Biurrun's avatar
Diego Biurrun committed
688 689 690
            /* Multiple fourcc, we skip JPEG. This is not correct, we should
             * export it as a separate AVStream but this needs a few changes
             * in the MOV demuxer, patch welcome. */
691 692 693
            url_fskip(pb, size - (url_ftell(pb) - start_pos));
            continue;
        }
694
        sc->pseudo_stream_id= pseudo_stream_id;
695
        sc->dref_id= dref_id;
696

697
        st->codec->codec_tag = format;
698
        id = codec_get_id(codec_movaudio_tags, format);
Michael Niedermayer's avatar
Michael Niedermayer committed
699 700 701
        if (id<=0 && (format&0xFFFF) == 'm' + ('s'<<8))
            id = codec_get_id(codec_wav_tags, bswap_32(format)&0xFFFF);

702
        if (st->codec->codec_type != CODEC_TYPE_VIDEO && id > 0) {
703
            st->codec->codec_type = CODEC_TYPE_AUDIO;
704 705
        } else if (st->codec->codec_type != CODEC_TYPE_AUDIO && /* do not overwrite codec type */
                   format && format != MKTAG('m', 'p', '4', 's')) { /* skip old asf mpeg4 tag */
706
            id = codec_get_id(codec_movvideo_tags, format);
707
            if (id <= 0)
708
                id = codec_get_id(codec_bmp_tags, format);
709 710
            if (id > 0)
                st->codec->codec_type = CODEC_TYPE_VIDEO;
711 712 713 714 715
            else if(st->codec->codec_type == CODEC_TYPE_DATA){
                id = codec_get_id(ff_codec_movsubtitle_tags, format);
                if(id > 0)
                    st->codec->codec_type = CODEC_TYPE_SUBTITLE;
            }
716 717
        }

718 719 720
        dprintf(c->fc, "size=%d 4CC= %c%c%c%c codec_type=%d\n", size,
                (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff,
                (format >> 24) & 0xff, st->codec->codec_type);
721

722
        if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
723
            st->codec->codec_id = id;
724 725 726 727
            get_be16(pb); /* version */
            get_be16(pb); /* revision level */
            get_be32(pb); /* vendor */
            get_be32(pb); /* temporal quality */
Diego Biurrun's avatar
Diego Biurrun committed
728
            get_be32(pb); /* spatial quality */
729 730 731 732

            st->codec->width = get_be16(pb); /* width */
            st->codec->height = get_be16(pb); /* height */

733 734 735
            get_be32(pb); /* horiz resolution */
            get_be32(pb); /* vert resolution */
            get_be32(pb); /* data size, always 0 */
736
            frames_per_sample = get_be16(pb); /* frames per samples */
737 738 739

            dprintf(c->fc, "frames/samples = %d\n", frames_per_sample);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
740 741 742 743 744
            get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
            if (codec_name[0] <= 31) {
                memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
                st->codec->codec_name[codec_name[0]] = 0;
            }
745

746
            st->codec->bits_per_sample = get_be16(pb); /* depth */
747
            st->codec->color_table_id = get_be16(pb); /* colortable id */
748 749
            dprintf(c->fc, "depth %d, ctab id %d\n",
                   st->codec->bits_per_sample, st->codec->color_table_id);
750
            /* figure out the palette situation */
751 752
            color_depth = st->codec->bits_per_sample & 0x1F;
            color_greyscale = st->codec->bits_per_sample & 0x20;
753 754

            /* if the depth is 2, 4, or 8 bpp, file is palettized */
755
            if ((color_depth == 2) || (color_depth == 4) ||
756 757 758
                (color_depth == 8)) {
                if (color_greyscale) {
                    /* compute the greyscale palette */
759
                    st->codec->bits_per_sample = color_depth;
760 761 762 763 764 765 766 767 768 769 770
                    color_count = 1 << color_depth;
                    color_index = 255;
                    color_dec = 256 / (color_count - 1);
                    for (j = 0; j < color_count; j++) {
                        r = g = b = color_index;
                        c->palette_control.palette[j] =
                            (r << 16) | (g << 8) | (b);
                        color_index -= color_dec;
                        if (color_index < 0)
                            color_index = 0;
                    }
771
                } else if (st->codec->color_table_id) {
772 773 774
                    /* if flag bit 3 is set, use the default palette */
                    color_count = 1 << color_depth;
                    if (color_depth == 2)
Michael Niedermayer's avatar
Michael Niedermayer committed
775
                        color_table = ff_qt_default_palette_4;
776
                    else if (color_depth == 4)
Michael Niedermayer's avatar
Michael Niedermayer committed
777
                        color_table = ff_qt_default_palette_16;
778
                    else
Michael Niedermayer's avatar
Michael Niedermayer committed
779
                        color_table = ff_qt_default_palette_256;
780 781 782 783 784 785 786 787 788 789 790 791 792

                    for (j = 0; j < color_count; j++) {
                        r = color_table[j * 4 + 0];
                        g = color_table[j * 4 + 1];
                        b = color_table[j * 4 + 2];
                        c->palette_control.palette[j] =
                            (r << 16) | (g << 8) | (b);
                    }
                } else {
                    /* load the palette from the file */
                    color_start = get_be32(pb);
                    color_count = get_be16(pb);
                    color_end = get_be16(pb);
793 794
                    if ((color_start <= 255) &&
                        (color_end <= 255)) {
795 796 797 798 799 800 801 802 803 804 805 806 807 808
                        for (j = color_start; j <= color_end; j++) {
                            /* each R, G, or B component is 16 bits;
                             * only use the top 8 bits; skip alpha bytes
                             * up front */
                            get_byte(pb);
                            get_byte(pb);
                            r = get_byte(pb);
                            get_byte(pb);
                            g = get_byte(pb);
                            get_byte(pb);
                            b = get_byte(pb);
                            get_byte(pb);
                            c->palette_control.palette[j] =
                                (r << 16) | (g << 8) | (b);
809
                        }
810 811
                    }
                }
812 813
                st->codec->palctrl = &c->palette_control;
                st->codec->palctrl->palette_changed = 1;
814
            } else
815
                st->codec->palctrl = NULL;
816
        } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
817
            int bits_per_sample;
818
            uint16_t version = get_be16(pb);
819

820
            st->codec