Revision 607f5fe5

View differences:

libavformat/asfdec.c
206 206
    return 0;
207 207
}
208 208

  
209
static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
210
{
211
    ASFContext *asf = s->priv_data;
212
    ByteIOContext *pb = s->pb;
213
    AVStream *st;
214
    ASFStream *asf_st;
215
    ff_asf_guid g;
216
    enum AVMediaType type;
217
    int type_specific_size, sizeX;
218
    uint64_t total_size;
219
    unsigned int tag1;
220
    int64_t pos1, pos2, start_time;
221
    int test_for_ext_stream_audio, is_dvr_ms_audio=0;
222

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

  
228
    pos1 = url_ftell(pb);
229

  
230
    st = av_new_stream(s, 0);
231
    if (!st)
232
        return AVERROR(ENOMEM);
233
    av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
234
    asf_st = av_mallocz(sizeof(ASFStream));
235
    if (!asf_st)
236
        return AVERROR(ENOMEM);
237
    st->priv_data = asf_st;
238
    start_time = asf->hdr.preroll;
239

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

  
242
    if(!(asf->hdr.flags & 0x01)) { // if we aren't streaming...
243
        st->duration = asf->hdr.play_time /
244
            (10000000 / 1000) - start_time;
245
    }
246
    ff_get_guid(pb, &g);
247

  
248
    test_for_ext_stream_audio = 0;
249
    if (!ff_guidcmp(&g, &ff_asf_audio_stream)) {
250
        type = AVMEDIA_TYPE_AUDIO;
251
    } else if (!ff_guidcmp(&g, &ff_asf_video_stream)) {
252
        type = AVMEDIA_TYPE_VIDEO;
253
    } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) {
254
        type = AVMEDIA_TYPE_VIDEO;
255
        st->codec->codec_id = CODEC_ID_MJPEG;
256
    } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) {
257
        type = AVMEDIA_TYPE_DATA;
258
    } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {
259
        test_for_ext_stream_audio = 1;
260
        type = AVMEDIA_TYPE_UNKNOWN;
261
    } else {
262
        return -1;
263
    }
264
    ff_get_guid(pb, &g);
265
    total_size = get_le64(pb);
266
    type_specific_size = get_le32(pb);
267
    get_le32(pb);
268
    st->id = get_le16(pb) & 0x7f; /* stream id */
269
    // mapping of asf ID to AV stream ID;
270
    asf->asfid2avid[st->id] = s->nb_streams - 1;
271

  
272
    get_le32(pb);
273

  
274
    if (test_for_ext_stream_audio) {
275
        ff_get_guid(pb, &g);
276
        if (!ff_guidcmp(&g, &ff_asf_ext_stream_audio_stream)) {
277
            type = AVMEDIA_TYPE_AUDIO;
278
            is_dvr_ms_audio=1;
279
            ff_get_guid(pb, &g);
280
            get_le32(pb);
281
            get_le32(pb);
282
            get_le32(pb);
283
            ff_get_guid(pb, &g);
284
            get_le32(pb);
285
        }
286
    }
287

  
288
    st->codec->codec_type = type;
289
    if (type == AVMEDIA_TYPE_AUDIO) {
290
        ff_get_wav_header(pb, st->codec, type_specific_size);
291
        if (is_dvr_ms_audio) {
292
            // codec_id and codec_tag are unreliable in dvr_ms
293
            // files. Set them later by probing stream.
294
            st->codec->codec_id = CODEC_ID_PROBE;
295
            st->codec->codec_tag = 0;
296
        }
297
        if (st->codec->codec_id == CODEC_ID_AAC) {
298
            st->need_parsing = AVSTREAM_PARSE_NONE;
299
        } else {
300
            st->need_parsing = AVSTREAM_PARSE_FULL;
301
        }
302
        /* We have to init the frame size at some point .... */
303
        pos2 = url_ftell(pb);
304
        if (size >= (pos2 + 8 - pos1 + 24)) {
305
            asf_st->ds_span = get_byte(pb);
306
            asf_st->ds_packet_size = get_le16(pb);
307
            asf_st->ds_chunk_size = get_le16(pb);
308
            get_le16(pb); //ds_data_size
309
            get_byte(pb); //ds_silence_data
310
        }
311
        //printf("Descrambling: ps:%d cs:%d ds:%d s:%d  sd:%d\n",
312
        //       asf_st->ds_packet_size, asf_st->ds_chunk_size,
313
        //       asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data);
314
        if (asf_st->ds_span > 1) {
315
            if (!asf_st->ds_chunk_size
316
                    || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1)
317
                    || asf_st->ds_packet_size % asf_st->ds_chunk_size)
318
                asf_st->ds_span = 0; // disable descrambling
319
        }
