mov.c 63.7 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
Baptiste Coudurier's avatar
Baptiste Coudurier committed
158
 <0: error occured, 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
    }

226 227
    if (!err && total_size < atom.size && atom.size < 0x7ffff) {
        url_fskip(pb, atom.size - total_size);
228 229
    }

230 231 232
    return err;
}

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 277
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
278
                    av_free(dref->path);
279
                    dref->path = av_mallocz(len+1);
280 281
                    if (!dref->path)
                        return AVERROR(ENOMEM);
282
                    get_buffer(pb, dref->path, len);
283
                    if (len > volume_len && !strncmp(dref->path, volume, volume_len)) {
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
                        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;
}

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

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

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

314 315 316 317
    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]);
318 319
    if(!ctype)
        c->isom = 1;
320 321 322 323
    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;
324 325
    else if(type == MKTAG('m', '1', 'a', ' '))
        st->codec->codec_id = CODEC_ID_MP2;
326 327 328
    else if(type == MKTAG('s', 'u', 'b', 'p')) {
        st->codec->codec_type = CODEC_TYPE_SUBTITLE;
    }
329 330 331 332
    get_be32(pb); /* component  manufacture */
    get_be32(pb); /* component flags */
    get_be32(pb); /* component flags mask */

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

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

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

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

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

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

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
379
    len = mp4_read_descr(c, pb, &tag);
380
    if (tag == MP4DecConfigDescrTag) {
381 382 383 384 385 386 387 388
        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
389
        len = mp4_read_descr(c, pb, &tag);
390
        if (tag == MP4DecSpecificDescrTag) {
Michel Bardiaux's avatar
Michel Bardiaux committed
391
            dprintf(c->fc, "Specific MPEG4 header len=%d\n", len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
392 393
            if((uint64_t)len > (1<<30))
                return -1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
394
            st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
395 396
            if (!st->codec->extradata)
                return AVERROR(ENOMEM);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
397 398 399 400 401 402
            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;
            }
403
        }
404 405 406 407
    }
    return 0;
}

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

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

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

429 430 431
/* this atom should contain all header atoms */
static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
432 433
    if (mov_read_default(c, pb, atom) < 0)
        return -1;
434 435 436 437 438 439
    /* 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
440 441 442 443 444 445
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);
}
446 447 448

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

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

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

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

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

    return 0;
}

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

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

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

492
    c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
    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;
}

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

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

519 520
    // currently SVQ3 decoder expect full STSD header - so let's fake it
    // this should be fixed and just SMI header should be passed
521
    av_free(st->codec->extradata);
522 523 524
    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
525 526 527 528
    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);
529 530
    return 0;
}
531

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
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;
}

552 553
/* 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)
554 555
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
556 557 558
    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)
559
        return -1;
560 561 562 563 564 565 566 567 568
    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);
569 570 571
    return 0;
}

Roberto Togni's avatar
Roberto Togni committed
572 573 574 575 576 577
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;
578

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

595 596 597 598 599
/**
 * 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)
600 601 602
{
    AVStream *st = c->fc->streams[c->fc->nb_streams-1];

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

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

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

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

    entries = get_be32(pb);
625

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

629
    sc->chunk_count = entries;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
630
    sc->chunk_offsets = av_malloc(entries * sizeof(int64_t));
631 632 633 634 635 636 637 638 639 640 641 642
    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;
643

644 645 646 647 648 649
    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];
650
    MOVStreamContext *sc = st->priv_data;
651 652
    int entries, frames_per_sample;
    uint32_t format;
653
    uint8_t codec_name[32];
654

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

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

    entries = get_be32(pb);

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

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

685 686 687 688
        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
689 690 691
            /* 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. */
692 693 694
            url_fskip(pb, size - (url_ftell(pb) - start_pos));
            continue;
        }
695
        sc->pseudo_stream_id= pseudo_stream_id;
696
        sc->dref_id= dref_id;
697

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

703
        if (st->codec->codec_type != CODEC_TYPE_VIDEO && id > 0) {
704
            st->codec->codec_type = CODEC_TYPE_AUDIO;
705 706
        } 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 */
707
            id = codec_get_id(codec_movvideo_tags, format);
708
            if (id <= 0)
709
                id = codec_get_id(codec_bmp_tags, format);
710 711
            if (id > 0)
                st->codec->codec_type = CODEC_TYPE_VIDEO;
712 713 714 715 716
            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;
            }
717 718
        }

719 720 721
        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);
722

723
        if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
724
            st->codec->codec_id = id;
725 726 727 728
            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
729
            get_be32(pb); /* spatial quality */
730 731 732 733

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

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

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
741 742 743 744 745
            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;
            }
746

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

            /* if the depth is 2, 4, or 8 bpp, file is palettized */
756
            if ((color_depth == 2) || (color_depth == 4) ||
757 758 759
                (color_depth == 8)) {
                if (color_greyscale) {
                    /* compute the greyscale palette */
760
                    st->codec->bits_per_sample = color_depth;
761 762 763 764 765 766 767 768 769 770 771
                    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;
                    }
772
                } else if (st->codec->color_table_id & 0x08) {
773 774 775
                    /* 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
776
                        color_table = ff_qt_default_palette_4;
777
                    else if (color_depth == 4)
Michael Niedermayer's avatar
Michael Niedermayer committed
778
                        color_table = ff_qt_default_palette_16;
779
                    else
Michael Niedermayer's avatar
Michael Niedermayer committed
780
                        color_table = ff_qt_default_palette_256;
781 782 783 784 785 786 787 788 789 790 791 792 793

                    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);
794 795
                    if ((color_start <= 255) &&
                        (color_end <= 255)) {
796 797 798 799 800 801 802 803 804 805 806 807 808 809
                        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);
810
                        }
811 812
                    }
                }
813 814
                st->codec->palctrl = &c->palette_control;
                st->codec->palctrl->palette_changed = 1;
815
            } else
816
                st->codec->palctrl = NULL;
817
        } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
818
            int bits_per_sample;
819
            uint16_t version = get_be16(pb);
820

821
            st->codec->codec_id = id;