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

u-bo1b at 0w.se u-bo1b at 0w.se
Sun Feb 17 22:14:07 CET 2013


On Sun, Feb 17, 2013 at 05:04:10PM +0100, Michael Niedermayer wrote:
> >  cinepak.c |  216 +++++++++++++++++++++++++++++++-------------------------------
> >  1 file changed, 110 insertions(+), 106 deletions(-)

> see av_clip_uint8()

> this can be factored out of the if/else

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

Thanks Michael,

Done, attaching the patch.

Regards,
Rl
-------------- next part --------------
--- libavcodec/cinepak.c.ori	2013-02-17 17:28:34.108133457 +0100
+++ libavcodec/cinepak.c	2013-02-17 21:58:40.559714683 +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  rgb0rgb1rgb2rgb3[12];
 } cvid_codebook;
 
 #define MAX_STRIPS      32
@@ -95,27 +97,33 @@
         }
 
         if (!(chunk_id & 0x01) || (flag & mask)) {
+            int k, kk;
+
             if ((data + n) > eod)
                 break;
 
+            for (k = 0; k < 12; ) {
+                int r = *data++;
+                for (kk = 0; kk < 3; ++kk)
+                    codebook[i].rgb0rgb1rgb2rgb3[k++] = r;
+            }
             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;
+                u = *(int8_t *)data++;
+                v = *(int8_t *)data++;
+                for(k=0; k<12; k+=3) {
+                    r = codebook[i].rgb0rgb1rgb2rgb3[k+0] + v*2;
+                    g = codebook[i].rgb0rgb1rgb2rgb3[k+1] - (u/2) - v;
+                    b = codebook[i].rgb0rgb1rgb2rgb3[k+2] + u*2;
+                    codebook[i].rgb0rgb1rgb2rgb3[k+0] = av_clip_uint8(r);
+                    codebook[i].rgb0rgb1rgb2rgb3[k+1] = av_clip_uint8(g);
+                    codebook[i].rgb0rgb1rgb2rgb3[k+2] = av_clip_uint8(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, it is already stored as grey rgb24
+                 * which makes it robust even when the frame is considered
+                 * to be rgb24 */
             }
         }
     }
@@ -126,25 +134,20 @@
 {
     const uint8_t   *eod = (data + size);
     uint32_t         flag, mask;
-    cvid_codebook   *codebook;
+    cvid_codebook   *codebook, *cb2[7]; /* we use only cb2[0],cb2[2],cb2[6] */
     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 * 3 + (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 +174,71 @@
                         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=k=0; i<4; i+=2) {
+                            int ii;
+                            for (ii=0; ii<4; ii+=2, k+=3)
+                                s->frame.data[0][ir[i+0] + ii+0] =
+                                s->frame.data[0][ir[i+0] + ii+1] =
+                                s->frame.data[0][ir[i+1] + ii+0] =
+                                s->frame.data[0][ir[i+1] + ii+1] =
+                                  codebook->rgb0rgb1rgb2rgb3[k];
+                        }
+                    } else {
+                        for (i=k=0; i<4; i+=2) {
+                            int ii;
+                            for (ii=0; ii<12; ii+=6, k+=3) {
+                                char *p = codebook->rgb0rgb1rgb2rgb3 + k;
+                                memcpy(s->frame.data[0]+ir[i+0]+ii+0, p, 3);
+                                memcpy(s->frame.data[0]+ir[i+0]+ii+3, p, 3);
+                                memcpy(s->frame.data[0]+ir[i+1]+ii+0, p, 3);
+                                memcpy(s->frame.data[0]+ir[i+1]+ii+3, p, 3);
+                            }
+                        }
                     }
 
                 } 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) {
+                            int ii, kk; 
+                            cb2[0] = &strip->v4_codebook[*data++];
+                            cb2[2] = &strip->v4_codebook[*data++];
+                            for (ii=0; ii<4; ii+=2)
+                                for (kk=0, k=0; kk<2; ++kk, k+=3)
+                                    s->frame.data[0][ir[i+0] + ii + kk] =
+                                      cb2[ii]->rgb0rgb1rgb2rgb3[k];
+                            for (ii=0; ii<4; ii+=2)
+                                for (kk=0, k=6; kk<2; ++kk, k+=3)
+                                    s->frame.data[0][ir[i+1] + ii + kk] =
+                                      cb2[ii]->rgb0rgb1rgb2rgb3[k];
+                        }
+                    } else {
+                        for (i=0; i<4; i+=2) {
+                            int k;
+                            cb2[0] = &strip->v4_codebook[*data++];
+                            cb2[6] = &strip->v4_codebook[*data++];
+                            for (k=0; k<12; k+=6)
+                                memcpy(s->frame.data[0]+ir[i+0]+k,
+                                  cb2[k]->rgb0rgb1rgb2rgb3+0, 6);
+                            for (k=0; k<12; k+=6)
+                                memcpy(s->frame.data[0]+ir[i+1]+k,
+                                  cb2[k]->rgb0rgb1rgb2rgb3+6, 6);
+                        }
                     }
 
                 }
             }
 
-            iy[0] += 4;  iy[1] += 4;
-            iy[2] += 4;  iy[3] += 4;
-            iu[0] += 2;  iu[1] += 2;
-            iv[0] += 2;  iv[1] += 2;
+            if (s->palette_video) {
+                ir[0] += 4;  ir[1] += 4;
+                ir[2] += 4;  ir[3] += 4;
+            } else {
+                ir[0] += 12;  ir[1] += 12;
+                ir[2] += 12;  ir[3] += 12;
+            }
         }
     }
 
@@ -412,7 +393,7 @@
     // check for paletted data
     if (avctx->bits_per_coded_sample != 8) {
         s->palette_video = 0;
-        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+        avctx->pix_fmt = AV_PIX_FMT_RGB24;
     } else {
         s->palette_video = 1;
         avctx->pix_fmt = AV_PIX_FMT_PAL8;


More information about the ffmpeg-devel mailing list