nutenc.c 41.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * nut muxer
 * Copyright (c) 2004-2007 Michael Niedermayer
 *
 * 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
 */

22 23
#include <stdint.h>

24
#include "libavutil/intreadwrite.h"
25
#include "libavutil/mathematics.h"
26
#include "libavutil/tree.h"
27
#include "libavutil/dict.h"
28
#include "libavutil/avassert.h"
29 30
#include "libavutil/time.h"
#include "libavutil/opt.h"
31
#include "libavcodec/bytestream.h"
32
#include "libavcodec/mpegaudiodata.h"
33
#include "nut.h"
34
#include "internal.h"
35
#include "avio_internal.h"
36
#include "riff.h"
37

38
static int find_expected_header(AVCodecParameters *p, int size, int key_frame,
39 40
                                uint8_t out[64])
{
41
    int sample_rate = p->sample_rate;
42

43
    if (size > 4096)
44 45 46 47
        return 0;

    AV_WB24(out, 1);

48
    if (p->codec_id == AV_CODEC_ID_MPEG4) {
49
        if (key_frame) {
50
            return 3;
51 52
        } else {
            out[3] = 0xB6;
53 54
            return 4;
        }
55 56
    } else if (p->codec_id == AV_CODEC_ID_MPEG1VIDEO ||
               p->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
57
        return 3;
58
    } else if (p->codec_id == AV_CODEC_ID_H264) {
59
        return 3;
60 61
    } else if (p->codec_id == AV_CODEC_ID_MP3 ||
               p->codec_id == AV_CODEC_ID_MP2) {
62
        int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size;
63
        int layer           = p->codec_id == AV_CODEC_ID_MP3 ? 3 : 2;
64
        unsigned int header = 0xFFF00000;
65

66 67
        lsf           = sample_rate < (24000 + 32000) / 2;
        mpeg25        = sample_rate < (12000 + 16000) / 2;
68
        sample_rate <<= lsf + mpeg25;
69 70 71
        if      (sample_rate < (32000 + 44100) / 2) sample_rate_index = 2;
        else if (sample_rate < (44100 + 48000) / 2) sample_rate_index = 0;
        else                                        sample_rate_index = 1;
72

73
        sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25);
74

75 76 77 78 79
        for (bitrate_index = 2; bitrate_index < 30; bitrate_index++) {
            frame_size =
                avpriv_mpa_bitrate_tab[lsf][layer - 1][bitrate_index >> 1];
            frame_size = (frame_size * 144000) / (sample_rate << lsf) +
                (bitrate_index & 1);
80

81
            if (frame_size == size)
82 83 84
                break;
        }

85 86 87
        header |= (!lsf) << 19;
        header |= (4 - layer) << 17;
        header |= 1 << 16; //no crc
88
        AV_WB32(out, header);
89 90 91 92
        if (size <= 0)
            return 2;  //we guess there is no crc, if there is one the user clearly does not care about overhead
        if (bitrate_index == 30)
            return -1;  //something is wrong ...
93

94 95 96
        header |= (bitrate_index >> 1) << 12;
        header |= sample_rate_index << 10;
        header |= (bitrate_index & 1) << 9;
97 98

        return 2; //FIXME actually put the needed ones in build_elision_headers()
99
        //return 3; //we guess that the private bit is not set
Diego Biurrun's avatar
Diego Biurrun committed
100
//FIXME the above assumptions should be checked, if these turn out false too often something should be done
101 102 103 104
    }
    return 0;
}

105
static int find_header_idx(AVFormatContext *s, AVCodecParameters *p, int size,
106 107
                           int frame_type)
{
108 109 110
    NUTContext *nut = s->priv_data;
    uint8_t out[64];
    int i;
111
    int len = find_expected_header(p, size, frame_type, out);
112

113 114
    for (i = 1; i < nut->header_count; i++) {
        if (len == nut->header_len[i] && !memcmp(out, nut->header[i], len)) {
115 116 117
            return i;
        }
    }
118

119 120 121
    return 0;
}

122 123
static void build_elision_headers(AVFormatContext *s)
{
124 125 126 127
    NUTContext *nut = s->priv_data;
    int i;
    //FIXME this is lame
    //FIXME write a 2pass mode to find the maximal headers
128 129 130 131 132 133 134
    static const uint8_t headers[][5] = {
        { 3, 0x00, 0x00, 0x01 },
        { 4, 0x00, 0x00, 0x01, 0xB6},
        { 2, 0xFF, 0xFA }, //mp3+crc
        { 2, 0xFF, 0xFB }, //mp3
        { 2, 0xFF, 0xFC }, //mp2+crc
        { 2, 0xFF, 0xFD }, //mp2
135 136
    };

137 138 139 140
    nut->header_count = 7;
    for (i = 1; i < nut->header_count; i++) {
        nut->header_len[i] = headers[i - 1][0];
        nut->header[i]     = &headers[i - 1][1];
141 142
    }
}
143

