nutdec.c 43.3 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/avassert.h"
25
#include "libavutil/bswap.h"
26
#include "libavutil/dict.h"
27
#include "libavutil/intreadwrite.h"
28
#include "libavutil/mathematics.h"
29
#include "libavutil/tree.h"
30
#include "libavcodec/bytestream.h"
31
#include "avio_internal.h"
32
#include "isom.h"
33
#include "nut.h"
34
#include "riff.h"
35

36 37
#define NUT_MAX_STREAMS 256    /* arbitrary sanity check value */

38 39 40
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
                                  int64_t *pos_arg, int64_t pos_limit);

41 42 43
static int get_str(AVIOContext *bc, char *string, unsigned int maxlen)
{
    unsigned int len = ffio_read_varlen(bc);
44

45
    if (len && maxlen)
46
        avio_read(bc, string, FFMIN(len, maxlen));
47
    while (len > maxlen) {
48
        avio_r8(bc);
49
        len--;
50 51
        if (bc->eof_reached)
            len = maxlen;
52 53
    }

54 55
    if (maxlen)
        string[FFMIN(len, maxlen - 1)] = 0;
56

57 58
    if (bc->eof_reached)
        return AVERROR_EOF;
59
    if (maxlen == len)
60 61 62 63 64
        return -1;
    else
        return 0;
}

65 66
static int64_t get_s(AVIOContext *bc)
{
67
    int64_t v = ffio_read_varlen(bc) + 1;
68

69 70 71 72
    if (v & 1)
        return -(v >> 1);
    else
        return  (v >> 1);
73 74
}

75 76 77
static uint64_t get_fourcc(AVIOContext *bc)
{
    unsigned int len = ffio_read_varlen(bc);
78

79 80 81 82
    if (len == 2)
        return avio_rl16(bc);
    else if (len == 4)
        return avio_rl32(bc);
83 84
    else {
        av_log(NULL, AV_LOG_ERROR, "Unsupported fourcc length %d\n", len);
85
        return -1;
86
    }
87 88 89
}

#ifdef TRACE
90 91
static inline uint64_t get_v_trace(AVIOContext *bc, const char *file,
                                   const char *func, int line)
92 93
{
    uint64_t v = ffio_read_varlen(bc);
94

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

100 101
static inline int64_t get_s_trace(AVIOContext *bc, const char *file,
                                  const char *func, int line)
102 103
{
    int64_t v = get_s(bc);
104

105 106
    av_log(NULL, AV_LOG_DEBUG, "get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n",
           v, v, file, func, line);
107 108 109
    return v;
}

110
static inline uint64_t get_4cc_trace(AVIOContext *bc, char *file,
111 112
                                    char *func, int line)
{
113
    uint64_t v = get_fourcc(bc);
114

115
    av_log(NULL, AV_LOG_DEBUG, "get_fourcc %5"PRId64" / %"PRIX64" in %s %s:%d\n",
116
           v, v, file, func, line);
117 118
    return v;
}
119 120
#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__)
121
#define get_fourcc(bc)       get_4cc_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
122 123
#endif

124 125
static int get_packetheader(NUTContext *nut, AVIOContext *bc,
                            int calculate_checksum, uint64_t startcode)
126
{
127
    int64_t size;
128
//    start = avio_tell(bc) - 8;
129

130 131
    startcode = av_be2ne64(startcode);
    startcode = ff_crc04C11DB7_update(0, (uint8_t*) &startcode, 8);
132

133
    ffio_init_checksum(bc, ff_crc04C11DB7_update, startcode);
134 135
    size = ffio_read_varlen(bc);
    if (size > 4096)
136
        avio_rb32(bc);
137
    if (ffio_get_checksum(bc) && size > 4096)
Michael Niedermayer's avatar
Michael Niedermayer committed
138
        return -1;
139

140
    ffio_init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0);
141 142 143 144

    return size;
}

145 146 147 148 149 150 151 152
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);
153
    while (!avio_feof(bc)) {
154 155
        state = (state << 8) | avio_r8(bc);
        if ((state >> 56) != 'N')
156
            continue;
157
        switch (state) {
158 159 160 161 162 163 164 165 166 167 168 169 170
        case MAIN_STARTCODE:
        case STREAM_STARTCODE:
        case SYNCPOINT_STARTCODE:
        case INFO_STARTCODE:
        case INDEX_STARTCODE:
            return state;
        }
    }

    return 0;
}

/**
171
 * Find the given startcode.
172 173
 * @param code the startcode
 * @param pos the start position of the search, or -1 if the current position
174
 * @return the position of the startcode or -1 if not found
175
 */
176 177 178 179 180
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)
181
            return avio_tell(bc) - 8;
182
        else if (startcode == 0)
183
            return -1;
184
        pos = -1;
185 186 187
    }
}

188 189
static int nut_probe(AVProbeData *p)
{
190 191
    int i;

192 193 194 195
    for (i = 0; i < p->buf_size-8; i++) {
        if (AV_RB32(p->buf+i) != MAIN_STARTCODE>>32)
            continue;
        if (AV_RB32(p->buf+i+4) == (MAIN_STARTCODE & 0xFFFFFFFF))
196 197 198 199 200
            return AVPROBE_SCORE_MAX;
    }
    return 0;
}

