nutdec.c 33.4 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/mathematics.h"
28
#include "libavutil/tree.h"
29
#include "avio_internal.h"
30 31
#include "nut.h"

32 33
#define NUT_MAX_STREAMS 256    /* arbitrary sanity check value */

34 35 36
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
                                  int64_t *pos_arg, int64_t pos_limit);

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

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

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

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

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

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

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

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

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

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

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

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

100
static inline uint64_t get_4cc_trace(AVIOContext *bc, char *file,
101 102
                                    char *func, int line)
{
103
    uint64_t v = get_fourcc(bc);
104

105
    av_log(NULL, AV_LOG_DEBUG, "get_fourcc %5"PRId64" / %"PRIX64" in %s %s:%d\n",
106
           v, v, file, func, line);
107 108
    return v;
}
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__)
111
#define get_fourcc(bc)       get_4cc_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
112 113
#endif

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

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

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

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

    return size;
}

135 136 137 138 139 140 141 142
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);
143
    while (!url_feof(bc)) {
144 145
        state = (state << 8) | avio_r8(bc);
        if ((state >> 56) != 'N')
146
            continue;
147
        switch (state) {
148 149 150 151 152 153 154 155 156 157 158 159 160
        case MAIN_STARTCODE:
        case STREAM_STARTCODE:
        case SYNCPOINT_STARTCODE:
        case INFO_STARTCODE:
        case INDEX_STARTCODE:
            return state;
        }
    }

    return 0;
}

/**
161
 * Find the given startcode.
162 163
 * @param code the startcode
 * @param pos the start position of the search, or -1 if the current position
164
 * @return the position of the startcode or -1 if not found
165
 */
166 167 168 169 170
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)
171
            return avio_tell(bc) - 8;
172
        else if (startcode == 0)
173
            return -1;
174
        pos = -1;
175 176 177
    }
}

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

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

191 192 193 194 195 196 197 198 199
#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);  \
            return -1;                                                        \
        }                                                                     \
        dst = tmp;                                                            \
    } while (0)
200

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

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

223
    end  = get_packetheader(nut, bc, 1, MAIN_STARTCODE);
224
    end += avio_tell(bc);
225

226 227
    GET_V(tmp, tmp >= 2 && tmp <= 3);
    GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS);
228

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

235
    GET_V(nut->time_base_count, tmp > 0 && tmp < INT_MAX / sizeof(AVRational));
236
    nut->time_base = av_malloc(nut->time_base_count * sizeof(AVRational));
237

238
    for (i = 0; i < nut->time_base_count; i++) {
239 240
        GET_V(nut->time_base[i].num, tmp > 0 && tmp < (1ULL << 31));
        GET_V(nut->time_base[i].den, tmp > 0 && tmp < (1ULL << 31));
241
        if (av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1) {
242
            av_log(s, AV_LOG_ERROR, "time base invalid\n");
243
            return AVERROR_INVALIDDATA;
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 278 279 280
    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) {
281
            av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
282
            return AVERROR_INVALIDDATA;
283
        }
284
        if (tmp_stream >= stream_count) {
285
            av_log(s, AV_LOG_ERROR, "illegal stream number\n");
286
            return AVERROR_INVALIDDATA;
287 288
        }

289
        for (j = 0; j < count; j++, i++) {
290
            if (i == 'N') {
291
                nut->frame_code[i].flags = FLAG_INVALID;
292 293 294
                j--;
                continue;
            }
295 296 297 298 299 300 301
            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;
302 303
        }
    }
304
    av_assert0(nut->frame_code['N'].flags == FLAG_INVALID);
305

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

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

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

    return 0;
}

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

348
    end  = get_packetheader(nut, bc, 1, STREAM_STARTCODE);
349
    end += avio_tell(bc);
350

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

357 358 359 360 361 362 363 364
    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,
365
                                                    ff_codec_bmp_tags,
366 367 368 369 370 371
                                                    0
                                                },
                                                tmp);
        break;
    case 1:
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
372 373 374 375 376 377
        st->codec->codec_id   = av_codec_get_id((const AVCodecTag * const []) {
                                                    ff_nut_audio_tags,
                                                    ff_codec_wav_tags,
                                                    0
                                                },
                                                tmp);
378 379 380 381 382 383 384 385 386 387 388
        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;
389
    }
