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