asfenc.c 31.1 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
 */
#include "avformat.h"
22
#include "internal.h"
23
#include "riff.h"
24
#include "asf.h"
25
#include "avio_internal.h"
26
#include "libavutil/dict.h"
27 28 29 30

#undef NDEBUG
#include <assert.h>

31

32
#define ASF_INDEXED_INTERVAL    10000000
33
#define ASF_INDEX_BLOCK         (1<<9)
34

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

#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

#define ASF_PPI_PROPERTY_FLAGS (\
48 49 50 51 52
                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 \
                )
53 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 147

#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

#define PACKET_HEADER_MIN_SIZE (\
148 149 150 151 152 153 154 155 156 157
                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*/ \
                )
158 159 160 161 162 163


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

#define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD (\
164 165 166 167 168 169
                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 \
                )
170

171
#define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS (\
172 173 174 175 176 177 178
                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 \
                )
179 180

#define SINGLE_PAYLOAD_DATA_LENGTH (\
181 182 183 184
                PACKET_SIZE - \
                PACKET_HEADER_MIN_SIZE - \
                PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
                )
185 186

#define MULTI_PAYLOAD_CONSTANT (\
187 188 189 190 191
                PACKET_SIZE - \
                PACKET_HEADER_MIN_SIZE - \
                1 - /*Payload Flags*/ \
                2*PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \
                )
192

193 194 195 196 197 198 199 200 201 202
typedef struct {
    uint32_t seqno;
    int is_streamed;
    ASFStream streams[128];              ///< it's max number and it's not that big
    /* non streamed additonnal info */
    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;
203 204
    int64_t packet_timestamp_start;
    int64_t packet_timestamp_end;
205 206
    unsigned int packet_nb_payloads;
    uint8_t packet_buf[PACKET_SIZE];
207
    AVIOContext pb;
208 209 210 211 212 213
    /* only for reading */
    uint64_t data_offset;                ///< beginning of the first data packet

    ASFIndex* index_ptr;
    uint32_t nb_index_memory_alloc;
    uint16_t maximum_packet;
214 215 216 217
    uint32_t next_packet_number;
    uint16_t next_packet_count;
    int      next_start_sec;
    int      end_sec;
218 219
} ASFContext;

220
static const AVCodecTag codec_asf_bmp_tags[] = {
221
    { AV_CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
222
    { AV_CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
223 224
    { AV_CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
    { AV_CODEC_ID_NONE, 0 },
225 226
};

227
#define PREROLL_TIME 3100
228

229
void ff_put_guid(AVIOContext *s, const ff_asf_guid *g)
230
{
Michael Niedermayer's avatar
Michael Niedermayer committed
231
    assert(sizeof(*g) == 16);
232
    avio_write(s, *g, sizeof(*g));
233 234
}

235
static void put_str16(AVIOContext *s, const char *tag)
236 237 238
{
    int len;
    uint8_t *pb;
239
    AVIOContext *dyn_buf;
240
    if (avio_open_dyn_buf(&dyn_buf) < 0)
241 242
        return;

243
    avio_put_str16le(dyn_buf, tag);
244
    len = avio_close_dyn_buf(dyn_buf, &pb);
245 246
    avio_wl16(s, len);
    avio_write(s, pb, len);
247
    av_freep(&pb);
248 249
}

250
static int64_t put_header(AVIOContext *pb, const ff_asf_guid *g)
251 252 253
{
    int64_t pos;

254
    pos = avio_tell(pb);
255
    ff_put_guid(pb, g);
256
    avio_wl64(pb, 24);
257 258 259 260
    return pos;
}

/* update header size */
261
static void end_header(AVIOContext *pb, int64_t pos)
262 263 264
{
    int64_t pos1;

265
    pos1 = avio_tell(pb);
266
    avio_seek(pb, pos + 16, SEEK_SET);
267
    avio_wl64(pb, pos1 - pos);
268
    avio_seek(pb, pos1, SEEK_SET);
269 270 271 272 273 274
}

/* write an asf chunk (only used in streaming case) */
static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags)
{
    ASFContext *asf = s->priv_data;
275
    AVIOContext *pb = s->pb;
276 277 278
    int length;

    length = payload_length + 8;
279 280 281 282 283
    avio_wl16(pb, type);
    avio_wl16(pb, length);    //size
    avio_wl32(pb, asf->seqno);//sequence number
    avio_wl16(pb, flags); /* unknown bytes */
    avio_wl16(pb, length);    //size_confirm
284 285 286 287 288 289 290 291
    asf->seqno++;
}

/* convert from unix to windows time */
static int64_t unix_to_file_time(int ti)
{
    int64_t t;

292 293
    t = ti * INT64_C(10000000);
    t += INT64_C(116444736000000000);
294 295 296 297 298 299 300
    return t;
}

/* write the header (used two times if non streamed) */
static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size)
{
    ASFContext *asf = s->priv_data;
301
    AVIOContext *pb = s->pb;
302
    AVDictionaryEntry *tags[5];
303 304
    int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
    int has_title;
305
    int metadata_count;
306 307 308
    AVCodecContext *enc;
    int64_t header_offset, cur_pos, hpos;
    int bit_rate;
309
    int64_t duration;
310

311
    ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);
312

313 314 315 316 317
    tags[0] = av_dict_get(s->metadata, "title"    , NULL, 0);
    tags[1] = av_dict_get(s->metadata, "author"   , NULL, 0);
    tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0);
    tags[3] = av_dict_get(s->metadata, "comment"  , NULL, 0);
    tags[4] = av_dict_get(s->metadata, "rating"   , NULL, 0);