390
    if (class < 3 && st->codec->codec_id == AV_CODEC_ID_NONE)
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
        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);
406
        avio_read(bc, st->codec->extradata, st->codec->extradata_size);
407 408
    }

409
    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
410 411
        GET_V(st->codec->width,  tmp > 0);
        GET_V(st->codec->height, tmp > 0);
412 413 414 415 416
        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);
417 418
            return -1;
        }
419
        ffio_read_varlen(bc); /* csp type */
420
    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
421
        GET_V(st->codec->sample_rate, tmp > 0);
422
        ffio_read_varlen(bc); // samplerate_den
423
        GET_V(st->codec->channels, tmp > 0);
424
    }
425 426 427
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
        av_log(s, AV_LOG_ERROR,
               "stream header %d checksum mismatch\n", stream_id);
428 429
        return -1;
    }
430 431 432
    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);
433 434 435
    return 0;
}

436 437 438
static void set_disposition_bits(AVFormatContext *avf, char *value,
                                 int stream_id)
{
439
    int flag = 0, i;
440 441

    for (i = 0; ff_nut_dispositions[i].flag; ++i)
442 443 444 445 446 447 448 449 450
        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;
}

451 452 453 454
static int decode_info_header(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
455 456
    uint64_t tmp, chapter_start, chapter_len;
    unsigned int stream_id_plus1, count;
457 458
    int chapter_id, i;
    int64_t value, end;
459
    char name[256], str_value[1024], type_str[256];
460
    const char *type;
461 462
    AVChapter *chapter      = NULL;
    AVStream *st            = NULL;
463
    AVDictionary **metadata = NULL;
464

465
    end  = get_packetheader(nut, bc, 1, INFO_STARTCODE);
466
    end += avio_tell(bc);
467

468
    GET_V(stream_id_plus1, tmp <= s->nb_streams);
469 470 471 472 473 474 475 476 477 478 479
    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);
480
        metadata = &chapter->metadata;
481 482
    } else if (stream_id_plus1) {
        st       = s->streams[stream_id_plus1 - 1];
483 484 485
        metadata = &st->metadata;
    } else
        metadata = &s->metadata;
486

487
    for (i = 0; i < count; i++) {
488
        get_str(bc, name, sizeof(name));
489 490 491
        value = get_s(bc);
        if (value == -1) {
            type = "UTF-8";
492
            get_str(bc, str_value, sizeof(str_value));
493
        } else if (value == -2) {
494
            get_str(bc, type_str, sizeof(type_str));
495
            type = type_str;
496
            get_str(bc, str_value, sizeof(str_value));
497 498 499 500 501 502 503 504
        } 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";
505
            get_s(bc);
506 507
        } else {
            type = "v";
508 509
        }

510
        if (stream_id_plus1 > s->nb_streams) {
511 512 513 514
            av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n");
            continue;
        }

515 516
        if (!strcmp(type, "UTF-8")) {
            if (chapter_id == 0 && !strcmp(name, "Disposition")) {
517
                set_disposition_bits(s, str_value, stream_id_plus1 - 1);
518 519
                continue;
            }
520 521 522 523 524 525

            if (stream_id_plus1 && !strcmp(name, "r_frame_rate")) {
                sscanf(str_value, "%d/%d", &st->r_frame_rate.num, &st->r_frame_rate.den);
                continue;
            }

526 527
            if (metadata && av_strcasecmp(name, "Uses") &&
                av_strcasecmp(name, "Depends") && av_strcasecmp(name, "Replaces"))
528
                av_dict_set(metadata, name, str_value, 0);
529
        }
530 531
    }

532
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
533
        av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n");
534 535 536 537 538
        return -1;
    }
    return 0;
}

539 540 541 542
static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
543 544
    int64_t end;
    uint64_t tmp;
545

546
    nut->last_syncpoint_pos = avio_tell(bc) - 8;
547

548
    end  = get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE);
549
    end += avio_tell(bc);
550

551 552 553
    tmp       = ffio_read_varlen(bc);
    *back_ptr = nut->last_syncpoint_pos - 16 * ffio_read_varlen(bc);
    if (*back_ptr < 0)
554
        return -1;
555

556 557
    ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count],
                    tmp / nut->time_base_count);
558

559
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
560
        av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
561 562
        return -1;
    }
563

