asfdec.c 53.4 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
2
 * ASF compatible demuxer
3
 * Copyright (c) 2000, 2001 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav 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.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * Libav is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with Libav; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
21

22 23
#include <inttypes.h>

24
#include "libavutil/attributes.h"
25
#include "libavutil/avassert.h"
26
#include "libavutil/avstring.h"
27
#include "libavutil/bswap.h"
28
#include "libavutil/common.h"
29
#include "libavutil/dict.h"
30
#include "libavutil/internal.h"
31
#include "libavutil/mathematics.h"
32
#include "libavutil/opt.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
33
#include "avformat.h"
34
#include "avio_internal.h"
35
#include "avlanguage.h"
36
#include "id3v2.h"
37
#include "internal.h"
38
#include "riff.h"
39
#include "asf.h"
40
#include "asfcrypt.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
41

42
typedef struct {
43
    const AVClass *class;
44 45 46
    int asfid2avid[128];                 ///< conversion table from asf ID 2 AVStream ID
    ASFStream streams[128];              ///< it's max number and it's not that big
    uint32_t stream_bitrates[128];       ///< max number of streams, bitrate for each (for streaming)
47
    AVRational dar[128];
48 49 50 51 52 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
    char stream_languages[128][6];       ///< max number of streams, language for each (RFC1766, e.g. en-US)
    /* non streamed additonnal info */
    /* packet filling */
    int packet_size_left;
    /* only for reading */
    uint64_t data_offset;                ///< beginning of the first data packet
    uint64_t data_object_offset;         ///< data object offset (excl. GUID & size)
    uint64_t data_object_size;           ///< size of the data object
    int index_read;

    ASFMainHeader hdr;

    int packet_flags;
    int packet_property;
    int packet_timestamp;
    int packet_segsizetype;
    int packet_segments;
    int packet_seq;
    int packet_replic_size;
    int packet_key_frame;
    int packet_padsize;
    unsigned int packet_frag_offset;
    unsigned int packet_frag_size;
    int64_t packet_frag_timestamp;
    int packet_multi_size;
    int packet_obj_size;
    int packet_time_delta;
    int packet_time_start;
    int64_t packet_pos;

    int stream_index;

80
    ASFStream *asf_st;                   ///< currently decoded stream
81 82

    int no_resync_search;
83 84
} ASFContext;

85
static const AVOption options[] = {
86
    { "no_resync_search", "Don't try to resynchronize by looking for a certain optional start code", offsetof(ASFContext, no_resync_search), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
87 88 89 90 91 92 93 94 95 96
    { NULL },
};

static const AVClass asf_class = {
    .class_name = "asf demuxer",
    .item_name  = av_default_item_name,
    .option     = options,
    .version    = LIBAVUTIL_VERSION_INT,
};

Michael Niedermayer's avatar
Michael Niedermayer committed
97 98 99
#undef NDEBUG
#include <assert.h>

100
#define ASF_MAX_STREAMS 127
101
#define FRAME_HEADER_SIZE 17
102
// Fix Me! FRAME_HEADER_SIZE may be different.
103

104
static const ff_asf_guid index_guid = {
Michael Niedermayer's avatar
Michael Niedermayer committed
105
    0x90, 0x08, 0x00, 0x33, 0xb1, 0xe5, 0xcf, 0x11, 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb
Fabrice Bellard's avatar
Fabrice Bellard committed
106 107
};

108
#ifdef DEBUG
109
static const ff_asf_guid stream_bitrate_guid = { /* (http://get.to/sdp) */
110 111
    0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2
};
Fabrice Bellard's avatar
Fabrice Bellard committed
112

113 114 115
#define PRINT_IF_GUID(g, cmp) \
    if (!ff_guidcmp(g, &cmp)) \
        av_dlog(NULL, "(GUID: %s) ", # cmp)
François Revol's avatar
François Revol committed
116

117
static void print_guid(ff_asf_guid *g)
Fabrice Bellard's avatar
Fabrice Bellard committed
118 119
{
    int i;
120 121 122 123 124 125 126 127 128 129 130 131
    PRINT_IF_GUID(g, ff_asf_header);
    else PRINT_IF_GUID(g, ff_asf_file_header);
    else PRINT_IF_GUID(g, ff_asf_stream_header);
    else PRINT_IF_GUID(g, ff_asf_audio_stream);
    else PRINT_IF_GUID(g, ff_asf_audio_conceal_none);
    else PRINT_IF_GUID(g, ff_asf_video_stream);
    else PRINT_IF_GUID(g, ff_asf_video_conceal_none);
    else PRINT_IF_GUID(g, ff_asf_command_stream);
    else PRINT_IF_GUID(g, ff_asf_comment_header);
    else PRINT_IF_GUID(g, ff_asf_codec_comment_header);
    else PRINT_IF_GUID(g, ff_asf_codec_comment1_header);
    else PRINT_IF_GUID(g, ff_asf_data_header);
François Revol's avatar
François Revol committed
132
    else PRINT_IF_GUID(g, index_guid);
133 134 135 136 137 138 139 140
    else PRINT_IF_GUID(g, ff_asf_head1_guid);
    else PRINT_IF_GUID(g, ff_asf_head2_guid);
    else PRINT_IF_GUID(g, ff_asf_my_guid);
    else PRINT_IF_GUID(g, ff_asf_ext_stream_header);
    else PRINT_IF_GUID(g, ff_asf_extended_content_header);
    else PRINT_IF_GUID(g, ff_asf_ext_stream_embed_stream_header);
    else PRINT_IF_GUID(g, ff_asf_ext_stream_audio_stream);
    else PRINT_IF_GUID(g, ff_asf_metadata_header);
141
    else PRINT_IF_GUID(g, ff_asf_metadata_library_header);
142
    else PRINT_IF_GUID(g, ff_asf_marker_header);
143
    else PRINT_IF_GUID(g, stream_bitrate_guid);
144
    else PRINT_IF_GUID(g, ff_asf_language_guid);
François Revol's avatar
François Revol committed
145
    else
146
        av_dlog(NULL, "(GUID: unknown) ");
147
    for (i = 0; i < 16; i++)
148 149
        av_dlog(NULL, " 0x%02x,", (*g)[i]);
    av_dlog(NULL, "}\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
150
}
151
#undef PRINT_IF_GUID
152 153
#else
#define print_guid(g)
Fabrice Bellard's avatar
Fabrice Bellard committed
154 155
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
156 157 158
static int asf_probe(AVProbeData *pd)
{
    /* check file header */
159
    if (!ff_guidcmp(pd->buf, &ff_asf_header))
Fabrice Bellard's avatar
Fabrice Bellard committed
160 161 162 163 164
        return AVPROBE_SCORE_MAX;
    else
        return 0;
}

165 166 167
/* size of type 2 (BOOL) is 32bit for "Extended Content Description Object"
 * but 16 bit for "Metadata Object" and "Metadata Library Object" */
static int get_value(AVIOContext *pb, int type, int type2_size)
168 169 170
{
    switch (type) {
    case 2:
171
        return (type2_size == 32) ? avio_rl32(pb) : avio_rl16(pb);
172 173 174 175 176 177 178 179
    case 3:
        return avio_rl32(pb);
    case 4:
        return avio_rl64(pb);
    case 5:
        return avio_rl16(pb);
    default:
        return INT_MIN;
180 181 182
    }
}

183 184 185 186
/* MSDN claims that this should be "compatible with the ID3 frame, APIC",
 * but in reality this is only loosely similar */
static int asf_read_picture(AVFormatContext *s, int len)
{
187
    AVPacket pkt          = { 0 };
188
    const CodecMime *mime = ff_id3v2_mime_tags;
189
    enum  AVCodecID id    = AV_CODEC_ID_NONE;
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    char mimetype[64];
    uint8_t  *desc = NULL;
    AVStream   *st = NULL;
    int ret, type, picsize, desc_len;

    /* type + picsize + mime + desc */
    if (len < 1 + 4 + 2 + 2) {
        av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len);
        return AVERROR_INVALIDDATA;
    }

    /* picture type */
    type = avio_r8(s->pb);
    len--;
    if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) {
        av_log(s, AV_LOG_WARNING, "Unknown attached picture type: %d.\n", type);
        type = 0;
    }

    /* picture data size */
    picsize = avio_rl32(s->pb);
211
    len    -= 4;
212 213 214

    /* picture MIME type */
    len -= avio_get_str16le(s->pb, len, mimetype, sizeof(mimetype));
215
    while (mime->id != AV_CODEC_ID_NONE) {
216 217 218 219 220 221
        if (!strncmp(mime->str, mimetype, sizeof(mimetype))) {
            id = mime->id;
            break;
        }
        mime++;
    }
222
    if (id == AV_CODEC_ID_NONE) {
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
        av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n",
               mimetype);
        return 0;
    }

    if (picsize >= len) {
        av_log(s, AV_LOG_ERROR, "Invalid attached picture data size: %d >= %d.\n",
               picsize, len);
        return AVERROR_INVALIDDATA;
    }

    /* picture description */
    desc_len = (len - picsize) * 2 + 1;
    desc     = av_malloc(desc_len);
    if (!desc)
        return AVERROR(ENOMEM);
    len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len);

    ret = av_get_packet(s->pb, &pkt, picsize);
    if (ret < 0)
        goto fail;

