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

23
#include "libavutil/avstring.h"
24
#include "libavutil/bswap.h"
25
#include "libavutil/dict.h"
26
#include "libavutil/mathematics.h"
27
#include "libavutil/tree.h"
28
#include "avio_internal.h"
29 30 31 32 33
#include "nut.h"

#undef NDEBUG
#include <assert.h>

34 35
#define NUT_MAX_STREAMS 256    /* arbitrary sanity check value */

36 37 38
static int get_str(AVIOContext *bc, char *string, unsigned int maxlen)
{
    unsigned int len = ffio_read_varlen(bc);
39

40
    if (len && maxlen)
41
        avio_read(bc, string, FFMIN(len, maxlen));
42
    while (len > maxlen) {
43
        avio_r8(bc);
44 45 46
        len--;
    }

47 48
    if (maxlen)
        string[FFMIN(len, maxlen - 1)] = 0;
49

50
    if (maxlen == len)
51 52 53 54 55
        return -1;
    else
        return 0;
}

56 57
static int64_t get_s(AVIOContext *bc)
{
58
    int64_t v = ffio_read_varlen(bc) + 1;
59

60 61 62 63
    if (v & 1)
        return -(v >> 1);
    else
        return  (v >> 1);
64 65
}

66 67 68
static uint64_t get_fourcc(AVIOContext *bc)
{
    unsigned int len = ffio_read_varlen(bc);
69

70 71 72 73 74 75
    if (len == 2)
        return avio_rl16(bc);
    else if (len == 4)
        return avio_rl32(bc);
    else
        return -1;
76 77 78
}

#ifdef TRACE
79 80 81 82
static inline uint64_t get_v_trace(AVIOContext *bc, char *file,
                                   char *func, int line)
{
    uint64_t v = ffio_read_varlen(bc);
83

84 85
    av_log(NULL, AV_LOG_DEBUG, "get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n",
           v, v, file, func, line);
86 87 88
    return v;
}

89 90 91 92
static inline int64_t get_s_trace(AVIOContext *bc, char *file,
                                  char *func, int line)
{
    int64_t v = get_s(bc);
93

94 95
    av_log(NULL, AV_LOG_DEBUG, "get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n",
           v, v, file, func, line);
96 97 98
    return v;
}

99 100 101 102
static inline uint64_t get_vb_trace(AVIOContext *bc, char *file,
                                    char *func, int line)
{
    uint64_t v = get_vb(bc);
103

104 105
    av_log(NULL, AV_LOG_DEBUG, "get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n",
           v, v, file, func, line);
106 107
    return v;
}
108 109 110
#define ffio_read_varlen(bc) get_v_trace(bc,  __FILE__, __PRETTY_FUNCTION__, __LINE__)
#define get_s(bc)            get_s_trace(bc,  __FILE__, __PRETTY_FUNCTION__, __LINE__)
#define get_vb(bc)           get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
111 112
#endif

113 114
static int get_packetheader(NUTContext *nut, AVIOContext *bc,
                            int calculate_checksum, uint64_t startcode)
115
{
116
    int64_t size;
117
//    start = avio_tell(bc) - 8;
118

119 120
    startcode = av_be2ne64(startcode);
    startcode = ff_crc04C11DB7_update(0, (uint8_t*) &startcode, 8);
121

122
    ffio_init_checksum(bc, ff_crc04C11DB7_update, startcode);
123 124
    size = ffio_read_varlen(bc);
    if (size > 4096)
125
        avio_rb32(bc);
126
    if (ffio_get_checksum(bc) && size > 4096)
Michael Niedermayer's avatar
Michael Niedermayer committed
127
        return -1;
128

129
    ffio_init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0);
130 131 132 133

    return size;
}

134 135 136 137 138 139 140 141
static uint64_t find_any_startcode(AVIOContext *bc, int64_t pos)
{
    uint64_t state = 0;

    if (pos >= 0)
        /* Note, this may fail if the stream is not seekable, but that should
         * not matter, as in this case we simply start where we currently are */
        avio_seek(bc, pos, SEEK_SET);
142
    while (!url_feof(bc)) {
143 144
        state = (state << 8) | avio_r8(bc);
        if ((state >> 56) != 'N')
145
            continue;
146
        switch (state) {
147 148 149 150 151 152 153 154 155 156 157 158 159
        case MAIN_STARTCODE:
        case STREAM_STARTCODE:
        case SYNCPOINT_STARTCODE:
        case INFO_STARTCODE:
        case INDEX_STARTCODE:
            return state;
        }
    }

    return 0;
}

