mov.c 277 KB
Newer Older
1
/*
2
 * MOV demuxer
3
 * Copyright (c) 2001 Fabrice Bellard
4
 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
5
 *
6 7 8
 * first version by Francois Revol <revol@free.fr>
 * seek function by Gael Chardon <gael.dev@4now.net>
 *
9 10 11
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
12 13
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
14
 * version 2.1 of the License, or (at your option) any later version.
15
 *
16
 * FFmpeg is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Lesser General Public
22
 * License along with FFmpeg; if not, write to the Free Software
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
 */
25

26
#include <inttypes.h>
27
#include <limits.h>
28
#include <stdint.h>
29

30
#include "libavutil/attributes.h"
31
#include "libavutil/channel_layout.h"
32
#include "libavutil/internal.h"
33
#include "libavutil/intreadwrite.h"
34
#include "libavutil/intfloat.h"
35
#include "libavutil/mathematics.h"
36
#include "libavutil/time_internal.h"
37
#include "libavutil/avassert.h"
38
#include "libavutil/avstring.h"
39
#include "libavutil/dict.h"
40
#include "libavutil/display.h"
41
#include "libavutil/opt.h"
42
#include "libavutil/aes.h"
43
#include "libavutil/aes_ctr.h"
44
#include "libavutil/pixdesc.h"
45
#include "libavutil/sha.h"
46 47
#include "libavutil/spherical.h"
#include "libavutil/stereo3d.h"
48
#include "libavutil/timecode.h"
49
#include "libavcodec/ac3tab.h"
50
#include "libavcodec/flac.h"
51
#include "libavcodec/mpegaudiodecheader.h"
52
#include "libavcodec/mlp_parse.h"
53
#include "avformat.h"
54
#include "internal.h"
55
#include "avio_internal.h"
56
#include "riff.h"
57
#include "isom.h"
58
#include "libavcodec/get_bits.h"
Raivo Hool's avatar
Raivo Hool committed
59
#include "id3v1.h"
60
#include "mov_chan.h"
61
#include "replaygain.h"
62

63
#if CONFIG_ZLIB
64 65 66
#include <zlib.h>
#endif

67 68
#include "qtpalette.h"

69 70 71
/* those functions parse an atom */
/* links atom IDs to parse functions */
typedef struct MOVParseTableEntry {
72
    uint32_t type;
73
    int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
74 75
} MOVParseTableEntry;

76
static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
77
static int mov_read_mfra(MOVContext *c, AVIOContext *f);
78 79
static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
                              int count, int duration);
80

81 82
static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
                                             unsigned len, const char *key)
83 84 85
{
    char buf[16];

86
    short current, total = 0;
87
    avio_rb16(pb); // unknown
88
    current = avio_rb16(pb);
89 90
    if (len >= 6)
        total = avio_rb16(pb);
91 92 93 94
    if (!total)
        snprintf(buf, sizeof(buf), "%d", current);
    else
        snprintf(buf, sizeof(buf), "%d/%d", current, total);
95
    c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
96
    av_dict_set(&c->fc->metadata, key, buf, 0);
97 98 99 100

    return 0;
}

101 102
static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
                                            unsigned len, const char *key)
103
{
104 105 106 107
    /* bypass padding bytes */
    avio_r8(pb);
    avio_r8(pb);
    avio_r8(pb);
108

109
    c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
110
    av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
111

112
    return 0;
113 114
}

115 116
static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
                                        unsigned len, const char *key)
117
{
118
    c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
119
    av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
120

121
    return 0;
122 123
}

Raivo Hool's avatar
Raivo Hool committed
124
static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
125 126
                             unsigned len, const char *key)
{
Raivo Hool's avatar
Raivo Hool committed
127
    short genre;
128

Raivo Hool's avatar
Raivo Hool committed
129
    avio_r8(pb); // unknown
130

Raivo Hool's avatar
Raivo Hool committed
131 132 133
    genre = avio_r8(pb);
    if (genre < 1 || genre > ID3v1_GENRE_MAX)
        return 0;
134
    c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
135
    av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
Raivo Hool's avatar
Raivo Hool committed
136 137

    return 0;
138 139
}

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
static const uint32_t mac_to_unicode[128] = {
    0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
    0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
    0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
    0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
    0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
    0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
    0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
    0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
    0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
    0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
    0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
    0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
    0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
    0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
    0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
    0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
};

159
static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
160 161 162 163 164 165 166
                               char *dst, int dstlen)
{
    char *p = dst;
    char *end = dst+dstlen-1;
    int i;

    for (i = 0; i < len; i++) {
167
        uint8_t t, c = avio_r8(pb);
168 169 170 171 172

        if (p >= end)
            continue;

        if (c < 0x80)
173
            *p++ = c;
174
        else if (p < end)
175 176 177 178 179 180
            PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
    }
    *p = 0;
    return p - dst;
}

181 182 183 184 185
static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
{
    AVPacket pkt;
    AVStream *st;
    MOVStreamContext *sc;
186
    enum AVCodecID id;
187 188 189
    int ret;

    switch (type) {
190 191 192
    case 0xd:  id = AV_CODEC_ID_MJPEG; break;
    case 0xe:  id = AV_CODEC_ID_PNG;   break;
    case 0x1b: id = AV_CODEC_ID_BMP;   break;
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    default:
        av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
        avio_skip(pb, len);
        return 0;
    }

    st = avformat_new_stream(c->fc, NULL);
    if (!st)
        return AVERROR(ENOMEM);
    sc = av_mallocz(sizeof(*sc));
    if (!sc)
        return AVERROR(ENOMEM);
    st->priv_data = sc;

    ret = av_get_packet(pb, &pkt, len);
    if (ret < 0)
        return ret;

211 212 213 214 215 216 217 218
    if (pkt.size >= 8 && id != AV_CODEC_ID_BMP) {
        if (AV_RB64(pkt.data) == 0x89504e470d0a1a0a) {
            id = AV_CODEC_ID_PNG;
        } else {
            id = AV_CODEC_ID_MJPEG;
        }
    }

219 220 221 222 223 224
    st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;

    st->attached_pic              = pkt;
    st->attached_pic.stream_index = st->index;
    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;

225 226
    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
    st->codecpar->codec_id   = id;
227 228 229 230

    return 0;
}

231
// 3GPP TS 26.244
232 233 234
static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
{
    char language[4] = { 0 };
235
    char buf[200], place[100];
236
    uint16_t langcode = 0;
237
    double longitude, latitude, altitude;
238 239
    const char *key = "location";

240 241
    if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
        av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
242
        return AVERROR_INVALIDDATA;
243
    }
244 245 246 247 248 249

    avio_skip(pb, 4); // version+flags
    langcode = avio_rb16(pb);
    ff_mov_lang_to_iso639(langcode, language);
    len -= 6;

250
    len -= avio_get_str(pb, len, place, sizeof(place));
251 252
    if (len < 1) {
        av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
253
        return AVERROR_INVALIDDATA;
254
    }
255 256 257
    avio_skip(pb, 1); // role
    len -= 1;

258
    if (len < 12) {
259
        av_log(c->fc, AV_LOG_ERROR,
260
               "loci too short (%u bytes left, need at least %d)\n", len, 12);
261
        return AVERROR_INVALIDDATA;
262
    }
263 264
    longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
    latitude  = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
265
    altitude  = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
266 267

    // Try to output in the same format as the ?xyz field
268 269 270 271 272
    snprintf(buf, sizeof(buf), "%+08.4f%+09.4f",  latitude, longitude);
    if (altitude)
        av_strlcatf(buf, sizeof(buf), "%+f", altitude);
    av_strlcatf(buf, sizeof(buf), "/%s", place);

273 274 275 276 277
    if (*language && strcmp(language, "und")) {
        char key2[16];
        snprintf(key2, sizeof(key2), "%s-%s", key, language);
        av_dict_set(&c->fc->metadata, key2, buf, 0);
    }
278
    c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
279 280 281
    return av_dict_set(&c->fc->metadata, key, buf, 0);
}

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
{
    int i, n_hmmt;

    if (len < 2)
        return 0;
    if (c->ignore_chapters)
        return 0;

    n_hmmt = avio_rb32(pb);
    for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
        int moment_time = avio_rb32(pb);
        avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
    }
    return 0;
}

299
static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
300 301
{
    char tmp_key[5];
302
    char key2[32], language[4] = {0};
303
    char *str = NULL;
304
    const char *key = NULL;
305
    uint16_t langcode = 0;
306
    uint32_t data_type = 0, str_size, str_size_alloc;
307
    int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
308
    int raw = 0;
309
    int num = 0;
310 311

    switch (atom.type) {
312 313
    case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
    case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
314 315
    case MKTAG( 'X','M','P','_'):
        if (c->export_xmp) { key = "xmp"; raw = 1; } break;
Raivo Hool's avatar
Raivo Hool committed
316
    case MKTAG( 'a','A','R','T'): key = "album_artist";    break;
317 318 319 320
    case MKTAG( 'a','k','I','D'): key = "account_type";
        parse = mov_metadata_int8_no_padding; break;
    case MKTAG( 'a','p','I','D'): key = "account_id"; break;
    case MKTAG( 'c','a','t','g'): key = "category"; break;
321 322
    case MKTAG( 'c','p','i','l'): key = "compilation";
        parse = mov_metadata_int8_no_padding; break;
323 324
    case MKTAG( 'c','p','r','t'): key = "copyright"; break;
    case MKTAG( 'd','e','s','c'): key = "description"; break;
325 326
    case MKTAG( 'd','i','s','k'): key = "disc";
        parse = mov_metadata_track_or_disc_number; break;
327 328
    case MKTAG( 'e','g','i','d'): key = "episode_uid";
        parse = mov_metadata_int8_no_padding; break;
329
    case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
Raivo Hool's avatar
Raivo Hool committed
330 331
    case MKTAG( 'g','n','r','e'): key = "genre";
        parse = mov_metadata_gnre; break;
332 333
    case MKTAG( 'h','d','v','d'): key = "hd_video";
        parse = mov_metadata_int8_no_padding; break;
334 335
    case MKTAG( 'H','M','M','T'):
        return mov_metadata_hmmt(c, pb, atom.size);
336
    case MKTAG( 'k','e','y','w'): key = "keywords";  break;
337
    case MKTAG( 'l','d','e','s'): key = "synopsis";  break;
338 339
    case MKTAG( 'l','o','c','i'):
        return mov_metadata_loci(c, pb, atom.size);
340 341
    case MKTAG( 'm','a','n','u'): key = "make"; break;
    case MKTAG( 'm','o','d','l'): key = "model"; break;
342 343
    case MKTAG( 'p','c','s','t'): key = "podcast";
        parse = mov_metadata_int8_no_padding; break;
344 345
    case MKTAG( 'p','g','a','p'): key = "gapless_playback";
        parse = mov_metadata_int8_no_padding; break;
346 347 348 349 350 351 352 353 354
    case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
    case MKTAG( 'r','t','n','g'): key = "rating";
        parse = mov_metadata_int8_no_padding; break;
    case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
    case MKTAG( 's','o','a','l'): key = "sort_album";   break;
    case MKTAG( 's','o','a','r'): key = "sort_artist";  break;
    case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
    case MKTAG( 's','o','n','m'): key = "sort_name";    break;
    case MKTAG( 's','o','s','n'): key = "sort_show";    break;
355 356
    case MKTAG( 's','t','i','k'): key = "media_type";
        parse = mov_metadata_int8_no_padding; break;
357
    case MKTAG( 't','r','k','n'): key = "track";
358
        parse = mov_metadata_track_or_disc_number; break;
359
    case MKTAG( 't','v','e','n'): key = "episode_id"; break;
360
    case MKTAG( 't','v','e','s'): key = "episode_sort";
361
        parse = mov_metadata_int8_bypass_padding; break;
362 363
    case MKTAG( 't','v','n','n'): key = "network";   break;
    case MKTAG( 't','v','s','h'): key = "show";      break;
364
    case MKTAG( 't','v','s','n'): key = "season_number";
365
        parse = mov_metadata_int8_bypass_padding; break;
366
    case MKTAG(0xa9,'A','R','T'): key = "artist";    break;
367
    case MKTAG(0xa9,'P','R','D'): key = "producer";  break;
368 369
    case MKTAG(0xa9,'a','l','b'): key = "album";     break;
    case MKTAG(0xa9,'a','u','t'): key = "artist";    break;
370
    case MKTAG(0xa9,'c','h','p'): key = "chapter";   break;
371
    case MKTAG(0xa9,'c','m','t'): key = "comment";   break;
372
    case MKTAG(0xa9,'c','o','m'): key = "composer";  break;
373 374
    case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
    case MKTAG(0xa9,'d','a','y'): key = "date";      break;
375 376 377
    case MKTAG(0xa9,'d','i','r'): key = "director";  break;
    case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
    case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
378
    case MKTAG(0xa9,'e','n','c'): key = "encoder";   break;
379
    case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
380
    case MKTAG(0xa9,'g','e','n'): key = "genre";     break;
381
    case MKTAG(0xa9,'g','r','p'): key = "grouping";  break;
382
    case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
383
    case MKTAG(0xa9,'i','n','f'): key = "comment";   break;
384 385 386
    case MKTAG(0xa9,'l','y','r'): key = "lyrics";    break;
    case MKTAG(0xa9,'m','a','k'): key = "make";      break;
    case MKTAG(0xa9,'m','o','d'): key = "model";     break;
387
    case MKTAG(0xa9,'n','a','m'): key = "title";     break;
388 389 390 391 392
    case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
    case MKTAG(0xa9,'p','r','d'): key = "producer";  break;
    case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
    case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
    case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
393
    case MKTAG(0xa9,'s','t','3'): key = "subtitle";  break;
394 395
    case MKTAG(0xa9,'s','w','r'): key = "encoder";   break;
    case MKTAG(0xa9,'t','o','o'): key = "encoder";   break;
396 397 398
    case MKTAG(0xa9,'t','r','k'): key = "track";     break;
    case MKTAG(0xa9,'u','r','l'): key = "URL";       break;
    case MKTAG(0xa9,'w','r','n'): key = "warning";   break;
399 400
    case MKTAG(0xa9,'w','r','t'): key = "composer";  break;
    case MKTAG(0xa9,'x','y','z'): key = "location";  break;
401
    }
402
retry:
403
    if (c->itunes_metadata && atom.size > 8) {
404 405
        int data_size = avio_rb32(pb);
        int tag = avio_rl32(pb);
406
        if (tag == MKTAG('d','a','t','a') && data_size <= atom.size) {
407 408
            data_type = avio_rb32(pb); // type
            avio_rb32(pb); // unknown
409 410
            str_size = data_size - 16;
            atom.size -= 16;
411 412 413 414 415

            if (atom.type == MKTAG('c', 'o', 'v', 'r')) {
                int ret = mov_read_covr(c, pb, data_type, str_size);
                if (ret < 0) {
                    av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
416
                    return ret;
417
                }
418 419 420
                atom.size -= str_size;
                if (atom.size > 8)
                    goto retry;
421
                return ret;
422 423
            } else if (!key && c->found_hdlr_mdta && c->meta_keys) {
                uint32_t index = AV_RB32(&atom.type);
424
                if (index < c->meta_keys_count && index > 0) {
425 426 427
                    key = c->meta_keys[index];
                } else {
                    av_log(c->fc, AV_LOG_WARNING,
428
                           "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
429 430
                           index, c->meta_keys_count);
                }
431
            }
432
        } else return 0;
433
    } else if (atom.size > 4 && key && !c->itunes_metadata && !raw) {
434
        str_size = avio_rb16(pb); // string length
435 436 437
        if (str_size > atom.size) {
            raw = 1;
            avio_seek(pb, -2, SEEK_CUR);
438
            av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
439 440
            goto retry;
        }
441
        langcode = avio_rb16(pb);
442
        ff_mov_lang_to_iso639(langcode, language);
443 444 445 446
        atom.size -= 4;
    } else
        str_size = atom.size;

447
    if (c->export_all && !key) {
448 449 450 451 452 453
        snprintf(tmp_key, 5, "%.4s", (char*)&atom.type);
        key = tmp_key;
    }

    if (!key)
        return 0;
454
    if (atom.size < 0 || str_size >= INT_MAX/2)
455
        return AVERROR_INVALIDDATA;
456

457
    // Allocates enough space if data_type is a int32 or float32 number, otherwise
458
    // worst-case requirement for output string in case of utf8 coded input
459
    num = (data_type >= 21 && data_type <= 23);
460
    str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
461
    str = av_mallocz(str_size_alloc);
462 463 464
    if (!str)
        return AVERROR(ENOMEM);

465
    if (parse)
466
        parse(c, pb, str_size, key);
467
    else {
468
        if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
469
            mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
        } else if (data_type == 21) { // BE signed integer, variable size
            int val = 0;
            if (str_size == 1)
                val = (int8_t)avio_r8(pb);
            else if (str_size == 2)
                val = (int16_t)avio_rb16(pb);
            else if (str_size == 3)
                val = ((int32_t)(avio_rb24(pb)<<8))>>8;
            else if (str_size == 4)
                val = (int32_t)avio_rb32(pb);
            if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
                av_log(c->fc, AV_LOG_ERROR,
                       "Failed to store the number (%d) in string.\n", val);
                av_free(str);
                return AVERROR_INVALIDDATA;
            }
        } else if (data_type == 22) { // BE unsigned integer, variable size
            unsigned int val = 0;
            if (str_size == 1)
                val = avio_r8(pb);
            else if (str_size == 2)
                val = avio_rb16(pb);
            else if (str_size == 3)
                val = avio_rb24(pb);
            else if (str_size == 4)
                val = avio_rb32(pb);
            if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
                av_log(c->fc, AV_LOG_ERROR,
                       "Failed to store the number (%u) in string.\n", val);
                av_free(str);
                return AVERROR_INVALIDDATA;
            }
502 503 504 505 506
        } else if (data_type == 23 && str_size >= 4) {  // BE float32
            float val = av_int2float(avio_rb32(pb));
            if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
                av_log(c->fc, AV_LOG_ERROR,
                       "Failed to store the float32 number (%f) in string.\n", val);
507
                av_free(str);
508 509
                return AVERROR_INVALIDDATA;
            }
510
        } else {
511 512 513 514
            int ret = ffio_read_size(pb, str, str_size);
            if (ret < 0) {
                av_free(str);
                return ret;
515
            }
516 517
            str[str_size] = 0;
        }
518
        c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
519
        av_dict_set(&c->fc->metadata, key, str, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
520 521
        if (*language && strcmp(language, "und")) {
            snprintf(key2, sizeof(key2), "%s-%s", key, language);
522
            av_dict_set(&c->fc->metadata, key2, str, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
523
        }
524 525 526 527 528 529
        if (!strcmp(key, "encoder")) {
            int major, minor, micro;
            if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
                c->handbrake_version = 1000000*major + 1000*minor + micro;
            }
        }
530
    }
531 532

    av_freep(&str);
533 534
    return 0;
}
535

536
static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
David Conrad's avatar
David Conrad committed
537 538
{
    int64_t start;
539
    int i, nb_chapters, str_len, version;
David Conrad's avatar
David Conrad committed
540
    char str[256+1];
541
    int ret;
David Conrad's avatar
David Conrad committed
542

543 544 545
    if (c->ignore_chapters)
        return 0;

David Conrad's avatar
David Conrad committed
546 547 548
    if ((atom.size -= 5) < 0)
        return 0;

549 550
    version = avio_r8(pb);
    avio_rb24(pb);
551
    if (version)
552 553
        avio_rb32(pb); // ???
    nb_chapters = avio_r8(pb);
David Conrad's avatar
David Conrad committed
554 555 556 557 558

    for (i = 0; i < nb_chapters; i++) {
        if (atom.size < 9)
            return 0;

559 560
        start = avio_rb64(pb);
        str_len = avio_r8(pb);
David Conrad's avatar
David Conrad committed
561 562 563 564

        if ((atom.size -= 9+str_len) < 0)
            return 0;

565 566 567
        ret = ffio_read_size(pb, str, str_len);
        if (ret < 0)
            return ret;
David Conrad's avatar
David Conrad committed
568
        str[str_len] = 0;
569
        avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
David Conrad's avatar
David Conrad committed
570 571 572 573
    }
    return 0;
}

574
#define MIN_DATA_ENTRY_BOX_SIZE 12
575
static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
576
{
577 578
    AVStream *st;
    MOVStreamContext *sc;
579 580
    int entries, i, j;

581 582 583 584 585
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

586 587
    avio_rb32(pb); // version + flags
    entries = avio_rb32(pb);
588 589
    if (!entries ||
        entries >  (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
590
        entries >= UINT_MAX / sizeof(*sc->drefs))
591
        return AVERROR_INVALIDDATA;
592
    sc->drefs_count = 0;
593
    av_free(sc->drefs);
594
    sc->drefs_count = 0;
595
    sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
596 597 598
    if (!sc->drefs)
        return AVERROR(ENOMEM);
    sc->drefs_count = entries;
599

600
    for (i = 0; i < entries; i++) {
601
        MOVDref *dref = &sc->drefs[i];
602
        uint32_t size = avio_rb32(pb);
603
        int64_t next = avio_tell(pb) + size - 4;
604

605
        if (size < 12)
606
            return AVERROR_INVALIDDATA;
607

608 609
        dref->type = avio_rl32(pb);
        avio_rb32(pb); // version + flags
610 611 612 613 614

        if (dref->type == MKTAG('a','l','i','s') && size > 150) {
            /* macintosh alias record */
            uint16_t volume_len, len;
            int16_t type;
615
            int ret;
616

617
            avio_skip(pb, 10);
618

619
            volume_len = avio_r8(pb);
620
            volume_len = FFMIN(volume_len, 27);
621 622 623
            ret = ffio_read_size(pb, dref->volume, 27);
            if (ret < 0)
                return ret;
624 625
            dref->volume[volume_len] = 0;
            av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
626

627
            avio_skip(pb, 12);
628

629
            len = avio_r8(pb);
630
            len = FFMIN(len, 63);
631 632 633
            ret = ffio_read_size(pb, dref->filename, 63);
            if (ret < 0)
                return ret;
634 635 636
            dref->filename[len] = 0;
            av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);

637
            avio_skip(pb, 16);
638 639

            /* read next level up_from_alias/down_to_target */
640 641
            dref->nlvl_from = avio_rb16(pb);
            dref->nlvl_to   = avio_rb16(pb);
642 643 644
            av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
                   dref->nlvl_from, dref->nlvl_to);

645
            avio_skip(pb, 16);
646

647
            for (type = 0; type != -1 && avio_tell(pb) < next; ) {
648
                if(avio_feof(pb))
649
                    return AVERROR_EOF;
650 651
                type = avio_rb16(pb);
                len = avio_rb16(pb);
652 653 654
                av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
                if (len&1)
                    len += 1;
655
                if (type == 2) { // absolute path
656
                    av_free(dref->path);
657
                    dref->path = av_mallocz(len+1);
658 659
                    if (!dref->path)
                        return AVERROR(ENOMEM);
660 661 662

                    ret = ffio_read_size(pb, dref->path, len);
                    if (ret < 0) {
663
                        av_freep(&dref->path);
664
                        return ret;
665
                    }
666
                    if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
667 668 669 670
                        len -= volume_len;
                        memmove(dref->path, dref->path+volume_len, len);
                        dref->path[len] = 0;
                    }
671 672 673 674 675 676 677
                    // trim string of any ending zeros
                    for (j = len - 1; j >= 0; j--) {
                        if (dref->path[j] == 0)
                            len--;
                        else
                            break;
                    }
678
                    for (j = 0; j < len; j++)
679
                        if (dref->path[j] == ':' || dref->path[j] == 0)
680 681
                            dref->path[j] = '/';
                    av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
682 683 684 685 686
                } else if (type == 0) { // directory name
                    av_free(dref->dir);
                    dref->dir = av_malloc(len+1);
                    if (!dref->dir)
                        return AVERROR(ENOMEM);
687 688 689

                    ret = ffio_read_size(pb, dref->dir, len);
                    if (ret < 0) {
690
                        av_freep(&dref->dir);
691
                        return ret;
692
                    }
693 694 695 696 697
                    dref->dir[len] = 0;
                    for (j = 0; j < len; j++)
                        if (dref->dir[j] == ':')
                            dref->dir[j] = '/';
                    av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
698
                } else
699
                    avio_skip(pb, len);
700
            }
701
        } else {
702
            av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
703 704 705
                   dref->type, size);
            entries--;
            i--;
706
        }
707
        avio_seek(pb, next, SEEK_SET);
708 709 710 711
    }
    return 0;
}

712
static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
713
{
714
    AVStream *st;
715
    uint32_t type;
716
    uint32_t ctype;
717
    int64_t title_size;
718
    char *title_str;
719
    int ret;
720

721 722
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
723 724

    /* component type */
725 726
    ctype = avio_rl32(pb);
    type = avio_rl32(pb); /* component subtype */
727

728 729
    av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
    av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
730

731
    if (c->trak_index < 0) {  // meta not inside a trak
732 733 734 735 736 737 738 739
        if (type == MKTAG('m','d','t','a')) {
            c->found_hdlr_mdta = 1;
        }
        return 0;
    }

    st = c->fc->streams[c->fc->nb_streams-1];

740
    if     (type == MKTAG('v','i','d','e'))
741
        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
742
    else if (type == MKTAG('s','o','u','n'))
743
        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
744
    else if (type == MKTAG('m','1','a',' '))
745
        st->codecpar->codec_id = AV_CODEC_ID_MP2;
746
    else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
747
        st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
748

749 750 751
    avio_rb32(pb); /* component  manufacture */
    avio_rb32(pb); /* component flags */
    avio_rb32(pb); /* component flags mask */
752

753 754
    title_size = atom.size - 24;
    if (title_size > 0) {
755 756
        if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
            return AVERROR_INVALIDDATA;
757 758 759
        title_str = av_malloc(title_size + 1); /* Add null terminator */
        if (!title_str)
            return AVERROR(ENOMEM);
760 761 762

        ret = ffio_read_size(pb, title_str, title_size);
        if (ret < 0) {
763
            av_freep(&title_str);
764
            return ret;
765
        }
766
        title_str[title_size] = 0;
767 768
        if (title_str[0]) {
            int off = (!c->isom && title_str[0] == title_size - 1);
769 770
            // flag added so as to not set stream handler name if already set from mdia->hdlr
            av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
771
        }
772 773 774
        av_freep(&title_str);
    }

775 776 777
    return 0;
}

778
static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
779
{
780
    return ff_mov_read_esds(c->fc, pb);
781 782
}

783
static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
784 785
{
    AVStream *st;
786
    enum AVAudioServiceType *ast;
787
    int ac3info, acmod, lfeon, bsmod;
788

789 790
    if (c->fc->nb_streams < 1)
        return 0;
791 792
    st = c->fc->streams[c->fc->nb_streams-1];

793
    ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE,
794 795 796 797
                                                            sizeof(*ast));
    if (!ast)
        return AVERROR(ENOMEM);

798
    ac3info = avio_rb24(pb);
799
    bsmod = (ac3info >> 14) & 0x7;
800 801
    acmod = (ac3info >> 11) & 0x7;
    lfeon = (ac3info >> 10) & 0x1;
802 803
    st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon;
    st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
804
    if (lfeon)
805
        st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
806
    *ast = bsmod;
807
    if (st->codecpar->channels > 1 && bsmod == 0x7)
808 809
        *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;

810 811
#if FF_API_LAVF_AVCTX
    FF_DISABLE_DEPRECATION_WARNINGS
812
    st->codec->audio_service_type = *ast;
813 814
    FF_ENABLE_DEPRECATION_WARNINGS
#endif
815 816 817 818

    return 0;
}

819 820 821
static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
822
    enum AVAudioServiceType *ast;
823 824 825 826 827 828
    int eac3info, acmod, lfeon, bsmod;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

829
    ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE,
830 831 832 833
                                                            sizeof(*ast));
    if (!ast)
        return AVERROR(ENOMEM);

834 835 836 837 838 839 840 841
    /* No need to parse fields for additional independent substreams and its
     * associated dependent substreams since libavcodec's E-AC-3 decoder
     * does not support them yet. */
    avio_rb16(pb); /* data_rate and num_ind_sub */
    eac3info = avio_rb24(pb);
    bsmod = (eac3info >> 12) & 0x1f;
    acmod = (eac3info >>  9) & 0x7;
    lfeon = (eac3info >>  8) & 0x1;
842
    st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
843
    if (lfeon)
844 845
        st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
    st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
846
    *ast = bsmod;
847
    if (st->codecpar->channels > 1 && bsmod == 0x7)
848 849
        *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;

850 851
#if FF_API_LAVF_AVCTX
    FF_DISABLE_DEPRECATION_WARNINGS
852
    st->codec->audio_service_type = *ast;
853 854
    FF_ENABLE_DEPRECATION_WARNINGS
#endif
855 856 857 858

    return 0;
}

859 860 861 862 863 864 865 866 867
static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    const uint32_t ddts_size = 20;
    AVStream *st = NULL;
    uint8_t *buf = NULL;
    uint32_t frame_duration_code = 0;
    uint32_t channel_layout_code = 0;
    GetBitContext gb;

868
    buf = av_malloc(ddts_size + AV_INPUT_BUFFER_PADDING_SIZE);
869 870 871 872 873 874 875 876 877 878 879
    if (!buf) {
        return AVERROR(ENOMEM);
    }
    if (avio_read(pb, buf, ddts_size) < ddts_size) {
        av_free(buf);
        return AVERROR_INVALIDDATA;
    }

    init_get_bits(&gb, buf, 8*ddts_size);

    if (c->fc->nb_streams < 1) {
880
        av_free(buf);
881 882 883 884
        return 0;
    }
    st = c->fc->streams[c->fc->nb_streams-1];

885
    st->codecpar->sample_rate = get_bits_long(&gb, 32);
886 887
    if (st->codecpar->sample_rate <= 0) {
        av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
888
        av_free(buf);
889 890
        return AVERROR_INVALIDDATA;
    }
891
    skip_bits_long(&gb, 32); /* max bitrate */
892 893
    st->codecpar->bit_rate = get_bits_long(&gb, 32);
    st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
894 895 896 897
    frame_duration_code = get_bits(&gb, 2);
    skip_bits(&gb, 30); /* various fields */
    channel_layout_code = get_bits(&gb, 16);

898
    st->codecpar->frame_size =
899 900 901 902 903 904 905 906
            (frame_duration_code == 0) ? 512 :
            (frame_duration_code == 1) ? 1024 :
            (frame_duration_code == 2) ? 2048 :
            (frame_duration_code == 3) ? 4096 : 0;

    if (channel_layout_code > 0xff) {
        av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout");
    }
907
    st->codecpar->channel_layout =
908 909 910 911 912 913 914
            ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
            ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
            ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
            ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
            ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
            ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0);

915
    st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
916
    av_free(buf);
917 918 919 920

    return 0;
}

921 922 923 924 925 926 927 928 929 930 931
static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

    if (atom.size < 16)
        return 0;

932 933 934
    /* skip version and flags */
    avio_skip(pb, 4);

935
    ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
936 937 938 939

    return 0;
}

940 941 942
static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
943
    int ret;
944 945 946 947 948

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

949
    if ((ret = ff_get_wav_header(c->fc, pb, st->codecpar, atom.size, 0)) < 0)
950
        av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
951

952
    return ret;
953 954
}

955
static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
956
{
957 958
    const int num = avio_rb32(pb);
    const int den = avio_rb32(pb);
959 960 961 962 963 964
    AVStream *st;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

965 966 967 968 969 970 971
    if ((st->sample_aspect_ratio.den != 1 || st->sample_aspect_ratio.num) && // default
        (den != st->sample_aspect_ratio.den || num != st->sample_aspect_ratio.num)) {
        av_log(c->fc, AV_LOG_WARNING,
               "sample aspect ratio already set to %d:%d, ignoring 'pasp' atom (%d:%d)\n",
               st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
               num, den);
    } else if (den != 0) {
972 973
        av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
                  num, den, 32767);
974 975 976 977
    }
    return 0;
}

978
/* this atom contains actual media data */
979
static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
980
{
981
    if (atom.size == 0) /* wrong one (MP4) */
982 983 984 985 986
        return 0;
    c->found_mdat=1;
    return 0; /* now go for moov */
}