245
    st  = avformat_new_stream(s, NULL);
246
    if (!st) {
247 248 249
        ret = AVERROR(ENOMEM);
        goto fail;
    }
250 251 252 253
    st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
    st->codec->codec_type         = AVMEDIA_TYPE_VIDEO;
    st->codec->codec_id           = id;
    st->attached_pic              = pkt;
254
    st->attached_pic.stream_index = st->index;
255
    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

    if (*desc)
        av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL);
    else
        av_freep(&desc);

    av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0);

    return 0;

fail:
    av_freep(&desc);
    av_free_packet(&pkt);
    return ret;
}

272 273 274 275 276 277 278 279 280 281
static void get_id3_tag(AVFormatContext *s, int len)
{
    ID3v2ExtraMeta *id3v2_extra_meta = NULL;

    ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
    if (id3v2_extra_meta)
        ff_id3v2_parse_apic(s, &id3v2_extra_meta);
    ff_id3v2_free_extra_meta(&id3v2_extra_meta);
}

282
static void get_tag(AVFormatContext *s, const char *key, int type, int len, int type2_size)
283
{
284
    char *value;
285
    int64_t off = avio_tell(s->pb);
286

287
    if ((unsigned)len >= (UINT_MAX - 1) / 2)
288 289
        return;

290
    value = av_malloc(2 * len + 1);
291
    if (!value)
292
        goto finish;
293

294
    if (type == 0) {         // UTF16-LE
295
        avio_get_str16le(s->pb, len, value, 2 * len + 1);
296 297 298 299 300 301 302 303 304
    } else if (type == 1) {  // byte array
        if (!strcmp(key, "WM/Picture")) { // handle cover art
            asf_read_picture(s, len);
        } else if (!strcmp(key, "ID3")) { // handle ID3 tag
            get_id3_tag(s, len);
        } else {
            av_log(s, AV_LOG_VERBOSE, "Unsupported byte array in tag %s.\n", key);
        }
        goto finish;
305
    } else if (type > 1 && type <= 5) {  // boolean or DWORD or QWORD or WORD
306
        uint64_t num = get_value(s->pb, type, type2_size);
307
        snprintf(value, len, "%"PRIu64, num);
308 309 310
    } else if (type == 6) { // (don't) handle GUID
        av_log(s, AV_LOG_DEBUG, "Unsupported GUID value in tag %s.\n", key);
        goto finish;
311
    } else {
312 313
        av_log(s, AV_LOG_DEBUG,
               "Unsupported value type %d in tag %s.\n", type, key);
314
        goto finish;
315
    }
316
    if (*value)
317
        av_dict_set(&s->metadata, key, value, 0);
318

319
finish:
320
    av_freep(&value);
321
    avio_seek(s->pb, off + len, SEEK_SET);
322 323
}

324 325 326
static int asf_read_file_properties(AVFormatContext *s, int64_t size)
{
    ASFContext *asf = s->priv_data;
327
    AVIOContext *pb = s->pb;
328 329

    ff_get_guid(pb, &asf->hdr.guid);
330 331
    asf->hdr.file_size   = avio_rl64(pb);
    asf->hdr.create_time = avio_rl64(pb);
332
    avio_rl64(pb);                               /* number of packets */
333 334 335 336 337 338 339 340
    asf->hdr.play_time   = avio_rl64(pb);
    asf->hdr.send_time   = avio_rl64(pb);
    asf->hdr.preroll     = avio_rl32(pb);
    asf->hdr.ignore      = avio_rl32(pb);
    asf->hdr.flags       = avio_rl32(pb);
    asf->hdr.min_pktsize = avio_rl32(pb);
    asf->hdr.max_pktsize = avio_rl32(pb);
    if (asf->hdr.min_pktsize >= (1U << 29))
341
        return AVERROR_INVALIDDATA;
342 343
    asf->hdr.max_bitrate = avio_rl32(pb);
    s->packet_size       = asf->hdr.max_pktsize;
344 345 346 347

    return 0;
}

348 349 350
static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
{
    ASFContext *asf = s->priv_data;
351
    AVIOContext *pb = s->pb;
352 353 354 355 356 357 358
    AVStream *st;
    ASFStream *asf_st;
    ff_asf_guid g;
    enum AVMediaType type;
    int type_specific_size, sizeX;
    unsigned int tag1;
    int64_t pos1, pos2, start_time;
359
    int test_for_ext_stream_audio, is_dvr_ms_audio = 0;
360 361 362 363 364 365

    if (s->nb_streams == ASF_MAX_STREAMS) {
        av_log(s, AV_LOG_ERROR, "too many streams\n");
        return AVERROR(EINVAL);
    }

366
    pos1 = avio_tell(pb);
367

368
    st = avformat_new_stream(s, NULL);
369 370
    if (!st)
        return AVERROR(ENOMEM);
371
    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
372 373 374
    asf_st = av_mallocz(sizeof(ASFStream));
    if (!asf_st)
        return AVERROR(ENOMEM);
375
    st->priv_data  = asf_st;
376
    st->start_time = 0;
377
    start_time     = asf->hdr.preroll;
378 379 380

    asf_st->stream_language_index = 128; // invalid stream index means no language info

381
    if (!(asf->hdr.flags & 0x01)) { // if we aren't streaming...
382
        st->duration = asf->hdr.play_time /
383
                       (10000000 / 1000) - start_time;
384 385 386 387 388 389 390 391 392
    }
    ff_get_guid(pb, &g);

    test_for_ext_stream_audio = 0;
    if (!ff_guidcmp(&g, &ff_asf_audio_stream)) {
        type = AVMEDIA_TYPE_AUDIO;
    } else if (!ff_guidcmp(&g, &ff_asf_video_stream)) {
        type = AVMEDIA_TYPE_VIDEO;
    } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) {
393
        type                = AVMEDIA_TYPE_VIDEO;
394
        st->codec->codec_id = AV_CODEC_ID_MJPEG;
395 396 397 398
    } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) {
        type = AVMEDIA_TYPE_DATA;
    } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {
        test_for_ext_stream_audio = 1;
399
        type                      = AVMEDIA_TYPE_UNKNOWN;
400 401 402 403
    } else {
        return -1;
    }
    ff_get_guid(pb, &g);
Mans Rullgard's avatar
Mans Rullgard committed
404
    avio_skip(pb, 8); /* total_size */
405 406 407
    type_specific_size = avio_rl32(pb);
    avio_rl32(pb);
    st->id = avio_rl16(pb) & 0x7f; /* stream id */
408 409 410
    // mapping of asf ID to AV stream ID;
    asf->asfid2avid[st->id] = s->nb_streams - 1;

411
    avio_rl32(pb);