564 565
    *ts = tmp / nut->time_base_count *
          av_q2d(nut->time_base[tmp % nut->time_base_count]) * AV_TIME_BASE;
566
    ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
567

568 569 570
    return 0;
}

571 572 573 574 575 576 577 578 579 580 581 582 583 584
//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;

    int64_t pos = FFMAX(0, filesize - 2*nut->max_distance);
    for(;;){
        int64_t ts = nut_read_timestamp(s, -1, &pos, INT64_MAX);
        if(ts < 0)
            break;
        duration = FFMAX(duration, ts);
        pos++;
    }
585 586
    if(duration > 0)
        s->duration_estimation_method = AVFMT_DURATION_FROM_PTS;
587 588 589
    return duration;
}

590 591 592 593
static int find_and_decode_index(NUTContext *nut)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
594 595
    uint64_t tmp, end;
    int i, j, syncpoint_count;
596
    int64_t filesize = avio_size(bc);
597 598
    int64_t *syncpoints;
    int8_t *has_keyframe;
599
    int ret = -1;
600

601 602 603
    if(filesize <= 0)
        return -1;

604 605 606
    avio_seek(bc, filesize - 12, SEEK_SET);
    avio_seek(bc, filesize - avio_rb64(bc), SEEK_SET);
    if (avio_rb64(bc) != INDEX_STARTCODE) {
607
        av_log(s, AV_LOG_ERROR, "no index at the end\n");
608 609 610

        if(s->duration<=0)
            s->duration = find_duration(nut, filesize);
611 612 613
        return -1;
    }

614
    end  = get_packetheader(nut, bc, 1, INDEX_STARTCODE);
615
    end += avio_tell(bc);
616

617
    ffio_read_varlen(bc); // max_pts
618
    GET_V(syncpoint_count, tmp < INT_MAX / 8 && tmp > 0);
619 620 621
    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++) {
622
        syncpoints[i] = ffio_read_varlen(bc);
623
        if (syncpoints[i] <= 0)
624
            goto fail;
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
        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) {
640
                    av_log(s, AV_LOG_ERROR, "index overflow A %d + %"PRIu64" >= %d\n", n, x, syncpoint_count + 1);
641
                    goto fail;
642
                }
643 644 645 646 647 648
                while (x--)
                    has_keyframe[n++] = flag;
                has_keyframe[n++] = !flag;
            } else {
                while (x != 1) {
                    if (n >= syncpoint_count + 1) {
649
                        av_log(s, AV_LOG_ERROR, "index overflow B\n");
650
                        goto fail;
651
                    }
652 653
                    has_keyframe[n++] = x & 1;
                    x >>= 1;
654 655
                }
            }
656
            if (has_keyframe[0]) {
657
                av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
658
                goto fail;
659
            }
660
            av_assert0(n <= syncpoint_count + 1);
661 662 663 664 665 666 667 668 669 670 671
            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);
672 673 674 675 676 677
                    last_pts += A + B;
                }
            }
        }
    }

678
    if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
679
        av_log(s, AV_LOG_ERROR, "index checksum mismatch\n");
680
        goto fail;
681
    }
682 683
    ret = 0;

684 685 686 687
fail:
    av_free(syncpoints);
    av_free(has_keyframe);
    return ret;
688 689
}

690
static int nut_read_header(AVFormatContext *s)
691 692
{
    NUTContext *nut = s->priv_data;
693
    AVIOContext *bc = s->pb;
694
    int64_t pos;
695
    int initialized_stream_count;
696

697
    nut->avf = s;
698 699

    /* main header */
700 701 702 703
    pos = 0;
    do {
        pos = find_startcode(bc, MAIN_STARTCODE, pos) + 1;
        if (pos < 0 + 1) {
704
            av_log(s, AV_LOG_ERROR, "No main startcode found.\n");
705
            return AVERROR_INVALIDDATA;
706
        }
707
    } while (decode_main_header(nut) < 0);
708 709

    /* stream headers */
710 711 712 713
    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) {
714
            av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n");
715
            return AVERROR_INVALIDDATA;
716
        }
717
        if (decode_stream_header(nut) >= 0)
718
            initialized_stream_count++;
719 720 721
    }

    /* info headers */
