00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavcodec/get_bits.h"
00023 #include "avformat.h"
00024 #include "id3v2.h"
00025 #include "apetag.h"
00026
00027 #define MPC_FRAMESIZE 1152
00028 #define DELAY_FRAMES 32
00029
00030 static const int mpc_rate[4] = { 44100, 48000, 37800, 32000 };
00031 typedef struct {
00032 int64_t pos;
00033 int size, skip;
00034 }MPCFrame;
00035
00036 typedef struct {
00037 int ver;
00038 uint32_t curframe, lastframe;
00039 uint32_t fcount;
00040 MPCFrame *frames;
00041 int curbits;
00042 int frames_noted;
00043 } MPCContext;
00044
00045 static int mpc_probe(AVProbeData *p)
00046 {
00047 const uint8_t *d = p->buf;
00048 if (ff_id3v2_match(d)) {
00049 d += ff_id3v2_tag_len(d);
00050 }
00051 if (d+3 < p->buf+p->buf_size)
00052 if (d[0] == 'M' && d[1] == 'P' && d[2] == '+' && (d[3] == 0x17 || d[3] == 0x7))
00053 return AVPROBE_SCORE_MAX;
00054 return 0;
00055 }
00056
00057 static int mpc_read_header(AVFormatContext *s, AVFormatParameters *ap)
00058 {
00059 MPCContext *c = s->priv_data;
00060 AVStream *st;
00061 int t, ret;
00062 int64_t pos = url_ftell(s->pb);
00063
00064 t = get_le24(s->pb);
00065 if(t != MKTAG('M', 'P', '+', 0)){
00066 uint8_t buf[ID3v2_HEADER_SIZE];
00067 if (url_fseek(s->pb, pos, SEEK_SET) < 0)
00068 return -1;
00069 ret = get_buffer(s->pb, buf, ID3v2_HEADER_SIZE);
00070 if (ret != ID3v2_HEADER_SIZE || !ff_id3v2_match(buf)) {
00071 av_log(s, AV_LOG_ERROR, "Not a Musepack file\n");
00072 return -1;
00073 }
00074
00075 t = ff_id3v2_tag_len(buf) - ID3v2_HEADER_SIZE;
00076 av_log(s, AV_LOG_DEBUG, "Skipping %d(%X) bytes of ID3 data\n", t, t);
00077 url_fskip(s->pb, t);
00078 if(get_le24(s->pb) != MKTAG('M', 'P', '+', 0)){
00079 av_log(s, AV_LOG_ERROR, "Not a Musepack file\n");
00080 return -1;
00081 }
00082
00083 if (url_fseek(s->pb, pos, SEEK_SET) < 0)
00084 return -1;
00085 ff_id3v2_read(s);
00086 get_le24(s->pb);
00087 }
00088 c->ver = get_byte(s->pb);
00089 if(c->ver != 0x07 && c->ver != 0x17){
00090 av_log(s, AV_LOG_ERROR, "Can demux Musepack SV7, got version %02X\n", c->ver);
00091 return -1;
00092 }
00093 c->fcount = get_le32(s->pb);
00094 if((int64_t)c->fcount * sizeof(MPCFrame) >= UINT_MAX){
00095 av_log(s, AV_LOG_ERROR, "Too many frames, seeking is not possible\n");
00096 return -1;
00097 }
00098 c->frames = av_malloc(c->fcount * sizeof(MPCFrame));
00099 c->curframe = 0;
00100 c->lastframe = -1;
00101 c->curbits = 8;
00102 c->frames_noted = 0;
00103
00104 st = av_new_stream(s, 0);
00105 if (!st)
00106 return AVERROR(ENOMEM);
00107 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00108 st->codec->codec_id = CODEC_ID_MUSEPACK7;
00109 st->codec->channels = 2;
00110 st->codec->bits_per_coded_sample = 16;
00111
00112 st->codec->extradata_size = 16;
00113 st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE);
00114 get_buffer(s->pb, st->codec->extradata, 16);
00115 st->codec->sample_rate = mpc_rate[st->codec->extradata[2] & 3];
00116 av_set_pts_info(st, 32, MPC_FRAMESIZE, st->codec->sample_rate);
00117
00118 st->start_time = 0;
00119 st->duration = c->fcount;
00120
00121
00122 if (!url_is_streamed(s->pb)) {
00123 int64_t pos = url_ftell(s->pb);
00124 ff_ape_parse_tag(s);
00125 url_fseek(s->pb, pos, SEEK_SET);
00126 }
00127
00128 return 0;
00129 }
00130
00131 static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt)
00132 {
00133 MPCContext *c = s->priv_data;
00134 int ret, size, size2, curbits, cur = c->curframe;
00135 int64_t tmp, pos;
00136
00137 if (c->curframe >= c->fcount)
00138 return -1;
00139
00140 if(c->curframe != c->lastframe + 1){
00141 url_fseek(s->pb, c->frames[c->curframe].pos, SEEK_SET);
00142 c->curbits = c->frames[c->curframe].skip;
00143 }
00144 c->lastframe = c->curframe;
00145 c->curframe++;
00146 curbits = c->curbits;
00147 pos = url_ftell(s->pb);
00148 tmp = get_le32(s->pb);
00149 if(curbits <= 12){
00150 size2 = (tmp >> (12 - curbits)) & 0xFFFFF;
00151 }else{
00152 tmp = (tmp << 32) | get_le32(s->pb);
00153 size2 = (tmp >> (44 - curbits)) & 0xFFFFF;
00154 }
00155 curbits += 20;
00156 url_fseek(s->pb, pos, SEEK_SET);
00157
00158 size = ((size2 + curbits + 31) & ~31) >> 3;
00159 if(cur == c->frames_noted){
00160 c->frames[cur].pos = pos;
00161 c->frames[cur].size = size;
00162 c->frames[cur].skip = curbits - 20;
00163 av_add_index_entry(s->streams[0], cur, cur, size, 0, AVINDEX_KEYFRAME);
00164 c->frames_noted++;
00165 }
00166 c->curbits = (curbits + size2) & 0x1F;
00167
00168 if (av_new_packet(pkt, size) < 0)
00169 return AVERROR(EIO);
00170
00171 pkt->data[0] = curbits;
00172 pkt->data[1] = (c->curframe > c->fcount);
00173 pkt->data[2] = 0;
00174 pkt->data[3] = 0;
00175
00176 pkt->stream_index = 0;
00177 pkt->pts = cur;
00178 ret = get_buffer(s->pb, pkt->data + 4, size);
00179 if(c->curbits)
00180 url_fseek(s->pb, -4, SEEK_CUR);
00181 if(ret < size){
00182 av_free_packet(pkt);
00183 return AVERROR(EIO);
00184 }
00185 pkt->size = ret + 4;
00186
00187 return 0;
00188 }
00189
00190 static int mpc_read_close(AVFormatContext *s)
00191 {
00192 MPCContext *c = s->priv_data;
00193
00194 av_freep(&c->frames);
00195 return 0;
00196 }
00197
00205 static int mpc_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
00206 {
00207 AVStream *st = s->streams[stream_index];
00208 MPCContext *c = s->priv_data;
00209 AVPacket pkt1, *pkt = &pkt1;
00210 int ret;
00211 int index = av_index_search_timestamp(st, timestamp - DELAY_FRAMES, flags);
00212 uint32_t lastframe;
00213
00214
00215 if (index >= 0){
00216 c->curframe = st->index_entries[index].pos;
00217 return 0;
00218 }
00219
00220 if(timestamp < 0 || timestamp >= c->fcount)
00221 return -1;
00222 timestamp -= DELAY_FRAMES;
00223
00224
00225 lastframe = c->curframe;
00226 if(c->frames_noted) c->curframe = c->frames_noted - 1;
00227 while(c->curframe < timestamp){
00228 ret = av_read_frame(s, pkt);
00229 if (ret < 0){
00230 c->curframe = lastframe;
00231 return -1;
00232 }
00233 av_free_packet(pkt);
00234 }
00235 return 0;
00236 }
00237
00238
00239 AVInputFormat mpc_demuxer = {
00240 "mpc",
00241 NULL_IF_CONFIG_SMALL("Musepack"),
00242 sizeof(MPCContext),
00243 mpc_probe,
00244 mpc_read_header,
00245 mpc_read_packet,
00246 mpc_read_close,
00247 mpc_read_seek,
00248 .extensions = "mpc",
00249 };