412 413 414 415

    if (test_for_ext_stream_audio) {
        ff_get_guid(pb, &g);
        if (!ff_guidcmp(&g, &ff_asf_ext_stream_audio_stream)) {
416 417
            type            = AVMEDIA_TYPE_AUDIO;
            is_dvr_ms_audio = 1;
418
            ff_get_guid(pb, &g);
419 420 421
            avio_rl32(pb);
            avio_rl32(pb);
            avio_rl32(pb);
422
            ff_get_guid(pb, &g);
423
            avio_rl32(pb);
424 425 426 427 428
        }
    }

    st->codec->codec_type = type;
    if (type == AVMEDIA_TYPE_AUDIO) {
429 430 431
        int ret = ff_get_wav_header(pb, st->codec, type_specific_size);
        if (ret < 0)
            return ret;
432 433 434
        if (is_dvr_ms_audio) {
            // codec_id and codec_tag are unreliable in dvr_ms
            // files. Set them later by probing stream.
435
            st->codec->codec_id  = AV_CODEC_ID_PROBE;
436 437
            st->codec->codec_tag = 0;
        }
438
        if (st->codec->codec_id == AV_CODEC_ID_AAC)
439
            st->need_parsing = AVSTREAM_PARSE_NONE;
440
        else
441 442
            st->need_parsing = AVSTREAM_PARSE_FULL;
        /* We have to init the frame size at some point .... */
443
        pos2 = avio_tell(pb);
444
        if (size >= (pos2 + 8 - pos1 + 24)) {
445
            asf_st->ds_span        = avio_r8(pb);
446
            asf_st->ds_packet_size = avio_rl16(pb);
447 448 449
            asf_st->ds_chunk_size  = avio_rl16(pb);
            avio_rl16(pb);  // ds_data_size
            avio_r8(pb);    // ds_silence_data
450 451
        }
        if (asf_st->ds_span > 1) {
452 453 454 455
            if (!asf_st->ds_chunk_size                                ||
                (asf_st->ds_packet_size / asf_st->ds_chunk_size <= 1) ||
                asf_st->ds_packet_size % asf_st->ds_chunk_size)
                asf_st->ds_span = 0;  // disable descrambling
456 457
        }
    } else if (type == AVMEDIA_TYPE_VIDEO &&
458
               size - (avio_tell(pb) - pos1 + 24) >= 51) {
459 460 461 462
        avio_rl32(pb);
        avio_rl32(pb);
        avio_r8(pb);
        avio_rl16(pb);        /* size */
463 464
        sizeX             = avio_rl32(pb); /* size */
        st->codec->width  = avio_rl32(pb);
465
        st->codec->height = avio_rl32(pb);
466
        /* not available for asf */
467 468
        avio_rl16(pb); /* panes */
        st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */
469
        tag1                             = avio_rl32(pb);
470
        avio_skip(pb, 20);
471 472
        if (sizeX > 40) {
            st->codec->extradata_size = sizeX - 40;
473 474
            st->codec->extradata      = av_mallocz(st->codec->extradata_size +
                                                   FF_INPUT_BUFFER_PADDING_SIZE);
475
            avio_read(pb, st->codec->extradata, st->codec->extradata_size);
476 477 478 479
        }

        /* Extract palette from extradata if bpp <= 8 */
        /* This code assumes that extradata contains only palette */
480
        /* This is true for all paletted codecs implemented in libavcodec */
481 482
        if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
#if HAVE_BIGENDIAN
483
            int i;
484 485
            for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE) / 4; i++)
                asf_st->palette[i] = av_bswap32(((uint32_t *)st->codec->extradata)[i]);
486
#else
487 488
            memcpy(asf_st->palette, st->codec->extradata,
                   FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
489
#endif
490
            asf_st->palette_changed = 1;
491 492 493
        }

        st->codec->codec_tag = tag1;
494 495
        st->codec->codec_id  = ff_codec_get_id(ff_codec_bmp_tags, tag1);
        if (tag1 == MKTAG('D', 'V', 'R', ' ')) {
496
            st->need_parsing = AVSTREAM_PARSE_FULL;
497 498 499 500
            /* issue658 contains wrong w/h and MS even puts a fake seq header
             * with wrong w/h in extradata while a correct one is in the stream.
             * maximum lameness */
            st->codec->width      =
501 502
                st->codec->height = 0;
            av_freep(&st->codec->extradata);
503
            st->codec->extradata_size = 0;
504
        }
505
        if (st->codec->codec_id == AV_CODEC_ID_H264)
506 507
            st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
    }
508
    pos2 = avio_tell(pb);
509
    avio_skip(pb, size - (pos2 - pos1 + 24));
510 511 512 513

    return 0;
}

514 515 516
static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size)
{
    ASFContext *asf = s->priv_data;
517
    AVIOContext *pb = s->pb;
518 519
    ff_asf_guid g;
    int ext_len, payload_ext_ct, stream_ct, i;
Mans Rullgard's avatar
Mans Rullgard committed
520
    uint32_t leak_rate, stream_num;
521 522
    unsigned int stream_languageid_index;

523 524 525 526 527 528 529 530 531 532 533 534 535
    avio_rl64(pb); // starttime
    avio_rl64(pb); // endtime
    leak_rate = avio_rl32(pb); // leak-datarate
    avio_rl32(pb); // bucket-datasize
    avio_rl32(pb); // init-bucket-fullness
    avio_rl32(pb); // alt-leak-datarate
    avio_rl32(pb); // alt-bucket-datasize
    avio_rl32(pb); // alt-init-bucket-fullness
    avio_rl32(pb); // max-object-size
    avio_rl32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
    stream_num = avio_rl16(pb); // stream-num

    stream_languageid_index = avio_rl16(pb); // stream-language-id-index
536 537 538
    if (stream_num < 128)
        asf->streams[stream_num].stream_language_index = stream_languageid_index;

539
    avio_rl64(pb); // avg frametime in 100ns units
540 541
    stream_ct      = avio_rl16(pb); // stream-name-count
    payload_ext_ct = avio_rl16(pb); // payload-extension-system-count
542 543 544 545

    if (stream_num < 128)
        asf->stream_bitrates[stream_num] = leak_rate;

546
    for (i = 0; i < stream_ct; i++) {
547 548
        avio_rl16(pb);
        ext_len = avio_rl16(pb);
549
        avio_skip(pb, ext_len);
550 551
    }

552
    for (i = 0; i < payload_ext_ct; i++) {
553
        ff_get_guid(pb, &g);
Mans Rullgard's avatar
Mans Rullgard committed
554
        avio_skip(pb, 2);
555
        ext_len = avio_rl32(pb);
556
        avio_skip(pb, ext_len);
557 558 559 560 561 562 563
    }

    return 0;
}

static int asf_read_content_desc(AVFormatContext *s, int64_t size)
{
564
    AVIOContext *pb = s->pb;
565 566
    int len1, len2, len3, len4, len5;

567 568 569 570 571
    len1 = avio_rl16(pb);
    len2 = avio_rl16(pb);
    len3 = avio_rl16(pb);
    len4 = avio_rl16(pb);
    len5 = avio_rl16(pb);
572 573 574 575
    get_tag(s, "title", 0, len1, 32);
    get_tag(s, "author", 0, len2, 32);
    get_tag(s, "copyright", 0, len3, 32);
    get_tag(s, "comment", 0, len4, 32);
576
    avio_skip(pb, len5);
577 578 579 580 581 582

    return 0;
}

static int asf_read_ext_content_desc(AVFormatContext *s, int64_t size)
{
583
    AVIOContext *pb = s->pb;
584 585 586
    ASFContext *asf = s->priv_data;
    int desc_count, i, ret;

587
    desc_count = avio_rl16(pb);
588 589
    for (i = 0; i < desc_count; i++) {
        int name_len, value_type, value_len;
590 591
        char name[1024];

592
        name_len = avio_rl16(pb);
593
        if (name_len % 2)   // must be even, broken lavf versions wrote len-1
594 595
            name_len += 1;
        if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
596
            avio_skip(pb, name_len - ret);
597 598
        value_type = avio_rl16(pb);
        value_len  = avio_rl16(pb);
599
        if (!value_type && value_len % 2)
600
            value_len += 1;
601 602 603 604
        /* My sample has that stream set to 0 maybe that mean the container.
         * ASF stream count starts at 1. I am using 0 to the container value
         * since it's unused. */
        if (!strcmp(name, "AspectRatioX"))
605
            asf->dar[0].num = get_value(s->pb, value_type, 32);
606
        else if (!strcmp(name, "AspectRatioY"))
607
            asf->dar[0].den = get_value(s->pb, value_type, 32);
608
        else
609
            get_tag(s, name, value_type, value_len, 32);
610 611 612 613 614 615 616
    }

    return 0;
}

