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 const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt)
00421 {
00422 if ((unsigned)pix_fmt >= PIX_FMT_NB)
00423 return NULL;
00424 else
00425 return av_pix_fmt_descriptors[pix_fmt].name;
00426 }
00427
00428 #if LIBAVCODEC_VERSION_MAJOR < 53
00429 enum PixelFormat avcodec_get_pix_fmt(const char *name)
00430 {
00431 return av_get_pix_fmt(name);
00432 }
00433
00434 void avcodec_pix_fmt_string (char *buf, int buf_size, enum PixelFormat pix_fmt)
00435 {
00436 av_get_pix_fmt_string(buf, buf_size, pix_fmt);
00437 }
00438 #endif
00439
00440 int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
00441 {
00442 return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
00443 }
00444
00445 #if LIBAVCODEC_VERSION_MAJOR < 53
00446 int ff_set_systematic_pal(uint32_t pal[256], enum PixelFormat pix_fmt){
00447 return ff_set_systematic_pal2(pal, pix_fmt);
00448 }
00449
00450 int ff_fill_linesize(AVPicture *picture, enum PixelFormat pix_fmt, int width)
00451 {
00452 return av_image_fill_linesizes(picture->linesize, pix_fmt, width);
00453 }
00454
00455 int ff_fill_pointer(AVPicture *picture, uint8_t *ptr, enum PixelFormat pix_fmt,
00456 int height)
00457 {
00458 return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
00459 }
00460 #endif
00461
00462 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00463 enum PixelFormat pix_fmt, int width, int height)
00464 {
00465 int ret;
00466
00467 if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
00468 return ret;
00469
00470 if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0)
00471 return ret;
00472
00473 return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
00474 }
00475
00476 int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
00477 unsigned char *dest, int dest_size)
00478 {
00479 int i, j, nb_planes = 0, linesizes[4];
00480 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00481 int size = avpicture_get_size(pix_fmt, width, height);
00482
00483 if (size > dest_size || size < 0)
00484 return AVERROR(EINVAL);
00485
00486 for (i = 0; i < desc->nb_components; i++)
00487 nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
00488 nb_planes++;
00489
00490 av_image_fill_linesizes(linesizes, pix_fmt, width);
00491 for (i = 0; i < nb_planes; i++) {
00492 int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
00493 const unsigned char *s = src->data[i];
00494 h = (height + (1 << shift) - 1) >> shift;
00495
00496 for (j = 0; j < h; j++) {
00497 memcpy(dest, s, linesizes[i]);
00498 dest += linesizes[i];
00499 s += src->linesize[i];
00500 }
00501 }
00502
00503 if (desc->flags & PIX_FMT_PAL)
00504 memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00505
00506 return size;
00507 }
00508
00509 int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height)
00510 {
00511 AVPicture dummy_pict;
00512 if(av_image_check_size(width, height, 0, NULL))
00513 return -1;
00514 switch (pix_fmt) {
00515 case PIX_FMT_RGB8:
00516 case PIX_FMT_BGR8:
00517 case PIX_FMT_RGB4_BYTE:
00518 case PIX_FMT_BGR4_BYTE:
00519 case PIX_FMT_GRAY8:
00520
00521 return width * height;
00522 }
00523 return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00524 }
00525
00526 int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
00527 int has_alpha)
00528 {
00529 const PixFmtInfo *pf, *ps;
00530 const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
00531 const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
00532 int loss;
00533
00534 ps = &pix_fmt_info[src_pix_fmt];
00535
00536
00537 loss = 0;
00538 pf = &pix_fmt_info[dst_pix_fmt];
00539 if (pf->depth < ps->depth ||
00540 ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE ||
00541 dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) &&
00542 (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE ||
00543 src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE)))
00544 loss |= FF_LOSS_DEPTH;
00545 if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
00546 dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
00547 loss |= FF_LOSS_RESOLUTION;
00548 switch(pf->color_type) {
00549 case FF_COLOR_RGB:
00550 if (ps->color_type != FF_COLOR_RGB &&
00551 ps->color_type != FF_COLOR_GRAY)
00552 loss |= FF_LOSS_COLORSPACE;
00553 break;
00554 case FF_COLOR_GRAY:
00555 if (ps->color_type != FF_COLOR_GRAY)
00556 loss |= FF_LOSS_COLORSPACE;
00557 break;
00558 case FF_COLOR_YUV:
00559 if (ps->color_type != FF_COLOR_YUV)
00560 loss |= FF_LOSS_COLORSPACE;
00561 break;
00562 case FF_COLOR_YUV_JPEG:
00563 if (ps->color_type != FF_COLOR_YUV_JPEG &&
00564 ps->color_type != FF_COLOR_YUV &&
00565 ps->color_type != FF_COLOR_GRAY)
00566 loss |= FF_LOSS_COLORSPACE;
00567 break;
00568 default:
00569
00570 if (ps->color_type != pf->color_type)
00571 loss |= FF_LOSS_COLORSPACE;
00572 break;
00573 }
00574 if (pf->color_type == FF_COLOR_GRAY &&
00575 ps->color_type != FF_COLOR_GRAY)
00576 loss |= FF_LOSS_CHROMA;
00577 if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00578 loss |= FF_LOSS_ALPHA;
00579 if (pf->pixel_type == FF_PIXEL_PALETTE &&
00580 (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00581 loss |= FF_LOSS_COLORQUANT;
00582 return loss;
00583 }
00584
00585 static int avg_bits_per_pixel(enum PixelFormat pix_fmt)
00586 {
00587 int bits;
00588 const PixFmtInfo *pf;
00589 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00590
00591 pf = &pix_fmt_info[pix_fmt];
00592 switch(pf->pixel_type) {
00593 case FF_PIXEL_PACKED:
00594 switch(pix_fmt) {
00595 case PIX_FMT_YUYV422:
00596 case PIX_FMT_UYVY422:
00597 case PIX_FMT_RGB565BE:
00598 case PIX_FMT_RGB565LE:
00599 case PIX_FMT_RGB555BE:
00600 case PIX_FMT_RGB555LE:
00601 case PIX_FMT_RGB444BE:
00602 case PIX_FMT_RGB444LE:
00603 case PIX_FMT_BGR565BE:
00604 case PIX_FMT_BGR565LE:
00605 case PIX_FMT_BGR555BE:
00606 case PIX_FMT_BGR555LE:
00607 case PIX_FMT_BGR444BE:
00608 case PIX_FMT_BGR444LE:
00609 bits = 16;
00610 break;
00611 case PIX_FMT_UYYVYY411:
00612 bits = 12;
00613 break;
00614 default:
00615 bits = pf->depth * pf->nb_channels;
00616 break;
00617 }
00618 break;
00619 case FF_PIXEL_PLANAR:
00620 if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
00621 bits = pf->depth * pf->nb_channels;
00622 } else {
00623 bits = pf->depth + ((2 * pf->depth) >>
00624 (desc->log2_chroma_w + desc->log2_chroma_h));
00625 }
00626 break;
00627 case FF_PIXEL_PALETTE:
00628 bits = 8;
00629 break;
00630 default:
00631 bits = -1;
00632 break;
00633 }
00634 return bits;
00635 }
00636
00637 static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
00638 enum PixelFormat src_pix_fmt,
00639 int has_alpha,
00640 int loss_mask)
00641 {
00642 int dist, i, loss, min_dist;
00643 enum PixelFormat dst_pix_fmt;
00644
00645
00646 dst_pix_fmt = PIX_FMT_NONE;
00647 min_dist = 0x7fffffff;
00648 for(i = 0;i < PIX_FMT_NB; i++) {
00649 if (pix_fmt_mask & (1ULL << i)) {
00650 loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00651 if (loss == 0) {
00652 dist = avg_bits_per_pixel(i);
00653 if (dist < min_dist) {
00654 min_dist = dist;
00655 dst_pix_fmt = i;
00656 }
00657 }
00658 }
00659 }
00660 return dst_pix_fmt;
00661 }
00662
00663 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
00664 int has_alpha, int *loss_ptr)
00665 {
00666 enum PixelFormat dst_pix_fmt;
00667 int loss_mask, i;
00668 static const int loss_mask_order[] = {
00669 ~0,
00670 ~FF_LOSS_ALPHA,
00671 ~FF_LOSS_RESOLUTION,
00672 ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00673 ~FF_LOSS_COLORQUANT,
00674 ~FF_LOSS_DEPTH,
00675 0,
00676 };
00677
00678
00679 i = 0;
00680 for(;;) {
00681 loss_mask = loss_mask_order[i++];
00682 dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00683 has_alpha, loss_mask);
00684 if (dst_pix_fmt >= 0)
00685 goto found;
00686 if (loss_mask == 0)
00687 break;
00688 }
00689 return PIX_FMT_NONE;
00690 found:
00691 if (loss_ptr)
00692 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00693 return dst_pix_fmt;
00694 }
00695
00696 #if LIBAVCODEC_VERSION_MAJOR < 53
00697 void ff_img_copy_plane(uint8_t *dst, int dst_wrap,
00698 const uint8_t *src, int src_wrap,
00699 int width, int height)
00700 {
00701 av_image_copy_plane(dst, dst_wrap, src, src_wrap, width, height);
00702 }
00703
00704 int ff_get_plane_bytewidth(enum PixelFormat pix_fmt, int width, int plane)
00705 {
00706 return av_image_get_linesize(pix_fmt, width, plane);
00707 }
00708
00709 void av_picture_data_copy(uint8_t *dst_data[4], int dst_linesize[4],
00710 uint8_t *src_data[4], int src_linesize[4],
00711 enum PixelFormat pix_fmt, int width, int height)
00712 {
00713 av_image_copy(dst_data, dst_linesize, src_data, src_linesize,
00714 pix_fmt, width, height);
00715 }
00716 #endif
00717
00718 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00719 enum PixelFormat pix_fmt, int width, int height)
00720 {
00721 av_image_copy(dst->data, dst->linesize, src->data,
00722 src->linesize, pix_fmt, width, height);
00723 }
00724
00725
00726 void ff_shrink22(uint8_t *dst, int dst_wrap,
00727 const uint8_t *src, int src_wrap,
00728 int width, int height)
00729 {
00730 int w;
00731 const uint8_t *s1, *s2;
00732 uint8_t *d;
00733
00734 for(;height > 0; height--) {
00735 s1 = src;
00736 s2 = s1 + src_wrap;
00737 d = dst;
00738 for(w = width;w >= 4; w-=4) {
00739 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00740 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
00741 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
00742 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
00743 s1 += 8;
00744 s2 += 8;
00745 d += 4;
00746 }
00747 for(;w > 0; w--) {
00748 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00749 s1 += 2;
00750 s2 += 2;
00751 d++;
00752 }
00753 src += 2 * src_wrap;
00754 dst += dst_wrap;
00755 }
00756 }
00757
00758
00759 void ff_shrink44(uint8_t *dst, int dst_wrap,
00760 const uint8_t *src, int src_wrap,
00761 int width, int height)
00762 {
00763 int w;
00764 const uint8_t *s1, *s2, *s3, *s4;
00765 uint8_t *d;
00766
00767 for(;height > 0; height--) {
00768 s1 = src;
00769 s2 = s1 + src_wrap;
00770 s3 = s2 + src_wrap;
00771 s4 = s3 + src_wrap;
00772 d = dst;
00773 for(w = width;w > 0; w--) {
00774 d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
00775 s2[0] + s2[1] + s2[2] + s2[3] +
00776 s3[0] + s3[1] + s3[2] + s3[3] +
00777 s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
00778 s1 += 4;
00779 s2 += 4;
00780 s3 += 4;
00781 s4 += 4;
00782 d++;
00783 }
00784 src += 4 * src_wrap;
00785 dst += dst_wrap;
00786 }
00787 }
00788
00789
00790 void ff_shrink88(uint8_t *dst, int dst_wrap,
00791 const uint8_t *src, int src_wrap,
00792 int width, int height)
00793 {
00794 int w, i;
00795
00796 for(;height > 0; height--) {
00797 for(w = width;w > 0; w--) {
00798 int tmp=0;
00799 for(i=0; i<8; i++){
00800 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
00801 src += src_wrap;
00802 }
00803 *(dst++) = (tmp + 32)>>6;
00804 src += 8 - 8*src_wrap;
00805 }
00806 src += 8*src_wrap - 8*width;
00807 dst += dst_wrap - width;
00808 }
00809 }
00810
00811
00812 int avpicture_alloc(AVPicture *picture,
00813 enum PixelFormat pix_fmt, int width, int height)
00814 {
00815 int ret;
00816
00817 if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
00818 memset(picture, 0, sizeof(AVPicture));
00819 return ret;
00820 }
00821
00822 return 0;
00823 }
00824
00825 void avpicture_free(AVPicture *picture)
00826 {
00827 av_free(picture->data[0]);
00828 }
00829
00830
00831 static inline int is_yuv_planar(const PixFmtInfo *ps)
00832 {
00833 return (ps->color_type == FF_COLOR_YUV ||
00834 ps->color_type == FF_COLOR_YUV_JPEG) &&
00835 ps->pixel_type == FF_PIXEL_PLANAR;
00836 }
00837
00838 int av_picture_crop(AVPicture *dst, const AVPicture *src,
00839 enum PixelFormat pix_fmt, int top_band, int left_band)
00840 {
00841 int y_shift;
00842 int x_shift;
00843
00844 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
00845 return -1;
00846
00847 y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00848 x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00849
00850 dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
00851 dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
00852 dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
00853
00854 dst->linesize[0] = src->linesize[0];
00855 dst->linesize[1] = src->linesize[1];
00856 dst->linesize[2] = src->linesize[2];
00857 return 0;
00858 }
00859
00860 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
00861 enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
00862 int *color)
00863 {
00864 uint8_t *optr;
00865 int y_shift;
00866 int x_shift;
00867 int yheight;
00868 int i, y;
00869
00870 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
00871 !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
00872
00873 for (i = 0; i < 3; i++) {
00874 x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
00875 y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
00876
00877 if (padtop || padleft) {
00878 memset(dst->data[i], color[i],
00879 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
00880 }
00881
00882 if (padleft || padright) {
00883 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00884 (dst->linesize[i] - (padright >> x_shift));
00885 yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00886 for (y = 0; y < yheight; y++) {
00887 memset(optr, color[i], (padleft + padright) >> x_shift);
00888 optr += dst->linesize[i];
00889 }
00890 }
00891
00892 if (src) {
00893 uint8_t *iptr = src->data[i];
00894 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00895 (padleft >> x_shift);
00896 memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
00897 iptr += src->linesize[i];
00898 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00899 (dst->linesize[i] - (padright >> x_shift));
00900 yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00901 for (y = 0; y < yheight; y++) {
00902 memset(optr, color[i], (padleft + padright) >> x_shift);
00903 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
00904 (width - padleft - padright) >> x_shift);
00905 iptr += src->linesize[i];
00906 optr += dst->linesize[i];
00907 }
00908 }
00909
00910 if (padbottom || padright) {
00911 optr = dst->data[i] + dst->linesize[i] *
00912 ((height - padbottom) >> y_shift) - (padright >> x_shift);
00913 memset(optr, color[i],dst->linesize[i] *
00914 (padbottom >> y_shift) + (padright >> x_shift));
00915 }
00916 }
00917 return 0;
00918 }
00919
00920
00921 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
00922 {
00923 const unsigned char *p;
00924 int src_wrap, ret, x, y;
00925 unsigned int a;
00926 uint32_t *palette = (uint32_t *)src->data[1];
00927
00928 p = src->data[0];
00929 src_wrap = src->linesize[0] - width;
00930 ret = 0;
00931 for(y=0;y<height;y++) {
00932 for(x=0;x<width;x++) {
00933 a = palette[p[0]] >> 24;
00934 if (a == 0x00) {
00935 ret |= FF_ALPHA_TRANSP;
00936 } else if (a != 0xff) {
00937 ret |= FF_ALPHA_SEMI_TRANSP;
00938 }
00939 p++;
00940 }
00941 p += src_wrap;
00942 }
00943 return ret;
00944 }
00945
00946 int img_get_alpha_info(const AVPicture *src,
00947 enum PixelFormat pix_fmt, int width, int height)
00948 {
00949 const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00950 int ret;
00951
00952
00953 if (!pf->is_alpha)
00954 return 0;
00955 switch(pix_fmt) {
00956 case PIX_FMT_PAL8:
00957 ret = get_alpha_info_pal8(src, width, height);
00958 break;
00959 default:
00960
00961 ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
00962 break;
00963 }
00964 return ret;
00965 }
00966
00967 #if !(HAVE_MMX && HAVE_YASM)
00968
00969 static void deinterlace_line_c(uint8_t *dst,
00970 const uint8_t *lum_m4, const uint8_t *lum_m3,
00971 const uint8_t *lum_m2, const uint8_t *lum_m1,
00972 const uint8_t *lum,
00973 int size)
00974 {
00975 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00976 int sum;
00977
00978 for(;size > 0;size--) {
00979 sum = -lum_m4[0];
00980 sum += lum_m3[0] << 2;
00981 sum += lum_m2[0] << 1;
00982 sum += lum_m1[0] << 2;
00983 sum += -lum[0];
00984 dst[0] = cm[(sum + 4) >> 3];
00985 lum_m4++;
00986 lum_m3++;
00987 lum_m2++;
00988 lum_m1++;
00989 lum++;
00990 dst++;
00991 }
00992 }
00993
00994 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
00995 uint8_t *lum_m2, uint8_t *lum_m1,
00996 uint8_t *lum, int size)
00997 {
00998 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00999 int sum;
01000
01001 for(;size > 0;size--) {
01002 sum = -lum_m4[0];
01003 sum += lum_m3[0] << 2;
01004 sum += lum_m2[0] << 1;
01005 lum_m4[0]=lum_m2[0];
01006 sum += lum_m1[0] << 2;
01007 sum += -lum[0];
01008 lum_m2[0] = cm[(sum + 4) >> 3];
01009 lum_m4++;
01010 lum_m3++;
01011 lum_m2++;
01012 lum_m1++;
01013 lum++;
01014 }
01015 }
01016 #endif
01017
01018
01019
01020
01021 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
01022 const uint8_t *src1, int src_wrap,
01023 int width, int height)
01024 {
01025 const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
01026 int y;
01027
01028 src_m2 = src1;
01029 src_m1 = src1;
01030 src_0=&src_m1[src_wrap];
01031 src_p1=&src_0[src_wrap];
01032 src_p2=&src_p1[src_wrap];
01033 for(y=0;y<(height-2);y+=2) {
01034 memcpy(dst,src_m1,width);
01035 dst += dst_wrap;
01036 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
01037 src_m2 = src_0;
01038 src_m1 = src_p1;
01039 src_0 = src_p2;
01040 src_p1 += 2*src_wrap;
01041 src_p2 += 2*src_wrap;
01042 dst += dst_wrap;
01043 }
01044 memcpy(dst,src_m1,width);
01045 dst += dst_wrap;
01046
01047 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
01048 }
01049
01050 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
01051 int width, int height)
01052 {
01053 uint8_t *src_m1, *src_0, *src_p1, *src_p2;
01054 int y;
01055 uint8_t *buf;
01056 buf = (uint8_t*)av_malloc(width);
01057
01058 src_m1 = src1;
01059 memcpy(buf,src_m1,width);
01060 src_0=&src_m1[src_wrap];
01061 src_p1=&src_0[src_wrap];
01062 src_p2=&src_p1[src_wrap];
01063 for(y=0;y<(height-2);y+=2) {
01064 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
01065 src_m1 = src_p1;
01066 src_0 = src_p2;
01067 src_p1 += 2*src_wrap;
01068 src_p2 += 2*src_wrap;
01069 }
01070
01071 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
01072 av_free(buf);
01073 }
01074
01075 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
01076 enum PixelFormat pix_fmt, int width, int height)
01077 {
01078 int i;
01079
01080 if (pix_fmt != PIX_FMT_YUV420P &&
01081 pix_fmt != PIX_FMT_YUVJ420P &&
01082 pix_fmt != PIX_FMT_YUV422P &&
01083 pix_fmt != PIX_FMT_YUVJ422P &&
01084 pix_fmt != PIX_FMT_YUV444P &&
01085 pix_fmt != PIX_FMT_YUV411P &&
01086 pix_fmt != PIX_FMT_GRAY8)
01087 return -1;
01088 if ((width & 3) != 0 || (height & 3) != 0)
01089 return -1;
01090
01091 for(i=0;i<3;i++) {
01092 if (i == 1) {
01093 switch(pix_fmt) {
01094 case PIX_FMT_YUVJ420P:
01095 case PIX_FMT_YUV420P:
01096 width >>= 1;
01097 height >>= 1;
01098 break;
01099 case PIX_FMT_YUV422P:
01100 case PIX_FMT_YUVJ422P:
01101 width >>= 1;
01102 break;
01103 case PIX_FMT_YUV411P:
01104 width >>= 2;
01105 break;
01106 default:
01107 break;
01108 }
01109 if (pix_fmt == PIX_FMT_GRAY8) {
01110 break;
01111 }
01112 }
01113 if (src == dst) {
01114 deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
01115 width, height);
01116 } else {
01117 deinterlace_bottom_field(dst->data[i],dst->linesize[i],
01118 src->data[i], src->linesize[i],
01119 width, height);
01120 }
01121 }
01122 emms_c();
01123 return 0;
01124 }
01125