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