[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