[FFmpeg-devel] [PATCH] Musepack SV8 demuxer and decoder
Kostya
kostya.shishkov
Sat Nov 3 11:42:22 CET 2007
On Sat, Nov 03, 2007 at 04:19:01AM +0100, Michael Niedermayer wrote:
> Hi
>
> On Fri, Nov 02, 2007 at 09:58:59AM +0200, Kostya wrote:
> > Here is $subj. I will try to provide samples soon.
samples are at ftp://upload.mplayerhq.hu/incoming/mpc8_samples.tar (partially uploaded)
> [...]
>
> > + code = get_bits(gb, mpc8_cnk_len[k-1][n-1] - 1);
> > +
> > + if (code >= mpc8_cnk_lost[k-1][n-1])
> > + code = ((code << 1) | get_bits1(gb)) - mpc8_cnk_lost[k-1][n-1];
>
> duplicate
what is duplicated?
> > +
> > + do {
> > + n--;
> > + if (code >= C[n]) {
> > + bits |= 1 << n;
> > + code -= C[n];
> > + C -= 32;
> > + k--;
> > + }
> > + } while(k > 0);
>
> interresting way to store bits
It's not my invention
> [...]
> > + bands[maxband - 1].res[0] = get_vlc2(gb, res_vlc[0].table, MPC8_RES_BITS, 2);
> > + bands[maxband - 1].res[1] = get_vlc2(gb, res_vlc[0].table, MPC8_RES_BITS, 2);
> > + if(bands[maxband - 1].res[0] > 15) bands[maxband - 1].res[0] -= 17;
> > + if(bands[maxband - 1].res[1] > 15) bands[maxband - 1].res[1] -= 17;
> > + for(i = maxband - 2; i >= 0; i--){
> > + bands[i].res[0] = get_vlc2(gb, res_vlc[bands[i+1].res[0] > 2].table, MPC8_RES_BITS, 2) + bands[i + 1].res[0];
> > + bands[i].res[1] = get_vlc2(gb, res_vlc[bands[i+1].res[1] > 2].table, MPC8_RES_BITS, 2) + bands[i + 1].res[1];
> > + if(bands[i].res[0] > 15) bands[i].res[0] -= 17;
> > + if(bands[i].res[1] > 15) bands[i].res[1] -= 17;
> > + }
>
> for(i = maxband - 1; i >= 0; i--){
> for(j=0; j<2; j++){
> last[j] = get_vlc2(gb, res_vlc[last[j] > 2].table, MPC8_RES_BITS, 2) + last[j];
> if(last[j] > 15) last[j] -= 17;
> bands[i].res[j]= last[j];
> }
> }
>
>
> [...]
> > +const static uint8_t mpc8_cnk_len[16][32] =
> > +{
> > + {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
> [...]
> > +const static uint32_t mpc8_cnk_lost[16][32] =
> > +{
> > + {0, 0, 1, 0, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
> [...]
> > +static const uint8_t mpc8_log2[32] =
> > +{ 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5};
> > +
> > +static const uint8_t mpc8_log2_lost[32] =
> > +{ 0, 1, 0, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31};
>
> these are nearly duplicate maybe you could change the code a little so
> only 1 would be needed
it's related to Golomb (not Rice) codes
first are obtained as ceil(log2(n)), the second is 2^ceil(log2(n)) - n
I'm trying to find a way to completely remove them
> [...]
> > +static const uint16_t mpc8_q6_codes[2][MPC8_Q6_SIZE] = {
> > +{
> > + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0004, 0x0003,
> > + 0x0004, 0x0005, 0x0005, 0x0006, 0x0004, 0x0005, 0x0004, 0x0003,
> > + 0x0005, 0x0006, 0x0007, 0x0007, 0x0006, 0x0007, 0x0008, 0x0009,
> > + 0x0005, 0x0006, 0x0007, 0x0004, 0x0005, 0x0006, 0x0007,
> > +},
> > +{
> > + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0004, 0x0005, 0x0004,
> > + 0x0005, 0x0006, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A,
> > + 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0007, 0x0008, 0x0009,
> > + 0x0006, 0x0007, 0x0005, 0x0006, 0x0007, 0x0002, 0x0003,
> > +}
> > +};
>
> this and several other tabels fit in 8bit
shrinked
> [...]
> > +/* shamelessly stolen from nutdec.c */
> > +static uint64_t get_v(ByteIOContext *bc){
>
> code duplication
I will prepare a patch to move it to avio.[ch]. Should it be
left as inline or prototype + function body?
> [...]
> > +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;
> > + int i, t, seekd;
> > + GetBitContext gb;
> > +
> > + url_fseek(&s->pb, off, SEEK_SET);
> > + mpc8_get_chunk_header(&s->pb, &tag, &size);
> > + if(tag != TAG_SEEKTABLE){
> > + av_log(s, AV_LOG_ERROR, "No seek table at given position\n");
> > + return;
> > + }
> > + if(!(buf = av_malloc(size)))
> > + return;
> > + get_buffer(&s->pb, buf, size);
> > + init_get_bits(&gb, buf, size * 8);
> > + size = gb_get_v(&gb);
>
> check size please
>
> [...]
> > + s->start_time = 0;
> > + s->duration = c->samples * AV_TIME_BASE / st->codec->sample_rate;
>
> /** decoding: position of the first frame of the component, in
> AV_TIME_BASE fractional seconds. NEVER set this value directly:
> ^^^^^
> it is deduced from the AVStream values. */
> int64_t start_time;
> /** decoding: duration of the stream, in AV_TIME_BASE fractional
> seconds. NEVER set this value directly: it is deduced from the
> ^^^^^
> AVStream values. */
> int64_t duration;
Oops, will set stream duration instead.
I will send a patch when I resolve Golomb-like codes reading and get_v()
will be made common.
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
More information about the ffmpeg-devel
mailing list