318

319
    duration = asf->duration + PREROLL_TIME * 10000;
320
    has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4];
321
    metadata_count = av_dict_count(s->metadata);
322 323 324

    bit_rate = 0;
    for(n=0;n<s->nb_streams;n++) {
325
        enc = s->streams[n]->codec;
326

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

329 330 331 332 333 334 335
        bit_rate += enc->bit_rate;
    }

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

336
    ff_put_guid(pb, &ff_asf_header);
337 338 339 340
    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); /* ??? */
341 342

    /* file header */
343
    header_offset = avio_tell(pb);
344
    hpos = put_header(pb, &ff_asf_file_header);
345
    ff_put_guid(pb, &ff_asf_my_guid);
346
    avio_wl64(pb, file_size);
347
    file_time = 0;
348 349 350 351 352
    avio_wl64(pb, unix_to_file_time(file_time));
    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 */
353
    avio_wl32(pb, (asf->is_streamed || !pb->seekable ) ? 3 : 2); /* ??? */
354 355 356
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, bit_rate); /* Nominal data rate in bps */
357 358 359
    end_header(pb, hpos);

    /* unknown headers */
360
    hpos = put_header(pb, &ff_asf_head1_guid);
361
    ff_put_guid(pb, &ff_asf_head2_guid);
362 363
    avio_wl32(pb, 6);
    avio_wl16(pb, 0);
364 365 366 367
    end_header(pb, hpos);

    /* title and other infos */
    if (has_title) {
368 369
        int len;
        uint8_t *buf;
370
        AVIOContext *dyn_buf;
371

372
        if (avio_open_dyn_buf(&dyn_buf) < 0)
373 374
            return AVERROR(ENOMEM);

375
        hpos = put_header(pb, &ff_asf_comment_header);
376 377

        for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) {
378
            len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0;
379
            avio_wl16(pb, len);
380
        }
381
        len = avio_close_dyn_buf(dyn_buf, &buf);
382
        avio_write(pb, buf, len);
383
        av_freep(&buf);
384 385
        end_header(pb, hpos);
    }
386
    if (metadata_count) {
387
        AVDictionaryEntry *tag = NULL;
388
        hpos = put_header(pb, &ff_asf_extended_content_header);
389
        avio_wl16(pb, metadata_count);
390
        while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
391
            put_str16(pb, tag->key);
392
            avio_wl16(pb, 0);
393
            put_str16(pb, tag->value);
394 395 396
        }
        end_header(pb, hpos);
    }
397 398 399 400 401 402

    /* stream headers */
    for(n=0;n<s->nb_streams;n++) {
        int64_t es_pos;
        //        ASFStream *stream = &asf->streams[n];

403
        enc = s->streams[n]->codec;
404
        asf->streams[n].num = n + 1;
405
        asf->streams[n].seq = 1;
406

407

408
        switch(enc->codec_type) {
409
        case AVMEDIA_TYPE_AUDIO:
410 411
            wav_extra_size = 0;
            extra_size = 18 + wav_extra_size;
412
            extra_size2 = 8;
413 414
            break;
        default:
415
        case AVMEDIA_TYPE_VIDEO:
416 417
            wav_extra_size = enc->extradata_size;
            extra_size = 0x33 + wav_extra_size;
418 419 420 421
            extra_size2 = 0;
            break;
        }

422
        hpos = put_header(pb, &ff_asf_stream_header);
423
        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
424 425
            ff_put_guid(pb, &ff_asf_audio_stream);
            ff_put_guid(pb, &ff_asf_audio_conceal_spread);
426
        } else {
427 428
            ff_put_guid(pb, &ff_asf_video_stream);
            ff_put_guid(pb, &ff_asf_video_conceal_none);
429
        }