987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
#define DRM_BLOB_SIZE 56

static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    uint8_t intermediate_key[20];
    uint8_t intermediate_iv[20];
    uint8_t input[64];
    uint8_t output[64];
    uint8_t file_checksum[20];
    uint8_t calculated_checksum[20];
    struct AVSHA *sha;
    int i;
    int ret = 0;
    uint8_t *activation_bytes = c->activation_bytes;
    uint8_t *fixed_key = c->audible_fixed_key;

    c->aax_mode = 1;

    sha = av_sha_alloc();
    if (!sha)
        return AVERROR(ENOMEM);
    c->aes_decrypt = av_aes_alloc();
    if (!c->aes_decrypt) {
        ret = AVERROR(ENOMEM);
        goto fail;
    }

    /* drm blob processing */
1015
    avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1016
    avio_read(pb, input, DRM_BLOB_SIZE);
1017
    avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1018 1019 1020 1021
    avio_read(pb, file_checksum, 20);

    av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == "); // required by external tools
    for (i = 0; i < 20; i++)
1022
        av_log(c->fc, AV_LOG_INFO, "%02x", file_checksum[i]);
1023 1024 1025
    av_log(c->fc, AV_LOG_INFO, "\n");

    /* verify activation data */
1026 1027 1028
    if (!activation_bytes) {
        av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
        ret = 0;  /* allow ffprobe to continue working on .aax files */
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
        goto fail;
    }
    if (c->activation_bytes_size != 4) {
        av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
        ret = AVERROR(EINVAL);
        goto fail;
    }

    /* verify fixed key */
    if (c->audible_fixed_key_size != 16) {
        av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
        ret = AVERROR(EINVAL);
        goto fail;
    }

    /* AAX (and AAX+) key derivation */
    av_sha_init(sha, 160);
    av_sha_update(sha, fixed_key, 16);
    av_sha_update(sha, activation_bytes, 4);
    av_sha_final(sha, intermediate_key);
    av_sha_init(sha, 160);
    av_sha_update(sha, fixed_key, 16);
    av_sha_update(sha, intermediate_key, 20);
    av_sha_update(sha, activation_bytes, 4);
    av_sha_final(sha, intermediate_iv);
    av_sha_init(sha, 160);
    av_sha_update(sha, intermediate_key, 16);
    av_sha_update(sha, intermediate_iv, 16);
    av_sha_final(sha, calculated_checksum);
    if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
        av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }
    av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
    av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
    for (i = 0; i < 4; i++) {
        // file data (in output) is stored in big-endian mode
        if (activation_bytes[i] != output[3 - i]) { // critical error
            av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
            ret = AVERROR_INVALIDDATA;
            goto fail;
        }
    }
    memcpy(c->file_key, output + 8, 16);
    memcpy(input, output + 26, 16);
    av_sha_init(sha, 160);
    av_sha_update(sha, input, 16);
    av_sha_update(sha, c->file_key, 16);
    av_sha_update(sha, fixed_key, 16);
    av_sha_final(sha, c->file_iv);

fail:
    av_free(sha);

    return ret;
}

// Audible AAX (and AAX+) bytestream decryption
static int aax_filter(uint8_t *input, int size, MOVContext *c)
{
    int blocks = 0;
    unsigned char iv[16];

    memcpy(iv, c->file_iv, 16); // iv is overwritten
    blocks = size >> 4; // trailing bytes are not encrypted!
    av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
    av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);

    return 0;
}

1101
/* read major brand, minor version and compatible brands and store them as metadata */
1102
static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1103
{
1104 1105 1106 1107
    uint32_t minor_ver;
    int comp_brand_size;
    char* comp_brands_str;
    uint8_t type[5] = {0};
1108 1109 1110
    int ret = ffio_read_size(pb, type, 4);
    if (ret < 0)
        return ret;
1111

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1112
    if (strcmp(type, "qt  "))
1113
        c->isom = 1;
1114
    av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1115
    av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1116
    minor_ver = avio_rb32(pb); /* minor version */
1117
    av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1118 1119 1120

    comp_brand_size = atom.size - 8;
    if (comp_brand_size < 0)
1121
        return AVERROR_INVALIDDATA;
1122 1123 1124
    comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
    if (!comp_brands_str)
        return AVERROR(ENOMEM);
1125 1126 1127

    ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
    if (ret < 0) {
1128
        av_freep(&comp_brands_str);
1129
        return ret;
1130
    }
1131
    comp_brands_str[comp_brand_size] = 0;
1132
    av_dict_set(&c->fc->metadata, "compatible_brands", comp_brands_str, 0);
1133 1134
    av_freep(&comp_brands_str);

1135 1136 1137
    return 0;
}

1138
/* this atom should contain all header atoms */
1139
static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1140
{
1141 1142
    int ret;

1143 1144 1145 1146 1147 1148
    if (c->found_moov) {
        av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
        avio_skip(pb, atom.size);
        return 0;
    }

1149 1150
    if ((ret = mov_read_default(c, pb, atom)) < 0)
        return ret;
1151 1152 1153 1154 1155 1156
    /* 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 */
}

1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
static MOVFragmentStreamInfo * get_frag_stream_info(
    MOVFragmentIndex *frag_index,
    int index,
    int id)
{
    int i;
    MOVFragmentIndexItem * item;

    if (index < 0 || index >= frag_index->nb_items)
        return NULL;
    item = &frag_index->item[index];
    for (i = 0; i < item->nb_stream_info; i++)
        if (item->stream_info[i].id == id)
            return &item->stream_info[i];

    // This shouldn't happen
    return NULL;
}

static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
{
    int i;
    MOVFragmentIndexItem * item;

    if (frag_index->current < 0 ||
        frag_index->current >= frag_index->nb_items)
        return;

    item = &frag_index->item[frag_index->current];
    for (i = 0; i < item->nb_stream_info; i++)
        if (item->stream_info[i].id == id) {
            item->current = i;
            return;
        }

    // id not found.  This shouldn't happen.
    item->current = -1;
}

static MOVFragmentStreamInfo * get_current_frag_stream_info(
    MOVFragmentIndex *frag_index)
{
1199
    MOVFragmentIndexItem *item;
1200 1201 1202 1203
    if (frag_index->current < 0 ||
        frag_index->current >= frag_index->nb_items)
        return NULL;

1204
    item = &frag_index->item[frag_index->current];
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
    if (item->current >= 0 && item->current < item->nb_stream_info)
        return &item->stream_info[item->current];

    // This shouldn't happen
    return NULL;
}

static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
{
    int a, b, m;
    int64_t moof_offset;

    // Optimize for appending new entries
    if (!frag_index->nb_items ||
        frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
        return frag_index->nb_items;

    a = -1;
    b = frag_index->nb_items;

    while (b - a > 1) {
        m = (a + b) >> 1;
        moof_offset = frag_index->item[m].moof_offset;
        if (moof_offset >= offset)
            b = m;
        if (moof_offset <= offset)
            a = m;
    }
    return b;
}

static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
{
1238 1239 1240 1241 1242 1243
    av_assert0(frag_stream_info);
    if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
        return frag_stream_info->sidx_pts;
    if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
        return frag_stream_info->first_tfra_pts;
    return frag_stream_info->tfdt_dts;
1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
}

static int64_t get_frag_time(MOVFragmentIndex *frag_index,
                             int index, int track_id)
{
    MOVFragmentStreamInfo * frag_stream_info;
    int64_t timestamp;
    int i;

    if (track_id >= 0) {
        frag_stream_info = get_frag_stream_info(frag_index, index, track_id);
        return frag_stream_info->sidx_pts;
    }

    for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
        frag_stream_info = &frag_index->item[index].stream_info[i];
        timestamp = get_stream_info_time(frag_stream_info);
        if (timestamp != AV_NOPTS_VALUE)
            return timestamp;
    }
    return AV_NOPTS_VALUE;
}

static int search_frag_timestamp(MOVFragmentIndex *frag_index,
                                 AVStream *st, int64_t timestamp)
{
1270
    int a, b, m, m0;
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
    int64_t frag_time;
    int id = -1;

    if (st) {
        // If the stream is referenced by any sidx, limit the search
        // to fragments that referenced this stream in the sidx
        MOVStreamContext *sc = st->priv_data;
        if (sc->has_sidx)
            id = st->id;
    }

    a = -1;
    b = frag_index->nb_items;

    while (b - a > 1) {
1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
        m0 = m = (a + b) >> 1;

        while (m < b &&
               (frag_time = get_frag_time(frag_index, m, id)) == AV_NOPTS_VALUE)
            m++;

        if (m < b && frag_time <= timestamp)
            a = m;
        else
            b = m0;
1296
    }
1297

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
    return a;
}

static int update_frag_index(MOVContext *c, int64_t offset)
{
    int index, i;
    MOVFragmentIndexItem * item;
    MOVFragmentStreamInfo * frag_stream_info;

    // If moof_offset already exists in frag_index, return index to it
    index = search_frag_moof_offset(&c->frag_index, offset);
    if (index < c->frag_index.nb_items &&
        c->frag_index.item[index].moof_offset == offset)
        return index;

    // offset is not yet in frag index.
    // Insert new item at index (sorted by moof offset)
    item = av_fast_realloc(c->frag_index.item,
                           &c->frag_index.allocated_size,
                           (c->frag_index.nb_items + 1) *
                           sizeof(*c->frag_index.item));
    if(!item)
        return -1;
    c->frag_index.item = item;

    frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
                                        sizeof(*item->stream_info));
    if (!frag_stream_info)
        return -1;

    for (i = 0; i < c->fc->nb_streams; i++) {
1329 1330 1331 1332
        // Avoid building frag index if streams lack track id.
        if (c->fc->streams[i]->id < 0)
            return AVERROR_INVALIDDATA;

1333 1334 1335 1336 1337
        frag_stream_info[i].id = c->fc->streams[i]->id;
        frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
        frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
        frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
        frag_stream_info[i].index_entry = -1;
1338
        frag_stream_info[i].encryption_index = NULL;
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
    }

    if (index < c->frag_index.nb_items)
        memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
                (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));

    item = &c->frag_index.item[index];
    item->headers_read = 0;
    item->current = 0;
    item->nb_stream_info = c->fc->nb_streams;
    item->moof_offset = offset;
    item->stream_info = frag_stream_info;
    c->frag_index.nb_items++;

    return index;
}

static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
                                   int id, int entries)
{
    int i;
    MOVFragmentStreamInfo * frag_stream_info;

    if (index < 0)
        return;
    for (i = index; i < frag_index->nb_items; i++) {
        frag_stream_info = get_frag_stream_info(frag_index, i, id);
        if (frag_stream_info && frag_stream_info->index_entry >= 0)
            frag_stream_info->index_entry += entries;
    }
}

1371
static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1372
{
1373 1374 1375
    // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
    c->fragment.found_tfhd = 0;

1376 1377
    if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
        c->has_looked_for_mfra = 1;
James Almer's avatar
James Almer committed
1378
        if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1379
            int ret;
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
            av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
                    "for a mfra\n");
            if ((ret = mov_read_mfra(c, pb)) < 0) {
                av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
                        "read the mfra (may be a live ismv)\n");
            }
        } else {
            av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
                    "seekable, can not look for mfra\n");
        }
    }
1391
    c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1392
    av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1393
    c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1394 1395
    return mov_read_default(c, pb, atom);
}
1396

1397
static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time)
1398 1399
{
    if (time) {
1400 1401
        if(time >= 2082844800)
            time -= 2082844800;  /* seconds between 1904-01-01 and Epoch */
1402 1403 1404 1405 1406 1407

        if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
            av_log(NULL, AV_LOG_DEBUG, "creation_time is not representable\n");
            return;
        }

1408
        avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1409 1410 1411
    }
}

1412
static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1413
{
1414 1415 1416
    AVStream *st;
    MOVStreamContext *sc;
    int version;
1417
    char language[4] = {0};
1418
    unsigned lang;
1419
    int64_t creation_time;
1420

1421 1422 1423 1424 1425
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

1426 1427 1428 1429 1430
    if (sc->time_scale) {
        av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
        return AVERROR_INVALIDDATA;
    }

1431
    version = avio_r8(pb);
1432
    if (version > 1) {
1433
        avpriv_request_sample(c->fc, "Version %d", version);
1434 1435
        return AVERROR_PATCHWELCOME;
    }
1436
    avio_rb24(pb); /* flags */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1437
    if (version == 1) {
1438 1439
        creation_time = avio_rb64(pb);
        avio_rb64(pb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1440
    } else {
1441 1442
        creation_time = avio_rb32(pb);
        avio_rb32(pb); /* modification time */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1443
    }
1444
    mov_metadata_creation_time(&st->metadata, creation_time);
1445

1446
    sc->time_scale = avio_rb32(pb);
1447
    if (sc->time_scale <= 0) {
1448 1449
        av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
        sc->time_scale = 1;
1450
    }
1451
    st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1452

1453
    lang = avio_rb16(pb); /* language */
1454
    if (ff_mov_lang_to_iso639(lang, language))
1455
        av_dict_set(&st->metadata, "language", language, 0);
1456
    avio_rb16(pb); /* quality */
1457 1458 1459 1460

    return 0;
}

1461
static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1462
{
1463
    int i;
1464
    int64_t creation_time;
1465 1466
    int version = avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
1467

1468
    if (version == 1) {
1469 1470
        creation_time = avio_rb64(pb);
        avio_rb64(pb);
1471
    } else {
1472 1473
        creation_time = avio_rb32(pb);
        avio_rb32(pb); /* modification time */
1474
    }
1475
    mov_metadata_creation_time(&c->fc->metadata, creation_time);
1476
    c->time_scale = avio_rb32(pb); /* time scale */
1477
    if (c->time_scale <= 0) {
1478 1479
        av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
        c->time_scale = 1;
1480
    }
1481
    av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1482

1483
    c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1484 1485
    // set the AVCodecContext duration because the duration of individual tracks
    // may be inaccurate
1486
    if (c->time_scale > 0 && !c->trex_data)
1487
        c->fc->duration = av_rescale(c->duration, AV_TIME_BASE, c->time_scale);
1488
    avio_rb32(pb); /* preferred scale */
1489

1490
    avio_rb16(pb); /* preferred volume */
1491

1492
    avio_skip(pb, 10); /* reserved */
1493

1494 1495 1496 1497 1498 1499
    /* movie display matrix, store it in main context and use it later on */
    for (i = 0; i < 3; i++) {
        c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
        c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
        c->movie_display_matrix[i][2] = avio_rb32(pb); //  2.30 fixed point
    }
1500

1501 1502 1503 1504 1505 1506 1507
    avio_rb32(pb); /* preview time */
    avio_rb32(pb); /* preview duration */
    avio_rb32(pb); /* poster time */
    avio_rb32(pb); /* selection time */
    avio_rb32(pb); /* selection duration */
    avio_rb32(pb); /* current time */
    avio_rb32(pb); /* next track ID */
1508 1509 1510 1511

    return 0;
}

1512
static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1513
{
1514 1515 1516 1517 1518 1519
    AVStream *st;
    int little_endian;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
1520

1521
    little_endian = avio_rb16(pb) & 0xFF;
1522
    av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1523
    if (little_endian == 1) {
1524
        switch (st->codecpar->codec_id) {
1525
        case AV_CODEC_ID_PCM_S24BE:
1526
            st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1527
            break;
1528
        case AV_CODEC_ID_PCM_S32BE:
1529
            st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1530
            break;
1531
        case AV_CODEC_ID_PCM_F32BE:
1532
            st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1533
            break;
1534
        case AV_CODEC_ID_PCM_F64BE:
1535
            st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1536
            break;
1537 1538 1539 1540 1541 1542 1543
        default:
            break;
        }
    }
    return 0;
}

1544 1545 1546 1547
static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    char color_parameter_type[5] = { 0 };
1548
    uint16_t color_primaries, color_trc, color_matrix;
1549
    int ret;
1550 1551 1552 1553 1554

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams - 1];

1555 1556 1557
    ret = ffio_read_size(pb, color_parameter_type, 4);
    if (ret < 0)
        return ret;
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
    if (strncmp(color_parameter_type, "nclx", 4) &&
        strncmp(color_parameter_type, "nclc", 4)) {
        av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
               color_parameter_type);
        return 0;
    }

    color_primaries = avio_rb16(pb);
    color_trc = avio_rb16(pb);
    color_matrix = avio_rb16(pb);

1569
    av_log(c->fc, AV_LOG_TRACE,
1570
           "%s: pri %d trc %d matrix %d",
1571
           color_parameter_type, color_primaries, color_trc, color_matrix);
1572

1573
    if (!strncmp(color_parameter_type, "nclx", 4)) {
1574
        uint8_t color_range = avio_r8(pb) >> 7;
1575
        av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
1576
        if (color_range)
1577
            st->codecpar->color_range = AVCOL_RANGE_JPEG;
1578
        else
1579
            st->codecpar->color_range = AVCOL_RANGE_MPEG;
1580
    }
1581 1582

    if (!av_color_primaries_name(color_primaries))
1583
        color_primaries = AVCOL_PRI_UNSPECIFIED;
1584
    if (!av_color_transfer_name(color_trc))
1585
        color_trc = AVCOL_TRC_UNSPECIFIED;
1586
    if (!av_color_space_name(color_matrix))
1587
        color_matrix = AVCOL_SPC_UNSPECIFIED;
1588

1589 1590 1591
    st->codecpar->color_primaries = color_primaries;
    st->codecpar->color_trc       = color_trc;
    st->codecpar->color_space     = color_matrix;
1592
    av_log(c->fc, AV_LOG_TRACE, "\n");
1593 1594 1595 1596

    return 0;
}

1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    unsigned mov_field_order;
    enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;

    if (c->fc->nb_streams < 1) // will happen with jp2 files
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    if (atom.size < 2)
        return AVERROR_INVALIDDATA;
    mov_field_order = avio_rb16(pb);
    if ((mov_field_order & 0xFF00) == 0x0100)
        decoded_field_order = AV_FIELD_PROGRESSIVE;
    else if ((mov_field_order & 0xFF00) == 0x0200) {
        switch (mov_field_order & 0xFF) {
        case 0x01: decoded_field_order = AV_FIELD_TT;
                   break;
        case 0x06: decoded_field_order = AV_FIELD_BB;
                   break;
        case 0x09: decoded_field_order = AV_FIELD_TB;
                   break;
        case 0x0E: decoded_field_order = AV_FIELD_BT;
                   break;
        }
    }
    if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
        av_log(NULL, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
    }
1626
    st->codecpar->field_order = decoded_field_order;
1627 1628 1629 1630

    return 0;
}

1631
static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
1632 1633
{
    int err = 0;
1634
    uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
1635 1636
    if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
        return AVERROR_INVALIDDATA;
1637 1638
    if ((err = av_reallocp(&par->extradata, size)) < 0) {
        par->extradata_size = 0;
1639 1640
        return err;
    }
1641
    par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
1642 1643 1644 1645 1646
    return 0;
}

/* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1647
                                        AVCodecParameters *par, uint8_t *buf)
1648 1649 1650 1651 1652 1653
{
    int64_t result = atom.size;
    int err;

    AV_WB32(buf    , atom.size + 8);
    AV_WL32(buf + 4, atom.type);
1654
    err = ffio_read_size(pb, buf + 8, atom.size);
1655
    if (err < 0) {
1656
        par->extradata_size -= atom.size;
1657 1658 1659
        return err;
    } else if (err < atom.size) {
        av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
1660
        par->extradata_size -= atom.size - err;
1661 1662
        result = err;
    }
1663
    memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1664 1665 1666
    return result;
}

1667
/* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
1668
static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1669
                              enum AVCodecID codec_id)
1670
{
1671
    AVStream *st;
1672
    uint64_t original_size;
1673
    int err;
1674 1675 1676

    if (c->fc->nb_streams < 1) // will happen with jp2 files
        return 0;
1677
    st = c->fc->streams[c->fc->nb_streams-1];
1678

1679
    if (st->codecpar->codec_id != codec_id)
1680 1681
        return 0; /* unexpected codec_id - don't mess with extradata */

1682 1683
    original_size = st->codecpar->extradata_size;
    err = mov_realloc_extradata(st->codecpar, atom);
1684
    if (err)
1685
        return err;
1686

1687
    err =  mov_read_atom_into_extradata(c, pb, atom, st->codecpar,  st->codecpar->extradata + original_size);
1688
    if (err < 0)
1689
        return err;
1690
    return 0; // Note: this is the original behavior to ignore truncation.
1691 1692
}

1693 1694 1695
/* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
1696
    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
1697 1698 1699 1700
}

static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
1701
    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVS);
1702 1703 1704 1705
}

static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
1706
    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
1707 1708
}

1709 1710 1711 1712 1713
static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
}

Carl Eugen Hoyos's avatar
Carl Eugen Hoyos committed
1714
static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1715
{
1716 1717 1718 1719
    int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
    if(ret == 0)
        ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
    return ret;
1720 1721
}

1722 1723 1724 1725 1726
static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);

    if (!ret && c->fc->nb_streams >= 1) {
1727 1728 1729 1730
        AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
        if (par->extradata_size >= 40) {
            par->height = AV_RB16(&par->extradata[36]);
            par->width  = AV_RB16(&par->extradata[38]);
1731 1732 1733 1734 1735
        }
    }
    return ret;
}

1736 1737
static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
1738
    if (c->fc->nb_streams >= 1) {
1739 1740 1741
        AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
        if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
            par->codec_id == AV_CODEC_ID_H264 &&
1742
            atom.size > 11) {
1743
            int cid;
1744
            avio_skip(pb, 10);
1745
            cid = avio_rb16(pb);
1746
            /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
1747
            if (cid == 0xd4d || cid == 0xd4e)
1748
                par->width = 1440;
1749
            return 0;
1750
        } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
1751
                    par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
1752
                    par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
                   atom.size >= 24) {
            int num, den;
            avio_skip(pb, 12);
            num = avio_rb32(pb);
            den = avio_rb32(pb);
            if (num <= 0 || den <= 0)
                return 0;
            switch (avio_rb32(pb)) {
            case 2:
                if (den >= INT_MAX / 2)
                    return 0;
                den *= 2;
            case 1:
                c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.num = num;
                c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.den = den;
            default:
                return 0;
            }
1771
        }
1772 1773 1774 1775 1776
    }

    return mov_read_avid(c, pb, atom);
}

1777 1778 1779 1780 1781 1782
static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    int ret = 0;
    int length = 0;
    uint64_t original_size;
    if (c->fc->nb_streams >= 1) {
1783 1784
        AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
        if (par->codec_id == AV_CODEC_ID_H264)
1785
            return 0;
1786
        if (atom.size == 16) {
1787 1788
            original_size = par->extradata_size;
            ret = mov_realloc_extradata(par, atom);
1789
            if (!ret) {
1790
                length =  mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
1791
                if (length == atom.size) {
1792
                    const uint8_t range_value = par->extradata[original_size + 19];
1793 1794
                    switch (range_value) {
                    case 1:
1795
                        par->color_range = AVCOL_RANGE_MPEG;
1796 1797
                        break;
                    case 2:
1798
                        par->color_range = AVCOL_RANGE_JPEG;
1799 1800 1801 1802 1803
                        break;
                    default:
                        av_log(c, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
                        break;
                    }
1804
                    ff_dlog(c, "color_range: %d\n", par->color_range);
1805 1806 1807 1808 1809 1810 1811 1812
                } else {
                  /* For some reason the whole atom was not added to the extradata */
                  av_log(c, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
                }
            } else {
                av_log(c, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
            }
        } else {
1813
            av_log(c, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
1814 1815 1816 1817 1818 1819
        }
    }

    return ret;
}

1820 1821
static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
1822
    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
1823 1824
}

1825
static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
Roberto Togni's avatar
Roberto Togni committed
1826
{
1827
    AVStream *st;
1828
    int ret;
1829 1830 1831 1832

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
Roberto Togni's avatar
Roberto Togni committed
1833

1834
    if ((uint64_t)atom.size > (1<<30))
1835
        return AVERROR_INVALIDDATA;
1836

1837 1838 1839
    if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
        st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
        st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
1840
        // pass all frma atom to codec, needed at least for QDMC and QDM2
1841
        av_freep(&st->codecpar->extradata);
1842
        ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1843 1844
        if (ret < 0)
            return ret;
1845
    } else if (atom.size > 8) { /* to read frma, esds atoms */
1846
        if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
            uint64_t buffer;
            ret = ffio_ensure_seekback(pb, 8);
            if (ret < 0)
                return ret;
            buffer = avio_rb64(pb);
            atom.size -= 8;
            if (  (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
                && buffer >> 32 <= atom.size
                && buffer >> 32 >= 8) {
                avio_skip(pb, -8);
                atom.size += 8;
1858
            } else if (!st->codecpar->extradata_size) {
1859
#define ALAC_EXTRADATA_SIZE 36
1860 1861
                st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
                if (!st->codecpar->extradata)
1862
                    return AVERROR(ENOMEM);
1863 1864 1865 1866 1867
                st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
                AV_WB32(st->codecpar->extradata    , ALAC_EXTRADATA_SIZE);
                AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
                AV_WB64(st->codecpar->extradata + 12, buffer);
                avio_read(pb, st->codecpar->extradata + 20, 16);
1868 1869 1870 1871
                avio_skip(pb, atom.size - 24);
                return 0;
            }
        }
1872 1873
        if ((ret = mov_read_default(c, pb, atom)) < 0)
            return ret;
1874
    } else
1875
        avio_skip(pb, atom.size);
Roberto Togni's avatar
Roberto Togni committed
1876 1877 1878
    return 0;
}

1879 1880 1881 1882
/**
 * This function reads atom content and puts data in extradata without tag
 * nor size unlike mov_read_extradata.
 */
1883
static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1884
{
1885
    AVStream *st;
1886
    int ret;
1887 1888 1889 1890

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
1891

1892
    if ((uint64_t)atom.size > (1<<30))
1893
        return AVERROR_INVALIDDATA;
1894

1895
    if (atom.size >= 10) {
1896
        // Broken files created by legacy versions of libavformat will
1897 1898 1899 1900 1901 1902 1903
        // wrap a whole fiel atom inside of a glbl atom.
        unsigned size = avio_rb32(pb);
        unsigned type = avio_rl32(pb);
        avio_seek(pb, -8, SEEK_CUR);
        if (type == MKTAG('f','i','e','l') && size == atom.size)
            return mov_read_default(c, pb, atom);
    }
1904
    if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
1905 1906 1907
        av_log(c, AV_LOG_WARNING, "ignoring multiple glbl\n");
        return 0;
    }
1908
    av_freep(&st->codecpar->extradata);
1909
    ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1910 1911
    if (ret < 0)
        return ret;
1912
    if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
1913 1914 1915 1916 1917
        /* HEVC-based Dolby Vision derived from hvc1.
           Happens to match with an identifier
           previously utilized for DV. Thus, if we have
           the hvcC extradata box available as specified,
           set codec to HEVC */
1918
        st->codecpar->codec_id = AV_CODEC_ID_HEVC;
1919

1920 1921 1922
    return 0;
}

1923 1924 1925 1926
static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    uint8_t profile_level;
1927
    int ret;
1928 1929 1930 1931 1932 1933 1934 1935 1936

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

    if (atom.size >= (1<<28) || atom.size < 7)
        return AVERROR_INVALIDDATA;

    profile_level = avio_r8(pb);
1937
    if ((profile_level & 0xf0) != 0xc0)
1938 1939 1940
        return 0;

    avio_seek(pb, 6, SEEK_CUR);
1941
    av_freep(&st->codecpar->extradata);
1942
    ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
1943
    if (ret < 0)
1944
        return ret;
1945

1946 1947 1948
    return 0;
}

Martin Storsjö's avatar
Martin Storsjö committed
1949 1950 1951 1952 1953
/**
 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
 * but can have extradata appended at the end after the 40 bytes belonging
 * to the struct.
 */
1954
static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
Martin Storsjö's avatar
Martin Storsjö committed
1955 1956
{
    AVStream *st;
1957
    int ret;
Martin Storsjö's avatar
Martin Storsjö committed
1958 1959 1960 1961 1962 1963 1964

    if (c->fc->nb_streams < 1)
        return 0;
    if (atom.size <= 40)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

1965
    if ((uint64_t)atom.size > (1<<30))
1966
        return AVERROR_INVALIDDATA;
Martin Storsjö's avatar
Martin Storsjö committed
1967

1968
    avio_skip(pb, 40);
1969
    av_freep(&st->codecpar->extradata);
1970
    ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
1971 1972 1973
    if (ret < 0)
        return ret;

Martin Storsjö's avatar
Martin Storsjö committed
1974 1975 1976
    return 0;
}

1977
static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1978
{
1979 1980
    AVStream *st;
    MOVStreamContext *sc;
1981
    unsigned int i, entries;
1982

1983 1984 1985 1986 1987
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

1988 1989
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
1990

1991
    entries = avio_rb32(pb);
1992

Alex Converse's avatar
Alex Converse committed
1993 1994
    if (!entries)
        return 0;
1995

1996
    if (sc->chunk_offsets)
1997
        av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n");
1998 1999
    av_free(sc->chunk_offsets);
    sc->chunk_count = 0;
2000
    sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2001
    if (!sc->chunk_offsets)
2002 2003 2004
        return AVERROR(ENOMEM);
    sc->chunk_count = entries;

2005
    if      (atom.type == MKTAG('s','t','c','o'))
2006
        for (i = 0; i < entries && !pb->eof_reached; i++)
2007
            sc->chunk_offsets[i] = avio_rb32(pb);
2008
    else if (atom.type == MKTAG('c','o','6','4'))
2009
        for (i = 0; i < entries && !pb->eof_reached; i++)
2010
            sc->chunk_offsets[i] = avio_rb64(pb);
2011
    else
2012
        return AVERROR_INVALIDDATA;
2013

2014 2015
    sc->chunk_count = i;

2016 2017
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2018
        return AVERROR_EOF;
2019
    }
2020

2021 2022 2023
    return 0;
}

2024 2025 2026 2027 2028 2029 2030 2031 2032
static int mov_codec_id(AVStream *st, uint32_t format)
{
    int id = ff_codec_get_id(ff_codec_movaudio_tags, format);

    if (id <= 0 &&
        ((format & 0xFFFF) == 'm' + ('s' << 8) ||
         (format & 0xFFFF) == 'T' + ('S' << 8)))
        id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);

2033 2034 2035
    if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
    } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2036
               /* skip old ASF MPEG-4 tag */
2037 2038 2039 2040 2041
               format && format != MKTAG('m','p','4','s')) {
        id = ff_codec_get_id(ff_codec_movvideo_tags, format);
        if (id <= 0)
            id = ff_codec_get_id(ff_codec_bmp_tags, format);
        if (id > 0)
2042
            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2043 2044 2045
        else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
                    (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
                    st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2046 2047
            id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
            if (id > 0)
2048
                st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2049 2050
            else
                id = ff_codec_get_id(ff_codec_movdata_tags, format);
2051 2052 2053
        }
    }

2054
    st->codecpar->codec_tag = format;
2055 2056 2057 2058

    return id;
}

2059 2060 2061
static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
                                 AVStream *st, MOVStreamContext *sc)
{
2062
    uint8_t codec_name[32] = { 0 };
2063 2064 2065 2066 2067 2068
    int64_t stsd_start;
    unsigned int len;

    /* The first 16 bytes of the video sample description are already
     * read in ff_mov_read_stsd_entries() */
    stsd_start = avio_tell(pb) - 16;
2069 2070 2071 2072 2073 2074 2075

    avio_rb16(pb); /* version */
    avio_rb16(pb); /* revision level */
    avio_rb32(pb); /* vendor */
    avio_rb32(pb); /* temporal quality */
    avio_rb32(pb); /* spatial quality */

2076 2077
    st->codecpar->width  = avio_rb16(pb); /* width */
    st->codecpar->height = avio_rb16(pb); /* height */
2078 2079 2080 2081 2082 2083 2084 2085 2086

    avio_rb32(pb); /* horiz resolution */
    avio_rb32(pb); /* vert resolution */
    avio_rb32(pb); /* data size, always 0 */
    avio_rb16(pb); /* frames per samples */

    len = avio_r8(pb); /* codec name, pascal string */
    if (len > 31)
        len = 31;
2087
    mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2088 2089
    if (len < 31)
        avio_skip(pb, 31 - len);
2090 2091 2092 2093

    if (codec_name[0])
        av_dict_set(&st->metadata, "encoder", codec_name, 0);

2094
    /* codec_tag YV12 triggers an UV swap in rawdec.c */
James Almer's avatar
James Almer committed
2095
    if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2096
        st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2097 2098
        st->codecpar->width &= ~1;
        st->codecpar->height &= ~1;
2099
    }