static int asf_read_language_list(AVFormatContext *s, int64_t size)
{
617
    AVIOContext *pb = s->pb;
618 619
    ASFContext *asf = s->priv_data;
    int j, ret;
620
    int stream_count = avio_rl16(pb);
621
    for (j = 0; j < stream_count; j++) {
622
        char lang[6];
623
        unsigned int lang_len = avio_r8(pb);
624 625
        if ((ret = avio_get_str16le(pb, lang_len, lang,
                                    sizeof(lang))) < lang_len)
626
            avio_skip(pb, lang_len - ret);
627
        if (j < 128)
628 629
            av_strlcpy(asf->stream_languages[j], lang,
                       sizeof(*asf->stream_languages));
630 631 632 633 634 635 636
    }

    return 0;
}

static int asf_read_metadata(AVFormatContext *s, int64_t size)
{
637
    AVIOContext *pb = s->pb;
638
    ASFContext *asf = s->priv_data;
639
    int n, stream_num, name_len, value_len;
640
    int ret, i;
641
    n = avio_rl16(pb);
642

643
    for (i = 0; i < n; i++) {
644
        char name[1024];
645
        int value_type;
646

647 648 649
        avio_rl16(pb);  // lang_list_index
        stream_num = avio_rl16(pb);
        name_len   = avio_rl16(pb);
650
        value_type = avio_rl16(pb); /* value_type */
651
        value_len  = avio_rl32(pb);
652 653

        if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
654
            avio_skip(pb, name_len - ret);
655
        av_dlog(s, "%d stream %d name_len %2d type %d len %4d <%s>\n",
656
                i, stream_num, name_len, value_type, value_len, name);
657 658 659 660 661 662 663 664 665 666 667

        if (!strcmp(name, "AspectRatioX")){
            int aspect_x = get_value(s->pb, value_type, 16);
            if(stream_num < 128)
                asf->dar[stream_num].num = aspect_x;
        } else if(!strcmp(name, "AspectRatioY")){
            int aspect_y = get_value(s->pb, value_type, 16);
            if(stream_num < 128)
                asf->dar[stream_num].den = aspect_y;
        } else {
            get_tag(s, name, value_type, value_len, 16);
668 669 670 671 672 673 674 675
        }
    }

    return 0;
}

static int asf_read_marker(AVFormatContext *s, int64_t size)
{
676
    AVIOContext *pb = s->pb;
677
    ASFContext *asf = s->priv_data;
678 679 680
    int i, count, name_len, ret;
    char name[1024];

681 682 683 684 685
    avio_rl64(pb);            // reserved 16 bytes
    avio_rl64(pb);            // ...
    count = avio_rl32(pb);    // markers count
    avio_rl16(pb);            // reserved 2 bytes
    name_len = avio_rl16(pb); // name length
686
    for (i = 0; i < name_len; i++)
687
        avio_r8(pb); // skip the name
688

689
    for (i = 0; i < count; i++) {
690 691 692
        int64_t pres_time;
        int name_len;

693 694
        avio_rl64(pb);             // offset, 8 bytes
        pres_time = avio_rl64(pb); // presentation time
695
        pres_time -= asf->hdr.preroll * 10000;
696 697 698 699
        avio_rl16(pb);             // entry length
        avio_rl32(pb);             // send time
        avio_rl32(pb);             // flags
        name_len = avio_rl32(pb);  // name length
700 701
        if ((ret = avio_get_str16le(pb, name_len * 2, name,
                                    sizeof(name))) < name_len)
702
            avio_skip(pb, name_len - ret);
703 704
        avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pres_time,
                           AV_NOPTS_VALUE, name);
705 706 707 708 709
    }

    return 0;
}