201 202 203 204 205
#define GET_V(dst, check)                                                     \
    do {                                                                      \
        tmp = ffio_read_varlen(bc);                                           \
        if (!(check)) {                                                       \
            av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);  \
206 207
            ret = AVERROR_INVALIDDATA;                                        \
            goto fail;                                                        \
208 209 210
        }                                                                     \
        dst = tmp;                                                            \
    } while (0)
211

212 213
static int skip_reserved(AVIOContext *bc, int64_t pos)
{
214
    pos -= avio_tell(bc);
215
    if (pos < 0) {
216
        avio_seek(bc, pos, SEEK_CUR);
217
        return AVERROR_INVALIDDATA;
218
    } else {
219 220 221
        while (pos--) {
            if (bc->eof_reached)
                return AVERROR_INVALIDDATA;
222
            avio_r8(bc);
223
        }
224 225 226 227
        return 0;
    }
}

228 229 230 231
static int decode_main_header(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
232 233
    uint64_t tmp, end;
    unsigned int stream_count;
234
    int i, j, count, ret;
235
    int tmp_stream, tmp_mul, tmp_pts, tmp_size, tmp_res, tmp_head_idx;
236

237
    end  = get_packetheader(nut, bc, 1, MAIN_STARTCODE);
238
    end += avio_tell(bc);
239

240
    nut->version = ffio_read_varlen(bc);
241 242 243 244
    if (nut->version < NUT_MIN_VERSION &&
        nut->version > NUT_MAX_VERSION) {
        av_log(s, AV_LOG_ERROR, "Version %d not supported.\n",
               nut->version);
245 246
        return AVERROR(ENOSYS);
    }
247 248
    if (nut->version > 3)
        nut->minor_version = ffio_read_varlen(bc);
249

250
    GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS);
251

252
    nut->max_distance = ffio_read_varlen(bc);
253
    if (nut->max_distance > 65536) {
254
        av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
255
        nut->max_distance = 65536;
256 257
    }

258
    GET_V(nut->time_base_count, tmp > 0 && tmp < INT_MAX / sizeof(AVRational));
259
    nut->time_base = av_malloc_array(nut->time_base_count, sizeof(AVRational));
260 261
    if (!nut->time_base)
        return AVERROR(ENOMEM);
262

263
    for (i = 0; i < nut->time_base_count; i++) {
264 265
        GET_V(nut->time_base[i].num, tmp > 0 && tmp < (1ULL << 31));
        GET_V(nut->time_base[i].den, tmp > 0 && tmp < (1ULL << 31));
266
        if (av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1) {
267
            av_log(s, AV_LOG_ERROR, "time base invalid\n");
268 269
            ret = AVERROR_INVALIDDATA;
            goto fail;
270 271
        }
    }
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    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);

303 304 305
        while (tmp_fields-- > 8) {
            if (bc->eof_reached) {
                av_log(s, AV_LOG_ERROR, "reached EOF while decoding main header\n");
306 307
                ret = AVERROR_INVALIDDATA;
                goto fail;
308
            }
309
            ffio_read_varlen(bc);
310
        }
311

312
        if (count <= 0 || count > 256 - (i <= 'N') - i) {
313
            av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
314 315
            ret = AVERROR_INVALIDDATA;
            goto fail;
316
        }
317
        if (tmp_stream >= stream_count) {
318
            av_log(s, AV_LOG_ERROR, "illegal stream number\n");
319 320
            ret = AVERROR_INVALIDDATA;
            goto fail;
321 322
        }

323
        for (j = 0; j < count; j++, i++) {
324
            if (i == 'N') {
325
                nut->frame_code[i].flags = FLAG_INVALID;
326 327 328
                j--;
                continue;
            }
329 330 331 332 333 334 335
            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;
336 337
        }
    }
338
    av_assert0(nut->frame_code['N'].flags == FLAG_INVALID);
339

340 341
    if (end > avio_tell(bc) + 4) {
        int rem = 1024;
342
        GET_V(nut->header_count, tmp < 128U);
343
        nut->header_count++;
344
        for (i = 1; i < nut->header_count; i++) {
345
            uint8_t *hdr;
346
            GET_V(nut->header_len[i], tmp > 0 && tmp < 256);
347
            rem -= nut->header_len[i];
348
            if (rem < 0) {
349
                av_log(s, AV_LOG_ERROR, "invalid elision header\n");
350 351
                ret = AVERROR_INVALIDDATA;
                goto fail;
352
            }
353
            hdr = av_malloc(nut->header_len[i]);
354 355 356 357
            if (!hdr) {
                ret = AVERROR(ENOMEM);
                goto fail;
            }
358 359
            avio_read(bc, hdr, nut->header_len[i]);
            nut->header[i] = hdr;
360
        }
361
        av_assert0(nut->header_len[0] == 0);
362 363
    }

364
    // flags had been effectively introduced in version 4