/**
160
 * Find the given startcode.
161 162
 * @param code the startcode
 * @param pos the start position of the search, or -1 if the current position
163
 * @return the position of the startcode or -1 if not found
164
 */
165 166 167 168 169
static int64_t find_startcode(AVIOContext *bc, uint64_t code, int64_t pos)
{
    for (;;) {
        uint64_t startcode = find_any_startcode(bc, pos);
        if (startcode == code)
170
            return avio_tell(bc) - 8;
171
        else if (startcode == 0)
172
            return -1;
173
        pos = -1;
174 175 176
    }
}

177 178
static int nut_probe(AVProbeData *p)
{
179
    int i;
180
    uint64_t code = 0;
181 182 183 184 185 186 187 188 189

    for (i = 0; i < p->buf_size; i++) {
        code = (code << 8) | p->buf[i];
        if (code == MAIN_STARTCODE)
            return AVPROBE_SCORE_MAX;
    }
    return 0;
}

190 191 192 193 194 195 196
#define GET_V(dst, check)                                                 \
    tmp = ffio_read_varlen(bc);                                           \
    if (!(check)) {                                                       \
        av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);  \
        return -1;                                                        \
    }                                                                     \
    dst = tmp;
197

198 199
static int skip_reserved(AVIOContext *bc, int64_t pos)
{
200
    pos -= avio_tell(bc);
201
    if (pos < 0) {
202
        avio_seek(bc, pos, SEEK_CUR);
203
        return -1;
204 205
    } else {
        while (pos--)
206
            avio_r8(bc);
207 208 209 210
        return 0;
    }
}

211 212 213 214
static int decode_main_header(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
215 216
    uint64_t tmp, end;
    unsigned int stream_count;
217 218
    int i, j, count;
    int tmp_stream, tmp_mul, tmp_pts, tmp_size, tmp_res, tmp_head_idx;
219

220
    end  = get_packetheader(nut, bc, 1, MAIN_STARTCODE);
221
    end += avio_tell(bc);
222

223 224
    GET_V(tmp, tmp >= 2 && tmp <= 3)
    GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS)
225

226
    nut->max_distance = ffio_read_varlen(bc);
227
    if (nut->max_distance > 65536) {
228
        av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
229
        nut->max_distance = 65536;
230 231
    }

232 233
    GET_V(nut->time_base_count, tmp > 0 && tmp < INT_MAX / sizeof(AVRational))
    nut->time_base = av_malloc(nut->time_base_count * sizeof(AVRational));
234

235 236 237 238
    for (i = 0; i < nut->time_base_count; i++) {
        GET_V(nut->time_base[i].num, tmp > 0 && tmp < (1ULL << 31))
        GET_V(nut->time_base[i].den, tmp > 0 && tmp < (1ULL << 31))
        if (av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1) {
239
            av_log(s, AV_LOG_ERROR, "time base invalid\n");
240
            return AVERROR_INVALIDDATA;
241 242
        }
    }
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
    tmp_pts      = 0;
    tmp_mul      = 1;
    tmp_stream   = 0;
    tmp_head_idx = 0;
    for (i = 0; i < 256;) {
        int tmp_flags  = ffio_read_varlen(bc);
        int tmp_fields = ffio_read_varlen(bc);

        if (tmp_fields > 0)
            tmp_pts = get_s(bc);
        if (tmp_fields > 1)
            tmp_mul = ffio_read_varlen(bc);
        if (tmp_fields > 2)
            tmp_stream = ffio_read_varlen(bc);
        if (tmp_fields > 3)
            tmp_size = ffio_read_varlen(bc);
        else
            tmp_size = 0;
        if (tmp_fields > 4)
            tmp_res = ffio_read_varlen(bc);
        else
            tmp_res = 0;
        if (tmp_fields > 5)
            count = ffio_read_varlen(bc);
        else
            count = tmp_mul - tmp_size;
        if (tmp_fields > 6)
            get_s(bc);
        if (tmp_fields > 7)
            tmp_head_idx = ffio_read_varlen(bc);

        while (tmp_fields-- > 8)
            ffio_read_varlen(bc);

        if (count == 0 || i + count > 256) {
278
            av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
279
            return AVERROR_INVALIDDATA;
280
        }
281
        if (tmp_stream >= stream_count) {
282
            av_log(s, AV_LOG_ERROR, "illegal stream number\n");
283
            return AVERROR_INVALIDDATA;
284 285
        }

286
        for (j = 0; j < count; j++, i++) {
287
            if (i == 'N') {
288
                nut->frame_code[i].flags = FLAG_INVALID;
289 290 291
                j--;
                continue;
            }
292 293 294 295 296 297 298
            nut->frame_code[i].flags          = tmp_flags;
            nut->frame_code[i].pts_delta      = tmp_pts;
            nut->frame_code[i].stream_id      = tmp_stream;
            nut->frame_code[i].size_mul       = tmp_mul;
            nut->frame_code[i].size_lsb       = tmp_size + j;
            nut->frame_code[i].reserved_count = tmp_res;
            nut->frame_code[i].header_idx     = tmp_head_idx;
299 300 301 302
        }
    }
    assert(nut->frame_code['N'].flags == FLAG_INVALID);

