[FFmpeg-devel] [PATCH] Electronic Arts MAD Decoder

Michael Niedermayer michaelni
Tue Jun 9 23:07:53 CEST 2009


On Mon, Jun 08, 2009 at 12:06:53PM +1000, Peter Ross wrote:
> Updated patch enclosed. Thanks to Diego and Reimar for the review.
> 
> On Sun, Jun 07, 2009 at 11:53:38AM +0200, Reimar D?ffinger wrote:
> > On Sun, Jun 07, 2009 at 04:24:59PM +1000, Peter Ross wrote:
> > 
> > except that I think your code is wrong and you should be using
> > ref_linesize for the ref_y offset.
> 
> Well spotted.
> 
> > 
> > > +        OPEN_READER(re, &s->gb);
> > > +        /* now quantify & encode AC coefficients */
> > > +        for(;;) {
> > > +            UPDATE_CACHE(re, &s->gb);
> > 
> > I know a lot of codecs use it, but is using this extremely lowlevel API
> > really the best way to do? Seems to me like it will result in a lot of
> > buggy an badly maintainable code.
> 
> The bulk of this is plagarised from mpeg12.c. Whereas the previous EA TQI
> codec used the MPEG-1 intra coefficient encoding method, for MAD the
> authors have changed the coding for the escaped RL values.
> 
> So I have left this verbose low-level code in with a comment. Suggestions
> on how to better reuse the code without bloat are welcome.

i wish i had an idea on how to factorize that, sadly i have no clean idea


[...]
> +static inline void mad_decode_block_intra(MadContext * t, DCTELEM * block)
> +{
> +    MpegEncContext *s = &t->s;
> +    int level, i, j, run;
> +    RLTable *rl = &ff_rl_mpeg1;
> +    const uint8_t *scantable = s->intra_scantable.permutated;
> +    int16_t *quant_matrix = s->intra_matrix;
> +
> +    block[0] = (128 + get_sbits(&s->gb, 8)) * quant_matrix[0];
> +
> +    /* The RL decoder is derived from mpeg1_decode_block_intra;
> +       Escaped level and run values a decoded differently */
> +    {
> +        OPEN_READER(re, &s->gb);
> +        /* now quantify & encode AC coefficients */
> +        for (;;) {
> +            UPDATE_CACHE(re, &s->gb);
> +            GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0);
> +
> +            if (level == 127) {
> +                break;
> +            } else if (level != 0) {
> +                i += run;
> +                j = scantable[i];
> +                level = (level*quant_matrix[j]) >> 4;
> +                level = (level-1)|1;
> +                level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1);
> +                LAST_SKIP_BITS(re, &s->gb, 1);
> +            } else {
> +                /* escape */
> +                UPDATE_CACHE(re, &s->gb);
> +                level = SHOW_SBITS(re, &s->gb, 10); SKIP_BITS(re, &s->gb, 10);
> +
> +                UPDATE_CACHE(re, &s->gb);
> +                run = SHOW_UBITS(re, &s->gb, 6)+1; LAST_SKIP_BITS(re, &s->gb, 6);
> +
> +                i += run;
> +                j = scantable[i];
> +                if (level < 0) {
> +                    level = -level;
> +                    level = (level*quant_matrix[j]) >> 4;
> +                    level = (level-1)|1;
> +                    level = -level;
> +                } else {
> +                    level = (level*quant_matrix[j]) >> 4;
> +                    level = (level-1)|1;
> +                }
> +            }
> +            if (i > 63) {
> +                av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y);
> +		return;

tabs


[...]
> +static void mad_decode_mb(MadContext *t, int inter)
> +{
> +    MpegEncContext *s = &t->s;
> +    int mv_map = 0;
> +    int mv_x, mv_y;
> +    int j;
> +
> +    if (inter) {

> +        if (show_bits(&s->gb, 2) & 0x3) {
> +            if (show_bits(&s->gb, 1) & 0x1) {  // vlc: 1b
> +                skip_bits(&s->gb, 1);
> +                mv_map = 63;
> +            } else {   // vlc: 01b
> +                skip_bits(&s->gb, 2);
> +                mv_map = get_bits(&s->gb, 6);
> +            }
> +            mv_x = mad_decode_motion(&s->gb);
> +            mv_y = mad_decode_motion(&s->gb);
> +        } else {  // vlc: 00b
> +            skip_bits(&s->gb, 2);
> +            mv_map = 0;
> +        }

v= decode210();

if(v<2){
    if(v){
    }else{
    }
}else{
}


[...]
> +static int mad_decode_frame(AVCodecContext *avctx,
> +                            void *data, int *data_size,
> +                            AVPacket *avpkt)
> +{
> +    const uint8_t *buf = avpkt->data;
> +    int buf_size       = avpkt->size;
> +    const uint8_t *buf_end = buf+buf_size;
> +    MadContext *t     = avctx->priv_data;
> +    MpegEncContext *s = &t->s;
> +    int chunk_type;
> +    int inter;
> +
> +    if (buf_size < 17) {
> +        av_log(avctx, AV_LOG_ERROR, "Input buffer too small\n");
> +        *data_size = 0;
> +        return -1;
> +    }
> +
> +    chunk_type = AV_RL32(&buf[0]);
> +    inter = (chunk_type == MADm_TAG || chunk_type == MADe_TAG);
> +    buf += 8;
> +
> +    av_reduce(&avctx->time_base.num, &avctx->time_base.den,
> +              AV_RL16(&buf[6]), 1000, 1<<30);
> +
> +    s->width  = AV_RL16(&buf[8]);
> +    s->height = AV_RL16(&buf[10]);
> +    mad_calc_intra_matrix(t, buf[13]);
> +    buf += 16;
> +
> +    if (avctx->width != s->width || avctx->height != s->height) {
> +        if (avcodec_check_dimensions(avctx, s->width, s->height) < 0)
> +            return -1;
> +        avcodec_set_dimensions(avctx, s->width, s->height);
> +        if (t->frame.data[0])
> +            avctx->release_buffer(avctx, &t->frame);
> +    }
> +
> +    t->frame.reference    = 1;

> +    t->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;

this looks unneeded

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The worst form of inequality is to try to make unequal things equal.
-- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090609/1544a2b7/attachment.pgp>



More information about the ffmpeg-devel mailing list