1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * WavPack demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2006,2011 Konstantin Shishkov 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 23cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 24cabdff1aSopenharmony_ci#include "libavutil/dict.h" 25cabdff1aSopenharmony_ci#include "avformat.h" 26cabdff1aSopenharmony_ci#include "internal.h" 27cabdff1aSopenharmony_ci#include "apetag.h" 28cabdff1aSopenharmony_ci#include "id3v1.h" 29cabdff1aSopenharmony_ci#include "wv.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_cienum WV_FLAGS { 32cabdff1aSopenharmony_ci WV_MONO = 0x0004, 33cabdff1aSopenharmony_ci WV_HYBRID = 0x0008, 34cabdff1aSopenharmony_ci WV_JOINT = 0x0010, 35cabdff1aSopenharmony_ci WV_CROSSD = 0x0020, 36cabdff1aSopenharmony_ci WV_HSHAPE = 0x0040, 37cabdff1aSopenharmony_ci WV_FLOAT = 0x0080, 38cabdff1aSopenharmony_ci WV_INT32 = 0x0100, 39cabdff1aSopenharmony_ci WV_HBR = 0x0200, 40cabdff1aSopenharmony_ci WV_HBAL = 0x0400, 41cabdff1aSopenharmony_ci WV_MCINIT = 0x0800, 42cabdff1aSopenharmony_ci WV_MCEND = 0x1000, 43cabdff1aSopenharmony_ci WV_DSD = 0x80000000, 44cabdff1aSopenharmony_ci}; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic const int wv_rates[16] = { 47cabdff1aSopenharmony_ci 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, 48cabdff1aSopenharmony_ci 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1 49cabdff1aSopenharmony_ci}; 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_citypedef struct WVContext { 52cabdff1aSopenharmony_ci uint8_t block_header[WV_HEADER_SIZE]; 53cabdff1aSopenharmony_ci WvHeader header; 54cabdff1aSopenharmony_ci int rate, chan, bpp; 55cabdff1aSopenharmony_ci uint32_t chmask; 56cabdff1aSopenharmony_ci int multichannel; 57cabdff1aSopenharmony_ci int block_parsed; 58cabdff1aSopenharmony_ci int64_t pos; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci int64_t apetag_start; 61cabdff1aSopenharmony_ci} WVContext; 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_cistatic int wv_probe(const AVProbeData *p) 64cabdff1aSopenharmony_ci{ 65cabdff1aSopenharmony_ci /* check file header */ 66cabdff1aSopenharmony_ci if (p->buf_size <= 32) 67cabdff1aSopenharmony_ci return 0; 68cabdff1aSopenharmony_ci if (AV_RL32(&p->buf[0]) == MKTAG('w', 'v', 'p', 'k') && 69cabdff1aSopenharmony_ci AV_RL32(&p->buf[4]) >= 24 && 70cabdff1aSopenharmony_ci AV_RL32(&p->buf[4]) <= WV_BLOCK_LIMIT && 71cabdff1aSopenharmony_ci AV_RL16(&p->buf[8]) >= 0x402 && 72cabdff1aSopenharmony_ci AV_RL16(&p->buf[8]) <= 0x410) 73cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 74cabdff1aSopenharmony_ci else 75cabdff1aSopenharmony_ci return 0; 76cabdff1aSopenharmony_ci} 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_cistatic int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb) 79cabdff1aSopenharmony_ci{ 80cabdff1aSopenharmony_ci WVContext *wc = ctx->priv_data; 81cabdff1aSopenharmony_ci int ret; 82cabdff1aSopenharmony_ci int rate, bpp, chan; 83cabdff1aSopenharmony_ci uint32_t chmask, flags; 84cabdff1aSopenharmony_ci unsigned rate_x; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci wc->pos = avio_tell(pb); 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci /* don't return bogus packets with the ape tag data */ 89cabdff1aSopenharmony_ci if (wc->apetag_start && wc->pos >= wc->apetag_start) 90cabdff1aSopenharmony_ci return AVERROR_EOF; 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci ret = avio_read(pb, wc->block_header, WV_HEADER_SIZE); 93cabdff1aSopenharmony_ci if (ret != WV_HEADER_SIZE) 94cabdff1aSopenharmony_ci return (ret < 0) ? ret : AVERROR_EOF; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci ret = ff_wv_parse_header(&wc->header, wc->block_header); 97cabdff1aSopenharmony_ci if (ret < 0) { 98cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Invalid block header.\n"); 99cabdff1aSopenharmony_ci return ret; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci if (wc->header.version < 0x402 || wc->header.version > 0x410) { 103cabdff1aSopenharmony_ci avpriv_report_missing_feature(ctx, "WV version 0x%03X", 104cabdff1aSopenharmony_ci wc->header.version); 105cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci /* Blocks with zero samples don't contain actual audio information 109cabdff1aSopenharmony_ci * and should be ignored */ 110cabdff1aSopenharmony_ci if (!wc->header.samples) 111cabdff1aSopenharmony_ci return 0; 112cabdff1aSopenharmony_ci // parse flags 113cabdff1aSopenharmony_ci flags = wc->header.flags; 114cabdff1aSopenharmony_ci rate_x = (flags & WV_DSD) ? 4 : 1; 115cabdff1aSopenharmony_ci bpp = (flags & WV_DSD) ? 0 : ((flags & 3) + 1) << 3; 116cabdff1aSopenharmony_ci chan = 1 + !(flags & WV_MONO); 117cabdff1aSopenharmony_ci chmask = flags & WV_MONO ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; 118cabdff1aSopenharmony_ci rate = wv_rates[(flags >> 23) & 0xF]; 119cabdff1aSopenharmony_ci wc->multichannel = !(wc->header.initial && wc->header.final); 120cabdff1aSopenharmony_ci if (wc->multichannel) { 121cabdff1aSopenharmony_ci chan = wc->chan; 122cabdff1aSopenharmony_ci chmask = wc->chmask; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci if ((rate == -1 || !chan || flags & WV_DSD) && !wc->block_parsed) { 125cabdff1aSopenharmony_ci int64_t block_end = avio_tell(pb) + wc->header.blocksize; 126cabdff1aSopenharmony_ci if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) { 127cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 128cabdff1aSopenharmony_ci "Cannot determine additional parameters\n"); 129cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci while (avio_tell(pb) < block_end && !avio_feof(pb)) { 132cabdff1aSopenharmony_ci int id, size; 133cabdff1aSopenharmony_ci id = avio_r8(pb); 134cabdff1aSopenharmony_ci size = (id & 0x80) ? avio_rl24(pb) : avio_r8(pb); 135cabdff1aSopenharmony_ci size <<= 1; 136cabdff1aSopenharmony_ci if (id & 0x40) 137cabdff1aSopenharmony_ci size--; 138cabdff1aSopenharmony_ci switch (id & 0x3F) { 139cabdff1aSopenharmony_ci case 0xD: 140cabdff1aSopenharmony_ci if (size <= 1) { 141cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 142cabdff1aSopenharmony_ci "Insufficient channel information\n"); 143cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci chan = avio_r8(pb); 146cabdff1aSopenharmony_ci switch (size - 2) { 147cabdff1aSopenharmony_ci case 0: 148cabdff1aSopenharmony_ci chmask = avio_r8(pb); 149cabdff1aSopenharmony_ci break; 150cabdff1aSopenharmony_ci case 1: 151cabdff1aSopenharmony_ci chmask = avio_rl16(pb); 152cabdff1aSopenharmony_ci break; 153cabdff1aSopenharmony_ci case 2: 154cabdff1aSopenharmony_ci chmask = avio_rl24(pb); 155cabdff1aSopenharmony_ci break; 156cabdff1aSopenharmony_ci case 3: 157cabdff1aSopenharmony_ci chmask = avio_rl32(pb); 158cabdff1aSopenharmony_ci break; 159cabdff1aSopenharmony_ci case 4: 160cabdff1aSopenharmony_ci avio_skip(pb, 1); 161cabdff1aSopenharmony_ci chan |= (avio_r8(pb) & 0xF) << 8; 162cabdff1aSopenharmony_ci chan += 1; 163cabdff1aSopenharmony_ci chmask = avio_rl24(pb); 164cabdff1aSopenharmony_ci break; 165cabdff1aSopenharmony_ci case 5: 166cabdff1aSopenharmony_ci avio_skip(pb, 1); 167cabdff1aSopenharmony_ci chan |= (avio_r8(pb) & 0xF) << 8; 168cabdff1aSopenharmony_ci chan += 1; 169cabdff1aSopenharmony_ci chmask = avio_rl32(pb); 170cabdff1aSopenharmony_ci break; 171cabdff1aSopenharmony_ci default: 172cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 173cabdff1aSopenharmony_ci "Invalid channel info size %d\n", size); 174cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci break; 177cabdff1aSopenharmony_ci case 0xE: 178cabdff1aSopenharmony_ci if (size <= 1) { 179cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 180cabdff1aSopenharmony_ci "Invalid DSD block\n"); 181cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 182cabdff1aSopenharmony_ci } 183cabdff1aSopenharmony_ci rate_x = 1U << (avio_r8(pb) & 0x1f); 184cabdff1aSopenharmony_ci if (size) 185cabdff1aSopenharmony_ci avio_skip(pb, size-1); 186cabdff1aSopenharmony_ci break; 187cabdff1aSopenharmony_ci case 0x27: 188cabdff1aSopenharmony_ci rate = avio_rl24(pb); 189cabdff1aSopenharmony_ci break; 190cabdff1aSopenharmony_ci default: 191cabdff1aSopenharmony_ci avio_skip(pb, size); 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci if (id & 0x40) 194cabdff1aSopenharmony_ci avio_skip(pb, 1); 195cabdff1aSopenharmony_ci } 196cabdff1aSopenharmony_ci if (rate == -1 || rate * (uint64_t)rate_x >= INT_MAX) { 197cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 198cabdff1aSopenharmony_ci "Cannot determine custom sampling rate\n"); 199cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci avio_seek(pb, block_end - wc->header.blocksize, SEEK_SET); 202cabdff1aSopenharmony_ci } 203cabdff1aSopenharmony_ci if (!wc->bpp) 204cabdff1aSopenharmony_ci wc->bpp = bpp; 205cabdff1aSopenharmony_ci if (!wc->chan) 206cabdff1aSopenharmony_ci wc->chan = chan; 207cabdff1aSopenharmony_ci if (!wc->chmask) 208cabdff1aSopenharmony_ci wc->chmask = chmask; 209cabdff1aSopenharmony_ci if (!wc->rate) 210cabdff1aSopenharmony_ci wc->rate = rate * rate_x; 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci if (flags && bpp != wc->bpp) { 213cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 214cabdff1aSopenharmony_ci "Bits per sample differ, this block: %i, header block: %i\n", 215cabdff1aSopenharmony_ci bpp, wc->bpp); 216cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 217cabdff1aSopenharmony_ci } 218cabdff1aSopenharmony_ci if (flags && !wc->multichannel && chan != wc->chan) { 219cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 220cabdff1aSopenharmony_ci "Channels differ, this block: %i, header block: %i\n", 221cabdff1aSopenharmony_ci chan, wc->chan); 222cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci if (flags && rate != -1 && !(flags & WV_DSD) && rate * rate_x != wc->rate) { 225cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 226cabdff1aSopenharmony_ci "Sampling rate differ, this block: %i, header block: %i\n", 227cabdff1aSopenharmony_ci rate * rate_x, wc->rate); 228cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci return 0; 231cabdff1aSopenharmony_ci} 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_cistatic int wv_read_header(AVFormatContext *s) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 236cabdff1aSopenharmony_ci WVContext *wc = s->priv_data; 237cabdff1aSopenharmony_ci AVStream *st; 238cabdff1aSopenharmony_ci int ret; 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci wc->block_parsed = 0; 241cabdff1aSopenharmony_ci for (;;) { 242cabdff1aSopenharmony_ci if ((ret = wv_read_block_header(s, pb)) < 0) 243cabdff1aSopenharmony_ci return ret; 244cabdff1aSopenharmony_ci if (!wc->header.samples) 245cabdff1aSopenharmony_ci avio_skip(pb, wc->header.blocksize); 246cabdff1aSopenharmony_ci else 247cabdff1aSopenharmony_ci break; 248cabdff1aSopenharmony_ci } 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci /* now we are ready: build format streams */ 251cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 252cabdff1aSopenharmony_ci if (!st) 253cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 254cabdff1aSopenharmony_ci if ((ret = ff_alloc_extradata(st->codecpar, 2)) < 0) 255cabdff1aSopenharmony_ci return ret; 256cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata, wc->header.version); 257cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 258cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_WAVPACK; 259cabdff1aSopenharmony_ci av_channel_layout_from_mask(&st->codecpar->ch_layout, wc->chmask); 260cabdff1aSopenharmony_ci st->codecpar->sample_rate = wc->rate; 261cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample = wc->bpp; 262cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, wc->rate); 263cabdff1aSopenharmony_ci st->start_time = 0; 264cabdff1aSopenharmony_ci if (wc->header.total_samples != 0xFFFFFFFFu) 265cabdff1aSopenharmony_ci st->duration = wc->header.total_samples; 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { 268cabdff1aSopenharmony_ci int64_t cur = avio_tell(s->pb); 269cabdff1aSopenharmony_ci wc->apetag_start = ff_ape_parse_tag(s); 270cabdff1aSopenharmony_ci if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) 271cabdff1aSopenharmony_ci ff_id3v1_read(s); 272cabdff1aSopenharmony_ci avio_seek(s->pb, cur, SEEK_SET); 273cabdff1aSopenharmony_ci } 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci return 0; 276cabdff1aSopenharmony_ci} 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_cistatic int wv_read_packet(AVFormatContext *s, AVPacket *pkt) 279cabdff1aSopenharmony_ci{ 280cabdff1aSopenharmony_ci WVContext *wc = s->priv_data; 281cabdff1aSopenharmony_ci int ret; 282cabdff1aSopenharmony_ci int off; 283cabdff1aSopenharmony_ci int64_t pos; 284cabdff1aSopenharmony_ci uint32_t block_samples; 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_ci if (avio_feof(s->pb)) 287cabdff1aSopenharmony_ci return AVERROR_EOF; 288cabdff1aSopenharmony_ci if (wc->block_parsed) { 289cabdff1aSopenharmony_ci if ((ret = wv_read_block_header(s, s->pb)) < 0) 290cabdff1aSopenharmony_ci return ret; 291cabdff1aSopenharmony_ci } 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci pos = wc->pos; 294cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, wc->header.blocksize + WV_HEADER_SIZE)) < 0) 295cabdff1aSopenharmony_ci return ret; 296cabdff1aSopenharmony_ci memcpy(pkt->data, wc->block_header, WV_HEADER_SIZE); 297cabdff1aSopenharmony_ci ret = avio_read(s->pb, pkt->data + WV_HEADER_SIZE, wc->header.blocksize); 298cabdff1aSopenharmony_ci if (ret != wc->header.blocksize) { 299cabdff1aSopenharmony_ci return AVERROR(EIO); 300cabdff1aSopenharmony_ci } 301cabdff1aSopenharmony_ci while (!(wc->header.flags & WV_FLAG_FINAL_BLOCK)) { 302cabdff1aSopenharmony_ci if ((ret = wv_read_block_header(s, s->pb)) < 0) { 303cabdff1aSopenharmony_ci return ret; 304cabdff1aSopenharmony_ci } 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci off = pkt->size; 307cabdff1aSopenharmony_ci if ((ret = av_grow_packet(pkt, WV_HEADER_SIZE + wc->header.blocksize)) < 0) { 308cabdff1aSopenharmony_ci return ret; 309cabdff1aSopenharmony_ci } 310cabdff1aSopenharmony_ci memcpy(pkt->data + off, wc->block_header, WV_HEADER_SIZE); 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_ci ret = avio_read(s->pb, pkt->data + off + WV_HEADER_SIZE, wc->header.blocksize); 313cabdff1aSopenharmony_ci if (ret != wc->header.blocksize) { 314cabdff1aSopenharmony_ci return (ret < 0) ? ret : AVERROR_EOF; 315cabdff1aSopenharmony_ci } 316cabdff1aSopenharmony_ci } 317cabdff1aSopenharmony_ci pkt->stream_index = 0; 318cabdff1aSopenharmony_ci pkt->pos = pos; 319cabdff1aSopenharmony_ci wc->block_parsed = 1; 320cabdff1aSopenharmony_ci pkt->pts = wc->header.block_idx; 321cabdff1aSopenharmony_ci block_samples = wc->header.samples; 322cabdff1aSopenharmony_ci if (block_samples > INT32_MAX) 323cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 324cabdff1aSopenharmony_ci "Too many samples in block: %"PRIu32"\n", block_samples); 325cabdff1aSopenharmony_ci else 326cabdff1aSopenharmony_ci pkt->duration = block_samples; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci return 0; 329cabdff1aSopenharmony_ci} 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ciconst AVInputFormat ff_wv_demuxer = { 332cabdff1aSopenharmony_ci .name = "wv", 333cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("WavPack"), 334cabdff1aSopenharmony_ci .priv_data_size = sizeof(WVContext), 335cabdff1aSopenharmony_ci .read_probe = wv_probe, 336cabdff1aSopenharmony_ci .read_header = wv_read_header, 337cabdff1aSopenharmony_ci .read_packet = wv_read_packet, 338cabdff1aSopenharmony_ci .flags = AVFMT_GENERIC_INDEX, 339cabdff1aSopenharmony_ci}; 340