430
        avio_wl64(pb, 0); /* ??? */
431
        es_pos = avio_tell(pb);
432 433 434 435
        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); /* ??? */
436

437
        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
438
            /* WAVEFORMATEX header */
439
            int wavsize = ff_put_wav_header(pb, enc);
440 441 442 443

            if (wavsize < 0)
                return -1;
            if (wavsize != extra_size) {
444
                cur_pos = avio_tell(pb);
445
                avio_seek(pb, es_pos, SEEK_SET);
446
                avio_wl32(pb, wavsize); /* wav header len */
447
                avio_seek(pb, cur_pos, SEEK_SET);
448
            }
449
            /* ERROR Correction */
450
            avio_w8(pb, 0x01);
451
            if(enc->codec_id == AV_CODEC_ID_ADPCM_G726 || !enc->block_align){
452 453
                avio_wl16(pb, 0x0190);
                avio_wl16(pb, 0x0190);
454
            }else{
455 456
                avio_wl16(pb, enc->block_align);
                avio_wl16(pb, enc->block_align);
457
            }
458 459
            avio_wl16(pb, 0x01);
            avio_w8(pb, 0x00);
460
        } else {
461 462 463 464
            avio_wl32(pb, enc->width);
            avio_wl32(pb, enc->height);
            avio_w8(pb, 2); /* ??? */
            avio_wl16(pb, 40 + enc->extradata_size); /* size */
465 466

            /* BITMAPINFOHEADER header */
467
            ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1);
468 469 470 471 472 473
        }
        end_header(pb, hpos);
    }

    /* media comments */

474
    hpos = put_header(pb, &ff_asf_codec_comment_header);
475
    ff_put_guid(pb, &ff_asf_codec_comment1_header);
476
    avio_wl32(pb, s->nb_streams);
477 478
    for(n=0;n<s->nb_streams;n++) {
        AVCodec *p;
Anton Khirnov's avatar
Anton Khirnov committed
479
        const char *desc;
480 481
        int len;
        uint8_t *buf;
482
        AVIOContext *dyn_buf;
483

484
        enc = s->streams[n]->codec;
485 486
        p = avcodec_find_encoder(enc->codec_id);

487
        if(enc->codec_type == AVMEDIA_TYPE_AUDIO)
488
            avio_wl16(pb, 2);
489
        else if(enc->codec_type == AVMEDIA_TYPE_VIDEO)
490
            avio_wl16(pb, 1);
491
        else
492
            avio_wl16(pb, -1);
493

494
        if(enc->codec_id == AV_CODEC_ID_WMAV2)
Anton Khirnov's avatar
Anton Khirnov committed
495
            desc = "Windows Media Audio V8";
496
        else
Anton Khirnov's avatar
Anton Khirnov committed
497
            desc = p ? p->name : enc->codec_name;
498

499
        if ( avio_open_dyn_buf(&dyn_buf) < 0)
500 501
            return AVERROR(ENOMEM);

502
        avio_put_str16le(dyn_buf, desc);
503
        len = avio_close_dyn_buf(dyn_buf, &buf);
504
        avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2
505

506
        avio_write(pb, buf, len);
507 508
        av_freep(&buf);

509
        avio_wl16(pb, 0); /* no parameters */
510 511


512
        /* id */
513
        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
514 515
            avio_wl16(pb, 2);
            avio_wl16(pb, enc->codec_tag);
516
        } else {
517 518
            avio_wl16(pb, 4);
            avio_wl32(pb, enc->codec_tag);
519
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
520 521
        if(!enc->codec_tag)
            return -1;
522 523 524 525 526
    }
    end_header(pb, hpos);

    /* patch the header size fields */

527
    cur_pos = avio_tell(pb);
528 529 530 531
    header_size = cur_pos - header_offset;
    if (asf->is_streamed) {
        header_size += 8 + 30 + 50;

532
        avio_seek(pb, header_offset - 10 - 30, SEEK_SET);
533
        avio_wl16(pb, header_size);
534
        avio_seek(pb, header_offset - 2 - 30, SEEK_SET);
535
        avio_wl16(pb, header_size);
536 537 538 539

        header_size -= 8 + 30 + 50;
    }
    header_size += 24 + 6;