365
    if (nut->version > 3 && end > avio_tell(bc) + 4) {
366 367 368
        nut->flags = ffio_read_varlen(bc);
    }

369
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
370
        av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n");
371 372
        ret = AVERROR_INVALIDDATA;
        goto fail;
373 374
    }

375
    nut->stream = av_calloc(stream_count, sizeof(StreamContext));
376 377 378 379
    if (!nut->stream) {
        ret = AVERROR(ENOMEM);
        goto fail;
    }
380
    for (i = 0; i < stream_count; i++)
381
        avformat_new_stream(s, NULL);
382 383

    return 0;
384 385 386 387 388 389 390
fail:
    av_freep(&nut->time_base);
    for (i = 1; i < nut->header_count; i++) {
        av_freep(&nut->header[i]);
    }
    nut->header_count = 0;
    return ret;
391 392
}

393 394 395 396
static int decode_stream_header(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
397
    StreamContext *stc;
398
    int class, stream_id, ret;
399
    uint64_t tmp, end;
400
    AVStream *st = NULL;
401

402
    end  = get_packetheader(nut, bc, 1, STREAM_STARTCODE);
403
    end += avio_tell(bc);
404

405
    GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base);
406 407
    stc = &nut->stream[stream_id];
    st  = s->streams[stream_id];
408
    if (!st)
409
        return AVERROR(ENOMEM);
410

411 412 413 414 415 416 417 418
    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_nut_video_tags,
419
                                                    ff_codec_bmp_tags,
420
                                                    ff_codec_movvideo_tags,
421 422 423 424 425 426
                                                    0
                                                },
                                                tmp);
        break;
    case 1:
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
427 428 429
        st->codec->codec_id   = av_codec_get_id((const AVCodecTag * const []) {
                                                    ff_nut_audio_tags,
                                                    ff_codec_wav_tags,
430
                                                    ff_nut_audio_extra_tags,
431 432 433
                                                    0
                                                },
                                                tmp);
434 435 436 437 438 439 440
        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;
Luca Barbato's avatar
Luca Barbato committed
441
        st->codec->codec_id   = ff_codec_get_id(ff_nut_data_tags, tmp);
442 443 444
        break;
    default:
        av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
445
        return AVERROR(ENOSYS);
446
    }
447
    if (class < 3 && st->codec->codec_id == AV_CODEC_ID_NONE)
448 449 450 451 452 453 454 455 456 457 458 459 460
        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) {
461
        if (ff_get_extradata(st->codec, bc, st->codec->extradata_size) < 0)
462
            return AVERROR(ENOMEM);
463 464
    }

465
    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
466 467
        GET_V(st->codec->width,  tmp > 0);
        GET_V(st->codec->height, tmp > 0);
468 469 470 471 472
        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);
473 474
            ret = AVERROR_INVALIDDATA;
            goto fail;
475
        }
476
        ffio_read_varlen(bc); /* csp type */
477
    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
478
        GET_V(st->codec->sample_rate, tmp > 0);
479
        ffio_read_varlen(bc); // samplerate_den
480
        GET_V(st->codec->channels, tmp > 0);
481
    }
482 483 484
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
        av_log(s, AV_LOG_ERROR,
               "stream header %d checksum mismatch\n", stream_id);
485 486
        ret = AVERROR_INVALIDDATA;
        goto fail;
487
    }
488 489 490
    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);
491
    return 0;
492 493 494 495 496 497
fail:
    if (st && st->codec) {
        av_freep(&st->codec->extradata);
        st->codec->extradata_size = 0;
    }
    return ret;
498 499
}

500 501 502
static void set_disposition_bits(AVFormatContext *avf, char *value,
                                 int stream_id)
{
503
    int flag = 0, i;
504 505

    for (i = 0; ff_nut_dispositions[i].flag; ++i)
506 507 508 509 510 511 512 513 514
        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;
}

515 516 517 518
static int decode_info_header(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
519 520
    uint64_t tmp, chapter_start, chapter_len;
    unsigned int stream_id_plus1, count;
521
    int chapter_id, i, ret = 0;
522
    int64_t value, end;
523
    char name[256], str_value[1024], type_str[256];
524
    const char *type;
525
    int *event_flags        = NULL;
526 527
    AVChapter *chapter      = NULL;
    AVStream *st            = NULL;
528
    AVDictionary **metadata = NULL;
529
    int metadata_flag       = 0;
530

531
    end  = get_packetheader(nut, bc, 1, INFO_STARTCODE);
532
    end += avio_tell(bc);
533

534
    GET_V(stream_id_plus1, tmp <= s->nb_streams);
535 536 537 538 539 540 541 542 543 544 545
    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);
546
        if (!chapter) {
547
            av_log(s, AV_LOG_ERROR, "Could not create chapter.\n");
548 549
            return AVERROR(ENOMEM);
        }
550
        metadata = &chapter->metadata;
551 552
    } else if (stream_id_plus1) {
        st       = s->streams[stream_id_plus1 - 1];
553
        metadata = &st->metadata;
554 555 556
        event_flags = &st->event_flags;
        metadata_flag = AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
    } else {
557
        metadata = &s->metadata;
558 559 560
        event_flags = &s->event_flags;
        metadata_flag = AVFMT_EVENT_FLAG_METADATA_UPDATED;
    }