2100
    /* Flash Media Server uses tag H.263 with Sorenson Spark */
2101
    if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2102
        !strncmp(codec_name, "Sorenson H263", 13))
2103
        st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2104

2105
    st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2106 2107 2108

    avio_seek(pb, stsd_start, SEEK_SET);

2109 2110
    if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
        st->codecpar->bits_per_coded_sample &= 0x1F;
2111 2112 2113 2114
        sc->has_palette = 1;
    }
}

2115 2116 2117 2118
static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
                                 AVStream *st, MOVStreamContext *sc)
{
    int bits_per_sample, flags;
2119
    uint16_t version = avio_rb16(pb);
2120
    AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2121 2122 2123 2124

    avio_rb16(pb); /* revision level */
    avio_rb32(pb); /* vendor */

2125 2126 2127
    st->codecpar->channels              = avio_rb16(pb); /* channel count */
    st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
    av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels);
2128 2129 2130 2131

    sc->audio_cid = avio_rb16(pb);
    avio_rb16(pb); /* packet size = 0 */

2132
    st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2133 2134

    // Read QT version 1 fields. In version 0 these do not exist.
2135
    av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2136
    if (!c->isom ||
2137 2138
        (compatible_brands && strstr(compatible_brands->value, "qt  ")) ||
        (sc->stsd_version == 0 && version > 0)) {
2139 2140 2141 2142 2143 2144 2145
        if (version == 1) {
            sc->samples_per_frame = avio_rb32(pb);
            avio_rb32(pb); /* bytes per packet */
            sc->bytes_per_frame = avio_rb32(pb);
            avio_rb32(pb); /* bytes per sample */
        } else if (version == 2) {
            avio_rb32(pb); /* sizeof struct only */
2146 2147
            st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
            st->codecpar->channels    = avio_rb32(pb);
2148
            avio_rb32(pb); /* always 0x7F000000 */
2149
            st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2150 2151 2152 2153

            flags = avio_rb32(pb); /* lpcm format specific flag */
            sc->bytes_per_frame   = avio_rb32(pb);
            sc->samples_per_frame = avio_rb32(pb);
2154 2155 2156
            if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
                st->codecpar->codec_id =
                    ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2157 2158
                                             flags);
        }
2159 2160
        if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
            /* can't correctly handle variable sized packet as audio unit */
2161
            switch (st->codecpar->codec_id) {
2162 2163 2164 2165 2166 2167
            case AV_CODEC_ID_MP2:
            case AV_CODEC_ID_MP3:
                st->need_parsing = AVSTREAM_PARSE_FULL;
                break;
            }
        }
2168 2169
    }

2170
    if (sc->format == 0) {
2171 2172 2173 2174
        if (st->codecpar->bits_per_coded_sample == 8)
            st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
        else if (st->codecpar->bits_per_coded_sample == 16)
            st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2175 2176
    }

2177
    switch (st->codecpar->codec_id) {
2178 2179
    case AV_CODEC_ID_PCM_S8:
    case AV_CODEC_ID_PCM_U8:
2180 2181
        if (st->codecpar->bits_per_coded_sample == 16)
            st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2182 2183 2184
        break;
    case AV_CODEC_ID_PCM_S16LE:
    case AV_CODEC_ID_PCM_S16BE:
2185 2186 2187 2188 2189
        if (st->codecpar->bits_per_coded_sample == 8)
            st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
        else if (st->codecpar->bits_per_coded_sample == 24)
            st->codecpar->codec_id =
                st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2190
                AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2191 2192 2193
        else if (st->codecpar->bits_per_coded_sample == 32)
             st->codecpar->codec_id =
                st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2194
                AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2195 2196 2197 2198
        break;
    /* set values for old format before stsd version 1 appeared */
    case AV_CODEC_ID_MACE3:
        sc->samples_per_frame = 6;
2199
        sc->bytes_per_frame   = 2 * st->codecpar->channels;
2200 2201 2202
        break;
    case AV_CODEC_ID_MACE6:
        sc->samples_per_frame = 6;
2203
        sc->bytes_per_frame   = 1 * st->codecpar->channels;
2204 2205 2206
        break;
    case AV_CODEC_ID_ADPCM_IMA_QT:
        sc->samples_per_frame = 64;
2207
        sc->bytes_per_frame   = 34 * st->codecpar->channels;
2208 2209 2210 2211 2212 2213 2214 2215 2216
        break;
    case AV_CODEC_ID_GSM:
        sc->samples_per_frame = 160;
        sc->bytes_per_frame   = 33;
        break;
    default:
        break;
    }

2217
    bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2218
    if (bits_per_sample) {
2219 2220
        st->codecpar->bits_per_coded_sample = bits_per_sample;
        sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels;
2221 2222 2223
    }
}

2224 2225
static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
                                    AVStream *st, MOVStreamContext *sc,
2226
                                    int64_t size)
2227 2228 2229 2230 2231
{
    // ttxt stsd contains display flags, justification, background
    // color, fonts, and default styles, so fake an atom to read it
    MOVAtom fake_atom = { .size = size };
    // mp4s contains a regular esds atom
2232
    if (st->codecpar->codec_tag != AV_RL32("mp4s"))
2233
        mov_read_glbl(c, pb, fake_atom);
2234 2235
    st->codecpar->width  = sc->width;
    st->codecpar->height = sc->height;
2236 2237
}

2238 2239 2240 2241 2242 2243 2244 2245 2246
static uint32_t yuv_to_rgba(uint32_t ycbcr)
{
    uint8_t r, g, b;
    int y, cb, cr;

    y  = (ycbcr >> 16) & 0xFF;
    cr = (ycbcr >> 8)  & 0xFF;
    cb =  ycbcr        & 0xFF;

2247 2248 2249
    b = av_clip_uint8((1164 * (y - 16)                     + 2018 * (cb - 128)) / 1000);
    g = av_clip_uint8((1164 * (y - 16) -  813 * (cr - 128) -  391 * (cb - 128)) / 1000);
    r = av_clip_uint8((1164 * (y - 16) + 1596 * (cr - 128)                    ) / 1000);
2250 2251 2252 2253 2254 2255 2256

    return (r << 16) | (g << 8) | b;
}

static int mov_rewrite_dvd_sub_extradata(AVStream *st)
{
    char buf[256] = {0};
2257
    uint8_t *src = st->codecpar->extradata;
2258 2259
    int i;

2260
    if (st->codecpar->extradata_size != 64)
2261 2262
        return 0;

2263
    if (st->codecpar->width > 0 &&  st->codecpar->height > 0)
2264
        snprintf(buf, sizeof(buf), "size: %dx%d\n",
2265
                 st->codecpar->width, st->codecpar->height);
2266 2267 2268 2269 2270 2271
    av_strlcat(buf, "palette: ", sizeof(buf));

    for (i = 0; i < 16; i++) {
        uint32_t yuv = AV_RB32(src + i * 4);
        uint32_t rgba = yuv_to_rgba(yuv);

2272
        av_strlcatf(buf, sizeof(buf), "%06"PRIx32"%s", rgba, i != 15 ? ", " : "");
2273 2274 2275 2276 2277
    }

    if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf))
        return 0;

2278 2279 2280 2281
    av_freep(&st->codecpar->extradata);
    st->codecpar->extradata_size = 0;
    st->codecpar->extradata = av_mallocz(strlen(buf) + AV_INPUT_BUFFER_PADDING_SIZE);
    if (!st->codecpar->extradata)
2282
        return AVERROR(ENOMEM);
2283 2284
    st->codecpar->extradata_size = strlen(buf);
    memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size);
2285 2286 2287 2288

    return 0;
}

Luca Barbato's avatar
Luca Barbato committed
2289 2290
static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
                                AVStream *st, MOVStreamContext *sc,
2291
                                int64_t size)
Luca Barbato's avatar
Luca Barbato committed
2292
{
2293 2294
    int ret;

2295
    if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2296
        if ((int)size != size)
Luca Barbato's avatar
Luca Barbato committed
2297
            return AVERROR(ENOMEM);
2298

2299
        ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2300 2301
        if (ret < 0)
            return ret;
2302 2303 2304
        if (size > 16) {
            MOVStreamContext *tmcd_ctx = st->priv_data;
            int val;
2305
            val = AV_RB32(st->codecpar->extradata + 4);
2306
            tmcd_ctx->tmcd_flags = val;
2307 2308
            st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
            st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2309 2310 2311 2312 2313
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
            st->codec->time_base = av_inv_q(st->avg_frame_rate);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
2314 2315
            /* adjust for per frame dur in counter mode */
            if (tmcd_ctx->tmcd_flags & 0x0008) {
2316 2317 2318 2319 2320 2321
                int timescale = AV_RB32(st->codecpar->extradata + 8);
                int framedur = AV_RB32(st->codecpar->extradata + 12);
                st->avg_frame_rate.num *= timescale;
                st->avg_frame_rate.den *= framedur;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
2322 2323
                st->codec->time_base.den *= timescale;
                st->codec->time_base.num *= framedur;
2324 2325
FF_ENABLE_DEPRECATION_WARNINGS
#endif
2326
            }
2327
            if (size > 30) {
2328 2329
                uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
                uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2330
                if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
2331
                    uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2332 2333 2334 2335
                    if (str_size > 0 && size >= (int)str_size + 26) {
                        char *reel_name = av_malloc(str_size + 1);
                        if (!reel_name)
                            return AVERROR(ENOMEM);
2336
                        memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2337 2338 2339 2340 2341 2342 2343 2344 2345 2346
                        reel_name[str_size] = 0; /* Add null terminator */
                        /* don't add reel_name if emtpy string */
                        if (*reel_name == 0) {
                            av_free(reel_name);
                        } else {
                            av_dict_set(&st->metadata, "reel_name", reel_name,  AV_DICT_DONT_STRDUP_VAL);
                        }
                    }
                }
            }
2347
        }
Luca Barbato's avatar
Luca Barbato committed
2348 2349 2350 2351 2352 2353 2354
    } else {
        /* other codec type, just skip (rtp, mp4s ...) */
        avio_skip(pb, size);
    }
    return 0;
}

2355 2356 2357
static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
                                   AVStream *st, MOVStreamContext *sc)
{
2358 2359 2360
    if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
        !st->codecpar->sample_rate && sc->time_scale > 1)
        st->codecpar->sample_rate = sc->time_scale;
2361 2362

    /* special codec parameters handling */
2363
    switch (st->codecpar->codec_id) {
2364 2365
#if CONFIG_DV_DEMUXER
    case AV_CODEC_ID_DVAUDIO:
2366 2367 2368 2369 2370
        c->dv_fctx = avformat_alloc_context();
        if (!c->dv_fctx) {
            av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
            return AVERROR(ENOMEM);
        }
2371 2372 2373 2374 2375 2376
        c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
        if (!c->dv_demux) {
            av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
            return AVERROR(ENOMEM);
        }
        sc->dv_audio_container = 1;
2377
        st->codecpar->codec_id    = AV_CODEC_ID_PCM_S16LE;
2378 2379 2380 2381
        break;
#endif
    /* no ifdef since parameters are always those */
    case AV_CODEC_ID_QCELP:
2382
        st->codecpar->channels = 1;
2383
        // force sample rate for qcelp when not stored in mov
2384 2385
        if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
            st->codecpar->sample_rate = 8000;
2386 2387 2388 2389
        // FIXME: Why is the following needed for some files?
        sc->samples_per_frame = 160;
        if (!sc->bytes_per_frame)
            sc->bytes_per_frame = 35;
2390 2391
        break;
    case AV_CODEC_ID_AMR_NB:
2392
        st->codecpar->channels    = 1;
2393
        /* force sample rate for amr, stsd in 3gp does not store sample rate */
2394
        st->codecpar->sample_rate = 8000;
2395 2396
        break;
    case AV_CODEC_ID_AMR_WB:
2397 2398
        st->codecpar->channels    = 1;
        st->codecpar->sample_rate = 16000;
2399 2400 2401 2402
        break;
    case AV_CODEC_ID_MP2:
    case AV_CODEC_ID_MP3:
        /* force type after stsd for m1a hdlr */
2403
        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2404 2405 2406 2407 2408
        break;
    case AV_CODEC_ID_GSM:
    case AV_CODEC_ID_ADPCM_MS:
    case AV_CODEC_ID_ADPCM_IMA_WAV:
    case AV_CODEC_ID_ILBC:
2409 2410 2411
    case AV_CODEC_ID_MACE3:
    case AV_CODEC_ID_MACE6:
    case AV_CODEC_ID_QDM2:
2412
        st->codecpar->block_align = sc->bytes_per_frame;
2413 2414
        break;
    case AV_CODEC_ID_ALAC:
2415 2416 2417
        if (st->codecpar->extradata_size == 36) {
            st->codecpar->channels    = AV_RB8 (st->codecpar->extradata + 21);
            st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2418 2419
        }
        break;
2420
    case AV_CODEC_ID_AC3:
2421
    case AV_CODEC_ID_EAC3:
2422
    case AV_CODEC_ID_MPEG1VIDEO:
2423
    case AV_CODEC_ID_VC1:
2424
    case AV_CODEC_ID_VP8:
2425
    case AV_CODEC_ID_VP9:
2426 2427 2428 2429 2430 2431 2432 2433
        st->need_parsing = AVSTREAM_PARSE_FULL;
        break;
    default:
        break;
    }
    return 0;
}

2434 2435
static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
                                  int codec_tag, int format,
2436
                                  int64_t size)
2437 2438 2439 2440 2441
{
    int video_codec_id = ff_codec_get_id(ff_codec_movvideo_tags, format);

    if (codec_tag &&
         (codec_tag != format &&
2442 2443
          // AVID 1:1 samples with differing data format and codec tag exist
          (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
2444 2445
          // prores is allowed to have differing data format and codec tag
          codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
2446 2447
          // so is dv (sigh)
          codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
2448
          (c->fc->video_codec_id ? video_codec_id != c->fc->video_codec_id
2449
                                 : codec_tag != MKTAG('j','p','e','g')))) {
2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461
        /* 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. */

        av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
        avio_skip(pb, size);
        return 1;
    }

    return 0;
}

2462
int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
2463
{
2464 2465
    AVStream *st;
    MOVStreamContext *sc;
2466
    int pseudo_stream_id;
2467

2468
    av_assert0 (c->fc->nb_streams >= 1);
2469 2470 2471
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

2472 2473 2474
    for (pseudo_stream_id = 0;
         pseudo_stream_id < entries && !pb->eof_reached;
         pseudo_stream_id++) {
2475
        //Parsing Sample description table
2476
        enum AVCodecID id;
Luca Barbato's avatar
Luca Barbato committed
2477
        int ret, dref_id = 1;
2478
        MOVAtom a = { AV_RL32("stsd") };
2479
        int64_t start_pos = avio_tell(pb);
2480
        int64_t size    = avio_rb32(pb); /* size */
2481
        uint32_t format = avio_rl32(pb); /* data format */
2482

2483
        if (size >= 16) {
2484 2485 2486
            avio_rb32(pb); /* reserved */
            avio_rb16(pb); /* reserved */
            dref_id = avio_rb16(pb);
2487
        } else if (size <= 7) {
2488 2489
            av_log(c->fc, AV_LOG_ERROR,
                   "invalid size %"PRId64" in stsd\n", size);
2490
            return AVERROR_INVALIDDATA;
2491
        }
2492

2493
        if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
2494 2495
                                   size - (avio_tell(pb) - start_pos))) {
            sc->stsd_count++;
2496
            continue;
2497
        }
2498

2499
        sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
2500
        sc->dref_id= dref_id;
2501
        sc->format = format;
2502

2503
        id = mov_codec_id(st, format);
2504

2505
        av_log(c->fc, AV_LOG_TRACE,
2506 2507
               "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
               av_fourcc2str(format), st->codecpar->codec_type);
2508

2509
        st->codecpar->codec_id = id;
2510
        if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
2511
            mov_parse_stsd_video(c, pb, st, sc);
2512
        } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
2513
            mov_parse_stsd_audio(c, pb, st, sc);
2514 2515 2516 2517
            if (st->codecpar->sample_rate < 0) {
                av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
                return AVERROR_INVALIDDATA;
            }
2518
        } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
2519 2520
            mov_parse_stsd_subtitle(c, pb, st, sc,
                                    size - (avio_tell(pb) - start_pos));
2521
        } else {
Luca Barbato's avatar
Luca Barbato committed
2522 2523 2524 2525
            ret = mov_parse_stsd_data(c, pb, st, sc,
                                      size - (avio_tell(pb) - start_pos));
            if (ret < 0)
                return ret;
2526
        }
2527
        /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
2528
        a.size = size - (avio_tell(pb) - start_pos);
2529
        if (a.size > 8) {
2530 2531
            if ((ret = mov_read_default(c, pb, a)) < 0)
                return ret;
2532
        } else if (a.size > 0)
2533
            avio_skip(pb, a.size);
2534

2535
        if (sc->extradata && st->codecpar->extradata) {
2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546
            int extra_size = st->codecpar->extradata_size;

            /* Move the current stream extradata to the stream context one. */
            sc->extradata_size[pseudo_stream_id] = extra_size;
            sc->extradata[pseudo_stream_id] = av_malloc(extra_size + AV_INPUT_BUFFER_PADDING_SIZE);
            if (!sc->extradata[pseudo_stream_id])
                return AVERROR(ENOMEM);
            memcpy(sc->extradata[pseudo_stream_id], st->codecpar->extradata, extra_size);
            av_freep(&st->codecpar->extradata);
            st->codecpar->extradata_size = 0;
        }
2547
        sc->stsd_count++;
2548
    }
2549

2550 2551
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
2552
        return AVERROR_EOF;
2553
    }
2554

2555
    return 0;
2556 2557
}

2558
static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2559
{
2560 2561
    AVStream *st;
    MOVStreamContext *sc;
2562
    int ret, entries;
2563 2564 2565 2566 2567

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams - 1];
    sc = st->priv_data;
2568

2569
    sc->stsd_version = avio_r8(pb);
2570
    avio_rb24(pb); /* flags */
2571
    entries = avio_rb32(pb);
2572

2573 2574
    /* Each entry contains a size (4 bytes) and format (4 bytes). */
    if (entries <= 0 || entries > atom.size / 8) {
2575 2576 2577
        av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
        return AVERROR_INVALIDDATA;
    }
2578

2579
    if (sc->extradata) {
2580 2581
        av_log(c->fc, AV_LOG_ERROR,
               "Duplicate stsd found in this track.\n");
2582 2583
        return AVERROR_INVALIDDATA;
    }
2584

2585 2586
    /* Prepare space for hosting multiple extradata. */
    sc->extradata = av_mallocz_array(entries, sizeof(*sc->extradata));
2587 2588
    if (!sc->extradata)
        return AVERROR(ENOMEM);
2589

2590
    sc->extradata_size = av_mallocz_array(entries, sizeof(*sc->extradata_size));
2591
    if (!sc->extradata_size) {
2592 2593 2594
        ret = AVERROR(ENOMEM);
        goto fail;
    }
2595

2596
    ret = ff_mov_read_stsd_entries(c, pb, entries);
2597
    if (ret < 0)
2598
        goto fail;
2599 2600

    /* Restore back the primary extradata. */
2601
    av_freep(&st->codecpar->extradata);
2602
    st->codecpar->extradata_size = sc->extradata_size[0];
2603 2604 2605 2606 2607 2608
    if (sc->extradata_size[0]) {
        st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
        if (!st->codecpar->extradata)
            return AVERROR(ENOMEM);
        memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
    }
2609

2610
    return mov_finalize_stsd_codec(c, pb, st, sc);
2611
fail:
2612 2613 2614 2615 2616 2617
    if (sc->extradata) {
        int j;
        for (j = 0; j < sc->stsd_count; j++)
            av_freep(&sc->extradata[j]);
    }

2618 2619 2620
    av_freep(&sc->extradata);
    av_freep(&sc->extradata_size);
    return ret;
2621 2622
}

2623
static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2624
{
2625 2626
    AVStream *st;
    MOVStreamContext *sc;
2627
    unsigned int i, entries;
2628

2629 2630 2631 2632 2633
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

2634 2635
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
2636

2637
    entries = avio_rb32(pb);
2638 2639
    if ((uint64_t)entries * 12 + 4 > atom.size)
        return AVERROR_INVALIDDATA;
2640

2641
    av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
2642

Alex Converse's avatar
Alex Converse committed
2643 2644
    if (!entries)
        return 0;
2645
    if (sc->stsc_data)
2646
        av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n");
2647 2648
    av_free(sc->stsc_data);
    sc->stsc_count = 0;
2649
    sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
2650
    if (!sc->stsc_data)
2651 2652
        return AVERROR(ENOMEM);

2653
    for (i = 0; i < entries && !pb->eof_reached; i++) {
2654 2655 2656
        sc->stsc_data[i].first = avio_rb32(pb);
        sc->stsc_data[i].count = avio_rb32(pb);
        sc->stsc_data[i].id = avio_rb32(pb);
2657
    }
2658 2659

    sc->stsc_count = i;
2660
    for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
2661
        int64_t first_min = i + 1;
2662 2663
        if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
            (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
2664
            sc->stsc_data[i].first < first_min ||
2665 2666 2667
            sc->stsc_data[i].count < 1 ||
            sc->stsc_data[i].id < 1) {
            av_log(c->fc, AV_LOG_WARNING, "STSC entry %d is invalid (first=%d count=%d id=%d)\n", i, sc->stsc_data[i].first, sc->stsc_data[i].count, sc->stsc_data[i].id);
2668 2669 2670 2671 2672 2673 2674 2675 2676
            if (i+1 >= sc->stsc_count) {
                sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
                if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
                    sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
                sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
                sc->stsc_data[i].id    = FFMAX(sc->stsc_data[i].id, 1);
                continue;
            }
            av_assert0(sc->stsc_data[i+1].first >= 2);
2677 2678 2679 2680 2681 2682
            // We replace this entry by the next valid
            sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
            sc->stsc_data[i].count = sc->stsc_data[i+1].count;
            sc->stsc_data[i].id    = sc->stsc_data[i+1].id;
        }
    }
2683

2684 2685
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
2686
        return AVERROR_EOF;
2687
    }
2688

2689 2690 2691
    return 0;
}

2692
static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
2693
{
2694
    return index < count - 1;
2695 2696
}

2697
/* Compute the samples value for the stsc entry at the given index. */
2698
static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
2699 2700 2701
{
    int chunk_count;

2702
    if (mov_stsc_index_valid(index, sc->stsc_count))
2703
        chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
2704 2705 2706
    else {
        // Validation for stsc / stco  happens earlier in mov_read_stsc + mov_read_trak.
        av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
2707
        chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
2708
    }
2709

2710
    return sc->stsc_data[index].count * (int64_t)chunk_count;
2711 2712
}

2713
static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2714 2715 2716 2717 2718 2719 2720 2721 2722 2723
{
    AVStream *st;
    MOVStreamContext *sc;
    unsigned i, entries;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

2724
    avio_rb32(pb); // version + flags
2725

2726
    entries = avio_rb32(pb);
2727
    if (sc->stps_data)
2728
        av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
2729 2730 2731
    av_free(sc->stps_data);
    sc->stps_count = 0;
    sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
2732 2733 2734
    if (!sc->stps_data)
        return AVERROR(ENOMEM);

2735
    for (i = 0; i < entries && !pb->eof_reached; i++) {
2736
        sc->stps_data[i] = avio_rb32(pb);
2737 2738
    }

2739 2740
    sc->stps_count = i;

2741 2742
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
2743
        return AVERROR_EOF;
2744
    }
2745

2746 2747 2748
    return 0;
}

2749
static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2750
{
2751 2752
    AVStream *st;
    MOVStreamContext *sc;
2753
    unsigned int i, entries;
2754

2755 2756 2757 2758 2759
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

2760 2761
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
2762

2763
    entries = avio_rb32(pb);
2764

2765
    av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
2766

2767
    if (!entries)
2768 2769
    {
        sc->keyframe_absent = 1;
2770
        if (!st->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
2771
            st->need_parsing = AVSTREAM_PARSE_HEADERS;
2772
        return 0;
2773
    }
2774
    if (sc->keyframes)
2775
        av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
2776
    if (entries >= UINT_MAX / sizeof(int))
2777
        return AVERROR_INVALIDDATA;
2778
    av_freep(&sc->keyframes);
2779 2780
    sc->keyframe_count = 0;
    sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
2781
    if (!sc->keyframes)
2782 2783
        return AVERROR(ENOMEM);

2784
    for (i = 0; i < entries && !pb->eof_reached; i++) {
2785
        sc->keyframes[i] = avio_rb32(pb);
2786
    }
2787 2788 2789

    sc->keyframe_count = i;

2790 2791
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
2792
        return AVERROR_EOF;
2793
    }
2794

2795 2796 2797
    return 0;
}

2798
static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2799
{
2800 2801
    AVStream *st;
    MOVStreamContext *sc;
2802 2803 2804
    unsigned int i, entries, sample_size, field_size, num_bytes;
    GetBitContext gb;
    unsigned char* buf;
2805
    int ret;
2806

2807 2808 2809 2810 2811
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

2812 2813
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
2814

2815
    if (atom.type == MKTAG('s','t','s','z')) {
2816
        sample_size = avio_rb32(pb);
2817 2818
        if (!sc->sample_size) /* do not overwrite value computed in stsd */
            sc->sample_size = sample_size;
2819
        sc->stsz_sample_size = sample_size;
2820
        field_size = 32;
2821 2822
    } else {
        sample_size = 0;
2823 2824
        avio_rb24(pb); /* reserved */
        field_size = avio_r8(pb);
2825
    }
2826
    entries = avio_rb32(pb);
2827

2828
    av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
2829

2830
    sc->sample_count = entries;
2831 2832 2833
    if (sample_size)
        return 0;

2834
    if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
2835
        av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
2836
        return AVERROR_INVALIDDATA;
2837 2838
    }

Alex Converse's avatar
Alex Converse committed
2839 2840
    if (!entries)
        return 0;
2841
    if (entries >= (UINT_MAX - 4) / field_size)
2842
        return AVERROR_INVALIDDATA;
2843
    if (sc->sample_sizes)
2844
        av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
2845 2846 2847
    av_free(sc->sample_sizes);
    sc->sample_count = 0;
    sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
2848
    if (!sc->sample_sizes)
2849 2850
        return AVERROR(ENOMEM);

2851 2852
    num_bytes = (entries*field_size+4)>>3;

2853
    buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
2854 2855 2856 2857 2858
    if (!buf) {
        av_freep(&sc->sample_sizes);
        return AVERROR(ENOMEM);
    }

2859 2860
    ret = ffio_read_size(pb, buf, num_bytes);
    if (ret < 0) {
2861 2862
        av_freep(&sc->sample_sizes);
        av_free(buf);
2863 2864
        av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
        return 0;
2865 2866 2867 2868
    }

    init_get_bits(&gb, buf, 8*num_bytes);

2869
    for (i = 0; i < entries && !pb->eof_reached; i++) {
2870
        sc->sample_sizes[i] = get_bits_long(&gb, field_size);
2871 2872
        sc->data_size += sc->sample_sizes[i];
    }
2873

2874 2875
    sc->sample_count = i;

2876 2877
    av_free(buf);

2878 2879
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSZ atom\n");
2880
        return AVERROR_EOF;
2881
    }
2882

2883 2884 2885
    return 0;
}

2886
static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2887
{
2888 2889
    AVStream *st;
    MOVStreamContext *sc;
2890
    unsigned int i, entries, alloc_size = 0;
2891 2892
    int64_t duration=0;
    int64_t total_sample_count=0;
2893

2894 2895 2896 2897 2898
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

2899 2900 2901
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
    entries = avio_rb32(pb);
2902

2903
    av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
2904
            c->fc->nb_streams-1, entries);
2905

2906
    if (sc->stts_data)
2907
        av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
2908
    av_freep(&sc->stts_data);
2909
    sc->stts_count = 0;
2910
    if (entries >= INT_MAX / sizeof(*sc->stts_data))
2911
        return AVERROR(ENOMEM);
2912

2913
    for (i = 0; i < entries && !pb->eof_reached; i++) {
Michael Niedermayer's avatar
Michael Niedermayer committed
2914
        int sample_duration;
2915
        unsigned int sample_count;
2916
        unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
2917 2918 2919 2920 2921 2922 2923 2924 2925
        MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size,
                                             min_entries * sizeof(*sc->stts_data));
        if (!stts_data) {
            av_freep(&sc->stts_data);
            sc->stts_count = 0;
            return AVERROR(ENOMEM);
        }
        sc->stts_count = min_entries;
        sc->stts_data = stts_data;
2926

2927 2928
        sample_count=avio_rb32(pb);
        sample_duration = avio_rb32(pb);
2929

2930 2931 2932
        sc->stts_data[i].count= sample_count;
        sc->stts_data[i].duration= sample_duration;

2933
        av_log(c->fc, AV_LOG_TRACE, "sample_count=%d, sample_duration=%d\n",
2934
                sample_count, sample_duration);
2935

2936
        duration+=(int64_t)sample_duration*(uint64_t)sample_count;
2937 2938 2939
        total_sample_count+=sample_count;
    }

2940 2941
    sc->stts_count = i;

2942 2943
    if (duration > 0 &&
        duration <= INT64_MAX - sc->duration_for_fps &&
2944
        total_sample_count <= INT_MAX - sc->nb_frames_for_fps
2945 2946 2947 2948
    ) {
        sc->duration_for_fps  += duration;
        sc->nb_frames_for_fps += total_sample_count;
    }
2949

2950 2951
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
2952
        return AVERROR_EOF;
2953
    }
2954

2955
    st->nb_frames= total_sample_count;
2956
    if (duration)
2957
        st->duration= FFMIN(st->duration, duration);
2958
    sc->track_end = duration;
2959 2960 2961
    return 0;
}

2962 2963 2964
static void mov_update_dts_shift(MOVStreamContext *sc, int duration)
{
    if (duration < 0) {
2965 2966 2967 2968
        if (duration == INT_MIN) {
            av_log(NULL, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
            duration++;
        }
2969 2970 2971 2972
        sc->dts_shift = FFMAX(sc->dts_shift, -duration);
    }
}

2973
static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2974
{
2975 2976
    AVStream *st;
    MOVStreamContext *sc;
2977
    unsigned int i, entries, ctts_count = 0;
2978

2979 2980 2981 2982 2983
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

2984 2985 2986
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
    entries = avio_rb32(pb);
2987

2988
    av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
2989

Alex Converse's avatar
Alex Converse committed
2990 2991
    if (!entries)
        return 0;
2992
    if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
2993
        return AVERROR_INVALIDDATA;
2994
    av_freep(&sc->ctts_data);
2995
    sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
2996
    if (!sc->ctts_data)
2997
        return AVERROR(ENOMEM);
2998

2999
    for (i = 0; i < entries && !pb->eof_reached; i++) {
3000 3001
        int count    =avio_rb32(pb);
        int duration =avio_rb32(pb);
3002

3003 3004 3005 3006 3007 3008 3009
        if (count <= 0) {
            av_log(c->fc, AV_LOG_TRACE,
                   "ignoring CTTS entry with count=%d duration=%d\n",
                   count, duration);
            continue;
        }

3010 3011
        add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size,
                       count, duration);
3012

3013
        av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3014 3015
                count, duration);

3016
        if (FFNABS(duration) < -(1<<28) && i+2<entries) {
3017 3018 3019 3020 3021 3022
            av_log(c->fc, AV_LOG_WARNING, "CTTS invalid\n");
            av_freep(&sc->ctts_data);
            sc->ctts_count = 0;
            return 0;
        }

3023 3024
        if (i+2<entries)
            mov_update_dts_shift(sc, duration);
3025
    }