540
    avio_seek(pb, header_offset - 14, SEEK_SET);
541
    avio_wl64(pb, header_size);
542
    avio_seek(pb, cur_pos, SEEK_SET);
543 544 545

    /* movie chunk, followed by packets of packet_size */
    asf->data_offset = cur_pos;
546
    ff_put_guid(pb, &ff_asf_data_header);
547
    avio_wl64(pb, data_chunk_size);
548
    ff_put_guid(pb, &ff_asf_my_guid);
549 550 551
    avio_wl64(pb, asf->nb_packets); /* nb packets */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 1); /* ??? */
552 553 554 555 556 557 558
    return 0;
}

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

559
    s->packet_size  = PACKET_SIZE;
560
    asf->nb_packets = 0;
561

562
    asf->index_ptr = av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK );
563 564
    asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
    asf->maximum_packet = 0;
565

Patric Stout's avatar
Patric Stout committed
566 567 568 569
    /* the data-chunk-size has to be 50, which is data_size - asf->data_offset
     *  at the moment this function is done. It is needed to use asf as
     *  streamable format. */
    if (asf_write_header1(s, 0, 50) < 0) {
570 571 572 573
        //av_free(asf);
        return -1;
    }

574
    avio_flush(s->pb);
575

576
    asf->packet_nb_payloads = 0;
577 578
    asf->packet_timestamp_start = -1;
    asf->packet_timestamp_end = -1;
579
    ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
580 581
                  NULL, NULL, NULL, NULL);

582 583 584
    if (s->avoid_negative_ts < 0)
        s->avoid_negative_ts = 1;

585 586 587 588 589 590 591 592 593 594 595 596
    return 0;
}

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

    asf->is_streamed = 1;

    return asf_write_header(s);
}

597 598
static int put_payload_parsing_info(
                                AVFormatContext *s,
599
                                unsigned int    sendtime,
600
                                unsigned int    duration,
601
                                int             nb_payloads,
602 603
                                int             padsize
            )
604 605
{
    ASFContext *asf = s->priv_data;
606
    AVIOContext *pb = s->pb;
607
    int ppi_size, i;
608
    int64_t start= avio_tell(pb);
609 610

    int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS;
611

612 613 614 615 616
    padsize -= PACKET_HEADER_MIN_SIZE;
    if(asf->multi_payloads_present)
        padsize--;
    assert(padsize>=0);

617
    avio_w8(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS);
618
    for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++){
619
        avio_w8(pb, 0x0);
620 621
    }

622 623
    if (asf->multi_payloads_present)
        iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT;
624 625 626

    if (padsize > 0) {
        if (padsize < 256)
627
            iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE;
628
        else
629
            iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD;
630
    }
631
    avio_w8(pb, iLengthTypeFlags);
632

633
    avio_w8(pb, ASF_PPI_PROPERTY_FLAGS);
634 635

    if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD)
636
        avio_wl16(pb, padsize - 2);
637
    if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE)
638
        avio_w8(pb, padsize - 1);
639

640 641
    avio_wl32(pb, sendtime);
    avio_wl16(pb, duration);
642
    if (asf->multi_payloads_present)
643
        avio_w8(pb, nb_payloads | ASF_PAYLOAD_FLAGS);
644

645
    ppi_size = avio_tell(pb) - start;
646

647
    return ppi_size;
648 649 650 651 652
}

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

655 656
    assert(asf->packet_timestamp_end >= asf->packet_timestamp_start);

657
    if (asf->is_streamed) {
658
        put_chunk(s, 0x4424, s->packet_size, 0);
659 660 661 662 663 664 665 666 667
    }

    packet_hdr_size = put_payload_parsing_info(
                            s,
                            asf->packet_timestamp_start,
                            asf->packet_timestamp_end - asf->packet_timestamp_start,
                            asf->packet_nb_payloads,
                            asf->packet_size_left
                        );
668

669 670
    packet_filled_size = PACKET_SIZE - asf->packet_size_left;
    assert(packet_hdr_size <= asf->packet_size_left);
671
    memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
672

673
    avio_write(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size);
674

675
    avio_flush(s->pb);
676
    asf->nb_packets++;
677
    asf->packet_nb_payloads = 0;
678 679
    asf->packet_timestamp_start = -1;
    asf->packet_timestamp_end = -1;
680
    ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
681 682 683
                  NULL, NULL, NULL, NULL);
}

