annotate ffmpeg/libavformat/wv.c @ 13:844d341cf643 tip

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