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

u-bo1b at 0w.se u-bo1b at 0w.se
Tue Feb 12 16:32:05 CET 2013


Hello,

Attaching the patch.

Regards,
Rl
-------------- next part --------------
--- 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;
+                    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++;
             }
         }
     }
@@ -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];
+                        }
                     }
 
                 }
             }
 
-            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 +416,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