mpc8.c 8.9 KB
Newer Older
K
Kostya Shishkov 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Musepack SV8 demuxer
 * Copyright (c) 2007 Konstantin Shishkov
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
21

22
#include "libavcodec/get_bits.h"
23
#include "libavcodec/unary.h"
A
Anton Khirnov 已提交
24
#include "apetag.h"
K
Kostya Shishkov 已提交
25
#include "avformat.h"
26
#include "internal.h"
27
#include "avio_internal.h"
K
Kostya Shishkov 已提交
28 29

/// Two-byte MPC tag
30
#define MKMPCTAG(a, b) ((a) | ((b) << 8))
K
Kostya Shishkov 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

#define TAG_MPCK MKTAG('M','P','C','K')

/// Reserved MPC tags
enum MPCPacketTags{
    TAG_STREAMHDR   = MKMPCTAG('S','H'),
    TAG_STREAMEND   = MKMPCTAG('S','E'),

    TAG_AUDIOPACKET = MKMPCTAG('A','P'),

    TAG_SEEKTBLOFF  = MKMPCTAG('S','O'),
    TAG_SEEKTABLE   = MKMPCTAG('S','T'),

    TAG_REPLAYGAIN  = MKMPCTAG('R','G'),
    TAG_ENCINFO     = MKMPCTAG('E','I'),
};

static const int mpc8_rate[8] = { 44100, 48000, 37800, 32000, -1, -1, -1, -1 };

50
typedef struct MPCContext {
K
Kostya Shishkov 已提交
51 52 53
    int ver;
    int64_t header_pos;
    int64_t samples;
54 55

    int64_t apetag_start;
K
Kostya Shishkov 已提交
56 57
} MPCContext;

58
static inline int64_t bs_get_v(const uint8_t **bs)
59
{
60
    uint64_t v = 0;
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    int br = 0;
    int c;

    do {
        c = **bs; (*bs)++;
        v <<= 7;
        v |= c & 0x7F;
        br++;
        if (br > 10)
            return -1;
    } while (c & 0x80);

    return v - br;
}

K
Kostya Shishkov 已提交
76 77
static int mpc8_probe(AVProbeData *p)
{
78 79
    const uint8_t *bs = p->buf + 4;
    const uint8_t *bs_end = bs + p->buf_size;
80 81
    int64_t size;

82 83 84 85
    if (p->buf_size < 16)
        return 0;
    if (AV_RL32(p->buf) != TAG_MPCK)
        return 0;
86 87 88
    while (bs < bs_end + 3) {
        int header_found = (bs[0] == 'S' && bs[1] == 'H');
        if (bs[0] < 'A' || bs[0] > 'Z' || bs[1] < 'A' || bs[1] > 'Z')
89
            return 0;
90 91 92
        bs += 2;
        size = bs_get_v(&bs);
        if (size < 2)
93
            return 0;
W
wm4 已提交
94
        if (size >= bs_end - bs + 2)
95
            return AVPROBE_SCORE_EXTENSION - 1; // seems to be valid MPC but no header yet
96
        if (header_found) {
97 98 99 100 101
            if (size < 11 || size > 28)
                return 0;
            if (!AV_RL32(bs)) //zero CRC is invalid
                return 0;
            return AVPROBE_SCORE_MAX;
102 103 104
        } else {
            bs += size - 2;
        }
105
    }
106
    return 0;
K
Kostya Shishkov 已提交
107 108 109 110
}

static inline int64_t gb_get_v(GetBitContext *gb)
{
111
    uint64_t v = 0;
K
Kostya Shishkov 已提交
112 113 114 115 116 117 118 119 120 121 122 123
    int bits = 0;
    while(get_bits1(gb) && bits < 64-7){
        v <<= 7;
        v |= get_bits(gb, 7);
        bits += 7;
    }
    v <<= 7;
    v |= get_bits(gb, 7);

    return v;
}

124
static void mpc8_get_chunk_header(AVIOContext *pb, int *tag, int64_t *size)
K
Kostya Shishkov 已提交
125 126
{
    int64_t pos;
127
    pos = avio_tell(pb);
128
    *tag = avio_rl16(pb);
129
    *size = ffio_read_varlen(pb);
130
    *size -= avio_tell(pb) - pos;
K
Kostya Shishkov 已提交
131 132 133 134 135 136 137 138
}

