| @@ -552,7 +552,7 @@ static int w64_probe(AVProbeData *p) · 551 unmodified lines |
| 552 | | 552 | |
| 553 | static int w64_read_header(AVFormatContext *s) | 553 | static int w64_read_header(AVFormatContext *s) |
| 554 | { | 554 | { |
| 555 | int64_t size; | 555 | int64_t size, data_ofs = 0; |
| 556 | AVIOContext *pb = s->pb; | 556 | AVIOContext *pb = s->pb; |
| 557 | WAVDemuxContext *wav = s->priv_data; | 557 | WAVDemuxContext *wav = s->priv_data; |
| 558 | AVStream *st; | 558 | AVStream *st; |
| @@ -572,34 +572,80 @@ static int w64_read_header(AVFormatContext *s) · 13 unmodified lines |
| 572 | return -1; | 572 | return -1; |
| 573 | } | 573 | } |
| 574 | | 574 | |
| 575 | size = find_guid(pb, ff_w64_guid_fmt); | 575 | wav->w64 = 1; |
| 576 | if (size < 0) { | | |
| 577 | av_log(s, AV_LOG_ERROR, "could not find fmt guid\n"); | | |
| 578 | return -1; | | |
| 579 | } | | |
| 580 | | 576 | |
| 581 | st = avformat_new_stream(s, NULL); | 577 | st = avformat_new_stream(s, NULL); |
| 582 | if (!st) | 578 | if (!st) |
| 583 | return AVERROR(ENOMEM); | 579 | return AVERROR(ENOMEM); |
| 584 | | 580 | |
| 585 | /* subtract chunk header size - normal wav file doesn't count it */ | 581 | while (!url_feof(pb)) { |
| 586 | ret = ff_get_wav_header(pb, st->codec, size - 24); | 582 | if (avio_read(pb, guid, 16) != 16) |
| 587 | if (ret < 0) | 583 | break; |
| 588 | return ret; | 584 | size = avio_rl64(pb); |
| 589 | avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); | 585 | if (size <= 24 || INT64_MAX - size < avio_tell(pb)) |
| | 586 | return AVERROR_INVALIDDATA; |
| 590 | | 587 | |
| 591 | handle_stream_probing(st); | 588 | if (!memcmp(guid, ff_w64_guid_fmt, 16)) { |
| 592 | st->need_parsing = AVSTREAM_PARSE_FULL_RAW; | 589 | /* subtract chunk header size - normal wav file doesn't count it */ |
| | 590 | ret = ff_get_wav_header(pb, st->codec, size - 24); |
| | 591 | if (ret < 0) |
| | 592 | return ret; |
| | 593 | avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); |
| 593 | | 594 | |
| 594 | avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); | 595 | avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); |
| | 596 | } else if (!memcmp(guid, ff_w64_guid_data, 16)) { |
| | 597 | wav->data_end = avio_tell(pb) + size - 24; |
| 595 | | 598 | |
| 596 | size = find_guid(pb, ff_w64_guid_data); | 599 | data_ofs = avio_tell(pb); |
| 597 | if (size < 0) { | 600 | if (!pb->seekable) |
| 598 | av_log(s, AV_LOG_ERROR, "could not find data guid\n"); | 601 | break; |
| 599 | return -1; | 602 | |
| | 603 | avio_skip(pb, size - 24); |
| | 604 | } else if (!memcmp(guid, ff_w64_guid_summarylist, 16)) { |
| | 605 | int64_t start, end, cur; |
| | 606 | uint32_t count, chunk_size, i; |
| | 607 | |
| | 608 | start = avio_tell(pb); |
| | 609 | end = start + size; |
| | 610 | count = avio_rl32(pb); |
| | 611 | |
| | 612 | for (i = 0; i < count; i++) { |
| | 613 | char chunk_key[5], *value; |
| | 614 | |
| | 615 | if (url_feof(pb) || (cur = avio_tell(pb)) < 0 || cur > end - 8 /* = tag + size */) |
| | 616 | break; |
| | 617 | |
| | 618 | chunk_key[4] = 0; |
| | 619 | avio_read(pb, chunk_key, 4); |
| | 620 | chunk_size = avio_rl32(pb); |
| | 621 | |
| | 622 | value = av_mallocz(chunk_size + 1); |
| | 623 | if (!value) |
| | 624 | return AVERROR(ENOMEM); |
| | 625 | |
| | 626 | ret = avio_get_str16le(pb, chunk_size, value, chunk_size); |
| | 627 | avio_skip(pb, chunk_size - ret); |
| | 628 | |
| | 629 | av_dict_set(&s->metadata, chunk_key, value, AV_DICT_DONT_STRDUP_VAL); |
| | 630 | } |
| | 631 | |
| | 632 | avio_skip(pb, end - avio_tell(pb)); |
| | 633 | } else { |
| | 634 | av_log(s, AV_LOG_DEBUG, "unknown guid: "FF_PRI_GUID"\n", FF_ARG_GUID(guid)); |
| | 635 | avio_skip(pb, size - 24); |
| | 636 | } |
| 600 | } | 637 | } |
| 601 | wav->data_end = avio_tell(pb) + size - 24; | 638 | |
| 602 | wav->w64 = 1; | 639 | if (!data_ofs) |
| | 640 | return AVERROR_EOF; |
| | 641 | |
| | 642 | ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); |
| | 643 | ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv); |
| | 644 | |
| | 645 | handle_stream_probing(st); |
| | 646 | st->need_parsing = AVSTREAM_PARSE_FULL_RAW; |
| | 647 | |
| | 648 | avio_seek(pb, data_ofs, SEEK_SET); |
| 603 | | 649 | |
| 604 | return 0; | 650 | return 0; |
| 605 | } | 651 | } |