Libav 0.7.1
|
00001 /* 00002 * Misc image conversion routines 00003 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 /* TODO: 00028 * - write 'ffimg' program to test all the image related stuff 00029 * - move all api to slice based system 00030 * - integrate deinterlacing, postprocessing and scaling in the conversion process 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 /* this table gives more information about formats */ 00074 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { 00075 /* YUV formats */ 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 /* YUV formats with alpha plane */ 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 /* JPEG YUV */ 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 /* RGB formats */ 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 /* gray / mono formats */ 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 /* paletted formats */ 00297 [PIX_FMT_PAL8] = { 00298 .nb_channels = 4, .is_alpha = 1, 00299 .color_type = FF_COLOR_RGB, 00300 .pixel_type = FF_PIXEL_PALETTE, 00301 .depth = 8, 00302 }, 00303 [PIX_FMT_UYYVYY411] = { 00304 .nb_channels = 1, 00305 .color_type = FF_COLOR_YUV, 00306 .pixel_type = FF_PIXEL_PACKED, 00307 .depth = 8, 00308 }, 00309 [PIX_FMT_ABGR] = { 00310 .nb_channels = 4, .is_alpha = 1, 00311 .color_type = FF_COLOR_RGB, 00312 .pixel_type = FF_PIXEL_PACKED, 00313 .depth = 8, 00314 }, 00315 [PIX_FMT_BGR565BE] = { 00316 .nb_channels = 3, 00317 .color_type = FF_COLOR_RGB, 00318 .pixel_type = FF_PIXEL_PACKED, 00319 .depth = 5, 00320 }, 00321 [PIX_FMT_BGR565LE] = { 00322 .nb_channels = 3, 00323 .color_type = FF_COLOR_RGB, 00324 .pixel_type = FF_PIXEL_PACKED, 00325 .depth = 5, 00326 }, 00327 [PIX_FMT_BGR555BE] = { 00328 .nb_channels = 3, 00329 .color_type = FF_COLOR_RGB, 00330 .pixel_type = FF_PIXEL_PACKED, 00331 .depth = 5, 00332 }, 00333 [PIX_FMT_BGR555LE] = { 00334 .nb_channels = 3, 00335 .color_type = FF_COLOR_RGB, 00336 .pixel_type = FF_PIXEL_PACKED, 00337 .depth = 5, 00338 }, 00339 [PIX_FMT_BGR444BE] = { 00340 .nb_channels = 3, 00341 .color_type = FF_COLOR_RGB, 00342 .pixel_type = FF_PIXEL_PACKED, 00343 .depth = 4, 00344 }, 00345 [PIX_FMT_BGR444LE] = { 00346 .nb_channels = 3, 00347 .color_type = FF_COLOR_RGB, 00348 .pixel_type = FF_PIXEL_PACKED, 00349 .depth = 4, 00350 }, 00351 [PIX_FMT_RGB8] = { 00352 .nb_channels = 1, 00353 .color_type = FF_COLOR_RGB, 00354 .pixel_type = FF_PIXEL_PACKED, 00355 .depth = 8, 00356 }, 00357 [PIX_FMT_RGB4] = { 00358 .nb_channels = 1, 00359 .color_type = FF_COLOR_RGB, 00360 .pixel_type = FF_PIXEL_PACKED, 00361 .depth = 4, 00362 }, 00363 [PIX_FMT_RGB4_BYTE] = { 00364 .nb_channels = 1, 00365 .color_type = FF_COLOR_RGB, 00366 .pixel_type = FF_PIXEL_PACKED, 00367 .depth = 8, 00368 }, 00369 [PIX_FMT_BGR8] = { 00370 .nb_channels = 1, 00371 .color_type = FF_COLOR_RGB, 00372 .pixel_type = FF_PIXEL_PACKED, 00373 .depth = 8, 00374 }, 00375 [PIX_FMT_BGR4] = { 00376 .nb_channels = 1, 00377 .color_type = FF_COLOR_RGB, 00378 .pixel_type = FF_PIXEL_PACKED, 00379 .depth = 4, 00380 }, 00381 [PIX_FMT_BGR4_BYTE] = { 00382 .nb_channels = 1, 00383 .color_type = FF_COLOR_RGB, 00384 .pixel_type = FF_PIXEL_PACKED, 00385 .depth = 8, 00386 }, 00387 [PIX_FMT_NV12] = { 00388 .nb_channels = 2, 00389 .color_type = FF_COLOR_YUV, 00390 .pixel_type = FF_PIXEL_PLANAR, 00391 .depth = 8, 00392 }, 00393 [PIX_FMT_NV21] = { 00394 .nb_channels = 2, 00395 .color_type = FF_COLOR_YUV, 00396 .pixel_type = FF_PIXEL_PLANAR, 00397 .depth = 8, 00398 }, 00399 00400 [PIX_FMT_BGRA] = { 00401 .nb_channels = 4, .is_alpha = 1, 00402 .color_type = FF_COLOR_RGB, 00403 .pixel_type = FF_PIXEL_PACKED, 00404 .depth = 8, 00405 }, 00406 [PIX_FMT_RGBA] = { 00407 .nb_channels = 4, .is_alpha = 1, 00408 .color_type = FF_COLOR_RGB, 00409 .pixel_type = FF_PIXEL_PACKED, 00410 .depth = 8, 00411 }, 00412 }; 00413 00414 void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift) 00415 { 00416 *h_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w; 00417 *v_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h; 00418 } 00419 00420 #if FF_API_GET_PIX_FMT_NAME 00421 const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt) 00422 { 00423 return av_get_pix_fmt_name(pix_fmt); 00424 } 00425 #endif 00426 00427 int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt) 00428 { 00429 return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL; 00430 } 00431 00432 int avpicture_fill(AVPicture *picture, uint8_t *ptr, 00433 enum PixelFormat pix_fmt, int width, int height) 00434 { 00435 int ret; 00436 00437 if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) 00438 return ret; 00439 00440 if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0) 00441 return ret; 00442 00443 return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize); 00444 } 00445 00446 int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height, 00447 unsigned char *dest, int dest_size) 00448 { 00449 int i, j, nb_planes = 0, linesizes[4]; 00450 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 00451 int size = avpicture_get_size(pix_fmt, width, height); 00452 00453 if (size > dest_size || size < 0) 00454 return AVERROR(EINVAL); 00455 00456 for (i = 0; i < desc->nb_components; i++) 00457 nb_planes = FFMAX(desc->comp[i].plane, nb_planes); 00458 nb_planes++; 00459 00460 av_image_fill_linesizes(linesizes, pix_fmt, width); 00461 for (i = 0; i < nb_planes; i++) { 00462 int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; 00463 const unsigned char *s = src->data[i]; 00464 h = (height + (1 << shift) - 1) >> shift; 00465 00466 for (j = 0; j < h; j++) { 00467 memcpy(dest, s, linesizes[i]); 00468 dest += linesizes[i]; 00469 s += src->linesize[i]; 00470 } 00471 } 00472 00473 if (desc->flags & PIX_FMT_PAL) 00474 memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4); 00475 00476 return size; 00477 } 00478 00479 int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height) 00480 { 00481 AVPicture dummy_pict; 00482 if(av_image_check_size(width, height, 0, NULL)) 00483 return -1; 00484 switch (pix_fmt) { 00485 case PIX_FMT_RGB8: 00486 case PIX_FMT_BGR8: 00487 case PIX_FMT_RGB4_BYTE: 00488 case PIX_FMT_BGR4_BYTE: 00489 case PIX_FMT_GRAY8: 00490 // do not include palette for these pseudo-paletted formats 00491 return width * height; 00492 } 00493 return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height); 00494 } 00495 00496 int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt, 00497 int has_alpha) 00498 { 00499 const PixFmtInfo *pf, *ps; 00500 const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt]; 00501 const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt]; 00502 int loss; 00503 00504 ps = &pix_fmt_info[src_pix_fmt]; 00505 00506 /* compute loss */ 00507 loss = 0; 00508 pf = &pix_fmt_info[dst_pix_fmt]; 00509 if (pf->depth < ps->depth || 00510 ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE || 00511 dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) && 00512 (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE || 00513 src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE))) 00514 loss |= FF_LOSS_DEPTH; 00515 if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w || 00516 dst_desc->log2_chroma_h > src_desc->log2_chroma_h) 00517 loss |= FF_LOSS_RESOLUTION; 00518 switch(pf->color_type) { 00519 case FF_COLOR_RGB: 00520 if (ps->color_type != FF_COLOR_RGB && 00521 ps->color_type != FF_COLOR_GRAY) 00522 loss |= FF_LOSS_COLORSPACE; 00523 break; 00524 case FF_COLOR_GRAY: 00525 if (ps->color_type != FF_COLOR_GRAY) 00526 loss |= FF_LOSS_COLORSPACE; 00527 break; 00528 case FF_COLOR_YUV: 00529 if (ps->color_type != FF_COLOR_YUV) 00530 loss |= FF_LOSS_COLORSPACE; 00531 break; 00532 case FF_COLOR_YUV_JPEG: 00533 if (ps->color_type != FF_COLOR_YUV_JPEG && 00534 ps->color_type != FF_COLOR_YUV && 00535 ps->color_type != FF_COLOR_GRAY) 00536 loss |= FF_LOSS_COLORSPACE; 00537 break; 00538 default: 00539 /* fail safe test */ 00540 if (ps->color_type != pf->color_type) 00541 loss |= FF_LOSS_COLORSPACE; 00542 break; 00543 } 00544 if (pf->color_type == FF_COLOR_GRAY && 00545 ps->color_type != FF_COLOR_GRAY) 00546 loss |= FF_LOSS_CHROMA; 00547 if (!pf->is_alpha && (ps->is_alpha && has_alpha)) 00548 loss |= FF_LOSS_ALPHA; 00549 if (pf->pixel_type == FF_PIXEL_PALETTE && 00550 (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY)) 00551 loss |= FF_LOSS_COLORQUANT; 00552 return loss; 00553 } 00554 00555 static int avg_bits_per_pixel(enum PixelFormat pix_fmt) 00556 { 00557 int bits; 00558 const PixFmtInfo *pf; 00559 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 00560 00561 pf = &pix_fmt_info[pix_fmt]; 00562 switch(pf->pixel_type) { 00563 case FF_PIXEL_PACKED: 00564 switch(pix_fmt) { 00565 case PIX_FMT_YUYV422: 00566 case PIX_FMT_UYVY422: 00567 case PIX_FMT_RGB565BE: 00568 case PIX_FMT_RGB565LE: 00569 case PIX_FMT_RGB555BE: 00570 case PIX_FMT_RGB555LE: 00571 case PIX_FMT_RGB444BE: 00572 case PIX_FMT_RGB444LE: 00573 case PIX_FMT_BGR565BE: 00574 case PIX_FMT_BGR565LE: 00575 case PIX_FMT_BGR555BE: 00576 case PIX_FMT_BGR555LE: 00577 case PIX_FMT_BGR444BE: 00578 case PIX_FMT_BGR444LE: 00579 bits = 16; 00580 break; 00581 case PIX_FMT_UYYVYY411: 00582 bits = 12; 00583 break; 00584 default: 00585 bits = pf->depth * pf->nb_channels; 00586 break; 00587 } 00588 break; 00589 case FF_PIXEL_PLANAR: 00590 if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) { 00591 bits = pf->depth * pf->nb_channels; 00592 } else { 00593 bits = pf->depth + ((2 * pf->depth) >> 00594 (desc->log2_chroma_w + desc->log2_chroma_h)); 00595 } 00596 break; 00597 case FF_PIXEL_PALETTE: 00598 bits = 8; 00599 break; 00600 default: 00601 bits = -1; 00602 break; 00603 } 00604 return bits; 00605 } 00606 00607 static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask, 00608 enum PixelFormat src_pix_fmt, 00609 int has_alpha, 00610 int loss_mask) 00611 { 00612 int dist, i, loss, min_dist; 00613 enum PixelFormat dst_pix_fmt; 00614 00615 /* find exact color match with smallest size */ 00616 dst_pix_fmt = PIX_FMT_NONE; 00617 min_dist = 0x7fffffff; 00618 for(i = 0;i < PIX_FMT_NB; i++) { 00619 if (pix_fmt_mask & (1ULL << i)) { 00620 loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask; 00621 if (loss == 0) { 00622 dist = avg_bits_per_pixel(i); 00623 if (dist < min_dist) { 00624 min_dist = dist; 00625 dst_pix_fmt = i; 00626 } 00627 } 00628 } 00629 } 00630 return dst_pix_fmt; 00631 } 00632 00633 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt, 00634 int has_alpha, int *loss_ptr) 00635 { 00636 enum PixelFormat dst_pix_fmt; 00637 int loss_mask, i; 00638 static const int loss_mask_order[] = { 00639 ~0, /* no loss first */ 00640 ~FF_LOSS_ALPHA, 00641 ~FF_LOSS_RESOLUTION, 00642 ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION), 00643 ~FF_LOSS_COLORQUANT, 00644 ~FF_LOSS_DEPTH, 00645 0, 00646 }; 00647 00648 /* try with successive loss */ 00649 i = 0; 00650 for(;;) { 00651 loss_mask = loss_mask_order[i++]; 00652 dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt, 00653 has_alpha, loss_mask); 00654 if (dst_pix_fmt >= 0) 00655 goto found; 00656 if (loss_mask == 0) 00657 break; 00658 } 00659 return PIX_FMT_NONE; 00660 found: 00661 if (loss_ptr) 00662 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); 00663 return dst_pix_fmt; 00664 } 00665 00666 void av_picture_copy(AVPicture *dst, const AVPicture *src, 00667 enum PixelFormat pix_fmt, int width, int height) 00668 { 00669 av_image_copy(dst->data, dst->linesize, src->data, 00670 src->linesize, pix_fmt, width, height); 00671 } 00672 00673 /* 2x2 -> 1x1 */ 00674 void ff_shrink22(uint8_t *dst, int dst_wrap, 00675 const uint8_t *src, int src_wrap, 00676 int width, int height) 00677 { 00678 int w; 00679 const uint8_t *s1, *s2; 00680 uint8_t *d; 00681 00682 for(;height > 0; height--) { 00683 s1 = src; 00684 s2 = s1 + src_wrap; 00685 d = dst; 00686 for(w = width;w >= 4; w-=4) { 00687 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; 00688 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; 00689 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; 00690 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; 00691 s1 += 8; 00692 s2 += 8; 00693 d += 4; 00694 } 00695 for(;w > 0; w--) { 00696 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; 00697 s1 += 2; 00698 s2 += 2; 00699 d++; 00700 } 00701 src += 2 * src_wrap; 00702 dst += dst_wrap; 00703 } 00704 } 00705 00706 /* 4x4 -> 1x1 */ 00707 void ff_shrink44(uint8_t *dst, int dst_wrap, 00708 const uint8_t *src, int src_wrap, 00709 int width, int height) 00710 { 00711 int w; 00712 const uint8_t *s1, *s2, *s3, *s4; 00713 uint8_t *d; 00714 00715 for(;height > 0; height--) { 00716 s1 = src; 00717 s2 = s1 + src_wrap; 00718 s3 = s2 + src_wrap; 00719 s4 = s3 + src_wrap; 00720 d = dst; 00721 for(w = width;w > 0; w--) { 00722 d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + 00723 s2[0] + s2[1] + s2[2] + s2[3] + 00724 s3[0] + s3[1] + s3[2] + s3[3] + 00725 s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; 00726 s1 += 4; 00727 s2 += 4; 00728 s3 += 4; 00729 s4 += 4; 00730 d++; 00731 } 00732 src += 4 * src_wrap; 00733 dst += dst_wrap; 00734 } 00735 } 00736 00737 /* 8x8 -> 1x1 */ 00738 void ff_shrink88(uint8_t *dst, int dst_wrap, 00739 const uint8_t *src, int src_wrap, 00740 int width, int height) 00741 { 00742 int w, i; 00743 00744 for(;height > 0; height--) { 00745 for(w = width;w > 0; w--) { 00746 int tmp=0; 00747 for(i=0; i<8; i++){ 00748 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7]; 00749 src += src_wrap; 00750 } 00751 *(dst++) = (tmp + 32)>>6; 00752 src += 8 - 8*src_wrap; 00753 } 00754 src += 8*src_wrap - 8*width; 00755 dst += dst_wrap - width; 00756 } 00757 } 00758 00759 00760 int avpicture_alloc(AVPicture *picture, 00761 enum PixelFormat pix_fmt, int width, int height) 00762 { 00763 int ret; 00764 00765 if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) { 00766 memset(picture, 0, sizeof(AVPicture)); 00767 return ret; 00768 } 00769 00770 return 0; 00771 } 00772 00773 void avpicture_free(AVPicture *picture) 00774 { 00775 av_free(picture->data[0]); 00776 } 00777 00778 /* return true if yuv planar */ 00779 static inline int is_yuv_planar(const PixFmtInfo *ps) 00780 { 00781 return (ps->color_type == FF_COLOR_YUV || 00782 ps->color_type == FF_COLOR_YUV_JPEG) && 00783 ps->pixel_type == FF_PIXEL_PLANAR; 00784 } 00785 00786 int av_picture_crop(AVPicture *dst, const AVPicture *src, 00787 enum PixelFormat pix_fmt, int top_band, int left_band) 00788 { 00789 int y_shift; 00790 int x_shift; 00791 00792 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt])) 00793 return -1; 00794 00795 y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h; 00796 x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w; 00797 00798 dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band; 00799 dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift); 00800 dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift); 00801 00802 dst->linesize[0] = src->linesize[0]; 00803 dst->linesize[1] = src->linesize[1]; 00804 dst->linesize[2] = src->linesize[2]; 00805 return 0; 00806 } 00807 00808 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, 00809 enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright, 00810 int *color) 00811 { 00812 uint8_t *optr; 00813 int y_shift; 00814 int x_shift; 00815 int yheight; 00816 int i, y; 00817 00818 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || 00819 !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1; 00820 00821 for (i = 0; i < 3; i++) { 00822 x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0; 00823 y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0; 00824 00825 if (padtop || padleft) { 00826 memset(dst->data[i], color[i], 00827 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift)); 00828 } 00829 00830 if (padleft || padright) { 00831 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + 00832 (dst->linesize[i] - (padright >> x_shift)); 00833 yheight = (height - 1 - (padtop + padbottom)) >> y_shift; 00834 for (y = 0; y < yheight; y++) { 00835 memset(optr, color[i], (padleft + padright) >> x_shift); 00836 optr += dst->linesize[i]; 00837 } 00838 } 00839 00840 if (src) { /* first line */ 00841 uint8_t *iptr = src->data[i]; 00842 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + 00843 (padleft >> x_shift); 00844 memcpy(optr, iptr, (width - padleft - padright) >> x_shift); 00845 iptr += src->linesize[i]; 00846 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + 00847 (dst->linesize[i] - (padright >> x_shift)); 00848 yheight = (height - 1 - (padtop + padbottom)) >> y_shift; 00849 for (y = 0; y < yheight; y++) { 00850 memset(optr, color[i], (padleft + padright) >> x_shift); 00851 memcpy(optr + ((padleft + padright) >> x_shift), iptr, 00852 (width - padleft - padright) >> x_shift); 00853 iptr += src->linesize[i]; 00854 optr += dst->linesize[i]; 00855 } 00856 } 00857 00858 if (padbottom || padright) { 00859 optr = dst->data[i] + dst->linesize[i] * 00860 ((height - padbottom) >> y_shift) - (padright >> x_shift); 00861 memset(optr, color[i],dst->linesize[i] * 00862 (padbottom >> y_shift) + (padright >> x_shift)); 00863 } 00864 } 00865 return 0; 00866 } 00867 00868 /* NOTE: we scan all the pixels to have an exact information */ 00869 static int get_alpha_info_pal8(const AVPicture *src, int width, int height) 00870 { 00871 const unsigned char *p; 00872 int src_wrap, ret, x, y; 00873 unsigned int a; 00874 uint32_t *palette = (uint32_t *)src->data[1]; 00875 00876 p = src->data[0]; 00877 src_wrap = src->linesize[0] - width; 00878 ret = 0; 00879 for(y=0;y<height;y++) { 00880 for(x=0;x<width;x++) { 00881 a = palette[p[0]] >> 24; 00882 if (a == 0x00) { 00883 ret |= FF_ALPHA_TRANSP; 00884 } else if (a != 0xff) { 00885 ret |= FF_ALPHA_SEMI_TRANSP; 00886 } 00887 p++; 00888 } 00889 p += src_wrap; 00890 } 00891 return ret; 00892 } 00893 00894 int img_get_alpha_info(const AVPicture *src, 00895 enum PixelFormat pix_fmt, int width, int height) 00896 { 00897 const PixFmtInfo *pf = &pix_fmt_info[pix_fmt]; 00898 int ret; 00899 00900 /* no alpha can be represented in format */ 00901 if (!pf->is_alpha) 00902 return 0; 00903 switch(pix_fmt) { 00904 case PIX_FMT_PAL8: 00905 ret = get_alpha_info_pal8(src, width, height); 00906 break; 00907 default: 00908 /* we do not know, so everything is indicated */ 00909 ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP; 00910 break; 00911 } 00912 return ret; 00913 } 00914 00915 #if !(HAVE_MMX && HAVE_YASM) 00916 /* filter parameters: [-1 4 2 4 -1] // 8 */ 00917 static void deinterlace_line_c(uint8_t *dst, 00918 const uint8_t *lum_m4, const uint8_t *lum_m3, 00919 const uint8_t *lum_m2, const uint8_t *lum_m1, 00920 const uint8_t *lum, 00921 int size) 00922 { 00923 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; 00924 int sum; 00925 00926 for(;size > 0;size--) { 00927 sum = -lum_m4[0]; 00928 sum += lum_m3[0] << 2; 00929 sum += lum_m2[0] << 1; 00930 sum += lum_m1[0] << 2; 00931 sum += -lum[0]; 00932 dst[0] = cm[(sum + 4) >> 3]; 00933 lum_m4++; 00934 lum_m3++; 00935 lum_m2++; 00936 lum_m1++; 00937 lum++; 00938 dst++; 00939 } 00940 } 00941 00942 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3, 00943 uint8_t *lum_m2, uint8_t *lum_m1, 00944 uint8_t *lum, int size) 00945 { 00946 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; 00947 int sum; 00948 00949 for(;size > 0;size--) { 00950 sum = -lum_m4[0]; 00951 sum += lum_m3[0] << 2; 00952 sum += lum_m2[0] << 1; 00953 lum_m4[0]=lum_m2[0]; 00954 sum += lum_m1[0] << 2; 00955 sum += -lum[0]; 00956 lum_m2[0] = cm[(sum + 4) >> 3]; 00957 lum_m4++; 00958 lum_m3++; 00959 lum_m2++; 00960 lum_m1++; 00961 lum++; 00962 } 00963 } 00964 #endif 00965 00966 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The 00967 top field is copied as is, but the bottom field is deinterlaced 00968 against the top field. */ 00969 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap, 00970 const uint8_t *src1, int src_wrap, 00971 int width, int height) 00972 { 00973 const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2; 00974 int y; 00975 00976 src_m2 = src1; 00977 src_m1 = src1; 00978 src_0=&src_m1[src_wrap]; 00979 src_p1=&src_0[src_wrap]; 00980 src_p2=&src_p1[src_wrap]; 00981 for(y=0;y<(height-2);y+=2) { 00982 memcpy(dst,src_m1,width); 00983 dst += dst_wrap; 00984 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width); 00985 src_m2 = src_0; 00986 src_m1 = src_p1; 00987 src_0 = src_p2; 00988 src_p1 += 2*src_wrap; 00989 src_p2 += 2*src_wrap; 00990 dst += dst_wrap; 00991 } 00992 memcpy(dst,src_m1,width); 00993 dst += dst_wrap; 00994 /* do last line */ 00995 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width); 00996 } 00997 00998 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, 00999 int width, int height) 01000 { 01001 uint8_t *src_m1, *src_0, *src_p1, *src_p2; 01002 int y; 01003 uint8_t *buf; 01004 buf = (uint8_t*)av_malloc(width); 01005 01006 src_m1 = src1; 01007 memcpy(buf,src_m1,width); 01008 src_0=&src_m1[src_wrap]; 01009 src_p1=&src_0[src_wrap]; 01010 src_p2=&src_p1[src_wrap]; 01011 for(y=0;y<(height-2);y+=2) { 01012 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width); 01013 src_m1 = src_p1; 01014 src_0 = src_p2; 01015 src_p1 += 2*src_wrap; 01016 src_p2 += 2*src_wrap; 01017 } 01018 /* do last line */ 01019 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width); 01020 av_free(buf); 01021 } 01022 01023 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, 01024 enum PixelFormat pix_fmt, int width, int height) 01025 { 01026 int i; 01027 01028 if (pix_fmt != PIX_FMT_YUV420P && 01029 pix_fmt != PIX_FMT_YUVJ420P && 01030 pix_fmt != PIX_FMT_YUV422P && 01031 pix_fmt != PIX_FMT_YUVJ422P && 01032 pix_fmt != PIX_FMT_YUV444P && 01033 pix_fmt != PIX_FMT_YUV411P && 01034 pix_fmt != PIX_FMT_GRAY8) 01035 return -1; 01036 if ((width & 3) != 0 || (height & 3) != 0) 01037 return -1; 01038 01039 for(i=0;i<3;i++) { 01040 if (i == 1) { 01041 switch(pix_fmt) { 01042 case PIX_FMT_YUVJ420P: 01043 case PIX_FMT_YUV420P: 01044 width >>= 1; 01045 height >>= 1; 01046 break; 01047 case PIX_FMT_YUV422P: 01048 case PIX_FMT_YUVJ422P: 01049 width >>= 1; 01050 break; 01051 case PIX_FMT_YUV411P: 01052 width >>= 2; 01053 break; 01054 default: 01055 break; 01056 } 01057 if (pix_fmt == PIX_FMT_GRAY8) { 01058 break; 01059 } 01060 } 01061 if (src == dst) { 01062 deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], 01063 width, height); 01064 } else { 01065 deinterlace_bottom_field(dst->data[i],dst->linesize[i], 01066 src->data[i], src->linesize[i], 01067 width, height); 01068 } 01069 } 01070 emms_c(); 01071 return 0; 01072 } 01073