303 304 305
    if (end > avio_tell(bc) + 4) {
        int rem = 1024;
        GET_V(nut->header_count, tmp < 128U)
306
        nut->header_count++;
307
        for (i = 1; i < nut->header_count; i++) {
308
            uint8_t *hdr;
309
            GET_V(nut->header_len[i], tmp > 0 && tmp < 256);
310
            rem -= nut->header_len[i];
311
            if (rem < 0) {
312
                av_log(s, AV_LOG_ERROR, "invalid elision header\n");
313
                return AVERROR_INVALIDDATA;
314
            }
315 316 317 318 319
            hdr = av_malloc(nut->header_len[i]);
            if (!hdr)
                return AVERROR(ENOMEM);
            avio_read(bc, hdr, nut->header_len[i]);
            nut->header[i] = hdr;
320
        }
321
        assert(nut->header_len[0] == 0);
322 323
    }

324
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
325
        av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n");
326
        return AVERROR_INVALIDDATA;
327 328
    }

329 330
    nut->stream = av_mallocz(sizeof(StreamContext) * stream_count);
    for (i = 0; i < stream_count; i++)
331
        avformat_new_stream(s, NULL);
332 333 334 335

    return 0;
}

336 337 338 339
static int decode_stream_header(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
340
    StreamContext *stc;
341
    int class, stream_id;
342 343 344
    uint64_t tmp, end;
    AVStream *st;

345
    end  = get_packetheader(nut, bc, 1, STREAM_STARTCODE);
346
    end += avio_tell(bc);
347

348
    GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base);
349 350
    stc = &nut->stream[stream_id];
    st  = s->streams[stream_id];
351
    if (!st)
352
        return AVERROR(ENOMEM);
353

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
    class                = ffio_read_varlen(bc);
    tmp                  = get_fourcc(bc);
    st->codec->codec_tag = tmp;
    switch (class) {
    case 0:
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
        st->codec->codec_id   = av_codec_get_id((const AVCodecTag * const []) {
                                                    ff_codec_bmp_tags,
                                                    ff_nut_video_tags,
                                                    0
                                                },
                                                tmp);
        break;
    case 1:
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
        st->codec->codec_id   = ff_codec_get_id(ff_codec_wav_tags, tmp);
        break;
    case 2:
        st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
        st->codec->codec_id   = ff_codec_get_id(ff_nut_subtitle_tags, tmp);
        break;
    case 3:
        st->codec->codec_type = AVMEDIA_TYPE_DATA;
        break;
    default:
        av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
        return -1;
381
    }
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
    if (class < 3 && st->codec->codec_id == CODEC_ID_NONE)
        av_log(s, AV_LOG_ERROR,
               "Unknown codec tag '0x%04x' for stream number %d\n",
               (unsigned int) tmp, stream_id);

    GET_V(stc->time_base_id, tmp < nut->time_base_count);
    GET_V(stc->msb_pts_shift, tmp < 16);
    stc->max_pts_distance = ffio_read_varlen(bc);
    GET_V(stc->decode_delay, tmp < 1000); // sanity limit, raise this if Moore's law is true
    st->codec->has_b_frames = stc->decode_delay;
    ffio_read_varlen(bc); // stream flags

    GET_V(st->codec->extradata_size, tmp < (1 << 30));
    if (st->codec->extradata_size) {
        st->codec->extradata = av_mallocz(st->codec->extradata_size +
                                          FF_INPUT_BUFFER_PADDING_SIZE);
398
        avio_read(bc, st->codec->extradata, st->codec->extradata_size);
399 400
    }

401 402
    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
        GET_V(st->codec->width,  tmp > 0)
403
        GET_V(st->codec->height, tmp > 0)