static void mpc8_parse_seektable(AVFormatContext *s, int64_t off)
{
    MPCContext *c = s->priv_data;
    int tag;
    int64_t size, pos, ppos[2];
    uint8_t *buf;
139
    int i, t, seekd, ret;
K
Kostya Shishkov 已提交
140 141
    GetBitContext gb;

142 143
    if (s->nb_streams == 0) {
        av_log(s, AV_LOG_ERROR, "No stream added before parsing seek table\n");
144 145 146
        return;
    }

A
Anton Khirnov 已提交
147
    avio_seek(s->pb, off, SEEK_SET);
148
    mpc8_get_chunk_header(s->pb, &tag, &size);
K
Kostya Shishkov 已提交
149 150 151 152
    if(tag != TAG_SEEKTABLE){
        av_log(s, AV_LOG_ERROR, "No seek table at given position\n");
        return;
    }
153
    if (size > INT_MAX/10 || size<=0) {
154
        av_log(s, AV_LOG_ERROR, "Bad seek table size\n");
155 156
        return;
    }
157
    if(!(buf = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE)))
K
Kostya Shishkov 已提交
158
        return;
159 160 161 162 163 164
    ret = avio_read(s->pb, buf, size);
    if (ret != size) {
        av_log(s, AV_LOG_ERROR, "seek table truncated\n");
        av_free(buf);
        return;
    }
165
    memset(buf+size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
166

K
Kostya Shishkov 已提交
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    init_get_bits(&gb, buf, size * 8);
    size = gb_get_v(&gb);
    if(size > UINT_MAX/4 || size > c->samples/1152){
        av_log(s, AV_LOG_ERROR, "Seek table is too big\n");
        return;
    }
    seekd = get_bits(&gb, 4);
    for(i = 0; i < 2; i++){
        pos = gb_get_v(&gb) + c->header_pos;
        ppos[1 - i] = pos;
        av_add_index_entry(s->streams[0], pos, i, 0, 0, AVINDEX_KEYFRAME);
    }
    for(; i < size; i++){
        t = get_unary(&gb, 1, 33) << 12;
        t += get_bits(&gb, 12);
        if(t & 1)
            t = -(t & ~1);
        pos = (t >> 1) + ppos[0]*2 - ppos[1];
        av_add_index_entry(s->streams[0], pos, i << seekd, 0, 0, AVINDEX_KEYFRAME);
        ppos[1] = ppos[0];
        ppos[0] = pos;
    }
    av_free(buf);
}

static void mpc8_handle_chunk(AVFormatContext *s, int tag, int64_t chunk_pos, int64_t size)
{
194
    AVIOContext *pb = s->pb;
K
Kostya Shishkov 已提交
195 196 197 198
    int64_t pos, off;

    switch(tag){
    case TAG_SEEKTBLOFF:
199
        pos = avio_tell(pb) + size;
200
        off = ffio_read_varlen(pb);
K
Kostya Shishkov 已提交
201
        mpc8_parse_seektable(s, chunk_pos + off);
A
Anton Khirnov 已提交
202
        avio_seek(pb, pos, SEEK_SET);
K
Kostya Shishkov 已提交
203 204
        break;
    default:
205
        avio_skip(pb, size);
K
Kostya Shishkov 已提交
206 207 208
    }
}

