Libav
|
00001 /* 00002 * Musepack SV8 demuxer 00003 * Copyright (c) 2007 Konstantin Shishkov 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavcodec/get_bits.h" 00023 #include "libavcodec/unary.h" 00024 #include "avformat.h" 00025 00027 #define MKMPCTAG(a, b) (a | (b << 8)) 00028 00029 #define TAG_MPCK MKTAG('M','P','C','K') 00030 00032 enum MPCPacketTags{ 00033 TAG_STREAMHDR = MKMPCTAG('S','H'), 00034 TAG_STREAMEND = MKMPCTAG('S','E'), 00035 00036 TAG_AUDIOPACKET = MKMPCTAG('A','P'), 00037 00038 TAG_SEEKTBLOFF = MKMPCTAG('S','O'), 00039 TAG_SEEKTABLE = MKMPCTAG('S','T'), 00040 00041 TAG_REPLAYGAIN = MKMPCTAG('R','G'), 00042 TAG_ENCINFO = MKMPCTAG('E','I'), 00043 }; 00044 00045 static const int mpc8_rate[8] = { 44100, 48000, 37800, 32000, -1, -1, -1, -1 }; 00046 00047 typedef struct { 00048 int ver; 00049 int frame; 00050 int64_t header_pos; 00051 int64_t samples; 00052 } MPCContext; 00053 00054 static inline int64_t bs_get_v(uint8_t **bs) 00055 { 00056 int64_t v = 0; 00057 int br = 0; 00058 int c; 00059 00060 do { 00061 c = **bs; (*bs)++; 00062 v <<= 7; 00063 v |= c & 0x7F; 00064 br++; 00065 if (br > 10) 00066 return -1; 00067 } while (c & 0x80); 00068 00069 return v - br; 00070 } 00071 00072 static int mpc8_probe(AVProbeData *p) 00073 { 00074 uint8_t *bs = p->buf + 4; 00075 uint8_t *bs_end = bs + p->buf_size; 00076 int64_t size; 00077 00078 if (p->buf_size < 16) 00079 return 0; 00080 if (AV_RL32(p->buf) != TAG_MPCK) 00081 return 0; 00082 while (bs < bs_end + 3) { 00083 int header_found = (bs[0] == 'S' && bs[1] == 'H'); 00084 if (bs[0] < 'A' || bs[0] > 'Z' || bs[1] < 'A' || bs[1] > 'Z') 00085 return 0; 00086 bs += 2; 00087 size = bs_get_v(&bs); 00088 if (size < 2) 00089 return 0; 00090 if (bs + size - 2 >= bs_end) 00091 return AVPROBE_SCORE_MAX / 4 - 1; //seems to be valid MPC but no header yet 00092 if (header_found) { 00093 if (size < 11 || size > 28) 00094 return 0; 00095 if (!AV_RL32(bs)) //zero CRC is invalid 00096 return 0; 00097 return AVPROBE_SCORE_MAX; 00098 } else { 00099 bs += size - 2; 00100 } 00101 } 00102 return 0; 00103 } 00104 00105 static inline int64_t gb_get_v(GetBitContext *gb) 00106 { 00107 int64_t v = 0; 00108 int bits = 0; 00109 while(get_bits1(gb) && bits < 64-7){ 00110 v <<= 7; 00111 v |= get_bits(gb, 7); 00112 bits += 7; 00113 } 00114 v <<= 7; 00115 v |= get_bits(gb, 7); 00116 00117 return v; 00118 } 00119 00120 static void mpc8_get_chunk_header(ByteIOContext *pb, int *tag, int64_t *size) 00121 { 00122 int64_t pos; 00123 pos = url_ftell(pb); 00124 *tag = get_le16(pb); 00125 *size = ff_get_v(pb); 00126 *size -= url_ftell(pb) - pos; 00127 } 00128 00129 static void mpc8_parse_seektable(AVFormatContext *s, int64_t off) 00130 { 00131 MPCContext *c = s->priv_data; 00132 int tag; 00133 int64_t size, pos, ppos[2]; 00134 uint8_t *buf; 00135 int i, t, seekd; 00136 GetBitContext gb; 00137 00138 url_fseek(s->pb, off, SEEK_SET); 00139 mpc8_get_chunk_header(s->pb, &tag, &size); 00140 if(tag != TAG_SEEKTABLE){ 00141 av_log(s, AV_LOG_ERROR, "No seek table at given position\n"); 00142 return; 00143 } 00144 if(!(buf = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE))) 00145 return; 00146 get_buffer(s->pb, buf, size); 00147 init_get_bits(&gb, buf, size * 8); 00148 size = gb_get_v(&gb); 00149 if(size > UINT_MAX/4 || size > c->samples/1152){ 00150 av_log(s, AV_LOG_ERROR, "Seek table is too big\n"); 00151 return; 00152 } 00153 seekd = get_bits(&gb, 4); 00154 for(i = 0; i < 2; i++){ 00155 pos = gb_get_v(&gb) + c->header_pos; 00156 ppos[1 - i] = pos; 00157 av_add_index_entry(s->streams[0], pos, i, 0, 0, AVINDEX_KEYFRAME); 00158 } 00159 for(; i < size; i++){ 00160 t = get_unary(&gb, 1, 33) << 12; 00161 t += get_bits(&gb, 12); 00162 if(t & 1) 00163 t = -(t & ~1); 00164 pos = (t >> 1) + ppos[0]*2 - ppos[1]; 00165 av_add_index_entry(s->streams[0], pos, i << seekd, 0, 0, AVINDEX_KEYFRAME); 00166 ppos[1] = ppos[0]; 00167 ppos[0] = pos; 00168 } 00169 av_free(buf); 00170 } 00171 00172 static void mpc8_handle_chunk(AVFormatContext *s, int tag, int64_t chunk_pos, int64_t size) 00173 { 00174 ByteIOContext *pb = s->pb; 00175 int64_t pos, off; 00176 00177 switch(tag){ 00178 case TAG_SEEKTBLOFF: 00179 pos = url_ftell(pb) + size; 00180 off = ff_get_v(pb); 00181 mpc8_parse_seektable(s, chunk_pos + off); 00182 url_fseek(pb, pos, SEEK_SET); 00183 break; 00184 default: 00185 url_fskip(pb, size); 00186 } 00187 } 00188 00189 static int mpc8_read_header(AVFormatContext *s, AVFormatParameters *ap) 00190 { 00191 MPCContext *c = s->priv_data; 00192 ByteIOContext *pb = s->pb; 00193 AVStream *st; 00194 int tag = 0; 00195 int64_t size, pos; 00196 00197 c->header_pos = url_ftell(pb); 00198 if(get_le32(pb) != TAG_MPCK){ 00199 av_log(s, AV_LOG_ERROR, "Not a Musepack8 file\n"); 00200 return -1; 00201 } 00202 00203 while(!url_feof(pb)){ 00204 pos = url_ftell(pb); 00205 mpc8_get_chunk_header(pb, &tag, &size); 00206 if(tag == TAG_STREAMHDR) 00207 break; 00208 mpc8_handle_chunk(s, tag, pos, size); 00209 } 00210 if(tag != TAG_STREAMHDR){ 00211 av_log(s, AV_LOG_ERROR, "Stream header not found\n"); 00212 return -1; 00213 } 00214 pos = url_ftell(pb); 00215 url_fskip(pb, 4); //CRC 00216 c->ver = get_byte(pb); 00217 if(c->ver != 8){ 00218 av_log(s, AV_LOG_ERROR, "Unknown stream version %d\n", c->ver); 00219 return -1; 00220 } 00221 c->samples = ff_get_v(pb); 00222 ff_get_v(pb); //silence samples at the beginning 00223 00224 st = av_new_stream(s, 0); 00225 if (!st) 00226 return AVERROR(ENOMEM); 00227 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00228 st->codec->codec_id = CODEC_ID_MUSEPACK8; 00229 st->codec->bits_per_coded_sample = 16; 00230 00231 st->codec->extradata_size = 2; 00232 st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); 00233 get_buffer(pb, st->codec->extradata, st->codec->extradata_size); 00234 00235 st->codec->channels = (st->codec->extradata[1] >> 4) + 1; 00236 st->codec->sample_rate = mpc8_rate[st->codec->extradata[0] >> 5]; 00237 av_set_pts_info(st, 32, 1152 << (st->codec->extradata[1]&3)*2, st->codec->sample_rate); 00238 st->duration = c->samples / (1152 << (st->codec->extradata[1]&3)*2); 00239 size -= url_ftell(pb) - pos; 00240 00241 return 0; 00242 } 00243 00244 static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt) 00245 { 00246 MPCContext *c = s->priv_data; 00247 int tag; 00248 int64_t pos, size; 00249 00250 while(!url_feof(s->pb)){ 00251 pos = url_ftell(s->pb); 00252 mpc8_get_chunk_header(s->pb, &tag, &size); 00253 if (size < 0) 00254 return -1; 00255 if(tag == TAG_AUDIOPACKET){ 00256 if(av_get_packet(s->pb, pkt, size) < 0) 00257 return AVERROR(ENOMEM); 00258 pkt->stream_index = 0; 00259 pkt->pts = c->frame; 00260 return 0; 00261 } 00262 if(tag == TAG_STREAMEND) 00263 return AVERROR(EIO); 00264 mpc8_handle_chunk(s, tag, pos, size); 00265 } 00266 return 0; 00267 } 00268 00269 static int mpc8_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) 00270 { 00271 AVStream *st = s->streams[stream_index]; 00272 MPCContext *c = s->priv_data; 00273 int index = av_index_search_timestamp(st, timestamp, flags); 00274 00275 if(index < 0) return -1; 00276 url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET); 00277 c->frame = st->index_entries[index].timestamp; 00278 return 0; 00279 } 00280 00281 00282 AVInputFormat mpc8_demuxer = { 00283 "mpc8", 00284 NULL_IF_CONFIG_SMALL("Musepack SV8"), 00285 sizeof(MPCContext), 00286 mpc8_probe, 00287 mpc8_read_header, 00288 mpc8_read_packet, 00289 NULL, 00290 mpc8_read_seek, 00291 };