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