3026

3027
    sc->ctts_count = ctts_count;
3028

3029 3030
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3031
        return AVERROR_EOF;
3032
    }
3033

3034
    av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3035

3036 3037 3038
    return 0;
}

3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062
static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    MOVStreamContext *sc;
    unsigned int i, entries;
    uint8_t version;
    uint32_t grouping_type;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

    version = avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
    grouping_type = avio_rl32(pb);
    if (grouping_type != MKTAG( 'r','a','p',' '))
        return 0; /* only support 'rap ' grouping */
    if (version == 1)
        avio_rb32(pb); /* grouping_type_parameter */

    entries = avio_rb32(pb);
    if (!entries)
        return 0;
3063
    if (sc->rap_group)
3064
        av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP atom\n");
3065 3066 3067
    av_free(sc->rap_group);
    sc->rap_group_count = 0;
    sc->rap_group = av_malloc_array(entries, sizeof(*sc->rap_group));
3068 3069 3070 3071 3072 3073 3074 3075 3076 3077
    if (!sc->rap_group)
        return AVERROR(ENOMEM);

    for (i = 0; i < entries && !pb->eof_reached; i++) {
        sc->rap_group[i].count = avio_rb32(pb); /* sample_count */
        sc->rap_group[i].index = avio_rb32(pb); /* group_description_index */
    }

    sc->rap_group_count = i;

3078 3079 3080 3081 3082 3083
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
        return AVERROR_EOF;
    }

    return 0;
3084 3085
}

3086 3087 3088
/**
 * Get ith edit list entry (media time, duration).
 */
3089 3090
static int get_edit_list_entry(MOVContext *mov,
                               const MOVStreamContext *msc,
3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103
                               unsigned int edit_list_index,
                               int64_t *edit_list_media_time,
                               int64_t *edit_list_duration,
                               int64_t global_timescale)
{
    if (edit_list_index == msc->elst_count) {
        return 0;
    }
    *edit_list_media_time = msc->elst_data[edit_list_index].time;
    *edit_list_duration = msc->elst_data[edit_list_index].duration;

    /* duration is in global timescale units;convert to msc timescale */
    if (global_timescale == 0) {
3104
      avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3105 3106 3107 3108 3109 3110 3111 3112
      return 0;
    }
    *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
                                     global_timescale);
    return 1;
}

/**
3113
 * Find the closest previous frame to the timestamp_pts, in e_old index
3114 3115
 * entries. Searching for just any frame / just key frames can be controlled by
 * last argument 'flag'.
3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129
 * Note that if ctts_data is not NULL, we will always search for a key frame
 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
 * return the first frame of the video.
 *
 * Here the timestamp_pts is considered to be a presentation timestamp and
 * the timestamp of index entries are considered to be decoding timestamps.
 *
 * Returns 0 if successful in finding a frame, else returns -1.
 * Places the found index corresponding output arg.
 *
 * If ctts_old is not NULL, then refines the searched entry by searching
 * backwards from the found timestamp, to find the frame with correct PTS.
 *
 * Places the found ctts_index and ctts_sample in corresponding output args.
3130
 */
3131 3132 3133 3134 3135 3136 3137 3138 3139 3140
static int find_prev_closest_index(AVStream *st,
                                   AVIndexEntry *e_old,
                                   int nb_old,
                                   MOVStts* ctts_data,
                                   int64_t ctts_count,
                                   int64_t timestamp_pts,
                                   int flag,
                                   int64_t* index,
                                   int64_t* ctts_index,
                                   int64_t* ctts_sample)
3141
{
3142
    MOVStreamContext *msc = st->priv_data;
3143 3144
    AVIndexEntry *e_keep = st->index_entries;
    int nb_keep = st->nb_index_entries;
3145
    int64_t i = 0;
3146 3147 3148 3149 3150 3151 3152 3153 3154 3155
    int64_t index_ctts_count;

    av_assert0(index);

    // If dts_shift > 0, then all the index timestamps will have to be offset by
    // at least dts_shift amount to obtain PTS.
    // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
    if (msc->dts_shift > 0) {
        timestamp_pts -= msc->dts_shift;
    }
3156 3157 3158

    st->index_entries = e_old;
    st->nb_index_entries = nb_old;
3159
    *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3160

3161
    // Keep going backwards in the index entries until the timestamp is the same.
3162 3163
    if (*index >= 0) {
        for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3164 3165 3166
             i--) {
            if ((flag & AVSEEK_FLAG_ANY) ||
                (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189
                *index = i - 1;
            }
        }
    }

    // If we have CTTS then refine the search, by searching backwards over PTS
    // computed by adding corresponding CTTS durations to index timestamps.
    if (ctts_data && *index >= 0) {
        av_assert0(ctts_index);
        av_assert0(ctts_sample);
        // Find out the ctts_index for the found frame.
        *ctts_index = 0;
        *ctts_sample = 0;
        for (index_ctts_count = 0; index_ctts_count < *index; index_ctts_count++) {
            if (*ctts_index < ctts_count) {
                (*ctts_sample)++;
                if (ctts_data[*ctts_index].count == *ctts_sample) {
                    (*ctts_index)++;
                    *ctts_sample = 0;
                }
            }
        }

3190
        while (*index >= 0 && (*ctts_index) >= 0 && (*ctts_index) < ctts_count) {
3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205
            // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
            // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
            // compensated by dts_shift above.
            if ((e_old[*index].timestamp + ctts_data[*ctts_index].duration) <= timestamp_pts &&
                (e_old[*index].flags & AVINDEX_KEYFRAME)) {
                break;
            }

            (*index)--;
            if (*ctts_sample == 0) {
                (*ctts_index)--;
                if (*ctts_index >= 0)
                  *ctts_sample = ctts_data[*ctts_index].count - 1;
            } else {
                (*ctts_sample)--;
3206 3207 3208 3209
            }
        }
    }

3210 3211 3212
    /* restore AVStream state*/
    st->index_entries = e_keep;
    st->nb_index_entries = nb_keep;
3213
    return *index >= 0 ? 0 : -1;
3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262
}

/**
 * Add index entry with the given values, to the end of st->index_entries.
 * Returns the new size st->index_entries if successful, else returns -1.
 *
 * This function is similar to ff_add_index_entry in libavformat/utils.c
 * except that here we are always unconditionally adding an index entry to
 * the end, instead of searching the entries list and skipping the add if
 * there is an existing entry with the same timestamp.
 * This is needed because the mov_fix_index calls this func with the same
 * unincremented timestamp for successive discarded frames.
 */
static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
                               int size, int distance, int flags)
{
    AVIndexEntry *entries, *ie;
    int64_t index = -1;
    const size_t min_size_needed = (st->nb_index_entries + 1) * sizeof(AVIndexEntry);

    // Double the allocation each time, to lower memory fragmentation.
    // Another difference from ff_add_index_entry function.
    const size_t requested_size =
        min_size_needed > st->index_entries_allocated_size ?
        FFMAX(min_size_needed, 2 * st->index_entries_allocated_size) :
        min_size_needed;

    if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
        return -1;

    entries = av_fast_realloc(st->index_entries,
                              &st->index_entries_allocated_size,
                              requested_size);
    if(!entries)
        return -1;

    st->index_entries= entries;

    index= st->nb_index_entries++;
    ie= &entries[index];

    ie->pos = pos;
    ie->timestamp = timestamp;
    ie->min_distance= distance;
    ie->size= size;
    ie->flags = flags;
    return index;
}

3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277
/**
 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
 */
static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
                                       int64_t* frame_duration_buffer,
                                       int frame_duration_buffer_size) {
    int i = 0;
    av_assert0(end_index >= 0 && end_index <= st->nb_index_entries);
    for (i = 0; i < frame_duration_buffer_size; i++) {
        end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
        st->index_entries[end_index - 1 - i].timestamp = end_ts;
    }
}

3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291
/**
 * Append a new ctts entry to ctts_data.
 * Returns the new ctts_count if successful, else returns -1.
 */
static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
                              int count, int duration)
{
    MOVStts *ctts_buf_new;
    const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVStts);
    const size_t requested_size =
        min_size_needed > *allocated_size ?
        FFMAX(min_size_needed, 2 * (*allocated_size)) :
        min_size_needed;

3292
    if((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1)
3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308
        return -1;

    ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size);

    if(!ctts_buf_new)
        return -1;

    *ctts_data = ctts_buf_new;

    ctts_buf_new[*ctts_count].count = count;
    ctts_buf_new[*ctts_count].duration = duration;

    *ctts_count = (*ctts_count) + 1;
    return *ctts_count;
}

3309 3310 3311 3312 3313 3314 3315 3316 3317 3318
#define MAX_REORDER_DELAY 16
static void mov_estimate_video_delay(MOVContext *c, AVStream* st) {
    MOVStreamContext *msc = st->priv_data;
    int ind;
    int ctts_ind = 0;
    int ctts_sample = 0;
    int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
    int buf_start = 0;
    int j, r, num_swaps;

3319 3320 3321
    for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
        pts_buf[j] = INT64_MIN;

3322 3323 3324 3325
    if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
        st->codecpar->codec_id == AV_CODEC_ID_H264) {
        st->codecpar->video_delay = 0;
        for(ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
3326 3327
            // Point j to the last elem of the buffer and insert the current pts there.
            j = buf_start;
3328 3329 3330
            buf_start = (buf_start + 1);
            if (buf_start == MAX_REORDER_DELAY + 1)
                buf_start = 0;
3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341

            pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;

            // The timestamps that are already in the sorted buffer, and are greater than the
            // current pts, are exactly the timestamps that need to be buffered to output PTS
            // in correct sorted order.
            // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
            // can be computed as the maximum no. of swaps any particular timestamp needs to
            // go through, to keep this buffer in sorted order.
            num_swaps = 0;
            while (j != buf_start) {
3342
                r = j - 1;
3343
                if (r < 0) r = MAX_REORDER_DELAY;
3344 3345 3346
                if (pts_buf[j] < pts_buf[r]) {
                    FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
                    ++num_swaps;
3347 3348
                } else {
                    break;
3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364
                }
                j = r;
            }
            st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);

            ctts_sample++;
            if (ctts_sample == msc->ctts_data[ctts_ind].count) {
                ctts_ind++;
                ctts_sample = 0;
            }
        }
        av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
               st->codecpar->video_delay, st->index);
    }
}

3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410
static void mov_current_sample_inc(MOVStreamContext *sc)
{
    sc->current_sample++;
    sc->current_index++;
    if (sc->index_ranges &&
        sc->current_index >= sc->current_index_range->end &&
        sc->current_index_range->end) {
        sc->current_index_range++;
        sc->current_index = sc->current_index_range->start;
    }
}

static void mov_current_sample_dec(MOVStreamContext *sc)
{
    sc->current_sample--;
    sc->current_index--;
    if (sc->index_ranges &&
        sc->current_index < sc->current_index_range->start &&
        sc->current_index_range > sc->index_ranges) {
        sc->current_index_range--;
        sc->current_index = sc->current_index_range->end - 1;
    }
}

static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
{
    int64_t range_size;

    sc->current_sample = current_sample;
    sc->current_index = current_sample;
    if (!sc->index_ranges) {
        return;
    }

    for (sc->current_index_range = sc->index_ranges;
        sc->current_index_range->end;
        sc->current_index_range++) {
        range_size = sc->current_index_range->end - sc->current_index_range->start;
        if (range_size > current_sample) {
            sc->current_index = sc->current_index_range->start + current_sample;
            break;
        }
        current_sample -= range_size;
    }
}

3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434
/**
 * Fix st->index_entries, so that it contains only the entries (and the entries
 * which are needed to decode them) that fall in the edit list time ranges.
 * Also fixes the timestamps of the index entries to match the timeline
 * specified the edit lists.
 */
static void mov_fix_index(MOVContext *mov, AVStream *st)
{
    MOVStreamContext *msc = st->priv_data;
    AVIndexEntry *e_old = st->index_entries;
    int nb_old = st->nb_index_entries;
    const AVIndexEntry *e_old_end = e_old + nb_old;
    const AVIndexEntry *current = NULL;
    MOVStts *ctts_data_old = msc->ctts_data;
    int64_t ctts_index_old = 0;
    int64_t ctts_sample_old = 0;
    int64_t ctts_count_old = msc->ctts_count;
    int64_t edit_list_media_time = 0;
    int64_t edit_list_duration = 0;
    int64_t frame_duration = 0;
    int64_t edit_list_dts_counter = 0;
    int64_t edit_list_dts_entry_end = 0;
    int64_t edit_list_start_ctts_sample = 0;
    int64_t curr_cts;
3435 3436
    int64_t curr_ctts = 0;
    int64_t empty_edits_sum_duration = 0;
3437 3438 3439 3440 3441 3442
    int64_t edit_list_index = 0;
    int64_t index;
    int flags;
    int64_t start_dts = 0;
    int64_t edit_list_start_encountered = 0;
    int64_t search_timestamp = 0;
3443 3444 3445 3446
    int64_t* frame_duration_buffer = NULL;
    int num_discarded_begin = 0;
    int first_non_zero_audio_edit = -1;
    int packet_skip_samples = 0;
3447
    MOVIndexRange *current_index_range;
3448
    int i;
3449
    int found_keyframe_after_edit = 0;
3450
    int found_non_empty_edit = 0;
3451

3452
    if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
3453 3454
        return;
    }
3455 3456 3457 3458 3459 3460 3461 3462 3463 3464

    // allocate the index ranges array
    msc->index_ranges = av_malloc((msc->elst_count + 1) * sizeof(msc->index_ranges[0]));
    if (!msc->index_ranges) {
        av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
        return;
    }
    msc->current_index_range = msc->index_ranges;
    current_index_range = msc->index_ranges - 1;

3465 3466 3467 3468 3469 3470 3471 3472 3473 3474
    // Clean AVStream from traces of old index
    st->index_entries = NULL;
    st->index_entries_allocated_size = 0;
    st->nb_index_entries = 0;

    // Clean ctts fields of MOVStreamContext
    msc->ctts_data = NULL;
    msc->ctts_count = 0;
    msc->ctts_index = 0;
    msc->ctts_sample = 0;
3475
    msc->ctts_allocated_size = 0;
3476

3477 3478 3479
    // Reinitialize min_corrected_pts so that it can be computed again.
    msc->min_corrected_pts = -1;

3480 3481
    // If the dts_shift is positive (in case of negative ctts values in mov),
    // then negate the DTS by dts_shift
3482
    if (msc->dts_shift > 0) {
3483
        edit_list_dts_entry_end -= msc->dts_shift;
3484
        av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
3485 3486 3487 3488
    }

    start_dts = edit_list_dts_entry_end;

3489
    while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
3490 3491 3492 3493 3494 3495
                               &edit_list_duration, mov->time_scale)) {
        av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
               st->index, edit_list_index, edit_list_media_time, edit_list_duration);
        edit_list_index++;
        edit_list_dts_counter = edit_list_dts_entry_end;
        edit_list_dts_entry_end += edit_list_duration;
3496
        num_discarded_begin = 0;
3497
        if (!found_non_empty_edit && edit_list_media_time == -1) {
3498
            empty_edits_sum_duration += edit_list_duration;
3499 3500
            continue;
        }
3501
        found_non_empty_edit = 1;
3502 3503 3504 3505

        // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
        // according to the edit list below.
        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3506 3507 3508 3509 3510 3511 3512 3513
            if (first_non_zero_audio_edit < 0) {
                first_non_zero_audio_edit = 1;
            } else {
                first_non_zero_audio_edit = 0;
            }

            if (first_non_zero_audio_edit > 0)
                st->skip_samples = msc->start_pad = 0;
3514 3515 3516 3517 3518 3519
        }

        // While reordering frame index according to edit list we must handle properly
        // the scenario when edit list entry starts from none key frame.
        // We find closest previous key frame and preserve it and consequent frames in index.
        // All frames which are outside edit list entry time boundaries will be dropped after decoding.
3520
        search_timestamp = edit_list_media_time;
3521 3522 3523 3524
        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
            // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
            // edit_list_media_time to cover the decoder delay.
3525
            search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
3526 3527
        }

3528 3529
        if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, 0,
                                    &index, &ctts_index_old, &ctts_sample_old) < 0) {
3530 3531 3532
            av_log(mov->fc, AV_LOG_WARNING,
                   "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
                   st->index, edit_list_index, search_timestamp);
3533 3534
            if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
                                        &index, &ctts_index_old, &ctts_sample_old) < 0) {
3535
                av_log(mov->fc, AV_LOG_WARNING,
3536
                       "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
3537 3538
                       st->index, edit_list_index, search_timestamp);
                index = 0;
3539 3540
                ctts_index_old = 0;
                ctts_sample_old = 0;
3541
            }
3542 3543 3544 3545 3546 3547
        }
        current = e_old + index;
        edit_list_start_ctts_sample = ctts_sample_old;

        // Iterate over index and arrange it according to edit list
        edit_list_start_encountered = 0;
3548
        found_keyframe_after_edit = 0;
3549 3550 3551 3552 3553 3554 3555 3556 3557
        for (; current < e_old_end; current++, index++) {
            // check  if frame outside edit list mark it for discard
            frame_duration = (current + 1 <  e_old_end) ?
                             ((current + 1)->timestamp - current->timestamp) : edit_list_duration;

            flags = current->flags;

            // frames (pts) before or after edit list
            curr_cts = current->timestamp + msc->dts_shift;
3558
            curr_ctts = 0;
3559 3560

            if (ctts_data_old && ctts_index_old < ctts_count_old) {
3561 3562 3563 3564
                curr_ctts = ctts_data_old[ctts_index_old].duration;
                av_log(mov->fc, AV_LOG_DEBUG, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n",
                       curr_cts, curr_ctts, ctts_index_old, ctts_count_old);
                curr_cts += curr_ctts;
3565 3566 3567
                ctts_sample_old++;
                if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
                    if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
3568
                                       &msc->ctts_allocated_size,
3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583
                                       ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
                                       ctts_data_old[ctts_index_old].duration) == -1) {
                        av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
                               ctts_index_old,
                               ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
                               ctts_data_old[ctts_index_old].duration);
                        break;
                    }
                    ctts_index_old++;
                    ctts_sample_old = 0;
                    edit_list_start_ctts_sample = 0;
                }
            }

            if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
3584 3585 3586 3587 3588 3589 3590 3591
                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
                    curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
                    first_non_zero_audio_edit > 0) {
                    packet_skip_samples = edit_list_media_time - curr_cts;
                    st->skip_samples += packet_skip_samples;

                    // Shift the index entry timestamp by packet_skip_samples to be correct.
                    edit_list_dts_counter -= packet_skip_samples;
3592
                    if (edit_list_start_encountered == 0)  {
3593 3594 3595 3596 3597 3598 3599 3600
                        edit_list_start_encountered = 1;
                        // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
                        // discarded packets.
                        if (frame_duration_buffer) {
                            fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
                                                       frame_duration_buffer, num_discarded_begin);
                            av_freep(&frame_duration_buffer);
                        }
3601 3602
                    }

3603
                    av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
3604 3605 3606
                } else {
                    flags |= AVINDEX_DISCARD_FRAME;
                    av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
3607

3608
                    if (edit_list_start_encountered == 0) {
3609 3610 3611 3612 3613 3614 3615 3616 3617 3618
                        num_discarded_begin++;
                        frame_duration_buffer = av_realloc(frame_duration_buffer,
                                                           num_discarded_begin * sizeof(int64_t));
                        if (!frame_duration_buffer) {
                            av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
                            break;
                        }
                        frame_duration_buffer[num_discarded_begin - 1] = frame_duration;

                        // Increment skip_samples for the first non-zero audio edit list
3619 3620
                        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
                            first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
3621 3622 3623
                            st->skip_samples += frame_duration;
                        }
                    }
3624
                }
3625
            } else {
3626 3627
                if (msc->min_corrected_pts < 0) {
                    msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
3628
                } else {
3629
                    msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
3630 3631 3632
                }
                if (edit_list_start_encountered == 0) {
                    edit_list_start_encountered = 1;
3633
                    // Make timestamps strictly monotonically increasing by rewriting timestamps for
3634
                    // discarded packets.
3635
                    if (frame_duration_buffer) {
3636 3637 3638 3639
                        fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
                                                   frame_duration_buffer, num_discarded_begin);
                        av_freep(&frame_duration_buffer);
                    }
3640
                }
3641 3642 3643 3644 3645 3646 3647 3648
            }

            if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
                                current->min_distance, flags) == -1) {
                av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
                break;
            }

3649 3650 3651 3652 3653 3654 3655
            // Update the index ranges array
            if (current_index_range < msc->index_ranges || index != current_index_range->end) {
                current_index_range++;
                current_index_range->start = index;
            }
            current_index_range->end = index + 1;

3656 3657 3658 3659 3660 3661
            // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
            if (edit_list_start_encountered > 0) {
                edit_list_dts_counter = edit_list_dts_counter + frame_duration;
            }

            // Break when found first key frame after edit entry completion
3662
            if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
3663
                ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
3664
                if (ctts_data_old) {
3665
                    // If we have CTTS and this is the first keyframe after edit elist,
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681
                    // wait for one more, because there might be trailing B-frames after this I-frame
                    // that do belong to the edit.
                    if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
                        found_keyframe_after_edit = 1;
                        continue;
                    }
                    if (ctts_sample_old != 0) {
                        if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
                                           &msc->ctts_allocated_size,
                                           ctts_sample_old - edit_list_start_ctts_sample,
                                           ctts_data_old[ctts_index_old].duration) == -1) {
                            av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
                                   ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample,
                                   ctts_data_old[ctts_index_old].duration);
                            break;
                        }
3682 3683 3684 3685 3686 3687
                    }
                }
                break;
            }
        }
    }
3688 3689 3690
    // If there are empty edits, then msc->min_corrected_pts might be positive
    // intentionally. So we subtract the sum duration of emtpy edits here.
    msc->min_corrected_pts -= empty_edits_sum_duration;
3691 3692 3693

    // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
    // dts by that amount to make the first pts zero.
3694 3695 3696 3697 3698 3699
    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        if (msc->min_corrected_pts > 0) {
            av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
            for (i = 0; i < st->nb_index_entries; ++i) {
                st->index_entries[i].timestamp -= msc->min_corrected_pts;
            }
3700 3701
        }
    }
3702 3703
    // Start time should be equal to zero or the duration of any empty edits.
    st->start_time = empty_edits_sum_duration;
3704

3705 3706
    // Update av stream length, if it ends up shorter than the track's media duration
    st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
3707
    msc->start_pad = st->skip_samples;
3708 3709 3710 3711

    // Free the old index and the old CTTS structures
    av_free(e_old);
    av_free(ctts_data_old);
3712
    av_freep(&frame_duration_buffer);
3713 3714 3715 3716 3717 3718

    // Null terminate the index ranges array
    current_index_range++;
    current_index_range->start = 0;
    current_index_range->end = 0;
    msc->current_index = msc->index_ranges[0].start;
3719 3720
}

3721 3722 3723
static void mov_build_index(MOVContext *mov, AVStream *st)
{
    MOVStreamContext *sc = st->priv_data;
3724
    int64_t current_offset;
3725 3726 3727 3728
    int64_t current_dts = 0;
    unsigned int stts_index = 0;
    unsigned int stsc_index = 0;
    unsigned int stss_index = 0;
3729
    unsigned int stps_index = 0;
3730
    unsigned int i, j;
3731
    uint64_t stream_size = 0;
3732 3733
    MOVStts *ctts_data_old = sc->ctts_data;
    unsigned int ctts_count_old = sc->ctts_count;
3734

3735
    if (sc->elst_count) {
3736
        int i, edit_start_index = 0, multiple_edits = 0;
3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748
        int64_t empty_duration = 0; // empty duration of the first edit list entry
        int64_t start_time = 0; // start time of the media

        for (i = 0; i < sc->elst_count; i++) {
            const MOVElst *e = &sc->elst_data[i];
            if (i == 0 && e->time == -1) {
                /* if empty, the first entry is the start time of the stream
                 * relative to the presentation itself */
                empty_duration = e->duration;
                edit_start_index = 1;
            } else if (i == edit_start_index && e->time >= 0) {
                start_time = e->time;
3749 3750
            } else {
                multiple_edits = 1;
3751
            }
3752 3753
        }

3754 3755 3756 3757 3758
        if (multiple_edits && !mov->advanced_editlist)
            av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
                   "Use -advanced_editlist to correctly decode otherwise "
                   "a/v desync might occur\n");

3759 3760 3761 3762 3763
        /* adjust first dts according to edit list */
        if ((empty_duration || start_time) && mov->time_scale > 0) {
            if (empty_duration)
                empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
            sc->time_offset = start_time - empty_duration;
3764
            sc->min_corrected_pts = start_time;
3765 3766
            if (!mov->advanced_editlist)
                current_dts = -sc->time_offset;
3767
        }
3768 3769 3770 3771

        if (!multiple_edits && !mov->advanced_editlist &&
            st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
            sc->start_pad = start_time;
3772 3773
    }

3774
    /* only use old uncompressed audio chunk demuxing when stts specifies it */
3775
    if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3776
          sc->stts_count == 1 && sc->stts_data[0].duration == 1)) {
3777 3778
        unsigned int current_sample = 0;
        unsigned int stts_sample = 0;
3779
        unsigned int sample_size;
3780
        unsigned int distance = 0;
3781 3782
        unsigned int rap_group_index = 0;
        unsigned int rap_group_sample = 0;
3783 3784
        int64_t last_dts = 0;
        int64_t dts_correction = 0;
3785
        int rap_group_present = sc->rap_group_count && sc->rap_group;
3786
        int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
3787

3788
        current_dts -= sc->dts_shift;
3789
        last_dts     = current_dts;
3790

3791
        if (!sc->sample_count || st->nb_index_entries)
Alex Converse's avatar
Alex Converse committed
3792
            return;
3793
        if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
3794
            return;
3795 3796 3797 3798
        if (av_reallocp_array(&st->index_entries,
                              st->nb_index_entries + sc->sample_count,
                              sizeof(*st->index_entries)) < 0) {
            st->nb_index_entries = 0;
3799
            return;
3800
        }
3801
        st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries);
3802

3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814
        if (ctts_data_old) {
            // Expand ctts entries such that we have a 1-1 mapping with samples
            if (sc->sample_count >= UINT_MAX / sizeof(*sc->ctts_data))
                return;
            sc->ctts_count = 0;
            sc->ctts_allocated_size = 0;
            sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size,
                                    sc->sample_count * sizeof(*sc->ctts_data));
            if (!sc->ctts_data) {
                av_free(ctts_data_old);
                return;
            }
3815 3816 3817

            memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size);

3818 3819 3820 3821 3822 3823 3824 3825 3826 3827
            for (i = 0; i < ctts_count_old &&
                        sc->ctts_count < sc->sample_count; i++)
                for (j = 0; j < ctts_data_old[i].count &&
                            sc->ctts_count < sc->sample_count; j++)
                    add_ctts_entry(&sc->ctts_data, &sc->ctts_count,
                                   &sc->ctts_allocated_size, 1,
                                   ctts_data_old[i].duration);
            av_free(ctts_data_old);
        }

3828
        for (i = 0; i < sc->chunk_count; i++) {
3829
            int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
3830
            current_offset = sc->chunk_offsets[i];
3831
            while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
3832
                i + 1 == sc->stsc_data[stsc_index + 1].first)
3833
                stsc_index++;
3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844

            if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
                sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
                av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
                sc->stsz_sample_size = sc->sample_size;
            }
            if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
                av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
                sc->stsz_sample_size = sc->sample_size;
            }

3845
            for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
3846
                int keyframe = 0;
3847 3848
                if (current_sample >= sc->sample_count) {
                    av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
3849
                    return;
3850
                }
3851

3852
                if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
3853
                    keyframe = 1;
3854 3855
                    if (stss_index + 1 < sc->keyframe_count)
                        stss_index++;
3856 3857 3858 3859
                } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
                    keyframe = 1;
                    if (stps_index + 1 < sc->stps_count)
                        stps_index++;
3860
                }
3861 3862 3863 3864 3865 3866 3867 3868
                if (rap_group_present && rap_group_index < sc->rap_group_count) {
                    if (sc->rap_group[rap_group_index].index > 0)
                        keyframe = 1;
                    if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
                        rap_group_sample = 0;
                        rap_group_index++;
                    }
                }
3869 3870 3871
                if (sc->keyframe_absent
                    && !sc->stps_count
                    && !rap_group_present
3872
                    && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
3873
                     keyframe = 1;
3874 3875
                if (keyframe)
                    distance = 0;
3876
                sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
3877
                if (sc->pseudo_stream_id == -1 ||
3878
                   sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
3879 3880 3881 3882 3883 3884
                    AVIndexEntry *e;
                    if (sample_size > 0x3FFFFFFF) {
                        av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
                        return;
                    }
                    e = &st->index_entries[st->nb_index_entries++];
3885
                    e->pos = current_offset;
3886
                    e->timestamp = current_dts;
3887 3888 3889
                    e->size = sample_size;
                    e->min_distance = distance;
                    e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
3890
                    av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
3891
                            "size %u, distance %u, keyframe %d\n", st->index, current_sample,
3892
                            current_offset, current_dts, sample_size, distance, keyframe);
3893
                    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
3894
                        ff_rfps_add_frame(mov->fc, st, current_dts);
3895
                }
3896

3897
                current_offset += sample_size;
3898
                stream_size += sample_size;
3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909

                /* A negative sample duration is invalid based on the spec,
                 * but some samples need it to correct the DTS. */
                if (sc->stts_data[stts_index].duration < 0) {
                    av_log(mov->fc, AV_LOG_WARNING,
                           "Invalid SampleDelta %d in STTS, at %d st:%d\n",
                           sc->stts_data[stts_index].duration, stts_index,
                           st->index);
                    dts_correction += sc->stts_data[stts_index].duration - 1;
                    sc->stts_data[stts_index].duration = 1;
                }
3910
                current_dts += sc->stts_data[stts_index].duration;
3911 3912 3913 3914 3915 3916 3917 3918 3919
                if (!dts_correction || current_dts + dts_correction > last_dts) {
                    current_dts += dts_correction;
                    dts_correction = 0;
                } else {
                    /* Avoid creating non-monotonous DTS */
                    dts_correction += current_dts - last_dts - 1;
                    current_dts = last_dts + 1;
                }
                last_dts = current_dts;
3920 3921 3922 3923 3924 3925 3926 3927 3928
                distance++;
                stts_sample++;
                current_sample++;
                if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
                    stts_sample = 0;
                    stts_index++;
                }
            }
        }
3929
        if (st->duration > 0)
3930
            st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