320
        switch (st->codec->codec_id) {
321
            case CODEC_ID_MP3:
322
                st->codec->frame_size = MPA_FRAME_SIZE;
323
                break;
324
            case CODEC_ID_PCM_S16LE:
325
            case CODEC_ID_PCM_S16BE:
326
            case CODEC_ID_PCM_U16LE:
327
            case CODEC_ID_PCM_U16BE:
328
            case CODEC_ID_PCM_S8:
329
            case CODEC_ID_PCM_U8:
330
            case CODEC_ID_PCM_ALAW:
331
            case CODEC_ID_PCM_MULAW:
332
                st->codec->frame_size = 1;
333
                break;
334
            default:
335
                /* This is probably wrong, but it prevents a crash later */
336
                st->codec->frame_size = 1;
337
                break;
338
        }
339
    } else if (type == AVMEDIA_TYPE_VIDEO &&
340
            size - (url_ftell(pb) - pos1 + 24) >= 51) {
341
        get_le32(pb);
342
        get_le32(pb);
343
        get_byte(pb);
344
        get_le16(pb);        /* size */
345
        sizeX= get_le32(pb); /* size */
346
        st->codec->width = get_le32(pb);
347
        st->codec->height = get_le32(pb);
348
        /* not available for asf */
349
        get_le16(pb); /* panes */
350
        st->codec->bits_per_coded_sample = get_le16(pb); /* depth */
351
        tag1 = get_le32(pb);
352
        url_fskip(pb, 20);
353
        //                av_log(s, AV_LOG_DEBUG, "size:%d tsize:%d sizeX:%d\n", size, total_size, sizeX);
354
        if (sizeX > 40) {
355
            st->codec->extradata_size = sizeX - 40;
356
            st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
357
            get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
358
        }
359

  
360
        /* Extract palette from extradata if bpp <= 8 */
361
        /* This code assumes that extradata contains only palette */
362
        /* This is true for all paletted codecs implemented in ffmpeg */
363
        if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
364
            st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
365
#if HAVE_BIGENDIAN
366
            for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
367
                st->codec->palctrl->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]);
368
#else
369
            memcpy(st->codec->palctrl->palette, st->codec->extradata,
370
                    FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
371
#endif
372
            st->codec->palctrl->palette_changed = 1;
373
        }
374

  
375
        st->codec->codec_tag = tag1;
376
        st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);
377
        if(tag1 == MKTAG('D', 'V', 'R', ' ')){
378
            st->need_parsing = AVSTREAM_PARSE_FULL;
379
            // issue658 containse wrong w/h and MS even puts a fake seq header with wrong w/h in extradata while a correct one is in te stream. maximum lameness
380
            st->codec->width  =
381
                st->codec->height = 0;
382
            av_freep(&st->codec->extradata);
383
            st->codec->extradata_size=0;
384
        }
385
        if(st->codec->codec_id == CODEC_ID_H264)
386
            st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
387
    }
388
    pos2 = url_ftell(pb);
389
    url_fskip(pb, size - (pos2 - pos1 + 24));
390

  
391
    return 0;