404 405 406 407 408
        st->sample_aspect_ratio.num = ffio_read_varlen(bc);
        st->sample_aspect_ratio.den = ffio_read_varlen(bc);
        if ((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)) {
            av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n",
                   st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
409 410
            return -1;
        }
411
        ffio_read_varlen(bc); /* csp type */
412 413
    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
        GET_V(st->codec->sample_rate, tmp > 0)
414
        ffio_read_varlen(bc); // samplerate_den
415 416
        GET_V(st->codec->channels, tmp > 0)
    }
417 418 419
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
        av_log(s, AV_LOG_ERROR,
               "stream header %d checksum mismatch\n", stream_id);
420 421
        return -1;
    }
422 423 424
    stc->time_base = &nut->time_base[stc->time_base_id];
    avpriv_set_pts_info(s->streams[stream_id], 63, stc->time_base->num,
                        stc->time_base->den);
425 426 427
    return 0;
}

428 429 430
static void set_disposition_bits(AVFormatContext *avf, char *value,
                                 int stream_id)
{
431
    int flag = 0, i;
432 433

    for (i = 0; ff_nut_dispositions[i].flag; ++i)
434 435 436 437 438 439 440 441 442
        if (!strcmp(ff_nut_dispositions[i].str, value))
            flag = ff_nut_dispositions[i].flag;
    if (!flag)
        av_log(avf, AV_LOG_INFO, "unknown disposition type '%s'\n", value);
    for (i = 0; i < avf->nb_streams; ++i)
        if (stream_id == i || stream_id == -1)
            avf->streams[i]->disposition |= flag;
}

443 444 445 446
static int decode_info_header(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
447 448
    uint64_t tmp, chapter_start, chapter_len;
    unsigned int stream_id_plus1, count;
449 450
    int chapter_id, i;
    int64_t value, end;
451
    char name[256], str_value[1024], type_str[256];
452
    const char *type;
453 454
    AVChapter *chapter      = NULL;
    AVStream *st            = NULL;
455
    AVDictionary **metadata = NULL;
456

457
    end  = get_packetheader(nut, bc, 1, INFO_STARTCODE);
458
    end += avio_tell(bc);
459 460

    GET_V(stream_id_plus1, tmp <= s->nb_streams)
461 462 463 464 465 466 467 468 469 470 471
    chapter_id    = get_s(bc);
    chapter_start = ffio_read_varlen(bc);
    chapter_len   = ffio_read_varlen(bc);
    count         = ffio_read_varlen(bc);

    if (chapter_id && !stream_id_plus1) {
        int64_t start = chapter_start / nut->time_base_count;
        chapter = avpriv_new_chapter(s, chapter_id,
                                     nut->time_base[chapter_start %
                                                    nut->time_base_count],
                                     start, start + chapter_len, NULL);
472
        metadata = &chapter->metadata;
473 474
    } else if (stream_id_plus1) {
        st       = s->streams[stream_id_plus1 - 1];
475 476 477
        metadata = &st->metadata;
    } else
        metadata = &s->metadata;
478

479
    for (i = 0; i < count; i++) {
480
        get_str(bc, name, sizeof(name));
481 482 483
        value = get_s(bc);
        if (value == -1) {
            type = "UTF-8";
484
            get_str(bc, str_value, sizeof(str_value));
485
        } else if (value == -2) {
486
            get_str(bc, type_str, sizeof(type_str));
487
            type = type_str;
488
            get_str(bc, str_value, sizeof(str_value));
489 490 491 492 493 494 495 496
        } else if (value == -3) {
            type  = "s";
            value = get_s(bc);
        } else if (value == -4) {
            type  = "t";
            value = ffio_read_varlen(bc);
        } else if (value < -4) {
            type = "r";
497
            get_s(bc);
498 499
        } else {
            type = "v";
500 501
        }

502
        if (stream_id_plus1 > s->nb_streams) {
503 504 505 506
            av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n");
            continue;
        }

507 508
        if (!strcmp(type, "UTF-8")) {
            if (chapter_id == 0 && !strcmp(name, "Disposition")) {
509
                set_disposition_bits(s, str_value, stream_id_plus1 - 1);
510 511
                continue;
            }
512 513
            if (metadata && av_strcasecmp(name, "Uses") &&
                av_strcasecmp(name, "Depends") && av_strcasecmp(name, "Replaces"))
514
                av_dict_set(metadata, name, str_value, 0);
515
        }
516 517
    }

518
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
519
        av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n");
520 521 522 523 524
        return -1;
    }
    return 0;
}