684 685 686
static void put_payload_header(
                                AVFormatContext *s,
                                ASFStream       *stream,
687
                                int64_t         presentation_time,
688 689
                                int             m_obj_size,
                                int             m_obj_offset,
690 691
                                int             payload_len,
                                int             flags
692
            )
693 694
{
    ASFContext *asf = s->priv_data;
695
    AVIOContext *pb = &asf->pb;
696
    int val;
697

698
    val = stream->num;
699
    if (flags & AV_PKT_FLAG_KEY)
700
        val |= ASF_PL_FLAG_KEY_FRAME;
701
    avio_w8(pb, val);
702

703 704
    avio_w8(pb, stream->seq);  //Media object number
    avio_wl32(pb, m_obj_offset); //Offset Into Media Object
705

706
    // Replicated Data shall be at least 8 bytes long.
707
    // The first 4 bytes of data shall contain the
708
    // Size of the Media Object that the payload belongs to.
709
    // The next 4 bytes of data shall contain the
710
    // Presentation Time for the media object that the payload belongs to.
711
    avio_w8(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH);
712

713
    avio_wl32(pb, m_obj_size);       //Replicated Data - Media Object Size
714
    avio_wl32(pb, (uint32_t) presentation_time);//Replicated Data - Presentation Time
715

716
    if (asf->multi_payloads_present){
717
        avio_wl16(pb, payload_len);   //payload length
718
    }
719 720
}

721 722 723
static void put_frame(
                    AVFormatContext *s,
                    ASFStream       *stream,
724
                    AVStream        *avst,
725
                    int64_t         timestamp,
726
                    const uint8_t   *buf,
727
                    int             m_obj_size,
728
                    int             flags
729
                )
730 731
{
    ASFContext *asf = s->priv_data;
732 733 734 735 736 737 738
    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) {
            asf->multi_payloads_present = (payload_len < MULTI_PAYLOAD_CONSTANT);
739

740
            asf->packet_size_left = PACKET_SIZE;
741 742 743 744 745 746
            if (asf->multi_payloads_present){
                frag_len1 = MULTI_PAYLOAD_CONSTANT - 1;
            }
            else {
                frag_len1 = SINGLE_PAYLOAD_DATA_LENGTH;
            }
747
            asf->packet_timestamp_start = timestamp;
748 749 750
        }
        else {
            // multi payloads
751
            frag_len1 = asf->packet_size_left - PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS - PACKET_HEADER_MIN_SIZE - 1;
752

753
            if(frag_len1 < payload_len && avst->codec->codec_type == AVMEDIA_TYPE_AUDIO){
754 755 756
                flush_packet(s);
                continue;
            }
757
        }
758
        if (frag_len1 > 0) {
759 760 761 762
            if (payload_len > frag_len1)
                payload_len = frag_len1;
            else if (payload_len == (frag_len1 - 1))
                payload_len = frag_len1 - 2;  //additional byte need to put padding length
763

764
            put_payload_header(s, stream, timestamp+PREROLL_TIME, m_obj_size, m_obj_offset, payload_len, flags);
765
            avio_write(&asf->pb, buf, payload_len);
766 767 768 769 770

            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);
771
            asf->packet_timestamp_end = timestamp;
772

773
            asf->packet_nb_payloads++;
774
        } else {
775
            payload_len = 0;
776
        }
777 778 779 780 781
        m_obj_offset += payload_len;
        buf += payload_len;

        if (!asf->multi_payloads_present)
            flush_packet(s);
782
        else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1))
783 784 785 786 787
            flush_packet(s);
    }
    stream->seq++;
}

788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
static void update_index(AVFormatContext *s, int start_sec,
                         uint32_t packet_number, uint16_t packet_count)
{
    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;
        }

        if (start_sec > asf->nb_index_memory_alloc) {
            asf->nb_index_memory_alloc = (start_sec + ASF_INDEX_BLOCK) & ~(ASF_INDEX_BLOCK - 1);
            asf->index_ptr = av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc );
        }
        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;
        }
    }
    asf->maximum_packet     = FFMAX(asf->maximum_packet, packet_count);
    asf->next_packet_number = packet_number;
    asf->next_packet_count  = packet_count;
    asf->next_start_sec     = start_sec;
}