144 145
static void build_frame_code(AVFormatContext *s)
{
146 147
    NUTContext *nut = s->priv_data;
    int key_frame, index, pred, stream_id;
148 149 150
    int start = 1;
    int end   = 254;
    int keyframe_0_esc = s->nb_streams > 2;
151
    int pred_table[10];
152 153
    FrameCode *ft;

154 155 156 157
    ft            = &nut->frame_code[start];
    ft->flags     = FLAG_CODED;
    ft->size_mul  = 1;
    ft->pts_delta = 1;
158
    start++;
159

160
    if (keyframe_0_esc) {
161
        /* keyframe = 0 escape */
162 163 164
        FrameCode *ft = &nut->frame_code[start];
        ft->flags    = FLAG_STREAM_ID | FLAG_SIZE_MSB | FLAG_CODED_PTS;
        ft->size_mul = 1;
165 166 167
        start++;
    }

168 169 170
    for (stream_id = 0; stream_id < s->nb_streams; stream_id++) {
        int start2 = start + (end - start) * stream_id       / s->nb_streams;
        int end2   = start + (end - start) * (stream_id + 1) / s->nb_streams;
171 172
        AVCodecParameters *par        = s->streams[stream_id]->codecpar;
        int is_audio                  = par->codec_type == AVMEDIA_TYPE_AUDIO;
173
        int intra_only        = /*codec->intra_only || */ is_audio;
174
        int pred_count;
175 176
        int frame_size = 0;

177 178 179
        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
            frame_size = av_get_audio_frame_duration2(par, 0);
            if (par->codec_id == AV_CODEC_ID_VORBIS && !frame_size)
180 181
                frame_size = 64;
        } else {
182
            AVRational f = av_div_q(av_inv_q(s->streams[stream_id]->avg_frame_rate), *nut->stream[stream_id].time_base);
183
            if (f.den == 1 && f.num>0)
184
                frame_size = f.num;
185
        }
186
        if (!frame_size)
187
            frame_size = 1;
188

189 190 191 192 193 194 195 196
        for (key_frame = 0; key_frame < 2; key_frame++) {
            if (!intra_only || !keyframe_0_esc || key_frame != 0) {
                FrameCode *ft = &nut->frame_code[start2];
                ft->flags     = FLAG_KEY * key_frame;
                ft->flags    |= FLAG_SIZE_MSB | FLAG_CODED_PTS;
                ft->stream_id = stream_id;
                ft->size_mul  = 1;
                if (is_audio)
197
                    ft->header_idx = find_header_idx(s, par, -1, key_frame);
198 199 200 201
                start2++;
            }
        }

202
        key_frame = intra_only;
203
#if 1
204
        if (is_audio) {
205
            int frame_bytes;
206
            int pts;
207

208 209
            if (par->block_align > 0) {
                frame_bytes = par->block_align;
210
            } else {
211 212
                int frame_size = av_get_audio_frame_duration2(par, 0);
                frame_bytes = frame_size * (int64_t)par->bit_rate / (8 * par->sample_rate);
213 214
            }

215
            for (pts = 0; pts < 2; pts++) {
216
                for (pred = 0; pred < 2; pred++) {
217
                    FrameCode *ft  = &nut->frame_code[start2];
218 219 220 221
                    ft->flags      = FLAG_KEY * key_frame;
                    ft->stream_id  = stream_id;
                    ft->size_mul   = frame_bytes + 2;
                    ft->size_lsb   = frame_bytes + pred;
222
                    ft->pts_delta  = pts * frame_size;
223
                    ft->header_idx = find_header_idx(s, par, frame_bytes + pred, key_frame);
224 225 226
                    start2++;
                }
            }
227 228 229 230 231
        } else {
            FrameCode *ft = &nut->frame_code[start2];
            ft->flags     = FLAG_KEY | FLAG_SIZE_MSB;
            ft->stream_id = stream_id;
            ft->size_mul  = 1;
232
            ft->pts_delta = frame_size;
233 234
            start2++;
        }
235
#endif
236

237
        if (par->video_delay) {
238 239 240 241 242 243
            pred_count    = 5;
            pred_table[0] = -2;
            pred_table[1] = -1;
            pred_table[2] = 1;
            pred_table[3] = 3;
            pred_table[4] = 4;
244
        } else if (par->codec_id == AV_CODEC_ID_VORBIS) {
245 246 247 248 249 250 251
            pred_count    = 3;
            pred_table[0] = 2;
            pred_table[1] = 9;
            pred_table[2] = 16;
        } else {
            pred_count    = 1;
            pred_table[0] = 1;
252 253
        }

254 255 256
        for (pred = 0; pred < pred_count; pred++) {
            int start3 = start2 + (end2 - start2) * pred / pred_count;
            int end3   = start2 + (end2 - start2) * (pred + 1) / pred_count;
257

258 259
            pred_table[pred] *= frame_size;

260 261 262 263 264
            for (index = start3; index < end3; index++) {
                FrameCode *ft = &nut->frame_code[index];
                ft->flags     = FLAG_KEY * key_frame;
                ft->flags    |= FLAG_SIZE_MSB;
                ft->stream_id = stream_id;
265
//FIXME use single byte size and pred from last
266 267 268 269
                ft->size_mul  = end3 - start3;
                ft->size_lsb  = index - start3;
                ft->pts_delta = pred_table[pred];
                if (is_audio)
270
                    ft->header_idx = find_header_idx(s, par, -1, key_frame);
271 272 273
            }
        }
    }
274
    memmove(&nut->frame_code['N' + 1], &nut->frame_code['N'], sizeof(FrameCode) * (255 - 'N'));
275 276 277
    nut->frame_code[0].flags       =
        nut->frame_code[255].flags =
        nut->frame_code['N'].flags = FLAG_INVALID;
278 279
}

280
static void put_tt(NUTContext *nut, AVRational *time_base, AVIOContext *bc, uint64_t val)
281
{
Michael Niedermayer's avatar
Michael Niedermayer committed
282
    val *= nut->time_base_count;
Anton Khirnov's avatar
Anton Khirnov committed
283
    val += time_base - nut->time_base;
284
    ff_put_v(bc, val);
Michael Niedermayer's avatar
Michael Niedermayer committed
285
}
286
/**
287
 * Store a string as vb.
288
 */
289 290
static void put_str(AVIOContext *bc, const char *string)
{
291
    size_t len = strlen(string);
292

293
    ff_put_v(bc, len);
294
    avio_write(bc, string, len);
295 296
}

297 298 299
static void put_s(AVIOContext *bc, int64_t val)
{
    ff_put_v(bc, 2 * FFABS(val) - (val > 0));
300 301 302
}