561

562
    for (i = 0; i < count; i++) {
563 564 565 566 567
        ret = get_str(bc, name, sizeof(name));
        if (ret < 0) {
            av_log(s, AV_LOG_ERROR, "get_str failed while decoding info header\n");
            return ret;
        }
568
        value = get_s(bc);
569 570
        str_value[0] = 0;

571 572
        if (value == -1) {
            type = "UTF-8";
573
            ret = get_str(bc, str_value, sizeof(str_value));
574
        } else if (value == -2) {
575 576 577 578 579
            ret = get_str(bc, type_str, sizeof(type_str));
            if (ret < 0) {
                av_log(s, AV_LOG_ERROR, "get_str failed while decoding info header\n");
                return ret;
            }
580
            type = type_str;
581
            ret = get_str(bc, str_value, sizeof(str_value));
582 583 584 585 586 587 588 589
        } 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";
590
            get_s(bc);
591 592
        } else {
            type = "v";
593 594
        }

595 596 597 598 599
        if (ret < 0) {
            av_log(s, AV_LOG_ERROR, "get_str failed while decoding info header\n");
            return ret;
        }

600
        if (stream_id_plus1 > s->nb_streams) {
601 602 603 604
            av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n");
            continue;
        }

605 606
        if (!strcmp(type, "UTF-8")) {
            if (chapter_id == 0 && !strcmp(name, "Disposition")) {
607
                set_disposition_bits(s, str_value, stream_id_plus1 - 1);
608 609
                continue;
            }
610 611 612

            if (stream_id_plus1 && !strcmp(name, "r_frame_rate")) {
                sscanf(str_value, "%d/%d", &st->r_frame_rate.num, &st->r_frame_rate.den);
613 614
                if (st->r_frame_rate.num >= 1000LL*st->r_frame_rate.den ||
                    st->r_frame_rate.num < 0 || st->r_frame_rate.num < 0)
615
                    st->r_frame_rate.num = st->r_frame_rate.den = 0;
616 617 618
                continue;
            }

619
            if (metadata && av_strcasecmp(name, "Uses") &&
620
                av_strcasecmp(name, "Depends") && av_strcasecmp(name, "Replaces")) {
621 622
                if (event_flags)
                    *event_flags |= metadata_flag;
623
                av_dict_set(metadata, name, str_value, 0);
624
            }
625
        }
626 627
    }

628
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
629
        av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n");
630
        return AVERROR_INVALIDDATA;
631
    }
632 633
fail:
    return FFMIN(ret, 0);
634 635
}

636 637 638 639
static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
640 641
    int64_t end;
    uint64_t tmp;
642
    int ret;
643

644
    nut->last_syncpoint_pos = avio_tell(bc) - 8;
645

646
    end  = get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE);
647
    end += avio_tell(bc);
648

649 650 651
    tmp       = ffio_read_varlen(bc);
    *back_ptr = nut->last_syncpoint_pos - 16 * ffio_read_varlen(bc);
    if (*back_ptr < 0)
652
        return AVERROR_INVALIDDATA;
653

654 655
    ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count],
                    tmp / nut->time_base_count);
656

657 658 659 660 661 662 663 664
    if (nut->flags & NUT_BROADCAST) {
        tmp = ffio_read_varlen(bc);
        av_log(s, AV_LOG_VERBOSE, "Syncpoint wallclock %"PRId64"\n",
               av_rescale_q(tmp / nut->time_base_count,
                            nut->time_base[tmp % nut->time_base_count],
                            AV_TIME_BASE_Q));
    }

665
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
666
        av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
667
        return AVERROR_INVALIDDATA;
668
    }
669

670 671
    *ts = tmp / nut->time_base_count *
          av_q2d(nut->time_base[tmp % nut->time_base_count]) * AV_TIME_BASE;
672 673 674

    if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts)) < 0)
        return ret;
675

676 677 678
    return 0;
}

679 680 681 682 683 684
//FIXME calculate exactly, this is just a good approximation.
static int64_t find_duration(NUTContext *nut, int64_t filesize)
{
    AVFormatContext *s = nut->avf;
    int64_t duration = 0;

685 686
    ff_find_last_ts(s, -1, &duration, NULL, nut_read_timestamp);

687 688
    if(duration > 0)
        s->duration_estimation_method = AVFMT_DURATION_FROM_PTS;
689 690 691
    return duration;
}

