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