#ifdef TRACE
303 304 305
static inline void ff_put_v_trace(AVIOContext *bc, uint64_t v, const char *file,
                                  const char *func, int line)
{
306
    av_log(NULL, AV_LOG_DEBUG, "ff_put_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
307

308
    ff_put_v(bc, v);
309 310
}

311
static inline void put_s_trace(AVIOContext *bc, int64_t v, const char *file, const char *func, int line)
312
{
Michael Niedermayer's avatar
Michael Niedermayer committed
313
    av_log(NULL, AV_LOG_DEBUG, "put_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
314 315 316

    put_s(bc, v);
}
317
#define ff_put_v(bc, v)  ff_put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
318 319 320
#define put_s(bc, v)  put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
#endif

Michael Niedermayer's avatar
Michael Niedermayer committed
321
//FIXME remove calculate_checksum
322 323 324 325 326 327
static void put_packet(NUTContext *nut, AVIOContext *bc, AVIOContext *dyn_bc,
                       int calculate_checksum, uint64_t startcode)
{
    uint8_t *dyn_buf = NULL;
    int dyn_size     = avio_close_dyn_buf(dyn_bc, &dyn_buf);
    int forw_ptr     = dyn_size + 4 * calculate_checksum;
Michael Niedermayer's avatar
Michael Niedermayer committed
328

329
    if (forw_ptr > 4096)
330
        ffio_init_checksum(bc, ff_crc04C11DB7_update, 0);
331
    avio_wb64(bc, startcode);
332
    ff_put_v(bc, forw_ptr);
333
    if (forw_ptr > 4096)
334
        avio_wl32(bc, ffio_get_checksum(bc));
335

336
    if (calculate_checksum)
337
        ffio_init_checksum(bc, ff_crc04C11DB7_update, 0);
338
    avio_write(bc, dyn_buf, dyn_size);
339
    if (calculate_checksum)
340
        avio_wl32(bc, ffio_get_checksum(bc));
341

342
    av_free(dyn_buf);
343 344
}

345 346 347 348
static void write_mainheader(NUTContext *nut, AVIOContext *bc)
{
    int i, j, tmp_pts, tmp_flags, tmp_stream, tmp_mul, tmp_size, tmp_fields,
        tmp_head_idx;
349
    int64_t tmp_match;
350

351
    ff_put_v(bc, nut->version);
352
    if (nut->version > 3)
353
        ff_put_v(bc, nut->minor_version = 1);
354 355 356
    ff_put_v(bc, nut->avf->nb_streams);
    ff_put_v(bc, nut->max_distance);
    ff_put_v(bc, nut->time_base_count);
357

358
    for (i = 0; i < nut->time_base_count; i++) {
359 360
        ff_put_v(bc, nut->time_base[i].num);
        ff_put_v(bc, nut->time_base[i].den);
361 362
    }

363 364 365 366 367 368 369 370
    tmp_pts      = 0;
    tmp_mul      = 1;
    tmp_stream   = 0;
    tmp_match    = 1 - (1LL << 62);
    tmp_head_idx = 0;
    for (i = 0; i < 256; ) {
        tmp_fields = 0;
        tmp_size   = 0;
371
//        tmp_res=0;
372 373 374 375 376 377
        if (tmp_pts      != nut->frame_code[i].pts_delta ) tmp_fields = 1;
        if (tmp_mul      != nut->frame_code[i].size_mul  ) tmp_fields = 2;
        if (tmp_stream   != nut->frame_code[i].stream_id ) tmp_fields = 3;
        if (tmp_size     != nut->frame_code[i].size_lsb  ) tmp_fields = 4;
//        if (tmp_res    != nut->frame_code[i].res            ) tmp_fields=5;
        if (tmp_head_idx != nut->frame_code[i].header_idx) tmp_fields = 8;
378 379 380 381 382 383

        tmp_pts    = nut->frame_code[i].pts_delta;
        tmp_flags  = nut->frame_code[i].flags;
        tmp_stream = nut->frame_code[i].stream_id;
        tmp_mul    = nut->frame_code[i].size_mul;
        tmp_size   = nut->frame_code[i].size_lsb;
384
//        tmp_res   = nut->frame_code[i].res;
385
        tmp_head_idx = nut->frame_code[i].header_idx;
386

387 388
        for (j = 0; i < 256; j++, i++) {
            if (i == 'N') {
389 390 391
                j--;
                continue;
            }
392 393 394 395 396 397 398 399
            if (nut->frame_code[i].pts_delta  != tmp_pts      ||
                nut->frame_code[i].flags      != tmp_flags    ||
                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].res        != tmp_res      ||
                nut->frame_code[i].header_idx != tmp_head_idx)
                break;
400
        }
401 402
        if (j != tmp_mul - tmp_size)
            tmp_fields = 6;
403

404 405
        ff_put_v(bc, tmp_flags);
        ff_put_v(bc, tmp_fields);
406 407 408 409 410 411 412 413
        if (tmp_fields > 0) put_s(bc, tmp_pts);
        if (tmp_fields > 1) ff_put_v(bc, tmp_mul);
        if (tmp_fields > 2) ff_put_v(bc, tmp_stream);
        if (tmp_fields > 3) ff_put_v(bc, tmp_size);
        if (tmp_fields > 4) ff_put_v(bc, 0 /*tmp_res*/);
        if (tmp_fields > 5) ff_put_v(bc, j);
        if (tmp_fields > 6) ff_put_v(bc, tmp_match);
        if (tmp_fields > 7) ff_put_v(bc, tmp_head_idx);
414
    }
415 416
    ff_put_v(bc, nut->header_count - 1);
    for (i = 1; i < nut->header_count; i++) {
417
        ff_put_v(bc, nut->header_len[i]);
418
        avio_write(bc, nut->header[i], nut->header_len[i]);
419
    }
420
    // flags had been effectively introduced in version 4
421
    if (nut->version > 3)
422
        ff_put_v(bc, nut->flags);
423
}
424

425 426 427 428
static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc,
                              AVStream *st, int i)
{
    NUTContext *nut       = avctx->priv_data;
429
    AVCodecParameters *par = st->codecpar;
430

431
    ff_put_v(bc, i);
432
    switch (par->codec_type) {
433 434
    case AVMEDIA_TYPE_VIDEO:    ff_put_v(bc, 0); break;
    case AVMEDIA_TYPE_AUDIO:    ff_put_v(bc, 1); break;
435
    case AVMEDIA_TYPE_SUBTITLE: ff_put_v(bc, 2); break;
436
    default:                    ff_put_v(bc, 3); break;
437
    }
438
    ff_put_v(bc, 4);
439

440 441
    if (par->codec_tag) {
        avio_wl32(bc, par->codec_tag);
442 443
    } else {
        av_log(avctx, AV_LOG_ERROR, "No codec tag defined for stream %d\n", i);
444
        return AVERROR(EINVAL);
445
    }
446

447 448 449
    ff_put_v(bc, nut->stream[i].time_base - nut->time_base);
    ff_put_v(bc, nut->stream[i].msb_pts_shift);
    ff_put_v(bc, nut->stream[i].max_pts_distance);
450
    ff_put_v(bc, par->video_delay);
451
    avio_w8(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
452

453 454
    ff_put_v(bc, par->extradata_size);
    avio_write(bc, par->extradata, par->extradata_size);
455

456
    switch (par->codec_type) {
457
    case AVMEDIA_TYPE_AUDIO:
458
        ff_put_v(bc, par->sample_rate);
459
        ff_put_v(bc, 1);
460
        ff_put_v(bc, par->channels);
461
        break;
462
    case AVMEDIA_TYPE_VIDEO:
463 464
        ff_put_v(bc, par->width);
        ff_put_v(bc, par->height);
465

466 467
        if (st->sample_aspect_ratio.num <= 0 ||
            st->sample_aspect_ratio.den <= 0) {
468 469
            ff_put_v(bc, 0);
            ff_put_v(bc, 0);
470
        } else {
471 472
            ff_put_v(bc, st->sample_aspect_ratio.num);
            ff_put_v(bc, st->sample_aspect_ratio.den);
473
        }
474
        ff_put_v(bc, 0); /* csp type -- unknown */
475 476 477 478 479 480 481
        break;
    default:
        break;
    }
    return 0;
}

482 483
static int add_info(AVIOContext *bc, const char *type, const char *value)
{
Michael Niedermayer's avatar
Michael Niedermayer committed
484 485 486 487 488 489
    put_str(bc, type);
    put_s(bc, -1);
    put_str(bc, value);
    return 1;
}

490 491 492
static int write_globalinfo(NUTContext *nut, AVIOContext *bc)
{
    AVFormatContext *s   = nut->avf;
493
    AVDictionaryEntry *t = NULL;
494
    AVIOContext *dyn_bc;
495 496 497 498
    uint8_t *dyn_buf = NULL;
    int count        = 0, dyn_size;
    int ret          = avio_open_dyn_buf(&dyn_bc);
    if (ret < 0)
499
        return ret;
Michael Niedermayer's avatar
Michael Niedermayer committed
500

501
    ff_standardize_creation_time(s);
502
    while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)))