692 693 694 695
static int find_and_decode_index(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
696 697
    uint64_t tmp, end;
    int i, j, syncpoint_count;
698
    int64_t filesize = avio_size(bc);
699
    int64_t *syncpoints = NULL;
700
    uint64_t max_pts;
701
    int8_t *has_keyframe = NULL;
702
    int ret = AVERROR_INVALIDDATA;
703

704 705 706
    if(filesize <= 0)
        return -1;

707 708 709
    avio_seek(bc, filesize - 12, SEEK_SET);
    avio_seek(bc, filesize - avio_rb64(bc), SEEK_SET);
    if (avio_rb64(bc) != INDEX_STARTCODE) {
710
        av_log(s, AV_LOG_ERROR, "no index at the end\n");
711 712 713

        if(s->duration<=0)
            s->duration = find_duration(nut, filesize);
714
        return ret;
715 716
    }

717
    end  = get_packetheader(nut, bc, 1, INDEX_STARTCODE);
718
    end += avio_tell(bc);
719

720 721 722 723 724 725
    max_pts = ffio_read_varlen(bc);
    s->duration = av_rescale_q(max_pts / nut->time_base_count,
                               nut->time_base[max_pts % nut->time_base_count],
                               AV_TIME_BASE_Q);
    s->duration_estimation_method = AVFMT_DURATION_FROM_PTS;

726
    GET_V(syncpoint_count, tmp < INT_MAX / 8 && tmp > 0);
727 728 729 730 731 732
    syncpoints   = av_malloc_array(syncpoint_count, sizeof(int64_t));
    has_keyframe = av_malloc_array(syncpoint_count + 1, sizeof(int8_t));
    if (!syncpoints || !has_keyframe) {
        ret = AVERROR(ENOMEM);
        goto fail;
    }
733
    for (i = 0; i < syncpoint_count; i++) {
734
        syncpoints[i] = ffio_read_varlen(bc);
735
        if (syncpoints[i] <= 0)
736
            goto fail;
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
        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) {
752
                    av_log(s, AV_LOG_ERROR, "index overflow A %d + %"PRIu64" >= %d\n", n, x, syncpoint_count + 1);
753
                    goto fail;
754
                }
755 756 757 758
                while (x--)
                    has_keyframe[n++] = flag;
                has_keyframe[n++] = !flag;
            } else {
759 760 761 762
                if (x <= 1) {
                    av_log(s, AV_LOG_ERROR, "index: x %"PRIu64" is invalid\n", x);
                    goto fail;
                }
763 764
                while (x != 1) {
                    if (n >= syncpoint_count + 1) {
765
                        av_log(s, AV_LOG_ERROR, "index overflow B\n");
766
                        goto fail;
767
                    }
768 769
                    has_keyframe[n++] = x & 1;
                    x >>= 1;
770 771
                }
            }
772
            if (has_keyframe[0]) {
773
                av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
774
                goto fail;
775
            }
776
            av_assert0(n <= syncpoint_count + 1);
777 778 779 780 781 782 783 784 785 786 787
            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);
788 789 790 791 792 793
                    last_pts += A + B;
                }
            }
        }
    }

794
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
795
        av_log(s, AV_LOG_ERROR, "index checksum mismatch\n");
796
        goto fail;
797
    }
798 799
    ret = 0;

800 801 802 803
fail:
    av_free(syncpoints);
    av_free(has_keyframe);
    return ret;
804 805
}

806 807 808 809 810 811 812 813 814 815 816 817 818
static int nut_read_close(AVFormatContext *s)
{
    NUTContext *nut = s->priv_data;
    int i;

    av_freep(&nut->time_base);
    av_freep(&nut->stream);
    ff_nut_free_sp(nut);
    for (i = 1; i < nut->header_count; i++)
        av_freep(&nut->header[i]);

    return 0;
}
819

820
static int nut_read_header(AVFormatContext *s)
821 822
{
    NUTContext *nut = s->priv_data;
823
    AVIOContext *bc = s->pb;
824
    int64_t pos;
825
    int initialized_stream_count;
826

827
    nut->avf = s;
828 829

    /* main header */
830 831 832 833
    pos = 0;
    do {
        pos = find_startcode(bc, MAIN_STARTCODE, pos) + 1;
        if (pos < 0 + 1) {
834
            av_log(s, AV_LOG_ERROR, "No main startcode found.\n");
835
            goto fail;
836
        }
837
    } while (decode_main_header(nut) < 0);
838 839

    /* stream headers */
840 841 842 843
    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) {
844
            av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n");
845
            goto fail;
846
        }
847
        if (decode_stream_header(nut) >= 0)
848
            initialized_stream_count++;
849 850 851
    }

    /* info headers */
852 853 854 855
    pos = 0;
    for (;;) {
        uint64_t startcode = find_any_startcode(bc, pos);
        pos = avio_tell(bc);
856

857
        if (startcode == 0) {
858
            av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
859
            goto fail;
860 861
        } else if (startcode == SYNCPOINT_STARTCODE) {
            nut->next_startcode = startcode;
862
            break;
863
        } else if (startcode != INFO_STARTCODE) {
864 865 866 867 868 869
            continue;
        }

        decode_info_header(nut);
    }

870
    s->internal->data_offset = pos - 8;
871

872 873
    if (bc->seekable) {
        int64_t orig_pos = avio_tell(bc);
874
        find_and_decode_index(nut);
875
        avio_seek(bc, orig_pos, SEEK_SET);
876
    }
877
    av_assert0(nut->next_startcode == SYNCPOINT_STARTCODE);
878

879 880
    ff_metadata_conv_ctx(s, NULL, ff_nut_metadata_conv);

