[FFmpeg-devel] [PATCH] 1bpp and 2bpp support in QTRLE

Michael Niedermayer michaelni
Sun Aug 31 16:52:53 CEST 2008


On Sun, Aug 31, 2008 at 12:13:13PM +0200, Stefan Gehrer wrote:
> Hi,
>
> patch is based on Roberto's patch here
> (http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-January/022046.html)
> and adds support for 1bpp and 2bpp decoding in qtrle.c.
> The samples from http://samples.mplayerhq.hu/V-codecs/QTRLE/
> play visually ok, but the 1bpp decoding produces warnings
> about trying to write pixels past the end of the image.
>
> Stefan

> Index: qtrle.c
> ===================================================================
> --- qtrle.c	(revision 15121)
> +++ qtrle.c	(working copy)

[...]

>  static void qtrle_decode_2bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
>  {
> +    int rle_code, i;
> +    int pixel_ptr;
> +    int row_inc = s->frame.linesize[0];
> +    unsigned char pi[16];  /* 16 palette indices */
> +    unsigned char *rgb = s->frame.data[0];
> +    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
> +
> +    while (lines_to_change--) {
> +        CHECK_STREAM_PTR(2);
> +        pixel_ptr = row_ptr + (16 * (s->buf[stream_ptr++] - 1));
> +
> +        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
> +            if (rle_code == 0) {
> +                /* there's another skip code in the stream */
> +                CHECK_STREAM_PTR(1);
> +                pixel_ptr += (16 * (s->buf[stream_ptr++] - 1));
> +                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
> +            } else if (rle_code < 0) {
> +                /* decode the run length code */
> +                rle_code = -rle_code;
> +                /* get the next 4 bytes from the stream, treat them as palette
> +                 * indices, and output them rle_code times */
> +                CHECK_STREAM_PTR(4);
> +                for (i = 15; i >= 0; i--) {
> +                    pi[15-i] = ((s->buf[stream_ptr]) >> ((i *2) & 0x07)) & 0x03;
> +                    stream_ptr+= ((i & 0x03) == 0);
> +                }
> +                CHECK_PIXEL_PTR(rle_code * 16);
> +
> +                while (rle_code--) {
> +                    for (i = 0; i < 16; i++)
> +                        rgb[pixel_ptr++] = pi[i];
> +                }
> +            } else {
> +                /* copy the same pixel directly to output 4 times */
> +                rle_code *= 4;
> +                CHECK_STREAM_PTR(rle_code);
> +                CHECK_PIXEL_PTR(rle_code*4);
> +
> +                while (rle_code--) {
> +                    rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 6) & 0x03;
> +                    rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x03;
> +                    rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 2) & 0x03;
> +                    rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x03;
> +                }
> +            }
> +        }
> +        row_ptr += row_inc;
> +    }
>  }

this looks like it can be in a common function handling 4bpp as well.
it that is marked as inline gcc should optimize the bpp out.


>  
>  static void qtrle_decode_4bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
> @@ -347,10 +442,13 @@
>      s->avctx = avctx;
>      switch (avctx->bits_per_sample) {
>      case 1:
> +    case 33:
> +        avctx->pix_fmt = PIX_FMT_MONOWHITE;
> +        break;
> +
>      case 2:
>      case 4:
>      case 8:
> -    case 33:
>      case 34:
>      case 36:
>      case 40:

> @@ -387,6 +485,7 @@
>      QtrleContext *s = avctx->priv_data;
>      int header, start_line;
>      int stream_ptr, height, row_ptr;
> +    int has_palette = 0;
>  
>      s->buf = buf;
>      s->size = buf_size;
> @@ -433,28 +532,19 @@
>      case 2:
>      case 34:
>          qtrle_decode_2bpp(s, stream_ptr, row_ptr, height);
> +        has_palette = 1;
>          break;
>  
>      case 4:
>      case 36:
>          qtrle_decode_4bpp(s, stream_ptr, row_ptr, height);
> -        /* make the palette available on the way out */
> -        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
> -        if (s->avctx->palctrl->palette_changed) {
> -            s->frame.palette_has_changed = 1;
> -            s->avctx->palctrl->palette_changed = 0;
> -        }
> +        has_palette = 1;
>          break;
>  
>      case 8:
>      case 40:
>          qtrle_decode_8bpp(s, stream_ptr, row_ptr, height);
> -        /* make the palette available on the way out */
> -        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
> -        if (s->avctx->palctrl->palette_changed) {
> -            s->frame.palette_has_changed = 1;
> -            s->avctx->palctrl->palette_changed = 0;
> -        }
> +        has_palette = 1;
>          break;
>  
>      case 16:
> @@ -474,6 +564,16 @@
>              avctx->bits_per_sample);
>          break;
>      }
> +
> +    if(has_palette) {
> +        /* make the palette available on the way out */
> +        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
> +        if (s->avctx->palctrl->palette_changed) {
> +            s->frame.palette_has_changed = 1;
> +            s->avctx->palctrl->palette_changed = 0;
> +        }
> +    }
> +
>  done:
>      *data_size = sizeof(AVFrame);
>      *(AVFrame*)data = s->frame;

The avctx->palctrl->palette_changed stuff is deprecated due to race
conditions caused by the design.

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The educated differ from the uneducated as much as the living from the
dead. -- 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/20080831/15c557ed/attachment.pgp>



More information about the ffmpeg-devel mailing list