710
static int asf_read_header(AVFormatContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
711
{
Fabrice Bellard's avatar
Fabrice Bellard committed
712
    ASFContext *asf = s->priv_data;
713
    ff_asf_guid g;
714
    AVIOContext *pb = s->pb;
715
    int i;
716
    int64_t gsize;
Fabrice Bellard's avatar
Fabrice Bellard committed
717

718 719
    ff_get_guid(pb, &g);
    if (ff_guidcmp(&g, &ff_asf_header))
720
        return -1;
721 722 723 724
    avio_rl64(pb);
    avio_rl32(pb);
    avio_r8(pb);
    avio_r8(pb);
725
    memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
726 727
    for (;;) {
        uint64_t gpos = avio_tell(pb);
728
        ff_get_guid(pb, &g);
729
        gsize = avio_rl64(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
730
        print_guid(&g);
731
        if (!ff_guidcmp(&g, &ff_asf_data_header)) {
732
            asf->data_object_offset = avio_tell(pb);
733 734 735
            /* If not streaming, gsize is not unlimited (how?),
             * and there is enough space in the file.. */
            if (!(asf->hdr.flags & 0x01) && gsize >= 100)
736
                asf->data_object_size = gsize - 24;
737
            else
738 739 740
                asf->data_object_size = (uint64_t)-1;
            break;
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
741
        if (gsize < 24)
742
            return -1;
743
        if (!ff_guidcmp(&g, &ff_asf_file_header)) {
744 745 746
            int ret = asf_read_file_properties(s, gsize);
            if (ret < 0)
                return ret;
747
        } else if (!ff_guidcmp(&g, &ff_asf_stream_header)) {
748 749 750
            int ret = asf_read_stream_properties(s, gsize);
            if (ret < 0)
                return ret;
751
        } else if (!ff_guidcmp(&g, &ff_asf_comment_header)) {
752
            asf_read_content_desc(s, gsize);
753
        } else if (!ff_guidcmp(&g, &ff_asf_language_guid)) {
754
            asf_read_language_list(s, gsize);
755
        } else if (!ff_guidcmp(&g, &ff_asf_extended_content_header)) {
756
            asf_read_ext_content_desc(s, gsize);
757
        } else if (!ff_guidcmp(&g, &ff_asf_metadata_header)) {
758
            asf_read_metadata(s, gsize);
759 760
        } else if (!ff_guidcmp(&g, &ff_asf_metadata_library_header)) {
            asf_read_metadata(s, gsize);
761
        } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_header)) {
762
            asf_read_ext_stream_properties(s, gsize);
763 764 765

            // there could be a optional stream properties object to follow
            // if so the next iteration will pick it up
766
            continue;
767 768
        } else if (!ff_guidcmp(&g, &ff_asf_head1_guid)) {
            ff_get_guid(pb, &g);
Mans Rullgard's avatar
Mans Rullgard committed
769
            avio_skip(pb, 6);
770
            continue;
771
        } else if (!ff_guidcmp(&g, &ff_asf_marker_header)) {
772
            asf_read_marker(s, gsize);
Anton Khirnov's avatar
Anton Khirnov committed
773
        } else if (pb->eof_reached) {
774
            return -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
775
        } else {
776
            if (!s->keylen) {
777
                if (!ff_guidcmp(&g, &ff_asf_content_encryption)) {
778 779
                    av_log(s, AV_LOG_WARNING,
                           "DRM protected stream detected, decoding will likely fail!\n");
780
                } else if (!ff_guidcmp(&g, &ff_asf_ext_content_encryption)) {
781 782
                    av_log(s, AV_LOG_WARNING,
                           "Ext DRM protected stream detected, decoding will likely fail!\n");
783
                } else if (!ff_guidcmp(&g, &ff_asf_digital_signature)) {
784 785
                    av_log(s, AV_LOG_WARNING,
                           "Digital signature detected, decoding will likely fail!\n");
786 787
                }
            }
Fabrice Bellard's avatar
Fabrice Bellard committed
788
        }
789 790 791 792
        if (avio_tell(pb) != gpos + gsize)
            av_log(s, AV_LOG_DEBUG,
                   "gpos mismatch our pos=%"PRIu64", end=%"PRId64"\n",
                   avio_tell(pb) - gpos, gsize);
793
        avio_seek(pb, gpos + gsize, SEEK_SET);
Fabrice Bellard's avatar
Fabrice Bellard committed
794
    }
795
    ff_get_guid(pb, &g);
796 797 798
    avio_rl64(pb);
    avio_r8(pb);
    avio_r8(pb);
Anton Khirnov's avatar
Anton Khirnov committed
799
    if (pb->eof_reached)
800
        return -1;
801
    asf->data_offset      = avio_tell(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
802 803
    asf->packet_size_left = 0;

804 805 806
    for (i = 0; i < 128; i++) {
        int stream_num = asf->asfid2avid[i];
        if (stream_num >= 0) {
807 808
            AVStream *st = s->streams[stream_num];
            if (!st->codec->bit_rate)
809
                st->codec->bit_rate = asf->stream_bitrates[i];
810
            if (asf->dar[i].num > 0 && asf->dar[i].den > 0) {
811 812
                av_reduce(&st->sample_aspect_ratio.num,
                          &st->sample_aspect_ratio.den,
813
                          asf->dar[i].num, asf->dar[i].den, INT_MAX);
814 815 816
            } else if ((asf->dar[0].num > 0) && (asf->dar[0].den > 0) &&
                       // Use ASF container value if the stream doesn't set AR.
                       (st->codec->codec_type == AVMEDIA_TYPE_VIDEO))
817 818
                av_reduce(&st->sample_aspect_ratio.num,
                          &st->sample_aspect_ratio.den,
819
                          asf->dar[0].num, asf->dar[0].den, INT_MAX);
820

821 822 823
            av_dlog(s, "i=%d, st->codec->codec_type:%d, asf->dar %d:%d sar=%d:%d\n",
                    i, st->codec->codec_type, asf->dar[i].num, asf->dar[i].den,
                    st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
824 825 826 827 828 829

            // copy and convert language codes to the frontend
            if (asf->streams[i].stream_language_index < 128) {
                const char *rfc1766 = asf->stream_languages[asf->streams[i].stream_language_index];
                if (rfc1766 && strlen(rfc1766) > 1) {
                    const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any
830 831
                    const char *iso6392       = av_convert_lang_to(primary_tag,
                                                                   AV_LANG_ISO639_2_BIBL);
832
                    if (iso6392)
833
                        av_dict_set(&st->metadata, "language", iso6392, 0);
834 835
                }
            }
836 837 838
        }
    }

839
    ff_metadata_conv(&s->metadata, NULL, ff_asf_metadata_conv);
840

Fabrice Bellard's avatar
Fabrice Bellard committed
841 842 843
    return 0;
}

844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
#define DO_2BITS(bits, var, defval)             \
    switch (bits & 3) {                         \
    case 3:                                     \
        var = avio_rl32(pb);                    \
        rsize += 4;                             \
        break;                                  \
    case 2:                                     \
        var = avio_rl16(pb);                    \
        rsize += 2;                             \
        break;                                  \
    case 1:                                     \
        var = avio_r8(pb);                      \
        rsize++;                                \
        break;                                  \
    default:                                    \
        var = defval;                           \
        break;                                  \
861 862
    }

863 864 865 866
/**
 * Load a single ASF packet into the demuxer.
 * @param s demux context
 * @param pb context to read data from
867
 * @return 0 on success, <0 on error
868
 */
869
static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
Fabrice Bellard's avatar
Fabrice Bellard committed
870 871
{
    ASFContext *asf = s->priv_data;
872
    uint32_t packet_length, padsize;
873
    int rsize = 8;
874 875
    int c, d, e, off;

876
    // if we do not know packet size, allow skipping up to 32 kB
877
    off = 32768;
878 879 880
    if (asf->no_resync_search)
        off = 3;
    else if (s->packet_size > 0)
881 882 883 884 885 886 887 888
        off = (avio_tell(pb) - s->data_offset) % s->packet_size + 3;

    c = d = e = -1;
    while (off-- > 0) {
        c = d;
        d = e;
        e = avio_r8(pb);
        if (c == 0x82 && !d && !e)
889 890
            break;
    }
891

892
    if (c != 0x82) {
893
        /* This code allows handling of -EAGAIN at packet boundaries (i.e.
894 895
         * if the packet sync code above triggers -EAGAIN). This does not
         * imply complete -EAGAIN handling support at random positions in
896
         * the stream. */
897
        if (pb->error == AVERROR(EAGAIN))
898
            return AVERROR(EAGAIN);
Anton Khirnov's avatar
Anton Khirnov committed
899
        if (!pb->eof_reached)
900 901
            av_log(s, AV_LOG_ERROR,
                   "ff asf bad header %x  at:%"PRId64"\n", c, avio_tell(pb));
902
    }
903
    if ((c & 0x8f) == 0x82) {
904
        if (d || e) {
Anton Khirnov's avatar
Anton Khirnov committed
905
            if (!pb->eof_reached)
906
                av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n");
907
            return -1;
908
        }
909 910 911
        c      = avio_r8(pb);
        d      = avio_r8(pb);
        rsize += 3;
912
    } else if (!pb->eof_reached) {
913
        avio_seek(pb, -1, SEEK_CUR); // FIXME
Fabrice Bellard's avatar
Fabrice Bellard committed
914
    }
915

916 917
    asf->packet_flags    = c;
    asf->packet_property = d;
918

919
    DO_2BITS(asf->packet_flags >> 5, packet_length, s->packet_size);
920 921 922
    DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored
    DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length

923 924 925
    // the following checks prevent overflows and infinite loops
    if (!packet_length || packet_length >= (1U << 29)) {
        av_log(s, AV_LOG_ERROR,
926
               "invalid packet_length %"PRIu32" at:%"PRId64"\n",
927
               packet_length, avio_tell(pb));
928
        return -1;
929
    }
930 931
    if (padsize >= packet_length) {
        av_log(s, AV_LOG_ERROR,
932
               "invalid padsize %"PRIu32" at:%"PRId64"\n", padsize, avio_tell(pb));
933
        return -1;
934 935
    }

936 937
    asf->packet_timestamp = avio_rl32(pb);
    avio_rl16(pb); /* duration */
938
    // rsize has at least 11 bytes which have to be present
939 940

    if (asf->packet_flags & 0x01) {
941 942
        asf->packet_segsizetype = avio_r8(pb);
        rsize++;
943 944
        asf->packet_segments = asf->packet_segsizetype & 0x3f;
    } else {
945
        asf->packet_segments    = 1;
946 947
        asf->packet_segsizetype = 0x80;
    }
948 949 950
    if (rsize > packet_length - padsize) {
        asf->packet_size_left = 0;
        av_log(s, AV_LOG_ERROR,
951
               "invalid packet header length %d for pktlen %"PRIu32"-%"PRIu32" at %"PRId64"\n",
952 953 954
               rsize, packet_length, padsize, avio_tell(pb));
        return -1;
    }
955
    asf->packet_size_left = packet_length - padsize - rsize;
956 957
    if (packet_length < asf->hdr.min_pktsize)
        padsize += asf->hdr.min_pktsize - packet_length;
958
    asf->packet_padsize = padsize;
959 960
    av_dlog(s, "packet: size=%d padsize=%d  left=%d\n",
            s->packet_size, asf->packet_padsize, asf->packet_size_left);
Fabrice Bellard's avatar
Fabrice Bellard committed
961 962 963
    return 0;
}

964 965 966 967
/**
 *
 * @return <0 if error
 */
968 969
static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb)
{
970
    ASFContext *asf = s->priv_data;
971 972
    int rsize       = 1;
    int num         = avio_r8(pb);
Mans Rullgard's avatar
Mans Rullgard committed
973
    int64_t ts0;
974 975 976

    asf->packet_segments--;
    asf->packet_key_frame = num >> 7;
977
    asf->stream_index     = asf->asfid2avid[num & 0x7f];
978 979 980 981
    // sequence should be ignored!
    DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
    DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
    DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
982 983 984
    av_dlog(asf, "key:%d stream:%d seq:%d offset:%d replic_size:%d\n",
            asf->packet_key_frame, asf->stream_index, asf->packet_seq,
            asf->packet_frag_offset, asf->packet_replic_size);
985
    if (asf->packet_replic_size >= 8) {
986
        asf->packet_obj_size = avio_rl32(pb);
987
        if (asf->packet_obj_size >= (1 << 24) || asf->packet_obj_size <= 0) {
988 989 990
            av_log(s, AV_LOG_ERROR, "packet_obj_size invalid\n");
            return -1;
        }
991
        asf->packet_frag_timestamp = avio_rl32(pb); // timestamp
992
        if (asf->packet_replic_size >= 8 + 38 + 4) {
993
            avio_skip(pb, 10);
994 995
            ts0 = avio_rl64(pb);
            avio_skip(pb, 8);
996
            avio_skip(pb, 12);
997
            avio_rl32(pb);
998
            avio_skip(pb, asf->packet_replic_size - 8 - 38 - 4);
999 1000 1001 1002 1003
            if (ts0 != -1)
                asf->packet_frag_timestamp = ts0 / 10000;
            else
                asf->packet_frag_timestamp = AV_NOPTS_VALUE;
        } else
1004
            avio_skip(pb, asf->packet_replic_size - 8);
1005
        rsize += asf->packet_replic_size; // FIXME - check validity
1006
    } else if (asf->packet_replic_size == 1) {
1007
        // multipacket - frag_offset is beginning timestamp
1008 1009
        asf->packet_time_start     = asf->packet_frag_offset;
        asf->packet_frag_offset    = 0;
1010 1011
        asf->packet_frag_timestamp = asf->packet_timestamp;

1012
        asf->packet_time_delta = avio_r8(pb);
1013
        rsize++;
1014 1015 1016
    } else if (asf->packet_replic_size != 0) {
        av_log(s, AV_LOG_ERROR, "unexpected packet_replic_size of %d\n",
               asf->packet_replic_size);
1017 1018 1019 1020
        return -1;
    }
    if (asf->packet_flags & 0x01) {
        DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
1021 1022 1023
        if (rsize > asf->packet_size_left) {
            av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n");
            return -1;
1024
        } else if (asf->packet_frag_size > asf->packet_size_left - rsize) {
1025
            if (asf->packet_frag_size > asf->packet_size_left - rsize + asf->packet_padsize) {
1026 1027
                av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid (%d-%d)\n",
                       asf->packet_size_left, rsize);
1028 1029 1030 1031 1032 1033
                return -1;
            } else {
                int diff = asf->packet_frag_size - (asf->packet_size_left - rsize);
                asf->packet_size_left += diff;
                asf->packet_padsize   -= diff;
            }
1034
        }
1035
    } else {
1036 1037 1038 1039
        if (rsize > asf->packet_size_left) {
            av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n");
            return -1;
        }
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
        asf->packet_frag_size = asf->packet_size_left - rsize;
    }
    if (asf->packet_replic_size == 1) {
        asf->packet_multi_size = asf->packet_frag_size;
        if (asf->packet_multi_size > asf->packet_size_left)
            return -1;
    }
    asf->packet_size_left -= rsize;

    return 0;
}

1052 1053 1054 1055 1056 1057
/**
 * Parse data from individual ASF packets (which were previously loaded
 * with asf_get_packet()).
 * @param s demux context
 * @param pb context to read data from
 * @param pkt pointer to store packet data into
1058
 * @return 0 if data was stored in pkt, <0 on error or 1 if more ASF
1059 1060
 *          packets need to be loaded (through asf_get_packet())
 */
1061
static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
Fabrice Bellard's avatar
Fabrice Bellard committed
1062
{
1063
    ASFContext *asf   = s->priv_data;
1064 1065
    ASFStream *asf_st = 0;
    for (;;) {
1066
        int ret;
1067 1068

        if (pb->eof_reached)
1069
            return AVERROR_EOF;
1070 1071 1072

        if (asf->packet_size_left < FRAME_HEADER_SIZE ||
            asf->packet_segments < 1) {
1073
            int ret = asf->packet_size_left + asf->packet_padsize;
1074 1075

            assert(ret >= 0);
1076
            /* fail safe */
1077
            avio_skip(pb, ret);
1078

1079
            asf->packet_pos = avio_tell(pb);
1080 1081
            if (asf->data_object_size != (uint64_t)-1 &&
                (asf->packet_pos - asf->data_object_offset >= asf->data_object_size))
1082
                return AVERROR_EOF;  /* Do not exceed the size of the data object */
1083
            return 1;
1084 1085
        }
        if (asf->packet_time_start == 0) {
1086 1087
            if (asf_read_frame_header(s, pb) < 0) {
                asf->packet_segments = 0;
1088
                continue;
1089
            }
1090 1091 1092 1093
            if (asf->stream_index < 0 ||
                s->streams[asf->stream_index]->discard >= AVDISCARD_ALL ||
                (!asf->packet_key_frame &&
                 s->streams[asf->stream_index]->discard >= AVDISCARD_NONKEY)) {
1094
                asf->packet_time_start = 0;
1095
                /* unhandled packet (should not happen) */
1096
                avio_skip(pb, asf->packet_frag_size);
1097
                asf->packet_size_left -= asf->packet_frag_size;
1098
                if (asf->stream_index < 0)
1099 1100
                    av_log(s, AV_LOG_ERROR, "ff asf skip %d (unknown stream)\n",
                           asf->packet_frag_size);
1101
                continue;
1102 1103 1104 1105
            }
            asf->asf_st = s->streams[asf->stream_index]->priv_data;
        }
        asf_st = asf->asf_st;
1106
        av_assert0(asf_st);
1107

1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
        if (!asf_st->frag_offset && asf->packet_frag_offset) {
            av_dlog(s, "skipping asf data pkt with fragment offset for "
                    "stream:%d, expected:%d but got %d from pkt)\n",
                    asf->stream_index, asf_st->frag_offset,
                    asf->packet_frag_offset);
            avio_skip(pb, asf->packet_frag_size);
            asf->packet_size_left -= asf->packet_frag_size;
            continue;
        }

1118
        if (asf->packet_replic_size == 1) {
1119
            // frag_offset is here used as the beginning timestamp
1120
            asf->packet_frag_timestamp = asf->packet_time_start;
1121 1122
            asf->packet_time_start    += asf->packet_time_delta;
            asf->packet_obj_size       = asf->packet_frag_size = avio_r8(pb);
1123
            asf->packet_size_left--;
1124
            asf->packet_multi_size--;
1125
            if (asf->packet_multi_size < asf->packet_obj_size) {
1126
                asf->packet_time_start = 0;
1127
                avio_skip(pb, asf->packet_multi_size);
1128
                asf->packet_size_left -= asf->packet_multi_size;
1129
                continue;
1130 1131 1132
            }
            asf->packet_multi_size -= asf->packet_obj_size;
        }
1133 1134
        if (asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size &&
            asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size) {
1135
            av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n",
1136 1137 1138
                   asf_st->frag_offset, asf->packet_frag_size,
                   asf->packet_obj_size, asf_st->pkt.size);
            asf->packet_obj_size = asf_st->pkt.size;
1139 1140
        }

1141
        if (asf_st->pkt.size != asf->packet_obj_size ||
1142
            // FIXME is this condition sufficient?
1143 1144
            asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) {
            if (asf_st->pkt.data) {
1145 1146 1147
                av_log(s, AV_LOG_INFO,
                       "freeing incomplete packet size %d, new %d\n",
                       asf_st->pkt.size, asf->packet_obj_size);
1148 1149 1150
                asf_st->frag_offset = 0;
                av_free_packet(&asf_st->pkt);
            }
1151 1152
            /* new packet */
            av_new_packet(&asf_st->pkt, asf->packet_obj_size);
1153 1154
            asf_st->seq              = asf->packet_seq;
            asf_st->pkt.dts          = asf->packet_frag_timestamp - asf->hdr.preroll;
1155
            asf_st->pkt.stream_index = asf->stream_index;
1156 1157
            asf_st->pkt.pos          = asf_st->packet_pos = asf->packet_pos;

1158 1159
            if (asf_st->pkt.data && asf_st->palette_changed) {
                uint8_t *pal;
1160
                pal = av_packet_new_side_data(&asf_st->pkt, AV_PKT_DATA_PALETTE,
1161 1162 1163 1164 1165 1166 1167 1168
                                              AVPALETTE_SIZE);
                if (!pal) {
                    av_log(s, AV_LOG_ERROR, "Cannot append palette to packet\n");
                } else {
                    memcpy(pal, asf_st->palette, AVPALETTE_SIZE);
                    asf_st->palette_changed = 0;
                }
            }
1169 1170 1171 1172 1173
            av_dlog(asf, "new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
                    asf->stream_index, asf->packet_key_frame,
                    asf_st->pkt.flags & AV_PKT_FLAG_KEY,
                    s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO,
                    asf->packet_obj_size);
1174
            if (s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
1175 1176
                asf->packet_key_frame = 1;
            if (asf->packet_key_frame)
1177
                asf_st->pkt.flags |= AV_PKT_FLAG_KEY;
1178 1179 1180
        }

        /* read data */
1181 1182 1183
        av_dlog(asf, "READ PACKET s:%d  os:%d  o:%d,%d  l:%d   DATA:%p\n",
                s->packet_size, asf_st->pkt.size, asf->packet_frag_offset,
                asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data);
1184 1185
        asf->packet_size_left -= asf->packet_frag_size;
        if (asf->packet_size_left < 0)
1186
            continue;
1187

1188 1189
        if (asf->packet_frag_offset >= asf_st->pkt.size ||
            asf->packet_frag_size > asf_st->pkt.size - asf->packet_frag_offset) {
1190 1191 1192 1193
            av_log(s, AV_LOG_ERROR,
                   "packet fragment position invalid %u,%u not in %u\n",
                   asf->packet_frag_offset, asf->packet_frag_size,
                   asf_st->pkt.size);
1194 1195 1196
            continue;
        }

1197
        ret = avio_read(pb, asf_st->pkt.data + asf->packet_frag_offset,
1198
                        asf->packet_frag_size);
1199 1200 1201
        if (ret != asf->packet_frag_size) {
            if (ret < 0 || asf->packet_frag_offset + ret == 0)
                return ret < 0 ? ret : AVERROR_EOF;
1202

1203 1204 1205 1206 1207 1208 1209
            if (asf_st->ds_span > 1) {
                // scrambling, we can either drop it completely or fill the remainder
                // TODO: should we fill the whole packet instead of just the current
                // fragment?
                memset(asf_st->pkt.data + asf->packet_frag_offset + ret, 0,
                       asf->packet_frag_size - ret);
                ret = asf->packet_frag_size;
1210
            } else {
1211 1212
                // no scrambling, so we can return partial packets
                av_shrink_packet(&asf_st->pkt, asf->packet_frag_offset + ret);
1213
            }
1214
        }
1215 1216
        if (s->key && s->keylen == 20)
            ff_asfcrypt_dec(s->key, asf_st->pkt.data + asf->packet_frag_offset,
1217 1218
                            ret);
        asf_st->frag_offset += ret;
1219 1220
        /* test if whole packet is read */
        if (asf_st->frag_offset == asf_st->pkt.size) {
1221
            // workaround for macroshit radio DVR-MS files
1222 1223
            if (s->streams[asf->stream_index]->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
                asf_st->pkt.size > 100) {
1224
                int i;
1225 1226
                for (i = 0; i < asf_st->pkt.size && !asf_st->pkt.data[i]; i++)
                    ;
1227
                if (i == asf_st->pkt.size) {
1228 1229 1230 1231 1232 1233 1234
                    av_log(s, AV_LOG_DEBUG, "discarding ms fart\n");
                    asf_st->frag_offset = 0;
                    av_free_packet(&asf_st->pkt);
                    continue;
                }
            }

1235 1236
            /* return packet */
            if (asf_st->ds_span > 1) {
1237 1238 1239 1240 1241
                if (asf_st->pkt.size != asf_st->ds_packet_size * asf_st->ds_span) {
                    av_log(s, AV_LOG_ERROR,
                           "pkt.size != ds_packet_size * ds_span (%d %d %d)\n",
                           asf_st->pkt.size, asf_st->ds_packet_size,
                           asf_st->ds_span);
1242 1243
                } else {
                    /* packet descrambling */
1244 1245 1246 1247
                    AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size +
                                                       FF_INPUT_BUFFER_PADDING_SIZE);
                    if (buf) {
                        uint8_t *newdata = buf->data;
1248
                        int offset = 0;
1249 1250
                        memset(newdata + asf_st->pkt.size, 0,
                               FF_INPUT_BUFFER_PADDING_SIZE);
1251 1252 1253 1254 1255 1256
                        while (offset < asf_st->pkt.size) {
                            int off = offset / asf_st->ds_chunk_size;
                            int row = off / asf_st->ds_span;
                            int col = off % asf_st->ds_span;
                            int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size;
                            assert(offset + asf_st->ds_chunk_size <= asf_st->pkt.size);
1257
                            assert(idx + 1 <= asf_st->pkt.size / asf_st->ds_chunk_size);
1258 1259 1260 1261 1262
                            memcpy(newdata + offset,
                                   asf_st->pkt.data + idx * asf_st->ds_chunk_size,
                                   asf_st->ds_chunk_size);
                            offset += asf_st->ds_chunk_size;
                        }
1263 1264 1265
                        av_buffer_unref(&asf_st->pkt.buf);
                        asf_st->pkt.buf  = buf;
                        asf_st->pkt.data = buf->data;
1266 1267 1268
                    }
                }
            }
1269 1270
            asf_st->frag_offset         = 0;
            *pkt                        = asf_st->pkt;
1271
#if FF_API_DESTRUCT_PACKET
1272
FF_DISABLE_DEPRECATION_WARNINGS
1273
            asf_st->pkt.destruct        = NULL;
1274
FF_ENABLE_DEPRECATION_WARNINGS
1275 1276
#endif
            asf_st->pkt.buf             = 0;
1277 1278
            asf_st->pkt.size            = 0;
            asf_st->pkt.data            = 0;
1279
            asf_st->pkt.side_data_elems = 0;
1280
            asf_st->pkt.side_data       = NULL;
1281 1282
            break; // packet completed
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
1283 1284 1285 1286
    }
    return 0;
}

1287 1288 1289 1290 1291 1292 1293 1294
static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    ASFContext *asf = s->priv_data;

    for (;;) {
        int ret;

        /* parse cached packets, if any */
1295
        if ((ret = asf_parse_packet(s, s->pb, pkt)) <= 0)
1296
            return ret;
1297
        if ((ret = asf_get_packet(s, s->pb)) < 0)
1298 1299
            assert(asf->packet_size_left < FRAME_HEADER_SIZE ||
                   asf->packet_segments < 1);
1300 1301 1302 1303
        asf->packet_time_start = 0;
    }
}

