asfenc.c 42 KB
Newer Older
1
/*
2
 * ASF muxer
3
 * Copyright (c) 2000, 2001 Fabrice Bellard
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13 14 15 16 17
 * 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
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

22
#include "libavutil/avassert.h"
23
#include "libavutil/dict.h"
24
#include "libavutil/mathematics.h"
25
#include "libavutil/parseutils.h"
26
#include "libavutil/opt.h"
27
#include "avformat.h"
28
#include "avlanguage.h"
29
#include "avio_internal.h"
30
#include "internal.h"
31
#include "riff.h"
32 33
#include "asf.h"

34
#define ASF_INDEXED_INTERVAL    10000000
35
#define ASF_INDEX_BLOCK         (1<<9)
36
#define ASF_PAYLOADS_PER_PACKET 63
37

38
#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
39 40 41
#define ASF_PACKET_ERROR_CORRECTION_FLAGS          \
    (ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT |    \
     ASF_PACKET_ERROR_CORRECTION_DATA_SIZE)
42 43 44 45 46 47 48

#if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
#   define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
#else
#   define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
#endif

49 50 51 52 53
#define ASF_PPI_PROPERTY_FLAGS                                       \
    (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE           |    \
     ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD |    \
     ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE       |    \
     ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE)
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

#define ASF_PPI_LENGTH_TYPE_FLAGS 0

#define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD

#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
#   define ASF_PPI_SEQUENCE_FIELD_SIZE 1
#endif
#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
#   define ASF_PPI_SEQUENCE_FIELD_SIZE 2
#endif
#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
#   define ASF_PPI_SEQUENCE_FIELD_SIZE 4
#endif
#ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
#   define ASF_PPI_SEQUENCE_FIELD_SIZE 0
#endif

#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
#   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
#endif
#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
#   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
#endif
#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
#   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
#endif
#ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
#   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
#endif

#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
#   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
#endif
#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
#   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
#endif
#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
#   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
#endif
#ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
#   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
#endif

#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
#endif
#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
#endif
#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
#endif
#ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
#   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
#endif

#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
#endif
#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
#endif
#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
#endif
#ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
#   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
#endif

#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
#endif
#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
#endif
#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
#endif
#ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
#   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
#endif

#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
#endif
#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
#   define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
#endif
#ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
#   define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
#endif

147 148 149 150 151 152 153 154 155 156
#define PACKET_HEADER_MIN_SIZE \
    (ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE +       \
     ASF_PACKET_ERROR_CORRECTION_DATA_SIZE +              \
     1 +        /* Length Type Flags */                   \
     1 +        /* Property Flags */                      \
     ASF_PPI_PACKET_LENGTH_FIELD_SIZE +                   \
     ASF_PPI_SEQUENCE_FIELD_SIZE +                        \
     ASF_PPI_PADDING_LENGTH_FIELD_SIZE +                  \
     4 +        /* Send Time Field */                     \
     2)         /* Duration Field */
157 158 159 160

// Replicated Data shall be at least 8 bytes long.
#define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
#define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD                \
    (1 +     /* Stream Number */                          \
     ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE +         \
     ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE +    \
     ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE +      \
     ASF_PAYLOAD_REPLICATED_DATA_LENGTH)

#define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS             \
    (1 +        /* Stream Number */                       \
     ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE +         \
     ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE +    \
     ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE +      \
     ASF_PAYLOAD_REPLICATED_DATA_LENGTH +                 \
     ASF_PAYLOAD_LENGTH_FIELD_SIZE)

176 177
#define SINGLE_PAYLOAD_HEADERS                            \
    (PACKET_HEADER_MIN_SIZE +                             \
178 179
     PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD)

180 181 182
#define MULTI_PAYLOAD_HEADERS                             \
    (PACKET_HEADER_MIN_SIZE +                             \
     1 +         /* Payload Flags */                      \
183
     2 * PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS)
184

185 186
#define DATA_HEADER_SIZE 50

187 188 189
#define PACKET_SIZE_MAX 65536
#define PACKET_SIZE_MIN 100

190 191 192 193 194
typedef struct ASFPayload {
    uint8_t type;
    uint16_t size;
} ASFPayload;

195 196 197 198 199 200
typedef struct ASFStream {
    int num;
    unsigned char seq;
    /* use for reading */
    AVPacket pkt;
    int frag_offset;
201
    int packet_obj_size;
202 203
    int timestamp;
    int64_t duration;
204 205
    int skip_to_key;
    int pkt_clean;
206 207 208 209 210 211 212 213 214 215 216

    int ds_span;                /* descrambling  */
    int ds_packet_size;
    int ds_chunk_size;

    int64_t packet_pos;

    uint16_t stream_language_index;

    int      palette_changed;
    uint32_t palette[256];
217 218 219

    int payload_ext_ct;
    ASFPayload payload[8];
220 221
} ASFStream;

222
typedef struct ASFContext {
223
    AVClass *av_class;
224 225 226
    uint32_t seqno;
    int is_streamed;
    ASFStream streams[128];              ///< it's max number and it's not that big
227 228
    const char *languages[128];
    int nb_languages;
229
    int64_t creation_time;
230
    /* non-streamed additional info */
231 232 233 234 235
    uint64_t nb_packets;                 ///< how many packets are there in the file, invalid if broadcasting
    int64_t duration;                    ///< in 100ns units
    /* packet filling */
    unsigned char multi_payloads_present;
    int packet_size_left;
236 237
    int64_t packet_timestamp_start;
    int64_t packet_timestamp_end;
238
    unsigned int packet_nb_payloads;
239
    uint8_t packet_buf[PACKET_SIZE_MAX];
240
    AVIOContext pb;
241 242 243
    /* only for reading */
    uint64_t data_offset;                ///< beginning of the first data packet

244
    ASFIndex *index_ptr;
245 246
    uint32_t nb_index_memory_alloc;
    uint16_t maximum_packet;
247 248
    uint32_t next_packet_number;
    uint16_t next_packet_count;
249
    uint64_t next_packet_offset;
250 251
    int      next_start_sec;
    int      end_sec;
252
    int      packet_size;
253 254
} ASFContext;

