00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027
00028
00029
00030
00031
00032
00033 #include "avcodec.h"
00034 #include "dsputil.h"
00035 #include "internal.h"
00036 #include "imgconvert.h"
00037 #include "libavutil/colorspace.h"
00038 #include "libavutil/pixdesc.h"
00039 #include "libavutil/imgutils.h"
00040
00041 #if HAVE_MMX && HAVE_YASM
00042 #include "x86/dsputil_mmx.h"
00043 #endif
00044
00045 #define xglue(x, y) x ## y
00046 #define glue(x, y) xglue(x, y)
00047
00048 #define FF_COLOR_RGB 0
00049 #define FF_COLOR_GRAY 1
00050 #define FF_COLOR_YUV 2
00051 #define FF_COLOR_YUV_JPEG 3
00053 #define FF_PIXEL_PLANAR 0
00054 #define FF_PIXEL_PACKED 1
00055 #define FF_PIXEL_PALETTE 2
00057 #if HAVE_MMX && HAVE_YASM
00058 #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
00059 #define deinterlace_line ff_deinterlace_line_mmx
00060 #else
00061 #define deinterlace_line_inplace deinterlace_line_inplace_c
00062 #define deinterlace_line deinterlace_line_c
00063 #endif
00064
00065 typedef struct PixFmtInfo {
00066 uint8_t nb_channels;
00067 uint8_t color_type;
00068 uint8_t pixel_type;
00069 uint8_t is_alpha : 1;
00070 uint8_t depth;
00071 } PixFmtInfo;
00072
00073
00074 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
00075
00076 [PIX_FMT_YUV420P] = {
00077 .nb_channels = 3,
00078 .color_type = FF_COLOR_YUV,
00079 .pixel_type = FF_PIXEL_PLANAR,
00080 .depth = 8,
00081 },
00082 [PIX_FMT_YUV422P] = {
00083 .nb_channels = 3,
00084 .color_type = FF_COLOR_YUV,
00085 .pixel_type = FF_PIXEL_PLANAR,
00086 .depth = 8,
00087 },
00088 [PIX_FMT_YUV444P] = {
00089 .nb_channels = 3,
00090 .color_type = FF_COLOR_YUV,
00091 .pixel_type = FF_PIXEL_PLANAR,
00092 .depth = 8,
00093 },
00094 [PIX_FMT_YUYV422] = {
00095 .nb_channels = 1,
00096 .color_type = FF_COLOR_YUV,
00097 .pixel_type = FF_PIXEL_PACKED,
00098 .depth = 8,
00099 },
00100 [PIX_FMT_UYVY422] = {
00101 .nb_channels = 1,
00102 .color_type = FF_COLOR_YUV,
00103 .pixel_type = FF_PIXEL_PACKED,
00104 .depth = 8,
00105 },
00106 [PIX_FMT_YUV410P] = {
00107 .nb_channels = 3,
00108 .color_type = FF_COLOR_YUV,
00109 .pixel_type = FF_PIXEL_PLANAR,
00110 .depth = 8,
00111 },
00112 [PIX_FMT_YUV411P] = {
00113 .nb_channels = 3,
00114 .color_type = FF_COLOR_YUV,
00115 .pixel_type = FF_PIXEL_PLANAR,
00116 .depth = 8,
00117 },
00118 [PIX_FMT_YUV440P] = {
00119 .nb_channels = 3,
00120 .color_type = FF_COLOR_YUV,
00121 .pixel_type = FF_PIXEL_PLANAR,
00122 .depth = 8,
00123 },
00124 [PIX_FMT_YUV420P16LE] = {
00125 .nb_channels = 3,
00126 .color_type = FF_COLOR_YUV,
00127 .pixel_type = FF_PIXEL_PLANAR,
00128 .depth = 16,
00129 },
00130 [PIX_FMT_YUV422P16LE] = {
00131 .nb_channels = 3,
00132 .color_type = FF_COLOR_YUV,
00133 .pixel_type = FF_PIXEL_PLANAR,
00134 .depth = 16,
00135 },
00136 [PIX_FMT_YUV444P16LE] = {
00137 .nb_channels = 3,
00138 .color_type = FF_COLOR_YUV,
00139 .pixel_type = FF_PIXEL_PLANAR,
00140 .depth = 16,
00141 },
00142 [PIX_FMT_YUV420P16BE] = {
00143 .nb_channels = 3,
00144 .color_type = FF_COLOR_YUV,
00145 .pixel_type = FF_PIXEL_PLANAR,
00146 .depth = 16,
00147 },
00148 [PIX_FMT_YUV422P16BE] = {
00149 .nb_channels = 3,
00150 .color_type = FF_COLOR_YUV,
00151 .pixel_type = FF_PIXEL_PLANAR,
00152 .depth = 16,
00153 },
00154 [PIX_FMT_YUV444P16BE] = {
00155 .nb_channels = 3,
00156 .color_type = FF_COLOR_YUV,
00157 .pixel_type = FF_PIXEL_PLANAR,
00158 .depth = 16,
00159 },
00160
00161
00162
00163 [PIX_FMT_YUVA420P] = {
00164 .nb_channels = 4,
00165 .color_type = FF_COLOR_YUV,
00166 .pixel_type = FF_PIXEL_PLANAR,
00167 .depth = 8,
00168 },
00169
00170
00171 [PIX_FMT_YUVJ420P] = {
00172 .nb_channels = 3,
00173 .color_type = FF_COLOR_YUV_JPEG,
00174 .pixel_type = FF_PIXEL_PLANAR,
00175 .depth = 8,
00176 },
00177 [PIX_FMT_YUVJ422P] = {
00178 .nb_channels = 3,
00179 .color_type = FF_COLOR_YUV_JPEG,
00180 .pixel_type = FF_PIXEL_PLANAR,
00181 .depth = 8,
00182 },
00183 [PIX_FMT_YUVJ444P] = {
00184 .nb_channels = 3,
00185 .color_type = FF_COLOR_YUV_JPEG,
00186 .pixel_type = FF_PIXEL_PLANAR,
00187 .depth = 8,
00188 },
00189 [PIX_FMT_YUVJ440P] = {
00190 .nb_channels = 3,
00191 .color_type = FF_COLOR_YUV_JPEG,
00192 .pixel_type = FF_PIXEL_PLANAR,
00193 .depth = 8,
00194 },
00195
00196
00197 [PIX_FMT_RGB24] = {
00198 .nb_channels = 3,
00199 .color_type = FF_COLOR_RGB,
00200 .pixel_type = FF_PIXEL_PACKED,
00201 .depth = 8,
00202 },
00203 [PIX_FMT_BGR24] = {
00204 .nb_channels = 3,
00205 .color_type = FF_COLOR_RGB,
00206 .pixel_type = FF_PIXEL_PACKED,
00207 .depth = 8,
00208 },
00209 [PIX_FMT_ARGB] = {
00210 .nb_channels = 4, .is_alpha = 1,
00211 .color_type = FF_COLOR_RGB,
00212 .pixel_type = FF_PIXEL_PACKED,
00213 .depth = 8,
00214 },
00215 [PIX_FMT_RGB48BE] = {
00216 .nb_channels = 3,
00217 .color_type = FF_COLOR_RGB,
00218 .pixel_type = FF_PIXEL_PACKED,
00219 .depth = 16,
00220 },
00221 [PIX_FMT_RGB48LE] = {
00222 .nb_channels = 3,
00223 .color_type = FF_COLOR_RGB,
00224 .pixel_type = FF_PIXEL_PACKED,
00225 .depth = 16,
00226 },
00227 [PIX_FMT_RGB565BE] = {
00228 .nb_channels = 3,
00229 .color_type = FF_COLOR_RGB,
00230 .pixel_type = FF_PIXEL_PACKED,
00231 .depth = 5,
00232 },
00233 [PIX_FMT_RGB565LE] = {
00234 .nb_channels = 3,
00235 .color_type = FF_COLOR_RGB,
00236 .pixel_type = FF_PIXEL_PACKED,
00237 .depth = 5,
00238 },
00239 [PIX_FMT_RGB555BE] = {
00240 .nb_channels = 3,
00241 .color_type = FF_COLOR_RGB,
00242 .pixel_type = FF_PIXEL_PACKED,
00243 .depth = 5,
00244 },
00245 [PIX_FMT_RGB555LE] = {
00246 .nb_channels = 3,
00247 .color_type = FF_COLOR_RGB,
00248 .pixel_type = FF_PIXEL_PACKED,
00249 .depth = 5,
00250 },
00251 [PIX_FMT_RGB444BE] = {
00252 .nb_channels = 3,
00253 .color_type = FF_COLOR_RGB,
00254 .pixel_type = FF_PIXEL_PACKED,
00255 .depth = 4,
00256 },
00257 [PIX_FMT_RGB444LE] = {
00258 .nb_channels = 3,
00259 .color_type = FF_COLOR_RGB,
00260 .pixel_type = FF_PIXEL_PACKED,
00261 .depth = 4,
00262 },
00263
00264
00265 [PIX_FMT_GRAY16BE] = {
00266 .nb_channels = 1,
00267 .color_type = FF_COLOR_GRAY,
00268 .pixel_type = FF_PIXEL_PLANAR,
00269 .depth = 16,
00270 },
00271 [PIX_FMT_GRAY16LE] = {
00272 .nb_channels = 1,
00273 .color_type = FF_COLOR_GRAY,
00274 .pixel_type = FF_PIXEL_PLANAR,
00275 .depth = 16,
00276 },
00277 [PIX_FMT_GRAY8] = {
00278 .nb_channels = 1,
00279 .color_type = FF_COLOR_GRAY,
00280 .pixel_type = FF_PIXEL_PLANAR,
00281 .depth = 8,
00282 },
00283 [PIX_FMT_MONOWHITE] = {
00284 .nb_channels = 1,
00285 .color_type = FF_COLOR_GRAY,
00286 .pixel_type = FF_PIXEL_PLANAR,
00287 .depth = 1,
00288 },
00289 [PIX_FMT_MONOBLACK] = {
00290 .nb_channels = 1,
00291 .color_type = FF_COLOR_GRAY,
00292 .pixel_type = FF_PIXEL_PLANAR,
00293 .depth = 1,
00294 },
00295
00296
00297 [PIX_FMT_PAL8] = {
00298 .nb_channels = 4, .is_alpha = 1,
00299 .color_type = FF_COLOR_RGB,
00300 .pixel_type = FF_PIXEL_PALETTE,
00301 .depth = 8,
00302 },
00303 [PIX_FMT_UYYVYY411] = {
00304 .nb_channels = 1,
00305 .color_type = FF_COLOR_YUV,
00306 .pixel_type = FF_PIXEL_PACKED,
00307 .depth = 8,
00308 },
00309 [PIX_FMT_ABGR] = {
00310 .nb_channels = 4, .is_alpha = 1,
00311 .color_type = FF_COLOR_RGB,
00312 .pixel_type = FF_PIXEL_PACKED,
00313 .depth = 8,
00314 },
00315 [PIX_FMT_BGR565BE] = {
00316 .nb_channels = 3,
00317 .color_type = FF_COLOR_RGB,
00318 .pixel_type = FF_PIXEL_PACKED,
00319 .depth = 5,
00320 },
00321 [PIX_FMT_BGR565LE] = {
00322 .nb_channels = 3,
00323 .color_type = FF_COLOR_RGB,
00324 .pixel_type = FF_PIXEL_PACKED,
00325 .depth = 5,
00326 },
00327 [PIX_FMT_BGR555BE] = {
00328 .nb_channels = 3,
00329 .color_type = FF_COLOR_RGB,
00330 .pixel_type = FF_PIXEL_PACKED,
00331 .depth = 5,
00332 },
00333 [PIX_FMT_BGR555LE] = {
00334 .nb_channels = 3,
00335 .color_type = FF_COLOR_RGB,
00336 .pixel_type = FF_PIXEL_PACKED,
00337 .depth = 5,
00338 },
00339 [PIX_FMT_BGR444BE] = {
00340 .nb_channels = 3,
00341 .color_type = FF_COLOR_RGB,
00342 .pixel_type = FF_PIXEL_PACKED,
00343 .depth = 4,
00344 },
00345 [PIX_FMT_BGR444LE] = {
00346 .nb_channels = 3,
00347 .color_type = FF_COLOR_RGB,
00348 .pixel_type = FF_PIXEL_PACKED,
00349 .depth = 4,
00350 },
00351 [PIX_FMT_RGB8] = {
00352 .nb_channels = 1,
00353 .color_type = FF_COLOR_RGB,
00354 .pixel_type = FF_PIXEL_PACKED,
00355 .depth = 8,
00356 },
00357 [PIX_FMT_RGB4] = {
00358 .nb_channels = 1,
00359 .color_type = FF_COLOR_RGB,
00360 .pixel_type = FF_PIXEL_PACKED,
00361 .depth = 4,
00362 },
00363 [PIX_FMT_RGB4_BYTE] = {
00364 .nb_channels = 1,
00365 .color_type = FF_COLOR_RGB,
00366 .pixel_type = FF_PIXEL_PACKED,
00367 .depth = 8,
00368 },
00369 [PIX_FMT_BGR8] = {
00370 .nb_channels = 1,
00371 .color_type = FF_COLOR_RGB,
00372 .pixel_type = FF_PIXEL_PACKED,
00373 .depth = 8,
00374 },
00375 [PIX_FMT_BGR4] = {
00376 .nb_channels = 1,
00377 .color_type = FF_COLOR_RGB,
00378 .pixel_type = FF_PIXEL_PACKED,
00379 .depth = 4,
00380 },
00381 [PIX_FMT_BGR4_BYTE] = {
00382 .nb_channels = 1,
00383 .color_type = FF_COLOR_RGB,
00384 .pixel_type = FF_PIXEL_PACKED,
00385 .depth = 8,
00386 },
00387 [PIX_FMT_NV12] = {
00388 .nb_channels = 2,
00389 .color_type = FF_COLOR_YUV,
00390 .pixel_type = FF_PIXEL_PLANAR,
00391 .depth = 8,
00392 },
00393 [PIX_FMT_NV21] = {
00394 .nb_channels = 2,
00395 .color_type = FF_COLOR_YUV,
00396 .pixel_type = FF_PIXEL_PLANAR,
00397 .depth = 8,
00398 },
00399
00400 [PIX_FMT_BGRA] = {
00401 .nb_channels = 4, .is_alpha = 1,
00402 .color_type = FF_COLOR_RGB,
00403 .pixel_type = FF_PIXEL_PACKED,
00404 .depth = 8,
00405 },
00406 [PIX_FMT_RGBA] = {
00407 .nb_channels = 4, .is_alpha = 1,
00408 .color_type = FF_COLOR_RGB,
00409 .pixel_type = FF_PIXEL_PACKED,
00410 .depth = 8,
00411 },
00412 };
00413
00414 void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift)
00415 {
00416 *h_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00417 *v_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00418 }
00419
00420 #if FF_API_GET_PIX_FMT_NAME
00421 const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt)
00422 {
00423 return av_get_pix_fmt_name(pix_fmt);
00424 }
00425 #endif
00426
00427 int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
00428 {
00429 return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
00430 }
00431
00432 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00433 enum PixelFormat pix_fmt, int width, int height)
00434 {
00435 int ret;
00436
00437 if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
00438 return ret;
00439
00440 if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0)
00441 return ret;
00442
00443 return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
00444 }
00445
00446 int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
00447 unsigned char *dest, int dest_size)
00448 {
00449 int i, j, nb_planes = 0, linesizes[4];
00450 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00451 int size = avpicture_get_size(pix_fmt, width, height);
00452
00453 if (size > dest_size || size < 0)
00454 return AVERROR(EINVAL);
00455
00456 for (i = 0; i < desc->nb_components; i++)
00457 nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
00458 nb_planes++;
00459
00460 av_image_fill_linesizes(linesizes, pix_fmt, width);
00461 for (i = 0; i < nb_planes; i++) {
00462 int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
00463 const unsigned char *s = src->data[i];
00464 h = (height + (1 << shift) - 1) >> shift;
00465
00466 for (j = 0; j < h; j++) {
00467 memcpy(dest, s, linesizes[i]);
00468 dest += linesizes[i];
00469 s += src->linesize[i];
00470 }
00471 }
00472
00473 switch (pix_fmt) {
00474 case PIX_FMT_RGB8:
00475 case PIX_FMT_BGR8:
00476 case PIX_FMT_RGB4_BYTE:
00477 case PIX_FMT_BGR4_BYTE:
00478 case PIX_FMT_GRAY8:
00479
00480 return size;
00481 }
00482
00483 if (desc->flags & PIX_FMT_PAL)
00484 memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00485
00486 return size;
00487 }
00488
00489 int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height)
00490 {
00491 AVPicture dummy_pict;
00492 if(av_image_check_size(width, height, 0, NULL))
00493 return -1;
00494 switch (pix_fmt) {
00495 case PIX_FMT_RGB8:
00496 case PIX_FMT_BGR8:
00497 case PIX_FMT_RGB4_BYTE:
00498 case PIX_FMT_BGR4_BYTE:
00499 case PIX_FMT_GRAY8:
00500
00501 return width * height;
00502 }
00503 return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00504 }
00505
00506 int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
00507 int has_alpha)
00508 {
00509 const PixFmtInfo *pf, *ps;
00510 const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
00511 const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
00512 int loss;
00513
00514 ps = &pix_fmt_info[src_pix_fmt];
00515
00516
00517 loss = 0;
00518 pf = &pix_fmt_info[dst_pix_fmt];
00519 if (pf->depth < ps->depth ||
00520 ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE ||
00521 dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) &&
00522 (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE ||
00523 src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE)))
00524 loss |= FF_LOSS_DEPTH;
00525 if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
00526 dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
00527 loss |= FF_LOSS_RESOLUTION;
00528 switch(pf->color_type) {
00529 case FF_COLOR_RGB:
00530 if (ps->color_type != FF_COLOR_RGB &&
00531 ps->color_type != FF_COLOR_GRAY)
00532 loss |= FF_LOSS_COLORSPACE;
00533 break;
00534 case FF_COLOR_GRAY:
00535 if (ps->color_type != FF_COLOR_GRAY)
00536 loss |= FF_LOSS_COLORSPACE;
00537 break;
00538 case FF_COLOR_YUV:
00539 if (ps->color_type != FF_COLOR_YUV)
00540 loss |= FF_LOSS_COLORSPACE;
00541 break;
00542 case FF_COLOR_YUV_JPEG:
00543 if (ps->color_type != FF_COLOR_YUV_JPEG &&
00544 ps->color_type != FF_COLOR_YUV &&
00545 ps->color_type != FF_COLOR_GRAY)
00546 loss |= FF_LOSS_COLORSPACE;
00547 break;
00548 default:
00549
00550 if (ps->color_type != pf->color_type)
00551 loss |= FF_LOSS_COLORSPACE;
00552 break;
00553 }
00554 if (pf->color_type == FF_COLOR_GRAY &&
00555 ps->color_type != FF_COLOR_GRAY)
00556 loss |= FF_LOSS_CHROMA;
00557 if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00558 loss |= FF_LOSS_ALPHA;
00559 if (pf->pixel_type == FF_PIXEL_PALETTE &&
00560 (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00561 loss |= FF_LOSS_COLORQUANT;
00562 return loss;
00563 }
00564
00565 static int avg_bits_per_pixel(enum PixelFormat pix_fmt)
00566 {
00567 int bits;
00568 const PixFmtInfo *pf;
00569 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00570
00571 pf = &pix_fmt_info[pix_fmt];
00572 switch(pf->pixel_type) {
00573 case FF_PIXEL_PACKED:
00574 switch(pix_fmt) {
00575 case PIX_FMT_YUYV422:
00576 case PIX_FMT_UYVY422:
00577 case PIX_FMT_RGB565BE:
00578 case PIX_FMT_RGB565LE:
00579 case PIX_FMT_RGB555BE:
00580 case PIX_FMT_RGB555LE:
00581 case PIX_FMT_RGB444BE:
00582 case PIX_FMT_RGB444LE:
00583 case PIX_FMT_BGR565BE:
00584 case PIX_FMT_BGR565LE:
00585 case PIX_FMT_BGR555BE:
00586 case PIX_FMT_BGR555LE:
00587 case PIX_FMT_BGR444BE:
00588 case PIX_FMT_BGR444LE:
00589 bits = 16;
00590 break;
00591 case PIX_FMT_UYYVYY411:
00592 bits = 12;
00593 break;
00594 default:
00595 bits = pf->depth * pf->nb_channels;
00596 break;
00597 }
00598 break;
00599 case FF_PIXEL_PLANAR:
00600 if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
00601 bits = pf->depth * pf->nb_channels;
00602 } else {
00603 bits = pf->depth + ((2 * pf->depth) >>
00604 (desc->log2_chroma_w + desc->log2_chroma_h));
00605 }
00606 break;
00607 case FF_PIXEL_PALETTE:
00608 bits = 8;
00609 break;
00610 default:
00611 bits = -1;
00612 break;
00613 }
00614 return bits;
00615 }
00616
00617 static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
00618 enum PixelFormat src_pix_fmt,
00619 int has_alpha,
00620 int loss_mask)
00621 {
00622 int dist, i, loss, min_dist;
00623 enum PixelFormat dst_pix_fmt;
00624
00625
00626 dst_pix_fmt = PIX_FMT_NONE;
00627 min_dist = 0x7fffffff;
00628
00629 for (i = 0; i < 64; i++) {
00630 if (pix_fmt_mask & (1ULL << i)) {
00631 loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00632 if (loss == 0) {
00633 dist = avg_bits_per_pixel(i);
00634 if (dist < min_dist) {
00635 min_dist = dist;
00636 dst_pix_fmt = i;
00637 }
00638 }
00639 }
00640 }
00641 return dst_pix_fmt;
00642 }
00643
00644 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
00645 int has_alpha, int *loss_ptr)
00646 {
00647 enum PixelFormat dst_pix_fmt;
00648 int loss_mask, i;
00649 static const int loss_mask_order[] = {
00650 ~0,
00651 ~FF_LOSS_ALPHA,
00652 ~FF_LOSS_RESOLUTION,
00653 ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00654 ~FF_LOSS_COLORQUANT,
00655 ~FF_LOSS_DEPTH,
00656 0,
00657 };
00658
00659
00660 i = 0;
00661 for(;;) {
00662 loss_mask = loss_mask_order[i++];
00663 dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00664 has_alpha, loss_mask);
00665 if (dst_pix_fmt >= 0)
00666 goto found;
00667 if (loss_mask == 0)
00668 break;
00669 }
00670 return PIX_FMT_NONE;
00671 found:
00672 if (loss_ptr)
00673 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00674 return dst_pix_fmt;
00675 }
00676
00677 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00678 enum PixelFormat pix_fmt, int width, int height)
00679 {
00680 av_image_copy(dst->data, dst->linesize, src->data,
00681 src->linesize, pix_fmt, width, height);
00682 }
00683
00684
00685 void ff_shrink22(uint8_t *dst, int dst_wrap,
00686 const uint8_t *src, int src_wrap,
00687 int width, int height)
00688 {
00689 int w;
00690 const uint8_t *s1, *s2;
00691 uint8_t *d;
00692
00693 for(;height > 0; height--) {
00694 s1 = src;
00695 s2 = s1 + src_wrap;
00696 d = dst;
00697 for(w = width;w >= 4; w-=4) {
00698 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00699 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
00700 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
00701 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
00702 s1 += 8;
00703 s2 += 8;
00704 d += 4;
00705 }
00706 for(;w > 0; w--) {
00707 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00708 s1 += 2;
00709 s2 += 2;
00710 d++;
00711 }
00712 src += 2 * src_wrap;
00713 dst += dst_wrap;
00714 }
00715 }
00716
00717
00718 void ff_shrink44(uint8_t *dst, int dst_wrap,
00719 const uint8_t *src, int src_wrap,
00720 int width, int height)
00721 {
00722 int w;
00723 const uint8_t *s1, *s2, *s3, *s4;
00724 uint8_t *d;
00725
00726 for(;height > 0; height--) {
00727 s1 = src;
00728 s2 = s1 + src_wrap;
00729 s3 = s2 + src_wrap;
00730 s4 = s3 + src_wrap;
00731 d = dst;
00732 for(w = width;w > 0; w--) {
00733 d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
00734 s2[0] + s2[1] + s2[2] + s2[3] +
00735 s3[0] + s3[1] + s3[2] + s3[3] +
00736 s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
00737 s1 += 4;
00738 s2 += 4;
00739 s3 += 4;
00740 s4 += 4;
00741 d++;
00742 }
00743 src += 4 * src_wrap;
00744 dst += dst_wrap;
00745 }
00746 }
00747
00748
00749 void ff_shrink88(uint8_t *dst, int dst_wrap,
00750 const uint8_t *src, int src_wrap,
00751 int width, int height)
00752 {
00753 int w, i;
00754
00755 for(;height > 0; height--) {
00756 for(w = width;w > 0; w--) {
00757 int tmp=0;
00758 for(i=0; i<8; i++){
00759 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
00760 src += src_wrap;
00761 }
00762 *(dst++) = (tmp + 32)>>6;
00763 src += 8 - 8*src_wrap;
00764 }
00765 src += 8*src_wrap - 8*width;
00766 dst += dst_wrap - width;
00767 }
00768 }
00769
00770
00771 int avpicture_alloc(AVPicture *picture,
00772 enum PixelFormat pix_fmt, int width, int height)
00773 {
00774 int ret;
00775
00776 if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
00777 memset(picture, 0, sizeof(AVPicture));
00778 return ret;
00779 }
00780
00781 return 0;
00782 }
00783
00784 void avpicture_free(AVPicture *picture)
00785 {
00786 av_free(picture->data[0]);
00787 }
00788
00789
00790 static inline int is_yuv_planar(const PixFmtInfo *ps)
00791 {
00792 return (ps->color_type == FF_COLOR_YUV ||
00793 ps->color_type == FF_COLOR_YUV_JPEG) &&
00794 ps->pixel_type == FF_PIXEL_PLANAR;
00795 }
00796
00797 int av_picture_crop(AVPicture *dst, const AVPicture *src,
00798 enum PixelFormat pix_fmt, int top_band, int left_band)
00799 {
00800 int y_shift;
00801 int x_shift;
00802
00803 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
00804 return -1;
00805
00806 y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00807 x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00808
00809 if (is_yuv_planar(&pix_fmt_info[pix_fmt])) {
00810 dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
00811 dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
00812 dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
00813 } else{
00814 if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
00815 return -1;
00816 if(left_band)
00817 return -1;
00818 dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
00819 }
00820
00821 dst->linesize[0] = src->linesize[0];
00822 dst->linesize[1] = src->linesize[1];
00823 dst->linesize[2] = src->linesize[2];
00824 return 0;
00825 }
00826
00827 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
00828 enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
00829 int *color)
00830 {
00831 uint8_t *optr;
00832 int y_shift;
00833 int x_shift;
00834 int yheight;
00835 int i, y;
00836
00837 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
00838 !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
00839
00840 for (i = 0; i < 3; i++) {
00841 x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
00842 y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
00843
00844 if (padtop || padleft) {
00845 memset(dst->data[i], color[i],
00846 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
00847 }
00848
00849 if (padleft || padright) {
00850 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00851 (dst->linesize[i] - (padright >> x_shift));
00852 yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00853 for (y = 0; y < yheight; y++) {
00854 memset(optr, color[i], (padleft + padright) >> x_shift);
00855 optr += dst->linesize[i];
00856 }
00857 }
00858
00859 if (src) {
00860 uint8_t *iptr = src->data[i];
00861 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00862 (padleft >> x_shift);
00863 memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
00864 iptr += src->linesize[i];
00865 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00866 (dst->linesize[i] - (padright >> x_shift));
00867 yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00868 for (y = 0; y < yheight; y++) {
00869 memset(optr, color[i], (padleft + padright) >> x_shift);
00870 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
00871 (width - padleft - padright) >> x_shift);
00872 iptr += src->linesize[i];
00873 optr += dst->linesize[i];
00874 }
00875 }
00876
00877 if (padbottom || padright) {
00878 optr = dst->data[i] + dst->linesize[i] *
00879 ((height - padbottom) >> y_shift) - (padright >> x_shift);
00880 memset(optr, color[i],dst->linesize[i] *
00881 (padbottom >> y_shift) + (padright >> x_shift));
00882 }
00883 }
00884 return 0;
00885 }
00886
00887
00888 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
00889 {
00890 const unsigned char *p;
00891 int src_wrap, ret, x, y;
00892 unsigned int a;
00893 uint32_t *palette = (uint32_t *)src->data[1];
00894
00895 p = src->data[0];
00896 src_wrap = src->linesize[0] - width;
00897 ret = 0;
00898 for(y=0;y<height;y++) {
00899 for(x=0;x<width;x++) {
00900 a = palette[p[0]] >> 24;
00901 if (a == 0x00) {
00902 ret |= FF_ALPHA_TRANSP;
00903 } else if (a != 0xff) {
00904 ret |= FF_ALPHA_SEMI_TRANSP;
00905 }
00906 p++;
00907 }
00908 p += src_wrap;
00909 }
00910 return ret;
00911 }
00912
00913 int img_get_alpha_info(const AVPicture *src,
00914 enum PixelFormat pix_fmt, int width, int height)
00915 {
00916 const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00917 int ret;
00918
00919
00920 if (!pf->is_alpha)
00921 return 0;
00922 switch(pix_fmt) {
00923 case PIX_FMT_PAL8:
00924 ret = get_alpha_info_pal8(src, width, height);
00925 break;
00926 default:
00927
00928 ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
00929 break;
00930 }
00931 return ret;
00932 }
00933
00934 #if !(HAVE_MMX && HAVE_YASM)
00935
00936 static void deinterlace_line_c(uint8_t *dst,
00937 const uint8_t *lum_m4, const uint8_t *lum_m3,
00938 const uint8_t *lum_m2, const uint8_t *lum_m1,
00939 const uint8_t *lum,
00940 int size)
00941 {
00942 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00943 int sum;
00944
00945 for(;size > 0;size--) {
00946 sum = -lum_m4[0];
00947 sum += lum_m3[0] << 2;
00948 sum += lum_m2[0] << 1;
00949 sum += lum_m1[0] << 2;
00950 sum += -lum[0];
00951 dst[0] = cm[(sum + 4) >> 3];
00952 lum_m4++;
00953 lum_m3++;
00954 lum_m2++;
00955 lum_m1++;
00956 lum++;
00957 dst++;
00958 }
00959 }
00960
00961 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
00962 uint8_t *lum_m2, uint8_t *lum_m1,
00963 uint8_t *lum, int size)
00964 {
00965 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00966 int sum;
00967
00968 for(;size > 0;size--) {
00969 sum = -lum_m4[0];
00970 sum += lum_m3[0] << 2;
00971 sum += lum_m2[0] << 1;
00972 lum_m4[0]=lum_m2[0];
00973 sum += lum_m1[0] << 2;
00974 sum += -lum[0];
00975 lum_m2[0] = cm[(sum + 4) >> 3];
00976 lum_m4++;
00977 lum_m3++;
00978 lum_m2++;
00979 lum_m1++;
00980 lum++;
00981 }
00982 }
00983 #endif
00984
00985
00986
00987
00988 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
00989 const uint8_t *src1, int src_wrap,
00990 int width, int height)
00991 {
00992 const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
00993 int y;
00994
00995 src_m2 = src1;
00996 src_m1 = src1;
00997 src_0=&src_m1[src_wrap];
00998 src_p1=&src_0[src_wrap];
00999 src_p2=&src_p1[src_wrap];
01000 for(y=0;y<(height-2);y+=2) {
01001 memcpy(dst,src_m1,width);
01002 dst += dst_wrap;
01003 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
01004 src_m2 = src_0;
01005 src_m1 = src_p1;
01006 src_0 = src_p2;
01007 src_p1 += 2*src_wrap;
01008 src_p2 += 2*src_wrap;
01009 dst += dst_wrap;
01010 }
01011 memcpy(dst,src_m1,width);
01012 dst += dst_wrap;
01013
01014 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
01015 }
01016
01017 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
01018 int width, int height)
01019 {
01020 uint8_t *src_m1, *src_0, *src_p1, *src_p2;
01021 int y;
01022 uint8_t *buf;
01023 buf = (uint8_t*)av_malloc(width);
01024
01025 src_m1 = src1;
01026 memcpy(buf,src_m1,width);
01027 src_0=&src_m1[src_wrap];
01028 src_p1=&src_0[src_wrap];
01029 src_p2=&src_p1[src_wrap];
01030 for(y=0;y<(height-2);y+=2) {
01031 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
01032 src_m1 = src_p1;
01033 src_0 = src_p2;
01034 src_p1 += 2*src_wrap;
01035 src_p2 += 2*src_wrap;
01036 }
01037
01038 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
01039 av_free(buf);
01040 }
01041
01042 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
01043 enum PixelFormat pix_fmt, int width, int height)
01044 {
01045 int i;
01046
01047 if (pix_fmt != PIX_FMT_YUV420P &&
01048 pix_fmt != PIX_FMT_YUVJ420P &&
01049 pix_fmt != PIX_FMT_YUV422P &&
01050 pix_fmt != PIX_FMT_YUVJ422P &&
01051 pix_fmt != PIX_FMT_YUV444P &&
01052 pix_fmt != PIX_FMT_YUV411P &&
01053 pix_fmt != PIX_FMT_GRAY8)
01054 return -1;
01055 if ((width & 3) != 0 || (height & 3) != 0)
01056 return -1;
01057
01058 for(i=0;i<3;i++) {
01059 if (i == 1) {
01060 switch(pix_fmt) {
01061 case PIX_FMT_YUVJ420P:
01062 case PIX_FMT_YUV420P:
01063 width >>= 1;
01064 height >>= 1;
01065 break;
01066 case PIX_FMT_YUV422P:
01067 case PIX_FMT_YUVJ422P:
01068 width >>= 1;
01069 break;
01070 case PIX_FMT_YUV411P:
01071 width >>= 2;
01072 break;
01073 default:
01074 break;
01075 }
01076 if (pix_fmt == PIX_FMT_GRAY8) {
01077 break;
01078 }
01079 }
01080 if (src == dst) {
01081 deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
01082 width, height);
01083 } else {
01084 deinterlace_bottom_field(dst->data[i],dst->linesize[i],
01085 src->data[i], src->linesize[i],
01086 width, height);
01087 }
01088 }
01089 emms_c();
01090 return 0;
01091 }
01092