3931
    } else {
3932
        unsigned chunk_samples, total = 0;
3933

3934 3935 3936
        if (!sc->chunk_count)
            return;

3937 3938 3939
        // compute total chunk count
        for (i = 0; i < sc->stsc_count; i++) {
            unsigned count, chunk_count;
3940

3941
            chunk_samples = sc->stsc_data[i].count;
3942 3943
            if (i != sc->stsc_count - 1 &&
                sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
3944 3945 3946 3947
                av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
                return;
            }

3948 3949 3950 3951 3952 3953 3954 3955 3956
            if (sc->samples_per_frame >= 160) { // gsm
                count = chunk_samples / sc->samples_per_frame;
            } else if (sc->samples_per_frame > 1) {
                unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
                count = (chunk_samples+samples-1) / samples;
            } else {
                count = (chunk_samples+1023) / 1024;
            }

3957
            if (mov_stsc_index_valid(i, sc->stsc_count))
3958 3959 3960 3961 3962 3963
                chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
            else
                chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
            total += chunk_count * count;
        }

3964
        av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
3965
        if (total >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
3966
            return;
3967 3968 3969 3970
        if (av_reallocp_array(&st->index_entries,
                              st->nb_index_entries + total,
                              sizeof(*st->index_entries)) < 0) {
            st->nb_index_entries = 0;
3971
            return;
3972
        }
3973
        st->index_entries_allocated_size = (st->nb_index_entries + total) * sizeof(*st->index_entries);
3974 3975 3976 3977

        // populate index
        for (i = 0; i < sc->chunk_count; i++) {
            current_offset = sc->chunk_offsets[i];
3978
            if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
3979 3980 3981 3982
                i + 1 == sc->stsc_data[stsc_index + 1].first)
                stsc_index++;
            chunk_samples = sc->stsc_data[stsc_index].count;

3983
            while (chunk_samples > 0) {
3984
                AVIndexEntry *e;
3985 3986
                unsigned size, samples;

3987 3988 3989 3990 3991 3992 3993
                if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
                    avpriv_request_sample(mov->fc,
                           "Zero bytes per frame, but %d samples per frame",
                           sc->samples_per_frame);
                    return;
                }

3994 3995 3996 3997 3998 3999 4000 4001
                if (sc->samples_per_frame >= 160) { // gsm
                    samples = sc->samples_per_frame;
                    size = sc->bytes_per_frame;
                } else {
                    if (sc->samples_per_frame > 1) {
                        samples = FFMIN((1024 / sc->samples_per_frame)*
                                        sc->samples_per_frame, chunk_samples);
                        size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4002
                    } else {
4003 4004
                        samples = FFMIN(1024, chunk_samples);
                        size = samples * sc->sample_size;
4005 4006
                    }
                }
4007

4008
                if (st->nb_index_entries >= total) {
4009
                    av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4010 4011
                    return;
                }
4012 4013 4014 4015
                if (size > 0x3FFFFFFF) {
                    av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
                    return;
                }
4016 4017 4018 4019 4020 4021
                e = &st->index_entries[st->nb_index_entries++];
                e->pos = current_offset;
                e->timestamp = current_dts;
                e->size = size;
                e->min_distance = 0;
                e->flags = AVINDEX_KEYFRAME;
4022 4023 4024
                av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
                       "size %u, duration %u\n", st->index, i, current_offset, current_dts,
                       size, samples);
4025 4026

                current_offset += size;
4027
                current_dts += samples;
4028
                chunk_samples -= samples;
4029 4030 4031
            }
        }
    }
4032

4033 4034 4035 4036
    if (!mov->ignore_editlist && mov->advanced_editlist) {
        // Fix index according to edit lists.
        mov_fix_index(mov, st);
    }
4037

4038 4039 4040 4041 4042 4043 4044 4045
    // Update start time of the stream.
    if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries > 0) {
        st->start_time = st->index_entries[0].timestamp + sc->dts_shift;
        if (sc->ctts_data) {
            st->start_time += sc->ctts_data[0].duration;
        }
    }

4046
    mov_estimate_video_delay(mov, st);
4047
}
4048

4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077
static int test_same_origin(const char *src, const char *ref) {
    char src_proto[64];
    char ref_proto[64];
    char src_auth[256];
    char ref_auth[256];
    char src_host[256];
    char ref_host[256];
    int src_port=-1;
    int ref_port=-1;

    av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
    av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);

    if (strlen(src) == 0) {
        return -1;
    } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
        strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
        strlen(src_host) + 1 >= sizeof(src_host) ||
        strlen(ref_host) + 1 >= sizeof(ref_host)) {
        return 0;
    } else if (strcmp(src_proto, ref_proto) ||
               strcmp(src_auth, ref_auth) ||
               strcmp(src_host, ref_host) ||
               src_port != ref_port) {
        return 0;
    } else
        return 1;
}

4078
static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4079
{
4080 4081
    /* try relative path, we do not try the absolute because it can leak information about our
       system to an attacker */
4082
    if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4083
        char filename[1025];
4084
        const char *src_path;
4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103
        int i, l;

        /* find a source dir */
        src_path = strrchr(src, '/');
        if (src_path)
            src_path++;
        else
            src_path = src;

        /* find a next level down to target */
        for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
            if (ref->path[l] == '/') {
                if (i == ref->nlvl_to - 1)
                    break;
                else
                    i++;
            }

        /* compose filename if next level down to target was found */
4104
        if (i == ref->nlvl_to - 1 && src_path - src  < sizeof(filename)) {
4105 4106 4107 4108
            memcpy(filename, src, src_path - src);
            filename[src_path - src] = 0;

            for (i = 1; i < ref->nlvl_from; i++)
4109
                av_strlcat(filename, "../", sizeof(filename));
4110

4111
            av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4112
            if (!c->use_absolute_path) {
4113 4114 4115 4116 4117 4118 4119 4120 4121 4122
                int same_origin = test_same_origin(src, filename);

                if (!same_origin) {
                    av_log(c->fc, AV_LOG_ERROR,
                        "Reference with mismatching origin, %s not tried for security reasons, "
                        "set demuxer option use_absolute_path to allow it anyway\n",
                        ref->path);
                    return AVERROR(ENOENT);
                }

4123 4124
                if(strstr(ref->path + l + 1, "..") ||
                   strstr(ref->path + l + 1, ":") ||
4125
                   (ref->nlvl_from > 1 && same_origin < 0) ||
4126
                   (filename[0] == '/' && src_path == src))
4127
                    return AVERROR(ENOENT);
4128
            }
4129

4130 4131
            if (strlen(filename) + 1 == sizeof(filename))
                return AVERROR(ENOENT);
4132
            if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
4133 4134
                return 0;
        }
4135 4136
    } else if (c->use_absolute_path) {
        av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
4137
               "this is a possible security issue\n");
4138
        if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
4139
            return 0;
4140 4141 4142 4143 4144
    } else {
        av_log(c->fc, AV_LOG_ERROR,
               "Absolute path %s not tried for security reasons, "
               "set demuxer option use_absolute_path to allow absolute paths\n",
               ref->path);
4145 4146 4147
    }

    return AVERROR(ENOENT);
4148
}
4149

4150 4151 4152 4153 4154 4155 4156 4157 4158 4159
static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
{
    if (sc->time_scale <= 0) {
        av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
        sc->time_scale = c->time_scale;
        if (sc->time_scale <= 0)
            sc->time_scale = 1;
    }
}

4160
static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4161 4162 4163
{
    AVStream *st;
    MOVStreamContext *sc;
4164
    int ret;
4165

4166
    st = avformat_new_stream(c->fc, NULL);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
4167
    if (!st) return AVERROR(ENOMEM);
4168
    st->id = -1;
4169
    sc = av_mallocz(sizeof(MOVStreamContext));
4170
    if (!sc) return AVERROR(ENOMEM);
4171 4172

    st->priv_data = sc;
4173
    st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
4174
    sc->ffindex = st->index;
4175
    c->trak_index = st->index;
4176

4177 4178 4179
    if ((ret = mov_read_default(c, pb, atom)) < 0)
        return ret;

4180 4181
    c->trak_index = -1;

4182 4183 4184 4185 4186 4187 4188
    // Here stsc refers to a chunk not described in stco. This is technically invalid,
    // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
    if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
        sc->stsc_count = 0;
        av_freep(&sc->stsc_data);
    }

4189
    /* sanity checks */
4190 4191 4192
    if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
                            (!sc->sample_size && !sc->sample_count))) ||
        (!sc->chunk_count && sc->sample_count)) {
4193 4194
        av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
               st->index);
4195 4196
        return 0;
    }
4197
    if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
4198 4199 4200 4201
        av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
               st->index);
        return AVERROR_INVALIDDATA;
    }
4202

4203
    fix_timescale(c, sc);
4204

4205
    avpriv_set_pts_info(st, 64, 1, sc->time_scale);
4206 4207 4208 4209

    mov_build_index(c, st);

    if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
4210
        MOVDref *dref = &sc->drefs[sc->dref_id - 1];
4211
        if (c->enable_drefs) {
4212
            if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223
                av_log(c->fc, AV_LOG_ERROR,
                       "stream %d, error opening alias: path='%s', dir='%s', "
                       "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
                       st->index, dref->path, dref->dir, dref->filename,
                       dref->volume, dref->nlvl_from, dref->nlvl_to);
        } else {
            av_log(c->fc, AV_LOG_WARNING,
                   "Skipped opening external track: "
                   "stream %d, alias: path='%s', dir='%s', "
                   "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
                   "Set enable_drefs to allow this.\n",
4224 4225
                   st->index, dref->path, dref->dir, dref->filename,
                   dref->volume, dref->nlvl_from, dref->nlvl_to);
4226
        }
4227
    } else {
4228
        sc->pb = c->fc->pb;
4229 4230
        sc->pb_is_copied = 1;
    }
4231

4232
    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4233
        if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
4234
            sc->height && sc->width &&
4235 4236 4237
            (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
            st->sample_aspect_ratio = av_d2q(((double)st->codecpar->height * sc->width) /
                                             ((double)st->codecpar->width * sc->height), INT_MAX);
4238 4239
        }

4240
#if FF_API_R_FRAME_RATE
4241 4242 4243
        if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
            av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
                      sc->time_scale, sc->stts_data[0].duration, INT_MAX);
4244
#endif
4245 4246
    }

4247
    // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
4248 4249
    if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
        TAG_IS_AVCI(st->codecpar->codec_tag)) {
4250 4251 4252
        ret = ff_generate_avci_extradata(st);
        if (ret < 0)
            return ret;
4253 4254
    }

4255
    switch (st->codecpar->codec_id) {
4256
#if CONFIG_H261_DECODER
4257
    case AV_CODEC_ID_H261:
4258
#endif
4259
#if CONFIG_H263_DECODER
4260
    case AV_CODEC_ID_H263:
4261
#endif
4262
#if CONFIG_MPEG4_DECODER
4263
    case AV_CODEC_ID_MPEG4:
4264
#endif
4265 4266
        st->codecpar->width = 0; /* let decoder init width/height */
        st->codecpar->height= 0;
4267 4268
        break;
    }
4269

4270
    // If the duration of the mp3 packets is not constant, then they could need a parser
4271
    if (st->codecpar->codec_id == AV_CODEC_ID_MP3
4272 4273
        && sc->stts_count > 3
        && sc->stts_count*10 > st->nb_frames
4274
        && sc->time_scale == st->codecpar->sample_rate) {
4275 4276
            st->need_parsing = AVSTREAM_PARSE_FULL;
    }
4277 4278 4279 4280 4281
    /* Do not need those anymore. */
    av_freep(&sc->chunk_offsets);
    av_freep(&sc->sample_sizes);
    av_freep(&sc->keyframes);
    av_freep(&sc->stts_data);
4282
    av_freep(&sc->stps_data);
4283
    av_freep(&sc->elst_data);
4284
    av_freep(&sc->rap_group);
4285

4286
    return 0;
4287 4288
}

4289
static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4290 4291 4292 4293 4294 4295 4296 4297
{
    int ret;
    c->itunes_metadata = 1;
    ret = mov_read_default(c, pb, atom);
    c->itunes_metadata = 0;
    return ret;
}

4298 4299 4300 4301 4302 4303 4304 4305 4306 4307
static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    uint32_t count;
    uint32_t i;

    if (atom.size < 8)
        return 0;

    avio_skip(pb, 4);
    count = avio_rb32(pb);
4308
    if (count > UINT_MAX / sizeof(*c->meta_keys) - 1) {
4309
        av_log(c->fc, AV_LOG_ERROR,
4310
               "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323
        return AVERROR_INVALIDDATA;
    }

    c->meta_keys_count = count + 1;
    c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
    if (!c->meta_keys)
        return AVERROR(ENOMEM);

    for (i = 1; i <= count; ++i) {
        uint32_t key_size = avio_rb32(pb);
        uint32_t type = avio_rl32(pb);
        if (key_size < 8) {
            av_log(c->fc, AV_LOG_ERROR,
4324 4325
                   "The key# %"PRIu32" in meta has invalid size:"
                   "%"PRIu32"\n", i, key_size);
4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340
            return AVERROR_INVALIDDATA;
        }
        key_size -= 8;
        if (type != MKTAG('m','d','t','a')) {
            avio_skip(pb, key_size);
        }
        c->meta_keys[i] = av_mallocz(key_size + 1);
        if (!c->meta_keys[i])
            return AVERROR(ENOMEM);
        avio_read(pb, c->meta_keys[i], key_size);
    }

    return 0;
}

4341
static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4342
{
4343 4344
    int64_t end = avio_tell(pb) + atom.size;
    uint8_t *key = NULL, *val = NULL, *mean = NULL;
4345
    int i;
4346
    int ret = 0;
4347 4348 4349 4350 4351 4352 4353
    AVStream *st;
    MOVStreamContext *sc;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;
4354

4355
    for (i = 0; i < 3; i++) {
4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369
        uint8_t **p;
        uint32_t len, tag;

        if (end - avio_tell(pb) <= 12)
            break;

        len = avio_rb32(pb);
        tag = avio_rl32(pb);
        avio_skip(pb, 4); // flags

        if (len < 12 || len - 12 > end - avio_tell(pb))
            break;
        len -= 12;

4370 4371 4372
        if (tag == MKTAG('m', 'e', 'a', 'n'))
            p = &mean;
        else if (tag == MKTAG('n', 'a', 'm', 'e'))
4373 4374 4375 4376 4377 4378 4379 4380 4381
            p = &key;
        else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
            avio_skip(pb, 4);
            len -= 4;
            p = &val;
        } else
            break;

        *p = av_malloc(len + 1);
4382 4383
        if (!*p) {
            ret = AVERROR(ENOMEM);
4384
            break;
4385
        }
4386 4387
        ret = ffio_read_size(pb, *p, len);
        if (ret < 0) {
4388
            av_freep(p);
4389
            break;
4390
        }
4391 4392 4393
        (*p)[len] = 0;
    }

4394
    if (mean && key && val) {
4395 4396 4397 4398 4399 4400
        if (strcmp(key, "iTunSMPB") == 0) {
            int priming, remainder, samples;
            if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
                if(priming>0 && priming<16384)
                    sc->start_pad = priming;
            }
4401 4402
        }
        if (strcmp(key, "cdec") != 0) {
4403 4404 4405 4406
            av_dict_set(&c->fc->metadata, key, val,
                        AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
            key = val = NULL;
        }
4407 4408 4409
    } else {
        av_log(c->fc, AV_LOG_VERBOSE,
               "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
4410 4411 4412 4413 4414
    }

    avio_seek(pb, end, SEEK_SET);
    av_freep(&key);
    av_freep(&val);
4415
    av_freep(&mean);
4416
    return ret;
4417 4418
}

4419
static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4420
{
4421
    while (atom.size > 8) {
4422 4423 4424 4425
        uint32_t tag;
        if (avio_feof(pb))
            return AVERROR_EOF;
        tag = avio_rl32(pb);
4426 4427
        atom.size -= 4;
        if (tag == MKTAG('h','d','l','r')) {
4428
            avio_seek(pb, -8, SEEK_CUR);
4429 4430 4431 4432 4433
            atom.size += 8;
            return mov_read_default(c, pb, atom);
        }
    }
    return 0;
4434 4435
}

4436 4437 4438 4439 4440 4441 4442 4443 4444
// return 1 when matrix is identity, 0 otherwise
#define IS_MATRIX_IDENT(matrix)            \
    ( (matrix)[0][0] == (1 << 16) &&       \
      (matrix)[1][1] == (1 << 16) &&       \
      (matrix)[2][2] == (1 << 30) &&       \
     !(matrix)[0][1] && !(matrix)[0][2] && \
     !(matrix)[1][0] && !(matrix)[1][2] && \
     !(matrix)[2][0] && !(matrix)[2][1])

4445
static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4446
{
4447
    int i, j, e;
4448 4449
    int width;
    int height;
4450
    int display_matrix[3][3];
4451
    int res_display_matrix[3][3] = { { 0 } };
4452 4453 4454
    AVStream *st;
    MOVStreamContext *sc;
    int version;
4455
    int flags;
4456 4457 4458 4459 4460

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;
4461

4462 4463 4464 4465 4466
    // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
    // avoids corrupting AVStreams mapped to an earlier tkhd.
    if (st->id != -1)
        return AVERROR_INVALIDDATA;

4467
    version = avio_r8(pb);
4468 4469
    flags = avio_rb24(pb);
    st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
4470

4471
    if (version == 1) {
4472 4473
        avio_rb64(pb);
        avio_rb64(pb);
4474
    } else {
4475 4476
        avio_rb32(pb); /* creation time */
        avio_rb32(pb); /* modification time */
4477
    }
4478 4479
    st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
    avio_rb32(pb); /* reserved */
4480

4481
    /* highlevel (considering edits) duration in movie timebase */
4482 4483 4484
    (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
    avio_rb32(pb); /* reserved */
    avio_rb32(pb); /* reserved */
4485

4486 4487 4488 4489
    avio_rb16(pb); /* layer */
    avio_rb16(pb); /* alternate group */
    avio_rb16(pb); /* volume */
    avio_rb16(pb); /* reserved */
4490

4491 4492
    //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
    // they're kept in fixed point format through all calculations
4493 4494
    // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
    // side data, but the scale factor is not needed to calculate aspect ratio
4495
    for (i = 0; i < 3; i++) {
4496 4497
        display_matrix[i][0] = avio_rb32(pb);   // 16.16 fixed point
        display_matrix[i][1] = avio_rb32(pb);   // 16.16 fixed point
4498
        display_matrix[i][2] = avio_rb32(pb);   //  2.30 fixed point
4499
    }
4500

4501 4502
    width = avio_rb32(pb);       // 16.16 fixed point track width
    height = avio_rb32(pb);      // 16.16 fixed point track height
4503 4504
    sc->width = width >> 16;
    sc->height = height >> 16;
4505

4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519
    // apply the moov display matrix (after the tkhd one)
    for (i = 0; i < 3; i++) {
        const int sh[3] = { 16, 16, 30 };
        for (j = 0; j < 3; j++) {
            for (e = 0; e < 3; e++) {
                res_display_matrix[i][j] +=
                    ((int64_t) display_matrix[i][e] *
                     c->movie_display_matrix[e][j]) >> sh[e];
            }
        }
    }

    // save the matrix when it is not the default identity
    if (!IS_MATRIX_IDENT(res_display_matrix)) {
4520
        double rotate;
4521 4522 4523 4524 4525 4526 4527 4528

        av_freep(&sc->display_matrix);
        sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
        if (!sc->display_matrix)
            return AVERROR(ENOMEM);

        for (i = 0; i < 3; i++)
            for (j = 0; j < 3; j++)
4529
                sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
4530

4531
#if FF_API_OLD_ROTATE_API
4532 4533 4534 4535 4536 4537 4538 4539 4540
        rotate = av_display_rotation_get(sc->display_matrix);
        if (!isnan(rotate)) {
            char rotate_buf[64];
            rotate = -rotate;
            if (rotate < 0) // for backward compatibility
                rotate += 360;
            snprintf(rotate_buf, sizeof(rotate_buf), "%g", rotate);
            av_dict_set(&st->metadata, "rotate", rotate_buf, 0);
        }
4541
#endif
4542 4543
    }

4544
    // transform the display width/height according to the matrix
4545
    // to keep the same scale, use [width height 1<<16]
4546 4547 4548
    if (width && height && sc->display_matrix) {
        double disp_transform[2];

4549
        for (i = 0; i < 2; i++)
4550 4551
            disp_transform[i] = hypot(sc->display_matrix[0 + i],
                                      sc->display_matrix[3 + i]);
4552

4553 4554
        if (disp_transform[0] > 0       && disp_transform[1] > 0 &&
            disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
4555
            fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
4556 4557 4558
            st->sample_aspect_ratio = av_d2q(
                disp_transform[0] / disp_transform[1],
                INT_MAX);
4559
    }
4560 4561 4562
    return 0;
}

4563
static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4564 4565 4566
{
    MOVFragment *frag = &c->fragment;
    MOVTrackExt *trex = NULL;
4567
    int flags, track_id, i;
4568

4569 4570
    avio_r8(pb); /* version */
    flags = avio_rb24(pb);
4571

4572
    track_id = avio_rb32(pb);
4573
    if (!track_id)
4574
        return AVERROR_INVALIDDATA;
4575
    for (i = 0; i < c->trex_count; i++)
4576
        if (c->trex_data[i].track_id == track_id) {
4577 4578 4579 4580
            trex = &c->trex_data[i];
            break;
        }
    if (!trex) {
4581 4582
        av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
        return 0;
4583
    }
4584
    c->fragment.found_tfhd = 1;
4585 4586
    frag->track_id = track_id;
    set_frag_stream(&c->frag_index, track_id);
4587

4588
    frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
4589 4590
                             avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
                             frag->moof_offset : frag->implicit_offset;
4591 4592 4593 4594 4595 4596 4597 4598
    frag->stsd_id  = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;

    frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
                     avio_rb32(pb) : trex->duration;
    frag->size     = flags & MOV_TFHD_DEFAULT_SIZE ?
                     avio_rb32(pb) : trex->size;
    frag->flags    = flags & MOV_TFHD_DEFAULT_FLAGS ?
                     avio_rb32(pb) : trex->flags;
4599
    av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
4600

4601 4602 4603
    return 0;
}

4604
static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4605
{
4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619
    unsigned i, num;
    void *new_tracks;

    num = atom.size / 4;
    if (!(new_tracks = av_malloc_array(num, sizeof(int))))
        return AVERROR(ENOMEM);

    av_free(c->chapter_tracks);
    c->chapter_tracks = new_tracks;
    c->nb_chapter_tracks = num;

    for (i = 0; i < num && !pb->eof_reached; i++)
        c->chapter_tracks[i] = avio_rb32(pb);

4620 4621 4622
    return 0;
}

4623
static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4624 4625
{
    MOVTrackExt *trex;
4626
    int err;
4627 4628

    if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
4629
        return AVERROR_INVALIDDATA;
4630 4631 4632 4633 4634
    if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
                                 sizeof(*c->trex_data))) < 0) {
        c->trex_count = 0;
        return err;
    }
4635 4636 4637

    c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.

4638
    trex = &c->trex_data[c->trex_count++];
4639 4640 4641 4642 4643 4644 4645
    avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */
    trex->track_id = avio_rb32(pb);
    trex->stsd_id  = avio_rb32(pb);
    trex->duration = avio_rb32(pb);
    trex->size     = avio_rb32(pb);
    trex->flags    = avio_rb32(pb);
4646 4647 4648
    return 0;
}

Martin Storsjö's avatar
Martin Storsjö committed
4649 4650 4651 4652 4653 4654
static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    MOVFragment *frag = &c->fragment;
    AVStream *st = NULL;
    MOVStreamContext *sc;
    int version, i;
4655 4656
    MOVFragmentStreamInfo * frag_stream_info;
    int64_t base_media_decode_time;
Martin Storsjö's avatar
Martin Storsjö committed
4657 4658 4659 4660 4661 4662 4663 4664

    for (i = 0; i < c->fc->nb_streams; i++) {
        if (c->fc->streams[i]->id == frag->track_id) {
            st = c->fc->streams[i];
            break;
        }
    }
    if (!st) {
4665 4666
        av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
        return 0;
Martin Storsjö's avatar
Martin Storsjö committed
4667 4668
    }
    sc = st->priv_data;
4669
    if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
Martin Storsjö's avatar
Martin Storsjö committed
4670 4671 4672 4673
        return 0;
    version = avio_r8(pb);
    avio_rb24(pb); /* flags */
    if (version) {
4674
        base_media_decode_time = avio_rb64(pb);
Martin Storsjö's avatar
Martin Storsjö committed
4675
    } else {
4676
        base_media_decode_time = avio_rb32(pb);
Martin Storsjö's avatar
Martin Storsjö committed
4677
    }
4678 4679 4680 4681 4682 4683

    frag_stream_info = get_current_frag_stream_info(&c->frag_index);
    if (frag_stream_info)
        frag_stream_info->tfdt_dts = base_media_decode_time;
    sc->track_end = base_media_decode_time;

Martin Storsjö's avatar
Martin Storsjö committed
4684 4685 4686
    return 0;
}

4687
static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4688 4689
{
    MOVFragment *frag = &c->fragment;
4690
    AVStream *st = NULL;
4691
    MOVStreamContext *sc;
4692
    MOVStts *ctts_data;
4693
    uint64_t offset;
4694
    int64_t dts, pts = AV_NOPTS_VALUE;
4695 4696
    int data_offset = 0;
    unsigned entries, first_sample_flags = frag->flags;
4697
    int flags, distance, i;
4698 4699 4700
    int64_t prev_dts = AV_NOPTS_VALUE;
    int next_frag_index = -1, index_entry_pos;
    size_t requested_size;
4701
    size_t old_ctts_allocated_size;
4702 4703
    AVIndexEntry *new_entries;
    MOVFragmentStreamInfo * frag_stream_info;
4704

4705 4706 4707 4708 4709
    if (!frag->found_tfhd) {
        av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
        return AVERROR_INVALIDDATA;
    }

4710 4711 4712 4713 4714 4715 4716
    for (i = 0; i < c->fc->nb_streams; i++) {
        if (c->fc->streams[i]->id == frag->track_id) {
            st = c->fc->streams[i];
            break;
        }
    }
    if (!st) {
4717 4718
        av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
        return 0;
4719
    }
4720
    sc = st->priv_data;
4721
    if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
4722
        return 0;
4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738

    // Find the next frag_index index that has a valid index_entry for
    // the current track_id.
    //
    // A valid index_entry means the trun for the fragment was read
    // and it's samples are in index_entries at the given position.
    // New index entries will be inserted before the index_entry found.
    index_entry_pos = st->nb_index_entries;
    for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
        frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
        if (frag_stream_info && frag_stream_info->index_entry >= 0) {
            next_frag_index = i;
            index_entry_pos = frag_stream_info->index_entry;
            break;
        }
    }
4739
    av_assert0(index_entry_pos <= st->nb_index_entries);
4740

4741 4742 4743
    avio_r8(pb); /* version */
    flags = avio_rb24(pb);
    entries = avio_rb32(pb);
4744
    av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
4745 4746

    if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data))
4747
        return AVERROR_INVALIDDATA;
4748 4749
    if (flags & MOV_TRUN_DATA_OFFSET)        data_offset        = avio_rb32(pb);
    if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779

    frag_stream_info = get_current_frag_stream_info(&c->frag_index);
    if (frag_stream_info)
    {
        if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
            c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
            pts = frag_stream_info->first_tfra_pts;
            av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
                    ", using it for pts\n", pts);
        } else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) {
            // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
            // pts = frag_stream_info->sidx_pts;
            dts = frag_stream_info->sidx_pts - sc->time_offset;
            av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
                    ", using it for pts\n", pts);
        } else if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) {
            dts = frag_stream_info->tfdt_dts - sc->time_offset;
            av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
                    ", using it for dts\n", dts);
        } else {
            dts = sc->track_end - sc->time_offset;
            av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
                    ", using it for dts\n", dts);
        }
    } else {
        dts = sc->track_end - sc->time_offset;
        av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
                ", using it for dts\n", dts);
    }
    offset   = frag->base_data_offset + data_offset;
4780
    distance = 0;
4781
    av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
4782 4783

    // realloc space for new index entries
4784
    if((uint64_t)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
4785 4786 4787
        entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries;
        av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
    }
4788 4789
    if (entries == 0)
        return 0;
4790 4791 4792 4793 4794 4795 4796 4797 4798 4799

    requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry);
    new_entries = av_fast_realloc(st->index_entries,
                                  &st->index_entries_allocated_size,
                                  requested_size);
    if(!new_entries)
        return AVERROR(ENOMEM);
    st->index_entries= new_entries;

    requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data);
4800
    old_ctts_allocated_size = sc->ctts_allocated_size;
4801 4802 4803 4804 4805 4806 4807 4808 4809
    ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size,
                                requested_size);
    if (!ctts_data)
        return AVERROR(ENOMEM);
    sc->ctts_data = ctts_data;

    // In case there were samples without ctts entries, ensure they get
    // zero valued entries. This ensures clips which mix boxes with and
    // without ctts entries don't pickup uninitialized data.
4810 4811
    memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0,
           sc->ctts_allocated_size - old_ctts_allocated_size);
4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836

    if (index_entry_pos < st->nb_index_entries) {
        // Make hole in index_entries and ctts_data for new samples
        memmove(st->index_entries + index_entry_pos + entries,
                st->index_entries + index_entry_pos,
                sizeof(*st->index_entries) *
                (st->nb_index_entries - index_entry_pos));
        memmove(sc->ctts_data + index_entry_pos + entries,
                sc->ctts_data + index_entry_pos,
                sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos));
        if (index_entry_pos < sc->current_sample) {
            sc->current_sample += entries;
        }
    }

    st->nb_index_entries += entries;
    sc->ctts_count = st->nb_index_entries;

    // Record the index_entry position in frag_index of this fragment
    if (frag_stream_info)
        frag_stream_info->index_entry = index_entry_pos;

    if (index_entry_pos > 0)
        prev_dts = st->index_entries[index_entry_pos-1].timestamp;

4837
    for (i = 0; i < entries && !pb->eof_reached; i++) {
4838 4839 4840
        unsigned sample_size = frag->size;
        int sample_flags = i ? frag->flags : first_sample_flags;
        unsigned sample_duration = frag->duration;
4841
        unsigned ctts_duration = 0;
4842
        int keyframe = 0;
4843
        int index_entry_flags = 0;
4844

4845 4846 4847
        if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
        if (flags & MOV_TRUN_SAMPLE_SIZE)     sample_size     = avio_rb32(pb);
        if (flags & MOV_TRUN_SAMPLE_FLAGS)    sample_flags    = avio_rb32(pb);
4848 4849 4850
        if (flags & MOV_TRUN_SAMPLE_CTS)      ctts_duration   = avio_rb32(pb);

        mov_update_dts_shift(sc, ctts_duration);
4851 4852 4853 4854
        if (pts != AV_NOPTS_VALUE) {
            dts = pts - sc->dts_shift;
            if (flags & MOV_TRUN_SAMPLE_CTS) {
                dts -= ctts_duration;
4855
            } else {
4856
                dts -= sc->time_offset;
4857
            }
4858 4859 4860 4861 4862 4863 4864 4865 4866
            av_log(c->fc, AV_LOG_DEBUG,
                   "pts %"PRId64" calculated dts %"PRId64
                   " sc->dts_shift %d ctts.duration %d"
                   " sc->time_offset %"PRId64
                   " flags & MOV_TRUN_SAMPLE_CTS %d\n",
                   pts, dts,
                   sc->dts_shift, ctts_duration,
                   sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
            pts = AV_NOPTS_VALUE;
4867
        }
4868

4869
        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
4870
            keyframe = 1;
4871 4872
        else
            keyframe =
4873 4874
                !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
                                  MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
4875
        if (keyframe) {
4876
            distance = 0;
4877
            index_entry_flags |= AVINDEX_KEYFRAME;
4878
        }
4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892
        // Fragments can overlap in time.  Discard overlapping frames after
        // decoding.
        if (prev_dts >= dts)
            index_entry_flags |= AVINDEX_DISCARD_FRAME;

        st->index_entries[index_entry_pos].pos = offset;
        st->index_entries[index_entry_pos].timestamp = dts;
        st->index_entries[index_entry_pos].size= sample_size;
        st->index_entries[index_entry_pos].min_distance= distance;
        st->index_entries[index_entry_pos].flags = index_entry_flags;

        sc->ctts_data[index_entry_pos].count = 1;
        sc->ctts_data[index_entry_pos].duration = ctts_duration;
        index_entry_pos++;
4893

4894
        av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
4895 4896
                "size %u, distance %d, keyframe %d\n", st->index,
                index_entry_pos, offset, dts, sample_size, distance, keyframe);
4897
        distance++;
4898
        dts += sample_duration;
4899
        offset += sample_size;
4900
        sc->data_size += sample_size;
4901 4902

        if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
4903
            1 <= INT_MAX - sc->nb_frames_for_fps
4904 4905 4906 4907
        ) {
            sc->duration_for_fps += sample_duration;
            sc->nb_frames_for_fps ++;
        }
4908
    }
