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