503
        count += add_info(dyn_bc, t->key, t->value);
Michael Niedermayer's avatar
Michael Niedermayer committed
504

505 506 507 508
    ff_put_v(bc, 0); //stream_if_plus1
    ff_put_v(bc, 0); //chapter_id
    ff_put_v(bc, 0); //timestamp_start
    ff_put_v(bc, 0); //length
Michael Niedermayer's avatar
Michael Niedermayer committed
509

510
    ff_put_v(bc, count);
Michael Niedermayer's avatar
Michael Niedermayer committed
511

512
    dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
513
    avio_write(bc, dyn_buf, dyn_size);
Michael Niedermayer's avatar
Michael Niedermayer committed
514
    av_free(dyn_buf);
515
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
516 517
}

518
static int write_streaminfo(NUTContext *nut, AVIOContext *bc, int stream_id) {
519 520
    AVFormatContext *s= nut->avf;
    AVStream* st = s->streams[stream_id];
521
    AVDictionaryEntry *t = NULL;
522
    AVIOContext *dyn_bc;
523 524
    uint8_t *dyn_buf=NULL;
    int count=0, dyn_size, i;
525
    int ret = avio_open_dyn_buf(&dyn_bc);
526
    if (ret < 0)
527 528
        return ret;

529 530
    while ((t = av_dict_get(st->metadata, "", t, AV_DICT_IGNORE_SUFFIX)))
        count += add_info(dyn_bc, t->key, t->value);
531 532 533 534
    for (i=0; ff_nut_dispositions[i].flag; ++i) {
        if (st->disposition & ff_nut_dispositions[i].flag)
            count += add_info(dyn_bc, "Disposition", ff_nut_dispositions[i].str);
    }
535
    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
536
        uint8_t buf[256];
537 538 539
        if (st->r_frame_rate.num>0 && st->r_frame_rate.den>0)
            snprintf(buf, sizeof(buf), "%d/%d", st->r_frame_rate.num, st->r_frame_rate.den);
        else
540
            snprintf(buf, sizeof(buf), "%d/%d", st->avg_frame_rate.num, st->avg_frame_rate.den);
541 542
        count += add_info(dyn_bc, "r_frame_rate", buf);
    }
543
    dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
544 545

    if (count) {
546 547 548 549
        ff_put_v(bc, stream_id + 1); //stream_id_plus1
        ff_put_v(bc, 0); //chapter_id
        ff_put_v(bc, 0); //timestamp_start
        ff_put_v(bc, 0); //length
550

551
        ff_put_v(bc, count);
552

553
        avio_write(bc, dyn_buf, dyn_size);
554 555 556 557 558 559
    }

    av_free(dyn_buf);
    return count;
}

Anton Khirnov's avatar
Anton Khirnov committed
560 561 562
static int write_chapter(NUTContext *nut, AVIOContext *bc, int id)
{
    AVIOContext *dyn_bc;
563
    uint8_t *dyn_buf     = NULL;
564
    AVDictionaryEntry *t = NULL;
565
    AVChapter *ch        = nut->avf->chapters[id];
Anton Khirnov's avatar
Anton Khirnov committed
566 567
    int ret, dyn_size, count = 0;

568
    ret = avio_open_dyn_buf(&dyn_bc);
Anton Khirnov's avatar
Anton Khirnov committed
569 570 571 572 573 574 575 576
    if (ret < 0)
        return ret;

    ff_put_v(bc, 0);                                        // stream_id_plus1
    put_s(bc, id + 1);                                      // chapter_id
    put_tt(nut, nut->chapter[id].time_base, bc, ch->start); // chapter_start
    ff_put_v(bc, ch->end - ch->start);                      // chapter_len

577
    while ((t = av_dict_get(ch->metadata, "", t, AV_DICT_IGNORE_SUFFIX)))
Anton Khirnov's avatar
Anton Khirnov committed
578 579 580 581
        count += add_info(dyn_bc, t->key, t->value);

    ff_put_v(bc, count);

582
    dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
Anton Khirnov's avatar
Anton Khirnov committed
583 584 585 586 587
    avio_write(bc, dyn_buf, dyn_size);
    av_freep(&dyn_buf);
    return 0;
}

588
static int write_index(NUTContext *nut, AVIOContext *bc) {
589 590 591 592 593 594 595 596 597 598
    int i;
    Syncpoint dummy= { .pos= 0 };
    Syncpoint *next_node[2] = { NULL };
    int64_t startpos = avio_tell(bc);
    int64_t payload_size;

    put_tt(nut, nut->max_pts_tb, bc, nut->max_pts);

    ff_put_v(bc, nut->sp_count);

599
    for (i=0; i<nut->sp_count; i++) {
600
        av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, (void**)next_node);
601 602 603 604
        ff_put_v(bc, (next_node[1]->pos >> 4) - (dummy.pos>>4));
        dummy.pos = next_node[1]->pos;
    }

605
    for (i=0; i<nut->avf->nb_streams; i++) {
606 607 608
        StreamContext *nus= &nut->stream[i];
        int64_t last_pts= -1;
        int j, k;
609
        for (j=0; j<nut->sp_count; j++) {
610
            int flag;
611
            int n = 0;
612 613 614 615 616 617 618

            if (j && nus->keyframe_pts[j] == nus->keyframe_pts[j-1]) {
                av_log(nut->avf, AV_LOG_WARNING, "Multiple keyframes with same PTS\n");
                nus->keyframe_pts[j] = AV_NOPTS_VALUE;
            }

            flag = (nus->keyframe_pts[j] != AV_NOPTS_VALUE) ^ (j+1 == nut->sp_count);
619
            for (; j<nut->sp_count && (nus->keyframe_pts[j] != AV_NOPTS_VALUE) == flag; j++)
620 621 622
                n++;

            ff_put_v(bc, 1 + 2*flag + 4*n);
623 624
            for (k= j - n; k<=j && k<nut->sp_count; k++) {
                if (nus->keyframe_pts[k] == AV_NOPTS_VALUE)
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
                    continue;
                av_assert0(nus->keyframe_pts[k] > last_pts);
                ff_put_v(bc, nus->keyframe_pts[k] - last_pts);
                last_pts = nus->keyframe_pts[k];
            }
        }
    }

    payload_size = avio_tell(bc) - startpos + 8 + 4;

    avio_wb64(bc, 8 + payload_size + av_log2(payload_size) / 7 + 1 + 4*(payload_size > 4096));

    return 0;
}