4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946
    if (i < entries) {
        // EOF found before reading all entries.  Fix the hole this would
        // leave in index_entries and ctts_data
        int gap = entries - i;
        memmove(st->index_entries + index_entry_pos,
                st->index_entries + index_entry_pos + gap,
                sizeof(*st->index_entries) *
                (st->nb_index_entries - (index_entry_pos + gap)));
        memmove(sc->ctts_data + index_entry_pos,
                sc->ctts_data + index_entry_pos + gap,
                sizeof(*sc->ctts_data) *
                (sc->ctts_count - (index_entry_pos + gap)));

        st->nb_index_entries -= gap;
        sc->ctts_count -= gap;
        if (index_entry_pos < sc->current_sample) {
            sc->current_sample -= gap;
        }
        entries = i;
    }

    // The end of this new fragment may overlap in time with the start
    // of the next fragment in index_entries. Mark the samples in the next
    // fragment that overlap with AVINDEX_DISCARD_FRAME
    prev_dts = AV_NOPTS_VALUE;
    if (index_entry_pos > 0)
        prev_dts = st->index_entries[index_entry_pos-1].timestamp;
    for (i = index_entry_pos; i < st->nb_index_entries; i++) {
        if (prev_dts < st->index_entries[i].timestamp)
            break;
        st->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
    }

    // If a hole was created to insert the new index_entries into,
    // the index_entry recorded for all subsequent moof must
    // be incremented by the number of entries inserted.
    fix_frag_index_entries(&c->frag_index, next_frag_index,
                           frag->track_id, entries);
4947

4948 4949
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
4950
        return AVERROR_EOF;
4951
    }
4952

4953
    frag->implicit_offset = offset;
4954 4955 4956 4957 4958 4959 4960 4961 4962 4963

    sc->track_end = dts + sc->time_offset;
    if (st->duration < sc->track_end)
        st->duration = sc->track_end;

    return 0;
}

static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
4964
    int64_t offset = avio_tell(pb) + atom.size, pts, timestamp;
4965
    uint8_t version;
4966
    unsigned i, j, track_id, item_count;
4967
    AVStream *st = NULL;
4968 4969
    AVStream *ref_st = NULL;
    MOVStreamContext *sc, *ref_sc = NULL;
4970 4971 4972 4973 4974
    AVRational timescale;

    version = avio_r8(pb);
    if (version > 1) {
        avpriv_request_sample(c->fc, "sidx version %u", version);
4975
        return 0;
4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987
    }

    avio_rb24(pb); // flags

    track_id = avio_rb32(pb); // Reference ID
    for (i = 0; i < c->fc->nb_streams; i++) {
        if (c->fc->streams[i]->id == track_id) {
            st = c->fc->streams[i];
            break;
        }
    }
    if (!st) {
4988 4989
        av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
        return 0;
4990 4991 4992 4993 4994 4995
    }

    sc = st->priv_data;

    timescale = av_make_q(1, avio_rb32(pb));

4996 4997 4998 4999 5000
    if (timescale.den <= 0) {
        av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
        return AVERROR_INVALIDDATA;
    }

5001 5002 5003 5004 5005 5006 5007 5008 5009 5010
    if (version == 0) {
        pts = avio_rb32(pb);
        offset += avio_rb32(pb);
    } else {
        pts = avio_rb64(pb);
        offset += avio_rb64(pb);
    }

    avio_rb16(pb); // reserved

5011
    item_count = avio_rb16(pb);
5012

5013 5014 5015
    for (i = 0; i < item_count; i++) {
        int index;
        MOVFragmentStreamInfo * frag_stream_info;
5016 5017 5018 5019 5020 5021 5022
        uint32_t size = avio_rb32(pb);
        uint32_t duration = avio_rb32(pb);
        if (size & 0x80000000) {
            avpriv_request_sample(c->fc, "sidx reference_type 1");
            return AVERROR_PATCHWELCOME;
        }
        avio_rb32(pb); // sap_flags
5023
        timestamp = av_rescale_q(pts, timescale, st->time_base);
5024 5025 5026 5027 5028 5029

        index = update_frag_index(c, offset);
        frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
        if (frag_stream_info)
            frag_stream_info->sidx_pts = timestamp;

5030 5031 5032 5033 5034 5035
        offset += size;
        pts += duration;
    }

    st->duration = sc->track_end = pts;

5036 5037 5038
    sc->has_sidx = 1;

    if (offset == avio_size(pb)) {
5039 5040 5041 5042 5043 5044 5045 5046
        // Find first entry in fragment index that came from an sidx.
        // This will pretty much always be the first entry.
        for (i = 0; i < c->frag_index.nb_items; i++) {
            MOVFragmentIndexItem * item = &c->frag_index.item[i];
            for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
                MOVFragmentStreamInfo * si;
                si = &item->stream_info[j];
                if (si->sidx_pts != AV_NOPTS_VALUE) {
5047
                    ref_st = c->fc->streams[j];
5048 5049 5050
                    ref_sc = ref_st->priv_data;
                    break;
                }
5051 5052
            }
        }
5053
        if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
5054 5055 5056 5057 5058 5059
            st = c->fc->streams[i];
            sc = st->priv_data;
            if (!sc->has_sidx) {
                st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
            }
        }
5060

5061
        c->frag_index.complete = 1;
5062
    }
5063

5064 5065 5066
    return 0;
}

5067 5068 5069
/* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
/* like the files created with Adobe Premiere 5.0, for samples see */
/* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
5070
static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5071 5072 5073 5074 5075
{
    int err;

    if (atom.size < 8)
        return 0; /* continue */
5076
    if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
5077
        avio_skip(pb, atom.size - 4);
5078 5079
        return 0;
    }
5080
    atom.type = avio_rl32(pb);
5081
    atom.size -= 8;
5082
    if (atom.type != MKTAG('m','d','a','t')) {
5083
        avio_skip(pb, atom.size);
5084 5085 5086 5087 5088 5089
        return 0;
    }
    err = mov_read_mdat(c, pb, atom);
    return err;
}

5090
static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5091
{
5092
#if CONFIG_ZLIB
5093
    AVIOContext ctx;
5094 5095
    uint8_t *cmov_data;
    uint8_t *moov_data; /* uncompressed data */
5096
    long cmov_len, moov_len;
5097
    int ret = -1;
5098

5099 5100
    avio_rb32(pb); /* dcom atom */
    if (avio_rl32(pb) != MKTAG('d','c','o','m'))
5101
        return AVERROR_INVALIDDATA;
5102
    if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
5103
        av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
5104
        return AVERROR_INVALIDDATA;
5105
    }
5106 5107
    avio_rb32(pb); /* cmvd atom */
    if (avio_rl32(pb) != MKTAG('c','m','v','d'))
5108
        return AVERROR_INVALIDDATA;
5109
    moov_len = avio_rb32(pb); /* uncompressed size */
5110
    cmov_len = atom.size - 6 * 4;
5111

5112
    cmov_data = av_malloc(cmov_len);
5113
    if (!cmov_data)
5114
        return AVERROR(ENOMEM);
5115
    moov_data = av_malloc(moov_len);
5116 5117
    if (!moov_data) {
        av_free(cmov_data);
5118
        return AVERROR(ENOMEM);
5119
    }
5120 5121 5122 5123
    ret = ffio_read_size(pb, cmov_data, cmov_len);
    if (ret < 0)
        goto free_and_return;

5124
    ret = AVERROR_INVALIDDATA;
5125
    if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
5126
        goto free_and_return;
5127
    if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
5128
        goto free_and_return;
5129
    ctx.seekable = AVIO_SEEKABLE_NORMAL;
5130
    atom.type = MKTAG('m','o','o','v');
5131 5132
    atom.size = moov_len;
    ret = mov_read_default(c, &ctx, atom);
5133
free_and_return:
5134 5135 5136
    av_free(moov_data);
    av_free(cmov_data);
    return ret;
5137 5138
#else
    av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
5139
    return AVERROR(ENOSYS);
5140
#endif
5141
}
5142

5143
/* edit list atom */
5144
static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5145
{
5146
    MOVStreamContext *sc;
5147
    int i, edit_count, version;
5148
    int64_t elst_entry_size;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
5149

5150
    if (c->fc->nb_streams < 1 || c->ignore_editlist)
5151 5152 5153
        return 0;
    sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;

5154
    version = avio_r8(pb); /* version */
5155 5156
    avio_rb24(pb); /* flags */
    edit_count = avio_rb32(pb); /* entries */
5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171
    atom.size -= 8;

    elst_entry_size = version == 1 ? 20 : 12;
    if (atom.size != edit_count * elst_entry_size) {
        if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
            av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
                   edit_count, atom.size + 8);
            return AVERROR_INVALIDDATA;
        } else {
            edit_count = atom.size / elst_entry_size;
            if (edit_count * elst_entry_size != atom.size) {
                av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.", atom.size, edit_count);
            }
        }
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
5172

5173 5174 5175 5176 5177 5178 5179 5180 5181
    if (!edit_count)
        return 0;
    if (sc->elst_data)
        av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
    av_free(sc->elst_data);
    sc->elst_count = 0;
    sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
    if (!sc->elst_data)
        return AVERROR(ENOMEM);
5182

5183
    av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
5184
    for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
5185 5186
        MOVElst *e = &sc->elst_data[i];

5187
        if (version == 1) {
5188 5189
            e->duration = avio_rb64(pb);
            e->time     = avio_rb64(pb);
5190
            atom.size -= 16;
5191
        } else {
5192 5193
            e->duration = avio_rb32(pb); /* segment duration */
            e->time     = (int32_t)avio_rb32(pb); /* media time */
5194
            atom.size -= 8;
5195
        }
5196
        e->rate = avio_rb32(pb) / 65536.0;
5197
        atom.size -= 4;
5198
        av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
5199 5200 5201 5202 5203 5204 5205 5206
               e->duration, e->time, e->rate);

        if (e->time < 0 && e->time != -1 &&
            c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
            av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
                   c->fc->nb_streams-1, i, e->time);
            return AVERROR_INVALIDDATA;
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
5207
    }
5208
    sc->elst_count = i;
5209

Baptiste Coudurier's avatar
Baptiste Coudurier committed
5210
    return 0;
5211 5212
}

5213
static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
Clément Bœsch's avatar
Clément Bœsch committed
5214 5215 5216 5217 5218 5219
{
    MOVStreamContext *sc;

    if (c->fc->nb_streams < 1)
        return AVERROR_INVALIDDATA;
    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5220
    sc->timecode_track = avio_rb32(pb);
Clément Bœsch's avatar
Clément Bœsch committed
5221 5222 5223
    return 0;
}

5224 5225 5226
static int mov_read_av1c(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
5227
    int ret;
5228 5229 5230 5231 5232

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams - 1];

5233
    if (atom.size < 4) {
5234 5235 5236 5237
        av_log(c->fc, AV_LOG_ERROR, "Empty AV1 Codec Configuration Box\n");
        return AVERROR_INVALIDDATA;
    }

5238 5239 5240
    /* For now, propagate only the OBUs, if any. Once libavcodec is
       updated to handle isobmff style extradata this can be removed. */
    avio_skip(pb, 4);
5241

5242 5243
    if (atom.size == 4)
        return 0;
5244

5245
    ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 4);
5246 5247 5248 5249 5250 5251
    if (ret < 0)
        return ret;

    return 0;
}

5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295
static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    int version, color_range, color_primaries, color_trc, color_space;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams - 1];

    if (atom.size < 5) {
        av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
        return AVERROR_INVALIDDATA;
    }

    version = avio_r8(pb);
    if (version != 1) {
        av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
        return 0;
    }
    avio_skip(pb, 3); /* flags */

    avio_skip(pb, 2); /* profile + level */
    color_range     = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
    color_primaries = avio_r8(pb);
    color_trc       = avio_r8(pb);
    color_space     = avio_r8(pb);
    if (avio_rb16(pb)) /* codecIntializationDataSize */
        return AVERROR_INVALIDDATA;

    if (!av_color_primaries_name(color_primaries))
        color_primaries = AVCOL_PRI_UNSPECIFIED;
    if (!av_color_transfer_name(color_trc))
        color_trc = AVCOL_TRC_UNSPECIFIED;
    if (!av_color_space_name(color_space))
        color_space = AVCOL_SPC_UNSPECIFIED;

    st->codecpar->color_range     = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
    st->codecpar->color_primaries = color_primaries;
    st->codecpar->color_trc       = color_trc;
    st->codecpar->color_space     = color_space;

    return 0;
}

5296 5297 5298
static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    MOVStreamContext *sc;
5299
    int i, version;
5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321

    if (c->fc->nb_streams < 1)
        return AVERROR_INVALIDDATA;

    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;

    if (atom.size < 5) {
        av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
        return AVERROR_INVALIDDATA;
    }

    version = avio_r8(pb);
    if (version) {
        av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
        return 0;
    }
    avio_skip(pb, 3); /* flags */

    sc->mastering = av_mastering_display_metadata_alloc();
    if (!sc->mastering)
        return AVERROR(ENOMEM);

5322 5323 5324 5325 5326 5327 5328 5329 5330
    for (i = 0; i < 3; i++) {
        sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
        sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
    }
    sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
    sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);

    sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
    sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
5331 5332 5333 5334 5335 5336 5337

    sc->mastering->has_primaries = 1;
    sc->mastering->has_luminance = 1;

    return 0;
}

5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361
static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    MOVStreamContext *sc;
    const int mapping[3] = {1, 2, 0};
    const int chroma_den = 50000;
    const int luma_den = 10000;
    int i;

    if (c->fc->nb_streams < 1)
        return AVERROR_INVALIDDATA;

    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;

    if (atom.size < 24) {
        av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
        return AVERROR_INVALIDDATA;
    }

    sc->mastering = av_mastering_display_metadata_alloc();
    if (!sc->mastering)
        return AVERROR(ENOMEM);

    for (i = 0; i < 3; i++) {
        const int j = mapping[i];
5362 5363 5364 5365 5366 5367 5368 5369
        sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
        sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
    }
    sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
    sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);

    sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
    sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
5370 5371 5372 5373 5374 5375 5376

    sc->mastering->has_luminance = 1;
    sc->mastering->has_primaries = 1;

    return 0;
}

5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408
static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    MOVStreamContext *sc;
    int version;

    if (c->fc->nb_streams < 1)
        return AVERROR_INVALIDDATA;

    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;

    if (atom.size < 5) {
        av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
        return AVERROR_INVALIDDATA;
    }

    version = avio_r8(pb);
    if (version) {
        av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
        return 0;
    }
    avio_skip(pb, 3); /* flags */

    sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
    if (!sc->coll)
        return AVERROR(ENOMEM);

    sc->coll->MaxCLL  = avio_rb16(pb);
    sc->coll->MaxFALL = avio_rb16(pb);

    return 0;
}

5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432
static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    MOVStreamContext *sc;

    if (c->fc->nb_streams < 1)
        return AVERROR_INVALIDDATA;

    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;

    if (atom.size < 4) {
        av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
        return AVERROR_INVALIDDATA;
    }

    sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
    if (!sc->coll)
        return AVERROR(ENOMEM);

    sc->coll->MaxCLL  = avio_rb16(pb);
    sc->coll->MaxFALL = avio_rb16(pb);

    return 0;
}

5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479
static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    MOVStreamContext *sc;
    enum AVStereo3DType type;
    int mode;

    if (c->fc->nb_streams < 1)
        return 0;

    st = c->fc->streams[c->fc->nb_streams - 1];
    sc = st->priv_data;

    if (atom.size < 5) {
        av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
        return AVERROR_INVALIDDATA;
    }
    avio_skip(pb, 4); /* version + flags */

    mode = avio_r8(pb);
    switch (mode) {
    case 0:
        type = AV_STEREO3D_2D;
        break;
    case 1:
        type = AV_STEREO3D_TOPBOTTOM;
        break;
    case 2:
        type = AV_STEREO3D_SIDEBYSIDE;
        break;
    default:
        av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
        return 0;
    }

    sc->stereo3d = av_stereo3d_alloc();
    if (!sc->stereo3d)
        return AVERROR(ENOMEM);

    sc->stereo3d->type = type;
    return 0;
}

static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    MOVStreamContext *sc;
James Almer's avatar
James Almer committed
5480
    int size, version, layout;
5481
    int32_t yaw, pitch, roll;
5482 5483
    uint32_t l = 0, t = 0, r = 0, b = 0;
    uint32_t tag, padding = 0;
5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497
    enum AVSphericalProjection projection;

    if (c->fc->nb_streams < 1)
        return 0;

    st = c->fc->streams[c->fc->nb_streams - 1];
    sc = st->priv_data;

    if (atom.size < 8) {
        av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
        return AVERROR_INVALIDDATA;
    }

    size = avio_rb32(pb);
5498
    if (size <= 12 || size > atom.size)
5499 5500 5501 5502 5503 5504 5505
        return AVERROR_INVALIDDATA;

    tag = avio_rl32(pb);
    if (tag != MKTAG('s','v','h','d')) {
        av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
        return 0;
    }
James Almer's avatar
James Almer committed
5506 5507 5508 5509 5510 5511 5512
    version = avio_r8(pb);
    if (version != 0) {
        av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
               version);
        return 0;
    }
    avio_skip(pb, 3); /* flags */
5513
    avio_skip(pb, size - 12); /* metadata_source */
5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533

    size = avio_rb32(pb);
    if (size > atom.size)
        return AVERROR_INVALIDDATA;

    tag = avio_rl32(pb);
    if (tag != MKTAG('p','r','o','j')) {
        av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
        return 0;
    }

    size = avio_rb32(pb);
    if (size > atom.size)
        return AVERROR_INVALIDDATA;

    tag = avio_rl32(pb);
    if (tag != MKTAG('p','r','h','d')) {
        av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
        return 0;
    }
5534 5535 5536 5537 5538 5539 5540
    version = avio_r8(pb);
    if (version != 0) {
        av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
               version);
        return 0;
    }
    avio_skip(pb, 3); /* flags */
5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551

    /* 16.16 fixed point */
    yaw   = avio_rb32(pb);
    pitch = avio_rb32(pb);
    roll  = avio_rb32(pb);

    size = avio_rb32(pb);
    if (size > atom.size)
        return AVERROR_INVALIDDATA;

    tag = avio_rl32(pb);
5552 5553 5554 5555 5556 5557 5558
    version = avio_r8(pb);
    if (version != 0) {
        av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
               version);
        return 0;
    }
    avio_skip(pb, 3); /* flags */
5559 5560
    switch (tag) {
    case MKTAG('c','b','m','p'):
5561 5562 5563 5564 5565 5566
        layout = avio_rb32(pb);
        if (layout) {
            av_log(c->fc, AV_LOG_WARNING,
                   "Unsupported cubemap layout %d\n", layout);
            return 0;
        }
5567
        projection = AV_SPHERICAL_CUBEMAP;
5568
        padding = avio_rb32(pb);
5569 5570
        break;
    case MKTAG('e','q','u','i'):
5571 5572 5573 5574 5575 5576 5577
        t = avio_rb32(pb);
        b = avio_rb32(pb);
        l = avio_rb32(pb);
        r = avio_rb32(pb);

        if (b >= UINT_MAX - t || r >= UINT_MAX - l) {
            av_log(c->fc, AV_LOG_ERROR,
5578
                   "Invalid bounding rectangle coordinates "
5579
                   "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
5580 5581 5582 5583 5584 5585 5586
            return AVERROR_INVALIDDATA;
        }

        if (l || t || r || b)
            projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
        else
            projection = AV_SPHERICAL_EQUIRECTANGULAR;
5587 5588
        break;
    default:
5589
        av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602
        return 0;
    }

    sc->spherical = av_spherical_alloc(&sc->spherical_size);
    if (!sc->spherical)
        return AVERROR(ENOMEM);

    sc->spherical->projection = projection;

    sc->spherical->yaw   = yaw;
    sc->spherical->pitch = pitch;
    sc->spherical->roll  = roll;

5603 5604 5605 5606 5607 5608 5609
    sc->spherical->padding = padding;

    sc->spherical->bound_left   = l;
    sc->spherical->bound_top    = t;
    sc->spherical->bound_right  = r;
    sc->spherical->bound_bottom = b;

5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627
    return 0;
}

static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
{
    int ret = 0;
    uint8_t *buffer = av_malloc(len + 1);
    const char *val;

    if (!buffer)
        return AVERROR(ENOMEM);
    buffer[len] = '\0';

    ret = ffio_read_size(pb, buffer, len);
    if (ret < 0)
        goto out;

    /* Check for mandatory keys and values, try to support XML as best-effort */
5628 5629
    if (!sc->spherical &&
        av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641
        (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
        av_stristr(val, "true") &&
        (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
        av_stristr(val, "true") &&
        (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
        av_stristr(val, "equirectangular")) {
        sc->spherical = av_spherical_alloc(&sc->spherical_size);
        if (!sc->spherical)
            goto out;

        sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;

5642
        if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675
            enum AVStereo3DType mode;

            if (av_stristr(buffer, "left-right"))
                mode = AV_STEREO3D_SIDEBYSIDE;
            else if (av_stristr(buffer, "top-bottom"))
                mode = AV_STEREO3D_TOPBOTTOM;
            else
                mode = AV_STEREO3D_2D;

            sc->stereo3d = av_stereo3d_alloc();
            if (!sc->stereo3d)
                goto out;

            sc->stereo3d->type = mode;
        }

        /* orientation */
        val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
        if (val)
            sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
        val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
        if (val)
            sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
        val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
        if (val)
            sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
    }

out:
    av_free(buffer);
    return ret;
}

5676 5677
static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
5678 5679
    AVStream *st;
    MOVStreamContext *sc;
5680
    int64_t ret;
5681 5682 5683 5684 5685
    uint8_t uuid[16];
    static const uint8_t uuid_isml_manifest[] = {
        0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
        0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
    };
5686 5687 5688 5689
    static const uint8_t uuid_xmp[] = {
        0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
        0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
    };
5690 5691 5692 5693
    static const uint8_t uuid_spherical[] = {
        0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
        0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
    };
5694

5695
    if (atom.size < sizeof(uuid) || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
5696 5697
        return AVERROR_INVALIDDATA;

5698 5699 5700 5701 5702
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams - 1];
    sc = st->priv_data;

5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733
    ret = avio_read(pb, uuid, sizeof(uuid));
    if (ret < 0) {
        return ret;
    } else if (ret != sizeof(uuid)) {
        return AVERROR_INVALIDDATA;
    }
    if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
        uint8_t *buffer, *ptr;
        char *endptr;
        size_t len = atom.size - sizeof(uuid);

        if (len < 4) {
            return AVERROR_INVALIDDATA;
        }
        ret = avio_skip(pb, 4); // zeroes
        len -= 4;

        buffer = av_mallocz(len + 1);
        if (!buffer) {
            return AVERROR(ENOMEM);
        }
        ret = avio_read(pb, buffer, len);
        if (ret < 0) {
            av_free(buffer);
            return ret;
        } else if (ret != len) {
            av_free(buffer);
            return AVERROR_INVALIDDATA;
        }

        ptr = buffer;
5734
        while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751
            ptr += sizeof("systemBitrate=\"") - 1;
            c->bitrates_count++;
            c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
            if (!c->bitrates) {
                c->bitrates_count = 0;
                av_free(buffer);
                return AVERROR(ENOMEM);
            }
            errno = 0;
            ret = strtol(ptr, &endptr, 10);
            if (ret < 0 || errno || *endptr != '"') {
                c->bitrates[c->bitrates_count - 1] = 0;
            } else {
                c->bitrates[c->bitrates_count - 1] = ret;
            }
        }

5752 5753 5754 5755 5756
        av_free(buffer);
    } else if (!memcmp(uuid, uuid_xmp, sizeof(uuid))) {
        uint8_t *buffer;
        size_t len = atom.size - sizeof(uuid);
        if (c->export_xmp) {
5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768
            buffer = av_mallocz(len + 1);
            if (!buffer) {
                return AVERROR(ENOMEM);
            }
            ret = avio_read(pb, buffer, len);
            if (ret < 0) {
                av_free(buffer);
                return ret;
            } else if (ret != len) {
                av_free(buffer);
                return AVERROR_INVALIDDATA;
            }
5769 5770
            buffer[len] = '\0';
            av_dict_set(&c->fc->metadata, "xmp", buffer, 0);
5771 5772 5773 5774 5775 5776
            av_free(buffer);
        } else {
            // skip all uuid atom, which makes it fast for long uuid-xmp file
            ret = avio_skip(pb, len);
            if (ret < 0)
                return ret;
5777
        }
5778 5779 5780 5781 5782 5783
    } else if (!memcmp(uuid, uuid_spherical, sizeof(uuid))) {
        size_t len = atom.size - sizeof(uuid);
        ret = mov_parse_uuid_spherical(sc, pb, len);
        if (ret < 0)
            return ret;
        if (!sc->spherical)
5784 5785
            av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
    }
5786

5787 5788 5789
    return 0;
}

5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811
static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    int ret;
    uint8_t content[16];

    if (atom.size < 8)
        return 0;

    ret = avio_read(pb, content, FFMIN(sizeof(content), atom.size));
    if (ret < 0)
        return ret;

    if (   !c->found_moov
        && !c->found_mdat
        && !memcmp(content, "Anevia\x1A\x1A", 8)
        && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
        c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
    }

    return 0;
}

5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828
static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    uint32_t format = avio_rl32(pb);
    MOVStreamContext *sc;
    enum AVCodecID id;
    AVStream *st;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams - 1];
    sc = st->priv_data;

    switch (sc->format)
    {
    case MKTAG('e','n','c','v'):        // encrypted video
    case MKTAG('e','n','c','a'):        // encrypted audio
        id = mov_codec_id(st, format);
5829 5830
        if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
            st->codecpar->codec_id != id) {
5831 5832
            av_log(c->fc, AV_LOG_WARNING,
                   "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
5833
                   (char*)&format, st->codecpar->codec_id);
5834 5835 5836
            break;
        }

5837
        st->codecpar->codec_id = id;
5838 5839 5840 5841
        sc->format = format;
        break;

    default:
5842 5843 5844 5845 5846
        if (format != sc->format) {
            av_log(c->fc, AV_LOG_WARNING,
                   "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
                   (char*)&format, (char*)&sc->format);
        }
5847 5848 5849 5850 5851 5852
        break;
    }

    return 0;
}

5853 5854 5855 5856 5857 5858 5859
/**
 * Gets the current encryption info and associated current stream context.  If
 * we are parsing a track fragment, this will return the specific encryption
 * info for this fragment; otherwise this will return the global encryption
 * info for the current stream.
 */
static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
5860
{
5861
    MOVFragmentStreamInfo *frag_stream_info;
5862
    AVStream *st;
5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877
    int i;

    frag_stream_info = get_current_frag_stream_info(&c->frag_index);
    if (frag_stream_info) {
        for (i = 0; i < c->fc->nb_streams; i++) {
            if (c->fc->streams[i]->id == frag_stream_info->id) {
              st = c->fc->streams[i];
              break;
            }
        }
        if (i == c->fc->nb_streams)
            return 0;
        *sc = st->priv_data;

        if (!frag_stream_info->encryption_index) {
5878 5879 5880
            // If this stream isn't encrypted, don't create the index.
            if (!(*sc)->cenc.default_encrypted_sample)
                return 0;
5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895
            frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
            if (!frag_stream_info->encryption_index)
                return AVERROR(ENOMEM);
        }
        *encryption_index = frag_stream_info->encryption_index;
        return 1;
    } else {
        // No current track fragment, using stream level encryption info.

        if (c->fc->nb_streams < 1)
            return 0;
        st = c->fc->streams[c->fc->nb_streams - 1];
        *sc = st->priv_data;

        if (!(*sc)->cenc.encryption_index) {
5896 5897 5898
            // If this stream isn't encrypted, don't create the index.
            if (!(*sc)->cenc.default_encrypted_sample)
                return 0;
5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914
            (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
            if (!(*sc)->cenc.encryption_index)
                return AVERROR(ENOMEM);
        }

        *encryption_index = (*sc)->cenc.encryption_index;
        return 1;
    }
}

static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
{
    int i;
    unsigned int subsample_count;
    AVSubsampleEncryptionInfo *subsamples;

5915 5916 5917 5918 5919
    if (!sc->cenc.default_encrypted_sample) {
        av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
        return AVERROR_INVALIDDATA;
    }

5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934
    *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
    if (!*sample)
        return AVERROR(ENOMEM);

    if (sc->cenc.per_sample_iv_size != 0) {
        if (avio_read(pb, (*sample)->iv, sc->cenc.per_sample_iv_size) != sc->cenc.per_sample_iv_size) {
            av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
            av_encryption_info_free(*sample);
            *sample = NULL;
            return AVERROR_INVALIDDATA;
        }
    }

    if (use_subsamples) {
        subsample_count = avio_rb16(pb);
5935
        av_free((*sample)->subsamples);
5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963
        (*sample)->subsamples = av_mallocz_array(subsample_count, sizeof(*subsamples));
        if (!(*sample)->subsamples) {
            av_encryption_info_free(*sample);
            *sample = NULL;
            return AVERROR(ENOMEM);
        }

        for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
            (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
            (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
        }

        if (pb->eof_reached) {
            av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
            av_encryption_info_free(*sample);
            *sample = NULL;
            return AVERROR_INVALIDDATA;
        }
        (*sample)->subsample_count = subsample_count;
    }

    return 0;
}

static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVEncryptionInfo **encrypted_samples;
    MOVEncryptionIndex *encryption_index;
5964
    MOVStreamContext *sc;
5965 5966
    int use_subsamples, ret;
    unsigned int sample_count, i, alloc_size = 0;
5967

5968 5969 5970 5971 5972 5973 5974
    ret = get_current_encryption_info(c, &encryption_index, &sc);
    if (ret != 1)
        return ret;

    if (encryption_index->nb_encrypted_samples) {
        // This can happen if we have both saio/saiz and senc atoms.
        av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
5975
        return 0;
5976
    }
5977

5978 5979
    avio_r8(pb); /* version */
    use_subsamples = avio_rb24(pb) & 0x02; /* flags */
5980

5981 5982 5983 5984 5985
    sample_count = avio_rb32(pb);
    if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
        return AVERROR(ENOMEM);

    for (i = 0; i < sample_count; i++) {
5986
        unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007
        encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
                                            min_samples * sizeof(*encrypted_samples));
        if (encrypted_samples) {
            encryption_index->encrypted_samples = encrypted_samples;

            ret = mov_read_sample_encryption_info(
                c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
        } else {
            ret = AVERROR(ENOMEM);
        }
        if (pb->eof_reached) {
            av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
            ret = AVERROR_INVALIDDATA;
        }

        if (ret < 0) {
            for (; i > 0; i--)
                av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
            av_freep(&encryption_index->encrypted_samples);
            return ret;
        }
6008
    }
6009
    encryption_index->nb_encrypted_samples = sample_count;
6010

6011 6012
    return 0;
}
6013

6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039
static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
{
    AVEncryptionInfo **sample, **encrypted_samples;
    int64_t prev_pos;
    size_t sample_count, sample_info_size, i;
    int ret = 0;
    unsigned int alloc_size = 0;

    if (encryption_index->nb_encrypted_samples)
        return 0;
    sample_count = encryption_index->auxiliary_info_sample_count;
    if (encryption_index->auxiliary_offsets_count != 1) {
        av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
        return AVERROR_PATCHWELCOME;
    }
    if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
        return AVERROR(ENOMEM);

    prev_pos = avio_tell(pb);
    if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
        avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
        av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
        goto finish;
    }

    for (i = 0; i < sample_count && !pb->eof_reached; i++) {
6040
        unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112
        encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
                                            min_samples * sizeof(*encrypted_samples));
        if (!encrypted_samples) {
            ret = AVERROR(ENOMEM);
            goto finish;
        }
        encryption_index->encrypted_samples = encrypted_samples;

        sample = &encryption_index->encrypted_samples[i];
        sample_info_size = encryption_index->auxiliary_info_default_size
                               ? encryption_index->auxiliary_info_default_size
                               : encryption_index->auxiliary_info_sizes[i];

        ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
        if (ret < 0)
            goto finish;
    }
    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
        ret = AVERROR_INVALIDDATA;
    } else {
        encryption_index->nb_encrypted_samples = sample_count;
    }

finish:
    avio_seek(pb, prev_pos, SEEK_SET);
    if (ret < 0) {
        for (; i > 0; i--) {
            av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
        }
        av_freep(&encryption_index->encrypted_samples);
    }
    return ret;
}

/**
 * Tries to read the given number of bytes from the stream and puts it in a
 * newly allocated buffer.  This reads in small chunks to avoid allocating large
 * memory if the file contains an invalid/malicious size value.
 */