525 526 527 528
static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
529
    int64_t end, tmp;
530

531
    nut->last_syncpoint_pos = avio_tell(bc) - 8;
532

533
    end  = get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE);
534
    end += avio_tell(bc);
535

536 537 538
    tmp       = ffio_read_varlen(bc);
    *back_ptr = nut->last_syncpoint_pos - 16 * ffio_read_varlen(bc);
    if (*back_ptr < 0)
539
        return -1;
540

541 542
    ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count],
                    tmp / nut->time_base_count);
543

544
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
545
        av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
546 547
        return -1;
    }
548

549 550
    *ts = tmp / s->nb_streams *
          av_q2d(nut->time_base[tmp % s->nb_streams]) * AV_TIME_BASE;
551
    ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
552

553 554 555
    return 0;
}

556 557 558 559
static int find_and_decode_index(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
560 561
    uint64_t tmp, end;
    int i, j, syncpoint_count;
562
    int64_t filesize = avio_size(bc);
563 564
    int64_t *syncpoints;
    int8_t *has_keyframe;
565
    int ret = -1;
566

567 568 569
    avio_seek(bc, filesize - 12, SEEK_SET);
    avio_seek(bc, filesize - avio_rb64(bc), SEEK_SET);
    if (avio_rb64(bc) != INDEX_STARTCODE) {
570 571 572 573
        av_log(s, AV_LOG_ERROR, "no index at the end\n");
        return -1;
    }

574
    end  = get_packetheader(nut, bc, 1, INDEX_STARTCODE);
575
    end += avio_tell(bc);
576

577 578 579 580 581
    ffio_read_varlen(bc); // max_pts
    GET_V(syncpoint_count, tmp < INT_MAX / 8 && tmp > 0)
    syncpoints   = av_malloc(sizeof(int64_t) *  syncpoint_count);
    has_keyframe = av_malloc(sizeof(int8_t)  * (syncpoint_count + 1));
    for (i = 0; i < syncpoint_count; i++) {
582
        syncpoints[i] = ffio_read_varlen(bc);
583
        if (syncpoints[i] <= 0)
584
            goto fail;
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
        if (i)
            syncpoints[i] += syncpoints[i - 1];
    }

    for (i = 0; i < s->nb_streams; i++) {
        int64_t last_pts = -1;
        for (j = 0; j < syncpoint_count;) {
            uint64_t x = ffio_read_varlen(bc);
            int type   = x & 1;
            int n      = j;
            x >>= 1;
            if (type) {
                int flag = x & 1;
                x >>= 1;
                if (n + x >= syncpoint_count + 1) {
600
                    av_log(s, AV_LOG_ERROR, "index overflow A\n");
601
                    goto fail;
602
                }
603 604 605 606 607 608
                while (x--)
                    has_keyframe[n++] = flag;
                has_keyframe[n++] = !flag;
            } else {
                while (x != 1) {
                    if (n >= syncpoint_count + 1) {
609
                        av_log(s, AV_LOG_ERROR, "index overflow B\n");
610
                        goto fail;
611
                    }
612 613
                    has_keyframe[n++] = x & 1;
                    x >>= 1;
614 615
                }
            }
616
            if (has_keyframe[0]) {
617
                av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
618
                goto fail;
619
            }
620 621 622 623 624 625 626 627 628 629 630 631
            assert(n <= syncpoint_count + 1);
            for (; j < n && j < syncpoint_count; j++) {
                if (has_keyframe[j]) {
                    uint64_t B, A = ffio_read_varlen(bc);
                    if (!A) {
                        A = ffio_read_varlen(bc);
                        B = ffio_read_varlen(bc);
                        // eor_pts[j][i] = last_pts + A + B
                    } else
                        B = 0;
                    av_add_index_entry(s->streams[i], 16 * syncpoints[j - 1],
                                       last_pts + A, 0, 0, AVINDEX_KEYFRAME);
632 633 634 635 636 637
                    last_pts += A + B;
                }
            }
        }
    }

638
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
639
        av_log(s, AV_LOG_ERROR, "index checksum mismatch\n");
640
        goto fail;
641
    }
642 643
    ret = 0;

644 645 646 647
fail:
    av_free(syncpoints);
    av_free(has_keyframe);
    return ret;
648 649
}