255
static const AVCodecTag codec_asf_bmp_tags[] = {
256
    { AV_CODEC_ID_MPEG4,     MKTAG('M', '4', 'S', '2') },
257
    { AV_CODEC_ID_MPEG4,     MKTAG('M', 'P', '4', 'S') },
258
    { AV_CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
259
    { AV_CODEC_ID_NONE,      0 },
260 261
};

262
#define PREROLL_TIME 3100
263

264
static void put_str16(AVIOContext *s, const char *tag)
265 266 267
{
    int len;
    uint8_t *pb;
268
    AVIOContext *dyn_buf;
269
    if (avio_open_dyn_buf(&dyn_buf) < 0)
270 271
        return;

272
    avio_put_str16le(dyn_buf, tag);
273
    len = avio_close_dyn_buf(dyn_buf, &pb);
274 275
    avio_wl16(s, len);
    avio_write(s, pb, len);
276
    av_freep(&pb);
277 278
}

279
static int64_t put_header(AVIOContext *pb, const ff_asf_guid *g)
280 281 282
{
    int64_t pos;

283
    pos = avio_tell(pb);
284
    ff_put_guid(pb, g);
285
    avio_wl64(pb, 24);
286 287 288 289
    return pos;
}

/* update header size */
290
static void end_header(AVIOContext *pb, int64_t pos)
291 292 293
{
    int64_t pos1;

294
    pos1 = avio_tell(pb);
295
    avio_seek(pb, pos + 16, SEEK_SET);
296
    avio_wl64(pb, pos1 - pos);
297
    avio_seek(pb, pos1, SEEK_SET);
298 299 300
}

/* write an asf chunk (only used in streaming case) */
301 302
static void put_chunk(AVFormatContext *s, int type,
                      int payload_length, int flags)
303 304
{
    ASFContext *asf = s->priv_data;
305
    AVIOContext *pb = s->pb;
306 307 308
    int length;

    length = payload_length + 8;
309
    avio_wl16(pb, type);
310 311 312 313
    avio_wl16(pb, length);      // size
    avio_wl32(pb, asf->seqno);  // sequence number
    avio_wl16(pb, flags);       // unknown bytes
    avio_wl16(pb, length);      // size_confirm
314 315 316
    asf->seqno++;
}

317 318
/* convert from av time to windows time */
static int64_t unix_to_file_time(int64_t ti)
319 320 321
{
    int64_t t;

322
    t  = ti * INT64_C(10);
323
    t += INT64_C(116444736000000000);
324 325 326
    return t;
}

327 328 329 330 331
static int32_t get_send_time(ASFContext *asf, int64_t pres_time, uint64_t *offset)
{
    int i;
    int32_t send_time = 0;
    *offset = asf->data_offset + DATA_HEADER_SIZE;
332
    for (i = 0; i < asf->next_start_sec; i++) {
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
        if (pres_time <= asf->index_ptr[i].send_time)
            break;
        send_time = asf->index_ptr[i].send_time;
        *offset   = asf->index_ptr[i].offset;
    }

    return send_time / 10000;
}

static int asf_write_markers(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;
    AVIOContext *pb = s->pb;
    int i;
    AVRational scale = {1, 10000000};
    int64_t hpos = put_header(pb, &ff_asf_marker_header);

350
    ff_put_guid(pb, &ff_asf_reserved_4);// ASF spec mandates this reserved value
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
    avio_wl32(pb, s->nb_chapters);     // markers count
    avio_wl16(pb, 0);                  // ASF spec mandates 0 for this
    avio_wl16(pb, 0);                  // name length 0, no name given

    for (i = 0; i < s->nb_chapters; i++) {
        AVChapter *c = s->chapters[i];
        AVDictionaryEntry *t = av_dict_get(c->metadata, "title", NULL, 0);
        int64_t pres_time = av_rescale_q(c->start, c->time_base, scale);
        uint64_t offset;
        int32_t send_time = get_send_time(asf, pres_time, &offset);
        int len = 0;
        uint8_t *buf;
        AVIOContext *dyn_buf;
        if (t) {
            if (avio_open_dyn_buf(&dyn_buf) < 0)
                return AVERROR(ENOMEM);
            avio_put_str16le(dyn_buf, t->value);
            len = avio_close_dyn_buf(dyn_buf, &buf);
        }
        avio_wl64(pb, offset);            // offset of the packet with send_time
        avio_wl64(pb, pres_time + PREROLL_TIME * 10000); // presentation time
        avio_wl16(pb, 12 + len);          // entry length
        avio_wl32(pb, send_time);         // send time
        avio_wl32(pb, 0);                 // flags, should be 0
        avio_wl32(pb, len / 2);           // marker desc length in WCHARS!
        if (t) {
            avio_write(pb, buf, len);     // marker desc
            av_freep(&buf);
        }
    }
    end_header(pb, hpos);
    return 0;
}

385
/* write the header (used two times if non streamed) */
386 387
static int asf_write_header1(AVFormatContext *s, int64_t file_size,
                             int64_t data_chunk_size)
388 389
{
    ASFContext *asf = s->priv_data;
390
    AVIOContext *pb = s->pb;
391
    AVDictionaryEntry *tags[5];
392
    int header_size, n, extra_size, extra_size2, wav_extra_size;
393
    int has_title, has_aspect_ratio = 0;
394
    int metadata_count;
395
    AVCodecParameters *par;
396 397
    int64_t header_offset, cur_pos, hpos;
    int bit_rate;
398
    int64_t duration;
399
    int audio_language_counts[128] = { 0 };
400

401
    ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);
402

403 404
    tags[0] = av_dict_get(s->metadata, "title", NULL, 0);
    tags[1] = av_dict_get(s->metadata, "author", NULL, 0);
405
    tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0);
