[FFmpeg-devel] [PATCH] Video decoder and demuxer for AMV files

Aurelien Jacobs aurel
Thu Sep 27 10:53:20 CEST 2007


On Wed, 26 Sep 2007 17:18:27 +0700
"Vladimir Voroshilov" <voroshil at gmail.com> wrote:

> 2007/9/26, Aurelien Jacobs <aurel at gnuage.org>:
> > Vladimir Voroshilov wrote:
> >
> [...]
> > > I forget to say that resulting image is flipped upside-down.
> > > Please anybody help me with fixing this.
> >
> > Short answer: negative stride
> >
> > Longer answer: Look at this code from mjpeg_decode_scan():
> >    ptr = s->picture.data[c] +
> >             (((s->linesize[c] * (v * mb_y + y) * 8) +
> >             (h * mb_x + x) * 8) >> s->avctx->lowres);
> >
> > To flip the image upside-down, s->picture.data[c] need to be
> > replaced by a pointer to (s->picture.data[c] + size of the image
> > buffer - size of one line), and s->linesize[c] must be negative.
> >
> > That's the basic principle. You will probably need to do other
> > small related changes. And ensure that the code still behave
> > the same way as it does now for other mjpeg codecs.
> >
> 
> Thanks you for info!
> I modified mjpeg_decode_scan routine.
> Now decoder produces correct (not flipped) picture.
> 
> All code enclosed into codec id check, thus there should not be any
> problems with other mjpeg codecs.
> 
> Updated patch is attached.
> 
> Index: libavcodec/mjpegdec.c
> ===================================================================
> --- libavcodec/mjpegdec.c	(revision 10560)
> +++ libavcodec/mjpegdec.c	(working copy)
> @@ -662,6 +662,15 @@
>      int EOBRUN = 0;
>  
>      if(Ah) return 0; /* TODO decode refinement planes too */
> +
> +    if(s->avctx->codec->id==CODEC_ID_AMVVIDEO) {
> +        //Modify pointers for getting upside-down flipped picture
> +        for(i=0; i < nb_components; i++) {
> +            int c = s->comp_index[i];
> +            s->picture.data[c] += (s->linesize[c] * (s->v_scount[i]
> * 8 * s->mb_height - 1));
> +            s->linesize[c] *= -1;
> +        }
> +    }
>      for(mb_y = 0; mb_y < s->mb_height; mb_y++) {
>          for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
>              if (s->restart_interval && !s->restart_count)
> @@ -717,6 +726,14 @@
>              }
>          }
>      }
> +    if(s->avctx->codec->id==CODEC_ID_AMVVIDEO) {
> +        //Restore pointers to original values
> +        for(i=0; i < nb_components; i++) {
> +            int c = s->comp_index[i];
> +            s->picture.data[c] += (s->linesize[c] * (s->v_scount[i]
> * 8 * s->mb_height - 1));
> +            s->linesize[c] *= -1;
> +        }
> +    }
>      return 0;
>  }

This is ugly IMO.
I would prefer not seeing any test related to one specific codec (ie. AMV)
inside the generic internal decoding function used by a lot of codecs
variations.
At worst, you could move this code around the mjpeg_decode_scan() call
in sp5xdec.c.
At best you could init s->picture.data and s->picture.linesize directly
to the proper value at amv codec init, but that may not be so simple.

Aurel




More information about the ffmpeg-devel mailing list