650
static int nut_read_header(AVFormatContext *s)
651 652
{
    NUTContext *nut = s->priv_data;
653
    AVIOContext *bc = s->pb;
654
    int64_t pos;
655
    int initialized_stream_count;
656

657
    nut->avf = s;
658 659

    /* main header */
660 661 662 663
    pos = 0;
    do {
        pos = find_startcode(bc, MAIN_STARTCODE, pos) + 1;
        if (pos < 0 + 1) {
664
            av_log(s, AV_LOG_ERROR, "No main startcode found.\n");
665
            return AVERROR_INVALIDDATA;
666
        }
667
    } while (decode_main_header(nut) < 0);
668 669

    /* stream headers */
670 671 672 673
    pos = 0;
    for (initialized_stream_count = 0; initialized_stream_count < s->nb_streams;) {
        pos = find_startcode(bc, STREAM_STARTCODE, pos) + 1;
        if (pos < 0 + 1) {
674
            av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n");
675
            return AVERROR_INVALIDDATA;
676
        }
677
        if (decode_stream_header(nut) >= 0)
678
            initialized_stream_count++;
679 680 681
    }

    /* info headers */
682 683 684 685
    pos = 0;
    for (;;) {
        uint64_t startcode = find_any_startcode(bc, pos);
        pos = avio_tell(bc);
686

687
        if (startcode == 0) {
688
            av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
689
            return AVERROR_INVALIDDATA;
690 691
        } else if (startcode == SYNCPOINT_STARTCODE) {
            nut->next_startcode = startcode;
692
            break;
693
        } else if (startcode != INFO_STARTCODE) {
694 695 696 697 698 699
            continue;
        }

        decode_info_header(nut);
    }

700
    s->data_offset = pos - 8;
701

702 703
    if (bc->seekable) {
        int64_t orig_pos = avio_tell(bc);
704
        find_and_decode_index(nut);
705
        avio_seek(bc, orig_pos, SEEK_SET);
706 707 708
    }
    assert(nut->next_startcode == SYNCPOINT_STARTCODE);

709 710
    ff_metadata_conv_ctx(s, NULL, ff_nut_metadata_conv);

711 712 713
    return 0;
}

714 715 716 717 718
static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id,
                               uint8_t *header_idx, int frame_code)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
719 720 721 722
    StreamContext *stc;
    int size, flags, size_mul, pts_delta, i, reserved_count;
    uint64_t tmp;

723 724 725 726
    if (avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) {
        av_log(s, AV_LOG_ERROR,
               "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n",
               avio_tell(bc), nut->last_syncpoint_pos, nut->max_distance);
727
        return AVERROR_INVALIDDATA;
728 729 730 731 732 733 734 735
    }

    flags          = nut->frame_code[frame_code].flags;
    size_mul       = nut->frame_code[frame_code].size_mul;
    size           = nut->frame_code[frame_code].size_lsb;
    *stream_id     = nut->frame_code[frame_code].stream_id;
    pts_delta      = nut->frame_code[frame_code].pts_delta;
    reserved_count = nut->frame_code[frame_code].reserved_count;
736
    *header_idx    = nut->frame_code[frame_code].header_idx;
737

738
    if (flags & FLAG_INVALID)
739
        return AVERROR_INVALIDDATA;
740
    if (flags & FLAG_CODED)
741
        flags ^= ffio_read_varlen(bc);
742
    if (flags & FLAG_STREAM_ID) {
743 744
        GET_V(*stream_id, tmp < s->nb_streams)
    }
745 746 747 748 749 750 751 752 753 754 755 756 757
    stc = &nut->stream[*stream_id];
    if (flags & FLAG_CODED_PTS) {
        int coded_pts = ffio_read_varlen(bc);
        // FIXME check last_pts validity?
        if (coded_pts < (1 << stc->msb_pts_shift)) {
            *pts = ff_lsb2full(stc, coded_pts);
        } else
            *pts = coded_pts - (1 << stc->msb_pts_shift);
    } else
        *pts = stc->last_pts + pts_delta;
    if (flags & FLAG_SIZE_MSB)
        size += size_mul * ffio_read_varlen(bc);
    if (flags & FLAG_MATCH_TIME)
758
        get_s(bc);
759 760 761 762 763
    if (flags & FLAG_HEADER_IDX)
        *header_idx = ffio_read_varlen(bc);
    if (flags & FLAG_RESERVED)
        reserved_count = ffio_read_varlen(bc);
    for (i = 0; i < reserved_count; i++)
764
        ffio_read_varlen(bc);
765

766
    if (*header_idx >= (unsigned)nut->header_count) {
767
        av_log(s, AV_LOG_ERROR, "header_idx invalid\n");
768
        return AVERROR_INVALIDDATA;
769
    }