406 407
    tags[3] = av_dict_get(s->metadata, "comment", NULL, 0);
    tags[4] = av_dict_get(s->metadata, "rating", NULL, 0);
408

409 410
    duration       = asf->duration + PREROLL_TIME * 10000;
    has_title      = tags[0] || tags[1] || tags[2] || tags[3] || tags[4];
411

412 413 414
    if (!file_size) {
        if (ff_parse_creation_time_metadata(s, &asf->creation_time, 0) != 0)
            av_dict_set(&s->metadata, "creation_time", NULL, 0);
415 416
    }

417
    metadata_count = av_dict_count(s->metadata);
418 419

    bit_rate = 0;
420
    for (n = 0; n < s->nb_streams; n++) {
421
        AVDictionaryEntry *entry;
422
        par = s->streams[n]->codecpar;
423

424
        avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */
425

426
        bit_rate += par->bit_rate;
427 428 429
        if (   par->codec_type == AVMEDIA_TYPE_VIDEO
            && par->sample_aspect_ratio.num > 0
            && par->sample_aspect_ratio.den > 0)
430
            has_aspect_ratio++;
431 432 433

        entry = av_dict_get(s->streams[n]->metadata, "language", NULL, 0);
        if (entry) {
434
            const char *iso6391lang = ff_convert_lang_to(entry->value, AV_LANG_ISO639_1);
435 436 437 438 439 440 441 442 443 444 445 446 447
            if (iso6391lang) {
                int i;
                for (i = 0; i < asf->nb_languages; i++) {
                    if (!strcmp(asf->languages[i], iso6391lang)) {
                        asf->streams[n].stream_language_index = i;
                        break;
                    }
                }
                if (i >= asf->nb_languages) {
                    asf->languages[asf->nb_languages] = iso6391lang;
                    asf->streams[n].stream_language_index = asf->nb_languages;
                    asf->nb_languages++;
                }
448
                if (par->codec_type == AVMEDIA_TYPE_AUDIO)
449
                    audio_language_counts[asf->streams[n].stream_language_index]++;
450 451 452 453
            }
        } else {
            asf->streams[n].stream_language_index = 128;
        }
454 455 456 457 458 459
    }

    if (asf->is_streamed) {
        put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
    }

460
    ff_put_guid(pb, &ff_asf_header);
461 462 463 464
    avio_wl64(pb, -1); /* header length, will be patched after */
    avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 2); /* ??? */
465 466

    /* file header */
467
    header_offset = avio_tell(pb);
468
    hpos          = put_header(pb, &ff_asf_file_header);
469
    ff_put_guid(pb, &ff_asf_my_guid);
470
    avio_wl64(pb, file_size);
471
    avio_wl64(pb, unix_to_file_time(asf->creation_time));
472 473 474 475
    avio_wl64(pb, asf->nb_packets); /* number of packets */
    avio_wl64(pb, duration); /* end time stamp (in 100ns units) */
    avio_wl64(pb, asf->duration); /* duration (in 100ns units) */
    avio_wl64(pb, PREROLL_TIME); /* start time stamp */
476
    avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2);  /* ??? */
477 478
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, s->packet_size); /* packet size */
479
    avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
480 481
    end_header(pb, hpos);

482
    /* header_extension */
483
    hpos = put_header(pb, &ff_asf_head1_guid);
484
    ff_put_guid(pb, &ff_asf_head2_guid);
485
    avio_wl16(pb, 6);