640 641
static int write_headers(AVFormatContext *avctx, AVIOContext *bc)
{
642
    NUTContext *nut = avctx->priv_data;
643
    AVIOContext *dyn_bc;
644
    int i, ret;
645

646 647
    ff_metadata_conv_ctx(avctx, ff_nut_metadata_conv, NULL);

648
    ret = avio_open_dyn_buf(&dyn_bc);
649
    if (ret < 0)
650 651 652
        return ret;
    write_mainheader(nut, dyn_bc);
    put_packet(nut, bc, dyn_bc, 1, MAIN_STARTCODE);
653

654
    for (i = 0; i < nut->avf->nb_streams; i++) {
655
        ret = avio_open_dyn_buf(&dyn_bc);
656
        if (ret < 0)
657
            return ret;
658 659
        ret = write_streamheader(avctx, dyn_bc, nut->avf->streams[i], i);
        if (ret < 0)
660
            return ret;
661
        put_packet(nut, bc, dyn_bc, 1, STREAM_STARTCODE);
662
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
663

664
    ret = avio_open_dyn_buf(&dyn_bc);
665
    if (ret < 0)
666 667 668
        return ret;
    write_globalinfo(nut, dyn_bc);
    put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
Michael Niedermayer's avatar
Michael Niedermayer committed
669

670
    for (i = 0; i < nut->avf->nb_streams; i++) {
671
        ret = avio_open_dyn_buf(&dyn_bc);
672
        if (ret < 0)
673 674 675 676 677 678
            return ret;
        ret = write_streaminfo(nut, dyn_bc, i);
        if (ret < 0)
            return ret;
        if (ret > 0)
            put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
679 680
        else
            ffio_free_dyn_buf(&dyn_bc);
681 682
    }

Anton Khirnov's avatar
Anton Khirnov committed
683
    for (i = 0; i < nut->avf->nb_chapters; i++) {
684
        ret = avio_open_dyn_buf(&dyn_bc);
Anton Khirnov's avatar
Anton Khirnov committed
685 686 687 688
        if (ret < 0)
            return ret;
        ret = write_chapter(nut, dyn_bc, i);
        if (ret < 0) {
689
            ffio_free_dyn_buf(&dyn_bc);
Anton Khirnov's avatar
Anton Khirnov committed
690 691 692 693 694
            return ret;
        }
        put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
    }

695
    nut->last_syncpoint_pos = INT_MIN;
Michael Niedermayer's avatar
Michael Niedermayer committed
696
    nut->header_count++;
697
    return 0;
698 699
}

700 701
static int nut_write_header(AVFormatContext *s)
{
702
    NUTContext *nut = s->priv_data;
703
    AVIOContext *bc = s->pb;
704
    int i, j, ret;
705

706
    nut->avf = s;
707

708
    nut->version = FFMAX(NUT_STABLE_VERSION, 3 + !!nut->flags);
709
    if (nut->version > 3 && s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
710 711 712 713 714 715 716 717
        av_log(s, AV_LOG_ERROR,
               "The additional syncpoint modes require version %d, "
               "that is currently not finalized, "
               "please set -f_strict experimental in order to enable it.\n",
               nut->version);
        return AVERROR_EXPERIMENTAL;
    }

718 719 720 721
    nut->stream   = av_calloc(s->nb_streams,  sizeof(*nut->stream ));
    nut->chapter  = av_calloc(s->nb_chapters, sizeof(*nut->chapter));
    nut->time_base= av_calloc(s->nb_streams +
                              s->nb_chapters, sizeof(*nut->time_base));
Reimar Döffinger's avatar
Reimar Döffinger committed
722
    if (!nut->stream || !nut->chapter || !nut->time_base) {
723 724 725 726 727
        av_freep(&nut->stream);
        av_freep(&nut->chapter);
        av_freep(&nut->time_base);
        return AVERROR(ENOMEM);
    }
728

729 730
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
731 732
        int ssize;
        AVRational time_base;
733
        ff_parse_specific_params(st, &time_base.den, &ssize, &time_base.num);
734

735 736
        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) {
            time_base = (AVRational) {1, st->codecpar->sample_rate};
737
        } else {
738
            time_base = ff_choose_timebase(s, st, 48000);
739 740
        }

741
        avpriv_set_pts_info(st, 64, time_base.num, time_base.den);
742

743 744
        for (j = 0; j < nut->time_base_count; j++)
            if (!memcmp(&time_base, &nut->time_base[j], sizeof(AVRational))) {
745 746
                break;
            }
747 748 749
        nut->time_base[j]        = time_base;
        nut->stream[i].time_base = &nut->time_base[j];
        if (j == nut->time_base_count)
750 751
            nut->time_base_count++;

752
        if (INT64_C(1000) * time_base.num >= time_base.den)
753 754 755
            nut->stream[i].msb_pts_shift = 7;
        else
            nut->stream[i].msb_pts_shift = 14;
756 757
        nut->stream[i].max_pts_distance =
            FFMAX(time_base.den, time_base.num) / time_base.num;
758 759
    }

Anton Khirnov's avatar
Anton Khirnov committed
760 761 762
    for (i = 0; i < s->nb_chapters; i++) {
        AVChapter *ch = s->chapters[i];

763
        for (j = 0; j < nut->time_base_count; j++)
Anton Khirnov's avatar
Anton Khirnov committed
764 765 766
            if (!memcmp(&ch->time_base, &nut->time_base[j], sizeof(AVRational)))
                break;

767
        nut->time_base[j]         = ch->time_base;
Anton Khirnov's avatar
Anton Khirnov committed
768
        nut->chapter[i].time_base = &nut->time_base[j];
769
        if (j == nut->time_base_count)
Anton Khirnov's avatar
Anton Khirnov committed
770 771 772
            nut->time_base_count++;
    }

773
    nut->max_distance = MAX_DISTANCE;
774
    build_elision_headers(s);
775
    build_frame_code(s);
776
    av_assert0(nut->frame_code['N'].flags == FLAG_INVALID);
777

778 779
    avio_write(bc, ID_STRING, strlen(ID_STRING));
    avio_w8(bc, 0);
780

781 782
    if ((ret = write_headers(s, bc)) < 0)
        return ret;
783

784 785 786
    if (s->avoid_negative_ts < 0)
        s->avoid_negative_ts = 1;

787
    avio_flush(bc);
788 789 790 791

    return 0;
}