881 882
    return 0;

883 884 885 886
fail:
    nut_read_close(s);

    return AVERROR_INVALIDDATA;
887 888
}

889 890 891 892 893 894 895 896 897 898
static int read_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int is_meta, int64_t maxpos)
{
    int count = ffio_read_varlen(bc);
    int skip_start = 0;
    int skip_end = 0;
    int channels = 0;
    int64_t channel_layout = 0;
    int sample_rate = 0;
    int width = 0;
    int height = 0;
899
    int i, ret;
900 901 902

    for (i=0; i<count; i++) {
        uint8_t name[256], str_value[256], type_str[256];
903
        int value;
904 905
        if (avio_tell(bc) >= maxpos)
            return AVERROR_INVALIDDATA;
906 907 908 909 910
        ret = get_str(bc, name, sizeof(name));
        if (ret < 0) {
            av_log(s, AV_LOG_ERROR, "get_str failed while reading sm data\n");
            return ret;
        }
911
        value = get_s(bc);
912 913

        if (value == -1) {
914 915 916 917 918
            ret = get_str(bc, str_value, sizeof(str_value));
            if (ret < 0) {
                av_log(s, AV_LOG_ERROR, "get_str failed while reading sm data\n");
                return ret;
            }
919 920 921 922 923
            av_log(s, AV_LOG_WARNING, "Unknown string %s / %s\n", name, str_value);
        } else if (value == -2) {
            uint8_t *dst = NULL;
            int64_t v64, value_len;

924 925 926 927 928
            ret = get_str(bc, type_str, sizeof(type_str));
            if (ret < 0) {
                av_log(s, AV_LOG_ERROR, "get_str failed while reading sm data\n");
                return ret;
            }
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
            value_len = ffio_read_varlen(bc);
            if (avio_tell(bc) + value_len >= maxpos)
                return AVERROR_INVALIDDATA;
            if (!strcmp(name, "Palette")) {
                dst = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, value_len);
            } else if (!strcmp(name, "Extradata")) {
                dst = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, value_len);
            } else if (sscanf(name, "CodecSpecificSide%"SCNd64"", &v64) == 1) {
                dst = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, value_len + 8);
                if(!dst)
                    return AVERROR(ENOMEM);
                AV_WB64(dst, v64);
                dst += 8;
            } else if (!strcmp(name, "ChannelLayout") && value_len == 8) {
                channel_layout = avio_rl64(bc);
                continue;
            } else {
                av_log(s, AV_LOG_WARNING, "Unknown data %s / %s\n", name, type_str);
                avio_skip(bc, value_len);
                continue;
            }
            if(!dst)
                return AVERROR(ENOMEM);
            avio_read(bc, dst, value_len);
        } else if (value == -3) {
            value = get_s(bc);
        } else if (value == -4) {
            value = ffio_read_varlen(bc);
        } else if (value < -4) {
            get_s(bc);
        } else {
            if (!strcmp(name, "SkipStart")) {
                skip_start = value;
            } else if (!strcmp(name, "SkipEnd")) {
                skip_end = value;
            } else if (!strcmp(name, "Channels")) {
                channels = value;
            } else if (!strcmp(name, "SampleRate")) {
                sample_rate = value;
            } else if (!strcmp(name, "Width")) {
                width = value;
            } else if (!strcmp(name, "Height")) {
                height = value;
            } else {
                av_log(s, AV_LOG_WARNING, "Unknown integer %s\n", name);
            }
        }
    }

    if (channels || channel_layout || sample_rate || width || height) {
        uint8_t *dst = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, 28);
        if (!dst)
            return AVERROR(ENOMEM);
        bytestream_put_le32(&dst,
                            AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT*(!!channels) +
                            AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT*(!!channel_layout) +
                            AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE*(!!sample_rate) +
                            AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS*(!!(width|height))
                           );
        if (channels)
            bytestream_put_le32(&dst, channels);
        if (channel_layout)
            bytestream_put_le64(&dst, channel_layout);
        if (sample_rate)
            bytestream_put_le32(&dst, sample_rate);
        if (width || height){
            bytestream_put_le32(&dst, width);
            bytestream_put_le32(&dst, height);
        }
    }

    if (skip_start || skip_end) {
        uint8_t *dst = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
        if (!dst)
            return AVERROR(ENOMEM);
        AV_WL32(dst, skip_start);
        AV_WL32(dst+4, skip_end);
    }

1008 1009 1010
    if (avio_tell(bc) >= maxpos)
        return AVERROR_INVALIDDATA;

1011 1012 1013
    return 0;
}

1014 1015 1016 1017 1018
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;
1019
    StreamContext *stc;
1020
    int size, flags, size_mul, pts_delta, i, reserved_count, ret;
1021 1022
    uint64_t tmp;

1023 1024
    if (!(nut->flags & NUT_PIPE) &&
        avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) {
1025 1026 1027
        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);
1028
        return AVERROR_INVALIDDATA;
1029 1030 1031 1032 1033 1034 1035 1036
    }

    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;
1037
    *header_idx    = nut->frame_code[frame_code].header_idx;
1038