486 487 488 489
    avio_wl32(pb, 0); /* length, to be filled later */
    if (asf->nb_languages) {
        int64_t hpos2;
        int i;
490
        int nb_audio_languages = 0;
491 492 493 494 495 496 497 498 499

        hpos2 = put_header(pb, &ff_asf_language_guid);
        avio_wl16(pb, asf->nb_languages);
        for (i = 0; i < asf->nb_languages; i++) {
            avio_w8(pb, 6);
            avio_put_str16le(pb, asf->languages[i]);
        }
        end_header(pb, hpos2);

500 501 502 503 504 505 506 507 508 509 510 511
        for (i = 0; i < asf->nb_languages; i++)
            if (audio_language_counts[i])
                nb_audio_languages++;

        if (nb_audio_languages > 1) {
            hpos2 = put_header(pb, &ff_asf_group_mutual_exclusion_object);
            ff_put_guid(pb, &ff_asf_mutex_language);
            avio_wl16(pb, nb_audio_languages);
            for (i = 0; i < asf->nb_languages; i++) {
                if (audio_language_counts[i]) {
                    avio_wl16(pb, audio_language_counts[i]);
                    for (n = 0; n < s->nb_streams; n++)
512
                        if (asf->streams[n].stream_language_index == i && s->streams[n]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
513 514 515 516 517 518
                            avio_wl16(pb, n + 1);
                }
            }
            end_header(pb, hpos2);
        }

519 520 521 522 523 524 525
        for (n = 0; n < s->nb_streams; n++) {
            int64_t es_pos;
            if (asf->streams[n].stream_language_index > 127)
                continue;
            es_pos = put_header(pb, &ff_asf_extended_stream_properties_object);
            avio_wl64(pb, 0); /* start time */
            avio_wl64(pb, 0); /* end time */
526
            avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* data bitrate bps */
527 528
            avio_wl32(pb, 5000); /* buffer size ms */
            avio_wl32(pb, 0); /* initial buffer fullness */
529
            avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* peak data bitrate */
530 531 532 533 534 535 536 537 538 539 540 541
            avio_wl32(pb, 5000); /* maximum buffer size ms */
            avio_wl32(pb, 0); /* max initial buffer fullness */
            avio_wl32(pb, 0); /* max object size */
            avio_wl32(pb, (!asf->is_streamed && pb->seekable) << 1); /* flags - seekable */
            avio_wl16(pb, n + 1); /* stream number */
            avio_wl16(pb, asf->streams[n].stream_language_index); /* language id index */
            avio_wl64(pb, 0); /* avg time per frame */
            avio_wl16(pb, 0); /* stream name count */
            avio_wl16(pb, 0); /* payload extension system count */
            end_header(pb, es_pos);
        }
    }
542 543 544 545 546
    if (has_aspect_ratio) {
        int64_t hpos2;
        hpos2 = put_header(pb, &ff_asf_metadata_header);
        avio_wl16(pb, 2 * has_aspect_ratio);
        for (n = 0; n < s->nb_streams; n++) {
547 548 549 550 551
            par = s->streams[n]->codecpar;
            if (   par->codec_type == AVMEDIA_TYPE_VIDEO
                && par->sample_aspect_ratio.num > 0
                && par->sample_aspect_ratio.den > 0) {
                AVRational sar = par->sample_aspect_ratio;
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioX");
                avio_wl32(pb, sar.num);
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioY");
                avio_wl32(pb, sar.den);
            }
        }
        end_header(pb, hpos2);
571 572 573 574 575 576 577
    }
    {
        int64_t pos1;
        pos1 = avio_tell(pb);
        avio_seek(pb, hpos + 42, SEEK_SET);
        avio_wl32(pb, pos1 - hpos - 46);
        avio_seek(pb, pos1, SEEK_SET);
578
    }
579 580
    end_header(pb, hpos);

581
    /* title and other info */
582
    if (has_title) {
583 584
        int len;
        uint8_t *buf;
585
        AVIOContext *dyn_buf;
586

587
        if (avio_open_dyn_buf(&dyn_buf) < 0)
588 589
            return AVERROR(ENOMEM);

590
        hpos = put_header(pb, &ff_asf_comment_header);
591 592

        for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) {
593
            len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0;
594
            avio_wl16(pb, len);
595
        }
596
        len = avio_close_dyn_buf(dyn_buf, &buf);
597
        avio_write(pb, buf, len);
598
        av_freep(&buf);
599 600
        end_header(pb, hpos);
    }
601
    if (metadata_count) {
602
        AVDictionaryEntry *tag = NULL;
603
        hpos = put_header(pb, &ff_asf_extended_content_header);
604
        avio_wl16(pb, metadata_count);
605
        while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
606
            put_str16(pb, tag->key);
607
            avio_wl16(pb, 0);
608
            put_str16(pb, tag->value);
609 610 611
        }
        end_header(pb, hpos);
    }
612 613 614
    /* chapters using ASF markers */
    if (!asf->is_streamed && s->nb_chapters) {
        int ret;
615
        if ((ret = asf_write_markers(s)) < 0)
616 617
            return ret;
    }
618
    /* stream headers */
619
    for (n = 0; n < s->nb_streams; n++) {
620 621 622
        int64_t es_pos;
        //        ASFStream *stream = &asf->streams[n];

623
        par                 = s->streams[n]->codecpar;
624
        asf->streams[n].num = n + 1;
625
        asf->streams[n].seq = 1;
626

627
        switch (par->codec_type) {
628
        case AVMEDIA_TYPE_AUDIO:
629
            wav_extra_size = 0;
630 631
            extra_size     = 18 + wav_extra_size;
            extra_size2    = 8;
632 633
            break;
        default:
634
        case AVMEDIA_TYPE_VIDEO:
635
            wav_extra_size = par->extradata_size;
636 637
            extra_size     = 0x33 + wav_extra_size;
            extra_size2    = 0;
638 639 640
            break;
        }

641
        hpos = put_header(pb, &ff_asf_stream_header);
642
        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
643 644
            ff_put_guid(pb, &ff_asf_audio_stream);
            ff_put_guid(pb, &ff_asf_audio_conceal_spread);
645
        } else {
646 647
            ff_put_guid(pb, &ff_asf_video_stream);
            ff_put_guid(pb, &ff_asf_video_conceal_none);
648
        }
649
        avio_wl64(pb, 0); /* ??? */
650
        es_pos = avio_tell(pb);
651 652 653 654
        avio_wl32(pb, extra_size); /* wav header len */
        avio_wl32(pb, extra_size2); /* additional data len */
        avio_wl16(pb, n + 1); /* stream number */
        avio_wl32(pb, 0); /* ??? */