1304 1305 1306 1307 1308 1309
// Added to support seeking after packets have been read
// If information is not reset, read_packet fails due to
// leftover information from previous reads
static void asf_reset_header(AVFormatContext *s)
{
    ASFContext *asf = s->priv_data;
Michael Niedermayer's avatar
Michael Niedermayer committed
1310 1311
    ASFStream *asf_st;
    int i;
1312

1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
    asf->packet_size_left      = 0;
    asf->packet_segments       = 0;
    asf->packet_flags          = 0;
    asf->packet_property       = 0;
    asf->packet_timestamp      = 0;
    asf->packet_segsizetype    = 0;
    asf->packet_segments       = 0;
    asf->packet_seq            = 0;
    asf->packet_replic_size    = 0;
    asf->packet_key_frame      = 0;
    asf->packet_padsize        = 0;
    asf->packet_frag_offset    = 0;
    asf->packet_frag_size      = 0;
1326
    asf->packet_frag_timestamp = 0;
1327 1328 1329 1330
    asf->packet_multi_size     = 0;
    asf->packet_obj_size       = 0;
    asf->packet_time_delta     = 0;
    asf->packet_time_start     = 0;
1331

1332 1333
    for (i = 0; i < s->nb_streams; i++) {
        asf_st = s->streams[i]->priv_data;
1334 1335
        if (!asf_st)
            continue;
Michael Niedermayer's avatar
Michael Niedermayer committed
1336
        av_free_packet(&asf_st->pkt);
1337 1338
        asf_st->frag_offset = 0;
        asf_st->seq         = 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
1339
    }
1340
    asf->asf_st = NULL;
1341 1342
}

