[FFmpeg-devel] Repost/fix: [PATCH] use correct colorspace in Cinepak decoder
u-bo1b at 0w.se
u-bo1b at 0w.se
Sun Feb 17 23:30:05 CET 2013
Oh, a mistake, there was an error in the patch, breaking when strips
not begin from x==0. Unclear if such strips ever existed in reality
but anyway.
Attaching the fixed version.
Rl
On Sun, Feb 17, 2013 at 10:14:07PM +0100, u-bo1b at 0w.se wrote:
> 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 23:18:33.131590238 +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,23 @@
{
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];
+ if (s->palette_video)
+ ir[0] = strip->x1 + (y * s->frame.linesize[0]);
+ else
+ 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 +177,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 +396,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