1039
    if (flags & FLAG_INVALID)
1040
        return AVERROR_INVALIDDATA;
1041
    if (flags & FLAG_CODED)
1042
        flags ^= ffio_read_varlen(bc);
1043
    if (flags & FLAG_STREAM_ID) {
1044
        GET_V(*stream_id, tmp < s->nb_streams);
1045
    }
1046 1047 1048 1049 1050 1051 1052
    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
1053
            *pts = coded_pts - (1LL << stc->msb_pts_shift);
1054 1055 1056 1057 1058
    } else
        *pts = stc->last_pts + pts_delta;
    if (flags & FLAG_SIZE_MSB)
        size += size_mul * ffio_read_varlen(bc);
    if (flags & FLAG_MATCH_TIME)
1059
        get_s(bc);
1060 1061 1062 1063
    if (flags & FLAG_HEADER_IDX)
        *header_idx = ffio_read_varlen(bc);
    if (flags & FLAG_RESERVED)
        reserved_count = ffio_read_varlen(bc);
1064 1065 1066 1067 1068
    for (i = 0; i < reserved_count; i++) {
        if (bc->eof_reached) {
            av_log(s, AV_LOG_ERROR, "reached EOF while decoding frame header\n");
            return AVERROR_INVALIDDATA;
        }
1069
        ffio_read_varlen(bc);
1070
    }
1071

1072
    if (*header_idx >= (unsigned)nut->header_count) {
1073
        av_log(s, AV_LOG_ERROR, "header_idx invalid\n");
1074
        return AVERROR_INVALIDDATA;
1075
    }
1076 1077
    if (size > 4096)
        *header_idx = 0;
1078 1079
    size -= nut->header_len[*header_idx];

1080 1081
    if (flags & FLAG_CHECKSUM) {
        avio_rb32(bc); // FIXME check this
1082 1083 1084
    } else if (!(nut->flags & NUT_PIPE) &&
               size > 2 * nut->max_distance ||
               FFABS(stc->last_pts - *pts) > stc->max_pts_distance) {
1085
        av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
1086
        return AVERROR_INVALIDDATA;
1087 1088
    }

1089 1090
    stc->last_pts   = *pts;
    stc->last_flags = flags;
1091 1092

    return size;
1093 1094
fail:
    return ret;
1095 1096
}

1097 1098 1099 1100
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
1101
    int size, stream_id, discard, ret;
1102
    int64_t pts, last_IP_pts;
1103
    StreamContext *stc;
1104
    uint8_t header_idx;
1105

1106 1107
    size = decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
    if (size < 0)
1108
        return size;
1109

1110
    stc = &nut->stream[stream_id];
1111 1112

    if (stc->last_flags & FLAG_KEY)
1113 1114 1115 1116 1117 1118 1119 1120 1121
        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) {
1122
        avio_skip(bc, size);
1123 1124 1125
        return 1;
    }

1126 1127 1128
    ret = av_new_packet(pkt, size + nut->header_len[header_idx]);
    if (ret < 0)
        return ret;
1129
    memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
1130
    pkt->pos = avio_tell(bc); // FIXME
1131 1132
    if (stc->last_flags & FLAG_SM_DATA) {
        int sm_size;
1133 1134 1135 1136 1137 1138 1139 1140
        if (read_sm_data(s, bc, pkt, 0, pkt->pos + size) < 0) {
            ret = AVERROR_INVALIDDATA;
            goto fail;
        }
        if (read_sm_data(s, bc, pkt, 1, pkt->pos + size) < 0) {
            ret = AVERROR_INVALIDDATA;
            goto fail;
        }
1141 1142 1143 1144 1145
        sm_size = avio_tell(bc) - pkt->pos;
        size      -= sm_size;
        pkt->size -= sm_size;
    }

1146 1147 1148
    ret = avio_read(bc, pkt->data + nut->header_len[header_idx], size);
    if (ret != size) {
        if (ret < 0)
1149
            goto fail;
1150
    }
1151
    av_shrink_packet(pkt, nut->header_len[header_idx] + ret);
1152

1153
    pkt->stream_index = stream_id;
1154
    if (stc->last_flags & FLAG_KEY)
1155
        pkt->flags |= AV_PKT_FLAG_KEY;
1156 1157 1158
    pkt->pts = pts;

    return 0;
1159 1160 1161
fail:
    av_free_packet(pkt);
    return ret;
1162 1163 1164 1165 1166
}

static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    NUTContext *nut = s->priv_data;
1167
    AVIOContext *bc = s->pb;
1168
    int i, frame_code = 0, ret, skip;
1169
    int64_t ts, back_ptr;
1170

