libavcodec/imgconvert.c
Go to the documentation of this file.
00001 /*
00002  * Misc image conversion routines
00003  * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 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 /* this table gives more information about formats */
00065 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
00066     /* YUV formats */
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     /* YUV formats with alpha plane */
00111     [PIX_FMT_YUVA420P] = {
00112         .is_alpha = 1,
00113         .color_type = FF_COLOR_YUV,
00114     },
00115 
00116     /* JPEG YUV */
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     /* RGB formats */
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     /* gray / mono formats */
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     /* paletted formats */
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         // do not include palette for these pseudo-paletted formats
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         // do not include palette for these pseudo-paletted formats
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     /* compute loss */
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         /* fail safe test */
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) /* all losses count (for backward compatibility) */
00481         *loss_ptr = 0;
00482 
00483     dst_pix_fmt = PIX_FMT_NONE; /* so first iteration doesn't have to be treated special */
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, /* no loss first */
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, //non zero entry that combines all loss variants including future additions
00506         0,
00507     };
00508 
00509     loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
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     /* try with successive loss */
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){ /* use format with smallest depth */
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) { /* use format with no loss */
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 /* 2x2 -> 1x1 */
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 /* 4x4 -> 1x1 */
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 /* 8x8 -> 1x1 */
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 /* return true if yuv planar */
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     /* set the used planes */
00656     for (i = 0; i < desc->nb_components; i++)
00657         planes[desc->comp[i].plane] = 1;
00658 
00659     /* if there is an unused plane, the format is not planar */
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) //FIXME add support for this too
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) { /* first line */
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 /* NOTE: we scan all the pixels to have an exact information */
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     /* no alpha can be represented in format */
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         /* we do not know, so everything is indicated */
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 /* filter parameters: [-1 4 2 4 -1] // 8 */
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 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
00857    top field is copied as is, but the bottom field is deinterlaced
00858    against the top field. */
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     /* do last line */
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     /* do last line */
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