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