1171 1172 1173 1174
    for (;;) {
        int64_t pos  = avio_tell(bc);
        uint64_t tmp = nut->next_startcode;
        nut->next_startcode = 0;
1175

1176 1177 1178
        if (tmp) {
            pos -= 8;
        } else {
1179
            frame_code = avio_r8(bc);
1180
            if (avio_feof(bc))
1181
                return AVERROR_EOF;
1182 1183 1184 1185
            if (frame_code == 'N') {
                tmp = frame_code;
                for (i = 1; i < 8; i++)
                    tmp = (tmp << 8) + avio_r8(bc);
1186 1187
            }
        }
1188
        switch (tmp) {
1189 1190 1191
        case MAIN_STARTCODE:
        case STREAM_STARTCODE:
        case INDEX_STARTCODE:
1192
            skip = get_packetheader(nut, bc, 0, tmp);
1193
            avio_skip(bc, skip);
1194 1195
            break;
        case INFO_STARTCODE:
1196
            if (decode_info_header(nut) < 0)
1197 1198 1199
                goto resync;
            break;
        case SYNCPOINT_STARTCODE:
1200
            if (decode_syncpoint(nut, &ts, &back_ptr) < 0)
1201
                goto resync;
1202
            frame_code = avio_r8(bc);
1203
        case 0:
1204 1205
            ret = decode_frame(nut, pkt, frame_code);
            if (ret == 0)
1206
                return 0;
1207
            else if (ret == 1) // OK but discard packet
1208 1209 1210
                break;
        default:
resync:
1211
            av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
1212 1213
            tmp = find_any_startcode(bc, FFMAX(nut->last_syncpoint_pos, nut->last_resync_pos) + 1);
            nut->last_resync_pos = avio_tell(bc);
1214
            if (tmp == 0)
1215
                return AVERROR_INVALIDDATA;
1216 1217
            av_log(s, AV_LOG_DEBUG, "sync\n");
            nut->next_startcode = tmp;
1218 1219 1220 1221
        }
    }
}

1222 1223 1224
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
                                  int64_t *pos_arg, int64_t pos_limit)
{
1225
    NUTContext *nut = s->priv_data;
1226
    AVIOContext *bc = s->pb;
1227
    int64_t pos, pts, back_ptr;
1228 1229
    av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n",
           stream_index, *pos_arg, pos_limit);
1230

1231 1232 1233 1234
    pos = *pos_arg;
    do {
        pos = find_startcode(bc, SYNCPOINT_STARTCODE, pos) + 1;
        if (pos < 1) {
1235
            av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
1236 1237
            return AV_NOPTS_VALUE;
        }
1238 1239
    } while (decode_syncpoint(nut, &pts, &back_ptr) < 0);
    *pos_arg = pos - 1;
1240
    av_assert0(nut->last_syncpoint_pos == *pos_arg);
1241

1242
    av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts, back_ptr);
1243
    if (stream_index == -2)
1244
        return back_ptr;
1245 1246
    av_assert0(stream_index == -1);
    return pts;
1247 1248
}

1249 1250 1251 1252 1253 1254 1255 1256
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 };
1257
    int64_t pos, pos2, ts;
1258
    int i;
1259

1260 1261 1262 1263
    if (nut->flags & NUT_PIPE) {
        return AVERROR(ENOSYS);
    }

1264 1265
    if (st->index_entries) {
        int index = av_index_search_timestamp(st, pts, flags);
1266 1267
        if (index < 0)
            index = av_index_search_timestamp(st, pts, flags ^ AVSEEK_FLAG_BACKWARD);
1268
        if (index < 0)
Michael Niedermayer's avatar
Michael Niedermayer committed
1269 1270
            return -1;

1271 1272 1273
        pos2 = st->index_entries[index].pos;
        ts   = st->index_entries[index].timestamp;
    } else {
1274 1275
        av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pts_cmp,
                     (void **) next_node);
1276 1277 1278 1279 1280 1281 1282
        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);
1283 1284
        if (pos < 0)
            return pos;
1285 1286 1287 1288

        if (!(flags & AVSEEK_FLAG_BACKWARD)) {
            dummy.pos    = pos + 16;
            next_node[1] = &nopts_sp;
1289 1290
            av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
                         (void **) next_node);
1291 1292 1293 1294 1295 1296 1297
            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
1298
        }
1299 1300 1301
        dummy.pos = pos;
        sp = av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
                          NULL);
Michael Niedermayer's avatar
Michael Niedermayer committed
1302

1303
        av_assert0(sp);
1304
        pos2 = sp->back_ptr - 15;
Michael Niedermayer's avatar
Michael Niedermayer committed
1305 1306
    }
    av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
1307
    pos = find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);
1308
    avio_seek(s->pb, pos, SEEK_SET);
1309
    nut->last_syncpoint_pos = pos;
1310
    av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
1311
    if (pos2 > pos || pos2 + 15 < pos)
1312
        av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
1313 1314
    for (i = 0; i < s->nb_streams; i++)
        nut->stream[i].skip_until_key_frame = 1;
1315

1316 1317
    nut->last_resync_pos = 0;

1318 1319 1320
    return 0;
}

1321
AVInputFormat ff_nut_demuxer = {
1322
    .name           = "nut",
1323
    .long_name      = NULL_IF_CONFIG_SMALL("NUT"),
1324
    .flags          = AVFMT_SEEK_TO_PTS,
1325 1326 1327 1328 1329 1330
    .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,
1331
    .extensions     = "nut",
1332
    .codec_tag      = ff_nut_codec_tags,
1333
};