655

656
        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
657
            /* WAVEFORMATEX header */
658
            int wavsize = ff_put_wav_header(s, pb, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
659 660 661 662

            if (wavsize < 0)
                return -1;
            if (wavsize != extra_size) {
663
                cur_pos = avio_tell(pb);
664
                avio_seek(pb, es_pos, SEEK_SET);
665
                avio_wl32(pb, wavsize); /* wav header len */
666
                avio_seek(pb, cur_pos, SEEK_SET);
667
            }
668
            /* ERROR Correction */
669
            avio_w8(pb, 0x01);
670
            if (par->codec_id == AV_CODEC_ID_ADPCM_G726 || !par->block_align) {
671 672
                avio_wl16(pb, 0x0190);
                avio_wl16(pb, 0x0190);
673
            } else {
674 675
                avio_wl16(pb, par->block_align);
                avio_wl16(pb, par->block_align);
676
            }
677 678
            avio_wl16(pb, 0x01);
            avio_w8(pb, 0x00);
679
        } else {
680 681
            avio_wl32(pb, par->width);
            avio_wl32(pb, par->height);
682
            avio_w8(pb, 2); /* ??? */
683
            avio_wl16(pb, 40 + par->extradata_size); /* size */
684 685

            /* BITMAPINFOHEADER header */
686
            ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 1, 0);
687 688 689 690 691 692
        }
        end_header(pb, hpos);
    }

    /* media comments */

693
    hpos = put_header(pb, &ff_asf_codec_comment_header);
694
    ff_put_guid(pb, &ff_asf_codec_comment1_header);
695
    avio_wl32(pb, s->nb_streams);
696
    for (n = 0; n < s->nb_streams; n++) {
697
        const AVCodecDescriptor *codec_desc;
Anton Khirnov's avatar
Anton Khirnov committed
698
        const char *desc;
699

700 701
        par  = s->streams[n]->codecpar;
        codec_desc = avcodec_descriptor_get(par->codec_id);
702

703
        if (par->codec_type == AVMEDIA_TYPE_AUDIO)
704
            avio_wl16(pb, 2);
705
        else if (par->codec_type == AVMEDIA_TYPE_VIDEO)
706
            avio_wl16(pb, 1);
707
        else
708
            avio_wl16(pb, -1);
709

710
        if (par->codec_id == AV_CODEC_ID_WMAV2)
Anton Khirnov's avatar
Anton Khirnov committed
711
            desc = "Windows Media Audio V8";
712
        else
713
            desc = codec_desc ? codec_desc->name : NULL;
714

715 716 717 718
        if (desc) {
            AVIOContext *dyn_buf;
            uint8_t *buf;
            int len;
719

720 721
            if (avio_open_dyn_buf(&dyn_buf) < 0)
                return AVERROR(ENOMEM);
722

723 724 725 726 727 728 729 730
            avio_put_str16le(dyn_buf, desc);
            len = avio_close_dyn_buf(dyn_buf, &buf);
            avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2

            avio_write(pb, buf, len);
            av_freep(&buf);
        } else
            avio_wl16(pb, 0);
731

732
        avio_wl16(pb, 0); /* no parameters */
733

734
        /* id */
735
        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
736
            avio_wl16(pb, 2);
737
            avio_wl16(pb, par->codec_tag);
738
        } else {
739
            avio_wl16(pb, 4);
740
            avio_wl32(pb, par->codec_tag);
741
        }
742
        if (!par->codec_tag)
Michael Niedermayer's avatar
Michael Niedermayer committed
743
            return -1;
744 745 746 747 748
    }
    end_header(pb, hpos);

    /* patch the header size fields */

749
    cur_pos     = avio_tell(pb);
750 751
    header_size = cur_pos - header_offset;
    if (asf->is_streamed) {
752
        header_size += 8 + 30 + DATA_HEADER_SIZE;
753

754
        avio_seek(pb, header_offset - 10 - 30, SEEK_SET);
755
        avio_wl16(pb, header_size);
756
        avio_seek(pb, header_offset - 2 - 30, SEEK_SET);
757
        avio_wl16(pb, header_size);
758

759
        header_size -= 8 + 30 + DATA_HEADER_SIZE;
760 761
    }
    header_size += 24 + 6;
762
    avio_seek(pb, header_offset - 14, SEEK_SET);
763
    avio_wl64(pb, header_size);
764
    avio_seek(pb, cur_pos, SEEK_SET);
765 766 767

    /* movie chunk, followed by packets of packet_size */
    asf->data_offset = cur_pos;
768
    ff_put_guid(pb, &ff_asf_data_header);
769
    avio_wl64(pb, data_chunk_size);
770
    ff_put_guid(pb, &ff_asf_my_guid);
771 772 773
    avio_wl64(pb, asf->nb_packets); /* nb packets */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 1); /* ??? */
774 775 776 777 778 779 780
    return 0;
}

