00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00025
00026
00027
00028
00029
00030
00031 #include "avcodec.h"
00032 #include "dsputil.h"
00033
00034 #ifdef USE_FASTMEMCPY
00035 #include "fastmemcpy.h"
00036 #endif
00037
00038 #ifdef HAVE_MMX
00039 #include "i386/mmx.h"
00040 #endif
00041
00042 #define xglue(x, y) x ## y
00043 #define glue(x, y) xglue(x, y)
00044
00045 #define FF_COLOR_RGB 0
00046 #define FF_COLOR_GRAY 1
00047 #define FF_COLOR_YUV 2
00048 #define FF_COLOR_YUV_JPEG 3
00049
00050 #define FF_PIXEL_PLANAR 0
00051 #define FF_PIXEL_PACKED 1
00052 #define FF_PIXEL_PALETTE 2
00053
00054 typedef struct PixFmtInfo {
00055 const char *name;
00056 uint8_t nb_channels;
00057 uint8_t color_type;
00058 uint8_t pixel_type;
00059 uint8_t is_alpha : 1;
00060 uint8_t x_chroma_shift;
00061 uint8_t y_chroma_shift;
00062 uint8_t depth;
00063 } PixFmtInfo;
00064
00065
00066 static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
00067
00068 [PIX_FMT_YUV420P] = {
00069 .name = "yuv420p",
00070 .nb_channels = 3,
00071 .color_type = FF_COLOR_YUV,
00072 .pixel_type = FF_PIXEL_PLANAR,
00073 .depth = 8,
00074 .x_chroma_shift = 1, .y_chroma_shift = 1,
00075 },
00076 [PIX_FMT_YUV422P] = {
00077 .name = "yuv422p",
00078 .nb_channels = 3,
00079 .color_type = FF_COLOR_YUV,
00080 .pixel_type = FF_PIXEL_PLANAR,
00081 .depth = 8,
00082 .x_chroma_shift = 1, .y_chroma_shift = 0,
00083 },
00084 [PIX_FMT_YUV444P] = {
00085 .name = "yuv444p",
00086 .nb_channels = 3,
00087 .color_type = FF_COLOR_YUV,
00088 .pixel_type = FF_PIXEL_PLANAR,
00089 .depth = 8,
00090 .x_chroma_shift = 0, .y_chroma_shift = 0,
00091 },
00092 [PIX_FMT_YUV422] = {
00093 .name = "yuv422",
00094 .nb_channels = 1,
00095 .color_type = FF_COLOR_YUV,
00096 .pixel_type = FF_PIXEL_PACKED,
00097 .depth = 8,
00098 .x_chroma_shift = 1, .y_chroma_shift = 0,
00099 },
00100 [PIX_FMT_UYVY422] = {
00101 .name = "uyvy422",
00102 .nb_channels = 1,
00103 .color_type = FF_COLOR_YUV,
00104 .pixel_type = FF_PIXEL_PACKED,
00105 .depth = 8,
00106 .x_chroma_shift = 1, .y_chroma_shift = 0,
00107 },
00108 [PIX_FMT_YUV410P] = {
00109 .name = "yuv410p",
00110 .nb_channels = 3,
00111 .color_type = FF_COLOR_YUV,
00112 .pixel_type = FF_PIXEL_PLANAR,
00113 .depth = 8,
00114 .x_chroma_shift = 2, .y_chroma_shift = 2,
00115 },
00116 [PIX_FMT_YUV411P] = {
00117 .name = "yuv411p",
00118 .nb_channels = 3,
00119 .color_type = FF_COLOR_YUV,
00120 .pixel_type = FF_PIXEL_PLANAR,
00121 .depth = 8,
00122 .x_chroma_shift = 2, .y_chroma_shift = 0,
00123 },
00124
00125
00126 [PIX_FMT_YUVJ420P] = {
00127 .name = "yuvj420p",
00128 .nb_channels = 3,
00129 .color_type = FF_COLOR_YUV_JPEG,
00130 .pixel_type = FF_PIXEL_PLANAR,
00131 .depth = 8,
00132 .x_chroma_shift = 1, .y_chroma_shift = 1,
00133 },
00134 [PIX_FMT_YUVJ422P] = {
00135 .name = "yuvj422p",
00136 .nb_channels = 3,
00137 .color_type = FF_COLOR_YUV_JPEG,
00138 .pixel_type = FF_PIXEL_PLANAR,
00139 .depth = 8,
00140 .x_chroma_shift = 1, .y_chroma_shift = 0,
00141 },
00142 [PIX_FMT_YUVJ444P] = {
00143 .name = "yuvj444p",
00144 .nb_channels = 3,
00145 .color_type = FF_COLOR_YUV_JPEG,
00146 .pixel_type = FF_PIXEL_PLANAR,
00147 .depth = 8,
00148 .x_chroma_shift = 0, .y_chroma_shift = 0,
00149 },
00150
00151
00152 [PIX_FMT_RGB24] = {
00153 .name = "rgb24",
00154 .nb_channels = 3,
00155 .color_type = FF_COLOR_RGB,
00156 .pixel_type = FF_PIXEL_PACKED,
00157 .depth = 8,
00158 .x_chroma_shift = 0, .y_chroma_shift = 0,
00159 },
00160 [PIX_FMT_BGR24] = {
00161 .name = "bgr24",
00162 .nb_channels = 3,
00163 .color_type = FF_COLOR_RGB,
00164 .pixel_type = FF_PIXEL_PACKED,
00165 .depth = 8,
00166 .x_chroma_shift = 0, .y_chroma_shift = 0,
00167 },
00168 [PIX_FMT_RGBA32] = {
00169 .name = "rgba32",
00170 .nb_channels = 4, .is_alpha = 1,
00171 .color_type = FF_COLOR_RGB,
00172 .pixel_type = FF_PIXEL_PACKED,
00173 .depth = 8,
00174 .x_chroma_shift = 0, .y_chroma_shift = 0,
00175 },
00176 [PIX_FMT_RGB565] = {
00177 .name = "rgb565",
00178 .nb_channels = 3,
00179 .color_type = FF_COLOR_RGB,
00180 .pixel_type = FF_PIXEL_PACKED,
00181 .depth = 5,
00182 .x_chroma_shift = 0, .y_chroma_shift = 0,
00183 },
00184 [PIX_FMT_RGB555] = {
00185 .name = "rgb555",
00186 .nb_channels = 4, .is_alpha = 1,
00187 .color_type = FF_COLOR_RGB,
00188 .pixel_type = FF_PIXEL_PACKED,
00189 .depth = 5,
00190 .x_chroma_shift = 0, .y_chroma_shift = 0,
00191 },
00192
00193
00194 [PIX_FMT_GRAY8] = {
00195 .name = "gray",
00196 .nb_channels = 1,
00197 .color_type = FF_COLOR_GRAY,
00198 .pixel_type = FF_PIXEL_PLANAR,
00199 .depth = 8,
00200 },
00201 [PIX_FMT_MONOWHITE] = {
00202 .name = "monow",
00203 .nb_channels = 1,
00204 .color_type = FF_COLOR_GRAY,
00205 .pixel_type = FF_PIXEL_PLANAR,
00206 .depth = 1,
00207 },
00208 [PIX_FMT_MONOBLACK] = {
00209 .name = "monob",
00210 .nb_channels = 1,
00211 .color_type = FF_COLOR_GRAY,
00212 .pixel_type = FF_PIXEL_PLANAR,
00213 .depth = 1,
00214 },
00215
00216
00217 [PIX_FMT_PAL8] = {
00218 .name = "pal8",
00219 .nb_channels = 4, .is_alpha = 1,
00220 .color_type = FF_COLOR_RGB,
00221 .pixel_type = FF_PIXEL_PALETTE,
00222 .depth = 8,
00223 },
00224 [PIX_FMT_XVMC_MPEG2_MC] = {
00225 .name = "xvmcmc",
00226 },
00227 [PIX_FMT_XVMC_MPEG2_IDCT] = {
00228 .name = "xvmcidct",
00229 },
00230 [PIX_FMT_UYVY411] = {
00231 .name = "uyvy411",
00232 .nb_channels = 1,
00233 .color_type = FF_COLOR_YUV,
00234 .pixel_type = FF_PIXEL_PACKED,
00235 .depth = 8,
00236 .x_chroma_shift = 2, .y_chroma_shift = 0,
00237 },
00238 };
00239
00240 void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
00241 {
00242 *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
00243 *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
00244 }
00245
00246 const char *avcodec_get_pix_fmt_name(int pix_fmt)
00247 {
00248 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
00249 return "???";
00250 else
00251 return pix_fmt_info[pix_fmt].name;
00252 }
00253
00254 enum PixelFormat avcodec_get_pix_fmt(const char* name)
00255 {
00256 int i;
00257
00258 for (i=0; i < PIX_FMT_NB; i++)
00259 if (!strcmp(pix_fmt_info[i].name, name))
00260 break;
00261 return i;
00262 }
00263
00264
00265 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00266 int pix_fmt, int width, int height)
00267 {
00268 int size, w2, h2, size2;
00269 PixFmtInfo *pinfo;
00270
00271 if(avcodec_check_dimensions(NULL, width, height))
00272 goto fail;
00273
00274 pinfo = &pix_fmt_info[pix_fmt];
00275 size = width * height;
00276 switch(pix_fmt) {
00277 case PIX_FMT_YUV420P:
00278 case PIX_FMT_YUV422P:
00279 case PIX_FMT_YUV444P:
00280 case PIX_FMT_YUV410P:
00281 case PIX_FMT_YUV411P:
00282 case PIX_FMT_YUVJ420P:
00283 case PIX_FMT_YUVJ422P:
00284 case PIX_FMT_YUVJ444P:
00285 w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
00286 h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
00287 size2 = w2 * h2;
00288 picture->data[0] = ptr;
00289 picture->data[1] = picture->data[0] + size;
00290 picture->data[2] = picture->data[1] + size2;
00291 picture->linesize[0] = width;
00292 picture->linesize[1] = w2;
00293 picture->linesize[2] = w2;
00294 return size + 2 * size2;
00295 case PIX_FMT_RGB24:
00296 case PIX_FMT_BGR24:
00297 picture->data[0] = ptr;
00298 picture->data[1] = NULL;
00299 picture->data[2] = NULL;
00300 picture->linesize[0] = width * 3;
00301 return size * 3;
00302 case PIX_FMT_RGBA32:
00303 picture->data[0] = ptr;
00304 picture->data[1] = NULL;
00305 picture->data[2] = NULL;
00306 picture->linesize[0] = width * 4;
00307 return size * 4;
00308 case PIX_FMT_RGB555:
00309 case PIX_FMT_RGB565:
00310 case PIX_FMT_YUV422:
00311 picture->data[0] = ptr;
00312 picture->data[1] = NULL;
00313 picture->data[2] = NULL;
00314 picture->linesize[0] = width * 2;
00315 return size * 2;
00316 case PIX_FMT_UYVY422:
00317 picture->data[0] = ptr;
00318 picture->data[1] = NULL;
00319 picture->data[2] = NULL;
00320 picture->linesize[0] = width * 2;
00321 return size * 2;
00322 case PIX_FMT_UYVY411:
00323 picture->data[0] = ptr;
00324 picture->data[1] = NULL;
00325 picture->data[2] = NULL;
00326 picture->linesize[0] = width + width/2;
00327 return size + size/2;
00328 case PIX_FMT_GRAY8:
00329 picture->data[0] = ptr;
00330 picture->data[1] = NULL;
00331 picture->data[2] = NULL;
00332 picture->linesize[0] = width;
00333 return size;
00334 case PIX_FMT_MONOWHITE:
00335 case PIX_FMT_MONOBLACK:
00336 picture->data[0] = ptr;
00337 picture->data[1] = NULL;
00338 picture->data[2] = NULL;
00339 picture->linesize[0] = (width + 7) >> 3;
00340 return picture->linesize[0] * height;
00341 case PIX_FMT_PAL8:
00342 size2 = (size + 3) & ~3;
00343 picture->data[0] = ptr;
00344 picture->data[1] = ptr + size2;
00345 picture->data[2] = NULL;
00346 picture->linesize[0] = width;
00347 picture->linesize[1] = 4;
00348 return size2 + 256 * 4;
00349 default:
00350 fail:
00351 picture->data[0] = NULL;
00352 picture->data[1] = NULL;
00353 picture->data[2] = NULL;
00354 picture->data[3] = NULL;
00355 return -1;
00356 }
00357 }
00358
00359 int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
00360 unsigned char *dest, int dest_size)
00361 {
00362 PixFmtInfo* pf = &pix_fmt_info[pix_fmt];
00363 int i, j, w, h, data_planes;
00364 const unsigned char* s;
00365 int size = avpicture_get_size(pix_fmt, width, height);
00366
00367 if (size > dest_size || size < 0)
00368 return -1;
00369
00370 if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
00371 if (pix_fmt == PIX_FMT_YUV422 ||
00372 pix_fmt == PIX_FMT_UYVY422 ||
00373 pix_fmt == PIX_FMT_RGB565 ||
00374 pix_fmt == PIX_FMT_RGB555)
00375 w = width * 2;
00376 else if (pix_fmt == PIX_FMT_UYVY411)
00377 w = width + width/2;
00378 else if (pix_fmt == PIX_FMT_PAL8)
00379 w = width;
00380 else
00381 w = width * (pf->depth * pf->nb_channels / 8);
00382
00383 data_planes = 1;
00384 h = height;
00385 } else {
00386 data_planes = pf->nb_channels;
00387 w = (width*pf->depth + 7)/8;
00388 h = height;
00389 }
00390
00391 for (i=0; i<data_planes; i++) {
00392 if (i == 1) {
00393 w = width >> pf->x_chroma_shift;
00394 h = height >> pf->y_chroma_shift;
00395 }
00396 s = src->data[i];
00397 for(j=0; j<h; j++) {
00398 memcpy(dest, s, w);
00399 dest += w;
00400 s += src->linesize[i];
00401 }
00402 }
00403
00404 if (pf->pixel_type == FF_PIXEL_PALETTE)
00405 memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00406
00407 return size;
00408 }
00409
00410 int avpicture_get_size(int pix_fmt, int width, int height)
00411 {
00412 AVPicture dummy_pict;
00413 return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00414 }
00415
00419 int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
00420 int has_alpha)
00421 {
00422 const PixFmtInfo *pf, *ps;
00423 int loss;
00424
00425 ps = &pix_fmt_info[src_pix_fmt];
00426 pf = &pix_fmt_info[dst_pix_fmt];
00427
00428
00429 loss = 0;
00430 pf = &pix_fmt_info[dst_pix_fmt];
00431 if (pf->depth < ps->depth ||
00432 (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
00433 loss |= FF_LOSS_DEPTH;
00434 if (pf->x_chroma_shift > ps->x_chroma_shift ||
00435 pf->y_chroma_shift > ps->y_chroma_shift)
00436 loss |= FF_LOSS_RESOLUTION;
00437 switch(pf->color_type) {
00438 case FF_COLOR_RGB:
00439 if (ps->color_type != FF_COLOR_RGB &&
00440 ps->color_type != FF_COLOR_GRAY)
00441 loss |= FF_LOSS_COLORSPACE;
00442 break;
00443 case FF_COLOR_GRAY:
00444 if (ps->color_type != FF_COLOR_GRAY)
00445 loss |= FF_LOSS_COLORSPACE;
00446 break;
00447 case FF_COLOR_YUV:
00448 if (ps->color_type != FF_COLOR_YUV)
00449 loss |= FF_LOSS_COLORSPACE;
00450 break;
00451 case FF_COLOR_YUV_JPEG:
00452 if (ps->color_type != FF_COLOR_YUV_JPEG &&
00453 ps->color_type != FF_COLOR_YUV &&
00454 ps->color_type != FF_COLOR_GRAY)
00455 loss |= FF_LOSS_COLORSPACE;
00456 break;
00457 default:
00458
00459 if (ps->color_type != pf->color_type)
00460 loss |= FF_LOSS_COLORSPACE;
00461 break;
00462 }
00463 if (pf->color_type == FF_COLOR_GRAY &&
00464 ps->color_type != FF_COLOR_GRAY)
00465 loss |= FF_LOSS_CHROMA;
00466 if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00467 loss |= FF_LOSS_ALPHA;
00468 if (pf->pixel_type == FF_PIXEL_PALETTE &&
00469 (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00470 loss |= FF_LOSS_COLORQUANT;
00471 return loss;
00472 }
00473
00474 static int avg_bits_per_pixel(int pix_fmt)
00475 {
00476 int bits;
00477 const PixFmtInfo *pf;
00478
00479 pf = &pix_fmt_info[pix_fmt];
00480 switch(pf->pixel_type) {
00481 case FF_PIXEL_PACKED:
00482 switch(pix_fmt) {
00483 case PIX_FMT_YUV422:
00484 case PIX_FMT_UYVY422:
00485 case PIX_FMT_RGB565:
00486 case PIX_FMT_RGB555:
00487 bits = 16;
00488 break;
00489 case PIX_FMT_UYVY411:
00490 bits = 12;
00491 break;
00492 default:
00493 bits = pf->depth * pf->nb_channels;
00494 break;
00495 }
00496 break;
00497 case FF_PIXEL_PLANAR:
00498 if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
00499 bits = pf->depth * pf->nb_channels;
00500 } else {
00501 bits = pf->depth + ((2 * pf->depth) >>
00502 (pf->x_chroma_shift + pf->y_chroma_shift));
00503 }
00504 break;
00505 case FF_PIXEL_PALETTE:
00506 bits = 8;
00507 break;
00508 default:
00509 bits = -1;
00510 break;
00511 }
00512 return bits;
00513 }
00514
00515 static int avcodec_find_best_pix_fmt1(int pix_fmt_mask,
00516 int src_pix_fmt,
00517 int has_alpha,
00518 int loss_mask)
00519 {
00520 int dist, i, loss, min_dist, dst_pix_fmt;
00521
00522
00523 dst_pix_fmt = -1;
00524 min_dist = 0x7fffffff;
00525 for(i = 0;i < PIX_FMT_NB; i++) {
00526 if (pix_fmt_mask & (1 << i)) {
00527 loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00528 if (loss == 0) {
00529 dist = avg_bits_per_pixel(i);
00530 if (dist < min_dist) {
00531 min_dist = dist;
00532 dst_pix_fmt = i;
00533 }
00534 }
00535 }
00536 }
00537 return dst_pix_fmt;
00538 }
00539
00543 int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
00544 int has_alpha, int *loss_ptr)
00545 {
00546 int dst_pix_fmt, loss_mask, i;
00547 static const int loss_mask_order[] = {
00548 ~0,
00549 ~FF_LOSS_ALPHA,
00550 ~FF_LOSS_RESOLUTION,
00551 ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00552 ~FF_LOSS_COLORQUANT,
00553 ~FF_LOSS_DEPTH,
00554 0,
00555 };
00556
00557
00558 i = 0;
00559 for(;;) {
00560 loss_mask = loss_mask_order[i++];
00561 dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00562 has_alpha, loss_mask);
00563 if (dst_pix_fmt >= 0)
00564 goto found;
00565 if (loss_mask == 0)
00566 break;
00567 }
00568 return -1;
00569 found:
00570 if (loss_ptr)
00571 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00572 return dst_pix_fmt;
00573 }
00574
00575 static void img_copy_plane(uint8_t *dst, int dst_wrap,
00576 const uint8_t *src, int src_wrap,
00577 int width, int height)
00578 {
00579 if((!dst) || (!src))
00580 return;
00581 for(;height > 0; height--) {
00582 memcpy(dst, src, width);
00583 dst += dst_wrap;
00584 src += src_wrap;
00585 }
00586 }
00587
00591 void img_copy(AVPicture *dst, const AVPicture *src,
00592 int pix_fmt, int width, int height)
00593 {
00594 int bwidth, bits, i;
00595 PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00596
00597 pf = &pix_fmt_info[pix_fmt];
00598 switch(pf->pixel_type) {
00599 case FF_PIXEL_PACKED:
00600 switch(pix_fmt) {
00601 case PIX_FMT_YUV422:
00602 case PIX_FMT_UYVY422:
00603 case PIX_FMT_RGB565:
00604 case PIX_FMT_RGB555:
00605 bits = 16;
00606 break;
00607 case PIX_FMT_UYVY411:
00608 bits = 12;
00609 break;
00610 default:
00611 bits = pf->depth * pf->nb_channels;
00612 break;
00613 }
00614 bwidth = (width * bits + 7) >> 3;
00615 img_copy_plane(dst->data[0], dst->linesize[0],
00616 src->data[0], src->linesize[0],
00617 bwidth, height);
00618 break;
00619 case FF_PIXEL_PLANAR:
00620 for(i = 0; i < pf->nb_channels; i++) {
00621 int w, h;
00622 w = width;
00623 h = height;
00624 if (i == 1 || i == 2) {
00625 w >>= pf->x_chroma_shift;
00626 h >>= pf->y_chroma_shift;
00627 }
00628 bwidth = (w * pf->depth + 7) >> 3;
00629 img_copy_plane(dst->data[i], dst->linesize[i],
00630 src->data[i], src->linesize[i],
00631 bwidth, h);
00632 }
00633 break;
00634 case FF_PIXEL_PALETTE:
00635 img_copy_plane(dst->data[0], dst->linesize[0],
00636 src->data[0], src->linesize[0],
00637 width, height);
00638
00639 img_copy_plane(dst->data[1], dst->linesize[1],
00640 src->data[1], src->linesize[1],
00641 4, 256);
00642 break;
00643 }
00644 }
00645
00646
00647
00648 static void yuv422_to_yuv420p(AVPicture *dst, const AVPicture *src,
00649 int width, int height)
00650 {
00651 const uint8_t *p, *p1;
00652 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00653 int w;
00654
00655 p1 = src->data[0];
00656 lum1 = dst->data[0];
00657 cb1 = dst->data[1];
00658 cr1 = dst->data[2];
00659
00660 for(;height >= 1; height -= 2) {
00661 p = p1;
00662 lum = lum1;
00663 cb = cb1;
00664 cr = cr1;
00665 for(w = width; w >= 2; w -= 2) {
00666 lum[0] = p[0];
00667 cb[0] = p[1];
00668 lum[1] = p[2];
00669 cr[0] = p[3];
00670 p += 4;
00671 lum += 2;
00672 cb++;
00673 cr++;
00674 }
00675 if (w) {
00676 lum[0] = p[0];
00677 cb[0] = p[1];
00678 cr[0] = p[3];
00679 cb++;
00680 cr++;
00681 }
00682 p1 += src->linesize[0];
00683 lum1 += dst->linesize[0];
00684 if (height>1) {
00685 p = p1;
00686 lum = lum1;
00687 for(w = width; w >= 2; w -= 2) {
00688 lum[0] = p[0];
00689 lum[1] = p[2];
00690 p += 4;
00691 lum += 2;
00692 }
00693 if (w) {
00694 lum[0] = p[0];
00695 }
00696 p1 += src->linesize[0];
00697 lum1 += dst->linesize[0];
00698 }
00699 cb1 += dst->linesize[1];
00700 cr1 += dst->linesize[2];
00701 }
00702 }
00703
00704 static void uyvy422_to_yuv420p(AVPicture *dst, const AVPicture *src,
00705 int width, int height)
00706 {
00707 const uint8_t *p, *p1;
00708 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00709 int w;
00710
00711 p1 = src->data[0];
00712
00713 lum1 = dst->data[0];
00714 cb1 = dst->data[1];
00715 cr1 = dst->data[2];
00716
00717 for(;height >= 1; height -= 2) {
00718 p = p1;
00719 lum = lum1;
00720 cb = cb1;
00721 cr = cr1;
00722 for(w = width; w >= 2; w -= 2) {
00723 lum[0] = p[1];
00724 cb[0] = p[0];
00725 lum[1] = p[3];
00726 cr[0] = p[2];
00727 p += 4;
00728 lum += 2;
00729 cb++;
00730 cr++;
00731 }
00732 if (w) {
00733 lum[0] = p[1];
00734 cb[0] = p[0];
00735 cr[0] = p[2];
00736 cb++;
00737 cr++;
00738 }
00739 p1 += src->linesize[0];
00740 lum1 += dst->linesize[0];
00741 if (height>1) {
00742 p = p1;
00743 lum = lum1;
00744 for(w = width; w >= 2; w -= 2) {
00745 lum[0] = p[1];
00746 lum[1] = p[3];
00747 p += 4;
00748 lum += 2;
00749 }
00750 if (w) {
00751 lum[0] = p[1];
00752 }
00753 p1 += src->linesize[0];
00754 lum1 += dst->linesize[0];
00755 }
00756 cb1 += dst->linesize[1];
00757 cr1 += dst->linesize[2];
00758 }
00759 }
00760
00761
00762 static void uyvy422_to_yuv422p(AVPicture *dst, const AVPicture *src,
00763 int width, int height)
00764 {
00765 const uint8_t *p, *p1;
00766 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00767 int w;
00768
00769 p1 = src->data[0];
00770 lum1 = dst->data[0];
00771 cb1 = dst->data[1];
00772 cr1 = dst->data[2];
00773 for(;height > 0; height--) {
00774 p = p1;
00775 lum = lum1;
00776 cb = cb1;
00777 cr = cr1;
00778 for(w = width; w >= 2; w -= 2) {
00779 lum[0] = p[1];
00780 cb[0] = p[0];
00781 lum[1] = p[3];
00782 cr[0] = p[2];
00783 p += 4;
00784 lum += 2;
00785 cb++;
00786 cr++;
00787 }
00788 p1 += src->linesize[0];
00789 lum1 += dst->linesize[0];
00790 cb1 += dst->linesize[1];
00791 cr1 += dst->linesize[2];
00792 }
00793 }
00794
00795
00796 static void yuv422_to_yuv422p(AVPicture *dst, const AVPicture *src,
00797 int width, int height)
00798 {
00799 const uint8_t *p, *p1;
00800 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00801 int w;
00802
00803 p1 = src->data[0];
00804 lum1 = dst->data[0];
00805 cb1 = dst->data[1];
00806 cr1 = dst->data[2];
00807 for(;height > 0; height--) {
00808 p = p1;
00809 lum = lum1;
00810 cb = cb1;
00811 cr = cr1;
00812 for(w = width; w >= 2; w -= 2) {
00813 lum[0] = p[0];
00814 cb[0] = p[1];
00815 lum[1] = p[2];
00816 cr[0] = p[3];
00817 p += 4;
00818 lum += 2;
00819 cb++;
00820 cr++;
00821 }
00822 p1 += src->linesize[0];
00823 lum1 += dst->linesize[0];
00824 cb1 += dst->linesize[1];
00825 cr1 += dst->linesize[2];
00826 }
00827 }
00828
00829 static void yuv422p_to_yuv422(AVPicture *dst, const AVPicture *src,
00830 int width, int height)
00831 {
00832 uint8_t *p, *p1;
00833 const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00834 int w;
00835
00836 p1 = dst->data[0];
00837 lum1 = src->data[0];
00838 cb1 = src->data[1];
00839 cr1 = src->data[2];
00840 for(;height > 0; height--) {
00841 p = p1;
00842 lum = lum1;
00843 cb = cb1;
00844 cr = cr1;
00845 for(w = width; w >= 2; w -= 2) {
00846 p[0] = lum[0];
00847 p[1] = cb[0];
00848 p[2] = lum[1];
00849 p[3] = cr[0];
00850 p += 4;
00851 lum += 2;
00852 cb++;
00853 cr++;
00854 }
00855 p1 += dst->linesize[0];
00856 lum1 += src->linesize[0];
00857 cb1 += src->linesize[1];
00858 cr1 += src->linesize[2];
00859 }
00860 }
00861
00862 static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src,
00863 int width, int height)
00864 {
00865 uint8_t *p, *p1;
00866 const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00867 int w;
00868
00869 p1 = dst->data[0];
00870 lum1 = src->data[0];
00871 cb1 = src->data[1];
00872 cr1 = src->data[2];
00873 for(;height > 0; height--) {
00874 p = p1;
00875 lum = lum1;
00876 cb = cb1;
00877 cr = cr1;
00878 for(w = width; w >= 2; w -= 2) {
00879 p[1] = lum[0];
00880 p[0] = cb[0];
00881 p[3] = lum[1];
00882 p[2] = cr[0];
00883 p += 4;
00884 lum += 2;
00885 cb++;
00886 cr++;
00887 }
00888 p1 += dst->linesize[0];
00889 lum1 += src->linesize[0];
00890 cb1 += src->linesize[1];
00891 cr1 += src->linesize[2];
00892 }
00893 }
00894
00895 static void uyvy411_to_yuv411p(AVPicture *dst, const AVPicture *src,
00896 int width, int height)
00897 {
00898 const uint8_t *p, *p1;
00899 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00900 int w;
00901
00902 p1 = src->data[0];
00903 lum1 = dst->data[0];
00904 cb1 = dst->data[1];
00905 cr1 = dst->data[2];
00906 for(;height > 0; height--) {
00907 p = p1;
00908 lum = lum1;
00909 cb = cb1;
00910 cr = cr1;
00911 for(w = width; w >= 4; w -= 4) {
00912 cb[0] = p[0];
00913 lum[0] = p[1];
00914 lum[1] = p[2];
00915 cr[0] = p[3];
00916 lum[2] = p[4];
00917 lum[3] = p[5];
00918 p += 6;
00919 lum += 4;
00920 cb++;
00921 cr++;
00922 }
00923 p1 += src->linesize[0];
00924 lum1 += dst->linesize[0];
00925 cb1 += dst->linesize[1];
00926 cr1 += dst->linesize[2];
00927 }
00928 }
00929
00930
00931 static void yuv420p_to_yuv422(AVPicture *dst, const AVPicture *src,
00932 int width, int height)
00933 {
00934 int w, h;
00935 uint8_t *line1, *line2, *linesrc = dst->data[0];
00936 uint8_t *lum1, *lum2, *lumsrc = src->data[0];
00937 uint8_t *cb1, *cb2 = src->data[1];
00938 uint8_t *cr1, *cr2 = src->data[2];
00939
00940 for(h = height / 2; h--;) {
00941 line1 = linesrc;
00942 line2 = linesrc + dst->linesize[0];
00943
00944 lum1 = lumsrc;
00945 lum2 = lumsrc + src->linesize[0];
00946
00947 cb1 = cb2;
00948 cr1 = cr2;
00949
00950 for(w = width / 2; w--;) {
00951 *line1++ = *lum1++; *line2++ = *lum2++;
00952 *line1++ = *line2++ = *cb1++;
00953 *line1++ = *lum1++; *line2++ = *lum2++;
00954 *line1++ = *line2++ = *cr1++;
00955 }
00956
00957 linesrc += dst->linesize[0] * 2;
00958 lumsrc += src->linesize[0] * 2;
00959 cb2 += src->linesize[1];
00960 cr2 += src->linesize[2];
00961 }
00962 }
00963
00964 static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src,
00965 int width, int height)
00966 {
00967 int w, h;
00968 uint8_t *line1, *line2, *linesrc = dst->data[0];
00969 uint8_t *lum1, *lum2, *lumsrc = src->data[0];
00970 uint8_t *cb1, *cb2 = src->data[1];
00971 uint8_t *cr1, *cr2 = src->data[2];
00972
00973 for(h = height / 2; h--;) {
00974 line1 = linesrc;
00975 line2 = linesrc + dst->linesize[0];
00976
00977 lum1 = lumsrc;
00978 lum2 = lumsrc + src->linesize[0];
00979
00980 cb1 = cb2;
00981 cr1 = cr2;
00982
00983 for(w = width / 2; w--;) {
00984 *line1++ = *line2++ = *cb1++;
00985 *line1++ = *lum1++; *line2++ = *lum2++;
00986 *line1++ = *line2++ = *cr1++;
00987 *line1++ = *lum1++; *line2++ = *lum2++;
00988 }
00989
00990 linesrc += dst->linesize[0] * 2;
00991 lumsrc += src->linesize[0] * 2;
00992 cb2 += src->linesize[1];
00993 cr2 += src->linesize[2];
00994 }
00995 }
00996
00997 #define SCALEBITS 10
00998 #define ONE_HALF (1 << (SCALEBITS - 1))
00999 #define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
01000
01001 #define YUV_TO_RGB1_CCIR(cb1, cr1)\
01002 {\
01003 cb = (cb1) - 128;\
01004 cr = (cr1) - 128;\
01005 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
01006 g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
01007 ONE_HALF;\
01008 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
01009 }
01010
01011 #define YUV_TO_RGB2_CCIR(r, g, b, y1)\
01012 {\
01013 y = ((y1) - 16) * FIX(255.0/219.0);\
01014 r = cm[(y + r_add) >> SCALEBITS];\
01015 g = cm[(y + g_add) >> SCALEBITS];\
01016 b = cm[(y + b_add) >> SCALEBITS];\
01017 }
01018
01019 #define YUV_TO_RGB1(cb1, cr1)\
01020 {\
01021 cb = (cb1) - 128;\
01022 cr = (cr1) - 128;\
01023 r_add = FIX(1.40200) * cr + ONE_HALF;\
01024 g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\
01025 b_add = FIX(1.77200) * cb + ONE_HALF;\
01026 }
01027
01028 #define YUV_TO_RGB2(r, g, b, y1)\
01029 {\
01030 y = (y1) << SCALEBITS;\
01031 r = cm[(y + r_add) >> SCALEBITS];\
01032 g = cm[(y + g_add) >> SCALEBITS];\
01033 b = cm[(y + b_add) >> SCALEBITS];\
01034 }
01035
01036 #define Y_CCIR_TO_JPEG(y)\
01037 cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS]
01038
01039 #define Y_JPEG_TO_CCIR(y)\
01040 (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
01041
01042 #define C_CCIR_TO_JPEG(y)\
01043 cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS]
01044
01045
01046 static inline int C_JPEG_TO_CCIR(int y) {
01047 y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS);
01048 if (y < 16)
01049 y = 16;
01050 return y;
01051 }
01052
01053
01054 #define RGB_TO_Y(r, g, b) \
01055 ((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
01056 FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
01057
01058 #define RGB_TO_U(r1, g1, b1, shift)\
01059 (((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
01060 FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
01061
01062 #define RGB_TO_V(r1, g1, b1, shift)\
01063 (((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
01064 FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
01065
01066 #define RGB_TO_Y_CCIR(r, g, b) \
01067 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
01068 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
01069
01070 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
01071 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
01072 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
01073
01074 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
01075 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
01076 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
01077
01078 static uint8_t y_ccir_to_jpeg[256];
01079 static uint8_t y_jpeg_to_ccir[256];
01080 static uint8_t c_ccir_to_jpeg[256];
01081 static uint8_t c_jpeg_to_ccir[256];
01082
01083
01084 static void img_convert_init(void)
01085 {
01086 int i;
01087 uint8_t *cm = cropTbl + MAX_NEG_CROP;
01088
01089 for(i = 0;i < 256; i++) {
01090 y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i);
01091 y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i);
01092 c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i);
01093 c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i);
01094 }
01095 }
01096
01097
01098 static void img_apply_table(uint8_t *dst, int dst_wrap,
01099 const uint8_t *src, int src_wrap,
01100 int width, int height, const uint8_t *table1)
01101 {
01102 int n;
01103 const uint8_t *s;
01104 uint8_t *d;
01105 const uint8_t *table;
01106
01107 table = table1;
01108 for(;height > 0; height--) {
01109 s = src;
01110 d = dst;
01111 n = width;
01112 while (n >= 4) {
01113 d[0] = table[s[0]];
01114 d[1] = table[s[1]];
01115 d[2] = table[s[2]];
01116 d[3] = table[s[3]];
01117 d += 4;
01118 s += 4;
01119 n -= 4;
01120 }
01121 while (n > 0) {
01122 d[0] = table[s[0]];
01123 d++;
01124 s++;
01125 n--;
01126 }
01127 dst += dst_wrap;
01128 src += src_wrap;
01129 }
01130 }
01131
01132
01133
01134
01135
01136 static void shrink41(uint8_t *dst, int dst_wrap,
01137 const uint8_t *src, int src_wrap,
01138 int width, int height)
01139 {
01140 int w;
01141 const uint8_t *s;
01142 uint8_t *d;
01143
01144 for(;height > 0; height--) {
01145 s = src;
01146 d = dst;
01147 for(w = width;w > 0; w--) {
01148 d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2;
01149 s += 4;
01150 d++;
01151 }
01152 src += src_wrap;
01153 dst += dst_wrap;
01154 }
01155 }
01156
01157
01158 static void shrink21(uint8_t *dst, int dst_wrap,
01159 const uint8_t *src, int src_wrap,
01160 int width, int height)
01161 {
01162 int w;
01163 const uint8_t *s;
01164 uint8_t *d;
01165
01166 for(;height > 0; height--) {
01167 s = src;
01168 d = dst;
01169 for(w = width;w > 0; w--) {
01170 d[0] = (s[0] + s[1]) >> 1;
01171 s += 2;
01172 d++;
01173 }
01174 src += src_wrap;
01175 dst += dst_wrap;
01176 }
01177 }
01178
01179
01180 static void shrink12(uint8_t *dst, int dst_wrap,
01181 const uint8_t *src, int src_wrap,
01182 int width, int height)
01183 {
01184 int w;
01185 uint8_t *d;
01186 const uint8_t *s1, *s2;
01187
01188 for(;height > 0; height--) {
01189 s1 = src;
01190 s2 = s1 + src_wrap;
01191 d = dst;
01192 for(w = width;w >= 4; w-=4) {
01193 d[0] = (s1[0] + s2[0]) >> 1;
01194 d[1] = (s1[1] + s2[1]) >> 1;
01195 d[2] = (s1[2] + s2[2]) >> 1;
01196 d[3] = (s1[3] + s2[3]) >> 1;
01197 s1 += 4;
01198 s2 += 4;
01199 d += 4;
01200 }
01201 for(;w > 0; w--) {
01202 d[0] = (s1[0] + s2[0]) >> 1;
01203 s1++;
01204 s2++;
01205 d++;
01206 }
01207 src += 2 * src_wrap;
01208 dst += dst_wrap;
01209 }
01210 }
01211
01212
01213 static void shrink22(uint8_t *dst, int dst_wrap,
01214 const uint8_t *src, int src_wrap,
01215 int width, int height)
01216 {
01217 int w;
01218 const uint8_t *s1, *s2;
01219 uint8_t *d;
01220
01221 for(;height > 0; height--) {
01222 s1 = src;
01223 s2 = s1 + src_wrap;
01224 d = dst;
01225 for(w = width;w >= 4; w-=4) {
01226 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
01227 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
01228 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
01229 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
01230 s1 += 8;
01231 s2 += 8;
01232 d += 4;
01233 }
01234 for(;w > 0; w--) {
01235 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
01236 s1 += 2;
01237 s2 += 2;
01238 d++;
01239 }
01240 src += 2 * src_wrap;
01241 dst += dst_wrap;
01242 }
01243 }
01244
01245
01246 static void shrink44(uint8_t *dst, int dst_wrap,
01247 const uint8_t *src, int src_wrap,
01248 int width, int height)
01249 {
01250 int w;
01251 const uint8_t *s1, *s2, *s3, *s4;
01252 uint8_t *d;
01253
01254 for(;height > 0; height--) {
01255 s1 = src;
01256 s2 = s1 + src_wrap;
01257 s3 = s2 + src_wrap;
01258 s4 = s3 + src_wrap;
01259 d = dst;
01260 for(w = width;w > 0; w--) {
01261 d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
01262 s2[0] + s2[1] + s2[2] + s2[3] +
01263 s3[0] + s3[1] + s3[2] + s3[3] +
01264 s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
01265 s1 += 4;
01266 s2 += 4;
01267 s3 += 4;
01268 s4 += 4;
01269 d++;
01270 }
01271 src += 4 * src_wrap;
01272 dst += dst_wrap;
01273 }
01274 }
01275
01276 static void grow21_line(uint8_t *dst, const uint8_t *src,
01277 int width)
01278 {
01279 int w;
01280 const uint8_t *s1;
01281 uint8_t *d;
01282
01283 s1 = src;
01284 d = dst;
01285 for(w = width;w >= 4; w-=4) {
01286 d[1] = d[0] = s1[0];
01287 d[3] = d[2] = s1[1];
01288 s1 += 2;
01289 d += 4;
01290 }
01291 for(;w >= 2; w -= 2) {
01292 d[1] = d[0] = s1[0];
01293 s1 ++;
01294 d += 2;
01295 }
01296
01297
01298 if (w) {
01299 d[0] = s1[0];
01300 }
01301 }
01302
01303 static void grow41_line(uint8_t *dst, const uint8_t *src,
01304 int width)
01305 {
01306 int w, v;
01307 const uint8_t *s1;
01308 uint8_t *d;
01309
01310 s1 = src;
01311 d = dst;
01312 for(w = width;w >= 4; w-=4) {
01313 v = s1[0];
01314 d[0] = v;
01315 d[1] = v;
01316 d[2] = v;
01317 d[3] = v;
01318 s1 ++;
01319 d += 4;
01320 }
01321 }
01322
01323
01324 static void grow21(uint8_t *dst, int dst_wrap,
01325 const uint8_t *src, int src_wrap,
01326 int width, int height)
01327 {
01328 for(;height > 0; height--) {
01329 grow21_line(dst, src, width);
01330 src += src_wrap;
01331 dst += dst_wrap;
01332 }
01333 }
01334
01335
01336 static void grow22(uint8_t *dst, int dst_wrap,
01337 const uint8_t *src, int src_wrap,
01338 int width, int height)
01339 {
01340 for(;height > 0; height--) {
01341 grow21_line(dst, src, width);
01342 if (height%2)
01343 src += src_wrap;
01344 dst += dst_wrap;
01345 }
01346 }
01347
01348
01349 static void grow41(uint8_t *dst, int dst_wrap,
01350 const uint8_t *src, int src_wrap,
01351 int width, int height)
01352 {
01353 for(;height > 0; height--) {
01354 grow41_line(dst, src, width);
01355 src += src_wrap;
01356 dst += dst_wrap;
01357 }
01358 }
01359
01360
01361 static void grow44(uint8_t *dst, int dst_wrap,
01362 const uint8_t *src, int src_wrap,
01363 int width, int height)
01364 {
01365 for(;height > 0; height--) {
01366 grow41_line(dst, src, width);
01367 if ((height & 3) == 1)
01368 src += src_wrap;
01369 dst += dst_wrap;
01370 }
01371 }
01372
01373
01374 static void conv411(uint8_t *dst, int dst_wrap,
01375 const uint8_t *src, int src_wrap,
01376 int width, int height)
01377 {
01378 int w, c;
01379 const uint8_t *s1, *s2;
01380 uint8_t *d;
01381
01382 width>>=1;
01383
01384 for(;height > 0; height--) {
01385 s1 = src;
01386 s2 = src + src_wrap;
01387 d = dst;
01388 for(w = width;w > 0; w--) {
01389 c = (s1[0] + s2[0]) >> 1;
01390 d[0] = c;
01391 d[1] = c;
01392 s1++;
01393 s2++;
01394 d += 2;
01395 }
01396 src += src_wrap * 2;
01397 dst += dst_wrap;
01398 }
01399 }
01400
01401
01402
01403 #define TRANSP_INDEX (6*6*6)
01404
01405
01406 static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
01407 {
01408 return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
01409 }
01410
01411 static void build_rgb_palette(uint8_t *palette, int has_alpha)
01412 {
01413 uint32_t *pal;
01414 static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
01415 int i, r, g, b;
01416
01417 pal = (uint32_t *)palette;
01418 i = 0;
01419 for(r = 0; r < 6; r++) {
01420 for(g = 0; g < 6; g++) {
01421 for(b = 0; b < 6; b++) {
01422 pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
01423 (pal_value[g] << 8) | pal_value[b];
01424 }
01425 }
01426 }
01427 if (has_alpha)
01428 pal[i++] = 0;
01429 while (i < 256)
01430 pal[i++] = 0xff000000;
01431 }
01432
01433
01434 static inline unsigned int bitcopy_n(unsigned int a, int n)
01435 {
01436 int mask;
01437 mask = (1 << n) - 1;
01438 return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
01439 }
01440
01441
01442
01443 #define RGB_NAME rgb555
01444
01445 #define RGB_IN(r, g, b, s)\
01446 {\
01447 unsigned int v = ((const uint16_t *)(s))[0];\
01448 r = bitcopy_n(v >> (10 - 3), 3);\
01449 g = bitcopy_n(v >> (5 - 3), 3);\
01450 b = bitcopy_n(v << 3, 3);\
01451 }
01452
01453 #define RGBA_IN(r, g, b, a, s)\
01454 {\
01455 unsigned int v = ((const uint16_t *)(s))[0];\
01456 r = bitcopy_n(v >> (10 - 3), 3);\
01457 g = bitcopy_n(v >> (5 - 3), 3);\
01458 b = bitcopy_n(v << 3, 3);\
01459 a = (-(v >> 15)) & 0xff;\
01460 }
01461
01462 #define RGBA_OUT(d, r, g, b, a)\
01463 {\
01464 ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \
01465 ((a << 8) & 0x8000);\
01466 }
01467
01468 #define BPP 2
01469
01470 #include "imgconvert_template.h"
01471
01472
01473
01474 #define RGB_NAME rgb565
01475
01476 #define RGB_IN(r, g, b, s)\
01477 {\
01478 unsigned int v = ((const uint16_t *)(s))[0];\
01479 r = bitcopy_n(v >> (11 - 3), 3);\
01480 g = bitcopy_n(v >> (5 - 2), 2);\
01481 b = bitcopy_n(v << 3, 3);\
01482 }
01483
01484 #define RGB_OUT(d, r, g, b)\
01485 {\
01486 ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
01487 }
01488
01489 #define BPP 2
01490
01491 #include "imgconvert_template.h"
01492
01493
01494
01495 #define RGB_NAME bgr24
01496
01497 #define RGB_IN(r, g, b, s)\
01498 {\
01499 b = (s)[0];\
01500 g = (s)[1];\
01501 r = (s)[2];\
01502 }
01503
01504 #define RGB_OUT(d, r, g, b)\
01505 {\
01506 (d)[0] = b;\
01507 (d)[1] = g;\
01508 (d)[2] = r;\
01509 }
01510
01511 #define BPP 3
01512
01513 #include "imgconvert_template.h"
01514
01515 #undef RGB_IN
01516 #undef RGB_OUT
01517 #undef BPP
01518
01519
01520
01521 #define RGB_NAME rgb24
01522 #define FMT_RGB24
01523
01524 #define RGB_IN(r, g, b, s)\
01525 {\
01526 r = (s)[0];\
01527 g = (s)[1];\
01528 b = (s)[2];\
01529 }
01530
01531 #define RGB_OUT(d, r, g, b)\
01532 {\
01533 (d)[0] = r;\
01534 (d)[1] = g;\
01535 (d)[2] = b;\
01536 }
01537
01538 #define BPP 3
01539
01540 #include "imgconvert_template.h"
01541
01542
01543
01544 #define RGB_NAME rgba32
01545 #define FMT_RGBA32
01546
01547 #define RGB_IN(r, g, b, s)\
01548 {\
01549 unsigned int v = ((const uint32_t *)(s))[0];\
01550 r = (v >> 16) & 0xff;\
01551 g = (v >> 8) & 0xff;\
01552 b = v & 0xff;\
01553 }
01554
01555 #define RGBA_IN(r, g, b, a, s)\
01556 {\
01557 unsigned int v = ((const uint32_t *)(s))[0];\
01558 a = (v >> 24) & 0xff;\
01559 r = (v >> 16) & 0xff;\
01560 g = (v >> 8) & 0xff;\
01561 b = v & 0xff;\
01562 }
01563
01564 #define RGBA_OUT(d, r, g, b, a)\
01565 {\
01566 ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
01567 }
01568
01569 #define BPP 4
01570
01571 #include "imgconvert_template.h"
01572
01573 static void mono_to_gray(AVPicture *dst, const AVPicture *src,
01574 int width, int height, int xor_mask)
01575 {
01576 const unsigned char *p;
01577 unsigned char *q;
01578 int v, dst_wrap, src_wrap;
01579 int y, w;
01580
01581 p = src->data[0];
01582 src_wrap = src->linesize[0] - ((width + 7) >> 3);
01583
01584 q = dst->data[0];
01585 dst_wrap = dst->linesize[0] - width;
01586 for(y=0;y<height;y++) {
01587 w = width;
01588 while (w >= 8) {
01589 v = *p++ ^ xor_mask;
01590 q[0] = -(v >> 7);
01591 q[1] = -((v >> 6) & 1);
01592 q[2] = -((v >> 5) & 1);
01593 q[3] = -((v >> 4) & 1);
01594 q[4] = -((v >> 3) & 1);
01595 q[5] = -((v >> 2) & 1);
01596 q[6] = -((v >> 1) & 1);
01597 q[7] = -((v >> 0) & 1);
01598 w -= 8;
01599 q += 8;
01600 }
01601 if (w > 0) {
01602 v = *p++ ^ xor_mask;
01603 do {
01604 q[0] = -((v >> 7) & 1);
01605 q++;
01606 v <<= 1;
01607 } while (--w);
01608 }
01609 p += src_wrap;
01610 q += dst_wrap;
01611 }
01612 }
01613
01614 static void monowhite_to_gray(AVPicture *dst, const AVPicture *src,
01615 int width, int height)
01616 {
01617 mono_to_gray(dst, src, width, height, 0xff);
01618 }
01619
01620 static void monoblack_to_gray(AVPicture *dst, const AVPicture *src,
01621 int width, int height)
01622 {
01623 mono_to_gray(dst, src, width, height, 0x00);
01624 }
01625
01626 static void gray_to_mono(AVPicture *dst, const AVPicture *src,
01627 int width, int height, int xor_mask)
01628 {
01629 int n;
01630 const uint8_t *s;
01631 uint8_t *d;
01632 int j, b, v, n1, src_wrap, dst_wrap, y;
01633
01634 s = src->data[0];
01635 src_wrap = src->linesize[0] - width;
01636
01637 d = dst->data[0];
01638 dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
01639
01640 for(y=0;y<height;y++) {
01641 n = width;
01642 while (n >= 8) {
01643 v = 0;
01644 for(j=0;j<8;j++) {
01645 b = s[0];
01646 s++;
01647 v = (v << 1) | (b >> 7);
01648 }
01649 d[0] = v ^ xor_mask;
01650 d++;
01651 n -= 8;
01652 }
01653 if (n > 0) {
01654 n1 = n;
01655 v = 0;
01656 while (n > 0) {
01657 b = s[0];
01658 s++;
01659 v = (v << 1) | (b >> 7);
01660 n--;
01661 }
01662 d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
01663 d++;
01664 }
01665 s += src_wrap;
01666 d += dst_wrap;
01667 }
01668 }
01669
01670 static void gray_to_monowhite(AVPicture *dst, const AVPicture *src,
01671 int width, int height)
01672 {
01673 gray_to_mono(dst, src, width, height, 0xff);
01674 }
01675
01676 static void gray_to_monoblack(AVPicture *dst, const AVPicture *src,
01677 int width, int height)
01678 {
01679 gray_to_mono(dst, src, width, height, 0x00);
01680 }
01681
01682 typedef struct ConvertEntry {
01683 void (*convert)(AVPicture *dst,
01684 const AVPicture *src, int width, int height);
01685 } ConvertEntry;
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704 static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
01705 [PIX_FMT_YUV420P] = {
01706 [PIX_FMT_YUV422] = {
01707 .convert = yuv420p_to_yuv422,
01708 },
01709 [PIX_FMT_RGB555] = {
01710 .convert = yuv420p_to_rgb555
01711 },
01712 [PIX_FMT_RGB565] = {
01713 .convert = yuv420p_to_rgb565
01714 },
01715 [PIX_FMT_BGR24] = {
01716 .convert = yuv420p_to_bgr24
01717 },
01718 [PIX_FMT_RGB24] = {
01719 .convert = yuv420p_to_rgb24
01720 },
01721 [PIX_FMT_RGBA32] = {
01722 .convert = yuv420p_to_rgba32
01723 },
01724 [PIX_FMT_UYVY422] = {
01725 .convert = yuv420p_to_uyvy422,
01726 },
01727 },
01728 [PIX_FMT_YUV422P] = {
01729 [PIX_FMT_YUV422] = {
01730 .convert = yuv422p_to_yuv422,
01731 },
01732 [PIX_FMT_UYVY422] = {
01733 .convert = yuv422p_to_uyvy422,
01734 },
01735 },
01736 [PIX_FMT_YUV444P] = {
01737 [PIX_FMT_RGB24] = {
01738 .convert = yuv444p_to_rgb24
01739 },
01740 },
01741 [PIX_FMT_YUVJ420P] = {
01742 [PIX_FMT_RGB555] = {
01743 .convert = yuvj420p_to_rgb555
01744 },
01745 [PIX_FMT_RGB565] = {
01746 .convert = yuvj420p_to_rgb565
01747 },
01748 [PIX_FMT_BGR24] = {
01749 .convert = yuvj420p_to_bgr24
01750 },
01751 [PIX_FMT_RGB24] = {
01752 .convert = yuvj420p_to_rgb24
01753 },
01754 [PIX_FMT_RGBA32] = {
01755 .convert = yuvj420p_to_rgba32
01756 },
01757 },
01758 [PIX_FMT_YUVJ444P] = {
01759 [PIX_FMT_RGB24] = {
01760 .convert = yuvj444p_to_rgb24
01761 },
01762 },
01763 [PIX_FMT_YUV422] = {
01764 [PIX_FMT_YUV420P] = {
01765 .convert = yuv422_to_yuv420p,
01766 },
01767 [PIX_FMT_YUV422P] = {
01768 .convert = yuv422_to_yuv422p,
01769 },
01770 },
01771 [PIX_FMT_UYVY422] = {
01772 [PIX_FMT_YUV420P] = {
01773 .convert = uyvy422_to_yuv420p,
01774 },
01775 [PIX_FMT_YUV422P] = {
01776 .convert = uyvy422_to_yuv422p,
01777 },
01778 },
01779 [PIX_FMT_RGB24] = {
01780 [PIX_FMT_YUV420P] = {
01781 .convert = rgb24_to_yuv420p
01782 },
01783 [PIX_FMT_RGB565] = {
01784 .convert = rgb24_to_rgb565
01785 },
01786 [PIX_FMT_RGB555] = {
01787 .convert = rgb24_to_rgb555
01788 },
01789 [PIX_FMT_RGBA32] = {
01790 .convert = rgb24_to_rgba32
01791 },
01792 [PIX_FMT_BGR24] = {
01793 .convert = rgb24_to_bgr24
01794 },
01795 [PIX_FMT_GRAY8] = {
01796 .convert = rgb24_to_gray
01797 },
01798 [PIX_FMT_PAL8] = {
01799 .convert = rgb24_to_pal8
01800 },
01801 [PIX_FMT_YUV444P] = {
01802 .convert = rgb24_to_yuv444p
01803 },
01804 [PIX_FMT_YUVJ420P] = {
01805 .convert = rgb24_to_yuvj420p
01806 },
01807 [PIX_FMT_YUVJ444P] = {
01808 .convert = rgb24_to_yuvj444p
01809 },
01810 },
01811 [PIX_FMT_RGBA32] = {
01812 [PIX_FMT_RGB24] = {
01813 .convert = rgba32_to_rgb24
01814 },
01815 [PIX_FMT_RGB555] = {
01816 .convert = rgba32_to_rgb555
01817 },
01818 [PIX_FMT_PAL8] = {
01819 .convert = rgba32_to_pal8
01820 },
01821 [PIX_FMT_YUV420P] = {
01822 .convert = rgba32_to_yuv420p
01823 },
01824 [PIX_FMT_GRAY8] = {
01825 .convert = rgba32_to_gray
01826 },
01827 },
01828 [PIX_FMT_BGR24] = {
01829 [PIX_FMT_RGB24] = {
01830 .convert = bgr24_to_rgb24
01831 },
01832 [PIX_FMT_YUV420P] = {
01833 .convert = bgr24_to_yuv420p
01834 },
01835 [PIX_FMT_GRAY8] = {
01836 .convert = bgr24_to_gray
01837 },
01838 },
01839 [PIX_FMT_RGB555] = {
01840 [PIX_FMT_RGB24] = {
01841 .convert = rgb555_to_rgb24
01842 },
01843 [PIX_FMT_RGBA32] = {
01844 .convert = rgb555_to_rgba32
01845 },
01846 [PIX_FMT_YUV420P] = {
01847 .convert = rgb555_to_yuv420p
01848 },
01849 [PIX_FMT_GRAY8] = {
01850 .convert = rgb555_to_gray
01851 },
01852 },
01853 [PIX_FMT_RGB565] = {
01854 [PIX_FMT_RGB24] = {
01855 .convert = rgb565_to_rgb24
01856 },
01857 [PIX_FMT_YUV420P] = {
01858 .convert = rgb565_to_yuv420p
01859 },
01860 [PIX_FMT_GRAY8] = {
01861 .convert = rgb565_to_gray
01862 },
01863 },
01864 [PIX_FMT_GRAY8] = {
01865 [PIX_FMT_RGB555] = {
01866 .convert = gray_to_rgb555
01867 },
01868 [PIX_FMT_RGB565] = {
01869 .convert = gray_to_rgb565
01870 },
01871 [PIX_FMT_RGB24] = {
01872 .convert = gray_to_rgb24
01873 },
01874 [PIX_FMT_BGR24] = {
01875 .convert = gray_to_bgr24
01876 },
01877 [PIX_FMT_RGBA32] = {
01878 .convert = gray_to_rgba32
01879 },
01880 [PIX_FMT_MONOWHITE] = {
01881 .convert = gray_to_monowhite
01882 },
01883 [PIX_FMT_MONOBLACK] = {
01884 .convert = gray_to_monoblack
01885 },
01886 },
01887 [PIX_FMT_MONOWHITE] = {
01888 [PIX_FMT_GRAY8] = {
01889 .convert = monowhite_to_gray
01890 },
01891 },
01892 [PIX_FMT_MONOBLACK] = {
01893 [PIX_FMT_GRAY8] = {
01894 .convert = monoblack_to_gray
01895 },
01896 },
01897 [PIX_FMT_PAL8] = {
01898 [PIX_FMT_RGB555] = {
01899 .convert = pal8_to_rgb555
01900 },
01901 [PIX_FMT_RGB565] = {
01902 .convert = pal8_to_rgb565
01903 },
01904 [PIX_FMT_BGR24] = {
01905 .convert = pal8_to_bgr24
01906 },
01907 [PIX_FMT_RGB24] = {
01908 .convert = pal8_to_rgb24
01909 },
01910 [PIX_FMT_RGBA32] = {
01911 .convert = pal8_to_rgba32
01912 },
01913 },
01914 [PIX_FMT_UYVY411] = {
01915 [PIX_FMT_YUV411P] = {
01916 .convert = uyvy411_to_yuv411p,
01917 },
01918 },
01919
01920 };
01921
01922 int avpicture_alloc(AVPicture *picture,
01923 int pix_fmt, int width, int height)
01924 {
01925 unsigned int size;
01926 void *ptr;
01927
01928 size = avpicture_get_size(pix_fmt, width, height);
01929 if(size<0)
01930 goto fail;
01931 ptr = av_malloc(size);
01932 if (!ptr)
01933 goto fail;
01934 avpicture_fill(picture, ptr, pix_fmt, width, height);
01935 return 0;
01936 fail:
01937 memset(picture, 0, sizeof(AVPicture));
01938 return -1;
01939 }
01940
01941 void avpicture_free(AVPicture *picture)
01942 {
01943 av_free(picture->data[0]);
01944 }
01945
01946
01947 static inline int is_yuv_planar(PixFmtInfo *ps)
01948 {
01949 return (ps->color_type == FF_COLOR_YUV ||
01950 ps->color_type == FF_COLOR_YUV_JPEG) &&
01951 ps->pixel_type == FF_PIXEL_PLANAR;
01952 }
01953
01954
01955 int img_convert(AVPicture *dst, int dst_pix_fmt,
01956 const AVPicture *src, int src_pix_fmt,
01957 int src_width, int src_height)
01958 {
01959 static int inited;
01960 int i, ret, dst_width, dst_height, int_pix_fmt;
01961 PixFmtInfo *src_pix, *dst_pix;
01962 ConvertEntry *ce;
01963 AVPicture tmp1, *tmp = &tmp1;
01964
01965 if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
01966 dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
01967 return -1;
01968 if (src_width <= 0 || src_height <= 0)
01969 return 0;
01970
01971 if (!inited) {
01972 inited = 1;
01973 img_convert_init();
01974 }
01975
01976 dst_width = src_width;
01977 dst_height = src_height;
01978
01979 dst_pix = &pix_fmt_info[dst_pix_fmt];
01980 src_pix = &pix_fmt_info[src_pix_fmt];
01981 if (src_pix_fmt == dst_pix_fmt) {
01982
01983 img_copy(dst, src, dst_pix_fmt, dst_width, dst_height);
01984 return 0;
01985 }
01986
01987 ce = &convert_table[src_pix_fmt][dst_pix_fmt];
01988 if (ce->convert) {
01989
01990 ce->convert(dst, src, dst_width, dst_height);
01991 return 0;
01992 }
01993
01994
01995 if (is_yuv_planar(dst_pix) &&
01996 src_pix_fmt == PIX_FMT_GRAY8) {
01997 int w, h, y;
01998 uint8_t *d;
01999
02000 if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
02001 img_copy_plane(dst->data[0], dst->linesize[0],
02002 src->data[0], src->linesize[0],
02003 dst_width, dst_height);
02004 } else {
02005 img_apply_table(dst->data[0], dst->linesize[0],
02006 src->data[0], src->linesize[0],
02007 dst_width, dst_height,
02008 y_jpeg_to_ccir);
02009 }
02010
02011 w = dst_width;
02012 h = dst_height;
02013 w >>= dst_pix->x_chroma_shift;
02014 h >>= dst_pix->y_chroma_shift;
02015 for(i = 1; i <= 2; i++) {
02016 d = dst->data[i];
02017 for(y = 0; y< h; y++) {
02018 memset(d, 128, w);
02019 d += dst->linesize[i];
02020 }
02021 }
02022 return 0;
02023 }
02024
02025
02026 if (is_yuv_planar(src_pix) &&
02027 dst_pix_fmt == PIX_FMT_GRAY8) {
02028 if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
02029 img_copy_plane(dst->data[0], dst->linesize[0],
02030 src->data[0], src->linesize[0],
02031 dst_width, dst_height);
02032 } else {
02033 img_apply_table(dst->data[0], dst->linesize[0],
02034 src->data[0], src->linesize[0],
02035 dst_width, dst_height,
02036 y_ccir_to_jpeg);
02037 }
02038 return 0;
02039 }
02040
02041
02042 if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) {
02043 int x_shift, y_shift, w, h, xy_shift;
02044 void (*resize_func)(uint8_t *dst, int dst_wrap,
02045 const uint8_t *src, int src_wrap,
02046 int width, int height);
02047
02048
02049 w = dst_width;
02050 h = dst_height;
02051 if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
02052 w >>= dst_pix->x_chroma_shift;
02053 else
02054 w >>= src_pix->x_chroma_shift;
02055 if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
02056 h >>= dst_pix->y_chroma_shift;
02057 else
02058 h >>= src_pix->y_chroma_shift;
02059
02060 x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
02061 y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
02062 xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf);
02063
02064
02065 switch(xy_shift) {
02066 case 0x00:
02067 resize_func = img_copy_plane;
02068 break;
02069 case 0x10:
02070 resize_func = shrink21;
02071 break;
02072 case 0x20:
02073 resize_func = shrink41;
02074 break;
02075 case 0x01:
02076 resize_func = shrink12;
02077 break;
02078 case 0x11:
02079 resize_func = shrink22;
02080 break;
02081 case 0x22:
02082 resize_func = shrink44;
02083 break;
02084 case 0xf0:
02085 resize_func = grow21;
02086 break;
02087 case 0xe0:
02088 resize_func = grow41;
02089 break;
02090 case 0xff:
02091 resize_func = grow22;
02092 break;
02093 case 0xee:
02094 resize_func = grow44;
02095 break;
02096 case 0xf1:
02097 resize_func = conv411;
02098 break;
02099 default:
02100
02101 goto no_chroma_filter;
02102 }
02103
02104 img_copy_plane(dst->data[0], dst->linesize[0],
02105 src->data[0], src->linesize[0],
02106 dst_width, dst_height);
02107
02108 for(i = 1;i <= 2; i++)
02109 resize_func(dst->data[i], dst->linesize[i],
02110 src->data[i], src->linesize[i],
02111 dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
02112
02113
02114 if (dst_pix->color_type != src_pix->color_type) {
02115 const uint8_t *y_table, *c_table;
02116 if (dst_pix->color_type == FF_COLOR_YUV) {
02117 y_table = y_jpeg_to_ccir;
02118 c_table = c_jpeg_to_ccir;
02119 } else {
02120 y_table = y_ccir_to_jpeg;
02121 c_table = c_ccir_to_jpeg;
02122 }
02123 img_apply_table(dst->data[0], dst->linesize[0],
02124 dst->data[0], dst->linesize[0],
02125 dst_width, dst_height,
02126 y_table);
02127
02128 for(i = 1;i <= 2; i++)
02129 img_apply_table(dst->data[i], dst->linesize[i],
02130 dst->data[i], dst->linesize[i],
02131 dst_width>>dst_pix->x_chroma_shift,
02132 dst_height>>dst_pix->y_chroma_shift,
02133 c_table);
02134 }
02135 return 0;
02136 }
02137 no_chroma_filter:
02138
02139
02140 if (src_pix_fmt == PIX_FMT_YUV422 ||
02141 dst_pix_fmt == PIX_FMT_YUV422) {
02142
02143 int_pix_fmt = PIX_FMT_YUV422P;
02144 } else if (src_pix_fmt == PIX_FMT_UYVY422 ||
02145 dst_pix_fmt == PIX_FMT_UYVY422) {
02146
02147 int_pix_fmt = PIX_FMT_YUV422P;
02148 } else if (src_pix_fmt == PIX_FMT_UYVY411 ||
02149 dst_pix_fmt == PIX_FMT_UYVY411) {
02150
02151 int_pix_fmt = PIX_FMT_YUV411P;
02152 } else if ((src_pix->color_type == FF_COLOR_GRAY &&
02153 src_pix_fmt != PIX_FMT_GRAY8) ||
02154 (dst_pix->color_type == FF_COLOR_GRAY &&
02155 dst_pix_fmt != PIX_FMT_GRAY8)) {
02156
02157 int_pix_fmt = PIX_FMT_GRAY8;
02158 } else if ((is_yuv_planar(src_pix) &&
02159 src_pix_fmt != PIX_FMT_YUV444P &&
02160 src_pix_fmt != PIX_FMT_YUVJ444P)) {
02161
02162 if (src_pix->color_type == FF_COLOR_YUV_JPEG)
02163 int_pix_fmt = PIX_FMT_YUVJ444P;
02164 else
02165 int_pix_fmt = PIX_FMT_YUV444P;
02166 } else if ((is_yuv_planar(dst_pix) &&
02167 dst_pix_fmt != PIX_FMT_YUV444P &&
02168 dst_pix_fmt != PIX_FMT_YUVJ444P)) {
02169
02170 if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
02171 int_pix_fmt = PIX_FMT_YUVJ444P;
02172 else
02173 int_pix_fmt = PIX_FMT_YUV444P;
02174 } else {
02175
02176 if (src_pix->is_alpha && dst_pix->is_alpha)
02177 int_pix_fmt = PIX_FMT_RGBA32;
02178 else
02179 int_pix_fmt = PIX_FMT_RGB24;
02180 }
02181 if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
02182 return -1;
02183 ret = -1;
02184 if (img_convert(tmp, int_pix_fmt,
02185 src, src_pix_fmt, src_width, src_height) < 0)
02186 goto fail1;
02187 if (img_convert(dst, dst_pix_fmt,
02188 tmp, int_pix_fmt, dst_width, dst_height) < 0)
02189 goto fail1;
02190 ret = 0;
02191 fail1:
02192 avpicture_free(tmp);
02193 return ret;
02194 }
02195
02196
02197 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
02198 {
02199 const unsigned char *p;
02200 int src_wrap, ret, x, y;
02201 unsigned int a;
02202 uint32_t *palette = (uint32_t *)src->data[1];
02203
02204 p = src->data[0];
02205 src_wrap = src->linesize[0] - width;
02206 ret = 0;
02207 for(y=0;y<height;y++) {
02208 for(x=0;x<width;x++) {
02209 a = palette[p[0]] >> 24;
02210 if (a == 0x00) {
02211 ret |= FF_ALPHA_TRANSP;
02212 } else if (a != 0xff) {
02213 ret |= FF_ALPHA_SEMI_TRANSP;
02214 }
02215 p++;
02216 }
02217 p += src_wrap;
02218 }
02219 return ret;
02220 }
02221
02226 int img_get_alpha_info(const AVPicture *src,
02227 int pix_fmt, int width, int height)
02228 {
02229 PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
02230 int ret;
02231
02232 pf = &pix_fmt_info[pix_fmt];
02233
02234 if (!pf->is_alpha)
02235 return 0;
02236 switch(pix_fmt) {
02237 case PIX_FMT_RGBA32:
02238 ret = get_alpha_info_rgba32(src, width, height);
02239 break;
02240 case PIX_FMT_RGB555:
02241 ret = get_alpha_info_rgb555(src, width, height);
02242 break;
02243 case PIX_FMT_PAL8:
02244 ret = get_alpha_info_pal8(src, width, height);
02245 break;
02246 default:
02247
02248 ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
02249 break;
02250 }
02251 return ret;
02252 }
02253
02254 #ifdef HAVE_MMX
02255 #define DEINT_INPLACE_LINE_LUM \
02256 movd_m2r(lum_m4[0],mm0);\
02257 movd_m2r(lum_m3[0],mm1);\
02258 movd_m2r(lum_m2[0],mm2);\
02259 movd_m2r(lum_m1[0],mm3);\
02260 movd_m2r(lum[0],mm4);\
02261 punpcklbw_r2r(mm7,mm0);\
02262 movd_r2m(mm2,lum_m4[0]);\
02263 punpcklbw_r2r(mm7,mm1);\
02264 punpcklbw_r2r(mm7,mm2);\
02265 punpcklbw_r2r(mm7,mm3);\
02266 punpcklbw_r2r(mm7,mm4);\
02267 paddw_r2r(mm3,mm1);\
02268 psllw_i2r(1,mm2);\
02269 paddw_r2r(mm4,mm0);\
02270 psllw_i2r(2,mm1);\
02271 paddw_r2r(mm6,mm2);\
02272 paddw_r2r(mm2,mm1);\
02273 psubusw_r2r(mm0,mm1);\
02274 psrlw_i2r(3,mm1);\
02275 packuswb_r2r(mm7,mm1);\
02276 movd_r2m(mm1,lum_m2[0]);
02277
02278 #define DEINT_LINE_LUM \
02279 movd_m2r(lum_m4[0],mm0);\
02280 movd_m2r(lum_m3[0],mm1);\
02281 movd_m2r(lum_m2[0],mm2);\
02282 movd_m2r(lum_m1[0],mm3);\
02283 movd_m2r(lum[0],mm4);\
02284 punpcklbw_r2r(mm7,mm0);\
02285 punpcklbw_r2r(mm7,mm1);\
02286 punpcklbw_r2r(mm7,mm2);\
02287 punpcklbw_r2r(mm7,mm3);\
02288 punpcklbw_r2r(mm7,mm4);\
02289 paddw_r2r(mm3,mm1);\
02290 psllw_i2r(1,mm2);\
02291 paddw_r2r(mm4,mm0);\
02292 psllw_i2r(2,mm1);\
02293 paddw_r2r(mm6,mm2);\
02294 paddw_r2r(mm2,mm1);\
02295 psubusw_r2r(mm0,mm1);\
02296 psrlw_i2r(3,mm1);\
02297 packuswb_r2r(mm7,mm1);\
02298 movd_r2m(mm1,dst[0]);
02299 #endif
02300
02301
02302 static void deinterlace_line(uint8_t *dst,
02303 const uint8_t *lum_m4, const uint8_t *lum_m3,
02304 const uint8_t *lum_m2, const uint8_t *lum_m1,
02305 const uint8_t *lum,
02306 int size)
02307 {
02308 #ifndef HAVE_MMX
02309 uint8_t *cm = cropTbl + MAX_NEG_CROP;
02310 int sum;
02311
02312 for(;size > 0;size--) {
02313 sum = -lum_m4[0];
02314 sum += lum_m3[0] << 2;
02315 sum += lum_m2[0] << 1;
02316 sum += lum_m1[0] << 2;
02317 sum += -lum[0];
02318 dst[0] = cm[(sum + 4) >> 3];
02319 lum_m4++;
02320 lum_m3++;
02321 lum_m2++;
02322 lum_m1++;
02323 lum++;
02324 dst++;
02325 }
02326 #else
02327
02328 {
02329 mmx_t rounder;
02330 rounder.uw[0]=4;
02331 rounder.uw[1]=4;
02332 rounder.uw[2]=4;
02333 rounder.uw[3]=4;
02334 pxor_r2r(mm7,mm7);
02335 movq_m2r(rounder,mm6);
02336 }
02337 for (;size > 3; size-=4) {
02338 DEINT_LINE_LUM
02339 lum_m4+=4;
02340 lum_m3+=4;
02341 lum_m2+=4;
02342 lum_m1+=4;
02343 lum+=4;
02344 dst+=4;
02345 }
02346 #endif
02347 }
02348 static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
02349 int size)
02350 {
02351 #ifndef HAVE_MMX
02352 uint8_t *cm = cropTbl + MAX_NEG_CROP;
02353 int sum;
02354
02355 for(;size > 0;size--) {
02356 sum = -lum_m4[0];
02357 sum += lum_m3[0] << 2;
02358 sum += lum_m2[0] << 1;
02359 lum_m4[0]=lum_m2[0];
02360 sum += lum_m1[0] << 2;
02361 sum += -lum[0];
02362 lum_m2[0] = cm[(sum + 4) >> 3];
02363 lum_m4++;
02364 lum_m3++;
02365 lum_m2++;
02366 lum_m1++;
02367 lum++;
02368 }
02369 #else
02370
02371 {
02372 mmx_t rounder;
02373 rounder.uw[0]=4;
02374 rounder.uw[1]=4;
02375 rounder.uw[2]=4;
02376 rounder.uw[3]=4;
02377 pxor_r2r(mm7,mm7);
02378 movq_m2r(rounder,mm6);
02379 }
02380 for (;size > 3; size-=4) {
02381 DEINT_INPLACE_LINE_LUM
02382 lum_m4+=4;
02383 lum_m3+=4;
02384 lum_m2+=4;
02385 lum_m1+=4;
02386 lum+=4;
02387 }
02388 #endif
02389 }
02390
02391
02392
02393
02394 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
02395 const uint8_t *src1, int src_wrap,
02396 int width, int height)
02397 {
02398 const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
02399 int y;
02400
02401 src_m2 = src1;
02402 src_m1 = src1;
02403 src_0=&src_m1[src_wrap];
02404 src_p1=&src_0[src_wrap];
02405 src_p2=&src_p1[src_wrap];
02406 for(y=0;y<(height-2);y+=2) {
02407 memcpy(dst,src_m1,width);
02408 dst += dst_wrap;
02409 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
02410 src_m2 = src_0;
02411 src_m1 = src_p1;
02412 src_0 = src_p2;
02413 src_p1 += 2*src_wrap;
02414 src_p2 += 2*src_wrap;
02415 dst += dst_wrap;
02416 }
02417 memcpy(dst,src_m1,width);
02418 dst += dst_wrap;
02419
02420 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
02421 }
02422
02423 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
02424 int width, int height)
02425 {
02426 uint8_t *src_m1, *src_0, *src_p1, *src_p2;
02427 int y;
02428 uint8_t *buf;
02429 buf = (uint8_t*)av_malloc(width);
02430
02431 src_m1 = src1;
02432 memcpy(buf,src_m1,width);
02433 src_0=&src_m1[src_wrap];
02434 src_p1=&src_0[src_wrap];
02435 src_p2=&src_p1[src_wrap];
02436 for(y=0;y<(height-2);y+=2) {
02437 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
02438 src_m1 = src_p1;
02439 src_0 = src_p2;
02440 src_p1 += 2*src_wrap;
02441 src_p2 += 2*src_wrap;
02442 }
02443
02444 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
02445 av_free(buf);
02446 }
02447
02448
02449
02450 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
02451 int pix_fmt, int width, int height)
02452 {
02453 int i;
02454
02455 if (pix_fmt != PIX_FMT_YUV420P &&
02456 pix_fmt != PIX_FMT_YUV422P &&
02457 pix_fmt != PIX_FMT_YUV444P &&
02458 pix_fmt != PIX_FMT_YUV411P)
02459 return -1;
02460 if ((width & 3) != 0 || (height & 3) != 0)
02461 return -1;
02462
02463 for(i=0;i<3;i++) {
02464 if (i == 1) {
02465 switch(pix_fmt) {
02466 case PIX_FMT_YUV420P:
02467 width >>= 1;
02468 height >>= 1;
02469 break;
02470 case PIX_FMT_YUV422P:
02471 width >>= 1;
02472 break;
02473 case PIX_FMT_YUV411P:
02474 width >>= 2;
02475 break;
02476 default:
02477 break;
02478 }
02479 }
02480 if (src == dst) {
02481 deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
02482 width, height);
02483 } else {
02484 deinterlace_bottom_field(dst->data[i],dst->linesize[i],
02485 src->data[i], src->linesize[i],
02486 width, height);
02487 }
02488 }
02489 #ifdef HAVE_MMX
02490 emms();
02491 #endif
02492 return 0;
02493 }
02494
02495 #undef FIX