[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