1343 1344 1345
static int asf_read_close(AVFormatContext *s)
{
    asf_reset_header(s);
1346

1347 1348 1349
    return 0;
}

1350 1351
static int64_t asf_read_pts(AVFormatContext *s, int stream_index,
                            int64_t *ppos, int64_t pos_limit)
1352 1353
{
    AVPacket pkt1, *pkt = &pkt1;
Michael Niedermayer's avatar
Michael Niedermayer committed
1354
    ASFStream *asf_st;
Michael Niedermayer's avatar
Michael Niedermayer committed
1355
    int64_t pts;
1356
    int64_t pos = *ppos;
1357
    int i;
1358
    int64_t start_pos[ASF_MAX_STREAMS];
1359

1360 1361
    for (i = 0; i < s->nb_streams; i++)
        start_pos[i] = pos;
1362

1363
    if (s->packet_size > 0)
1364 1365 1366 1367
        pos = (pos + s->packet_size - 1 - s->data_offset) /
              s->packet_size * s->packet_size +
              s->data_offset;
    *ppos = pos;
1368
    avio_seek(s->pb, pos, SEEK_SET);
1369

Michael Niedermayer's avatar
Michael Niedermayer committed
1370
    asf_reset_header(s);
1371 1372
    for (;;) {
        if (asf_read_packet(s, pkt) < 0) {
1373
            av_log(s, AV_LOG_INFO, "asf_read_pts failed\n");
1374
            return AV_NOPTS_VALUE;
Michael Niedermayer's avatar
Michael Niedermayer committed
1375
        }
1376

1377
        pts = pkt->dts;
Michael Niedermayer's avatar
Michael Niedermayer committed
1378 1379

        av_free_packet(pkt);
1380 1381
        if (pkt->flags & AV_PKT_FLAG_KEY) {
            i = pkt->stream_index;
1382

1383
            asf_st = s->streams[i]->priv_data;
1384
            av_assert0(asf_st);
1385

1386
//            assert((asf_st->packet_pos - s->data_offset) % s->packet_size == 0);
1387
            pos = asf_st->packet_pos;
1388

1389 1390 1391
            av_add_index_entry(s->streams[i], pos, pts, pkt->size,
                               pos - start_pos[i] + 1, AVINDEX_KEYFRAME);
            start_pos[i] = asf_st->packet_pos + 1;
1392

1393 1394
            if (pkt->stream_index == stream_index)
                break;
1395 1396 1397
        }
    }

1398
    *ppos = pos;
Michael Niedermayer's avatar
Michael Niedermayer committed
1399
    return pts;
1400 1401
}

