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