00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/audioconvert.h"
00023 #include "libavutil/intreadwrite.h"
00024 #include "avformat.h"
00025 #include "apetag.h"
00026 #include "id3v1.h"
00027
00028
00029 #define WV_BLOCK_LIMIT 1047576
00030
00031 #define WV_EXTRA_SIZE 12
00032
00033 #define WV_START_BLOCK 0x0800
00034 #define WV_END_BLOCK 0x1000
00035 #define WV_SINGLE_BLOCK (WV_START_BLOCK | WV_END_BLOCK)
00036
00037 enum WV_FLAGS{
00038 WV_MONO = 0x0004,
00039 WV_HYBRID = 0x0008,
00040 WV_JOINT = 0x0010,
00041 WV_CROSSD = 0x0020,
00042 WV_HSHAPE = 0x0040,
00043 WV_FLOAT = 0x0080,
00044 WV_INT32 = 0x0100,
00045 WV_HBR = 0x0200,
00046 WV_HBAL = 0x0400,
00047 WV_MCINIT = 0x0800,
00048 WV_MCEND = 0x1000,
00049 };
00050
00051 static const int wv_rates[16] = {
00052 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
00053 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1
00054 };
00055
00056 typedef struct{
00057 uint32_t blksize, flags;
00058 int rate, chan, bpp;
00059 uint32_t chmask;
00060 uint32_t samples, soff;
00061 int multichannel;
00062 int block_parsed;
00063 uint8_t extra[WV_EXTRA_SIZE];
00064 int64_t pos;
00065 }WVContext;
00066
00067 static int wv_probe(AVProbeData *p)
00068 {
00069
00070 if (p->buf_size <= 32)
00071 return 0;
00072 if (p->buf[0] == 'w' && p->buf[1] == 'v' &&
00073 p->buf[2] == 'p' && p->buf[3] == 'k')
00074 return AVPROBE_SCORE_MAX;
00075 else
00076 return 0;
00077 }
00078
00079 static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb, int append)
00080 {
00081 WVContext *wc = ctx->priv_data;
00082 uint32_t tag, ver;
00083 int size;
00084 int rate, bpp, chan;
00085 uint32_t chmask;
00086
00087 wc->pos = avio_tell(pb);
00088 if(!append){
00089 tag = avio_rl32(pb);
00090 if (tag != MKTAG('w', 'v', 'p', 'k'))
00091 return -1;
00092 size = avio_rl32(pb);
00093 if(size < 24 || size > WV_BLOCK_LIMIT){
00094 av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size);
00095 return -1;
00096 }
00097 wc->blksize = size;
00098 ver = avio_rl16(pb);
00099 if(ver < 0x402 || ver > 0x410){
00100 av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver);
00101 return -1;
00102 }
00103 avio_r8(pb);
00104 avio_r8(pb);
00105 wc->samples = avio_rl32(pb);
00106 wc->soff = avio_rl32(pb);
00107 avio_read(pb, wc->extra, WV_EXTRA_SIZE);
00108 }else{
00109 size = wc->blksize;
00110 }
00111 wc->flags = AV_RL32(wc->extra + 4);
00112
00113 bpp = ((wc->flags & 3) + 1) << 3;
00114 chan = 1 + !(wc->flags & WV_MONO);
00115 chmask = wc->flags & WV_MONO ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
00116 rate = wv_rates[(wc->flags >> 23) & 0xF];
00117 wc->multichannel = !!((wc->flags & WV_SINGLE_BLOCK) != WV_SINGLE_BLOCK);
00118 if(wc->multichannel){
00119 chan = wc->chan;
00120 chmask = wc->chmask;
00121 }
00122 if((rate == -1 || !chan) && !wc->block_parsed){
00123 int64_t block_end = avio_tell(pb) + wc->blksize - 24;
00124 if(url_is_streamed(pb)){
00125 av_log(ctx, AV_LOG_ERROR, "Cannot determine additional parameters\n");
00126 return -1;
00127 }
00128 while(avio_tell(pb) < block_end){
00129 int id, size;
00130 id = avio_r8(pb);
00131 size = (id & 0x80) ? avio_rl24(pb) : avio_r8(pb);
00132 size <<= 1;
00133 if(id&0x40)
00134 size--;
00135 switch(id&0x3F){
00136 case 0xD:
00137 if(size <= 1){
00138 av_log(ctx, AV_LOG_ERROR, "Insufficient channel information\n");
00139 return -1;
00140 }
00141 chan = avio_r8(pb);
00142 switch(size - 2){
00143 case 0:
00144 chmask = avio_r8(pb);
00145 break;
00146 case 1:
00147 chmask = avio_rl16(pb);
00148 break;
00149 case 2:
00150 chmask = avio_rl24(pb);
00151 break;
00152 case 3:
00153 chmask = avio_rl32(pb);
00154 break;
00155 case 5:
00156 avio_seek(pb, 1, SEEK_CUR);
00157 chan |= (avio_r8(pb) & 0xF) << 8;
00158 chmask = avio_rl24(pb);
00159 break;
00160 default:
00161 av_log(ctx, AV_LOG_ERROR, "Invalid channel info size %d\n", size);
00162 return -1;
00163 }
00164 break;
00165 case 0x27:
00166 rate = avio_rl24(pb);
00167 break;
00168 default:
00169 avio_seek(pb, size, SEEK_CUR);
00170 }
00171 if(id&0x40)
00172 avio_seek(pb, 1, SEEK_CUR);
00173 }
00174 if(rate == -1){
00175 av_log(ctx, AV_LOG_ERROR, "Cannot determine custom sampling rate\n");
00176 return -1;
00177 }
00178 avio_seek(pb, block_end - wc->blksize + 24, SEEK_SET);
00179 }
00180 if(!wc->bpp) wc->bpp = bpp;
00181 if(!wc->chan) wc->chan = chan;
00182 if(!wc->chmask) wc->chmask = chmask;
00183 if(!wc->rate) wc->rate = rate;
00184
00185 if(wc->flags && bpp != wc->bpp){
00186 av_log(ctx, AV_LOG_ERROR, "Bits per sample differ, this block: %i, header block: %i\n", bpp, wc->bpp);
00187 return -1;
00188 }
00189 if(wc->flags && !wc->multichannel && chan != wc->chan){
00190 av_log(ctx, AV_LOG_ERROR, "Channels differ, this block: %i, header block: %i\n", chan, wc->chan);
00191 return -1;
00192 }
00193 if(wc->flags && rate != -1 && rate != wc->rate){
00194 av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", rate, wc->rate);
00195 return -1;
00196 }
00197 wc->blksize = size - 24;
00198 return 0;
00199 }
00200
00201 static int wv_read_header(AVFormatContext *s,
00202 AVFormatParameters *ap)
00203 {
00204 AVIOContext *pb = s->pb;
00205 WVContext *wc = s->priv_data;
00206 AVStream *st;
00207
00208 wc->block_parsed = 0;
00209 if(wv_read_block_header(s, pb, 0) < 0)
00210 return -1;
00211
00212
00213 st = av_new_stream(s, 0);
00214 if (!st)
00215 return -1;
00216 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00217 st->codec->codec_id = CODEC_ID_WAVPACK;
00218 st->codec->channels = wc->chan;
00219 st->codec->channel_layout = wc->chmask;
00220 st->codec->sample_rate = wc->rate;
00221 st->codec->bits_per_coded_sample = wc->bpp;
00222 av_set_pts_info(st, 64, 1, wc->rate);
00223 st->start_time = 0;
00224 st->duration = wc->samples;
00225
00226 if(!url_is_streamed(s->pb)) {
00227 int64_t cur = avio_tell(s->pb);
00228 ff_ape_parse_tag(s);
00229 if(!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX))
00230 ff_id3v1_read(s);
00231 avio_seek(s->pb, cur, SEEK_SET);
00232 }
00233
00234 return 0;
00235 }
00236
00237 static int wv_read_packet(AVFormatContext *s,
00238 AVPacket *pkt)
00239 {
00240 WVContext *wc = s->priv_data;
00241 int ret;
00242 int size, ver, off;
00243
00244 if (url_feof(s->pb))
00245 return AVERROR(EIO);
00246 if(wc->block_parsed){
00247 if(wv_read_block_header(s, s->pb, 0) < 0)
00248 return -1;
00249 }
00250
00251 off = wc->multichannel ? 4 : 0;
00252 if(av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE + off) < 0)
00253 return AVERROR(ENOMEM);
00254 if(wc->multichannel)
00255 AV_WL32(pkt->data, wc->blksize + WV_EXTRA_SIZE + 12);
00256 memcpy(pkt->data + off, wc->extra, WV_EXTRA_SIZE);
00257 ret = avio_read(s->pb, pkt->data + WV_EXTRA_SIZE + off, wc->blksize);
00258 if(ret != wc->blksize){
00259 av_free_packet(pkt);
00260 return AVERROR(EIO);
00261 }
00262 while(!(wc->flags & WV_END_BLOCK)){
00263 if(avio_rl32(s->pb) != MKTAG('w', 'v', 'p', 'k')){
00264 av_free_packet(pkt);
00265 return -1;
00266 }
00267 if((ret = av_append_packet(s->pb, pkt, 4)) < 0){
00268 av_free_packet(pkt);
00269 return ret;
00270 }
00271 size = AV_RL32(pkt->data + pkt->size - 4);
00272 if(size < 24 || size > WV_BLOCK_LIMIT){
00273 av_free_packet(pkt);
00274 av_log(s, AV_LOG_ERROR, "Incorrect block size %d\n", size);
00275 return -1;
00276 }
00277 wc->blksize = size;
00278 ver = avio_rl16(s->pb);
00279 if(ver < 0x402 || ver > 0x410){
00280 av_free_packet(pkt);
00281 av_log(s, AV_LOG_ERROR, "Unsupported version %03X\n", ver);
00282 return -1;
00283 }
00284 avio_r8(s->pb);
00285 avio_r8(s->pb);
00286 wc->samples = avio_rl32(s->pb);
00287 wc->soff = avio_rl32(s->pb);
00288 if((ret = av_append_packet(s->pb, pkt, WV_EXTRA_SIZE)) < 0){
00289 av_free_packet(pkt);
00290 return ret;
00291 }
00292 memcpy(wc->extra, pkt->data + pkt->size - WV_EXTRA_SIZE, WV_EXTRA_SIZE);
00293
00294 if(wv_read_block_header(s, s->pb, 1) < 0){
00295 av_free_packet(pkt);
00296 return -1;
00297 }
00298 ret = av_append_packet(s->pb, pkt, wc->blksize);
00299 if(ret < 0){
00300 av_free_packet(pkt);
00301 return ret;
00302 }
00303 }
00304 pkt->stream_index = 0;
00305 wc->block_parsed = 1;
00306 pkt->pts = wc->soff;
00307 av_add_index_entry(s->streams[0], wc->pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME);
00308 return 0;
00309 }
00310
00311 static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
00312 {
00313 AVStream *st = s->streams[stream_index];
00314 WVContext *wc = s->priv_data;
00315 AVPacket pkt1, *pkt = &pkt1;
00316 int ret;
00317 int index = av_index_search_timestamp(st, timestamp, flags);
00318 int64_t pos, pts;
00319
00320
00321 if (index >= 0){
00322 wc->block_parsed = 1;
00323 avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET);
00324 return 0;
00325 }
00326
00327 if(timestamp < 0 || timestamp >= s->duration)
00328 return -1;
00329
00330 pos = avio_tell(s->pb);
00331 do{
00332 ret = av_read_frame(s, pkt);
00333 if (ret < 0){
00334 avio_seek(s->pb, pos, SEEK_SET);
00335 return -1;
00336 }
00337 pts = pkt->pts;
00338 av_free_packet(pkt);
00339 }while(pts < timestamp);
00340 return 0;
00341 }
00342
00343 AVInputFormat ff_wv_demuxer = {
00344 "wv",
00345 NULL_IF_CONFIG_SMALL("WavPack"),
00346 sizeof(WVContext),
00347 wv_probe,
00348 wv_read_header,
00349 wv_read_packet,
00350 NULL,
00351 wv_read_seek,
00352 };