722 723 724 725
    pos = 0;
    for (;;) {
        uint64_t startcode = find_any_startcode(bc, pos);
        pos = avio_tell(bc);
726

727
        if (startcode == 0) {
728
            av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
729
            return AVERROR_INVALIDDATA;
730 731
        } else if (startcode == SYNCPOINT_STARTCODE) {
            nut->next_startcode = startcode;
732
            break;
733
        } else if (startcode != INFO_STARTCODE) {
734 735 736 737 738 739
            continue;
        }

        decode_info_header(nut);
    }

740
    s->data_offset = pos - 8;
741

742 743
    if (bc->seekable) {
        int64_t orig_pos = avio_tell(bc);
744
        find_and_decode_index(nut);
745
        avio_seek(bc, orig_pos, SEEK_SET);
746
    }
747
    av_assert0(nut->next_startcode == SYNCPOINT_STARTCODE);
748

749 750
    ff_metadata_conv_ctx(s, NULL, ff_nut_metadata_conv);

751 752 753
    return 0;
}

754 755 756 757 758
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;
759 760 761 762
    StreamContext *stc;
    int size, flags, size_mul, pts_delta, i, reserved_count;
    uint64_t tmp;

763 764 765 766
    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);
767
        return AVERROR_INVALIDDATA;
768 769 770 771 772 773 774 775
    }

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

778
    if (flags & FLAG_INVALID)
779
        return AVERROR_INVALIDDATA;
780
    if (flags & FLAG_CODED)
781
        flags ^= ffio_read_varlen(bc);
782
    if (flags & FLAG_STREAM_ID) {
783
        GET_V(*stream_id, tmp < s->nb_streams);
784
    }
785 786 787 788 789 790 791 792 793 794 795 796 797
    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)
798
        get_s(bc);
799 800 801 802 803
    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++)
804
        ffio_read_varlen(bc);
805

806
    if (*header_idx >= (unsigned)nut->header_count) {
807
        av_log(s, AV_LOG_ERROR, "header_idx invalid\n");
808
        return AVERROR_INVALIDDATA;
809
    }
810 811
    if (size > 4096)
        *header_idx = 0;
812 813
    size -= nut->header_len[*header_idx];

814 815 816 817
    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) {
818
        av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
819
        return AVERROR_INVALIDDATA;
820 821
    }

822 823
    stc->last_pts   = *pts;
    stc->last_flags = flags;
824 825 826 827

    return size;
}

828 829 830 831
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code)
{
    AVFormatContext *s = nut->avf;
    AVIOContext *bc    = s->pb;
832
    int size, stream_id, discard;
833
    int64_t pts, last_IP_pts;
834
    StreamContext *stc;
835
    uint8_t header_idx;
836

837 838
    size = decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
    if (size < 0)
839
        return size;
840

841
    stc = &nut->stream[stream_id];
842 843

    if (stc->last_flags & FLAG_KEY)
844 845 846 847 848 849 850 851 852
        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) {
853
        avio_skip(bc, size);
854 855 856
        return 1;
    }

857 858
    av_new_packet(pkt, size + nut->header_len[header_idx]);
    memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
859
    pkt->pos = avio_tell(bc); // FIXME
860
    avio_read(bc, pkt->data + nut->header_len[header_idx], size);
861

862
    pkt->stream_index = stream_id;
863
    if (stc->last_flags & FLAG_KEY)
864
        pkt->flags |= AV_PKT_FLAG_KEY;
865 866 867 868 869 870 871 872
    pkt->pts = pts;

    return 0;
}

static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    NUTContext *nut = s->priv_data;
873
    AVIOContext *bc = s->pb;
874
    int i, frame_code = 0, ret, skip;
875
    int64_t ts, back_ptr;
876