static int asf_write_header(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;

781
    s->packet_size  = asf->packet_size;
782
    s->max_interleave_delta = 0;
783
    asf->nb_packets = 0;
784

785 786 787 788 789
    if (s->nb_streams > 127) {
        av_log(s, AV_LOG_ERROR, "ASF can only handle 127 streams\n");
        return AVERROR(EINVAL);
    }

790
    asf->index_ptr             = av_malloc(sizeof(ASFIndex) * ASF_INDEX_BLOCK);
791 792
    if (!asf->index_ptr)
        return AVERROR(ENOMEM);
793
    asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
794
    asf->maximum_packet        = 0;
795

796 797 798 799
    /* the data-chunk-size has to be 50 (DATA_HEADER_SIZE), which is
     * data_size - asf->data_offset at the moment this function is done.
     * It is needed to use asf as a streamable format. */
    if (asf_write_header1(s, 0, DATA_HEADER_SIZE) < 0) {
800
        //av_free(asf);
801
        av_freep(&asf->index_ptr);
802 803 804
        return -1;
    }

805
    avio_flush(s->pb);
806

807
    asf->packet_nb_payloads     = 0;
808
    asf->packet_timestamp_start = -1;
809
    asf->packet_timestamp_end   = -1;
810
    ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
811
                      NULL, NULL, NULL, NULL);
812

813 814 815
    if (s->avoid_negative_ts < 0)
        s->avoid_negative_ts = 1;

816 817 818 819 820 821 822 823 824 825 826 827
    return 0;
}

static int asf_write_stream_header(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;

    asf->is_streamed = 1;

    return asf_write_header(s);
}

828 829 830
static int put_payload_parsing_info(AVFormatContext *s,
                                    unsigned sendtime, unsigned duration,
                                    int nb_payloads, int padsize)
831 832
{
    ASFContext *asf = s->priv_data;
833
    AVIOContext *pb = s->pb;
834
    int ppi_size, i;
835
    int64_t start = avio_tell(pb);
836 837

    int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS;
838

839
    padsize -= PACKET_HEADER_MIN_SIZE;
840
    if (asf->multi_payloads_present)
841
        padsize--;
842
    av_assert0(padsize >= 0);
843

844
    avio_w8(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS);
845
    for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++)
846
        avio_w8(pb, 0x0);
847

848 849
    if (asf->multi_payloads_present)
        iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT;
850 851 852

    if (padsize > 0) {
        if (padsize < 256)
853
            iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE;
854
        else
855
            iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD;
856
    }
857
    avio_w8(pb, iLengthTypeFlags);
858

859
    avio_w8(pb, ASF_PPI_PROPERTY_FLAGS);
860 861

    if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD)
862
        avio_wl16(pb, padsize - 2);
863
    if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE)
864
        avio_w8(pb, padsize - 1);
865

866 867
    avio_wl32(pb, sendtime);
    avio_wl16(pb, duration);
868
    if (asf->multi_payloads_present)
869
        avio_w8(pb, nb_payloads | ASF_PAYLOAD_FLAGS);
870

871
    ppi_size = avio_tell(pb) - start;
872

873
    return ppi_size;
874 875 876 877 878
}

static void flush_packet(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;
879
    int packet_hdr_size, packet_filled_size;
880

881
    av_assert0(asf->packet_timestamp_end >= asf->packet_timestamp_start);
882

883
    if (asf->is_streamed)
884
        put_chunk(s, 0x4424, s->packet_size, 0);
885

886 887
    packet_hdr_size = put_payload_parsing_info(s,
                                               asf->packet_timestamp_start,
888
                                               asf->packet_timestamp_end - asf->packet_timestamp_start,
889 890
                                               asf->packet_nb_payloads,
                                               asf->packet_size_left);
891

892
    packet_filled_size = asf->packet_size - asf->packet_size_left;
893
    av_assert0(packet_hdr_size <= asf->packet_size_left);
894
    memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
895

896
    avio_write(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size);
897

898
    avio_flush(s->pb);
899
    asf->nb_packets++;
900
    asf->packet_nb_payloads     = 0;
901
    asf->packet_timestamp_start = -1;
902
    asf->packet_timestamp_end   = -1;
903
    ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
904
                      NULL, NULL, NULL, NULL);
905 906
}

907
static void put_payload_header(AVFormatContext *s, ASFStream *stream,
908
                               int64_t presentation_time, int m_obj_size,
909
                               int m_obj_offset, int payload_len, int flags)
910 911
{
    ASFContext *asf = s->priv_data;
912
    AVIOContext *pb = &asf->pb;
913
    int val;
914

915
    val = stream->num;
916
    if (flags & AV_PKT_FLAG_KEY)
917
        val |= ASF_PL_FLAG_KEY_FRAME;
918
    avio_w8(pb, val);
919

920 921
    avio_w8(pb, stream->seq);     // Media object number
    avio_wl32(pb, m_obj_offset);  // Offset Into Media Object
922

923
    // Replicated Data shall be at least 8 bytes long.
924
    // The first 4 bytes of data shall contain the
925
    // Size of the Media Object that the payload belongs to.
926
    // The next 4 bytes of data shall contain the
927
    // Presentation Time for the media object that the payload belongs to.
928
    avio_w8(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH);
929

930
    avio_wl32(pb, m_obj_size);        // Replicated Data - Media Object Size
931
    avio_wl32(pb, (uint32_t) presentation_time); // Replicated Data - Presentation Time
932

933 934
    if (asf->multi_payloads_present) {
        avio_wl16(pb, payload_len);   // payload length
935
    }
936 937
}

938
static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst,
939
                      int64_t timestamp, const uint8_t *buf,
940
                      int m_obj_size, int flags)