1402
static int asf_build_simple_index(AVFormatContext *s, int stream_index)
1403
{
1404
    ff_asf_guid g;
1405 1406
    ASFContext *asf     = s->priv_data;
    int64_t current_pos = avio_tell(s->pb);
1407
    int i, ret = 0;
1408

1409
    avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
1410 1411
    if ((ret = ff_get_guid(s->pb, &g)) < 0)
        goto end;
1412 1413

    /* the data object can be followed by other top-level objects,
1414
     * skip them until the simple index object is reached */
1415
    while (ff_guidcmp(&g, &index_guid)) {
1416
        int64_t gsize = avio_rl64(s->pb);
Anton Khirnov's avatar
Anton Khirnov committed
1417
        if (gsize < 24 || s->pb->eof_reached) {
1418
            goto end;
1419
        }
1420
        avio_skip(s->pb, gsize - 24);
1421 1422
        if ((ret = ff_get_guid(s->pb, &g)) < 0)
            goto end;
1423 1424 1425
    }

    {
1426
        int64_t itime, last_pos = -1;
1427
        int pct, ict;
1428
        int64_t av_unused gsize = avio_rl64(s->pb);
1429 1430
        if ((ret = ff_get_guid(s->pb, &g)) < 0)
            goto end;
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
        itime = avio_rl64(s->pb);
        pct   = avio_rl32(s->pb);
        ict   = avio_rl32(s->pb);
        av_log(s, AV_LOG_DEBUG,
               "itime:0x%"PRIx64", pct:%d, ict:%d\n", itime, pct, ict);

        for (i = 0; i < ict; i++) {
            int pktnum        = avio_rl32(s->pb);
            int pktct         = avio_rl16(s->pb);
            int64_t pos       = s->data_offset + s->packet_size * (int64_t)pktnum;
            int64_t index_pts = FFMAX(av_rescale(itime, i, 10000) - asf->hdr.preroll, 0);

            if (pos != last_pos) {
                av_log(s, AV_LOG_DEBUG, "pktnum:%d, pktct:%d  pts: %"PRId64"\n",
                       pktnum, pktct, index_pts);
                av_add_index_entry(s->streams[stream_index], pos, index_pts,
                                   s->packet_size, 0, AVINDEX_KEYFRAME);
                last_pos = pos;
1449
            }
1450
        }
1451
        asf->index_read = ict > 0;
1452
    }
1453 1454 1455
end:
    if (s->pb->eof_reached)
        ret = 0;
1456
    avio_seek(s->pb, current_pos, SEEK_SET);
1457
    return ret;
1458 1459
}

1460 1461
static int asf_read_seek(AVFormatContext *s, int stream_index,
                         int64_t pts, int flags)
1462
{
1463
    ASFContext *asf = s->priv_data;
1464
    AVStream *st    = s->streams[stream_index];
1465
    int64_t pos;
1466
    int index, ret = 0;
1467

1468
    if (s->packet_size <= 0)
1469 1470
        return -1;

1471
    /* Try using the protocol's read_seek if available */
1472
    if (s->pb) {
1473
        int ret = avio_seek_time(s->pb, stream_index, pts, flags);
1474
        if (ret >= 0)
1475
            asf_reset_header(s);
1476
        if (ret != AVERROR(ENOSYS))
Aurelien Jacobs's avatar
Aurelien Jacobs committed
1477
            return ret;
1478 1479
    }

1480 1481 1482 1483 1484 1485 1486
    /* explicitly handle the case of seeking to 0 */
    if (!pts) {
        asf_reset_header(s);
        avio_seek(s->pb, s->data_offset, SEEK_SET);
        return 0;
    }

1487
    if (!asf->index_read)
1488
        ret = asf_build_simple_index(s, stream_index);
1489

1490
    if (!ret && asf->index_read && st->index_entries) {
1491 1492
        index = av_index_search_timestamp(st, pts, flags);
        if (index >= 0) {
1493 1494
            /* find the position */
            pos = st->index_entries[index].pos;
1495

1496 1497 1498 1499 1500
            /* do the seek */
            av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
            avio_seek(s->pb, pos, SEEK_SET);
            asf_reset_header(s);
            return 0;
1501
        }
1502
    }
1503
    /* no index or seeking by index failed */
1504
    if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0)
1505
        return -1;
1506 1507
    asf_reset_header(s);
    return 0;
1508 1509
}

1510
AVInputFormat ff_asf_demuxer = {
1511
    .name           = "asf",
1512
    .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1513 1514 1515 1516 1517 1518 1519
    .priv_data_size = sizeof(ASFContext),
    .read_probe     = asf_probe,
    .read_header    = asf_read_header,
    .read_packet    = asf_read_packet,
    .read_close     = asf_read_close,
    .read_seek      = asf_read_seek,
    .read_timestamp = asf_read_pts,
1520
    .flags          = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH,
1521
    .priv_class     = &asf_class,
Fabrice Bellard's avatar
Fabrice Bellard committed
1522
};