wv.c
Go to the documentation of this file.
1 /*
2  * WavPack demuxer
3  * Copyright (c) 2006,2011 Konstantin Shishkov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
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 
39 enum 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 
53 static 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 
58 typedef struct {
59  uint32_t blksize, flags;
60  int rate, chan, bpp;
61  uint32_t chmask;
62  uint32_t samples, soff;
66  int64_t pos;
67 
68  int64_t apetag_start;
69 } WVContext;
70 
71 static int wv_probe(AVProbeData *p)
72 {
73  /* check file header */
74  if (p->buf_size <= 32)
75  return 0;
76  if (p->buf[0] == 'w' && p->buf[1] == 'v' &&
77  p->buf[2] == 'p' && p->buf[3] == 'k')
78  return AVPROBE_SCORE_MAX;
79  else
80  return 0;
81 }
82 
84  int append)
85 {
86  WVContext *wc = ctx->priv_data;
87  uint32_t tag, ver;
88  int size;
89  int rate, bpp, chan;
90  uint32_t chmask;
91 
92  wc->pos = avio_tell(pb);
93 
94  /* don't return bogus packets with the ape tag data */
95  if (wc->apetag_start && wc->pos >= wc->apetag_start)
96  return AVERROR_EOF;
97 
98  if (!append) {
99  tag = avio_rl32(pb);
100  if (tag != MKTAG('w', 'v', 'p', 'k'))
101  return AVERROR_INVALIDDATA;
102  size = avio_rl32(pb);
103  if (size < 24 || size > WV_BLOCK_LIMIT) {
104  av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size);
105  return AVERROR_INVALIDDATA;
106  }
107  wc->blksize = size;
108  ver = avio_rl16(pb);
109  if (ver < 0x402 || ver > 0x410) {
110  av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver);
111  return AVERROR_PATCHWELCOME;
112  }
113  avio_r8(pb); // track no
114  avio_r8(pb); // track sub index
115  wc->samples = avio_rl32(pb); // total samples in file
116  wc->soff = avio_rl32(pb); // offset in samples of current block
117  avio_read(pb, wc->extra, WV_EXTRA_SIZE);
118  } else {
119  size = wc->blksize;
120  }
121  wc->flags = AV_RL32(wc->extra + 4);
122  /* Blocks with zero samples don't contain actual audio information
123  * and should be ignored */
124  if (!AV_RN32(wc->extra))
125  return 0;
126  // parse flags
127  bpp = ((wc->flags & 3) + 1) << 3;
128  chan = 1 + !(wc->flags & WV_MONO);
130  rate = wv_rates[(wc->flags >> 23) & 0xF];
131  wc->multichannel = !!((wc->flags & WV_SINGLE_BLOCK) != WV_SINGLE_BLOCK);
132  if (wc->multichannel) {
133  chan = wc->chan;
134  chmask = wc->chmask;
135  }
136  if ((rate == -1 || !chan) && !wc->block_parsed) {
137  int64_t block_end = avio_tell(pb) + wc->blksize - 24;
138  if (!pb->seekable) {
139  av_log(ctx, AV_LOG_ERROR,
140  "Cannot determine additional parameters\n");
141  return AVERROR_INVALIDDATA;
142  }
143  while (avio_tell(pb) < block_end) {
144  int id, size;
145  id = avio_r8(pb);
146  size = (id & 0x80) ? avio_rl24(pb) : avio_r8(pb);
147  size <<= 1;
148  if (id & 0x40)
149  size--;
150  switch (id & 0x3F) {
151  case 0xD:
152  if (size <= 1) {
153  av_log(ctx, AV_LOG_ERROR,
154  "Insufficient channel information\n");
155  return AVERROR_INVALIDDATA;
156  }
157  chan = avio_r8(pb);
158  switch (size - 2) {
159  case 0:
160  chmask = avio_r8(pb);
161  break;
162  case 1:
163  chmask = avio_rl16(pb);
164  break;
165  case 2:
166  chmask = avio_rl24(pb);
167  break;
168  case 3:
169  chmask = avio_rl32(pb);
170  break;
171  case 5:
172  avio_skip(pb, 1);
173  chan |= (avio_r8(pb) & 0xF) << 8;
174  chmask = avio_rl24(pb);
175  break;
176  default:
177  av_log(ctx, AV_LOG_ERROR,
178  "Invalid channel info size %d\n", size);
179  return AVERROR_INVALIDDATA;
180  }
181  break;
182  case 0x27:
183  rate = avio_rl24(pb);
184  break;
185  default:
186  avio_skip(pb, size);
187  }
188  if (id & 0x40)
189  avio_skip(pb, 1);
190  }
191  if (rate == -1) {
192  av_log(ctx, AV_LOG_ERROR,
193  "Cannot determine custom sampling rate\n");
194  return AVERROR_INVALIDDATA;
195  }
196  avio_seek(pb, block_end - wc->blksize + 24, SEEK_SET);
197  }
198  if (!wc->bpp)
199  wc->bpp = bpp;
200  if (!wc->chan)
201  wc->chan = chan;
202  if (!wc->chmask)
203  wc->chmask = chmask;
204  if (!wc->rate)
205  wc->rate = rate;
206 
207  if (wc->flags && bpp != wc->bpp) {
208  av_log(ctx, AV_LOG_ERROR,
209  "Bits per sample differ, this block: %i, header block: %i\n",
210  bpp, wc->bpp);
211  return AVERROR_INVALIDDATA;
212  }
213  if (wc->flags && !wc->multichannel && chan != wc->chan) {
214  av_log(ctx, AV_LOG_ERROR,
215  "Channels differ, this block: %i, header block: %i\n",
216  chan, wc->chan);
217  return AVERROR_INVALIDDATA;
218  }
219  if (wc->flags && rate != -1 && rate != wc->rate) {
220  av_log(ctx, AV_LOG_ERROR,
221  "Sampling rate differ, this block: %i, header block: %i\n",
222  rate, wc->rate);
223  return AVERROR_INVALIDDATA;
224  }
225  wc->blksize = size - 24;
226  return 0;
227 }
228 
230 {
231  AVIOContext *pb = s->pb;
232  WVContext *wc = s->priv_data;
233  AVStream *st;
234  int ret;
235 
236  wc->block_parsed = 0;
237  for (;;) {
238  if ((ret = wv_read_block_header(s, pb, 0)) < 0)
239  return ret;
240  if (!AV_RN32(wc->extra))
241  avio_skip(pb, wc->blksize - 24);
242  else
243  break;
244  }
245 
246  /* now we are ready: build format streams */
247  st = avformat_new_stream(s, NULL);
248  if (!st)
249  return AVERROR(ENOMEM);
252  st->codec->channels = wc->chan;
253  st->codec->channel_layout = wc->chmask;
254  st->codec->sample_rate = wc->rate;
255  st->codec->bits_per_coded_sample = wc->bpp;
256  avpriv_set_pts_info(st, 64, 1, wc->rate);
257  st->start_time = 0;
258  if (wc->samples != 0xFFFFFFFFu)
259  st->duration = wc->samples;
260 
261  if (s->pb->seekable) {
262  int64_t cur = avio_tell(s->pb);
265  ff_id3v1_read(s);
266  avio_seek(s->pb, cur, SEEK_SET);
267  }
268 
269  return 0;
270 }
271 
273 {
274  WVContext *wc = s->priv_data;
275  int ret;
276  int size, ver, off;
277  int64_t pos;
278  uint32_t block_samples;
279 
280  if (url_feof(s->pb))
281  return AVERROR_EOF;
282  if (wc->block_parsed) {
283  if ((ret = wv_read_block_header(s, s->pb, 0)) < 0)
284  return ret;
285  }
286 
287  pos = wc->pos;
288  off = wc->multichannel ? 4 : 0;
289  if (av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE + off) < 0)
290  return AVERROR(ENOMEM);
291  if (wc->multichannel)
292  AV_WL32(pkt->data, wc->blksize + WV_EXTRA_SIZE + 12);
293  memcpy(pkt->data + off, wc->extra, WV_EXTRA_SIZE);
294  ret = avio_read(s->pb, pkt->data + WV_EXTRA_SIZE + off, wc->blksize);
295  if (ret != wc->blksize) {
296  av_free_packet(pkt);
297  return AVERROR(EIO);
298  }
299  while (!(wc->flags & WV_END_BLOCK)) {
300  if (avio_rl32(s->pb) != MKTAG('w', 'v', 'p', 'k')) {
301  av_free_packet(pkt);
302  return AVERROR_INVALIDDATA;
303  }
304  if ((ret = av_append_packet(s->pb, pkt, 4)) < 0) {
305  av_free_packet(pkt);
306  return ret;
307  }
308  size = AV_RL32(pkt->data + pkt->size - 4);
309  if (size < 24 || size > WV_BLOCK_LIMIT) {
310  av_free_packet(pkt);
311  av_log(s, AV_LOG_ERROR, "Incorrect block size %d\n", size);
312  return AVERROR_INVALIDDATA;
313  }
314  wc->blksize = size;
315  ver = avio_rl16(s->pb);
316  if (ver < 0x402 || ver > 0x410) {
317  av_free_packet(pkt);
318  av_log(s, AV_LOG_ERROR, "Unsupported version %03X\n", ver);
319  return AVERROR_PATCHWELCOME;
320  }
321  avio_r8(s->pb); // track no
322  avio_r8(s->pb); // track sub index
323  wc->samples = avio_rl32(s->pb); // total samples in file
324  wc->soff = avio_rl32(s->pb); // offset in samples of current block
325  if ((ret = av_append_packet(s->pb, pkt, WV_EXTRA_SIZE)) < 0) {
326  av_free_packet(pkt);
327  return ret;
328  }
329  memcpy(wc->extra, pkt->data + pkt->size - WV_EXTRA_SIZE, WV_EXTRA_SIZE);
330 
331  if ((ret = wv_read_block_header(s, s->pb, 1)) < 0) {
332  av_free_packet(pkt);
333  return ret;
334  }
335  ret = av_append_packet(s->pb, pkt, wc->blksize);
336  if (ret < 0) {
337  av_free_packet(pkt);
338  return ret;
339  }
340  }
341  pkt->stream_index = 0;
342  wc->block_parsed = 1;
343  pkt->pts = wc->soff;
344  block_samples = AV_RL32(wc->extra);
345  if (block_samples > INT32_MAX)
347  "Too many samples in block: %"PRIu32"\n", block_samples);
348  else
349  pkt->duration = block_samples;
350 
351  av_add_index_entry(s->streams[0], pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME);
352  return 0;
353 }
354 
355 static int wv_read_seek(AVFormatContext *s, int stream_index,
356  int64_t timestamp, int flags)
357 {
358  AVStream *st = s->streams[stream_index];
359  WVContext *wc = s->priv_data;
360  AVPacket pkt1, *pkt = &pkt1;
361  int ret;
362  int index = av_index_search_timestamp(st, timestamp, flags);
363  int64_t pos, pts;
364 
365  /* if found, seek there */
366  if (index >= 0 &&
367  timestamp <= st->index_entries[st->nb_index_entries - 1].timestamp) {
368  wc->block_parsed = 1;
369  avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET);
370  return 0;
371  }
372  /* if timestamp is out of bounds, return error */
373  if (timestamp < 0 || timestamp >= s->duration)
374  return AVERROR(EINVAL);
375 
376  pos = avio_tell(s->pb);
377  do {
378  ret = av_read_frame(s, pkt);
379  if (ret < 0) {
380  avio_seek(s->pb, pos, SEEK_SET);
381  return ret;
382  }
383  pts = pkt->pts;
384  av_free_packet(pkt);
385  } while(pts < timestamp);
386  return 0;
387 }
388 
390  .name = "wv",
391  .long_name = NULL_IF_CONFIG_SMALL("WavPack"),
392  .priv_data_size = sizeof(WVContext),
393  .read_probe = wv_probe,
397 };
int64_t pos
Definition: wv.c:66
int block_parsed
Definition: wv.c:64
uint32_t soff
Definition: wv.c:62
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags)
Add an index entry into a sorted list.
static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: wv.c:355
enum AVCodecID id
Definition: mxfenc.c:89
Definition: wv.c:48
int rate
Definition: wv.c:60
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
int64_t pos
Definition: avformat.h:592
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition: libcdio.c:153
void ff_id3v1_read(AVFormatContext *s)
Read an ID3v1 tag.
Definition: id3v1.c:228
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
AVIndexEntry * index_entries
Only used if the format does not support seeking natively.
Definition: avformat.h:822
Definition: wv.c:46
Definition: wv.c:43
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:256
#define AV_CH_LAYOUT_STEREO
AVDictionaryEntry * av_dict_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:39
static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb, int append)
Definition: wv.c:83
Definition: wv.c:49
int multichannel
Definition: wv.c:63
Format I/O context.
Definition: avformat.h:944
#define AV_WL32(p, darg)
Definition: intreadwrite.h:282
Public dictionary API.
uint8_t
static AVPacket pkt
Definition: demuxing.c:56
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
AVStream ** streams
Definition: avformat.h:992
static uint8_t * append(uint8_t *buf, const uint8_t *src, int size)
uint8_t * data
Definition: wv.c:45
uint32_t tag
Definition: movenc.c:894
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
int duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
Read data and append it to the current content of the AVPacket.
#define WV_BLOCK_LIMIT
Definition: wv.c:31
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
#define AVINDEX_KEYFRAME
Definition: avformat.h:599
AVDictionary * metadata
Definition: avformat.h:1092
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags)
Get the index for a specific timestamp.
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:579
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
#define WV_END_BLOCK
Definition: wv.c:36
int64_t ff_ape_parse_tag(AVFormatContext *s)
Read and parse an APE tag.
Definition: apetag.c:114
Definition: wv.c:47
int size
uint64_t channel_layout
Audio channel layout.
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:337
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
uint8_t extra[WV_EXTRA_SIZE]
Definition: wv.c:65
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:117
#define WV_EXTRA_SIZE
Definition: wv.c:33
audio channel layout utility functions
static int read_probe(AVProbeData *pd)
ret
Definition: avfilter.c:821
uint32_t blksize
Definition: wv.c:59
int bpp
Definition: wv.c:60
int64_t apetag_start
Definition: wv.c:68
#define AV_RL32
AVInputFormat ff_wv_demuxer
Definition: wv.c:389
int url_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:280
#define WV_SINGLE_BLOCK
Definition: wv.c:37
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:517
Stream structure.
Definition: avformat.h:643
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
NULL
Definition: eval.c:55
Definition: wv.c:58
uint32_t flags
Definition: wv.c:59
enum AVMediaType codec_type
enum AVCodecID codec_id
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
WV_FLAGS
Definition: wv.c:39
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
Definition: libcdio.c:114
int nb_index_entries
Definition: avformat.h:824
int index
Definition: gxfenc.c:89
static int wv_read_header(AVFormatContext *s)
Definition: wv.c:229
int chan
Definition: wv.c:60
uint32_t chmask
Definition: wv.c:61
static int wv_probe(AVProbeData *p)
Definition: wv.c:71
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
#define AV_RN32(p)
Definition: intreadwrite.h:356
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
static int wv_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: wv.c:272
Definition: wv.c:50
static int flags
Definition: cpu.c:23
static const int wv_rates[16]
Definition: wv.c:53
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:696
Definition: wv.c:40
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:563
Main libavformat public API header.
Definition: wv.c:44
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:689
Definition: wv.c:41
Definition: wv.c:42
uint32_t samples
Definition: wv.c:62
int channels
number of audio channels
void * priv_data
Format private data.
Definition: avformat.h:964
int64_t duration
Decoding: duration of the stream, in AV_TIME_BASE fractional seconds.
Definition: avformat.h:1009
Filter the word “frame” indicates either a video frame or a group of audio samples
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
#define AV_DICT_IGNORE_SUFFIX
Definition: dict.h:68
unsigned int avio_rl24(AVIOContext *s)
Definition: aviobuf.c:571
#define AV_CH_LAYOUT_MONO
#define MKTAG(a, b, c, d)
Definition: common.h:282
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...