static int w64_read_header(AVFormatContext *s) { int64_t size; AVIOContext *pb = s->pb; WAVDemuxContext *wav = s->priv_data; AVStream *st; uint8_t guid[16]; int ret; avio_read(pb, guid, 16); if (memcmp(guid, guid_riff, 16)) return -1; if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */ return -1; avio_read(pb, guid, 16); if (memcmp(guid, guid_wave, 16)) { av_log(s, AV_LOG_ERROR, "could not find wave guid\n"); return -1; } size = find_guid(pb, guid_fmt); if (size < 0) { av_log(s, AV_LOG_ERROR, "could not find fmt guid\n"); return -1; } st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); /* subtract chunk header size - normal wav file doesn't count it */ ret = ff_get_wav_header(pb, st->codec, size - 24); if (ret < 0) return ret; avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); handle_stream_probing(st); st->need_parsing = AVSTREAM_PARSE_FULL_RAW; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); size = find_guid(pb, guid_data); if (size < 0) { av_log(s, AV_LOG_ERROR, "could not find data guid\n"); return -1; } wav->data_end = avio_tell(pb) + size - 24; wav->w64 = 1; return 0; }
static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) { AVIOContext *pb = s->pb; int ret; /* parse fmt header */ *st = avformat_new_stream(s, NULL); if (!*st) return AVERROR(ENOMEM); ret = ff_get_wav_header(pb, (*st)->codec, size); if (ret < 0) return ret; handle_stream_probing(*st); (*st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate); return 0; }
static int w64_read_header(AVFormatContext *s) { int64_t size, data_ofs = 0; AVIOContext *pb = s->pb; WAVDemuxContext *wav = s->priv_data; AVStream *st; uint8_t guid[16]; int ret; avio_read(pb, guid, 16); if (memcmp(guid, ff_w64_guid_riff, 16)) return AVERROR_INVALIDDATA; /* riff + wave + fmt + sizes */ if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) return AVERROR_INVALIDDATA; avio_read(pb, guid, 16); if (memcmp(guid, ff_w64_guid_wave, 16)) { av_log(s, AV_LOG_ERROR, "could not find wave guid\n"); return AVERROR_INVALIDDATA; } wav->w64 = 1; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); while (!url_feof(pb)) { if (avio_read(pb, guid, 16) != 16) break; size = avio_rl64(pb); if (size <= 24 || INT64_MAX - size < avio_tell(pb)) return AVERROR_INVALIDDATA; if (!memcmp(guid, ff_w64_guid_fmt, 16)) { /* subtract chunk header size - normal wav file doesn't count it */ ret = ff_get_wav_header(pb, st->codec, size - 24); if (ret < 0) return ret; avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); } else if (!memcmp(guid, ff_w64_guid_fact, 16)) { int64_t samples; samples = avio_rl64(pb); if (samples > 0) st->duration = samples; } else if (!memcmp(guid, ff_w64_guid_data, 16)) { wav->data_end = avio_tell(pb) + size - 24; data_ofs = avio_tell(pb); if (!pb->seekable) break; avio_skip(pb, size - 24); } else if (!memcmp(guid, ff_w64_guid_summarylist, 16)) { int64_t start, end, cur; uint32_t count, chunk_size, i; start = avio_tell(pb); end = start + size; count = avio_rl32(pb); for (i = 0; i < count; i++) { char chunk_key[5], *value; if (url_feof(pb) || (cur = avio_tell(pb)) < 0 || cur > end - 8 /* = tag + size */) break; chunk_key[4] = 0; avio_read(pb, chunk_key, 4); chunk_size = avio_rl32(pb); value = av_mallocz(chunk_size + 1); if (!value) return AVERROR(ENOMEM); ret = avio_get_str16le(pb, chunk_size, value, chunk_size); avio_skip(pb, chunk_size - ret); av_dict_set(&s->metadata, chunk_key, value, AV_DICT_DONT_STRDUP_VAL); } avio_skip(pb, end - avio_tell(pb)); } else { av_log(s, AV_LOG_DEBUG, "unknown guid: "FF_PRI_GUID"\n", FF_ARG_GUID(guid)); avio_skip(pb, size - 24); } } if (!data_ofs) return AVERROR_EOF; ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv); handle_stream_probing(st); st->need_parsing = AVSTREAM_PARSE_FULL_RAW; avio_seek(pb, data_ofs, SEEK_SET); return 0; }