941 942
{
    ASFContext *asf = s->priv_data;
943 944 945 946 947 948
    int m_obj_offset, payload_len, frag_len1;

    m_obj_offset = 0;
    while (m_obj_offset < m_obj_size) {
        payload_len = m_obj_size - m_obj_offset;
        if (asf->packet_timestamp_start == -1) {
949 950
            const int multi_payload_constant = (asf->packet_size - MULTI_PAYLOAD_HEADERS);
            asf->multi_payloads_present = (payload_len < multi_payload_constant);
951

952
            asf->packet_size_left = asf->packet_size;
953
            if (asf->multi_payloads_present) {
954
                frag_len1 = multi_payload_constant - 1;
955
            } else {
956
                frag_len1 = asf->packet_size - SINGLE_PAYLOAD_HEADERS;
957
            }
958
            asf->packet_timestamp_start = timestamp;
959
        } else {
960
            // multi payloads
961 962 963
            frag_len1 = asf->packet_size_left -
                        PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS -
                        PACKET_HEADER_MIN_SIZE - 1;
964

965
            if (frag_len1 < payload_len &&
966
                avst->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
967 968 969
                flush_packet(s);
                continue;
            }
970 971 972 973 974
            if (asf->packet_timestamp_start > INT64_MAX - UINT16_MAX ||
                timestamp > asf->packet_timestamp_start + UINT16_MAX) {
                flush_packet(s);
                continue;
            }
975
        }
976
        if (frag_len1 > 0) {
977 978 979
            if (payload_len > frag_len1)
                payload_len = frag_len1;
            else if (payload_len == (frag_len1 - 1))
980
                payload_len = frag_len1 - 2;  // additional byte need to put padding length
981

982 983
            put_payload_header(s, stream, timestamp + PREROLL_TIME,
                               m_obj_size, m_obj_offset, payload_len, flags);
984
            avio_write(&asf->pb, buf, payload_len);
985 986 987 988 989

            if (asf->multi_payloads_present)
                asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS);
            else
                asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD);
990
            asf->packet_timestamp_end = timestamp;
991

992
            asf->packet_nb_payloads++;
993
        } else {
994
            payload_len = 0;
995
        }
996
        m_obj_offset += payload_len;
997
        buf          += payload_len;
998 999 1000

        if (!asf->multi_payloads_present)
            flush_packet(s);
1001
        else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1))
1002
            flush_packet(s);
1003 1004
        else if (asf->packet_nb_payloads == ASF_PAYLOADS_PER_PACKET)
            flush_packet(s);
1005 1006 1007 1008
    }
    stream->seq++;
}

1009
static int update_index(AVFormatContext *s, int start_sec,
1010 1011
                         uint32_t packet_number, uint16_t packet_count,
                         uint64_t packet_offset)
1012 1013 1014 1015 1016 1017 1018 1019 1020
{
    ASFContext *asf = s->priv_data;

    if (start_sec > asf->next_start_sec) {
        int i;

        if (!asf->next_start_sec) {
            asf->next_packet_number = packet_number;
            asf->next_packet_count  = packet_count;
1021
            asf->next_packet_offset = packet_offset;
1022 1023 1024
        }

        if (start_sec > asf->nb_index_memory_alloc) {
1025
            int err;
1026
            asf->nb_index_memory_alloc = (start_sec + ASF_INDEX_BLOCK) & ~(ASF_INDEX_BLOCK - 1);
1027 1028 1029 1030 1031 1032
            if ((err = av_reallocp_array(&asf->index_ptr,
                                         asf->nb_index_memory_alloc,
                                         sizeof(*asf->index_ptr))) < 0) {
                asf->nb_index_memory_alloc = 0;
                return err;
            }
1033 1034 1035 1036
        }
        for (i = asf->next_start_sec; i < start_sec; i++) {
            asf->index_ptr[i].packet_number = asf->next_packet_number;
            asf->index_ptr[i].packet_count  = asf->next_packet_count;
1037 1038 1039
            asf->index_ptr[i].send_time     = asf->next_start_sec * INT64_C(10000000);
            asf->index_ptr[i].offset        = asf->next_packet_offset;

1040 1041 1042 1043 1044
        }
    }
    asf->maximum_packet     = FFMAX(asf->maximum_packet, packet_count);
    asf->next_packet_number = packet_number;
    asf->next_packet_count  = packet_count;
1045
    asf->next_packet_offset = packet_offset;
1046
    asf->next_start_sec     = start_sec;
1047 1048

    return 0;
1049 1050
}

1051
static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
1052 1053
{
    ASFContext *asf = s->priv_data;
1054
    AVIOContext *pb = s->pb;
1055
    ASFStream *stream;
1056
    AVCodecParameters *par;
1057 1058
    uint32_t packet_number;
    int64_t pts;
1059
    int start_sec;
1060
    int flags = pkt->flags;
1061
    int ret;
1062
    uint64_t offset = avio_tell(pb);
1063

1064
    par  = s->streams[pkt->stream_index]->codecpar;
1065
    stream = &asf->streams[pkt->stream_index];
1066

1067
    if (par->codec_type == AVMEDIA_TYPE_AUDIO)
1068
        flags &= ~AV_PKT_FLAG_KEY;
1069

1070
    pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
1071
    av_assert0(pts != AV_NOPTS_VALUE);
1072 1073 1074 1075 1076
    if (   pts < - PREROLL_TIME
        || pts > (INT_MAX-3)/10000LL * ASF_INDEXED_INTERVAL - PREROLL_TIME) {
        av_log(s, AV_LOG_ERROR, "input pts %"PRId64" is invalid\n", pts);
        return AVERROR(EINVAL);
    }
1077
    pts *= 10000;
1078
    asf->duration = FFMAX(asf->duration, pts + pkt->duration * 10000);
1079

1080
    packet_number = asf->nb_packets;
1081 1082
    put_frame(s, stream, s->streams[pkt->stream_index],
              pkt->dts, pkt->data, pkt->size, flags);
1083

1084 1085 1086
    start_sec = (int)((PREROLL_TIME * 10000 + pts + ASF_INDEXED_INTERVAL - 1)
              / ASF_INDEXED_INTERVAL);

1087
    /* check index */
1088
    if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) {
1089
        uint16_t packet_count = asf->nb_packets - packet_number;
1090 1091
        ret = update_index(s, start_sec, packet_number, packet_count, offset);
        if (ret < 0)
1092
            return ret;
1093
    }
