00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <inttypes.h>
00029
00030 #include "mpeg2.h"
00031 #include "convert.h"
00032 #include "convert_internal.h"
00033
00034 static uint32_t matrix_coefficients = 6;
00035
00036 const int32_t Inverse_Table_6_9[8][4] = {
00037 {117504, 138453, 13954, 34903},
00038 {117504, 138453, 13954, 34903},
00039 {104597, 132201, 25675, 53279},
00040 {104597, 132201, 25675, 53279},
00041 {104448, 132798, 24759, 53109},
00042 {104597, 132201, 25675, 53279},
00043 {104597, 132201, 25675, 53279},
00044 {117579, 136230, 16907, 35559}
00045 };
00046
00047 typedef void yuv2rgb_c_internal (uint8_t *, uint8_t *, uint8_t *, uint8_t *,
00048 void *, void *, int);
00049
00050 void * table_rV[256];
00051 void * table_gU[256];
00052 int table_gV[256];
00053 void * table_bU[256];
00054
00055 #define RGB(type,i) \
00056 U = pu[i]; \
00057 V = pv[i]; \
00058 r = (type *) table_rV[V]; \
00059 g = (type *) (((uint8_t *)table_gU[U]) + table_gV[V]); \
00060 b = (type *) table_bU[U];
00061
00062 #define DST(py,dst,i) \
00063 Y = py[2*i]; \
00064 dst[2*i] = r[Y] + g[Y] + b[Y]; \
00065 Y = py[2*i+1]; \
00066 dst[2*i+1] = r[Y] + g[Y] + b[Y];
00067
00068 #define DSTRGB(py,dst,i) \
00069 Y = py[2*i]; \
00070 dst[6*i] = r[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = b[Y]; \
00071 Y = py[2*i+1]; \
00072 dst[6*i+3] = r[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = b[Y];
00073
00074 #define DSTBGR(py,dst,i) \
00075 Y = py[2*i]; \
00076 dst[6*i] = b[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = r[Y]; \
00077 Y = py[2*i+1]; \
00078 dst[6*i+3] = b[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = r[Y];
00079
00080 static void yuv2rgb_c_32 (uint8_t * py_1, uint8_t * py_2,
00081 uint8_t * pu, uint8_t * pv,
00082 void * _dst_1, void * _dst_2, int width)
00083 {
00084 int U, V, Y;
00085 uint32_t * r, * g, * b;
00086 uint32_t * dst_1, * dst_2;
00087
00088 width >>= 3;
00089 dst_1 = (uint32_t *) _dst_1;
00090 dst_2 = (uint32_t *) _dst_2;
00091
00092 do {
00093 RGB (uint32_t, 0);
00094 DST (py_1, dst_1, 0);
00095 DST (py_2, dst_2, 0);
00096
00097 RGB (uint32_t, 1);
00098 DST (py_2, dst_2, 1);
00099 DST (py_1, dst_1, 1);
00100
00101 RGB (uint32_t, 2);
00102 DST (py_1, dst_1, 2);
00103 DST (py_2, dst_2, 2);
00104
00105 RGB (uint32_t, 3);
00106 DST (py_2, dst_2, 3);
00107 DST (py_1, dst_1, 3);
00108
00109 pu += 4;
00110 pv += 4;
00111 py_1 += 8;
00112 py_2 += 8;
00113 dst_1 += 8;
00114 dst_2 += 8;
00115 } while (--width);
00116 }
00117
00118
00119 static void yuv2rgb_c_24_rgb (uint8_t * py_1, uint8_t * py_2,
00120 uint8_t * pu, uint8_t * pv,
00121 void * _dst_1, void * _dst_2, int width)
00122 {
00123 int U, V, Y;
00124 uint8_t * r, * g, * b;
00125 uint8_t * dst_1, * dst_2;
00126
00127 width >>= 3;
00128 dst_1 = (uint8_t *) _dst_1;
00129 dst_2 = (uint8_t *) _dst_2;
00130
00131 do {
00132 RGB (uint8_t, 0);
00133 DSTRGB (py_1, dst_1, 0);
00134 DSTRGB (py_2, dst_2, 0);
00135
00136 RGB (uint8_t, 1);
00137 DSTRGB (py_2, dst_2, 1);
00138 DSTRGB (py_1, dst_1, 1);
00139
00140 RGB (uint8_t, 2);
00141 DSTRGB (py_1, dst_1, 2);
00142 DSTRGB (py_2, dst_2, 2);
00143
00144 RGB (uint8_t, 3);
00145 DSTRGB (py_2, dst_2, 3);
00146 DSTRGB (py_1, dst_1, 3);
00147
00148 pu += 4;
00149 pv += 4;
00150 py_1 += 8;
00151 py_2 += 8;
00152 dst_1 += 24;
00153 dst_2 += 24;
00154 } while (--width);
00155 }
00156
00157
00158 static void yuv2rgb_c_24_bgr (uint8_t * py_1, uint8_t * py_2,
00159 uint8_t * pu, uint8_t * pv,
00160 void * _dst_1, void * _dst_2, int width)
00161 {
00162 int U, V, Y;
00163 uint8_t * r, * g, * b;
00164 uint8_t * dst_1, * dst_2;
00165
00166 width >>= 3;
00167 dst_1 = (uint8_t *) _dst_1;
00168 dst_2 = (uint8_t *) _dst_2;
00169
00170 do {
00171 RGB (uint8_t, 0);
00172 DSTBGR (py_1, dst_1, 0);
00173 DSTBGR (py_2, dst_2, 0);
00174
00175 RGB (uint8_t, 1);
00176 DSTBGR (py_2, dst_2, 1);
00177 DSTBGR (py_1, dst_1, 1);
00178
00179 RGB (uint8_t, 2);
00180 DSTBGR (py_1, dst_1, 2);
00181 DSTBGR (py_2, dst_2, 2);
00182
00183 RGB (uint8_t, 3);
00184 DSTBGR (py_2, dst_2, 3);
00185 DSTBGR (py_1, dst_1, 3);
00186
00187 pu += 4;
00188 pv += 4;
00189 py_1 += 8;
00190 py_2 += 8;
00191 dst_1 += 24;
00192 dst_2 += 24;
00193 } while (--width);
00194 }
00195
00196
00197
00198 static void yuv2rgb_c_16 (uint8_t * py_1, uint8_t * py_2,
00199 uint8_t * pu, uint8_t * pv,
00200 void * _dst_1, void * _dst_2, int width)
00201 {
00202 int U, V, Y;
00203 uint16_t * r, * g, * b;
00204 uint16_t * dst_1, * dst_2;
00205
00206 width >>= 3;
00207 dst_1 = (uint16_t *) _dst_1;
00208 dst_2 = (uint16_t *) _dst_2;
00209
00210 do {
00211 RGB (uint16_t, 0);
00212 DST (py_1, dst_1, 0);
00213 DST (py_2, dst_2, 0);
00214
00215 RGB (uint16_t, 1);
00216 DST (py_2, dst_2, 1);
00217 DST (py_1, dst_1, 1);
00218
00219 RGB (uint16_t, 2);
00220 DST (py_1, dst_1, 2);
00221 DST (py_2, dst_2, 2);
00222
00223 RGB (uint16_t, 3);
00224 DST (py_2, dst_2, 3);
00225 DST (py_1, dst_1, 3);
00226
00227 pu += 4;
00228 pv += 4;
00229 py_1 += 8;
00230 py_2 += 8;
00231 dst_1 += 8;
00232 dst_2 += 8;
00233 } while (--width);
00234 }
00235
00236 static int div_round (int dividend, int divisor)
00237 {
00238 if (dividend > 0)
00239 return (dividend + (divisor>>1)) / divisor;
00240 else
00241 return -((-dividend + (divisor>>1)) / divisor);
00242 }
00243
00244 static yuv2rgb_c_internal * yuv2rgb_c_init (int order, int bpp)
00245 {
00246 int i;
00247 uint8_t table_Y[1024];
00248 uint32_t * table_32 = 0;
00249 uint16_t * table_16 = 0;
00250 uint8_t * table_8 = 0;
00251 int entry_size = 0;
00252 void * table_r = 0;
00253 void * table_g = 0;
00254 void * table_b = 0;
00255 yuv2rgb_c_internal * yuv2rgb;
00256
00257 int crv = Inverse_Table_6_9[matrix_coefficients][0];
00258 int cbu = Inverse_Table_6_9[matrix_coefficients][1];
00259 int cgu = -Inverse_Table_6_9[matrix_coefficients][2];
00260 int cgv = -Inverse_Table_6_9[matrix_coefficients][3];
00261
00262 for (i = 0; i < 1024; i++) {
00263 int j;
00264
00265 j = (76309 * (i - 384 - 16) + 32768) >> 16;
00266 j = (j < 0) ? 0 : ((j > 255) ? 255 : j);
00267 table_Y[i] = j;
00268 }
00269
00270 switch (bpp) {
00271 case 32:
00272 yuv2rgb = yuv2rgb_c_32;
00273
00274 table_32 = (uint32_t *) malloc ((197 + 2*682 + 256 + 132) *
00275 sizeof (uint32_t));
00276
00277 entry_size = sizeof (uint32_t);
00278 table_r = table_32 + 197;
00279 table_b = table_32 + 197 + 685;
00280 table_g = table_32 + 197 + 2*682;
00281
00282 for (i = -197; i < 256+197; i++)
00283 ((uint32_t *) table_r)[i] =
00284 table_Y[i+384] << ((order == CONVERT_RGB) ? 16 : 0);
00285 for (i = -132; i < 256+132; i++)
00286 ((uint32_t *) table_g)[i] = table_Y[i+384] << 8;
00287 for (i = -232; i < 256+232; i++)
00288 ((uint32_t *) table_b)[i] =
00289 table_Y[i+384] << ((order == CONVERT_RGB) ? 0 : 16);
00290 break;
00291
00292 case 24:
00293 yuv2rgb = (order == CONVERT_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr;
00294
00295 table_8 = (uint8_t *) malloc ((256 + 2*232) * sizeof (uint8_t));
00296
00297 entry_size = sizeof (uint8_t);
00298 table_r = table_g = table_b = table_8 + 232;
00299
00300 for (i = -232; i < 256+232; i++)
00301 ((uint8_t * )table_b)[i] = table_Y[i+384];
00302 break;
00303
00304 case 15:
00305 case 16:
00306 yuv2rgb = yuv2rgb_c_16;
00307
00308 table_16 = (uint16_t *) malloc ((197 + 2*682 + 256 + 132) *
00309 sizeof (uint16_t));
00310
00311 entry_size = sizeof (uint16_t);
00312 table_r = table_16 + 197;
00313 table_b = table_16 + 197 + 685;
00314 table_g = table_16 + 197 + 2*682;
00315
00316 for (i = -197; i < 256+197; i++) {
00317 int j = table_Y[i+384] >> 3;
00318
00319 if (order == CONVERT_RGB)
00320 j <<= ((bpp==16) ? 11 : 10);
00321
00322 ((uint16_t *)table_r)[i] = j;
00323 }
00324 for (i = -132; i < 256+132; i++) {
00325 int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3);
00326
00327 ((uint16_t *)table_g)[i] = j << 5;
00328 }
00329 for (i = -232; i < 256+232; i++) {
00330 int j = table_Y[i+384] >> 3;
00331
00332 if (order == CONVERT_RGB)
00333 j <<= ((bpp==16) ? 11 : 10);
00334
00335 ((uint16_t *)table_b)[i] = j;
00336 }
00337 break;
00338
00339 default:
00340 fprintf (stderr, "%ibpp not supported by yuv2rgb\n", bpp);
00341 exit (1);
00342 }
00343
00344 for (i = 0; i < 256; i++) {
00345 table_rV[i] = (((uint8_t *)table_r) +
00346 entry_size * div_round (crv * (i-128), 76309));
00347 table_gU[i] = (((uint8_t *)table_g) +
00348 entry_size * div_round (cgu * (i-128), 76309));
00349 table_gV[i] = entry_size * div_round (cgv * (i-128), 76309);
00350 table_bU[i] = (((uint8_t *)table_b) +
00351 entry_size * div_round (cbu * (i-128), 76309));
00352 }
00353
00354 return yuv2rgb;
00355 }
00356
00357 static void convert_yuv2rgb_c (void * _id, uint8_t * const * src,
00358 unsigned int v_offset)
00359 {
00360 convert_rgb_t * id = (convert_rgb_t *) _id;
00361 uint8_t * dst;
00362 uint8_t * py;
00363 uint8_t * pu;
00364 uint8_t * pv;
00365 int loop;
00366
00367 dst = id->rgb_ptr + id->rgb_stride * v_offset;
00368 py = src[0]; pu = src[1]; pv = src[2];
00369
00370 loop = 8;
00371 do {
00372 id->yuv2rgb (py, py + (id->uv_stride << 1), pu, pv,
00373 dst, dst + id->rgb_stride, id->width);
00374 py += id->uv_stride << 2;
00375 pu += id->uv_stride;
00376 pv += id->uv_stride;
00377 dst += 2 * id->rgb_stride;
00378 } while (--loop);
00379 }
00380
00381 static void convert_start (void * _id, uint8_t * const * dest, int flags)
00382 {
00383 convert_rgb_t * id = (convert_rgb_t *) _id;
00384 id->rgb_ptr = dest[0];
00385 switch (flags) {
00386 case CONVERT_BOTTOM_FIELD:
00387 id->rgb_ptr += id->rgb_stride_frame;
00388
00389 case CONVERT_TOP_FIELD:
00390 id->uv_stride = id->uv_stride_frame << 1;
00391 id->rgb_stride = id->rgb_stride_frame << 1;
00392 break;
00393 default:
00394 id->uv_stride = id->uv_stride_frame;
00395 id->rgb_stride = id->rgb_stride_frame;
00396 }
00397 }
00398
00399 static void convert_internal (int order, int bpp, int width, int height,
00400 uint32_t accel, void * arg,
00401 convert_init_t * result)
00402 {
00403 convert_rgb_t * id = (convert_rgb_t *) result->id;
00404
00405 if (!id) {
00406 result->id_size = sizeof (convert_rgb_t);
00407 } else {
00408 id->width = width;
00409 id->uv_stride_frame = width >> 1;
00410 id->rgb_stride_frame = ((bpp + 7) >> 3) * width;
00411
00412 result->buf_size[0] = id->rgb_stride_frame * height;
00413 result->buf_size[1] = result->buf_size[2] = 0;
00414 result->start = convert_start;
00415
00416 result->copy = NULL;
00417 #ifdef ARCH_X86
00418 if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMXEXT)) {
00419 result->copy = yuv2rgb_init_mmxext (order, bpp);
00420 }
00421 if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMX)) {
00422 result->copy = yuv2rgb_init_mmx (order, bpp);
00423 }
00424 #endif
00425 #ifdef LIBVO_MLIB
00426 if ((result->copy == NULL) && (accel & MPEG2_ACCEL_MLIB)) {
00427 result->copy = yuv2rgb_init_mlib (order, bpp);
00428 }
00429 #endif
00430 if (result->copy == NULL) {
00431 result->copy = convert_yuv2rgb_c;
00432 id->yuv2rgb = yuv2rgb_c_init (order, bpp);
00433 }
00434 }
00435 }
00436
00437 void convert_rgb32 (int width, int height, uint32_t accel, void * arg,
00438 convert_init_t * result)
00439 {
00440 convert_internal (CONVERT_RGB, 32, width, height, accel, arg, result);
00441 }
00442
00443 void convert_rgb24 (int width, int height, uint32_t accel, void * arg,
00444 convert_init_t * result)
00445 {
00446 convert_internal (CONVERT_RGB, 24, width, height, accel, arg, result);
00447 }
00448
00449 void convert_rgb16 (int width, int height, uint32_t accel, void * arg,
00450 convert_init_t * result)
00451 {
00452 convert_internal (CONVERT_RGB, 16, width, height, accel, arg, result);
00453 }
00454
00455 void convert_rgb15 (int width, int height, uint32_t accel, void * arg,
00456 convert_init_t * result)
00457 {
00458 convert_internal (CONVERT_RGB, 15, width, height, accel, arg, result);
00459 }
00460
00461 void convert_bgr32 (int width, int height, uint32_t accel, void * arg,
00462 convert_init_t * result)
00463 {
00464 convert_internal (CONVERT_BGR, 32, width, height, accel, arg, result);
00465 }
00466
00467 void convert_bgr24 (int width, int height, uint32_t accel, void * arg,
00468 convert_init_t * result)
00469 {
00470 convert_internal (CONVERT_BGR, 24, width, height, accel, arg, result);
00471 }
00472
00473 void convert_bgr16 (int width, int height, uint32_t accel, void * arg,
00474 convert_init_t * result)
00475 {
00476 convert_internal (CONVERT_BGR, 16, width, height, accel, arg, result);
00477 }
00478
00479 void convert_bgr15 (int width, int height, uint32_t accel, void * arg,
00480 convert_init_t * result)
00481 {
00482 convert_internal (CONVERT_BGR, 15, width, height, accel, arg, result);
00483 }
00484
00485 convert_t * convert_rgb (int order, int bpp)
00486 {
00487 if (order == CONVERT_RGB || order == CONVERT_BGR)
00488 switch (bpp) {
00489 case 32: return (order == CONVERT_RGB) ? convert_rgb32 : convert_bgr32;
00490 case 24: return (order == CONVERT_RGB) ? convert_rgb24 : convert_bgr24;
00491 case 16: return (order == CONVERT_RGB) ? convert_rgb16 : convert_bgr16;
00492 case 15: return (order == CONVERT_RGB) ? convert_rgb15 : convert_bgr15;
00493 }
00494 return NULL;
00495 }