[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