1094 1095
    asf->end_sec = start_sec;

1096 1097 1098
    return 0;
}

1099
static int asf_write_index(AVFormatContext *s, const ASFIndex *index,
1100
                           uint16_t max, uint32_t count)
1101
{
1102
    AVIOContext *pb = s->pb;
1103 1104
    int i;

1105
    ff_put_guid(pb, &ff_asf_simple_index_header);
1106
    avio_wl64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2) * count);
1107
    ff_put_guid(pb, &ff_asf_my_guid);
1108 1109 1110
    avio_wl64(pb, ASF_INDEXED_INTERVAL);
    avio_wl32(pb, max);
    avio_wl32(pb, count);
1111
    for (i = 0; i < count; i++) {
1112 1113
        avio_wl32(pb, index[i].packet_number);
        avio_wl16(pb, index[i].packet_count);
1114 1115
    }

1116 1117 1118 1119 1120 1121
    return 0;
}

static int asf_write_trailer(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;
1122
    int64_t file_size, data_size;
1123
    int ret;
1124 1125 1126 1127 1128

    /* flush the current packet */
    if (asf->pb.buf_ptr > asf->pb.buffer)
        flush_packet(s);

1129
    /* write index */
1130
    data_size = avio_tell(s->pb);
1131
    if (!asf->is_streamed && asf->next_start_sec) {
1132
        if ((ret = update_index(s, asf->end_sec + 1, 0, 0, 0)) < 0)
1133
            return ret;
1134
        asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->next_start_sec);
1135
    }
1136
    avio_flush(s->pb);
1137

1138
    if (asf->is_streamed || !s->pb->seekable) {
1139 1140 1141
        put_chunk(s, 0x4524, 0, 0); /* end of stream */
    } else {
        /* rewrite an updated header */
1142
        file_size = avio_tell(s->pb);
1143
        avio_seek(s->pb, 0, SEEK_SET);
1144
        asf_write_header1(s, file_size, data_size - asf->data_offset);
1145 1146
    }

1147
    av_freep(&asf->index_ptr);
1148 1149 1150
    return 0;
}

1151 1152 1153 1154 1155
static const AVOption asf_options[] = {
    { "packet_size", "Packet size", offsetof(ASFContext, packet_size), AV_OPT_TYPE_INT, {.i64 = 3200}, PACKET_SIZE_MIN, PACKET_SIZE_MAX, AV_OPT_FLAG_ENCODING_PARAM },
    { NULL },
};

1156
#if CONFIG_ASF_MUXER
1157 1158 1159
static const AVClass asf_muxer_class = {
    .class_name     = "ASF muxer",
    .item_name      = av_default_item_name,
1160
    .option         = asf_options,
1161 1162 1163
    .version        = LIBAVUTIL_VERSION_INT,
};

1164
AVOutputFormat ff_asf_muxer = {
1165
    .name           = "asf",
1166
    .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1167 1168 1169
    .mime_type      = "video/x-ms-asf",
    .extensions     = "asf,wmv,wma",
    .priv_data_size = sizeof(ASFContext),
1170
    .audio_codec    = AV_CODEC_ID_WMAV2,
1171
    .video_codec    = AV_CODEC_ID_MSMPEG4V3,
1172 1173 1174
    .write_header   = asf_write_header,
    .write_packet   = asf_write_packet,
    .write_trailer  = asf_write_trailer,
1175
    .flags          = AVFMT_GLOBALHEADER,
1176
    .codec_tag      = (const AVCodecTag * const []) {
1177 1178
        codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
    },
1179
    .priv_class        = &asf_muxer_class,
1180
};
1181
#endif /* CONFIG_ASF_MUXER */
1182

1183
#if CONFIG_ASF_STREAM_MUXER
1184 1185 1186
static const AVClass asf_stream_muxer_class = {
    .class_name     = "ASF stream muxer",
    .item_name      = av_default_item_name,
1187
    .option         = asf_options,
1188 1189 1190
    .version        = LIBAVUTIL_VERSION_INT,
};

1191
AVOutputFormat ff_asf_stream_muxer = {
1192
    .name           = "asf_stream",
1193
    .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1194 1195 1196
    .mime_type      = "video/x-ms-asf",
    .extensions     = "asf,wmv,wma",
    .priv_data_size = sizeof(ASFContext),
1197
    .audio_codec    = AV_CODEC_ID_WMAV2,
1198
    .video_codec    = AV_CODEC_ID_MSMPEG4V3,
1199 1200 1201
    .write_header   = asf_write_stream_header,
    .write_packet   = asf_write_packet,
    .write_trailer  = asf_write_trailer,
1202
    .flags          = AVFMT_GLOBALHEADER,
1203
    .codec_tag      = (const AVCodecTag * const []) {
1204 1205
        codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
    },
1206
    .priv_class        = &asf_stream_muxer_class,
1207
};
1208
#endif /* CONFIG_ASF_STREAM_MUXER */