392
}
393

  
209 394
static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size)
210 395
{
211 396
    ASFContext *asf = s->priv_data;
......
396 581
    ASFContext *asf = s->priv_data;
397 582
    ff_asf_guid g;
398 583
    ByteIOContext *pb = s->pb;
399
    AVStream *st;
400
    ASFStream *asf_st;
401 584
    int i;
402 585
    int64_t gsize;
403 586

  
......
431 614
        if (!ff_guidcmp(&g, &ff_asf_file_header)) {
432 615
            asf_read_file_properties(s, gsize);
433 616
        } else if (!ff_guidcmp(&g, &ff_asf_stream_header)) {
434
            enum AVMediaType type;
435
            int type_specific_size, sizeX;
436
            uint64_t total_size;
437
            unsigned int tag1;
438
            int64_t pos1, pos2, start_time;
439
            int test_for_ext_stream_audio, is_dvr_ms_audio=0;
440

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

  
446
            pos1 = url_ftell(pb);
447

  
448
            st = av_new_stream(s, 0);
449
            if (!st)
450
                return AVERROR(ENOMEM);
451
            av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
452
            asf_st = av_mallocz(sizeof(ASFStream));
453
            if (!asf_st)
454
                return AVERROR(ENOMEM);
455
            st->priv_data = asf_st;
456
            start_time = asf->hdr.preroll;
457

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

  
460
            if(!(asf->hdr.flags & 0x01)) { // if we aren't streaming...
461
                st->duration = asf->hdr.play_time /
462
                    (10000000 / 1000) - start_time;
463
            }
464
            ff_get_guid(pb, &g);
465

  
466
            test_for_ext_stream_audio = 0;
467
            if (!ff_guidcmp(&g, &ff_asf_audio_stream)) {
468
                type = AVMEDIA_TYPE_AUDIO;
469
            } else if (!ff_guidcmp(&g, &ff_asf_video_stream)) {
470
                type = AVMEDIA_TYPE_VIDEO;
471
            } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) {
472
                type = AVMEDIA_TYPE_VIDEO;
473
                st->codec->codec_id = CODEC_ID_MJPEG;
474
            } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) {
475
                type = AVMEDIA_TYPE_DATA;
476
            } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {
477
                test_for_ext_stream_audio = 1;
478
                type = AVMEDIA_TYPE_UNKNOWN;
479
            } else {
480
                return -1;
481
            }
482
            ff_get_guid(pb, &g);
483
            total_size = get_le64(pb);
484
            type_specific_size = get_le32(pb);
485
            get_le32(pb);
486
            st->id = get_le16(pb) & 0x7f; /* stream id */
487
            // mapping of asf ID to AV stream ID;
488
            asf->asfid2avid[st->id] = s->nb_streams - 1;
489

  
490
            get_le32(pb);
491

  
492
            if (test_for_ext_stream_audio) {
493
                ff_get_guid(pb, &g);
494
                if (!ff_guidcmp(&g, &ff_asf_ext_stream_audio_stream)) {
495
                    type = AVMEDIA_TYPE_AUDIO;
496
                    is_dvr_ms_audio=1;
497
                    ff_get_guid(pb, &g);
498
                    get_le32(pb);
499
                    get_le32(pb);
500
                    get_le32(pb);
501
                    ff_get_guid(pb, &g);
502
                    get_le32(pb);
503
                }
504
            }
505

  
506
            st->codec->codec_type = type;
507
            if (type == AVMEDIA_TYPE_AUDIO) {
508
                ff_get_wav_header(pb, st->codec, type_specific_size);
509
                if (is_dvr_ms_audio) {
510
                    // codec_id and codec_tag are unreliable in dvr_ms
511
                    // files. Set them later by probing stream.
512
                    st->codec->codec_id = CODEC_ID_PROBE;
513
                    st->codec->codec_tag = 0;
514
                }
515
                if (st->codec->codec_id == CODEC_ID_AAC) {
516
                    st->need_parsing = AVSTREAM_PARSE_NONE;
517
                } else {
518
                    st->need_parsing = AVSTREAM_PARSE_FULL;
519
                }
520
                /* We have to init the frame size at some point .... */
521
                pos2 = url_ftell(pb);
522
                if (gsize >= (pos2 + 8 - pos1 + 24)) {
523
                    asf_st->ds_span = get_byte(pb);
524
                    asf_st->ds_packet_size = get_le16(pb);
525
                    asf_st->ds_chunk_size = get_le16(pb);
526
                    get_le16(pb); //ds_data_size
527
                    get_byte(pb); //ds_silence_data
528
                }
529
                //printf("Descrambling: ps:%d cs:%d ds:%d s:%d  sd:%d\n",
530
                //       asf_st->ds_packet_size, asf_st->ds_chunk_size,
531
                //       asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data);
532
                if (asf_st->ds_span > 1) {
533
                    if (!asf_st->ds_chunk_size
534
                        || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1)
535
                        || asf_st->ds_packet_size % asf_st->ds_chunk_size)
536
                        asf_st->ds_span = 0; // disable descrambling
537
                }