770 771
    if (size > 4096)
        *header_idx = 0;
772 773
    size -= nut->header_len[*header_idx];

774 775 776 777
    if (flags & FLAG_CHECKSUM) {
        avio_rb32(bc); // FIXME check this
    } else if (size > 2 * nut->max_distance || FFABS(stc->last_pts - *pts) >
               stc->max_pts_distance) {
778
        av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
779
        return AVERROR_INVALIDDATA;
780 781
    }

782 783
    stc->last_pts   = *pts;
    stc->last_flags = flags;
784 785 786 787

    return size;
}

788 789 790 791
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
792
    int size, stream_id, discard;
793
    int64_t pts, last_IP_pts;
794
    StreamContext *stc;
795
    uint8_t header_idx;
796

797 798
    size = decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
    if (size < 0)
799
        return size;
800

801
    stc = &nut->stream[stream_id];
802 803

    if (stc->last_flags & FLAG_KEY)
804 805 806 807 808 809 810 811 812
        stc->skip_until_key_frame = 0;

    discard     = s->streams[stream_id]->discard;
    last_IP_pts = s->streams[stream_id]->last_IP_pts;
    if ((discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY)) ||
        (discard >= AVDISCARD_BIDIR  && last_IP_pts != AV_NOPTS_VALUE &&
         last_IP_pts > pts) ||
        discard >= AVDISCARD_ALL ||
        stc->skip_until_key_frame) {
813
        avio_skip(bc, size);
814 815 816
        return 1;
    }

817 818
    av_new_packet(pkt, size + nut->header_len[header_idx]);
    memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
819
    pkt->pos = avio_tell(bc); // FIXME
820
    avio_read(bc, pkt->data + nut->header_len[header_idx], size);
821

822
    pkt->stream_index = stream_id;
823
    if (stc->last_flags & FLAG_KEY)
824
        pkt->flags |= AV_PKT_FLAG_KEY;
825 826 827 828 829 830 831 832
    pkt->pts = pts;

    return 0;
}

static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    NUTContext *nut = s->priv_data;
833
    AVIOContext *bc = s->pb;
834
    int i, frame_code = 0, ret, skip;
835
    int64_t ts, back_ptr;
836

837 838 839 840
    for (;;) {
        int64_t pos  = avio_tell(bc);
        uint64_t tmp = nut->next_startcode;
        nut->next_startcode = 0;
841

842 843 844
        if (tmp) {
            pos -= 8;
        } else {
845
            frame_code = avio_r8(bc);
846
            if (url_feof(bc))
847
                return -1;
848 849 850 851
            if (frame_code == 'N') {
                tmp = frame_code;
                for (i = 1; i < 8; i++)
                    tmp = (tmp << 8) + avio_r8(bc);
852 853
            }
        }
854
        switch (tmp) {
855 856 857
        case MAIN_STARTCODE:
        case STREAM_STARTCODE:
        case INDEX_STARTCODE:
858
            skip = get_packetheader(nut, bc, 0, tmp);
859
            avio_skip(bc, skip);
860 861
            break;
        case INFO_STARTCODE:
862
            if (decode_info_header(nut) < 0)
863 864 865
                goto resync;
            break;
        case SYNCPOINT_STARTCODE:
866
            if (decode_syncpoint(nut, &ts, &back_ptr) < 0)
867
                goto resync;
868
            frame_code = avio_r8(bc);
869
        case 0:
870 871
            ret = decode_frame(nut, pkt, frame_code);
            if (ret == 0)
872
                return 0;
873
            else if (ret == 1) // OK but discard packet
874 875 876
                break;
        default:
resync:
877 878 879
            av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
            tmp = find_any_startcode(bc, nut->last_syncpoint_pos + 1);
            if (tmp == 0)
880
                return AVERROR_INVALIDDATA;
881 882
            av_log(s, AV_LOG_DEBUG, "sync\n");
            nut->next_startcode = tmp;
883 884 885 886
        }
    }
}

887 888 889
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
                                  int64_t *pos_arg, int64_t pos_limit)
{
890
    NUTContext *nut = s->priv_data;
891
    AVIOContext *bc = s->pb;
892
    int64_t pos, pts, back_ptr;
893 894
    av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n",
           stream_index, *pos_arg, pos_limit);
895