209
static int mpc8_read_header(AVFormatContext *s)
K
Kostya Shishkov 已提交
210 211
{
    MPCContext *c = s->priv_data;
212
    AVIOContext *pb = s->pb;
K
Kostya Shishkov 已提交
213 214 215 216
    AVStream *st;
    int tag = 0;
    int64_t size, pos;

217
    c->header_pos = avio_tell(pb);
218
    if(avio_rl32(pb) != TAG_MPCK){
K
Kostya Shishkov 已提交
219
        av_log(s, AV_LOG_ERROR, "Not a Musepack8 file\n");
220
        return AVERROR_INVALIDDATA;
K
Kostya Shishkov 已提交
221 222
    }

223
    while(!avio_feof(pb)){
224
        pos = avio_tell(pb);
K
Kostya Shishkov 已提交
225
        mpc8_get_chunk_header(pb, &tag, &size);
W
wm4 已提交
226 227 228 229
        if (size < 0) {
            av_log(s, AV_LOG_ERROR, "Invalid chunk length\n");
            return AVERROR_INVALIDDATA;
        }
K
Kostya Shishkov 已提交
230 231 232 233 234 235
        if(tag == TAG_STREAMHDR)
            break;
        mpc8_handle_chunk(s, tag, pos, size);
    }
    if(tag != TAG_STREAMHDR){
        av_log(s, AV_LOG_ERROR, "Stream header not found\n");
236
        return AVERROR_INVALIDDATA;
K
Kostya Shishkov 已提交
237
    }
238
    pos = avio_tell(pb);
239
    avio_skip(pb, 4); //CRC
240
    c->ver = avio_r8(pb);
K
Kostya Shishkov 已提交
241
    if(c->ver != 8){
242
        avpriv_report_missing_feature(s, "Stream version %d", c->ver);
243
        return AVERROR_PATCHWELCOME;
K
Kostya Shishkov 已提交
244
    }
245 246
    c->samples = ffio_read_varlen(pb);
    ffio_read_varlen(pb); //silence samples at the beginning
K
Kostya Shishkov 已提交
247

248
    st = avformat_new_stream(s, NULL);
K
Kostya Shishkov 已提交
249 250
    if (!st)
        return AVERROR(ENOMEM);
251 252 253
    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
    st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK8;
    st->codecpar->bits_per_coded_sample = 16;
K
Kostya Shishkov 已提交
254

255
    if (ff_get_extradata(s, st->codecpar, pb, 2) < 0)
P
Paul B Mahol 已提交
256
        return AVERROR(ENOMEM);
K
Kostya Shishkov 已提交
257

258 259 260
    st->codecpar->channels = (st->codecpar->extradata[1] >> 4) + 1;
    st->codecpar->sample_rate = mpc8_rate[st->codecpar->extradata[0] >> 5];
    avpriv_set_pts_info(st, 32, 1152  << (st->codecpar->extradata[1]&3)*2, st->codecpar->sample_rate);
261
    st->start_time = 0;
262
    st->duration = c->samples / (1152 << (st->codecpar->extradata[1]&3)*2);
263
    size -= avio_tell(pb) - pos;
264 265
    if (size > 0)
        avio_skip(pb, size);
K
Kostya Shishkov 已提交
266

267
    if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
A
Anton Khirnov 已提交
268
        int64_t pos = avio_tell(s->pb);
269
        c->apetag_start = ff_ape_parse_tag(s);
A
Anton Khirnov 已提交
270 271 272
        avio_seek(s->pb, pos, SEEK_SET);
    }

K
Kostya Shishkov 已提交
273 274 275 276 277 278 279 280 281
    return 0;
}

static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    MPCContext *c = s->priv_data;
    int tag;
    int64_t pos, size;

282
    while(!avio_feof(s->pb)){
283
        pos = avio_tell(s->pb);
284 285 286 287 288

        /* don't return bogus packets with the ape tag data */
        if (c->apetag_start && pos >= c->apetag_start)
            return AVERROR_EOF;

289
        mpc8_get_chunk_header(s->pb, &tag, &size);
290 291
        if (size < 0)
            return -1;
K
Kostya Shishkov 已提交
292
        if(tag == TAG_AUDIOPACKET){
293
            if(av_get_packet(s->pb, pkt, size) < 0)
K
Kostya Shishkov 已提交
294 295
                return AVERROR(ENOMEM);
            pkt->stream_index = 0;
296
            pkt->duration     = 1;
K
Kostya Shishkov 已提交
297 298 299
            return 0;
        }
        if(tag == TAG_STREAMEND)
300
            return AVERROR_EOF;
K
Kostya Shishkov 已提交
301 302
        mpc8_handle_chunk(s, tag, pos, size);
    }
303
    return AVERROR_EOF;
K
Kostya Shishkov 已提交
304 305 306 307 308 309 310 311
}

static int mpc8_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
{
    AVStream *st = s->streams[stream_index];
    int index = av_index_search_timestamp(st, timestamp, flags);

    if(index < 0) return -1;
312 313
    if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0)
        return -1;
314
    ff_update_cur_dts(s, st, st->index_entries[index].timestamp);
K
Kostya Shishkov 已提交
315 316 317 318
    return 0;
}


319
AVInputFormat ff_mpc8_demuxer = {
320 321 322 323 324 325 326
    .name           = "mpc8",
    .long_name      = NULL_IF_CONFIG_SMALL("Musepack SV8"),
    .priv_data_size = sizeof(MPCContext),
    .read_probe     = mpc8_probe,
    .read_header    = mpc8_read_header,
    .read_packet    = mpc8_read_packet,
    .read_seek      = mpc8_read_seek,
K
Kostya Shishkov 已提交
327
};