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