static int mov_try_read_block(AVIOContext *pb, size_t size, uint8_t **data)
{
    const unsigned int block_size = 1024 * 1024;
    uint8_t *buffer = NULL;
    unsigned int alloc_size = 0, offset = 0;
    while (offset < size) {
        unsigned int new_size =
            alloc_size >= INT_MAX - block_size ? INT_MAX : alloc_size + block_size;
        uint8_t *new_buffer = av_fast_realloc(buffer, &alloc_size, new_size);
        unsigned int to_read = FFMIN(size, alloc_size) - offset;
        if (!new_buffer) {
            av_free(buffer);
            return AVERROR(ENOMEM);
        }
        buffer = new_buffer;

        if (avio_read(pb, buffer + offset, to_read) != to_read) {
            av_free(buffer);
            return AVERROR_INVALIDDATA;
        }
        offset += to_read;
    }

    *data = buffer;
    return 0;
}

static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    MOVEncryptionIndex *encryption_index;
    MOVStreamContext *sc;
    int ret;
6113
    unsigned int sample_count, aux_info_type, aux_info_param;
6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131

    ret = get_current_encryption_info(c, &encryption_index, &sc);
    if (ret != 1)
        return ret;

    if (encryption_index->nb_encrypted_samples) {
        // This can happen if we have both saio/saiz and senc atoms.
        av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
        return 0;
    }

    if (encryption_index->auxiliary_info_sample_count) {
        av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
        return AVERROR_INVALIDDATA;
    }

    avio_r8(pb); /* version */
    if (avio_rb24(pb) & 0x01) {  /* flags */
6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154
        aux_info_type = avio_rb32(pb);
        aux_info_param = avio_rb32(pb);
        if (sc->cenc.default_encrypted_sample) {
            if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
                av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
                return 0;
            }
            if (aux_info_param != 0) {
                av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
                return 0;
            }
        } else {
            // Didn't see 'schm' or 'tenc', so this isn't encrypted.
            if ((aux_info_type == MKBETAG('c','e','n','c') ||
                 aux_info_type == MKBETAG('c','e','n','s') ||
                 aux_info_type == MKBETAG('c','b','c','1') ||
                 aux_info_type == MKBETAG('c','b','c','s')) &&
                aux_info_param == 0) {
                av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
                return AVERROR_INVALIDDATA;
            } else {
                return 0;
            }
6155
        }
6156 6157 6158
    } else if (!sc->cenc.default_encrypted_sample) {
        // Didn't see 'schm' or 'tenc', so this isn't encrypted.
        return 0;
6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185
    }

    encryption_index->auxiliary_info_default_size = avio_r8(pb);
    sample_count = avio_rb32(pb);
    encryption_index->auxiliary_info_sample_count = sample_count;

    if (encryption_index->auxiliary_info_default_size == 0) {
        ret = mov_try_read_block(pb, sample_count, &encryption_index->auxiliary_info_sizes);
        if (ret < 0) {
            av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info\n");
            return ret;
        }
    }

    if (encryption_index->auxiliary_offsets_count) {
        return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
    }

    return 0;
}

static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    uint64_t *auxiliary_offsets;
    MOVEncryptionIndex *encryption_index;
    MOVStreamContext *sc;
    int i, ret;
6186 6187
    unsigned int version, entry_count, aux_info_type, aux_info_param;
    unsigned int alloc_size = 0;
6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205

    ret = get_current_encryption_info(c, &encryption_index, &sc);
    if (ret != 1)
        return ret;

    if (encryption_index->nb_encrypted_samples) {
        // This can happen if we have both saio/saiz and senc atoms.
        av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
        return 0;
    }

    if (encryption_index->auxiliary_offsets_count) {
        av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
        return AVERROR_INVALIDDATA;
    }

    version = avio_r8(pb); /* version */
    if (avio_rb24(pb) & 0x01) {  /* flags */
6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228
        aux_info_type = avio_rb32(pb);
        aux_info_param = avio_rb32(pb);
        if (sc->cenc.default_encrypted_sample) {
            if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
                av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
                return 0;
            }
            if (aux_info_param != 0) {
                av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
                return 0;
            }
        } else {
            // Didn't see 'schm' or 'tenc', so this isn't encrypted.
            if ((aux_info_type == MKBETAG('c','e','n','c') ||
                 aux_info_type == MKBETAG('c','e','n','s') ||
                 aux_info_type == MKBETAG('c','b','c','1') ||
                 aux_info_type == MKBETAG('c','b','c','s')) &&
                aux_info_param == 0) {
                av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
                return AVERROR_INVALIDDATA;
            } else {
                return 0;
            }
6229
        }
6230 6231 6232
    } else if (!sc->cenc.default_encrypted_sample) {
        // Didn't see 'schm' or 'tenc', so this isn't encrypted.
        return 0;
6233 6234 6235 6236 6237 6238 6239
    }

    entry_count = avio_rb32(pb);
    if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
        return AVERROR(ENOMEM);

    for (i = 0; i < entry_count && !pb->eof_reached; i++) {
6240
        unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274
        auxiliary_offsets = av_fast_realloc(
            encryption_index->auxiliary_offsets, &alloc_size,
            min_offsets * sizeof(*auxiliary_offsets));
        if (!auxiliary_offsets) {
            av_freep(&encryption_index->auxiliary_offsets);
            return AVERROR(ENOMEM);
        }
        encryption_index->auxiliary_offsets = auxiliary_offsets;

        if (version == 0) {
            encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
        } else {
            encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
        }
        if (c->frag_index.current >= 0) {
            encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
        }
    }

    if (pb->eof_reached) {
        av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
        av_freep(&encryption_index->auxiliary_offsets);
        return AVERROR_INVALIDDATA;
    }

    encryption_index->auxiliary_offsets_count = entry_count;

    if (encryption_index->auxiliary_info_sample_count) {
        return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
    }

    return 0;
}

6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382
static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVEncryptionInitInfo *info, *old_init_info;
    uint8_t **key_ids;
    AVStream *st;
    uint8_t *side_data, *extra_data, *old_side_data;
    size_t side_data_size;
    int ret = 0, old_side_data_size;
    unsigned int version, kid_count, extra_data_size, alloc_size = 0;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

    version = avio_r8(pb); /* version */
    avio_rb24(pb);  /* flags */

    info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
                                         /* key_id_size */ 16, /* data_size */ 0);
    if (!info)
        return AVERROR(ENOMEM);

    if (avio_read(pb, info->system_id, 16) != 16) {
        av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
        ret = AVERROR_INVALIDDATA;
        goto finish;
    }

    if (version > 0) {
        kid_count = avio_rb32(pb);
        if (kid_count >= INT_MAX / sizeof(*key_ids))
            return AVERROR(ENOMEM);

        for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
            unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
            key_ids = av_fast_realloc(info->key_ids, &alloc_size,
                                      min_kid_count * sizeof(*key_ids));
            if (!key_ids) {
                ret = AVERROR(ENOMEM);
                goto finish;
            }
            info->key_ids = key_ids;

            info->key_ids[i] = av_mallocz(16);
            if (!info->key_ids[i]) {
                ret = AVERROR(ENOMEM);
                goto finish;
            }
            info->num_key_ids = i + 1;

            if (avio_read(pb, info->key_ids[i], 16) != 16) {
                av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
                ret = AVERROR_INVALIDDATA;
                goto finish;
            }
        }

        if (pb->eof_reached) {
            av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
            ret = AVERROR_INVALIDDATA;
            goto finish;
        }
    }

    extra_data_size = avio_rb32(pb);
    ret = mov_try_read_block(pb, extra_data_size, &extra_data);
    if (ret < 0)
        goto finish;

    av_freep(&info->data);  // malloc(0) may still allocate something.
    info->data = extra_data;
    info->data_size = extra_data_size;

    // If there is existing initialization data, append to the list.
    old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
    if (old_side_data) {
        old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size);
        if (old_init_info) {
            // Append to the end of the list.
            for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
                if (!cur->next) {
                    cur->next = info;
                    break;
                }
            }
            info = old_init_info;
        } else {
            // Assume existing side-data will be valid, so the only error we could get is OOM.
            ret = AVERROR(ENOMEM);
            goto finish;
        }
    }

    side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
    if (!side_data) {
        ret = AVERROR(ENOMEM);
        goto finish;
    }
    ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
                                  side_data, side_data_size);
    if (ret < 0)
        av_free(side_data);

finish:
    av_encryption_init_info_free(info);
    return ret;
}

6383 6384 6385 6386
static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    MOVStreamContext *sc;
6387

6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398
    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

    if (sc->pseudo_stream_id != 0) {
        av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
        return AVERROR_PATCHWELCOME;
    }

    if (atom.size < 8)
6399
        return AVERROR_INVALIDDATA;
6400 6401 6402 6403 6404 6405 6406 6407

    avio_rb32(pb); /* version and flags */

    if (!sc->cenc.default_encrypted_sample) {
        sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
        if (!sc->cenc.default_encrypted_sample) {
            return AVERROR(ENOMEM);
        }
6408 6409
    }

6410 6411 6412
    sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
    return 0;
}
6413

6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427
static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    MOVStreamContext *sc;
    unsigned int version, pattern, is_protected, iv_size;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];
    sc = st->priv_data;

    if (sc->pseudo_stream_id != 0) {
        av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
        return AVERROR_PATCHWELCOME;
6428 6429
    }

6430 6431 6432 6433 6434 6435
    if (!sc->cenc.default_encrypted_sample) {
        sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
        if (!sc->cenc.default_encrypted_sample) {
            return AVERROR(ENOMEM);
        }
    }
6436

6437
    if (atom.size < 20)
6438
        return AVERROR_INVALIDDATA;
6439 6440 6441 6442 6443 6444 6445 6446 6447 6448

    version = avio_r8(pb); /* version */
    avio_rb24(pb); /* flags */

    avio_r8(pb); /* reserved */
    pattern = avio_r8(pb);

    if (version > 0) {
        sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
        sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
6449 6450
    }

6451 6452 6453 6454 6455 6456 6457 6458
    is_protected = avio_r8(pb);
    if (is_protected && !sc->cenc.encryption_index) {
        // The whole stream should be by-default encrypted.
        sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
        if (!sc->cenc.encryption_index)
            return AVERROR(ENOMEM);
    }
    sc->cenc.per_sample_iv_size = avio_r8(pb);
6459 6460 6461 6462 6463
    if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
        sc->cenc.per_sample_iv_size != 16) {
        av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
        return AVERROR_INVALIDDATA;
    }
6464
    if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
6465
        av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
6466
        return AVERROR_INVALIDDATA;
6467 6468
    }

6469 6470 6471 6472 6473 6474 6475 6476
    if (is_protected && !sc->cenc.per_sample_iv_size) {
        iv_size = avio_r8(pb);
        if (iv_size != 8 && iv_size != 16) {
            av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
            return AVERROR_INVALIDDATA;
        }

        if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
6477
            av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
6478 6479 6480 6481 6482
            return AVERROR_INVALIDDATA;
        }
    }

    return 0;
6483 6484
}

6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521
static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    int last, type, size, ret;
    uint8_t buf[4];

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

    if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
        return AVERROR_INVALIDDATA;

    /* Check FlacSpecificBox version. */
    if (avio_r8(pb) != 0)
        return AVERROR_INVALIDDATA;

    avio_rb24(pb); /* Flags */

    avio_read(pb, buf, sizeof(buf));
    flac_parse_block_header(buf, &last, &type, &size);

    if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
        av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
        return AVERROR_INVALIDDATA;
    }

    ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
    if (ret < 0)
        return ret;

    if (!last)
        av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");

    return 0;
}

6522
static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
6523
{
6524
    int i, ret;
6525

6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538
    if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) {
        av_log(c->fc, AV_LOG_ERROR, "Only the 'cenc' encryption scheme is supported\n");
        return AVERROR_PATCHWELCOME;
    }

    if (!sc->cenc.aes_ctr) {
        /* initialize the cipher */
        sc->cenc.aes_ctr = av_aes_ctr_alloc();
        if (!sc->cenc.aes_ctr) {
            return AVERROR(ENOMEM);
        }

        ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
6539 6540 6541 6542
        if (ret < 0) {
            return ret;
        }
    }
6543

6544
    av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
6545

6546
    if (!sample->subsample_count)
6547 6548 6549 6550 6551 6552
    {
        /* decrypt the whole packet */
        av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
        return 0;
    }

6553
    for (i = 0; i < sample->subsample_count; i++)
6554
    {
6555
        if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
6556 6557 6558 6559 6560
            av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
            return AVERROR_INVALIDDATA;
        }

        /* skip the clear bytes */
6561 6562
        input += sample->subsamples[i].bytes_of_clear_data;
        size -= sample->subsamples[i].bytes_of_clear_data;
6563 6564

        /* decrypt the encrypted bytes */
6565 6566 6567
        av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, sample->subsamples[i].bytes_of_protected_data);
        input += sample->subsamples[i].bytes_of_protected_data;
        size -= sample->subsamples[i].bytes_of_protected_data;
6568 6569
    }

6570
    if (size > 0) {
6571 6572 6573 6574
        av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
        return AVERROR_INVALIDDATA;
    }

6575 6576 6577
    return 0;
}

6578
static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
6579 6580 6581 6582
{
    MOVFragmentStreamInfo *frag_stream_info;
    MOVEncryptionIndex *encryption_index;
    AVEncryptionInfo *encrypted_sample;
6583
    int encrypted_index, ret;
6584

6585
    frag_stream_info = get_frag_stream_info(&mov->frag_index, mov->frag_index.current, st->id);
6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602
    encrypted_index = current_index;
    encryption_index = NULL;
    if (frag_stream_info) {
        // Note this only supports encryption info in the first sample descriptor.
        if (mov->fragment.stsd_id == 1) {
            if (frag_stream_info->encryption_index) {
                encrypted_index = current_index - frag_stream_info->index_entry;
                encryption_index = frag_stream_info->encryption_index;
            } else {
                encryption_index = sc->cenc.encryption_index;
            }
        }
    } else {
        encryption_index = sc->cenc.encryption_index;
    }

    if (encryption_index) {
6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613
        if (encryption_index->auxiliary_info_sample_count &&
            !encryption_index->nb_encrypted_samples) {
            av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
            return AVERROR_INVALIDDATA;
        }
        if (encryption_index->auxiliary_offsets_count &&
            !encryption_index->nb_encrypted_samples) {
            av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
            return AVERROR_INVALIDDATA;
        }

6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626
        if (!encryption_index->nb_encrypted_samples) {
            // Full-sample encryption with default settings.
            encrypted_sample = sc->cenc.default_encrypted_sample;
        } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
            // Per-sample setting override.
            encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
        } else {
            av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
            return AVERROR_INVALIDDATA;
        }

        if (mov->decryption_key) {
            return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
6627 6628 6629 6630 6631 6632 6633 6634 6635
        } else {
            size_t size;
            uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
            if (!side_data)
                return AVERROR(ENOMEM);
            ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
            if (ret < 0)
                av_free(side_data);
            return ret;
6636 6637 6638
        }
    }

6639 6640 6641
    return 0;
}

6642 6643 6644 6645 6646
static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    const int OPUS_SEEK_PREROLL_MS = 80;
    AVStream *st;
    size_t size;
6647
    uint16_t pre_skip;
6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

    if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
        return AVERROR_INVALIDDATA;

    /* Check OpusSpecificBox version. */
    if (avio_r8(pb) != 0) {
        av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
        return AVERROR_INVALIDDATA;
    }

    /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
    size = atom.size + 8;

    if (ff_alloc_extradata(st->codecpar, size))
        return AVERROR(ENOMEM);

    AV_WL32(st->codecpar->extradata, MKTAG('O','p','u','s'));
    AV_WL32(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
    AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
    avio_read(pb, st->codecpar->extradata + 9, size - 9);

    /* OpusSpecificBox is stored in big-endian, but OpusHead is
       little-endian; aside from the preceeding magic and version they're
       otherwise currently identical.  Data after output gain at offset 16
       doesn't need to be bytewapped. */
    pre_skip = AV_RB16(st->codecpar->extradata + 10);
    AV_WL16(st->codecpar->extradata + 10, pre_skip);
    AV_WL32(st->codecpar->extradata + 12, AV_RB32(st->codecpar->extradata + 12));
    AV_WL16(st->codecpar->extradata + 16, AV_RB16(st->codecpar->extradata + 16));

    st->codecpar->initial_padding = pre_skip;
    st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
                                              (AVRational){1, 1000},
                                              (AVRational){1, 48000});

    return 0;
}

6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721
static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    AVStream *st;
    unsigned format_info;
    int channel_assignment, channel_assignment1, channel_assignment2;
    int ratebits;

    if (c->fc->nb_streams < 1)
        return 0;
    st = c->fc->streams[c->fc->nb_streams-1];

    if (atom.size < 10)
        return AVERROR_INVALIDDATA;

    format_info = avio_rb32(pb);

    ratebits            = (format_info >> 28) & 0xF;
    channel_assignment1 = (format_info >> 15) & 0x1F;
    channel_assignment2 = format_info & 0x1FFF;
    if (channel_assignment2)
        channel_assignment = channel_assignment2;
    else
        channel_assignment = channel_assignment1;

    st->codecpar->frame_size = 40 << (ratebits & 0x7);
    st->codecpar->sample_rate = mlp_samplerate(ratebits);
    st->codecpar->channels = truehd_channels(channel_assignment);
    st->codecpar->channel_layout = truehd_layout(channel_assignment);

    return 0;
}

6722
static const MOVParseTableEntry mov_default_parse_table[] = {
6723
{ MKTAG('A','C','L','R'), mov_read_aclr },
Carl Eugen Hoyos's avatar
Carl Eugen Hoyos committed
6724
{ MKTAG('A','P','R','G'), mov_read_avid },
Piotr Bandurski's avatar
Piotr Bandurski committed
6725
{ MKTAG('A','A','L','P'), mov_read_avid },
6726
{ MKTAG('A','R','E','S'), mov_read_ares },
6727
{ MKTAG('a','v','s','s'), mov_read_avss },
6728
{ MKTAG('a','v','1','C'), mov_read_av1c },
David Conrad's avatar
David Conrad committed
6729
{ MKTAG('c','h','p','l'), mov_read_chpl },
6730
{ MKTAG('c','o','6','4'), mov_read_stco },
6731
{ MKTAG('c','o','l','r'), mov_read_colr },
6732 6733
{ MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
{ MKTAG('d','i','n','f'), mov_read_default },
6734
{ MKTAG('D','p','x','E'), mov_read_dpxe },
6735 6736 6737 6738
{ MKTAG('d','r','e','f'), mov_read_dref },
{ MKTAG('e','d','t','s'), mov_read_default },
{ MKTAG('e','l','s','t'), mov_read_elst },
{ MKTAG('e','n','d','a'), mov_read_enda },
6739
{ MKTAG('f','i','e','l'), mov_read_fiel },
6740
{ MKTAG('a','d','r','m'), mov_read_adrm },
6741 6742 6743
{ MKTAG('f','t','y','p'), mov_read_ftyp },
{ MKTAG('g','l','b','l'), mov_read_glbl },
{ MKTAG('h','d','l','r'), mov_read_hdlr },
6744
{ MKTAG('i','l','s','t'), mov_read_ilst },
6745
{ MKTAG('j','p','2','h'), mov_read_jp2h },
6746 6747 6748
{ MKTAG('m','d','a','t'), mov_read_mdat },
{ MKTAG('m','d','h','d'), mov_read_mdhd },
{ MKTAG('m','d','i','a'), mov_read_default },
6749
{ MKTAG('m','e','t','a'), mov_read_meta },
6750 6751 6752 6753 6754
{ MKTAG('m','i','n','f'), mov_read_default },
{ MKTAG('m','o','o','f'), mov_read_moof },
{ MKTAG('m','o','o','v'), mov_read_moov },
{ MKTAG('m','v','e','x'), mov_read_default },
{ MKTAG('m','v','h','d'), mov_read_mvhd },
6755
{ MKTAG('S','M','I',' '), mov_read_svq3 },
6756
{ MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
6757
{ MKTAG('a','v','c','C'), mov_read_glbl },
6758
{ MKTAG('p','a','s','p'), mov_read_pasp },
6759
{ MKTAG('s','i','d','x'), mov_read_sidx },
6760 6761
{ MKTAG('s','t','b','l'), mov_read_default },
{ MKTAG('s','t','c','o'), mov_read_stco },
6762
{ MKTAG('s','t','p','s'), mov_read_stps },
Martin Storsjö's avatar
Martin Storsjö committed
6763
{ MKTAG('s','t','r','f'), mov_read_strf },
6764 6765 6766 6767 6768
{ MKTAG('s','t','s','c'), mov_read_stsc },
{ MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
{ MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
{ MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
{ MKTAG('s','t','t','s'), mov_read_stts },
6769
{ MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
6770
{ MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
Martin Storsjö's avatar
Martin Storsjö committed
6771
{ MKTAG('t','f','d','t'), mov_read_tfdt },
6772 6773 6774
{ MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
{ MKTAG('t','r','a','k'), mov_read_trak },
{ MKTAG('t','r','a','f'), mov_read_default },
6775 6776
{ MKTAG('t','r','e','f'), mov_read_default },
{ MKTAG('t','m','c','d'), mov_read_tmcd },
6777
{ MKTAG('c','h','a','p'), mov_read_chap },
6778 6779
{ MKTAG('t','r','e','x'), mov_read_trex },
{ MKTAG('t','r','u','n'), mov_read_trun },
6780
{ MKTAG('u','d','t','a'), mov_read_default },
6781 6782
{ MKTAG('w','a','v','e'), mov_read_wave },
{ MKTAG('e','s','d','s'), mov_read_esds },
6783
{ MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
6784
{ MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
6785
{ MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
6786
{ MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
6787
{ MKTAG('w','f','e','x'), mov_read_wfex },
6788
{ MKTAG('c','m','o','v'), mov_read_cmov },
6789
{ MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
6790
{ MKTAG('d','v','c','1'), mov_read_dvc1 },
6791
{ MKTAG('s','b','g','p'), mov_read_sbgp },
6792
{ MKTAG('h','v','c','C'), mov_read_glbl },
6793
{ MKTAG('u','u','i','d'), mov_read_uuid },
6794
{ MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
6795
{ MKTAG('f','r','e','e'), mov_read_free },
6796
{ MKTAG('-','-','-','-'), mov_read_custom },
6797 6798 6799
{ MKTAG('s','i','n','f'), mov_read_default },
{ MKTAG('f','r','m','a'), mov_read_frma },
{ MKTAG('s','e','n','c'), mov_read_senc },
6800 6801
{ MKTAG('s','a','i','z'), mov_read_saiz },
{ MKTAG('s','a','i','o'), mov_read_saio },
6802
{ MKTAG('p','s','s','h'), mov_read_pssh },
6803 6804 6805
{ MKTAG('s','c','h','m'), mov_read_schm },
{ MKTAG('s','c','h','i'), mov_read_default },
{ MKTAG('t','e','n','c'), mov_read_tenc },
6806
{ MKTAG('d','f','L','a'), mov_read_dfla },
6807 6808
{ MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
{ MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
6809
{ MKTAG('d','O','p','s'), mov_read_dops },
6810
{ MKTAG('d','m','l','p'), mov_read_dmlp },
6811
{ MKTAG('S','m','D','m'), mov_read_smdm },
6812
{ MKTAG('C','o','L','L'), mov_read_coll },
6813
{ MKTAG('v','p','c','C'), mov_read_vpcc },
6814 6815
{ MKTAG('m','d','c','v'), mov_read_mdcv },
{ MKTAG('c','l','l','i'), mov_read_clli },
Baptiste Coudurier's avatar
Baptiste Coudurier committed
6816
{ 0, NULL }
6817 6818
};

6819 6820 6821 6822 6823 6824
static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
    int64_t total_size = 0;
    MOVAtom a;
    int i;

6825 6826 6827 6828 6829 6830
    if (c->atom_depth > 10) {
        av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
        return AVERROR_INVALIDDATA;
    }
    c->atom_depth ++;

6831 6832
    if (atom.size < 0)
        atom.size = INT64_MAX;
6833
    while (total_size <= atom.size - 8 && !avio_feof(pb)) {
6834 6835 6836 6837 6838 6839
        int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
        a.size = atom.size;
        a.type=0;
        if (atom.size >= 8) {
            a.size = avio_rb32(pb);
            a.type = avio_rl32(pb);
6840 6841
            if (a.type == MKTAG('f','r','e','e') &&
                a.size >= 8 &&
6842
                c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT &&
6843 6844 6845
                c->moov_retry) {
                uint8_t buf[8];
                uint32_t *type = (uint32_t *)buf + 1;
6846 6847
                if (avio_read(pb, buf, 8) != 8)
                    return AVERROR_INVALIDDATA;
6848 6849 6850 6851 6852 6853 6854
                avio_seek(pb, -8, SEEK_CUR);
                if (*type == MKTAG('m','v','h','d') ||
                    *type == MKTAG('c','m','o','v')) {
                    av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free atom.\n");
                    a.type = MKTAG('m','o','o','v');
                }
            }
6855 6856 6857 6858 6859 6860 6861
            if (atom.type != MKTAG('r','o','o','t') &&
                atom.type != MKTAG('m','o','o','v'))
            {
                if (a.type == MKTAG('t','r','a','k') || a.type == MKTAG('m','d','a','t'))
                {
                    av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
                    avio_skip(pb, -8);
6862
                    c->atom_depth --;
6863 6864 6865 6866
                    return 0;
                }
            }
            total_size += 8;
6867
            if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
6868 6869 6870
                a.size = avio_rb64(pb) - 8;
                total_size += 8;
            }
6871
        }
6872 6873
        av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
               av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
6874
        if (a.size == 0) {
6875
            a.size = atom.size - total_size + 8;
6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892
        }
        a.size -= 8;
        if (a.size < 0)
            break;
        a.size = FFMIN(a.size, atom.size - total_size);

        for (i = 0; mov_default_parse_table[i].type; i++)
            if (mov_default_parse_table[i].type == a.type) {
                parse = mov_default_parse_table[i].parse;
                break;
            }

        // container is user data
        if (!parse && (atom.type == MKTAG('u','d','t','a') ||
                       atom.type == MKTAG('i','l','s','t')))
            parse = mov_read_udta_string;

6893 6894 6895 6896 6897 6898 6899 6900
        // Supports parsing the QuickTime Metadata Keys.
        // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
        if (!parse && c->found_hdlr_mdta &&
            atom.type == MKTAG('m','e','t','a') &&
            a.type == MKTAG('k','e','y','s')) {
            parse = mov_read_keys;
        }

6901 6902 6903 6904 6905 6906
        if (!parse) { /* skip leaf atoms data */
            avio_skip(pb, a.size);
        } else {
            int64_t start_pos = avio_tell(pb);
            int64_t left;
            int err = parse(c, pb, a);
6907 6908
            if (err < 0) {
                c->atom_depth --;
6909
                return err;
6910
            }
6911
            if (c->found_moov && c->found_mdat &&
6912
                ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
6913
                 start_pos + a.size == avio_size(pb))) {
6914
                if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
6915
                    c->next_root_atom = start_pos + a.size;
6916
                c->atom_depth --;
6917 6918 6919 6920 6921
                return 0;
            }
            left = a.size - avio_tell(pb) + start_pos;
            if (left > 0) /* skip garbage at atom end */
                avio_skip(pb, left);
6922 6923 6924 6925
            else if (left < 0) {
                av_log(c->fc, AV_LOG_WARNING,
                       "overread end of atom '%.4s' by %"PRId64" bytes\n",
                       (char*)&a.type, -left);
6926 6927
                avio_seek(pb, left, SEEK_CUR);
            }
6928 6929 6930 6931 6932 6933 6934 6935
        }

        total_size += a.size;
    }

    if (total_size < atom.size && atom.size < 0x7ffff)
        avio_skip(pb, atom.size - total_size);

6936
    c->atom_depth --;
6937 6938 6939
    return 0;
}

6940
static int mov_probe(const AVProbeData *p)
Fabrice Bellard's avatar
Fabrice Bellard committed
6941
{
6942
    int64_t offset;
6943
    uint32_t tag;
6944
    int score = 0;
6945
    int moov_offset = -1;
6946

Fabrice Bellard's avatar
Fabrice Bellard committed
6947
    /* check file header */
6948
    offset = 0;
6949
    for (;;) {
6950 6951
        /* ignore invalid offset */
        if ((offset + 8) > (unsigned int)p->buf_size)
6952
            break;
6953
        tag = AV_RL32(p->buf + offset + 4);
6954
        switch(tag) {
6955
        /* check for obvious tags */
6956
        case MKTAG('m','o','o','v'):
6957
            moov_offset = offset + 4;
6958 6959 6960
        case MKTAG('m','d','a','t'):
        case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
        case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
6961
        case MKTAG('f','t','y','p'):
6962 6963 6964 6965
            if (AV_RB32(p->buf+offset) < 8 &&
                (AV_RB32(p->buf+offset) != 1 ||
                 offset + 12 > (unsigned int)p->buf_size ||
                 AV_RB64(p->buf+offset + 8) == 0)) {
6966
                score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
6967
            } else if (tag == MKTAG('f','t','y','p') &&
6968 6969 6970
                       (   AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
                        || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
                    )) {
6971
                score = FFMAX(score, 5);
6972 6973 6974
            } else {
                score = AVPROBE_SCORE_MAX;
            }
6975 6976
            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
            break;
6977
        /* those are more common words, so rate then a bit less */
6978 6979 6980 6981 6982
        case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
        case MKTAG('w','i','d','e'):
        case MKTAG('f','r','e','e'):
        case MKTAG('j','u','n','k'):
        case MKTAG('p','i','c','t'):
6983 6984 6985
            score  = FFMAX(score, AVPROBE_SCORE_MAX - 5);
            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
            break;
6986
        case MKTAG(0x82,0x82,0x7f,0x7d):
6987 6988 6989
        case MKTAG('s','k','i','p'):
        case MKTAG('u','u','i','d'):
        case MKTAG('p','r','f','l'):
6990
            /* if we only find those cause probedata is too small at least rate them */
6991
            score  = FFMAX(score, AVPROBE_SCORE_EXTENSION);
6992
            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
6993 6994
            break;
        default:
6995 6996 6997
            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
        }
    }
6998
    if(score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
6999 7000 7001 7002
        /* moov atom in the header - we should make sure that this is not a
         * MOV-packed MPEG-PS */
        offset = moov_offset;

7003 7004 7005 7006 7007 7008 7009 7010
        while(offset < (p->buf_size - 16)){ /* Sufficient space */
               /* We found an actual hdlr atom */
            if(AV_RL32(p->buf + offset     ) == MKTAG('h','d','l','r') &&
               AV_RL32(p->buf + offset +  8) == MKTAG('m','h','l','r') &&
               AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')){
                av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
                /* We found a media handler reference atom describing an
                 * MPEG-PS-in-MOV, return a
7011 7012 7013 7014 7015 7016
                 * low score to force expanding the probe window until
                 * mpegps_probe finds what it needs */
                return 5;
            }else
                /* Keep looking */
                offset+=2;
7017
        }
7018
    }
7019 7020

    return score;
Fabrice Bellard's avatar
Fabrice Bellard committed
7021 7022
}

7023 7024 7025 7026
// must be done after parsing all trak because there's no order requirement
static void mov_read_chapters(AVFormatContext *s)
{
    MOVContext *mov = s->priv_data;
7027
    AVStream *st;
7028 7029
    MOVStreamContext *sc;
    int64_t cur_pos;
7030 7031
    int i, j;
    int chapter_track;
7032

7033
    for (j = 0; j < mov->nb_chapter_tracks; j++) {
Rodger Combs's avatar
Rodger Combs committed
7034 7035 7036 7037 7038 7039 7040 7041 7042 7043
        chapter_track = mov->chapter_tracks[j];
        st = NULL;
        for (i = 0; i < s->nb_streams; i++)
            if (s->streams[i]->id == chapter_track) {
                st = s->streams[i];
                break;
            }
        if (!st) {
            av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
            continue;
7044 7045
        }

Rodger Combs's avatar
Rodger Combs committed
7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058
        sc = st->priv_data;
        cur_pos = avio_tell(sc->pb);

        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
            if (st->nb_index_entries) {
                // Retrieve the first frame, if possible
                AVPacket pkt;
                AVIndexEntry *sample = &st->index_entries[0];
                if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
                    av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
                    goto finish;
                }
7059

Rodger Combs's avatar
Rodger Combs committed
7060 7061
                if (av_get_packet(sc->pb, &pkt, sample->size) < 0)
                    goto finish;
7062

Rodger Combs's avatar
Rodger Combs committed
7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081
                st->attached_pic              = pkt;
                st->attached_pic.stream_index = st->index;
                st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
            }
        } else {
            st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
            st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
            st->discard = AVDISCARD_ALL;
            for (i = 0; i < st->nb_index_entries; i++) {
                AVIndexEntry *sample = &st->index_entries[i];
                int64_t end = i+1 < st->nb_index_entries ? st->index_entries[i+1].timestamp : st->duration;
                uint8_t *title;
                uint16_t ch;
                int len, title_len;

                if (end < sample->timestamp) {
                    av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
                    end = AV_NOPTS_VALUE;
                }
7082

Rodger Combs's avatar
Rodger Combs committed
7083 7084 7085 7086
                if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
                    av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
                    goto finish;
                }
7087

Rodger Combs's avatar
Rodger Combs committed
7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114
                // the first two bytes are the length of the title
                len = avio_rb16(sc->pb);
                if (len > sample->size-2)
                    continue;
                title_len = 2*len + 1;
                if (!(title = av_mallocz(title_len)))
                    goto finish;

                // The samples could theoretically be in any encoding if there's an encd
                // atom following, but in practice are only utf-8 or utf-16, distinguished
                // instead by the presence of a BOM
                if (!len) {
                    title[0] = 0;
                } else {
                    ch = avio_rb16(sc->pb);
                    if (ch == 0xfeff)
                        avio_get_str16be(sc->pb, len, title, title_len);
                    else if (ch == 0xfffe)
                        avio_get_str16le(sc->pb, len, title, title_len);
                    else {
                        AV_WB16(title, ch);
                        if (len == 1 || len == 2)
                            title[len] = 0;
                        else
                            avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
                    }
                }
7115

Rodger Combs's avatar
Rodger Combs committed
7116 7117
                avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
                av_freep(&title);
7118
            }
7119 7120
        }
finish:
Rodger Combs's avatar
Rodger Combs committed
7121
        avio_seek(sc->pb, cur_pos, SEEK_SET);
7122
    }
7123 7124
}

7125
static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
7126
                                             uint32_t value, int flags)
7127
{
7128 7129
    AVTimecode tc;
    char buf[AV_TIMECODE_STR_SIZE];
7130
    AVRational rate = st->avg_frame_rate;
7131 7132 7133
    int ret = av_timecode_init(&tc, rate, flags, 0, s);
    if (ret < 0)
        return ret;
7134
    av_dict_set(&st->metadata, "timecode",
7135
                av_timecode_make_string(&tc, buf, value), 0);
7136 7137 7138
    return 0;
}

7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163
static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
{
    MOVStreamContext *sc = st->priv_data;
    char buf[AV_TIMECODE_STR_SIZE];
    int64_t cur_pos = avio_tell(sc->pb);
    int hh, mm, ss, ff, drop;

    if (!st->nb_index_entries)
        return -1;

    avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
    avio_skip(s->pb, 13);
    hh = avio_r8(s->pb);
    mm = avio_r8(s->pb);
    ss = avio_r8(s->pb);
    drop = avio_r8(s->pb);
    ff = avio_r8(s->pb);
    snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
             hh, mm, ss, drop ? ';' : ':', ff);
    av_dict_set(&st->metadata, "timecode", buf, 0);

    avio_seek(sc->pb, cur_pos, SEEK_SET);
    return 0;
}

7164 7165 7166
static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
{
    MOVStreamContext *sc = st->priv_data;
7167
    int flags = 0;
7168 7169 7170 7171 7172 7173 7174 7175 7176
    int64_t cur_pos = avio_tell(sc->pb);
    uint32_t value;

    if (!st->nb_index_entries)
        return -1;

    avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
    value = avio_rb32(s->pb);

7177 7178 7179 7180
    if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
    if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
    if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;

7181 7182 7183 7184 7185
    /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
     * not the case) and thus assume "frame number format" instead of QT one.
     * No sample with tmcd track can be found with a QT timecode at the moment,
     * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
     * format). */
7186
    parse_timecode_in_framenum_format(s, st, value, flags);
7187 7188 7189 7190 7191

    avio_seek(sc->pb, cur_pos, SEEK_SET);
    return 0;
}

7192 7193 7194 7195 7196 7197 7198
static void mov_free_encryption_index(MOVEncryptionIndex **index) {
    int i;
    if (!index || !*index) return;
    for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
        av_encryption_info_free((*index)->encrypted_samples[i]);
    }
    av_freep(&(*index)->encrypted_samples);
7199 7200
    av_freep(&(*index)->auxiliary_info_sizes);
    av_freep(&(*index)->auxiliary_offsets);
7201 7202 7203
    av_freep(index);
}

7204 7205 7206 7207 7208 7209 7210 7211 7212
static int mov_read_close(AVFormatContext *s)
{
    MOVContext *mov = s->priv_data;
    int i, j;

    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MOVStreamContext *sc = st->priv_data;

7213 7214 7215
        if (!sc)
            continue;

7216 7217 7218 7219 7220 7221
        av_freep(&sc->ctts_data);
        for (j = 0; j < sc->drefs_count; j++) {
            av_freep(&sc->drefs[j].path);
            av_freep(&sc->drefs[j].dir);
        }
        av_freep(&sc->drefs);
7222 7223 7224

        sc->drefs_count = 0;

7225
        if (!sc->pb_is_copied)
7226
            ff_format_io_close(s, &sc->pb);
7227

7228
        sc->pb = NULL;
7229 7230
        av_freep(&sc->chunk_offsets);
        av_freep(&sc->stsc_data);
7231 7232
        av_freep(&sc->sample_sizes);
        av_freep(&sc->keyframes);
7233
        av_freep(&sc->stts_data);
7234
        av_freep(&sc->stps_data);
7235
        av_freep(&sc->elst_data);
7236
        av_freep(&sc->rap_group);
7237
        av_freep(&sc->display_matrix);
7238
        av_freep(&sc->index_ranges);
7239

7240 7241 7242
        if (sc->extradata)
            for (j = 0; j < sc->stsd_count; j++)
                av_free(sc->extradata[j]);
7243 7244
        av_freep(&sc->extradata);
        av_freep(&sc->extradata_size);
7245

7246 7247
        mov_free_encryption_index(&sc->cenc.encryption_index);
        av_encryption_info_free(sc->cenc.default_encrypted_sample);
7248
        av_aes_ctr_free(sc->cenc.aes_ctr);
7249 7250 7251

        av_freep(&sc->stereo3d);
        av_freep(&sc->spherical);
7252
        av_freep(&sc->mastering);
7253
        av_freep(&sc->coll);
7254 7255 7256
    }

    if (mov->dv_demux) {
7257 7258
        avformat_free_context(mov->dv_fctx);
        mov->dv_fctx = NULL;
7259 7260
    }

7261 7262 7263 7264 7265 7266 7267
    if (mov->meta_keys) {
        for (i = 1; i < mov->meta_keys_count; i++) {
            av_freep(&mov->meta_keys[i]);
        }
        av_freep(&mov->meta_keys);
    }

7268
    av_freep(&mov->trex_data);
7269
    av_freep(&mov->bitrates);
7270

7271
    for (i = 0; i < mov->frag_index.nb_items; i++) {
7272 7273 7274 7275
        MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
        for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
            mov_free_encryption_index(&frag[j].encryption_index);
        }
7276
        av_freep(&mov->frag_index.item[i].stream_info);
7277
    }
7278
    av_freep(&mov->frag_index.item);
7279

7280
    av_freep(&mov->aes_decrypt);
7281
    av_freep(&mov->chapter_tracks);
7282

7283 7284 7285
    return 0;
}

7286 7287
static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
{
7288
    int i;
7289 7290 7291 7292 7293

    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MOVStreamContext *sc = st->priv_data;

7294
        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7295 7296
            sc->timecode_track == tmcd_id)
            return 1;
7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308
    }
    return 0;
}

/* look for a tmcd track not referenced by any video track, and export it globally */
static void export_orphan_timecode(AVFormatContext *s)
{
    int i;

    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];

7309
        if (st->codecpar->codec_tag  == MKTAG('t','m','c','d') &&
7310 7311 7312 7313 7314 7315 7316 7317 7318 7319
            !tmcd_is_referenced(s, i + 1)) {
            AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
            if (tcr) {
                av_dict_set(&s->metadata, "timecode", tcr->value, 0);
                break;
            }
        }
    }
}