896 897 898 899
    pos = *pos_arg;
    do {
        pos = find_startcode(bc, SYNCPOINT_STARTCODE, pos) + 1;
        if (pos < 1) {
900
            assert(nut->next_startcode == 0);
901
            av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
902 903
            return AV_NOPTS_VALUE;
        }
904 905
    } while (decode_syncpoint(nut, &pts, &back_ptr) < 0);
    *pos_arg = pos - 1;
906 907
    assert(nut->last_syncpoint_pos == *pos_arg);

908 909 910 911 912
    av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts, back_ptr);
    if (stream_index == -1)
        return pts;
    else if (stream_index == -2)
        return back_ptr;
913

914
    assert(0);
915 916
}

917 918 919 920 921 922 923 924
static int read_seek(AVFormatContext *s, int stream_index,
                     int64_t pts, int flags)
{
    NUTContext *nut    = s->priv_data;
    AVStream *st       = s->streams[stream_index];
    Syncpoint dummy    = { .ts = pts * av_q2d(st->time_base) * AV_TIME_BASE };
    Syncpoint nopts_sp = { .ts = AV_NOPTS_VALUE, .back_ptr = AV_NOPTS_VALUE };
    Syncpoint *sp, *next_node[2] = { &nopts_sp, &nopts_sp };
925
    int64_t pos, pos2, ts;
926
    int i;
927

928 929 930
    if (st->index_entries) {
        int index = av_index_search_timestamp(st, pts, flags);
        if (index < 0)
Michael Niedermayer's avatar
Michael Niedermayer committed
931 932
            return -1;

933 934 935
        pos2 = st->index_entries[index].pos;
        ts   = st->index_entries[index].timestamp;
    } else {
936 937
        av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pts_cmp,
                     (void **) next_node);
938 939 940 941 942 943 944 945 946 947 948
        av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n",
               next_node[0]->pos, next_node[1]->pos, next_node[0]->ts,
               next_node[1]->ts);
        pos = ff_gen_search(s, -1, dummy.ts, next_node[0]->pos,
                            next_node[1]->pos, next_node[1]->pos,
                            next_node[0]->ts, next_node[1]->ts,
                            AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp);

        if (!(flags & AVSEEK_FLAG_BACKWARD)) {
            dummy.pos    = pos + 16;
            next_node[1] = &nopts_sp;
949 950
            av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
                         (void **) next_node);
951 952 953 954 955 956 957
            pos2 = ff_gen_search(s, -2, dummy.pos, next_node[0]->pos,
                                 next_node[1]->pos, next_node[1]->pos,
                                 next_node[0]->back_ptr, next_node[1]->back_ptr,
                                 flags, &ts, nut_read_timestamp);
            if (pos2 >= 0)
                pos = pos2;
            // FIXME dir but I think it does not matter
Michael Niedermayer's avatar
Michael Niedermayer committed
958
        }
959 960 961
        dummy.pos = pos;
        sp = av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
                          NULL);
Michael Niedermayer's avatar
Michael Niedermayer committed
962 963

        assert(sp);
964
        pos2 = sp->back_ptr - 15;
Michael Niedermayer's avatar
Michael Niedermayer committed
965 966
    }
    av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
967
    pos = find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);
968
    avio_seek(s->pb, pos, SEEK_SET);
969
    av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
970
    if (pos2 > pos || pos2 + 15 < pos)
971
        av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
972 973
    for (i = 0; i < s->nb_streams; i++)
        nut->stream[i].skip_until_key_frame = 1;
974

975 976 977
    return 0;
}

978 979 980
static int nut_read_close(AVFormatContext *s)
{
    NUTContext *nut = s->priv_data;
981
    int i;
982 983 984

    av_freep(&nut->time_base);
    av_freep(&nut->stream);
985
    ff_nut_free_sp(nut);
986
    for (i = 1; i < nut->header_count; i++)
987
        av_freep(&nut->header[i]);
988 989 990 991

    return 0;
}

992
AVInputFormat ff_nut_demuxer = {
993 994 995 996 997 998 999 1000
    .name           = "nut",
    .long_name      = NULL_IF_CONFIG_SMALL("NUT format"),
    .priv_data_size = sizeof(NUTContext),
    .read_probe     = nut_probe,
    .read_header    = nut_read_header,
    .read_packet    = nut_read_packet,
    .read_close     = nut_read_close,
    .read_seek      = read_seek,
1001 1002 1003 1004 1005
    .extensions     = "nut",
    .codec_tag      = (const AVCodecTag * const []) {
        ff_codec_bmp_tags, ff_nut_video_tags, ff_codec_wav_tags,
        ff_nut_subtitle_tags, 0
    },
1006
};