Fix for interlaced huffyuv by roberto togni <rtogni at bresciaonline.it>

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6513 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
atmos4 2002-06-23 01:30:47 +00:00
parent 69d5224ae2
commit 98571211e8
1 changed files with 215 additions and 67 deletions

View File

@ -81,6 +81,8 @@ typedef struct {
int method; int method;
// Bitmap color type // Bitmap color type
int bitmaptype; int bitmaptype;
// Interlaced flag
int interlaced;
// Huffman tables // Huffman tables
unsigned char decode1_shift[256]; unsigned char decode1_shift[256];
unsigned char decode2_shift[256]; unsigned char decode2_shift[256];
@ -200,17 +202,6 @@ static int init(sh_video_t *sh)
sh->context = (void *)hc; sh->context = (void *)hc;
mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Allocating above line buffer\n");
if ((hc->abovebuf1 = malloc(sizeof(char) * 4 * bih->biWidth)) == NULL) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for HuffYUV above buffer 1\n");
return 0;
}
if ((hc->abovebuf2 = malloc(sizeof(char) * 4 * bih->biWidth)) == NULL) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for HuffYUV above buffer 2\n");
return 0;
}
if (bih->biCompression != FOURCC_HFYU) { if (bih->biCompression != FOURCC_HFYU) {
mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[HuffYUV] BITMAPHEADER fourcc != HFYU\n"); mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[HuffYUV] BITMAPHEADER fourcc != HFYU\n");
return 0; return 0;
@ -296,6 +287,33 @@ static int init(sh_video_t *sh)
mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[HuffYUV] Method unknown\n"); mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[HuffYUV] Method unknown\n");
} }
/* Take care of interlaced images */
hc->interlaced = 0;
if (bih->biHeight > 288) {
// Image is interlaced (flag != 0), but we may not care
hc->interlaced = 1;
mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Image is interlaced\n");
}
/* Allocate buffers */
hc->abovebuf1 = NULL;
hc->abovebuf2 = NULL;
if ((hc->method == METHOD_MEDIAN) || (hc->method == METHOD_GRAD) ||
(hc->method == METHOD_GRAD_DECORR)) {
// If inetrlaced flag will be 2
(hc->interlaced)++;
mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Allocating above line buffer\n");
if ((hc->abovebuf1 = malloc(sizeof(char) * 4 * bih->biWidth * hc->interlaced)) == NULL) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for HuffYUV above buffer 1\n");
return 0;
}
if ((hc->abovebuf2 = malloc(sizeof(char) * 4 * bih->biWidth * hc->interlaced)) == NULL) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for HuffYUV above buffer 2\n");
return 0;
}
}
/* Get compressed Huffman tables */ /* Get compressed Huffman tables */
if (bih->biSize == sizeof(BITMAPINFOHEADER) /*&& !(bih->biBitCount&7)*/) { if (bih->biSize == sizeof(BITMAPINFOHEADER) /*&& !(bih->biBitCount&7)*/) {
hufftable = (hc->bitmaptype == BMPTYPE_YUV) ? HUFFTABLE_CLASSIC_YUV : HUFFTABLE_CLASSIC_RGB; hufftable = (hc->bitmaptype == BMPTYPE_YUV) ? HUFFTABLE_CLASSIC_YUV : HUFFTABLE_CLASSIC_RGB;
@ -477,6 +495,40 @@ static void uninit(sh_video_t *sh)
#define YUV_PREDMED_1ST() \
{ \
MEDIAN (left_y, abovebuf[0], curbuf[width2*4-2]); \
curbuf[0] = outptr[pixel_ptr++] = left_y = med + y1; \
MEDIAN (left_u, abovebuf[1], curbuf[width2*4+1-4]); \
curbuf[1] = outptr[pixel_ptr++] = left_u = med + u; \
MEDIAN (left_y, abovebuf[2], abovebuf[0]); \
curbuf[2] = outptr[pixel_ptr++] = left_y = med + y2; \
MEDIAN (left_v, abovebuf[3], curbuf[width2*4+3-4]); \
curbuf[3] = outptr[pixel_ptr++] = left_v = med + v; \
}
#define YUV_PREDGRAD() \
{ \
curbuf[col] = outptr[pixel_ptr++] = left_y += y1 + abovebuf[col]-abovebuf[col-2]; \
curbuf[col+1] = outptr[pixel_ptr++] = left_u += u + abovebuf[col+1]-abovebuf[col+1-4]; \
curbuf[col+2] = outptr[pixel_ptr++] = left_y += y2 + abovebuf[col+2]-abovebuf[col+2-2]; \
curbuf[col+3] = outptr[pixel_ptr++] = left_v += v + abovebuf[col+3]-abovebuf[col+3-4]; \
}
#define YUV_PREDGRAD_1ST() \
{ \
curbuf[0] = outptr[pixel_ptr++] = left_y += y1 + abovebuf[0] - curbuf[width2*4-2]; \
curbuf[1] = outptr[pixel_ptr++] = left_u += u + abovebuf[1] - curbuf[width2*4+1-4]; \
curbuf[2] = outptr[pixel_ptr++] = left_y += y2 + abovebuf[2] - abovebuf[0]; \
curbuf[3] = outptr[pixel_ptr++] = left_v += v + abovebuf[3] - curbuf[width2*4+3-4]; \
}
#define RGB_PREDLEFT_DECORR() \ #define RGB_PREDLEFT_DECORR() \
{ \ { \
outptr[pixel_ptr++] = left_b += b + g; \ outptr[pixel_ptr++] = left_b += b + g; \
@ -487,6 +539,15 @@ static void uninit(sh_video_t *sh)
#define RGB_PREDLEFT_DECORR_BUF() \
{ \
abovebuf[col] = outptr[pixel_ptr++] = left_b += b + g; \
abovebuf[col+1] = outptr[pixel_ptr++] = left_g += g; \
abovebuf[col+2] = outptr[pixel_ptr++] = left_r += r + g; \
pixel_ptr += bgr32; \
}
#define RGB_PREDLEFT() \ #define RGB_PREDLEFT() \
{ \ { \
outptr[pixel_ptr++] = left_b += b; \ outptr[pixel_ptr++] = left_b += b; \
@ -497,6 +558,34 @@ static void uninit(sh_video_t *sh)
#define RGB_PREDGRAD_DECORR() \
{ \
curbuf[col] = outptr[pixel_ptr++] = left_b += b + g + abovebuf[col]-abovebuf[col-3]; \
curbuf[col+1] = outptr[pixel_ptr++] = left_g += g + abovebuf[col+1]-abovebuf[col+1-3]; \
curbuf[col+2] = outptr[pixel_ptr++] = left_r += r + g + abovebuf[col+2]-abovebuf[col+2-3]; \
pixel_ptr += bgr32; \
}
#define RGB_PREDGRAD_DECORR_1ST() \
{ \
curbuf[0] = outptr[pixel_ptr++] = left_b += b + g + abovebuf[0] - curbuf[width2*3-3]; \
curbuf[1] = outptr[pixel_ptr++] = left_g += g + abovebuf[1] - curbuf[width2*3+1-3]; \
curbuf[2] = outptr[pixel_ptr++] = left_r += r + g + abovebuf[2] - curbuf[width2*3+2-3]; \
pixel_ptr += bgr32; \
}
#define SWAPBUF() \
{ \
swap = abovebuf; \
abovebuf = curbuf; \
curbuf = swap; \
}
/* /*
* *
@ -520,18 +609,30 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
unsigned char *outptr; unsigned char *outptr;
int width = sh->disp_w; // Real image width int width = sh->disp_w; // Real image width
int height = sh->disp_h; // Real image height int height = sh->disp_h; // Real image height
int width2, height2;
int bgr32; int bgr32;
int interlaced, oddlines;
// skipped frame // Skipped frame
if(len <= 0) if(len <= 0)
return NULL; return NULL;
/* Do not accept stride for rgb, it gives me wrong output :-( */ /* If image is interlaced and we care about it fix size */
if (hc->bitmaptype == BMPTYPE_YUV) if (hc->interlaced == 2) {
mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, sh->disp_w, sh->disp_h); width2 = width*2; // Double image width
else height2 = height/2; // Half image height
mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, 0, sh->disp_w, sh->disp_h); oddlines = height%2; // Set if line number is odd
interlaced = 1; // Used also for row counter computation, must be exactly 1
} else {
width2 = width; // Real image width
height2 = height; // Real image height
interlaced = 0; // Flag is 0: no need to deinterlaced image
oddlines = 0; // Don't care about odd line number if not interlaced
}
/* Get output image buffer */
mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, sh->disp_w, sh->disp_h);
if (!mpi) { if (!mpi) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate mpi image for huffyuv codec.\n"); mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate mpi image for huffyuv codec.\n");
return NULL; return NULL;
@ -541,6 +642,7 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
if (hc->bitmaptype == BMPTYPE_YUV) { if (hc->bitmaptype == BMPTYPE_YUV) {
width >>= 1; // Each cycle stores two pixels width >>= 1; // Each cycle stores two pixels
width2 >>= 1;
if (hc->method == METHOD_GRAD) { if (hc->method == METHOD_GRAD) {
/* /*
* YUV predict gradient * YUV predict gradient
@ -550,26 +652,41 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
// Decompress 1st row (always stored with left prediction) // Decompress 1st row (always stored with left prediction)
for (col = 1*4; col < width*4; col += 4) { for (col = 1*4; col < width*4; col += 4) {
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
YUV_PREDLEFT_BUF(abovebuf, col); YUV_PREDLEFT_BUF (abovebuf, col);
} }
curbuf[width*4-1] = curbuf[width*4-2] = curbuf[width*4-3] = 0; if (interlaced) {
for (row = 1; row < height; row++) { pixel_ptr = mpi->stride[0];
pixel_ptr = row * mpi->stride[0]; for (col = width*4; col < width*8; col += 4) {
HUFF_DECOMPRESS_YUYV();
YUV_PREDLEFT_BUF (abovebuf, col);
}
}
curbuf[width2*4-1] = curbuf[width2*4-2] = curbuf[width2*4-3] = 0;
for (row = 1; row < height2; row++) {
pixel_ptr = (interlaced + 1) * row * mpi->stride[0];
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
curbuf[0] = outptr[pixel_ptr++] = left_y += y1 + abovebuf[0] - curbuf[width*4-2]; YUV_PREDGRAD_1ST();
curbuf[1] = outptr[pixel_ptr++] = left_u += u + abovebuf[1] - curbuf[width*4+1-4];
curbuf[2] = outptr[pixel_ptr++] = left_y += y2 + abovebuf[2] - abovebuf[0];
curbuf[3] = outptr[pixel_ptr++] = left_v += v + abovebuf[3] - curbuf[width*4+3-4];
for (col = 1*4; col < width*4; col += 4) { for (col = 1*4; col < width*4; col += 4) {
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
curbuf[col] = outptr[pixel_ptr++] = left_y += y1 + abovebuf[col]-abovebuf[col-2]; YUV_PREDGRAD();
curbuf[col+1] = outptr[pixel_ptr++] = left_u += u + abovebuf[col+1]-abovebuf[col+1-4]; }
curbuf[col+2] = outptr[pixel_ptr++] = left_y += y2 + abovebuf[col+2]-abovebuf[col+2-2]; if (interlaced) {
curbuf[col+3] = outptr[pixel_ptr++] = left_v += v + abovebuf[col+3]-abovebuf[col+3-4]; pixel_ptr = (2 * row + 1) * mpi->stride[0];
for (col = width*4; col < width*8; col += 4) {
HUFF_DECOMPRESS_YUYV();
YUV_PREDGRAD();
}
}
SWAPBUF();
}
if (oddlines) {
pixel_ptr = 2 * height * mpi->stride[0];
HUFF_DECOMPRESS_YUYV();
YUV_PREDGRAD_1ST();
for (col = 1*4; col < width*4; col += 4) {
HUFF_DECOMPRESS_YUYV();
YUV_PREDGRAD();
} }
swap = abovebuf;
abovebuf = curbuf;
curbuf = swap;
} }
} else if (hc->method == METHOD_MEDIAN) { } else if (hc->method == METHOD_MEDIAN) {
/* /*
@ -582,8 +699,15 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
YUV_PREDLEFT_BUF (abovebuf, col); YUV_PREDLEFT_BUF (abovebuf, col);
} }
if (interlaced) {
pixel_ptr = mpi->stride[0];
for (col = width*4; col < width*8; col += 4) {
HUFF_DECOMPRESS_YUYV();
YUV_PREDLEFT_BUF (abovebuf, col);
}
}
// Decompress 1st two pixels of 2nd row // Decompress 1st two pixels of 2nd row
pixel_ptr = mpi->stride[0]; pixel_ptr = mpi->stride[0] * (interlaced + 1);
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
YUV_PREDLEFT_BUF (curbuf, 0); YUV_PREDLEFT_BUF (curbuf, 0);
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
@ -593,27 +717,39 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
YUV_PREDMED(); YUV_PREDMED();
} }
swap = abovebuf; if (interlaced) {
abovebuf = curbuf; pixel_ptr = mpi->stride[0] * 3;
curbuf = swap; for (col = width*4; col < width*8; col += 4) {
for (row = 2; row < height; row++) { HUFF_DECOMPRESS_YUYV();
pixel_ptr = row * mpi->stride[0]; YUV_PREDMED();
}
}
SWAPBUF();
for (row = 2; row < height2; row++) {
pixel_ptr = (interlaced + 1) * row * mpi->stride[0];
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
MEDIAN (left_y, abovebuf[0], curbuf[width*4-2]); YUV_PREDMED_1ST();
curbuf[0] = outptr[pixel_ptr++] = left_y = med + y1; for (col = 1*4; col < width*4; col += 4) {
MEDIAN (left_u, abovebuf[1], curbuf[width*4+1-4]); HUFF_DECOMPRESS_YUYV();
curbuf[1] = outptr[pixel_ptr++] = left_u = med + u; YUV_PREDMED();
MEDIAN (left_y, abovebuf[2], abovebuf[0]); }
curbuf[2] = outptr[pixel_ptr++] = left_y = med + y2; if (interlaced) {
MEDIAN (left_v, abovebuf[3], curbuf[width*4+3-4]); pixel_ptr = (2 * row + 1) * mpi->stride[0];
curbuf[3] = outptr[pixel_ptr++] = left_v = med + v; for (col = width*4; col < width*8; col += 4) {
HUFF_DECOMPRESS_YUYV();
YUV_PREDMED();
}
}
SWAPBUF();
}
if (oddlines) {
pixel_ptr = 2 * height2 * mpi->stride[0];
HUFF_DECOMPRESS_YUYV();
YUV_PREDMED_1ST();
for (col = 1*4; col < width*4; col += 4) { for (col = 1*4; col < width*4; col += 4) {
HUFF_DECOMPRESS_YUYV(); HUFF_DECOMPRESS_YUYV();
YUV_PREDMED(); YUV_PREDMED();
} }
swap = abovebuf;
abovebuf = curbuf;
curbuf = swap;
} }
} else { } else {
/* /*
@ -663,29 +799,41 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
// Decompress 1st row (always stored with left prediction) // Decompress 1st row (always stored with left prediction)
for (col = 1*3; col < width*3; col += 3) { for (col = 1*3; col < width*3; col += 3) {
HUFF_DECOMPRESS_RGB_DECORR(); HUFF_DECOMPRESS_RGB_DECORR();
abovebuf[col] = outptr[pixel_ptr++] = left_b += b + g; RGB_PREDLEFT_DECORR_BUF();
abovebuf[col+1] = outptr[pixel_ptr++] = left_g += g;
abovebuf[col+2] = outptr[pixel_ptr++] = left_r += r + g;
pixel_ptr += bgr32;
} }
curbuf[width*3-1] = curbuf[width*3-2] = curbuf[width*3-3] = 0; if (interlaced) {
for (row = 1; row < height; row++) { pixel_ptr = (height-2)*mpi->stride[0];
pixel_ptr = (height - row - 1) * mpi->stride[0]; for (col = width*3; col < width*6; col += 3) {
HUFF_DECOMPRESS_RGB_DECORR();
RGB_PREDLEFT_DECORR_BUF();
}
}
curbuf[width2*3-1] = curbuf[width2*3-2] = curbuf[width2*3-3] = 0;
for (row = 1; row < height2; row++) {
pixel_ptr = (height - (interlaced + 1) * row - 1) * mpi->stride[0];
HUFF_DECOMPRESS_RGB_DECORR(); HUFF_DECOMPRESS_RGB_DECORR();
curbuf[0] = outptr[pixel_ptr++] = left_b += b + g + abovebuf[0] - curbuf[width*3-3]; RGB_PREDGRAD_DECORR_1ST();
curbuf[1] = outptr[pixel_ptr++] = left_g += g + abovebuf[1] - curbuf[width*3+1-3];
curbuf[2] = outptr[pixel_ptr++] = left_r += r + g + abovebuf[2] - curbuf[width*3+2-3];
pixel_ptr += bgr32;
for (col = 1*3; col < width*3; col += 3) { for (col = 1*3; col < width*3; col += 3) {
HUFF_DECOMPRESS_RGB_DECORR(); HUFF_DECOMPRESS_RGB_DECORR();
curbuf[col] = outptr[pixel_ptr++] = left_b += b + g + abovebuf[col]-abovebuf[col-3]; RGB_PREDGRAD_DECORR();
curbuf[col+1] = outptr[pixel_ptr++] = left_g += g + abovebuf[col+1]-abovebuf[col+1-3]; }
curbuf[col+2] = outptr[pixel_ptr++] = left_r += r + g + abovebuf[col+2]-abovebuf[col+2-3]; if (interlaced) {
pixel_ptr += bgr32; pixel_ptr = (height - 2 * row - 2) * mpi->stride[0];
for (col = width*3; col < width*6; col += 3) {
HUFF_DECOMPRESS_RGB_DECORR();
RGB_PREDGRAD_DECORR();
}
}
SWAPBUF();
}
if (oddlines) {
pixel_ptr = mpi->stride[0];
HUFF_DECOMPRESS_RGB_DECORR();
RGB_PREDGRAD_DECORR_1ST();
for (col = 1*3; col < width*3; col += 3) {
HUFF_DECOMPRESS_RGB_DECORR();
RGB_PREDGRAD_DECORR();
} }
swap = abovebuf;
abovebuf = curbuf;
curbuf = swap;
} }
} else { } else {
/* /*