1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * WAV demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2001, 2002 Fabrice Bellard 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * Sony Wave64 demuxer 6cabdff1aSopenharmony_ci * RF64 demuxer 7cabdff1aSopenharmony_ci * Copyright (c) 2009 Daniel Verkamp 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * BW64 demuxer 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * This file is part of FFmpeg. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 14cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 16cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 19cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 20cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21cabdff1aSopenharmony_ci * Lesser General Public License for more details. 22cabdff1aSopenharmony_ci * 23cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 24cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 25cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26cabdff1aSopenharmony_ci */ 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include <stdint.h> 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "config_components.h" 31cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 32cabdff1aSopenharmony_ci#include "libavutil/dict.h" 33cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 34cabdff1aSopenharmony_ci#include "libavutil/log.h" 35cabdff1aSopenharmony_ci#include "libavutil/mathematics.h" 36cabdff1aSopenharmony_ci#include "libavutil/opt.h" 37cabdff1aSopenharmony_ci#include "avformat.h" 38cabdff1aSopenharmony_ci#include "avio.h" 39cabdff1aSopenharmony_ci#include "avio_internal.h" 40cabdff1aSopenharmony_ci#include "demux.h" 41cabdff1aSopenharmony_ci#include "id3v2.h" 42cabdff1aSopenharmony_ci#include "internal.h" 43cabdff1aSopenharmony_ci#include "metadata.h" 44cabdff1aSopenharmony_ci#include "pcm.h" 45cabdff1aSopenharmony_ci#include "riff.h" 46cabdff1aSopenharmony_ci#include "w64.h" 47cabdff1aSopenharmony_ci#include "spdif.h" 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_citypedef struct WAVDemuxContext { 50cabdff1aSopenharmony_ci const AVClass *class; 51cabdff1aSopenharmony_ci int64_t data_end; 52cabdff1aSopenharmony_ci int w64; 53cabdff1aSopenharmony_ci AVStream *vst; 54cabdff1aSopenharmony_ci int64_t smv_data_ofs; 55cabdff1aSopenharmony_ci int smv_block_size; 56cabdff1aSopenharmony_ci int smv_frames_per_jpeg; 57cabdff1aSopenharmony_ci int smv_block; 58cabdff1aSopenharmony_ci int smv_last_stream; 59cabdff1aSopenharmony_ci int smv_eof; 60cabdff1aSopenharmony_ci int audio_eof; 61cabdff1aSopenharmony_ci int ignore_length; 62cabdff1aSopenharmony_ci int max_size; 63cabdff1aSopenharmony_ci int spdif; 64cabdff1aSopenharmony_ci int smv_given_first; 65cabdff1aSopenharmony_ci int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended 66cabdff1aSopenharmony_ci int rifx; // RIFX: integer byte order for parameters is big endian 67cabdff1aSopenharmony_ci} WAVDemuxContext; 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(WAVDemuxContext, x) 70cabdff1aSopenharmony_ci#define DEC AV_OPT_FLAG_DECODING_PARAM 71cabdff1aSopenharmony_cistatic const AVOption demux_options[] = { 72cabdff1aSopenharmony_ci#define W64_DEMUXER_OPTIONS_OFFSET (1 * CONFIG_WAV_DEMUXER) 73cabdff1aSopenharmony_ci#if CONFIG_WAV_DEMUXER 74cabdff1aSopenharmony_ci { "ignore_length", "Ignore length", OFFSET(ignore_length), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, 75cabdff1aSopenharmony_ci#endif 76cabdff1aSopenharmony_ci { "max_size", "max size of single packet", OFFSET(max_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 1024, 1 << 22, DEC }, 77cabdff1aSopenharmony_ci { NULL }, 78cabdff1aSopenharmony_ci}; 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_cistatic void set_spdif(AVFormatContext *s, WAVDemuxContext *wav) 81cabdff1aSopenharmony_ci{ 82cabdff1aSopenharmony_ci if (CONFIG_SPDIF_DEMUXER && s->streams[0]->codecpar->codec_tag == 1) { 83cabdff1aSopenharmony_ci enum AVCodecID codec; 84cabdff1aSopenharmony_ci int len = 1<<16; 85cabdff1aSopenharmony_ci int ret = ffio_ensure_seekback(s->pb, len); 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci if (ret >= 0) { 88cabdff1aSopenharmony_ci uint8_t *buf = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE); 89cabdff1aSopenharmony_ci if (!buf) { 90cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 91cabdff1aSopenharmony_ci } else { 92cabdff1aSopenharmony_ci int64_t pos = avio_tell(s->pb); 93cabdff1aSopenharmony_ci len = ret = avio_read(s->pb, buf, len); 94cabdff1aSopenharmony_ci if (len >= 0) { 95cabdff1aSopenharmony_ci ret = ff_spdif_probe(buf, len, &codec); 96cabdff1aSopenharmony_ci if (ret > AVPROBE_SCORE_EXTENSION) { 97cabdff1aSopenharmony_ci s->streams[0]->codecpar->codec_id = codec; 98cabdff1aSopenharmony_ci wav->spdif = 1; 99cabdff1aSopenharmony_ci } 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci avio_seek(s->pb, pos, SEEK_SET); 102cabdff1aSopenharmony_ci av_free(buf); 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci } 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci if (ret < 0) 107cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Cannot check for SPDIF\n"); 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci} 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci#if CONFIG_WAV_DEMUXER 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_cistatic int64_t next_tag(AVIOContext *pb, uint32_t *tag, int big_endian) 114cabdff1aSopenharmony_ci{ 115cabdff1aSopenharmony_ci *tag = avio_rl32(pb); 116cabdff1aSopenharmony_ci if (!big_endian) { 117cabdff1aSopenharmony_ci return avio_rl32(pb); 118cabdff1aSopenharmony_ci } else { 119cabdff1aSopenharmony_ci return avio_rb32(pb); 120cabdff1aSopenharmony_ci } 121cabdff1aSopenharmony_ci} 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci/* RIFF chunks are always at even offsets relative to where they start. */ 124cabdff1aSopenharmony_cistatic int64_t wav_seek_tag(WAVDemuxContext * wav, AVIOContext *s, int64_t offset, int whence) 125cabdff1aSopenharmony_ci{ 126cabdff1aSopenharmony_ci offset += offset < INT64_MAX && offset + wav->unaligned & 1; 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci return avio_seek(s, offset, whence); 129cabdff1aSopenharmony_ci} 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci/* return the size of the found tag */ 132cabdff1aSopenharmony_cistatic int64_t find_tag(WAVDemuxContext * wav, AVIOContext *pb, uint32_t tag1) 133cabdff1aSopenharmony_ci{ 134cabdff1aSopenharmony_ci unsigned int tag; 135cabdff1aSopenharmony_ci int64_t size; 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci for (;;) { 138cabdff1aSopenharmony_ci if (avio_feof(pb)) 139cabdff1aSopenharmony_ci return AVERROR_EOF; 140cabdff1aSopenharmony_ci size = next_tag(pb, &tag, wav->rifx); 141cabdff1aSopenharmony_ci if (tag == tag1) 142cabdff1aSopenharmony_ci break; 143cabdff1aSopenharmony_ci wav_seek_tag(wav, pb, size, SEEK_CUR); 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci return size; 146cabdff1aSopenharmony_ci} 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_cistatic int wav_probe(const AVProbeData *p) 149cabdff1aSopenharmony_ci{ 150cabdff1aSopenharmony_ci /* check file header */ 151cabdff1aSopenharmony_ci if (p->buf_size <= 32) 152cabdff1aSopenharmony_ci return 0; 153cabdff1aSopenharmony_ci if (!memcmp(p->buf + 8, "WAVE", 4)) { 154cabdff1aSopenharmony_ci if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4)) 155cabdff1aSopenharmony_ci /* Since the ACT demuxer has a standard WAV header at the top of 156cabdff1aSopenharmony_ci * its own, the returned score is decreased to avoid a probe 157cabdff1aSopenharmony_ci * conflict between ACT and WAV. */ 158cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX - 1; 159cabdff1aSopenharmony_ci else if ((!memcmp(p->buf, "RF64", 4) || 160cabdff1aSopenharmony_ci !memcmp(p->buf, "BW64", 4)) && 161cabdff1aSopenharmony_ci !memcmp(p->buf + 12, "ds64", 4)) 162cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 163cabdff1aSopenharmony_ci } 164cabdff1aSopenharmony_ci return 0; 165cabdff1aSopenharmony_ci} 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_cistatic void handle_stream_probing(AVStream *st) 168cabdff1aSopenharmony_ci{ 169cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) { 170cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 171cabdff1aSopenharmony_ci sti->request_probe = AVPROBE_SCORE_EXTENSION; 172cabdff1aSopenharmony_ci sti->probe_packets = FFMIN(sti->probe_packets, 32); 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci} 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_cistatic int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream *st) 177cabdff1aSopenharmony_ci{ 178cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 179cabdff1aSopenharmony_ci WAVDemuxContext *wav = s->priv_data; 180cabdff1aSopenharmony_ci int ret; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci /* parse fmt header */ 183cabdff1aSopenharmony_ci ret = ff_get_wav_header(s, pb, st->codecpar, size, wav->rifx); 184cabdff1aSopenharmony_ci if (ret < 0) 185cabdff1aSopenharmony_ci return ret; 186cabdff1aSopenharmony_ci handle_stream_probing(st); 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; 189cabdff1aSopenharmony_ci 190cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci return 0; 193cabdff1aSopenharmony_ci} 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_cistatic int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream *st) 196cabdff1aSopenharmony_ci{ 197cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 198cabdff1aSopenharmony_ci int version, num_streams, i, channels = 0, ret; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci if (size < 36) 201cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 204cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_XMA2; 205cabdff1aSopenharmony_ci ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci version = avio_r8(pb); 208cabdff1aSopenharmony_ci if (version != 3 && version != 4) 209cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 210cabdff1aSopenharmony_ci num_streams = avio_r8(pb); 211cabdff1aSopenharmony_ci if (size != (32 + ((version==3)?0:8) + 4*num_streams)) 212cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 213cabdff1aSopenharmony_ci avio_skip(pb, 10); 214cabdff1aSopenharmony_ci st->codecpar->sample_rate = avio_rb32(pb); 215cabdff1aSopenharmony_ci if (version == 4) 216cabdff1aSopenharmony_ci avio_skip(pb, 8); 217cabdff1aSopenharmony_ci avio_skip(pb, 4); 218cabdff1aSopenharmony_ci st->duration = avio_rb32(pb); 219cabdff1aSopenharmony_ci avio_skip(pb, 8); 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci for (i = 0; i < num_streams; i++) { 222cabdff1aSopenharmony_ci channels += avio_r8(pb); 223cabdff1aSopenharmony_ci avio_skip(pb, 3); 224cabdff1aSopenharmony_ci } 225cabdff1aSopenharmony_ci av_channel_layout_uninit(&st->codecpar->ch_layout); 226cabdff1aSopenharmony_ci st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; 227cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels = channels; 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci if (st->codecpar->ch_layout.nb_channels <= 0 || st->codecpar->sample_rate <= 0) 230cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_ci avio_seek(pb, -size, SEEK_CUR); 235cabdff1aSopenharmony_ci if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) 236cabdff1aSopenharmony_ci return ret; 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci return 0; 239cabdff1aSopenharmony_ci} 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_cistatic inline int wav_parse_bext_string(AVFormatContext *s, const char *key, 242cabdff1aSopenharmony_ci int length) 243cabdff1aSopenharmony_ci{ 244cabdff1aSopenharmony_ci char temp[257]; 245cabdff1aSopenharmony_ci int ret; 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ci av_assert0(length < sizeof(temp)); 248cabdff1aSopenharmony_ci if ((ret = ffio_read_size(s->pb, temp, length)) < 0) 249cabdff1aSopenharmony_ci return ret; 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_ci temp[length] = 0; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci if (strlen(temp)) 254cabdff1aSopenharmony_ci return av_dict_set(&s->metadata, key, temp, 0); 255cabdff1aSopenharmony_ci 256cabdff1aSopenharmony_ci return 0; 257cabdff1aSopenharmony_ci} 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_cistatic int wav_parse_bext_tag(AVFormatContext *s, int64_t size) 260cabdff1aSopenharmony_ci{ 261cabdff1aSopenharmony_ci char temp[131], *coding_history; 262cabdff1aSopenharmony_ci int ret, x; 263cabdff1aSopenharmony_ci uint64_t time_reference; 264cabdff1aSopenharmony_ci int64_t umid_parts[8], umid_mask = 0; 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci if ((ret = wav_parse_bext_string(s, "description", 256)) < 0 || 267cabdff1aSopenharmony_ci (ret = wav_parse_bext_string(s, "originator", 32)) < 0 || 268cabdff1aSopenharmony_ci (ret = wav_parse_bext_string(s, "originator_reference", 32)) < 0 || 269cabdff1aSopenharmony_ci (ret = wav_parse_bext_string(s, "origination_date", 10)) < 0 || 270cabdff1aSopenharmony_ci (ret = wav_parse_bext_string(s, "origination_time", 8)) < 0) 271cabdff1aSopenharmony_ci return ret; 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci time_reference = avio_rl64(s->pb); 274cabdff1aSopenharmony_ci snprintf(temp, sizeof(temp), "%"PRIu64, time_reference); 275cabdff1aSopenharmony_ci if ((ret = av_dict_set(&s->metadata, "time_reference", temp, 0)) < 0) 276cabdff1aSopenharmony_ci return ret; 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci /* check if version is >= 1, in which case an UMID may be present */ 279cabdff1aSopenharmony_ci if (avio_rl16(s->pb) >= 1) { 280cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 281cabdff1aSopenharmony_ci umid_mask |= umid_parts[x] = avio_rb64(s->pb); 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci if (umid_mask) { 284cabdff1aSopenharmony_ci /* the string formatting below is per SMPTE 330M-2004 Annex C */ 285cabdff1aSopenharmony_ci if (umid_parts[4] == 0 && umid_parts[5] == 0 && 286cabdff1aSopenharmony_ci umid_parts[6] == 0 && umid_parts[7] == 0) { 287cabdff1aSopenharmony_ci /* basic UMID */ 288cabdff1aSopenharmony_ci snprintf(temp, sizeof(temp), 289cabdff1aSopenharmony_ci "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, 290cabdff1aSopenharmony_ci umid_parts[0], umid_parts[1], 291cabdff1aSopenharmony_ci umid_parts[2], umid_parts[3]); 292cabdff1aSopenharmony_ci } else { 293cabdff1aSopenharmony_ci /* extended UMID */ 294cabdff1aSopenharmony_ci snprintf(temp, sizeof(temp), 295cabdff1aSopenharmony_ci "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64 296cabdff1aSopenharmony_ci "%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, 297cabdff1aSopenharmony_ci umid_parts[0], umid_parts[1], 298cabdff1aSopenharmony_ci umid_parts[2], umid_parts[3], 299cabdff1aSopenharmony_ci umid_parts[4], umid_parts[5], 300cabdff1aSopenharmony_ci umid_parts[6], umid_parts[7]); 301cabdff1aSopenharmony_ci } 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci if ((ret = av_dict_set(&s->metadata, "umid", temp, 0)) < 0) 304cabdff1aSopenharmony_ci return ret; 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci avio_skip(s->pb, 190); 308cabdff1aSopenharmony_ci } else 309cabdff1aSopenharmony_ci avio_skip(s->pb, 254); 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci if (size > 602) { 312cabdff1aSopenharmony_ci /* CodingHistory present */ 313cabdff1aSopenharmony_ci size -= 602; 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci if (!(coding_history = av_malloc(size + 1))) 316cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ci if ((ret = ffio_read_size(s->pb, coding_history, size)) < 0) { 319cabdff1aSopenharmony_ci av_free(coding_history); 320cabdff1aSopenharmony_ci return ret; 321cabdff1aSopenharmony_ci } 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ci coding_history[size] = 0; 324cabdff1aSopenharmony_ci if ((ret = av_dict_set(&s->metadata, "coding_history", coding_history, 325cabdff1aSopenharmony_ci AV_DICT_DONT_STRDUP_VAL)) < 0) 326cabdff1aSopenharmony_ci return ret; 327cabdff1aSopenharmony_ci } 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_ci return 0; 330cabdff1aSopenharmony_ci} 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_cistatic const AVMetadataConv wav_metadata_conv[] = { 333cabdff1aSopenharmony_ci { "description", "comment" }, 334cabdff1aSopenharmony_ci { "originator", "encoded_by" }, 335cabdff1aSopenharmony_ci { "origination_date", "date" }, 336cabdff1aSopenharmony_ci { "origination_time", "creation_time" }, 337cabdff1aSopenharmony_ci { 0 }, 338cabdff1aSopenharmony_ci}; 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_ci/* wav input */ 341cabdff1aSopenharmony_cistatic int wav_read_header(AVFormatContext *s) 342cabdff1aSopenharmony_ci{ 343cabdff1aSopenharmony_ci int64_t size, av_uninit(data_size); 344cabdff1aSopenharmony_ci int64_t sample_count = 0; 345cabdff1aSopenharmony_ci int rf64 = 0, bw64 = 0; 346cabdff1aSopenharmony_ci uint32_t tag; 347cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 348cabdff1aSopenharmony_ci AVStream *st = NULL; 349cabdff1aSopenharmony_ci WAVDemuxContext *wav = s->priv_data; 350cabdff1aSopenharmony_ci int ret, got_fmt = 0, got_xma2 = 0; 351cabdff1aSopenharmony_ci int64_t next_tag_ofs, data_ofs = -1; 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ci wav->unaligned = avio_tell(s->pb) & 1; 354cabdff1aSopenharmony_ci 355cabdff1aSopenharmony_ci wav->smv_data_ofs = -1; 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci /* read chunk ID */ 358cabdff1aSopenharmony_ci tag = avio_rl32(pb); 359cabdff1aSopenharmony_ci switch (tag) { 360cabdff1aSopenharmony_ci case MKTAG('R', 'I', 'F', 'F'): 361cabdff1aSopenharmony_ci break; 362cabdff1aSopenharmony_ci case MKTAG('R', 'I', 'F', 'X'): 363cabdff1aSopenharmony_ci wav->rifx = 1; 364cabdff1aSopenharmony_ci break; 365cabdff1aSopenharmony_ci case MKTAG('R', 'F', '6', '4'): 366cabdff1aSopenharmony_ci rf64 = 1; 367cabdff1aSopenharmony_ci break; 368cabdff1aSopenharmony_ci case MKTAG('B', 'W', '6', '4'): 369cabdff1aSopenharmony_ci bw64 = 1; 370cabdff1aSopenharmony_ci break; 371cabdff1aSopenharmony_ci default: 372cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid start code %s in RIFF header\n", 373cabdff1aSopenharmony_ci av_fourcc2str(tag)); 374cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 375cabdff1aSopenharmony_ci } 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_ci /* read chunk size */ 378cabdff1aSopenharmony_ci avio_rl32(pb); 379cabdff1aSopenharmony_ci 380cabdff1aSopenharmony_ci /* read format */ 381cabdff1aSopenharmony_ci if (avio_rl32(pb) != MKTAG('W', 'A', 'V', 'E')) { 382cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid format in RIFF header\n"); 383cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 384cabdff1aSopenharmony_ci } 385cabdff1aSopenharmony_ci 386cabdff1aSopenharmony_ci if (rf64 || bw64) { 387cabdff1aSopenharmony_ci if (avio_rl32(pb) != MKTAG('d', 's', '6', '4')) 388cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 389cabdff1aSopenharmony_ci size = avio_rl32(pb); 390cabdff1aSopenharmony_ci if (size < 24) 391cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 392cabdff1aSopenharmony_ci avio_rl64(pb); /* RIFF size */ 393cabdff1aSopenharmony_ci 394cabdff1aSopenharmony_ci data_size = avio_rl64(pb); 395cabdff1aSopenharmony_ci sample_count = avio_rl64(pb); 396cabdff1aSopenharmony_ci 397cabdff1aSopenharmony_ci if (data_size < 0 || sample_count < 0) { 398cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in " 399cabdff1aSopenharmony_ci "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n", 400cabdff1aSopenharmony_ci data_size, sample_count); 401cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 402cabdff1aSopenharmony_ci } 403cabdff1aSopenharmony_ci avio_skip(pb, size - 24); /* skip rest of ds64 chunk */ 404cabdff1aSopenharmony_ci 405cabdff1aSopenharmony_ci } 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci /* Create the audio stream now so that its index is always zero */ 408cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 409cabdff1aSopenharmony_ci if (!st) 410cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 411cabdff1aSopenharmony_ci 412cabdff1aSopenharmony_ci for (;;) { 413cabdff1aSopenharmony_ci AVStream *vst; 414cabdff1aSopenharmony_ci size = next_tag(pb, &tag, wav->rifx); 415cabdff1aSopenharmony_ci next_tag_ofs = avio_tell(pb) + size; 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci if (avio_feof(pb)) 418cabdff1aSopenharmony_ci break; 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci switch (tag) { 421cabdff1aSopenharmony_ci case MKTAG('f', 'm', 't', ' '): 422cabdff1aSopenharmony_ci /* only parse the first 'fmt ' tag found */ 423cabdff1aSopenharmony_ci if (!got_xma2 && !got_fmt && (ret = wav_parse_fmt_tag(s, size, st)) < 0) { 424cabdff1aSopenharmony_ci return ret; 425cabdff1aSopenharmony_ci } else if (got_fmt) 426cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n"); 427cabdff1aSopenharmony_ci 428cabdff1aSopenharmony_ci got_fmt = 1; 429cabdff1aSopenharmony_ci break; 430cabdff1aSopenharmony_ci case MKTAG('X', 'M', 'A', '2'): 431cabdff1aSopenharmony_ci /* only parse the first 'XMA2' tag found */ 432cabdff1aSopenharmony_ci if (!got_fmt && !got_xma2 && (ret = wav_parse_xma2_tag(s, size, st)) < 0) { 433cabdff1aSopenharmony_ci return ret; 434cabdff1aSopenharmony_ci } else if (got_xma2) 435cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "found more than one 'XMA2' tag\n"); 436cabdff1aSopenharmony_ci 437cabdff1aSopenharmony_ci got_xma2 = 1; 438cabdff1aSopenharmony_ci break; 439cabdff1aSopenharmony_ci case MKTAG('d', 'a', 't', 'a'): 440cabdff1aSopenharmony_ci if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) && !got_fmt && !got_xma2) { 441cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 442cabdff1aSopenharmony_ci "found no 'fmt ' tag before the 'data' tag\n"); 443cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 444cabdff1aSopenharmony_ci } 445cabdff1aSopenharmony_ci 446cabdff1aSopenharmony_ci if (rf64 || bw64) { 447cabdff1aSopenharmony_ci next_tag_ofs = wav->data_end = avio_tell(pb) + data_size; 448cabdff1aSopenharmony_ci } else if (size != 0xFFFFFFFF) { 449cabdff1aSopenharmony_ci data_size = size; 450cabdff1aSopenharmony_ci next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX; 451cabdff1aSopenharmony_ci } else { 452cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Ignoring maximum wav data size, " 453cabdff1aSopenharmony_ci "file may be invalid\n"); 454cabdff1aSopenharmony_ci data_size = 0; 455cabdff1aSopenharmony_ci next_tag_ofs = wav->data_end = INT64_MAX; 456cabdff1aSopenharmony_ci } 457cabdff1aSopenharmony_ci 458cabdff1aSopenharmony_ci data_ofs = avio_tell(pb); 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci /* don't look for footer metadata if we can't seek or if we don't 461cabdff1aSopenharmony_ci * know where the data tag ends 462cabdff1aSopenharmony_ci */ 463cabdff1aSopenharmony_ci if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || (!(rf64 && !bw64) && !size)) 464cabdff1aSopenharmony_ci goto break_loop; 465cabdff1aSopenharmony_ci break; 466cabdff1aSopenharmony_ci case MKTAG('f', 'a', 'c', 't'): 467cabdff1aSopenharmony_ci if (!sample_count) 468cabdff1aSopenharmony_ci sample_count = (!wav->rifx ? avio_rl32(pb) : avio_rb32(pb)); 469cabdff1aSopenharmony_ci break; 470cabdff1aSopenharmony_ci case MKTAG('b', 'e', 'x', 't'): 471cabdff1aSopenharmony_ci if ((ret = wav_parse_bext_tag(s, size)) < 0) 472cabdff1aSopenharmony_ci return ret; 473cabdff1aSopenharmony_ci break; 474cabdff1aSopenharmony_ci case MKTAG('S','M','V','0'): 475cabdff1aSopenharmony_ci if (!got_fmt) { 476cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'SMV0' tag\n"); 477cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 478cabdff1aSopenharmony_ci } 479cabdff1aSopenharmony_ci // SMV file, a wav file with video appended. 480cabdff1aSopenharmony_ci if (size != MKTAG('0','2','0','0')) { 481cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Unknown SMV version found\n"); 482cabdff1aSopenharmony_ci goto break_loop; 483cabdff1aSopenharmony_ci } 484cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "Found SMV data\n"); 485cabdff1aSopenharmony_ci wav->smv_given_first = 0; 486cabdff1aSopenharmony_ci vst = avformat_new_stream(s, NULL); 487cabdff1aSopenharmony_ci if (!vst) 488cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 489cabdff1aSopenharmony_ci wav->vst = vst; 490cabdff1aSopenharmony_ci avio_r8(pb); 491cabdff1aSopenharmony_ci vst->id = 1; 492cabdff1aSopenharmony_ci vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 493cabdff1aSopenharmony_ci vst->codecpar->codec_id = AV_CODEC_ID_SMVJPEG; 494cabdff1aSopenharmony_ci vst->codecpar->width = avio_rl24(pb); 495cabdff1aSopenharmony_ci vst->codecpar->height = avio_rl24(pb); 496cabdff1aSopenharmony_ci if ((ret = ff_alloc_extradata(vst->codecpar, 4)) < 0) { 497cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n"); 498cabdff1aSopenharmony_ci return ret; 499cabdff1aSopenharmony_ci } 500cabdff1aSopenharmony_ci size = avio_rl24(pb); 501cabdff1aSopenharmony_ci wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3; 502cabdff1aSopenharmony_ci avio_rl24(pb); 503cabdff1aSopenharmony_ci wav->smv_block_size = avio_rl24(pb); 504cabdff1aSopenharmony_ci if (!wav->smv_block_size) 505cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 506cabdff1aSopenharmony_ci avpriv_set_pts_info(vst, 32, 1, avio_rl24(pb)); 507cabdff1aSopenharmony_ci vst->duration = avio_rl24(pb); 508cabdff1aSopenharmony_ci avio_rl24(pb); 509cabdff1aSopenharmony_ci avio_rl24(pb); 510cabdff1aSopenharmony_ci wav->smv_frames_per_jpeg = avio_rl24(pb); 511cabdff1aSopenharmony_ci if (wav->smv_frames_per_jpeg > 65536) { 512cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "too many frames per jpeg\n"); 513cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 514cabdff1aSopenharmony_ci } 515cabdff1aSopenharmony_ci AV_WL32(vst->codecpar->extradata, wav->smv_frames_per_jpeg); 516cabdff1aSopenharmony_ci goto break_loop; 517cabdff1aSopenharmony_ci case MKTAG('L', 'I', 'S', 'T'): 518cabdff1aSopenharmony_ci case MKTAG('l', 'i', 's', 't'): 519cabdff1aSopenharmony_ci if (size < 4) { 520cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "too short LIST tag\n"); 521cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 522cabdff1aSopenharmony_ci } 523cabdff1aSopenharmony_ci switch (avio_rl32(pb)) { 524cabdff1aSopenharmony_ci case MKTAG('I', 'N', 'F', 'O'): 525cabdff1aSopenharmony_ci ff_read_riff_info(s, size - 4); 526cabdff1aSopenharmony_ci break; 527cabdff1aSopenharmony_ci case MKTAG('a', 'd', 't', 'l'): 528cabdff1aSopenharmony_ci if (s->nb_chapters > 0) { 529cabdff1aSopenharmony_ci while (avio_tell(pb) < next_tag_ofs && 530cabdff1aSopenharmony_ci !avio_feof(pb)) { 531cabdff1aSopenharmony_ci char cue_label[512]; 532cabdff1aSopenharmony_ci unsigned id, sub_size; 533cabdff1aSopenharmony_ci 534cabdff1aSopenharmony_ci if (avio_rl32(pb) != MKTAG('l', 'a', 'b', 'l')) 535cabdff1aSopenharmony_ci break; 536cabdff1aSopenharmony_ci 537cabdff1aSopenharmony_ci sub_size = avio_rl32(pb); 538cabdff1aSopenharmony_ci if (sub_size < 5) 539cabdff1aSopenharmony_ci break; 540cabdff1aSopenharmony_ci id = avio_rl32(pb); 541cabdff1aSopenharmony_ci avio_get_str(pb, sub_size - 4, cue_label, sizeof(cue_label)); 542cabdff1aSopenharmony_ci avio_skip(pb, avio_tell(pb) & 1); 543cabdff1aSopenharmony_ci 544cabdff1aSopenharmony_ci for (int i = 0; i < s->nb_chapters; i++) { 545cabdff1aSopenharmony_ci if (s->chapters[i]->id == id) { 546cabdff1aSopenharmony_ci av_dict_set(&s->chapters[i]->metadata, "title", cue_label, 0); 547cabdff1aSopenharmony_ci break; 548cabdff1aSopenharmony_ci } 549cabdff1aSopenharmony_ci } 550cabdff1aSopenharmony_ci } 551cabdff1aSopenharmony_ci } 552cabdff1aSopenharmony_ci break; 553cabdff1aSopenharmony_ci } 554cabdff1aSopenharmony_ci break; 555cabdff1aSopenharmony_ci case MKTAG('I', 'D', '3', ' '): 556cabdff1aSopenharmony_ci case MKTAG('i', 'd', '3', ' '): { 557cabdff1aSopenharmony_ci ID3v2ExtraMeta *id3v2_extra_meta; 558cabdff1aSopenharmony_ci ff_id3v2_read_dict(pb, &ffformatcontext(s)->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); 559cabdff1aSopenharmony_ci if (id3v2_extra_meta) { 560cabdff1aSopenharmony_ci ff_id3v2_parse_apic(s, id3v2_extra_meta); 561cabdff1aSopenharmony_ci ff_id3v2_parse_chapters(s, id3v2_extra_meta); 562cabdff1aSopenharmony_ci ff_id3v2_parse_priv(s, id3v2_extra_meta); 563cabdff1aSopenharmony_ci } 564cabdff1aSopenharmony_ci ff_id3v2_free_extra_meta(&id3v2_extra_meta); 565cabdff1aSopenharmony_ci } 566cabdff1aSopenharmony_ci break; 567cabdff1aSopenharmony_ci case MKTAG('c', 'u', 'e', ' '): 568cabdff1aSopenharmony_ci if (size >= 4 && got_fmt && st->codecpar->sample_rate > 0) { 569cabdff1aSopenharmony_ci AVRational tb = {1, st->codecpar->sample_rate}; 570cabdff1aSopenharmony_ci unsigned nb_cues = avio_rl32(pb); 571cabdff1aSopenharmony_ci 572cabdff1aSopenharmony_ci if (size >= nb_cues * 24LL + 4LL) { 573cabdff1aSopenharmony_ci for (int i = 0; i < nb_cues; i++) { 574cabdff1aSopenharmony_ci unsigned offset, id = avio_rl32(pb); 575cabdff1aSopenharmony_ci 576cabdff1aSopenharmony_ci if (avio_feof(pb)) 577cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci avio_skip(pb, 16); 580cabdff1aSopenharmony_ci offset = avio_rl32(pb); 581cabdff1aSopenharmony_ci 582cabdff1aSopenharmony_ci if (!avpriv_new_chapter(s, id, tb, offset, AV_NOPTS_VALUE, NULL)) 583cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 584cabdff1aSopenharmony_ci } 585cabdff1aSopenharmony_ci } 586cabdff1aSopenharmony_ci } 587cabdff1aSopenharmony_ci break; 588cabdff1aSopenharmony_ci } 589cabdff1aSopenharmony_ci 590cabdff1aSopenharmony_ci /* seek to next tag unless we know that we'll run into EOF */ 591cabdff1aSopenharmony_ci if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) || 592cabdff1aSopenharmony_ci wav_seek_tag(wav, pb, next_tag_ofs, SEEK_SET) < 0) { 593cabdff1aSopenharmony_ci break; 594cabdff1aSopenharmony_ci } 595cabdff1aSopenharmony_ci } 596cabdff1aSopenharmony_ci 597cabdff1aSopenharmony_cibreak_loop: 598cabdff1aSopenharmony_ci if (!got_fmt && !got_xma2) { 599cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "no 'fmt ' or 'XMA2' tag found\n"); 600cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 601cabdff1aSopenharmony_ci } 602cabdff1aSopenharmony_ci 603cabdff1aSopenharmony_ci if (data_ofs < 0) { 604cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "no 'data' tag found\n"); 605cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 606cabdff1aSopenharmony_ci } 607cabdff1aSopenharmony_ci 608cabdff1aSopenharmony_ci avio_seek(pb, data_ofs, SEEK_SET); 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_ci if (data_size > (INT64_MAX>>3)) { 611cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Data size %"PRId64" is too large\n", data_size); 612cabdff1aSopenharmony_ci data_size = 0; 613cabdff1aSopenharmony_ci } 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci if ( st->codecpar->bit_rate > 0 && data_size > 0 616cabdff1aSopenharmony_ci && st->codecpar->sample_rate > 0 617cabdff1aSopenharmony_ci && sample_count > 0 && st->codecpar->ch_layout.nb_channels > 1 618cabdff1aSopenharmony_ci && sample_count % st->codecpar->ch_layout.nb_channels == 0) { 619cabdff1aSopenharmony_ci if (fabs(8.0 * data_size * st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate / 620cabdff1aSopenharmony_ci sample_count /st->codecpar->bit_rate - 1.0) < 0.3) 621cabdff1aSopenharmony_ci sample_count /= st->codecpar->ch_layout.nb_channels; 622cabdff1aSopenharmony_ci } 623cabdff1aSopenharmony_ci 624cabdff1aSopenharmony_ci if (data_size > 0 && sample_count && st->codecpar->ch_layout.nb_channels && 625cabdff1aSopenharmony_ci (data_size << 3) / sample_count / st->codecpar->ch_layout.nb_channels > st->codecpar->bits_per_coded_sample + 1) { 626cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "ignoring wrong sample_count %"PRId64"\n", sample_count); 627cabdff1aSopenharmony_ci sample_count = 0; 628cabdff1aSopenharmony_ci } 629cabdff1aSopenharmony_ci 630cabdff1aSopenharmony_ci /* G.729 hack (for Ticket4577) 631cabdff1aSopenharmony_ci * FIXME: Come up with cleaner, more general solution */ 632cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_G729 && sample_count && (data_size << 3) > sample_count) { 633cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "ignoring wrong sample_count %"PRId64"\n", sample_count); 634cabdff1aSopenharmony_ci sample_count = 0; 635cabdff1aSopenharmony_ci } 636cabdff1aSopenharmony_ci 637cabdff1aSopenharmony_ci if (!sample_count || av_get_exact_bits_per_sample(st->codecpar->codec_id) > 0) 638cabdff1aSopenharmony_ci if ( st->codecpar->ch_layout.nb_channels 639cabdff1aSopenharmony_ci && data_size 640cabdff1aSopenharmony_ci && av_get_bits_per_sample(st->codecpar->codec_id) 641cabdff1aSopenharmony_ci && wav->data_end <= avio_size(pb)) 642cabdff1aSopenharmony_ci sample_count = (data_size << 3) 643cabdff1aSopenharmony_ci / 644cabdff1aSopenharmony_ci (st->codecpar->ch_layout.nb_channels * (uint64_t)av_get_bits_per_sample(st->codecpar->codec_id)); 645cabdff1aSopenharmony_ci 646cabdff1aSopenharmony_ci if (sample_count) 647cabdff1aSopenharmony_ci st->duration = sample_count; 648cabdff1aSopenharmony_ci 649cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S32LE && 650cabdff1aSopenharmony_ci st->codecpar->block_align == st->codecpar->ch_layout.nb_channels * 4 && 651cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample == 32 && 652cabdff1aSopenharmony_ci st->codecpar->extradata_size == 2 && 653cabdff1aSopenharmony_ci AV_RL16(st->codecpar->extradata) == 1) { 654cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_PCM_F16LE; 655cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample = 16; 656cabdff1aSopenharmony_ci } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE && 657cabdff1aSopenharmony_ci st->codecpar->block_align == st->codecpar->ch_layout.nb_channels * 4 && 658cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample == 24) { 659cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_PCM_F24LE; 660cabdff1aSopenharmony_ci } else if (st->codecpar->codec_id == AV_CODEC_ID_XMA1 || 661cabdff1aSopenharmony_ci st->codecpar->codec_id == AV_CODEC_ID_XMA2) { 662cabdff1aSopenharmony_ci st->codecpar->block_align = 2048; 663cabdff1aSopenharmony_ci } else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS && st->codecpar->ch_layout.nb_channels > 2 && 664cabdff1aSopenharmony_ci st->codecpar->block_align < INT_MAX / st->codecpar->ch_layout.nb_channels) { 665cabdff1aSopenharmony_ci st->codecpar->block_align *= st->codecpar->ch_layout.nb_channels; 666cabdff1aSopenharmony_ci } 667cabdff1aSopenharmony_ci 668cabdff1aSopenharmony_ci ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); 669cabdff1aSopenharmony_ci ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv); 670cabdff1aSopenharmony_ci 671cabdff1aSopenharmony_ci set_spdif(s, wav); 672cabdff1aSopenharmony_ci 673cabdff1aSopenharmony_ci#ifdef OHOS_OPT_COMPAT 674cabdff1aSopenharmony_ci if (ffformatcontext(s)->id3v2_meta && s->metadata) { 675cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Discarding fmt metadata because ID3 tag is found.\n"); 676cabdff1aSopenharmony_ci av_dict_free(&s->metadata); 677cabdff1aSopenharmony_ci s->metadata = NULL; 678cabdff1aSopenharmony_ci } 679cabdff1aSopenharmony_ci#endif 680cabdff1aSopenharmony_ci 681cabdff1aSopenharmony_ci return 0; 682cabdff1aSopenharmony_ci} 683cabdff1aSopenharmony_ci 684cabdff1aSopenharmony_ci/** 685cabdff1aSopenharmony_ci * Find chunk with w64 GUID by skipping over other chunks. 686cabdff1aSopenharmony_ci * @return the size of the found chunk 687cabdff1aSopenharmony_ci */ 688cabdff1aSopenharmony_cistatic int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16]) 689cabdff1aSopenharmony_ci{ 690cabdff1aSopenharmony_ci uint8_t guid[16]; 691cabdff1aSopenharmony_ci int64_t size; 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci while (!avio_feof(pb)) { 694cabdff1aSopenharmony_ci avio_read(pb, guid, 16); 695cabdff1aSopenharmony_ci size = avio_rl64(pb); 696cabdff1aSopenharmony_ci if (size <= 24 || size > INT64_MAX - 8) 697cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 698cabdff1aSopenharmony_ci if (!memcmp(guid, guid1, 16)) 699cabdff1aSopenharmony_ci return size; 700cabdff1aSopenharmony_ci avio_skip(pb, FFALIGN(size, INT64_C(8)) - 24); 701cabdff1aSopenharmony_ci } 702cabdff1aSopenharmony_ci return AVERROR_EOF; 703cabdff1aSopenharmony_ci} 704cabdff1aSopenharmony_ci 705cabdff1aSopenharmony_cistatic int wav_read_packet(AVFormatContext *s, AVPacket *pkt) 706cabdff1aSopenharmony_ci{ 707cabdff1aSopenharmony_ci int ret, size; 708cabdff1aSopenharmony_ci int64_t left; 709cabdff1aSopenharmony_ci WAVDemuxContext *wav = s->priv_data; 710cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 711cabdff1aSopenharmony_ci 712cabdff1aSopenharmony_ci if (CONFIG_SPDIF_DEMUXER && wav->spdif == 1) 713cabdff1aSopenharmony_ci return ff_spdif_read_packet(s, pkt); 714cabdff1aSopenharmony_ci 715cabdff1aSopenharmony_ci if (wav->smv_data_ofs > 0) { 716cabdff1aSopenharmony_ci int64_t audio_dts, video_dts; 717cabdff1aSopenharmony_ci AVStream *vst = wav->vst; 718cabdff1aSopenharmony_cismv_retry: 719cabdff1aSopenharmony_ci audio_dts = (int32_t)ffstream( st)->cur_dts; 720cabdff1aSopenharmony_ci video_dts = (int32_t)ffstream(vst)->cur_dts; 721cabdff1aSopenharmony_ci 722cabdff1aSopenharmony_ci if (audio_dts != AV_NOPTS_VALUE && video_dts != AV_NOPTS_VALUE) { 723cabdff1aSopenharmony_ci /*We always return a video frame first to get the pixel format first*/ 724cabdff1aSopenharmony_ci wav->smv_last_stream = wav->smv_given_first ? 725cabdff1aSopenharmony_ci av_compare_ts(video_dts, vst->time_base, 726cabdff1aSopenharmony_ci audio_dts, st->time_base) > 0 : 0; 727cabdff1aSopenharmony_ci wav->smv_given_first = 1; 728cabdff1aSopenharmony_ci } 729cabdff1aSopenharmony_ci wav->smv_last_stream = !wav->smv_last_stream; 730cabdff1aSopenharmony_ci wav->smv_last_stream |= wav->audio_eof; 731cabdff1aSopenharmony_ci wav->smv_last_stream &= !wav->smv_eof; 732cabdff1aSopenharmony_ci if (wav->smv_last_stream) { 733cabdff1aSopenharmony_ci uint64_t old_pos = avio_tell(s->pb); 734cabdff1aSopenharmony_ci uint64_t new_pos = wav->smv_data_ofs + 735cabdff1aSopenharmony_ci wav->smv_block * (int64_t)wav->smv_block_size; 736cabdff1aSopenharmony_ci if (avio_seek(s->pb, new_pos, SEEK_SET) < 0) { 737cabdff1aSopenharmony_ci ret = AVERROR_EOF; 738cabdff1aSopenharmony_ci goto smv_out; 739cabdff1aSopenharmony_ci } 740cabdff1aSopenharmony_ci size = avio_rl24(s->pb); 741cabdff1aSopenharmony_ci if (size > wav->smv_block_size) { 742cabdff1aSopenharmony_ci ret = AVERROR_EOF; 743cabdff1aSopenharmony_ci goto smv_out; 744cabdff1aSopenharmony_ci } 745cabdff1aSopenharmony_ci ret = av_get_packet(s->pb, pkt, size); 746cabdff1aSopenharmony_ci if (ret < 0) 747cabdff1aSopenharmony_ci goto smv_out; 748cabdff1aSopenharmony_ci pkt->pos -= 3; 749cabdff1aSopenharmony_ci pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg; 750cabdff1aSopenharmony_ci pkt->duration = wav->smv_frames_per_jpeg; 751cabdff1aSopenharmony_ci wav->smv_block++; 752cabdff1aSopenharmony_ci 753cabdff1aSopenharmony_ci pkt->stream_index = vst->index; 754cabdff1aSopenharmony_cismv_out: 755cabdff1aSopenharmony_ci avio_seek(s->pb, old_pos, SEEK_SET); 756cabdff1aSopenharmony_ci if (ret == AVERROR_EOF) { 757cabdff1aSopenharmony_ci wav->smv_eof = 1; 758cabdff1aSopenharmony_ci goto smv_retry; 759cabdff1aSopenharmony_ci } 760cabdff1aSopenharmony_ci return ret; 761cabdff1aSopenharmony_ci } 762cabdff1aSopenharmony_ci } 763cabdff1aSopenharmony_ci 764cabdff1aSopenharmony_ci left = wav->data_end - avio_tell(s->pb); 765cabdff1aSopenharmony_ci if (wav->ignore_length) 766cabdff1aSopenharmony_ci left = INT_MAX; 767cabdff1aSopenharmony_ci if (left <= 0) { 768cabdff1aSopenharmony_ci if (CONFIG_W64_DEMUXER && wav->w64) 769cabdff1aSopenharmony_ci left = find_guid(s->pb, ff_w64_guid_data) - 24; 770cabdff1aSopenharmony_ci else 771cabdff1aSopenharmony_ci left = find_tag(wav, s->pb, MKTAG('d', 'a', 't', 'a')); 772cabdff1aSopenharmony_ci if (left < 0) { 773cabdff1aSopenharmony_ci wav->audio_eof = 1; 774cabdff1aSopenharmony_ci if (wav->smv_data_ofs > 0 && !wav->smv_eof) 775cabdff1aSopenharmony_ci goto smv_retry; 776cabdff1aSopenharmony_ci return AVERROR_EOF; 777cabdff1aSopenharmony_ci } 778cabdff1aSopenharmony_ci if (INT64_MAX - left < avio_tell(s->pb)) 779cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 780cabdff1aSopenharmony_ci wav->data_end = avio_tell(s->pb) + left; 781cabdff1aSopenharmony_ci } 782cabdff1aSopenharmony_ci 783cabdff1aSopenharmony_ci size = wav->max_size; 784cabdff1aSopenharmony_ci if (st->codecpar->block_align > 1) { 785cabdff1aSopenharmony_ci if (size < st->codecpar->block_align) 786cabdff1aSopenharmony_ci size = st->codecpar->block_align; 787cabdff1aSopenharmony_ci size = (size / st->codecpar->block_align) * st->codecpar->block_align; 788cabdff1aSopenharmony_ci } 789cabdff1aSopenharmony_ci size = FFMIN(size, left); 790cabdff1aSopenharmony_ci ret = av_get_packet(s->pb, pkt, size); 791cabdff1aSopenharmony_ci if (ret < 0) 792cabdff1aSopenharmony_ci return ret; 793cabdff1aSopenharmony_ci pkt->stream_index = 0; 794cabdff1aSopenharmony_ci 795cabdff1aSopenharmony_ci return ret; 796cabdff1aSopenharmony_ci} 797cabdff1aSopenharmony_ci 798cabdff1aSopenharmony_cistatic int wav_read_seek(AVFormatContext *s, 799cabdff1aSopenharmony_ci int stream_index, int64_t timestamp, int flags) 800cabdff1aSopenharmony_ci{ 801cabdff1aSopenharmony_ci WAVDemuxContext *wav = s->priv_data; 802cabdff1aSopenharmony_ci AVStream *ast = s->streams[0], *vst = wav->vst; 803cabdff1aSopenharmony_ci wav->smv_eof = 0; 804cabdff1aSopenharmony_ci wav->audio_eof = 0; 805cabdff1aSopenharmony_ci 806cabdff1aSopenharmony_ci if (stream_index != 0 && (!vst || stream_index != vst->index)) 807cabdff1aSopenharmony_ci return AVERROR(EINVAL); 808cabdff1aSopenharmony_ci if (wav->smv_data_ofs > 0) { 809cabdff1aSopenharmony_ci int64_t smv_timestamp = timestamp; 810cabdff1aSopenharmony_ci if (stream_index == 0) 811cabdff1aSopenharmony_ci smv_timestamp = av_rescale_q(timestamp, ast->time_base, vst->time_base); 812cabdff1aSopenharmony_ci else 813cabdff1aSopenharmony_ci timestamp = av_rescale_q(smv_timestamp, vst->time_base, ast->time_base); 814cabdff1aSopenharmony_ci if (wav->smv_frames_per_jpeg > 0) { 815cabdff1aSopenharmony_ci wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg; 816cabdff1aSopenharmony_ci } 817cabdff1aSopenharmony_ci } 818cabdff1aSopenharmony_ci 819cabdff1aSopenharmony_ci switch (ast->codecpar->codec_id) { 820cabdff1aSopenharmony_ci case AV_CODEC_ID_MP2: 821cabdff1aSopenharmony_ci case AV_CODEC_ID_MP3: 822cabdff1aSopenharmony_ci case AV_CODEC_ID_AC3: 823cabdff1aSopenharmony_ci case AV_CODEC_ID_DTS: 824cabdff1aSopenharmony_ci case AV_CODEC_ID_XMA2: 825cabdff1aSopenharmony_ci /* use generic seeking with dynamically generated indexes */ 826cabdff1aSopenharmony_ci return -1; 827cabdff1aSopenharmony_ci default: 828cabdff1aSopenharmony_ci break; 829cabdff1aSopenharmony_ci } 830cabdff1aSopenharmony_ci return ff_pcm_read_seek(s, 0, timestamp, flags); 831cabdff1aSopenharmony_ci} 832cabdff1aSopenharmony_ci 833cabdff1aSopenharmony_cistatic const AVClass wav_demuxer_class = { 834cabdff1aSopenharmony_ci .class_name = "WAV demuxer", 835cabdff1aSopenharmony_ci .item_name = av_default_item_name, 836cabdff1aSopenharmony_ci .option = demux_options, 837cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 838cabdff1aSopenharmony_ci}; 839cabdff1aSopenharmony_ciconst AVInputFormat ff_wav_demuxer = { 840cabdff1aSopenharmony_ci .name = "wav", 841cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("WAV / WAVE (Waveform Audio)"), 842cabdff1aSopenharmony_ci .priv_data_size = sizeof(WAVDemuxContext), 843cabdff1aSopenharmony_ci .read_probe = wav_probe, 844cabdff1aSopenharmony_ci .read_header = wav_read_header, 845cabdff1aSopenharmony_ci .read_packet = wav_read_packet, 846cabdff1aSopenharmony_ci .read_seek = wav_read_seek, 847cabdff1aSopenharmony_ci .flags = AVFMT_GENERIC_INDEX, 848cabdff1aSopenharmony_ci .codec_tag = ff_wav_codec_tags_list, 849cabdff1aSopenharmony_ci .priv_class = &wav_demuxer_class, 850cabdff1aSopenharmony_ci}; 851cabdff1aSopenharmony_ci#endif /* CONFIG_WAV_DEMUXER */ 852cabdff1aSopenharmony_ci 853cabdff1aSopenharmony_ci#if CONFIG_W64_DEMUXER 854cabdff1aSopenharmony_cistatic int w64_probe(const AVProbeData *p) 855cabdff1aSopenharmony_ci{ 856cabdff1aSopenharmony_ci if (p->buf_size <= 40) 857cabdff1aSopenharmony_ci return 0; 858cabdff1aSopenharmony_ci if (!memcmp(p->buf, ff_w64_guid_riff, 16) && 859cabdff1aSopenharmony_ci !memcmp(p->buf + 24, ff_w64_guid_wave, 16)) 860cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 861cabdff1aSopenharmony_ci else 862cabdff1aSopenharmony_ci return 0; 863cabdff1aSopenharmony_ci} 864cabdff1aSopenharmony_ci 865cabdff1aSopenharmony_cistatic int w64_read_header(AVFormatContext *s) 866cabdff1aSopenharmony_ci{ 867cabdff1aSopenharmony_ci int64_t size, data_ofs = 0; 868cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 869cabdff1aSopenharmony_ci WAVDemuxContext *wav = s->priv_data; 870cabdff1aSopenharmony_ci AVStream *st; 871cabdff1aSopenharmony_ci uint8_t guid[16]; 872cabdff1aSopenharmony_ci int ret; 873cabdff1aSopenharmony_ci 874cabdff1aSopenharmony_ci if (avio_read(pb, guid, 16) != 16 || memcmp(guid, ff_w64_guid_riff, 16)) 875cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 876cabdff1aSopenharmony_ci 877cabdff1aSopenharmony_ci /* riff + wave + fmt + sizes */ 878cabdff1aSopenharmony_ci if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) 879cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 880cabdff1aSopenharmony_ci 881cabdff1aSopenharmony_ci avio_read(pb, guid, 16); 882cabdff1aSopenharmony_ci if (memcmp(guid, ff_w64_guid_wave, 16)) { 883cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "could not find wave guid\n"); 884cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 885cabdff1aSopenharmony_ci } 886cabdff1aSopenharmony_ci 887cabdff1aSopenharmony_ci wav->w64 = 1; 888cabdff1aSopenharmony_ci 889cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 890cabdff1aSopenharmony_ci if (!st) 891cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 892cabdff1aSopenharmony_ci 893cabdff1aSopenharmony_ci while (!avio_feof(pb)) { 894cabdff1aSopenharmony_ci if (avio_read(pb, guid, 16) != 16) 895cabdff1aSopenharmony_ci break; 896cabdff1aSopenharmony_ci size = avio_rl64(pb); 897cabdff1aSopenharmony_ci if (size <= 24 || INT64_MAX - size < avio_tell(pb)) 898cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 899cabdff1aSopenharmony_ci 900cabdff1aSopenharmony_ci if (!memcmp(guid, ff_w64_guid_fmt, 16)) { 901cabdff1aSopenharmony_ci /* subtract chunk header size - normal wav file doesn't count it */ 902cabdff1aSopenharmony_ci ret = ff_get_wav_header(s, pb, st->codecpar, size - 24, 0); 903cabdff1aSopenharmony_ci if (ret < 0) 904cabdff1aSopenharmony_ci return ret; 905cabdff1aSopenharmony_ci avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); 906cabdff1aSopenharmony_ci 907cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 908cabdff1aSopenharmony_ci } else if (!memcmp(guid, ff_w64_guid_fact, 16)) { 909cabdff1aSopenharmony_ci int64_t samples; 910cabdff1aSopenharmony_ci 911cabdff1aSopenharmony_ci samples = avio_rl64(pb); 912cabdff1aSopenharmony_ci if (samples > 0) 913cabdff1aSopenharmony_ci st->duration = samples; 914cabdff1aSopenharmony_ci avio_skip(pb, FFALIGN(size, INT64_C(8)) - 32); 915cabdff1aSopenharmony_ci } else if (!memcmp(guid, ff_w64_guid_data, 16)) { 916cabdff1aSopenharmony_ci wav->data_end = avio_tell(pb) + size - 24; 917cabdff1aSopenharmony_ci 918cabdff1aSopenharmony_ci data_ofs = avio_tell(pb); 919cabdff1aSopenharmony_ci if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) 920cabdff1aSopenharmony_ci break; 921cabdff1aSopenharmony_ci 922cabdff1aSopenharmony_ci avio_skip(pb, size - 24); 923cabdff1aSopenharmony_ci } else if (!memcmp(guid, ff_w64_guid_summarylist, 16)) { 924cabdff1aSopenharmony_ci int64_t start, end, cur; 925cabdff1aSopenharmony_ci uint32_t count, chunk_size, i; 926cabdff1aSopenharmony_ci int64_t filesize = avio_size(s->pb); 927cabdff1aSopenharmony_ci 928cabdff1aSopenharmony_ci start = avio_tell(pb); 929cabdff1aSopenharmony_ci end = start + FFALIGN(size, INT64_C(8)) - 24; 930cabdff1aSopenharmony_ci count = avio_rl32(pb); 931cabdff1aSopenharmony_ci 932cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 933cabdff1aSopenharmony_ci char chunk_key[5], *value; 934cabdff1aSopenharmony_ci 935cabdff1aSopenharmony_ci if (avio_feof(pb) || (cur = avio_tell(pb)) < 0 || cur > end - 8 /* = tag + size */) 936cabdff1aSopenharmony_ci break; 937cabdff1aSopenharmony_ci 938cabdff1aSopenharmony_ci chunk_key[4] = 0; 939cabdff1aSopenharmony_ci avio_read(pb, chunk_key, 4); 940cabdff1aSopenharmony_ci chunk_size = avio_rl32(pb); 941cabdff1aSopenharmony_ci if (chunk_size == UINT32_MAX || (filesize >= 0 && chunk_size > filesize)) 942cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 943cabdff1aSopenharmony_ci 944cabdff1aSopenharmony_ci value = av_malloc(chunk_size + 1); 945cabdff1aSopenharmony_ci if (!value) 946cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 947cabdff1aSopenharmony_ci 948cabdff1aSopenharmony_ci ret = avio_get_str16le(pb, chunk_size, value, chunk_size); 949cabdff1aSopenharmony_ci if (ret < 0) { 950cabdff1aSopenharmony_ci av_free(value); 951cabdff1aSopenharmony_ci return ret; 952cabdff1aSopenharmony_ci } 953cabdff1aSopenharmony_ci avio_skip(pb, chunk_size - ret); 954cabdff1aSopenharmony_ci 955cabdff1aSopenharmony_ci av_dict_set(&s->metadata, chunk_key, value, AV_DICT_DONT_STRDUP_VAL); 956cabdff1aSopenharmony_ci } 957cabdff1aSopenharmony_ci 958cabdff1aSopenharmony_ci avio_skip(pb, end - avio_tell(pb)); 959cabdff1aSopenharmony_ci } else { 960cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "unknown guid: "FF_PRI_GUID"\n", FF_ARG_GUID(guid)); 961cabdff1aSopenharmony_ci avio_skip(pb, FFALIGN(size, INT64_C(8)) - 24); 962cabdff1aSopenharmony_ci } 963cabdff1aSopenharmony_ci } 964cabdff1aSopenharmony_ci 965cabdff1aSopenharmony_ci if (!data_ofs) 966cabdff1aSopenharmony_ci return AVERROR_EOF; 967cabdff1aSopenharmony_ci 968cabdff1aSopenharmony_ci ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); 969cabdff1aSopenharmony_ci ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv); 970cabdff1aSopenharmony_ci 971cabdff1aSopenharmony_ci handle_stream_probing(st); 972cabdff1aSopenharmony_ci ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; 973cabdff1aSopenharmony_ci 974cabdff1aSopenharmony_ci avio_seek(pb, data_ofs, SEEK_SET); 975cabdff1aSopenharmony_ci 976cabdff1aSopenharmony_ci set_spdif(s, wav); 977cabdff1aSopenharmony_ci 978cabdff1aSopenharmony_ci return 0; 979cabdff1aSopenharmony_ci} 980cabdff1aSopenharmony_ci 981cabdff1aSopenharmony_cistatic const AVClass w64_demuxer_class = { 982cabdff1aSopenharmony_ci .class_name = "W64 demuxer", 983cabdff1aSopenharmony_ci .item_name = av_default_item_name, 984cabdff1aSopenharmony_ci .option = &demux_options[W64_DEMUXER_OPTIONS_OFFSET], 985cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 986cabdff1aSopenharmony_ci}; 987cabdff1aSopenharmony_ci 988cabdff1aSopenharmony_ciconst AVInputFormat ff_w64_demuxer = { 989cabdff1aSopenharmony_ci .name = "w64", 990cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Sony Wave64"), 991cabdff1aSopenharmony_ci .priv_data_size = sizeof(WAVDemuxContext), 992cabdff1aSopenharmony_ci .read_probe = w64_probe, 993cabdff1aSopenharmony_ci .read_header = w64_read_header, 994cabdff1aSopenharmony_ci .read_packet = wav_read_packet, 995cabdff1aSopenharmony_ci .read_seek = wav_read_seek, 996cabdff1aSopenharmony_ci .flags = AVFMT_GENERIC_INDEX, 997cabdff1aSopenharmony_ci .codec_tag = ff_wav_codec_tags_list, 998cabdff1aSopenharmony_ci .priv_class = &w64_demuxer_class, 999cabdff1aSopenharmony_ci}; 1000cabdff1aSopenharmony_ci#endif /* CONFIG_W64_DEMUXER */ 1001