[FFmpeg-devel] [PATCH] use correct colorspace in Cinepak decoder

Michael Niedermayer michaelni at gmx.at
Sun Feb 17 17:04:10 CET 2013


On Tue, Feb 12, 2013 at 04:32:05PM +0100, u-bo1b at 0w.se wrote:
> Hello,
> 
> Attaching the patch.
> 
> Regards,
> Rl

>  cinepak.c |  216 +++++++++++++++++++++++++++++++-------------------------------
>  1 file changed, 110 insertions(+), 106 deletions(-)
> 49ef9d5e81503385afb736e2b6b60da7a3ffa714  cinepak-decoder-colorspace.patch
> --- libavcodec/cinepak.c.ori	2013-02-10 21:53:01.783361913 +0100
> +++ libavcodec/cinepak.c	2013-02-12 10:41:25.927936697 +0100
> @@ -28,6 +28,9 @@
>   *   http://www.csse.monash.edu.au/~timf/
>   * @see For more information on the quirky data inside Sega FILM/CPK files, visit:
>   *   http://wiki.multimedia.cx/index.php?title=Sega_FILM
> + *
> + * Cinepak colorspace support (c) 2013 Rl, Aetey Global Technologies AB
> + * @author Cinepak colorspace, Rl, Aetey Global Technologies AB
>   */
>  
>  #include <stdio.h>
> @@ -40,8 +43,7 @@
>  
>  
>  typedef struct {
> -    uint8_t  y0, y1, y2, y3;
> -    uint8_t  u, v;
> +    uint8_t  r[4], g[4], b[4];
>  } cvid_codebook;
>  
>  #define MAX_STRIPS      32
> @@ -99,23 +101,36 @@
>                  break;
>  
>              if (n == 6) {
> -                codebook[i].y0 = *data++;
> -                codebook[i].y1 = *data++;
> -                codebook[i].y2 = *data++;
> -                codebook[i].y3 = *data++;
> -                codebook[i].u  = 128 + *data++;
> -                codebook[i].v  = 128 + *data++;
> +                int r, g, b, u, v;
> +                int k;
> +                codebook[i].r[0]=codebook[i].g[0]=codebook[i].b[0] = *data++;
> +                codebook[i].r[1]=codebook[i].g[1]=codebook[i].b[1] = *data++;
> +                codebook[i].r[2]=codebook[i].g[2]=codebook[i].b[2] = *data++;
> +                codebook[i].r[3]=codebook[i].g[3]=codebook[i].b[3] = *data++;
> +                u = *(int8_t *)data++;
> +                v = *(int8_t *)data++;
> +                for(k=0; k<4; ++k) {
> +                    r = codebook[i].r[k] + v*2;
> +                    g = codebook[i].g[k] - (u/2) - v;
> +                    b = codebook[i].b[k] + u*2;

> +                    if(     r <   0) r = 0;
> +                    else if(r > 255) r = 255;
> +                    if(     g <   0) g = 0;
> +                    else if(g > 255) g = 255;
> +                    if(     b <   0) b = 0;
> +                    else if(b > 255) b = 255;

see av_clip_uint8()


> +                    codebook[i].r[k] = r;
> +                    codebook[i].g[k] = g;
> +                    codebook[i].b[k] = b;
> +                }
>              } else {
>                  /* this codebook type indicates either greyscale or
> -                 * palettized video; if palettized, U & V components will
> -                 * not be used so it is safe to set them to 128 for the
> -                 * benefit of greyscale rendering in YUV420P */
> -                codebook[i].y0 = *data++;
> -                codebook[i].y1 = *data++;
> -                codebook[i].y2 = *data++;
> -                codebook[i].y3 = *data++;
> -                codebook[i].u  = 128;
> -                codebook[i].v  = 128;

> +                 * palettized video, store as grey rgb24 to make it
> +                 * robust even when the frame is considered to be rgb24 */
> +                codebook[i].r[0]=codebook[i].g[0]=codebook[i].b[0] = *data++;
> +                codebook[i].r[1]=codebook[i].g[1]=codebook[i].b[1] = *data++;
> +                codebook[i].r[2]=codebook[i].g[2]=codebook[i].b[2] = *data++;
> +                codebook[i].r[3]=codebook[i].g[3]=codebook[i].b[3] = *data++;

this can be factored out of the if/else


>              }
>          }
>      }
> @@ -126,25 +141,20 @@
>  {
>      const uint8_t   *eod = (data + size);
>      uint32_t         flag, mask;
> -    cvid_codebook   *codebook;
> +    cvid_codebook   *codebook, *cb2;
>      unsigned int     x, y;
> -    uint32_t         iy[4];
> -    uint32_t         iu[2];
> -    uint32_t         iv[2];
> +    uint32_t         ir[4];
> +    int              i, k;
>  
>      flag = 0;
>      mask = 0;
>  
>      for (y=strip->y1; y < strip->y2; y+=4) {
>  
> -        iy[0] = strip->x1 + (y * s->frame.linesize[0]);
> -        iy[1] = iy[0] + s->frame.linesize[0];
> -        iy[2] = iy[1] + s->frame.linesize[0];
> -        iy[3] = iy[2] + s->frame.linesize[0];
> -        iu[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[1]);
> -        iu[1] = iu[0] + s->frame.linesize[1];
> -        iv[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[2]);
> -        iv[1] = iv[0] + s->frame.linesize[2];
> +        ir[0] = strip->x1 + (y * s->frame.linesize[0]);
> +        ir[1] = ir[0] + s->frame.linesize[0];
> +        ir[2] = ir[1] + s->frame.linesize[0];
> +        ir[3] = ir[2] + s->frame.linesize[0];
>  
>          for (x=strip->x1; x < strip->x2; x+=4) {
>              if ((chunk_id & 0x01) && !(mask >>= 1)) {
> @@ -171,93 +181,87 @@
>                          return AVERROR_INVALIDDATA;
>  
>                      codebook = &strip->v1_codebook[*data++];
> -                    s->frame.data[0][iy[0] + 0] = codebook->y0;
> -                    s->frame.data[0][iy[0] + 1] = codebook->y0;
> -                    s->frame.data[0][iy[1] + 0] = codebook->y0;
> -                    s->frame.data[0][iy[1] + 1] = codebook->y0;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[0]] = codebook->u;
> -                        s->frame.data[2][iv[0]] = codebook->v;
> -                    }
> -
> -                    s->frame.data[0][iy[0] + 2] = codebook->y1;
> -                    s->frame.data[0][iy[0] + 3] = codebook->y1;
> -                    s->frame.data[0][iy[1] + 2] = codebook->y1;
> -                    s->frame.data[0][iy[1] + 3] = codebook->y1;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[0] + 1] = codebook->u;
> -                        s->frame.data[2][iv[0] + 1] = codebook->v;
> -                    }
> -
> -                    s->frame.data[0][iy[2] + 0] = codebook->y2;
> -                    s->frame.data[0][iy[2] + 1] = codebook->y2;
> -                    s->frame.data[0][iy[3] + 0] = codebook->y2;
> -                    s->frame.data[0][iy[3] + 1] = codebook->y2;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[1]] = codebook->u;
> -                        s->frame.data[2][iv[1]] = codebook->v;
> -                    }
> -
> -                    s->frame.data[0][iy[2] + 2] = codebook->y3;
> -                    s->frame.data[0][iy[2] + 3] = codebook->y3;
> -                    s->frame.data[0][iy[3] + 2] = codebook->y3;
> -                    s->frame.data[0][iy[3] + 3] = codebook->y3;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[1] + 1] = codebook->u;
> -                        s->frame.data[2][iv[1] + 1] = codebook->v;
> +                    if (s->palette_video) {
> +                        for (i=0; i<4; i+=2) {
> +                            s->frame.data[0][ir[i+0] + 0] = codebook->r[i+0];
> +                            s->frame.data[0][ir[i+0] + 1] = codebook->r[i+0];
> +                            s->frame.data[0][ir[i+0] + 2] = codebook->r[i+1];
> +                            s->frame.data[0][ir[i+0] + 3] = codebook->r[i+1];
> +                            s->frame.data[0][ir[i+1] + 0] = codebook->r[i+0];
> +                            s->frame.data[0][ir[i+1] + 1] = codebook->r[i+0];
> +                            s->frame.data[0][ir[i+1] + 2] = codebook->r[i+1];
> +                            s->frame.data[0][ir[i+1] + 3] = codebook->r[i+1];
> +                        }
> +                    } else {
> +                      for (i=0; i<4; i++) {
> +                        int i1 = i&2;
> +                        for (k=0; k<12; k+=3) {
> +                          int k1 = (k>=6);

> +                          s->frame.data[0][ir[i] + k + 0] = codebook->r[i1+k1];
> +                          s->frame.data[0][ir[i] + k + 1] = codebook->g[i1+k1];
> +                          s->frame.data[0][ir[i] + k + 2] = codebook->b[i1+k1];



> +                        }
> +                      }
>                      }
>  
>                  } else if (flag & mask) {
>                      if ((data + 4) > eod)
>                          return AVERROR_INVALIDDATA;
>  
> -                    codebook = &strip->v4_codebook[*data++];
> -                    s->frame.data[0][iy[0] + 0] = codebook->y0;
> -                    s->frame.data[0][iy[0] + 1] = codebook->y1;
> -                    s->frame.data[0][iy[1] + 0] = codebook->y2;
> -                    s->frame.data[0][iy[1] + 1] = codebook->y3;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[0]] = codebook->u;
> -                        s->frame.data[2][iv[0]] = codebook->v;
> -                    }
> -
> -                    codebook = &strip->v4_codebook[*data++];
> -                    s->frame.data[0][iy[0] + 2] = codebook->y0;
> -                    s->frame.data[0][iy[0] + 3] = codebook->y1;
> -                    s->frame.data[0][iy[1] + 2] = codebook->y2;
> -                    s->frame.data[0][iy[1] + 3] = codebook->y3;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[0] + 1] = codebook->u;
> -                        s->frame.data[2][iv[0] + 1] = codebook->v;
> -                    }
> -
> -                    codebook = &strip->v4_codebook[*data++];
> -                    s->frame.data[0][iy[2] + 0] = codebook->y0;
> -                    s->frame.data[0][iy[2] + 1] = codebook->y1;
> -                    s->frame.data[0][iy[3] + 0] = codebook->y2;
> -                    s->frame.data[0][iy[3] + 1] = codebook->y3;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[1]] = codebook->u;
> -                        s->frame.data[2][iv[1]] = codebook->v;
> -                    }
> -
> -                    codebook = &strip->v4_codebook[*data++];
> -                    s->frame.data[0][iy[2] + 2] = codebook->y0;
> -                    s->frame.data[0][iy[2] + 3] = codebook->y1;
> -                    s->frame.data[0][iy[3] + 2] = codebook->y2;
> -                    s->frame.data[0][iy[3] + 3] = codebook->y3;
> -                    if (!s->palette_video) {
> -                        s->frame.data[1][iu[1] + 1] = codebook->u;
> -                        s->frame.data[2][iv[1] + 1] = codebook->v;
> +                    if (s->palette_video) {
> +                        for (i=0; i<4; i+=2) {
> +                            codebook = &strip->v4_codebook[*data++];
> +                            cb2      = &strip->v4_codebook[*data++];
> +                            s->frame.data[0][ir[i+0] +  0] = codebook->r[0];
> +                            s->frame.data[0][ir[i+0] +  1] = codebook->r[1];
> +                            s->frame.data[0][ir[i+0] +  2] =      cb2->r[0];
> +                            s->frame.data[0][ir[i+0] +  3] =      cb2->r[1];
> +                            s->frame.data[0][ir[i+1] +  0] = codebook->r[2];
> +                            s->frame.data[0][ir[i+1] +  1] = codebook->r[3];
> +                            s->frame.data[0][ir[i+1] +  2] =      cb2->r[2];
> +                            s->frame.data[0][ir[i+1] +  3] =      cb2->r[3];
> +                        }
> +                    } else {
> +                        for (i=0; i<4; i+=2) {
> +                            codebook = &strip->v4_codebook[*data++];
> +                            cb2      = &strip->v4_codebook[*data++];
> +                            s->frame.data[0][ir[i+0] +  0] = codebook->r[0];
> +                            s->frame.data[0][ir[i+0] +  1] = codebook->g[0];
> +                            s->frame.data[0][ir[i+0] +  2] = codebook->b[0];
> +                            s->frame.data[0][ir[i+0] +  3] = codebook->r[1];
> +                            s->frame.data[0][ir[i+0] +  4] = codebook->g[1];
> +                            s->frame.data[0][ir[i+0] +  5] = codebook->b[1];
> +                            s->frame.data[0][ir[i+0] +  6] =      cb2->r[0];
> +                            s->frame.data[0][ir[i+0] +  7] =      cb2->g[0];
> +                            s->frame.data[0][ir[i+0] +  8] =      cb2->b[0];
> +                            s->frame.data[0][ir[i+0] +  9] =      cb2->r[1];
> +                            s->frame.data[0][ir[i+0] + 10] =      cb2->g[1];
> +                            s->frame.data[0][ir[i+0] + 11] =      cb2->b[1];
> +                            s->frame.data[0][ir[i+1] +  0] = codebook->r[2];
> +                            s->frame.data[0][ir[i+1] +  1] = codebook->g[2];
> +                            s->frame.data[0][ir[i+1] +  2] = codebook->b[2];
> +                            s->frame.data[0][ir[i+1] +  3] = codebook->r[3];
> +                            s->frame.data[0][ir[i+1] +  4] = codebook->g[3];
> +                            s->frame.data[0][ir[i+1] +  5] = codebook->b[3];
> +                            s->frame.data[0][ir[i+1] +  6] =      cb2->r[2];
> +                            s->frame.data[0][ir[i+1] +  7] =      cb2->g[2];
> +                            s->frame.data[0][ir[i+1] +  8] =      cb2->b[2];
> +                            s->frame.data[0][ir[i+1] +  9] =      cb2->r[3];
> +                            s->frame.data[0][ir[i+1] + 10] =      cb2->g[3];
> +                            s->frame.data[0][ir[i+1] + 11] =      cb2->b[3];

this can be simplified and made faster if the codebooks store data in
the same order as the output


[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Let us carefully observe those good qualities wherein our enemies excel us
and endeavor to excel them, by avoiding what is faulty, and imitating what
is excellent in them. -- Plutarch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130217/dc23b67d/attachment.asc>


More information about the ffmpeg-devel mailing list