877 878 879 880
    for (;;) {
        int64_t pos  = avio_tell(bc);
        uint64_t tmp = nut->next_startcode;
        nut->next_startcode = 0;
881

882 883 884
        if (tmp) {
            pos -= 8;
        } else {
885
            frame_code = avio_r8(bc);
886
            if (url_feof(bc))
887
                return -1;
888 889 890 891
            if (frame_code == 'N') {
                tmp = frame_code;
                for (i = 1; i < 8; i++)
                    tmp = (tmp << 8) + avio_r8(bc);
892 893
            }
        }
894
        switch (tmp) {
895 896 897
        case MAIN_STARTCODE:
        case STREAM_STARTCODE:
        case INDEX_STARTCODE:
898
            skip = get_packetheader(nut, bc, 0, tmp);
899
            avio_skip(bc, skip);
900 901
            break;
        case INFO_STARTCODE:
902
            if (decode_info_header(nut) < 0)
903 904 905
                goto resync;
            break;
        case SYNCPOINT_STARTCODE:
906
            if (decode_syncpoint(nut, &ts, &back_ptr) < 0)
907
                goto resync;
908
            frame_code = avio_r8(bc);
909
        case 0:
910 911
            ret = decode_frame(nut, pkt, frame_code);
            if (ret == 0)
912
                return 0;
913
            else if (ret == 1) // OK but discard packet
914 915 916
                break;
        default:
resync:
917 918 919
            av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
            tmp = find_any_startcode(bc, nut->last_syncpoint_pos + 1);
            if (tmp == 0)
920
                return AVERROR_INVALIDDATA;
921 922
            av_log(s, AV_LOG_DEBUG, "sync\n");
            nut->next_startcode = tmp;
923 924 925 926
        }
    }
}

927 928 929
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
                                  int64_t *pos_arg, int64_t pos_limit)
{
930
    NUTContext *nut = s->priv_data;
931
    AVIOContext *bc = s->pb;
932
    int64_t pos, pts, back_ptr;
933 934
    av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n",
           stream_index, *pos_arg, pos_limit);
935

936 937 938 939
    pos = *pos_arg;
    do {
        pos = find_startcode(bc, SYNCPOINT_STARTCODE, pos) + 1;
        if (pos < 1) {
940
            av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
941 942
            return AV_NOPTS_VALUE;
        }
943 944
    } while (decode_syncpoint(nut, &pts, &back_ptr) < 0);
    *pos_arg = pos - 1;
945
    av_assert0(nut->last_syncpoint_pos == *pos_arg);
946

947
    av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts, back_ptr);
948
    if (stream_index == -2)
949
        return back_ptr;
950 951
    av_assert0(stream_index == -1);
    return pts;
952 953
}

954 955 956 957 958 959 960 961
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 };
962
    int64_t pos, pos2, ts;
963
    int i;
964

965 966
    if (st->index_entries) {
        int index = av_index_search_timestamp(st, pts, flags);
967 968
        if (index < 0)
            index = av_index_search_timestamp(st, pts, flags ^ AVSEEK_FLAG_BACKWARD);
969
        if (index < 0)
Michael Niedermayer's avatar
Michael Niedermayer committed
970 971
            return -1;

972 973 974
        pos2 = st->index_entries[index].pos;
        ts   = st->index_entries[index].timestamp;
    } else {
975 976
        av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pts_cmp,
                     (void **) next_node);
977 978 979 980 981 982 983 984 985 986 987
        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;
988 989
            av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
                         (void **) next_node);
990 991 992 993 994 995 996
            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
997
        }
998 999 1000
        dummy.pos = pos;
        sp = av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
                          NULL);
Michael Niedermayer's avatar
Michael Niedermayer committed
1001

1002
        av_assert0(sp);
1003
        pos2 = sp->back_ptr - 15;
Michael Niedermayer's avatar
Michael Niedermayer committed
1004 1005
    }
    av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
1006
    pos = find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);
1007
    avio_seek(s->pb, pos, SEEK_SET);
1008
    av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
1009
    if (pos2 > pos || pos2 + 15 < pos)
1010
        av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
1011 1012
    for (i = 0; i < s->nb_streams; i++)
        nut->stream[i].skip_until_key_frame = 1;
1013

1014 1015 1016
    return 0;
}

1017 1018 1019
static int nut_read_close(AVFormatContext *s)
{
    NUTContext *nut = s->priv_data;
1020
    int i;
1021 1022 1023

    av_freep(&nut->time_base);
    av_freep(&nut->stream);
1024
    ff_nut_free_sp(nut);
1025
    for (i = 1; i < nut->header_count; i++)
1026
        av_freep(&nut->header[i]);
1027 1028 1029 1030

    return 0;
}

1031
AVInputFormat ff_nut_demuxer = {
1032
    .name           = "nut",
1033
    .long_name      = NULL_IF_CONFIG_SMALL("NUT"),
1034
    .flags          = AVFMT_SEEK_TO_PTS,
1035 1036 1037 1038 1039 1040
    .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,
1041
    .extensions     = "nut",
1042
    .codec_tag      = ff_nut_codec_tags,
1043
};