• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/mpc.c

Go to the documentation of this file.
00001 /*
00002  * Musepack demuxer
00003  * Copyright (c) 2006 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 "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         /* skip ID3 tags and try again */
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         /* read ID3 tags */
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     /* scan for seekpoints */
00118     st->start_time = 0;
00119     st->duration = c->fcount;
00120 
00121     /* try to read APE tags */
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     /* if found, seek there */
00215     if (index >= 0){
00216         c->curframe = st->index_entries[index].pos;
00217         return 0;
00218     }
00219     /* if timestamp is out of bounds, return error */
00220     if(timestamp < 0 || timestamp >= c->fcount)
00221         return -1;
00222     timestamp -= DELAY_FRAMES;
00223     /* seek to the furthest known position and read packets until
00224        we reach desired position */
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 };

Generated on Fri Sep 16 2011 17:17:39 for FFmpeg by  doxygen 1.7.1