792 793 794 795 796 797 798 799 800 801 802 803 804
static int get_needed_flags(NUTContext *nut, StreamContext *nus, FrameCode *fc,
                            AVPacket *pkt)
{
    int flags = 0;

    if (pkt->flags & AV_PKT_FLAG_KEY)
        flags |= FLAG_KEY;
    if (pkt->stream_index != fc->stream_id)
        flags |= FLAG_STREAM_ID;
    if (pkt->size / fc->size_mul)
        flags |= FLAG_SIZE_MSB;
    if (pkt->pts - nus->last_pts != fc->pts_delta)
        flags |= FLAG_CODED_PTS;
805 806
    if (pkt->side_data_elems && nut->version > 3)
        flags |= FLAG_SM_DATA;
807 808 809 810 811 812 813 814 815
    if (pkt->size > 2 * nut->max_distance)
        flags |= FLAG_CHECKSUM;
    if (FFABS(pkt->pts - nus->last_pts) > nus->max_pts_distance)
        flags |= FLAG_CHECKSUM;
    if (pkt->size < nut->header_len[fc->header_idx] ||
        (pkt->size > 4096 && fc->header_idx)        ||
        memcmp(pkt->data, nut->header[fc->header_idx],
               nut->header_len[fc->header_idx]))
        flags |= FLAG_HEADER_IDX;
816

817
    return flags | (fc->flags & FLAG_CODED);
818 819
}

820 821
static int find_best_header_idx(NUTContext *nut, AVPacket *pkt)
{
822
    int i;
823 824
    int best_i   = 0;
    int best_len = 0;
825

826
    if (pkt->size > 4096)
827 828
        return 0;

829 830 831 832 833 834
    for (i = 1; i < nut->header_count; i++)
        if (pkt->size >= nut->header_len[i]
            && nut->header_len[i] > best_len
            && !memcmp(pkt->data, nut->header[i], nut->header_len[i])) {
            best_i   = i;
            best_len = nut->header_len[i];
835 836 837 838
        }
    return best_i;
}

839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int is_meta)
{
    int ret, i, dyn_size;
    unsigned flags;
    AVIOContext *dyn_bc;
    int sm_data_count = 0;
    uint8_t tmp[256];
    uint8_t *dyn_buf;

    ret = avio_open_dyn_buf(&dyn_bc);
    if (ret < 0)
        return ret;

    for (i = 0; i<pkt->side_data_elems; i++) {
        const uint8_t *data = pkt->side_data[i].data;
        int size = pkt->side_data[i].size;
        const uint8_t *data_end = data + size;

        if (is_meta) {
            if (   pkt->side_data[i].type == AV_PKT_DATA_METADATA_UPDATE
                || pkt->side_data[i].type == AV_PKT_DATA_STRINGS_METADATA) {
860 861 862 863
                if (!size || data[size-1]) {
                    ret = AVERROR(EINVAL);
                    goto fail;
                }
864 865 866 867
                while (data < data_end) {
                    const uint8_t *key = data;
                    const uint8_t *val = data + strlen(key) + 1;

868 869 870 871
                    if(val >= data_end) {
                        ret = AVERROR(EINVAL);
                        goto fail;
                    }
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
                    put_str(dyn_bc, key);
                    put_s(dyn_bc, -1);
                    put_str(dyn_bc, val);
                    data = val + strlen(val) + 1;
                    sm_data_count++;
                }
            }
        } else {
            switch (pkt->side_data[i].type) {
            case AV_PKT_DATA_PALETTE:
            case AV_PKT_DATA_NEW_EXTRADATA:
            case AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL:
            default:
                if (pkt->side_data[i].type == AV_PKT_DATA_PALETTE) {
                    put_str(dyn_bc, "Palette");
                } else if(pkt->side_data[i].type == AV_PKT_DATA_NEW_EXTRADATA) {
                    put_str(dyn_bc, "Extradata");
                } else if(pkt->side_data[i].type == AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL) {
                    snprintf(tmp, sizeof(tmp), "CodecSpecificSide%"PRId64"", AV_RB64(data));
                    put_str(dyn_bc, tmp);
                } else {
                    snprintf(tmp, sizeof(tmp), "UserData%s-SD-%d",
894
                            (s->flags & AVFMT_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT,
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
                            pkt->side_data[i].type);
                    put_str(dyn_bc, tmp);
                }
                put_s(dyn_bc, -2);
                put_str(dyn_bc, "bin");
                ff_put_v(dyn_bc, pkt->side_data[i].size);
                avio_write(dyn_bc, data, pkt->side_data[i].size);
                sm_data_count++;
                break;
            case AV_PKT_DATA_PARAM_CHANGE:
                flags = bytestream_get_le32(&data);
                if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
                    put_str(dyn_bc, "Channels");
                    put_s(dyn_bc, bytestream_get_le32(&data));
                    sm_data_count++;
                }
                if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
                    put_str(dyn_bc, "ChannelLayout");
                    put_s(dyn_bc, -2);
                    put_str(dyn_bc, "u64");
                    ff_put_v(bc, 8);
                    avio_write(dyn_bc, data, 8); data+=8;
                    sm_data_count++;
                }
                if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
                    put_str(dyn_bc, "SampleRate");
                    put_s(dyn_bc, bytestream_get_le32(&data));
                    sm_data_count++;
                }
                if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
                    put_str(dyn_bc, "Width");
                    put_s(dyn_bc, bytestream_get_le32(&data));
                    put_str(dyn_bc, "Height");
                    put_s(dyn_bc, bytestream_get_le32(&data));
                    sm_data_count+=2;
                }
931
                break;
932 933 934 935 936 937 938 939 940 941 942 943 944 945
            case AV_PKT_DATA_SKIP_SAMPLES:
                if (AV_RL32(data)) {
                    put_str(dyn_bc, "SkipStart");
                    put_s(dyn_bc, (unsigned)AV_RL32(data));
                    sm_data_count++;
                }
                if (AV_RL32(data+4)) {
                    put_str(dyn_bc, "SkipEnd");
                    put_s(dyn_bc, (unsigned)AV_RL32(data+4));
                    sm_data_count++;
                }
                break;
            case AV_PKT_DATA_METADATA_UPDATE:
            case AV_PKT_DATA_STRINGS_METADATA:
946
            case AV_PKT_DATA_QUALITY_STATS:
947 948 949 950 951 952
                // belongs into meta, not side data
                break;
            }
        }
    }

953
fail:
954 955 956 957 958
    ff_put_v(bc, sm_data_count);
    dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
    avio_write(bc, dyn_buf, dyn_size);
    av_freep(&dyn_buf);

959
    return ret;
960 961
}