816
static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
817 818 819 820
{
    ASFContext *asf = s->priv_data;
    ASFStream *stream;
    AVCodecContext *codec;
821 822
    uint32_t packet_number;
    int64_t pts;
823
    int start_sec;
824
    int flags= pkt->flags;
825

826
    codec = s->streams[pkt->stream_index]->codec;
827
    stream = &asf->streams[pkt->stream_index];
828

829
    if(codec->codec_type == AVMEDIA_TYPE_AUDIO)
830
        flags &= ~AV_PKT_FLAG_KEY;
831

832
    pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
833
    assert(pts != AV_NOPTS_VALUE);
834 835
    pts *= 10000;
    asf->duration= FFMAX(asf->duration, pts + pkt->duration * 10000);
836

837
    packet_number = asf->nb_packets;
838
    put_frame(s, stream, s->streams[pkt->stream_index], pkt->dts, pkt->data, pkt->size, flags);
839

840 841 842
    start_sec = (int)((PREROLL_TIME * 10000 + pts + ASF_INDEXED_INTERVAL - 1)
              / ASF_INDEXED_INTERVAL);

843
    /* check index */
844
    if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) {
845
        uint16_t packet_count = asf->nb_packets - packet_number;
846
        update_index(s, start_sec, packet_number, packet_count);
847
    }
848 849
    asf->end_sec = start_sec;

850 851 852 853 854 855
    return 0;
}

//
static int asf_write_index(AVFormatContext *s, ASFIndex *index, uint16_t max, uint32_t count)
{
856
    AVIOContext *pb = s->pb;
857 858
    int i;

859
    ff_put_guid(pb, &ff_asf_simple_index_header);
860
    avio_wl64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count);
861
    ff_put_guid(pb, &ff_asf_my_guid);
862 863 864
    avio_wl64(pb, ASF_INDEXED_INTERVAL);
    avio_wl32(pb, max);
    avio_wl32(pb, count);
865
    for(i=0; i<count; i++) {
866 867
        avio_wl32(pb, index[i].packet_number);
        avio_wl16(pb, index[i].packet_count);
868 869
    }

870 871 872 873 874 875
    return 0;
}

static int asf_write_trailer(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;
876
    int64_t file_size,data_size;
877 878 879 880 881

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

882
    /* write index */
883
    data_size = avio_tell(s->pb);
884 885 886
    if (!asf->is_streamed && asf->next_start_sec) {
        update_index(s, asf->end_sec + 1, 0, 0);
        asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->next_start_sec);
887
    }
888
    avio_flush(s->pb);
889

890
    if (asf->is_streamed || !s->pb->seekable) {
891 892 893
        put_chunk(s, 0x4524, 0, 0); /* end of stream */
    } else {
        /* rewrite an updated header */
894
        file_size = avio_tell(s->pb);
895
        avio_seek(s->pb, 0, SEEK_SET);
896
        asf_write_header1(s, file_size, data_size - asf->data_offset);
897 898
    }

899
    av_free(asf->index_ptr);
900 901 902
    return 0;
}

903
#if CONFIG_ASF_MUXER
904
AVOutputFormat ff_asf_muxer = {
905
    .name           = "asf",
906
    .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
907 908 909
    .mime_type      = "video/x-ms-asf",
    .extensions     = "asf,wmv,wma",
    .priv_data_size = sizeof(ASFContext),
910
    .audio_codec    = AV_CODEC_ID_WMAV2,
911
    .video_codec    = AV_CODEC_ID_MSMPEG4V3,
912 913 914
    .write_header   = asf_write_header,
    .write_packet   = asf_write_packet,
    .write_trailer  = asf_write_trailer,
915 916 917 918
    .flags          = AVFMT_GLOBALHEADER,
    .codec_tag      = (const AVCodecTag* const []){
        codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
    },
919
};
920
#endif
921

922
#if CONFIG_ASF_STREAM_MUXER
923
AVOutputFormat ff_asf_stream_muxer = {
924
    .name           = "asf_stream",
925
    .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
926 927 928
    .mime_type      = "video/x-ms-asf",
    .extensions     = "asf,wmv,wma",
    .priv_data_size = sizeof(ASFContext),
929
    .audio_codec    = AV_CODEC_ID_WMAV2,
930
    .video_codec    = AV_CODEC_ID_MSMPEG4V3,
931 932 933
    .write_header   = asf_write_stream_header,
    .write_packet   = asf_write_packet,
    .write_trailer  = asf_write_trailer,
934 935 936 937
    .flags          = AVFMT_GLOBALHEADER,
    .codec_tag      = (const AVCodecTag* const []){
        codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
    },
938
};
939
#endif //CONFIG_ASF_STREAM_MUXER