538
                switch (st->codec->codec_id) {
539
                case CODEC_ID_MP3:
540
                    st->codec->frame_size = MPA_FRAME_SIZE;
541
                    break;
542
                case CODEC_ID_PCM_S16LE:
543
                case CODEC_ID_PCM_S16BE:
544
                case CODEC_ID_PCM_U16LE:
545
                case CODEC_ID_PCM_U16BE:
546
                case CODEC_ID_PCM_S8:
547
                case CODEC_ID_PCM_U8:
548
                case CODEC_ID_PCM_ALAW:
549
                case CODEC_ID_PCM_MULAW:
550
                    st->codec->frame_size = 1;
551
                    break;
552
                default:
553
                    /* This is probably wrong, but it prevents a crash later */
554
                    st->codec->frame_size = 1;
555
                    break;
556
                }
557
            } else if (type == AVMEDIA_TYPE_VIDEO &&
558
                       gsize - (url_ftell(pb) - pos1 + 24) >= 51) {
559
                get_le32(pb);
560
                get_le32(pb);
561
                get_byte(pb);
562
                get_le16(pb);        /* size */
563
                sizeX= get_le32(pb); /* size */
564
                st->codec->width = get_le32(pb);
565
                st->codec->height = get_le32(pb);
566
                /* not available for asf */
567
                get_le16(pb); /* panes */
568
                st->codec->bits_per_coded_sample = get_le16(pb); /* depth */
569
                tag1 = get_le32(pb);
570
                url_fskip(pb, 20);
571
//                av_log(s, AV_LOG_DEBUG, "size:%d tsize:%d sizeX:%d\n", size, total_size, sizeX);
572
                if (sizeX > 40) {
573
                    st->codec->extradata_size = sizeX - 40;
574
                    st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
575
                    get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
576
                }
577

  
578
                /* Extract palette from extradata if bpp <= 8 */
579
                /* This code assumes that extradata contains only palette */
580
                /* This is true for all paletted codecs implemented in ffmpeg */
581
                if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
582
                    st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
583
#if HAVE_BIGENDIAN
584
                    for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
585
                        st->codec->palctrl->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]);
586
#else
587
                    memcpy(st->codec->palctrl->palette, st->codec->extradata,
588
                           FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
589
#endif
590
                    st->codec->palctrl->palette_changed = 1;
591
                }
592

  
593
                st->codec->codec_tag = tag1;
594
                st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);
595
                if(tag1 == MKTAG('D', 'V', 'R', ' ')){
596
                    st->need_parsing = AVSTREAM_PARSE_FULL;
597
                    // issue658 containse wrong w/h and MS even puts a fake seq header with wrong w/h in extradata while a correct one is in te stream. maximum lameness
598
                    st->codec->width  =
599
                    st->codec->height = 0;
600
                    av_freep(&st->codec->extradata);
601
                    st->codec->extradata_size=0;
602
                }
603
                if(st->codec->codec_id == CODEC_ID_H264)
604
                    st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
605
            }
606
            pos2 = url_ftell(pb);
607
            url_fskip(pb, gsize - (pos2 - pos1 + 24));
617
            asf_read_stream_properties(s, gsize);
608 618
        } else if (!ff_guidcmp(&g, &ff_asf_comment_header)) {
609 619
            asf_read_content_desc(s, gsize);
610 620
        } else if (!ff_guidcmp(&g, &ff_asf_language_guid)) {

Also available in: Unified diff