962 963 964 965
static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
{
    NUTContext *nut    = s->priv_data;
    StreamContext *nus = &nut->stream[pkt->stream_index];
966
    AVIOContext *bc    = s->pb, *dyn_bc, *sm_bc = NULL;
967 968
    FrameCode *fc;
    int64_t coded_pts;
969 970
    int best_length, frame_code, flags, needed_flags, i, header_idx;
    int best_header_idx;
971
    int key_frame = !!(pkt->flags & AV_PKT_FLAG_KEY);
972
    int store_sp  = 0;
973
    int ret = 0;
974 975
    int sm_size = 0;
    int data_size = pkt->size;
976
    uint8_t *sm_buf = NULL;
977

978
    if (pkt->pts < 0) {
979 980 981
        av_log(s, AV_LOG_ERROR,
               "Negative pts not supported stream %d, pts %"PRId64"\n",
               pkt->stream_index, pkt->pts);
982 983
        if (pkt->pts == AV_NOPTS_VALUE)
            av_log(s, AV_LOG_ERROR, "Try to enable the genpts flag\n");
984 985
        return AVERROR(EINVAL);
    }
986

987 988 989 990
    if (pkt->side_data_elems && nut->version > 3) {
        ret = avio_open_dyn_buf(&sm_bc);
        if (ret < 0)
            return ret;
991 992 993
        ret = write_sm_data(s, sm_bc, pkt, 0);
        if (ret >= 0)
            ret = write_sm_data(s, sm_bc, pkt, 1);
994
        sm_size = avio_close_dyn_buf(sm_bc, &sm_buf);
995 996
        if (ret < 0)
            goto fail;
997 998 999
        data_size += sm_size;
    }

1000
    if (1LL << (20 + 3 * nut->header_count) <= avio_tell(bc))
1001
        write_headers(s, bc);
Michael Niedermayer's avatar
Michael Niedermayer committed
1002

1003 1004
    if (key_frame && !(nus->last_flags & FLAG_KEY))
        store_sp = 1;
1005

1006
    if (data_size + 30 /*FIXME check*/ + avio_tell(bc) >= nut->last_syncpoint_pos + nut->max_distance)
1007
        store_sp = 1;
1008

1009
//FIXME: Ensure store_sp is 1 in the first place.
1010

1011 1012
    if (store_sp &&
        (!(nut->flags & NUT_PIPE) || nut->last_syncpoint_pos == INT_MIN)) {
1013
        int64_t sp_pos = INT64_MAX;
1014

1015
        ff_nut_reset_ts(nut, *nus->time_base, pkt->dts);
1016 1017
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st   = s->streams[i];
1018 1019 1020 1021
            int64_t dts_tb = av_rescale_rnd(pkt->dts,
                nus->time_base->num * (int64_t)nut->stream[i].time_base->den,
                nus->time_base->den * (int64_t)nut->stream[i].time_base->num,
                AV_ROUND_DOWN);
1022 1023
            int index = av_index_search_timestamp(st, dts_tb,
                                                  AVSEEK_FLAG_BACKWARD);
1024
            if (index >= 0) {
1025
                sp_pos = FFMIN(sp_pos, st->index_entries[index].pos);
1026 1027 1028 1029 1030 1031 1032
                if (!nut->write_index && 2*index > st->nb_index_entries) {
                    memmove(st->index_entries,
                            st->index_entries + index,
                            sizeof(*st->index_entries) * (st->nb_index_entries - index));
                    st->nb_index_entries -=  index;
                }
            }
1033
        }
1034

1035 1036 1037
        nut->last_syncpoint_pos = avio_tell(bc);
        ret                     = avio_open_dyn_buf(&dyn_bc);
        if (ret < 0)
1038
            goto fail;
Anton Khirnov's avatar
Anton Khirnov committed
1039
        put_tt(nut, nus->time_base, dyn_bc, pkt->dts);
1040
        ff_put_v(dyn_bc, sp_pos != INT64_MAX ? (nut->last_syncpoint_pos - sp_pos) >> 4 : 0);
1041 1042 1043 1044 1045

        if (nut->flags & NUT_BROADCAST) {
            put_tt(nut, nus->time_base, dyn_bc,
                   av_rescale_q(av_gettime(), AV_TIME_BASE_Q, *nus->time_base));
        }
1046
        put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE);
1047

1048
        if (nut->write_index) {
1049
        if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0 /*unused*/, pkt->dts)) < 0)
1050
            goto fail;
1051

1052 1053
        if ((1ll<<60) % nut->sp_count == 0)
            for (i=0; i<s->nb_streams; i++) {
1054 1055
                int j;
                StreamContext *nus = &nut->stream[i];
1056
                av_reallocp_array(&nus->keyframe_pts, 2*nut->sp_count, sizeof(*nus->keyframe_pts));
1057 1058 1059 1060
                if (!nus->keyframe_pts) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
1061
                for (j=nut->sp_count == 1 ? 0 : nut->sp_count; j<2*nut->sp_count; j++)
1062 1063
                    nus->keyframe_pts[j] = AV_NOPTS_VALUE;
        }
1064
        }
1065
    }
1066
    av_assert0(nus->last_pts != AV_NOPTS_VALUE);
1067

1068 1069 1070
    coded_pts = pkt->pts & ((1 << nus->msb_pts_shift) - 1);
    if (ff_lsb2full(nus, coded_pts) != pkt->pts)
        coded_pts = pkt->pts + (1 << nus->msb_pts_shift);
1071

1072
    best_header_idx = find_best_header_idx(nut, pkt);
1073

1074 1075 1076 1077 1078 1079
    best_length = INT_MAX;
    frame_code  = -1;
    for (i = 0; i < 256; i++) {
        int length    = 0;
        FrameCode *fc = &nut->frame_code[i];
        int flags     = fc->flags;
1080

1081
        if (flags & FLAG_INVALID)
1082
            continue;
1083
        needed_flags = get_needed_flags(nut, nus, fc, pkt);
1084

1085
        if (flags & FLAG_CODED) {
1086
            length++;
Michael Niedermayer's avatar
Michael Niedermayer committed
1087
            flags = needed_flags;
1088 1089
        }

1090
        if ((flags & needed_flags) != needed_flags)
1091 1092
            continue;

1093
        if ((flags ^ needed_flags) & FLAG_KEY)
1094 1095
            continue;

1096 1097
        if (flags & FLAG_STREAM_ID)
            length += ff_get_v_length(pkt->stream_index);
1098

1099
        if (data_size % fc->size_mul != fc->size_lsb)
1100
            continue;
1101
        if (flags & FLAG_SIZE_MSB)
1102
            length += ff_get_v_length(data_size / fc->size_mul);
1103

1104 1105
        if (flags & FLAG_CHECKSUM)
            length += 4;
1106

1107
        if (flags & FLAG_CODED_PTS)
1108
            length += ff_get_v_length(coded_pts);
1109

1110 1111
        if (   (flags & FLAG_CODED)
            && nut->header_len[best_header_idx] > nut->header_len[fc->header_idx] + 1) {
1112 1113 1114
            flags |= FLAG_HEADER_IDX;
        }

1115
        if (flags & FLAG_HEADER_IDX) {
1116
            length += 1 - nut->header_len[best_header_idx];
1117
        } else {
1118 1119 1120
            length -= nut->header_len[fc->header_idx];
        }

1121 1122 1123
        length *= 4;
        length += !(flags & FLAG_CODED_PTS);
        length += !(flags & FLAG_CHECKSUM);
1124

1125 1126 1127
        if (length < best_length) {
            best_length = length;
            frame_code  = i;
1128 1129
        }
    }