7320 7321
static int read_tfra(MOVContext *mov, AVIOContext *f)
{
7322
    int version, fieldlength, i, j;
7323 7324
    int64_t pos = avio_tell(f);
    uint32_t size = avio_rb32(f);
7325
    unsigned track_id, item_count;
7326

7327
    if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
7328
        return 1;
7329 7330 7331 7332 7333
    }
    av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");

    version = avio_r8(f);
    avio_rb24(f);
7334
    track_id = avio_rb32(f);
7335
    fieldlength = avio_rb32(f);
7336 7337
    item_count = avio_rb32(f);
    for (i = 0; i < item_count; i++) {
7338
        int64_t time, offset;
7339 7340
        int index;
        MOVFragmentStreamInfo * frag_stream_info;
7341 7342 7343 7344 7345

        if (avio_feof(f)) {
            return AVERROR_INVALIDDATA;
        }

7346 7347 7348 7349 7350 7351 7352
        if (version == 1) {
            time   = avio_rb64(f);
            offset = avio_rb64(f);
        } else {
            time   = avio_rb32(f);
            offset = avio_rb32(f);
        }
7353 7354 7355 7356 7357 7358 7359 7360 7361 7362

        // The first sample of each stream in a fragment is always a random
        // access sample.  So it's entry in the tfra can be used as the
        // initial PTS of the fragment.
        index = update_frag_index(mov, offset);
        frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
        if (frag_stream_info &&
            frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
            frag_stream_info->first_tfra_pts = time;

7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378
        for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
            avio_r8(f);
        for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
            avio_r8(f);
        for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
            avio_r8(f);
    }

    avio_seek(f, pos + size, SEEK_SET);
    return 0;
}

static int mov_read_mfra(MOVContext *c, AVIOContext *f)
{
    int64_t stream_size = avio_size(f);
    int64_t original_pos = avio_tell(f);
7379
    int64_t seek_ret;
7380 7381
    int32_t mfra_size;
    int ret = -1;
7382 7383 7384 7385
    if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
        ret = seek_ret;
        goto fail;
    }
7386 7387 7388 7389 7390
    mfra_size = avio_rb32(f);
    if (mfra_size < 0 || mfra_size > stream_size) {
        av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
        goto fail;
    }
7391 7392 7393 7394
    if ((seek_ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) {
        ret = seek_ret;
        goto fail;
    }
7395 7396 7397 7398 7399 7400 7401 7402 7403
    if (avio_rb32(f) != mfra_size) {
        av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
        goto fail;
    }
    if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
        av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
        goto fail;
    }
    av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
7404 7405 7406 7407 7408 7409
    do {
        ret = read_tfra(c, f);
        if (ret < 0)
            goto fail;
    } while (!ret);
    ret = 0;
7410
fail:
7411 7412
    seek_ret = avio_seek(f, original_pos, SEEK_SET);
    if (seek_ret < 0) {
7413 7414
        av_log(c->fc, AV_LOG_ERROR,
               "failed to seek back after looking for mfra\n");
7415 7416
        ret = seek_ret;
    }
7417 7418 7419
    return ret;
}

7420
static int mov_read_header(AVFormatContext *s)
7421
{
7422
    MOVContext *mov = s->priv_data;
7423
    AVIOContext *pb = s->pb;
7424
    int j, err;
7425
    MOVAtom atom = { AV_RL32("root") };
7426
    int i;
7427

7428 7429 7430 7431 7432 7433
    if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
        av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
            mov->decryption_key_len, AES_CTR_KEY_SIZE);
        return AVERROR(EINVAL);
    }

7434
    mov->fc = s;
7435
    mov->trak_index = -1;
7436
    /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
7437
    if (pb->seekable & AVIO_SEEKABLE_NORMAL)
7438
        atom.size = avio_size(pb);
7439
    else
Baptiste Coudurier's avatar
Baptiste Coudurier committed
7440
        atom.size = INT64_MAX;
7441 7442

    /* check MOV header */
7443
    do {
7444 7445 7446 7447 7448 7449 7450
        if (mov->moov_retry)
            avio_seek(pb, 0, SEEK_SET);
        if ((err = mov_read_default(mov, pb, atom)) < 0) {
            av_log(s, AV_LOG_ERROR, "error reading header\n");
            mov_read_close(s);
            return err;
        }
James Almer's avatar
James Almer committed
7451
    } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++);
7452 7453
    if (!mov->found_moov) {
        av_log(s, AV_LOG_ERROR, "moov atom not found\n");
7454
        mov_read_close(s);
7455
        return AVERROR_INVALIDDATA;
7456
    }
7457
    av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
7458

James Almer's avatar
James Almer committed
7459
    if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
7460
        if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
7461 7462
            mov_read_chapters(s);
        for (i = 0; i < s->nb_streams; i++)
7463
            if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
7464
                mov_read_timecode_track(s, s->streams[i]);
7465 7466 7467
            } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
                mov_read_rtmd_track(s, s->streams[i]);
            }
7468
    }
7469

7470 7471 7472 7473
    /* copy timecode metadata from tmcd tracks to the related video streams */
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MOVStreamContext *sc = st->priv_data;
7474
        if (sc->timecode_track > 0) {
7475
            AVDictionaryEntry *tcr;
7476
            int tmcd_st_id = -1;
7477

7478 7479 7480 7481
            for (j = 0; j < s->nb_streams; j++)
                if (s->streams[j]->id == sc->timecode_track)
                    tmcd_st_id = j;

7482
            if (tmcd_st_id < 0 || tmcd_st_id == i)
7483 7484 7485 7486 7487 7488
                continue;
            tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
            if (tcr)
                av_dict_set(&st->metadata, "timecode", tcr->value, 0);
        }
    }
7489
    export_orphan_timecode(s);
7490

7491 7492 7493
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MOVStreamContext *sc = st->priv_data;
7494
        fix_timescale(mov, sc);
7495
        if(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id == AV_CODEC_ID_AAC) {
7496 7497
            st->skip_samples = sc->start_pad;
        }
7498
        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
7499
            av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
7500
                      sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
7501 7502 7503 7504
        if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
            if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
                st->codecpar->width  = sc->width;
                st->codecpar->height = sc->height;
7505
            }
7506
            if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
7507 7508 7509
                if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
                    return err;
            }
7510
        }
7511
        if (mov->handbrake_version &&
7512
            mov->handbrake_version <= 1000000*0 + 1000*10 + 2 &&  // 0.10.2
7513
            st->codecpar->codec_id == AV_CODEC_ID_MP3
7514 7515 7516 7517
        ) {
            av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
            st->need_parsing = AVSTREAM_PARSE_FULL;
        }
7518 7519
    }

7520 7521 7522 7523
    if (mov->trex_data) {
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st = s->streams[i];
            MOVStreamContext *sc = st->priv_data;
7524 7525 7526 7527 7528 7529 7530
            if (st->duration > 0) {
                if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
                    av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
                           sc->data_size, sc->time_scale);
                    mov_read_close(s);
                    return AVERROR_INVALIDDATA;
                }
7531
                st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration;
7532
            }
7533 7534 7535
        }
    }

7536 7537 7538 7539 7540
    if (mov->use_mfra_for > 0) {
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st = s->streams[i];
            MOVStreamContext *sc = st->priv_data;
            if (sc->duration_for_fps > 0) {
7541 7542 7543 7544 7545 7546
                if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
                    av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
                           sc->data_size, sc->time_scale);
                    mov_read_close(s);
                    return AVERROR_INVALIDDATA;
                }
7547
                st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale /
7548 7549 7550 7551 7552
                    sc->duration_for_fps;
            }
        }
    }

7553 7554
    for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
        if (mov->bitrates[i]) {
7555
            s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
7556 7557 7558
        }
    }

7559 7560
    ff_rfps_calculate(s);

7561 7562
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
7563
        MOVStreamContext *sc = st->priv_data;
7564

7565
        switch (st->codecpar->codec_type) {
7566 7567 7568 7569 7570 7571 7572 7573 7574
        case AVMEDIA_TYPE_AUDIO:
            err = ff_replaygain_export(st, s->metadata);
            if (err < 0) {
                mov_read_close(s);
                return err;
            }
            break;
        case AVMEDIA_TYPE_VIDEO:
            if (sc->display_matrix) {
7575
                err = av_stream_add_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, (uint8_t*)sc->display_matrix,
7576
                                              sizeof(int32_t) * 9);
7577 7578
                if (err < 0)
                    return err;
7579 7580 7581

                sc->display_matrix = NULL;
            }
7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599
            if (sc->stereo3d) {
                err = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D,
                                              (uint8_t *)sc->stereo3d,
                                              sizeof(*sc->stereo3d));
                if (err < 0)
                    return err;

                sc->stereo3d = NULL;
            }
            if (sc->spherical) {
                err = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL,
                                              (uint8_t *)sc->spherical,
                                              sc->spherical_size);
                if (err < 0)
                    return err;

                sc->spherical = NULL;
            }
7600 7601 7602 7603 7604 7605 7606 7607 7608
            if (sc->mastering) {
                err = av_stream_add_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
                                              (uint8_t *)sc->mastering,
                                              sizeof(*sc->mastering));
                if (err < 0)
                    return err;

                sc->mastering = NULL;
            }
7609 7610 7611 7612 7613 7614 7615 7616 7617
            if (sc->coll) {
                err = av_stream_add_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
                                              (uint8_t *)sc->coll,
                                              sc->coll_size);
                if (err < 0)
                    return err;

                sc->coll = NULL;
            }
7618
            break;
7619 7620
        }
    }
7621
    ff_configure_buffers_for_index(s, AV_TIME_BASE);
7622

7623 7624 7625
    for (i = 0; i < mov->frag_index.nb_items; i++)
        if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
            mov->frag_index.item[i].headers_read = 1;
7626

7627 7628 7629
    return 0;
}

7630
static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
7631
{
7632
    AVIndexEntry *sample = NULL;
7633
    int64_t best_dts = INT64_MAX;
7634
    int i;
7635
    for (i = 0; i < s->nb_streams; i++) {
7636 7637
        AVStream *avst = s->streams[i];
        MOVStreamContext *msc = avst->priv_data;
7638
        if (msc->pb && msc->current_sample < avst->nb_index_entries) {
7639
            AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
7640
            int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
7641
            av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
7642 7643
            if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
                ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7644
                 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb &&
7645
                 ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
7646
                  (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
7647 7648
                sample = current_sample;
                best_dts = dts;
7649
                *st = avst;
7650
            }
7651 7652
        }
    }
7653 7654 7655
    return sample;
}

7656 7657 7658 7659 7660 7661 7662
static int should_retry(AVIOContext *pb, int error_code) {
    if (error_code == AVERROR_EOF || avio_feof(pb))
        return 0;

    return 1;
}

7663
static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
7664
{
7665
    int ret;
7666 7667
    MOVContext *mov = s->priv_data;

7668 7669
    if (index >= 0 && index < mov->frag_index.nb_items)
        target = mov->frag_index.item[index].moof_offset;
7670 7671 7672 7673 7674 7675
    if (avio_seek(s->pb, target, SEEK_SET) != target) {
        av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
        return AVERROR_INVALIDDATA;
    }

    mov->next_root_atom = 0;
7676 7677 7678 7679 7680 7681 7682 7683
    if (index < 0 || index >= mov->frag_index.nb_items)
        index = search_frag_moof_offset(&mov->frag_index, target);
    if (index < mov->frag_index.nb_items) {
        if (index + 1 < mov->frag_index.nb_items)
            mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
        if (mov->frag_index.item[index].headers_read)
            return 0;
        mov->frag_index.item[index].headers_read = 1;
7684 7685 7686 7687
    }

    mov->found_mdat = 0;

7688 7689 7690 7691
    ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
    if (ret < 0)
        return ret;
    if (avio_feof(s->pb))
7692 7693 7694 7695 7696 7697
        return AVERROR_EOF;
    av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));

    return 1;
}

7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720
static int mov_change_extradata(MOVStreamContext *sc, AVPacket *pkt)
{
    uint8_t *side, *extradata;
    int extradata_size;

    /* Save the current index. */
    sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;

    /* Notify the decoder that extradata changed. */
    extradata_size = sc->extradata_size[sc->last_stsd_index];
    extradata = sc->extradata[sc->last_stsd_index];
    if (extradata_size > 0 && extradata) {
        side = av_packet_new_side_data(pkt,
                                       AV_PKT_DATA_NEW_EXTRADATA,
                                       extradata_size);
        if (!side)
            return AVERROR(ENOMEM);
        memcpy(side, extradata, extradata_size);
    }

    return 0;
}

7721 7722 7723 7724 7725 7726
static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    MOVContext *mov = s->priv_data;
    MOVStreamContext *sc;
    AVIndexEntry *sample;
    AVStream *st = NULL;
7727
    int64_t current_index;
7728
    int ret;
7729
    mov->fc = s;
7730 7731
 retry:
    sample = mov_find_next_sample(s, &st);
7732
    if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
7733 7734
        if (!mov->next_root_atom)
            return AVERROR_EOF;
7735
        if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
7736
            return ret;
7737 7738
        goto retry;
    }
7739
    sc = st->priv_data;
7740
    /* must be done just before reading, to avoid infinite loop on sample */
7741 7742
    current_index = sc->current_index;
    mov_current_sample_inc(sc);
7743

7744 7745 7746 7747 7748
    if (mov->next_root_atom) {
        sample->pos = FFMIN(sample->pos, mov->next_root_atom);
        sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
    }

7749
    if (st->discard != AVDISCARD_ALL) {
7750 7751
        int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
        if (ret64 != sample->pos) {
7752 7753
            av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
                   sc->ffindex, sample->pos);
7754 7755 7756
            if (should_retry(sc->pb, ret64)) {
                mov_current_sample_dec(sc);
            }
7757
            return AVERROR_INVALIDDATA;
7758
        }
7759 7760 7761 7762 7763 7764

        if( st->discard == AVDISCARD_NONKEY && 0==(sample->flags & AVINDEX_KEYFRAME) ) {
            av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
            goto retry;
        }

7765
        ret = av_get_packet(sc->pb, pkt, sample->size);
7766
        if (ret < 0) {
7767 7768 7769
            if (should_retry(sc->pb, ret)) {
                mov_current_sample_dec(sc);
            }
7770
            return ret;
7771
        }
7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782
        if (sc->has_palette) {
            uint8_t *pal;

            pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
            if (!pal) {
                av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
            } else {
                memcpy(pal, sc->palette, AVPALETTE_SIZE);
                sc->has_palette = 0;
            }
        }
7783 7784
#if CONFIG_DV_DEMUXER
        if (mov->dv_demux && sc->dv_audio_container) {
7785
            avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
7786
            av_freep(&pkt->data);
7787
            pkt->size = 0;
7788
            ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
7789 7790 7791
            if (ret < 0)
                return ret;
        }
7792
#endif
7793 7794 7795 7796
        if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !st->need_parsing && pkt->size > 4) {
            if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
                st->need_parsing = AVSTREAM_PARSE_FULL;
        }
7797 7798
    }

7799
    pkt->stream_index = sc->ffindex;
7800
    pkt->dts = sample->timestamp;
7801 7802 7803
    if (sample->flags & AVINDEX_DISCARD_FRAME) {
        pkt->flags |= AV_PKT_FLAG_DISCARD;
    }
7804
    if (sc->ctts_data && sc->ctts_index < sc->ctts_count) {
7805
        pkt->pts = pkt->dts + sc->dts_shift + sc->ctts_data[sc->ctts_index].duration;
7806
        /* update ctts context */
7807 7808 7809 7810 7811
        sc->ctts_sample++;
        if (sc->ctts_index < sc->ctts_count &&
            sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) {
            sc->ctts_index++;
            sc->ctts_sample = 0;
7812
        }
7813
    } else {
7814
        int64_t next_dts = (sc->current_sample < st->nb_index_entries) ?
7815
            st->index_entries[sc->current_sample].timestamp : st->duration;
7816 7817 7818

        if (next_dts >= pkt->dts)
            pkt->duration = next_dts - pkt->dts;
7819
        pkt->pts = pkt->dts;
7820
    }
7821 7822
    if (st->discard == AVDISCARD_ALL)
        goto retry;
7823
    pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
7824
    pkt->pos = sample->pos;
7825

7826 7827 7828 7829 7830
    /* Multiple stsd handling. */
    if (sc->stsc_data) {
        /* Keep track of the stsc index for the given sample, then check
        * if the stsd index is different from the last used one. */
        sc->stsc_sample++;
7831
        if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
7832 7833 7834 7835
            mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
            sc->stsc_index++;
            sc->stsc_sample = 0;
        /* Do not check indexes after a switch. */
7836 7837 7838
        } else if (sc->stsc_data[sc->stsc_index].id > 0 &&
                   sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
                   sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
7839 7840 7841 7842 7843 7844
            ret = mov_change_extradata(sc, pkt);
            if (ret < 0)
                return ret;
        }
    }

7845 7846 7847
    if (mov->aax_mode)
        aax_filter(pkt->data, pkt->size, mov);

7848
    ret = cenc_filter(mov, st, sc, pkt, current_index);
7849 7850
    if (ret < 0) {
        av_packet_unref(pkt);
7851
        return ret;
7852
    }
7853

7854 7855
    return 0;
}
7856

7857 7858 7859
static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
{
    MOVContext *mov = s->priv_data;
7860
    int index;
7861

7862
    if (!mov->frag_index.complete)
7863 7864
        return 0;

7865 7866 7867 7868 7869 7870 7871
    index = search_frag_timestamp(&mov->frag_index, st, timestamp);
    if (index < 0)
        index = 0;
    if (!mov->frag_index.item[index].headers_read)
        return mov_switch_root(s, -1, index);
    if (index + 1 < mov->frag_index.nb_items)
        mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
7872 7873 7874 7875

    return 0;
}

7876
static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
7877 7878
{
    MOVStreamContext *sc = st->priv_data;
7879
    int sample, time_sample, ret;
7880
    unsigned int i;
7881

7882 7883 7884
    // Here we consider timestamp to be PTS, hence try to offset it so that we
    // can search over the DTS timeline.
    timestamp -= (sc->min_corrected_pts + sc->dts_shift);
7885 7886

    ret = mov_seek_fragment(s, st, timestamp);
7887 7888 7889
    if (ret < 0)
        return ret;

7890
    sample = av_index_search_timestamp(st, timestamp, flags);
7891
    av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
7892 7893
    if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
        sample = 0;
7894
    if (sample < 0) /* not sure what to do */
7895
        return AVERROR_INVALIDDATA;
7896
    mov_current_sample_set(sc, sample);
7897
    av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
7898 7899 7900 7901
    /* adjust ctts index */
    if (sc->ctts_data) {
        time_sample = 0;
        for (i = 0; i < sc->ctts_count; i++) {
7902 7903
            int next = time_sample + sc->ctts_data[i].count;
            if (next > sc->current_sample) {
7904 7905
                sc->ctts_index = i;
                sc->ctts_sample = sc->current_sample - time_sample;
7906
                break;
7907
            }
7908
            time_sample = next;
7909 7910
        }
    }
7911

7912
    /* adjust stsd index */
7913
    if (sc->chunk_count) {
7914 7915
    time_sample = 0;
    for (i = 0; i < sc->stsc_count; i++) {
7916
        int64_t next = time_sample + mov_get_stsc_samples(sc, i);
7917 7918 7919 7920 7921
        if (next > sc->current_sample) {
            sc->stsc_index = i;
            sc->stsc_sample = sc->current_sample - time_sample;
            break;
        }
7922
        av_assert0(next == (int)next);
7923 7924
        time_sample = next;
    }
7925
    }
7926

7927
    return sample;
7928 7929
}

7930
static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
7931
{
7932
    MOVContext *mc = s->priv_data;
7933 7934 7935
    AVStream *st;
    int sample;
    int i;
7936

7937
    if (stream_index >= s->nb_streams)
7938
        return AVERROR_INVALIDDATA;
7939

7940
    st = s->streams[stream_index];
7941
    sample = mov_seek_stream(s, st, sample_time, flags);
7942
    if (sample < 0)
7943
        return sample;
7944

7945 7946 7947
    if (mc->seek_individually) {
        /* adjust seek timestamp to found sample timestamp */
        int64_t seek_timestamp = st->index_entries[sample].timestamp;
7948

7949 7950 7951 7952 7953
        for (i = 0; i < s->nb_streams; i++) {
            int64_t timestamp;
            MOVStreamContext *sc = s->streams[i]->priv_data;
            st = s->streams[i];
            st->skip_samples = (sample_time <= 0) ? sc->start_pad : 0;
7954

7955 7956
            if (stream_index == i)
                continue;
7957

7958 7959 7960 7961 7962 7963 7964 7965
            timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
            mov_seek_stream(s, st, timestamp, flags);
        }
    } else {
        for (i = 0; i < s->nb_streams; i++) {
            MOVStreamContext *sc;
            st = s->streams[i];
            sc = st->priv_data;
7966
            mov_current_sample_set(sc, 0);
7967 7968 7969 7970 7971 7972 7973 7974 7975
        }
        while (1) {
            MOVStreamContext *sc;
            AVIndexEntry *entry = mov_find_next_sample(s, &st);
            if (!entry)
                return AVERROR_INVALIDDATA;
            sc = st->priv_data;
            if (sc->ffindex == stream_index && sc->current_sample == sample)
                break;
7976
            mov_current_sample_inc(sc);
7977
        }
7978
    }
7979 7980 7981
    return 0;
}

7982 7983 7984
#define OFFSET(x) offsetof(MOVContext, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption mov_options[] = {
7985 7986
    {"use_absolute_path",
        "allow using absolute path when opening alias, this is a possible security issue",
7987
        OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
7988
        0, 1, FLAGS},
7989 7990
    {"seek_streams_individually",
        "Seek each stream individually to the to the closest point",
7991
        OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
7992
        0, 1, FLAGS},
7993 7994 7995 7996 7997
    {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
        0, 1, FLAGS},
    {"advanced_editlist",
        "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
        OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
7998
        0, 1, FLAGS},
7999 8000
    {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
        0, 1, FLAGS},
8001 8002
    {"use_mfra_for",
        "use mfra for fragment timestamps",
8003
        OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
8004
        -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
8005
        "use_mfra_for"},
8006
    {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
8007
        FLAGS, "use_mfra_for" },
8008
    {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
8009
        FLAGS, "use_mfra_for" },
8010
    {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
8011
        FLAGS, "use_mfra_for" },
8012
    { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
8013
        AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8014
    { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
8015
        AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8016 8017 8018 8019 8020 8021
    { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
        AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
    { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
        "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
        AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
        .flags = AV_OPT_FLAG_DECODING_PARAM },
8022
    { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8023 8024
    { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
        {.i64 = 0}, 0, 1, FLAGS },
8025

8026
    { NULL },
8027 8028
};

8029
static const AVClass mov_class = {
8030 8031
    .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
    .item_name  = av_default_item_name,
8032
    .option     = mov_options,
8033 8034
    .version    = LIBAVUTIL_VERSION_INT,
};
8035

8036
AVInputFormat ff_mov_demuxer = {
8037
    .name           = "mov,mp4,m4a,3gp,3g2,mj2",
8038
    .long_name      = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8039
    .priv_class     = &mov_class,
8040
    .priv_data_size = sizeof(MOVContext),
8041
    .extensions     = "mov,mp4,m4a,3gp,3g2,mj2",
8042 8043 8044 8045 8046
    .read_probe     = mov_probe,
    .read_header    = mov_read_header,
    .read_packet    = mov_read_packet,
    .read_close     = mov_read_close,
    .read_seek      = mov_read_seek,
8047
    .flags          = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS,
8048
};