1130
    av_assert0(frame_code != -1);
1131

1132 1133 1134 1135
    fc           = &nut->frame_code[frame_code];
    flags        = fc->flags;
    needed_flags = get_needed_flags(nut, nus, fc, pkt);
    header_idx   = fc->header_idx;
1136

1137
    ffio_init_checksum(bc, ff_crc04C11DB7_update, 0);
1138
    avio_w8(bc, frame_code);
1139 1140
    if (flags & FLAG_CODED) {
        ff_put_v(bc, (flags ^ needed_flags) & ~(FLAG_CODED));
1141 1142
        flags = needed_flags;
    }
1143 1144
    if (flags & FLAG_STREAM_ID)  ff_put_v(bc, pkt->stream_index);
    if (flags & FLAG_CODED_PTS)  ff_put_v(bc, coded_pts);
1145
    if (flags & FLAG_SIZE_MSB )  ff_put_v(bc, data_size / fc->size_mul);
1146
    if (flags & FLAG_HEADER_IDX) ff_put_v(bc, header_idx = best_header_idx);
1147

1148 1149
    if (flags & FLAG_CHECKSUM)   avio_wl32(bc, ffio_get_checksum(bc));
    else                         ffio_get_checksum(bc);
1150

1151 1152 1153
    if (flags & FLAG_SM_DATA) {
        avio_write(bc, sm_buf, sm_size);
    }
1154
    avio_write(bc, pkt->data + nut->header_len[header_idx], pkt->size - nut->header_len[header_idx]);
1155

1156 1157
    nus->last_flags = flags;
    nus->last_pts   = pkt->pts;
1158 1159

    //FIXME just store one per syncpoint
1160
    if (flags & FLAG_KEY && !(nut->flags & NUT_PIPE)) {
1161 1162 1163 1164 1165 1166 1167
        av_add_index_entry(
            s->streams[pkt->stream_index],
            nut->last_syncpoint_pos,
            pkt->pts,
            0,
            0,
            AVINDEX_KEYFRAME);
1168
        if (nus->keyframe_pts && nus->keyframe_pts[nut->sp_count] == AV_NOPTS_VALUE)
1169 1170
            nus->keyframe_pts[nut->sp_count] = pkt->pts;
    }
1171

1172
    if (!nut->max_pts_tb || av_compare_ts(nut->max_pts, *nut->max_pts_tb, pkt->pts, *nus->time_base) < 0) {
1173 1174 1175 1176
        nut->max_pts = pkt->pts;
        nut->max_pts_tb = nus->time_base;
    }

1177 1178 1179 1180
fail:
    av_freep(&sm_buf);

    return ret;
1181 1182
}

1183 1184 1185
static int nut_write_trailer(AVFormatContext *s)
{
    NUTContext *nut = s->priv_data;
1186
    AVIOContext *bc = s->pb, *dyn_bc;
1187
    int ret;
1188

1189
    while (nut->header_count < 3)
1190
        write_headers(s, bc);
1191 1192

    ret = avio_open_dyn_buf(&dyn_bc);
1193 1194
    if (ret >= 0 && nut->sp_count) {
        av_assert1(nut->write_index);
1195 1196 1197 1198
        write_index(nut, dyn_bc);
        put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE);
    }

1199 1200 1201 1202 1203 1204 1205 1206
    return 0;
}

static void nut_write_deinit(AVFormatContext *s)
{
    NUTContext *nut = s->priv_data;
    int i;

1207
    ff_nut_free_sp(nut);
1208 1209 1210
    if (nut->stream)
        for (i=0; i<s->nb_streams; i++)
            av_freep(&nut->stream[i].keyframe_pts);
1211

1212
    av_freep(&nut->stream);
Anton Khirnov's avatar
Anton Khirnov committed
1213
    av_freep(&nut->chapter);
1214
    av_freep(&nut->time_base);
1215 1216
}

1217 1218 1219 1220 1221 1222 1223
#define OFFSET(x) offsetof(NUTContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
    { "syncpoints",  "NUT syncpoint behaviour",                         OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0},             INT_MIN, INT_MAX, E, "syncpoints" },
    { "default",     "",                                                0,             AV_OPT_TYPE_CONST, {.i64 = 0},             INT_MIN, INT_MAX, E, "syncpoints" },
    { "none",        "Disable syncpoints, low overhead and unseekable", 0,             AV_OPT_TYPE_CONST, {.i64 = NUT_PIPE},      INT_MIN, INT_MAX, E, "syncpoints" },
    { "timestamped", "Extend syncpoints with a wallclock timestamp",    0,             AV_OPT_TYPE_CONST, {.i64 = NUT_BROADCAST}, INT_MIN, INT_MAX, E, "syncpoints" },
1224
    { "write_index", "Write index",                               OFFSET(write_index), AV_OPT_TYPE_BOOL,  {.i64 = 1},                   0,       1, E, },
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
    { NULL },
};

static const AVClass class = {
    .class_name = "nutenc",
    .item_name  = av_default_item_name,
    .option     = options,
    .version    = LIBAVUTIL_VERSION_INT,
};

1235
AVOutputFormat ff_nut_muxer = {
1236
    .name           = "nut",
1237
    .long_name      = NULL_IF_CONFIG_SMALL("NUT"),
1238 1239 1240
    .mime_type      = "video/x-nut",
    .extensions     = "nut",
    .priv_data_size = sizeof(NUTContext),
1241 1242 1243
    .audio_codec    = CONFIG_LIBVORBIS ? AV_CODEC_ID_VORBIS :
                      CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_MP2,
    .video_codec    = AV_CODEC_ID_MPEG4,
1244 1245 1246
    .write_header   = nut_write_header,
    .write_packet   = nut_write_packet,
    .write_trailer  = nut_write_trailer,
1247
    .deinit         = nut_write_deinit,
1248
    .flags          = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,
1249
    .codec_tag      = ff_nut_codec_tags,
1250
    .priv_class     = &class,
1251
};