Libav 0.7.1
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 Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 /* TODO:
00028  * - write 'ffimg' program to test all the image related stuff
00029  * - move all api to slice based system
00030  * - integrate deinterlacing, postprocessing and scaling in the conversion process
00031  */
00032 
00033 #include "avcodec.h"
00034 #include "dsputil.h"
00035 #include "internal.h"
00036 #include "imgconvert.h"
00037 #include "libavutil/colorspace.h"
00038 #include "libavutil/pixdesc.h"
00039 #include "libavutil/imgutils.h"
00040 
00041 #if HAVE_MMX && HAVE_YASM
00042 #include "x86/dsputil_mmx.h"
00043 #endif
00044 
00045 #define xglue(x, y) x ## y
00046 #define glue(x, y) xglue(x, y)
00047 
00048 #define FF_COLOR_RGB      0 
00049 #define FF_COLOR_GRAY     1 
00050 #define FF_COLOR_YUV      2 
00051 #define FF_COLOR_YUV_JPEG 3 
00053 #define FF_PIXEL_PLANAR   0 
00054 #define FF_PIXEL_PACKED   1 
00055 #define FF_PIXEL_PALETTE  2  
00057 #if HAVE_MMX && HAVE_YASM
00058 #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
00059 #define deinterlace_line         ff_deinterlace_line_mmx
00060 #else
00061 #define deinterlace_line_inplace deinterlace_line_inplace_c
00062 #define deinterlace_line         deinterlace_line_c
00063 #endif
00064 
00065 typedef struct PixFmtInfo {
00066     uint8_t nb_channels;     
00067     uint8_t color_type;      
00068     uint8_t pixel_type;      
00069     uint8_t is_alpha : 1;    
00070     uint8_t depth;           
00071 } PixFmtInfo;
00072 
00073 /* this table gives more information about formats */
00074 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
00075     /* YUV formats */
00076     [PIX_FMT_YUV420P] = {
00077         .nb_channels = 3,
00078         .color_type = FF_COLOR_YUV,
00079         .pixel_type = FF_PIXEL_PLANAR,
00080         .depth = 8,
00081     },
00082     [PIX_FMT_YUV422P] = {
00083         .nb_channels = 3,
00084         .color_type = FF_COLOR_YUV,
00085         .pixel_type = FF_PIXEL_PLANAR,
00086         .depth = 8,
00087     },
00088     [PIX_FMT_YUV444P] = {
00089         .nb_channels = 3,
00090         .color_type = FF_COLOR_YUV,
00091         .pixel_type = FF_PIXEL_PLANAR,
00092         .depth = 8,
00093     },
00094     [PIX_FMT_YUYV422] = {
00095         .nb_channels = 1,
00096         .color_type = FF_COLOR_YUV,
00097         .pixel_type = FF_PIXEL_PACKED,
00098         .depth = 8,
00099     },
00100     [PIX_FMT_UYVY422] = {
00101         .nb_channels = 1,
00102         .color_type = FF_COLOR_YUV,
00103         .pixel_type = FF_PIXEL_PACKED,
00104         .depth = 8,
00105     },
00106     [PIX_FMT_YUV410P] = {
00107         .nb_channels = 3,
00108         .color_type = FF_COLOR_YUV,
00109         .pixel_type = FF_PIXEL_PLANAR,
00110         .depth = 8,
00111     },
00112     [PIX_FMT_YUV411P] = {
00113         .nb_channels = 3,
00114         .color_type = FF_COLOR_YUV,
00115         .pixel_type = FF_PIXEL_PLANAR,
00116         .depth = 8,
00117     },
00118     [PIX_FMT_YUV440P] = {
00119         .nb_channels = 3,
00120         .color_type = FF_COLOR_YUV,
00121         .pixel_type = FF_PIXEL_PLANAR,
00122         .depth = 8,
00123     },
00124     [PIX_FMT_YUV420P16LE] = {
00125         .nb_channels = 3,
00126         .color_type = FF_COLOR_YUV,
00127         .pixel_type = FF_PIXEL_PLANAR,
00128         .depth = 16,
00129     },
00130     [PIX_FMT_YUV422P16LE] = {
00131         .nb_channels = 3,
00132         .color_type = FF_COLOR_YUV,
00133         .pixel_type = FF_PIXEL_PLANAR,
00134         .depth = 16,
00135     },
00136     [PIX_FMT_YUV444P16LE] = {
00137         .nb_channels = 3,
00138         .color_type = FF_COLOR_YUV,
00139         .pixel_type = FF_PIXEL_PLANAR,
00140         .depth = 16,
00141     },
00142     [PIX_FMT_YUV420P16BE] = {
00143         .nb_channels = 3,
00144         .color_type = FF_COLOR_YUV,
00145         .pixel_type = FF_PIXEL_PLANAR,
00146         .depth = 16,
00147     },
00148     [PIX_FMT_YUV422P16BE] = {
00149         .nb_channels = 3,
00150         .color_type = FF_COLOR_YUV,
00151         .pixel_type = FF_PIXEL_PLANAR,
00152         .depth = 16,
00153     },
00154     [PIX_FMT_YUV444P16BE] = {
00155         .nb_channels = 3,
00156         .color_type = FF_COLOR_YUV,
00157         .pixel_type = FF_PIXEL_PLANAR,
00158         .depth = 16,
00159     },
00160 
00161 
00162     /* YUV formats with alpha plane */
00163     [PIX_FMT_YUVA420P] = {
00164         .nb_channels = 4,
00165         .color_type = FF_COLOR_YUV,
00166         .pixel_type = FF_PIXEL_PLANAR,
00167         .depth = 8,
00168     },
00169 
00170     /* JPEG YUV */
00171     [PIX_FMT_YUVJ420P] = {
00172         .nb_channels = 3,
00173         .color_type = FF_COLOR_YUV_JPEG,
00174         .pixel_type = FF_PIXEL_PLANAR,
00175         .depth = 8,
00176     },
00177     [PIX_FMT_YUVJ422P] = {
00178         .nb_channels = 3,
00179         .color_type = FF_COLOR_YUV_JPEG,
00180         .pixel_type = FF_PIXEL_PLANAR,
00181         .depth = 8,
00182     },
00183     [PIX_FMT_YUVJ444P] = {
00184         .nb_channels = 3,
00185         .color_type = FF_COLOR_YUV_JPEG,
00186         .pixel_type = FF_PIXEL_PLANAR,
00187         .depth = 8,
00188     },
00189     [PIX_FMT_YUVJ440P] = {
00190         .nb_channels = 3,
00191         .color_type = FF_COLOR_YUV_JPEG,
00192         .pixel_type = FF_PIXEL_PLANAR,
00193         .depth = 8,
00194     },
00195 
00196     /* RGB formats */
00197     [PIX_FMT_RGB24] = {
00198         .nb_channels = 3,
00199         .color_type = FF_COLOR_RGB,
00200         .pixel_type = FF_PIXEL_PACKED,
00201         .depth = 8,
00202     },
00203     [PIX_FMT_BGR24] = {
00204         .nb_channels = 3,
00205         .color_type = FF_COLOR_RGB,
00206         .pixel_type = FF_PIXEL_PACKED,
00207         .depth = 8,
00208     },
00209     [PIX_FMT_ARGB] = {
00210         .nb_channels = 4, .is_alpha = 1,
00211         .color_type = FF_COLOR_RGB,
00212         .pixel_type = FF_PIXEL_PACKED,
00213         .depth = 8,
00214     },
00215     [PIX_FMT_RGB48BE] = {
00216         .nb_channels = 3,
00217         .color_type = FF_COLOR_RGB,
00218         .pixel_type = FF_PIXEL_PACKED,
00219         .depth = 16,
00220     },
00221     [PIX_FMT_RGB48LE] = {
00222         .nb_channels = 3,
00223         .color_type = FF_COLOR_RGB,
00224         .pixel_type = FF_PIXEL_PACKED,
00225         .depth = 16,
00226     },
00227     [PIX_FMT_RGB565BE] = {
00228         .nb_channels = 3,
00229         .color_type = FF_COLOR_RGB,
00230         .pixel_type = FF_PIXEL_PACKED,
00231         .depth = 5,
00232     },
00233     [PIX_FMT_RGB565LE] = {
00234         .nb_channels = 3,
00235         .color_type = FF_COLOR_RGB,
00236         .pixel_type = FF_PIXEL_PACKED,
00237         .depth = 5,
00238     },
00239     [PIX_FMT_RGB555BE] = {
00240         .nb_channels = 3,
00241         .color_type = FF_COLOR_RGB,
00242         .pixel_type = FF_PIXEL_PACKED,
00243         .depth = 5,
00244     },
00245     [PIX_FMT_RGB555LE] = {
00246         .nb_channels = 3,
00247         .color_type = FF_COLOR_RGB,
00248         .pixel_type = FF_PIXEL_PACKED,
00249         .depth = 5,
00250     },
00251     [PIX_FMT_RGB444BE] = {
00252         .nb_channels = 3,
00253         .color_type = FF_COLOR_RGB,
00254         .pixel_type = FF_PIXEL_PACKED,
00255         .depth = 4,
00256     },
00257     [PIX_FMT_RGB444LE] = {
00258         .nb_channels = 3,
00259         .color_type = FF_COLOR_RGB,
00260         .pixel_type = FF_PIXEL_PACKED,
00261         .depth = 4,
00262     },
00263 
00264     /* gray / mono formats */
00265     [PIX_FMT_GRAY16BE] = {
00266         .nb_channels = 1,
00267         .color_type = FF_COLOR_GRAY,
00268         .pixel_type = FF_PIXEL_PLANAR,
00269         .depth = 16,
00270     },
00271     [PIX_FMT_GRAY16LE] = {
00272         .nb_channels = 1,
00273         .color_type = FF_COLOR_GRAY,
00274         .pixel_type = FF_PIXEL_PLANAR,
00275         .depth = 16,
00276     },
00277     [PIX_FMT_GRAY8] = {
00278         .nb_channels = 1,
00279         .color_type = FF_COLOR_GRAY,
00280         .pixel_type = FF_PIXEL_PLANAR,
00281         .depth = 8,
00282     },
00283     [PIX_FMT_MONOWHITE] = {
00284         .nb_channels = 1,
00285         .color_type = FF_COLOR_GRAY,
00286         .pixel_type = FF_PIXEL_PLANAR,
00287         .depth = 1,
00288     },
00289     [PIX_FMT_MONOBLACK] = {
00290         .nb_channels = 1,
00291         .color_type = FF_COLOR_GRAY,
00292         .pixel_type = FF_PIXEL_PLANAR,
00293         .depth = 1,
00294     },
00295 
00296     /* paletted formats */
00297     [PIX_FMT_PAL8] = {
00298         .nb_channels = 4, .is_alpha = 1,
00299         .color_type = FF_COLOR_RGB,
00300         .pixel_type = FF_PIXEL_PALETTE,
00301         .depth = 8,
00302     },
00303     [PIX_FMT_UYYVYY411] = {
00304         .nb_channels = 1,
00305         .color_type = FF_COLOR_YUV,
00306         .pixel_type = FF_PIXEL_PACKED,
00307         .depth = 8,
00308     },
00309     [PIX_FMT_ABGR] = {
00310         .nb_channels = 4, .is_alpha = 1,
00311         .color_type = FF_COLOR_RGB,
00312         .pixel_type = FF_PIXEL_PACKED,
00313         .depth = 8,
00314     },
00315     [PIX_FMT_BGR565BE] = {
00316         .nb_channels = 3,
00317         .color_type = FF_COLOR_RGB,
00318         .pixel_type = FF_PIXEL_PACKED,
00319         .depth = 5,
00320     },
00321     [PIX_FMT_BGR565LE] = {
00322         .nb_channels = 3,
00323         .color_type = FF_COLOR_RGB,
00324         .pixel_type = FF_PIXEL_PACKED,
00325         .depth = 5,
00326     },
00327     [PIX_FMT_BGR555BE] = {
00328         .nb_channels = 3,
00329         .color_type = FF_COLOR_RGB,
00330         .pixel_type = FF_PIXEL_PACKED,
00331         .depth = 5,
00332     },
00333     [PIX_FMT_BGR555LE] = {
00334         .nb_channels = 3,
00335         .color_type = FF_COLOR_RGB,
00336         .pixel_type = FF_PIXEL_PACKED,
00337         .depth = 5,
00338     },
00339     [PIX_FMT_BGR444BE] = {
00340         .nb_channels = 3,
00341         .color_type = FF_COLOR_RGB,
00342         .pixel_type = FF_PIXEL_PACKED,
00343         .depth = 4,
00344     },
00345     [PIX_FMT_BGR444LE] = {
00346         .nb_channels = 3,
00347         .color_type = FF_COLOR_RGB,
00348         .pixel_type = FF_PIXEL_PACKED,
00349         .depth = 4,
00350     },
00351     [PIX_FMT_RGB8] = {
00352         .nb_channels = 1,
00353         .color_type = FF_COLOR_RGB,
00354         .pixel_type = FF_PIXEL_PACKED,
00355         .depth = 8,
00356     },
00357     [PIX_FMT_RGB4] = {
00358         .nb_channels = 1,
00359         .color_type = FF_COLOR_RGB,
00360         .pixel_type = FF_PIXEL_PACKED,
00361         .depth = 4,
00362     },
00363     [PIX_FMT_RGB4_BYTE] = {
00364         .nb_channels = 1,
00365         .color_type = FF_COLOR_RGB,
00366         .pixel_type = FF_PIXEL_PACKED,
00367         .depth = 8,
00368     },
00369     [PIX_FMT_BGR8] = {
00370         .nb_channels = 1,
00371         .color_type = FF_COLOR_RGB,
00372         .pixel_type = FF_PIXEL_PACKED,
00373         .depth = 8,
00374     },
00375     [PIX_FMT_BGR4] = {
00376         .nb_channels = 1,
00377         .color_type = FF_COLOR_RGB,
00378         .pixel_type = FF_PIXEL_PACKED,
00379         .depth = 4,
00380     },
00381     [PIX_FMT_BGR4_BYTE] = {
00382         .nb_channels = 1,
00383         .color_type = FF_COLOR_RGB,
00384         .pixel_type = FF_PIXEL_PACKED,
00385         .depth = 8,
00386     },
00387     [PIX_FMT_NV12] = {
00388         .nb_channels = 2,
00389         .color_type = FF_COLOR_YUV,
00390         .pixel_type = FF_PIXEL_PLANAR,
00391         .depth = 8,
00392     },
00393     [PIX_FMT_NV21] = {
00394         .nb_channels = 2,
00395         .color_type = FF_COLOR_YUV,
00396         .pixel_type = FF_PIXEL_PLANAR,
00397         .depth = 8,
00398     },
00399 
00400     [PIX_FMT_BGRA] = {
00401         .nb_channels = 4, .is_alpha = 1,
00402         .color_type = FF_COLOR_RGB,
00403         .pixel_type = FF_PIXEL_PACKED,
00404         .depth = 8,
00405     },
00406     [PIX_FMT_RGBA] = {
00407         .nb_channels = 4, .is_alpha = 1,
00408         .color_type = FF_COLOR_RGB,
00409         .pixel_type = FF_PIXEL_PACKED,
00410         .depth = 8,
00411     },
00412 };
00413 
00414 void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift)
00415 {
00416     *h_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00417     *v_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00418 }
00419 
00420 #if FF_API_GET_PIX_FMT_NAME
00421 const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt)
00422 {
00423     return av_get_pix_fmt_name(pix_fmt);
00424 }
00425 #endif
00426 
00427 int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
00428 {
00429     return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
00430 }
00431 
00432 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00433                    enum PixelFormat pix_fmt, int width, int height)
00434 {
00435     int ret;
00436 
00437     if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
00438         return ret;
00439 
00440     if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0)
00441         return ret;
00442 
00443     return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
00444 }
00445 
00446 int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
00447                      unsigned char *dest, int dest_size)
00448 {
00449     int i, j, nb_planes = 0, linesizes[4];
00450     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00451     int size = avpicture_get_size(pix_fmt, width, height);
00452 
00453     if (size > dest_size || size < 0)
00454         return AVERROR(EINVAL);
00455 
00456     for (i = 0; i < desc->nb_components; i++)
00457         nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
00458     nb_planes++;
00459 
00460     av_image_fill_linesizes(linesizes, pix_fmt, width);
00461     for (i = 0; i < nb_planes; i++) {
00462         int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
00463         const unsigned char *s = src->data[i];
00464         h = (height + (1 << shift) - 1) >> shift;
00465 
00466         for (j = 0; j < h; j++) {
00467             memcpy(dest, s, linesizes[i]);
00468             dest += linesizes[i];
00469             s += src->linesize[i];
00470         }
00471     }
00472 
00473     if (desc->flags & PIX_FMT_PAL)
00474         memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00475 
00476     return size;
00477 }
00478 
00479 int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height)
00480 {
00481     AVPicture dummy_pict;
00482     if(av_image_check_size(width, height, 0, NULL))
00483         return -1;
00484     switch (pix_fmt) {
00485     case PIX_FMT_RGB8:
00486     case PIX_FMT_BGR8:
00487     case PIX_FMT_RGB4_BYTE:
00488     case PIX_FMT_BGR4_BYTE:
00489     case PIX_FMT_GRAY8:
00490         // do not include palette for these pseudo-paletted formats
00491         return width * height;
00492     }
00493     return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00494 }
00495 
00496 int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
00497                              int has_alpha)
00498 {
00499     const PixFmtInfo *pf, *ps;
00500     const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
00501     const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
00502     int loss;
00503 
00504     ps = &pix_fmt_info[src_pix_fmt];
00505 
00506     /* compute loss */
00507     loss = 0;
00508     pf = &pix_fmt_info[dst_pix_fmt];
00509     if (pf->depth < ps->depth ||
00510         ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE ||
00511           dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) &&
00512          (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE ||
00513           src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE)))
00514         loss |= FF_LOSS_DEPTH;
00515     if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
00516         dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
00517         loss |= FF_LOSS_RESOLUTION;
00518     switch(pf->color_type) {
00519     case FF_COLOR_RGB:
00520         if (ps->color_type != FF_COLOR_RGB &&
00521             ps->color_type != FF_COLOR_GRAY)
00522             loss |= FF_LOSS_COLORSPACE;
00523         break;
00524     case FF_COLOR_GRAY:
00525         if (ps->color_type != FF_COLOR_GRAY)
00526             loss |= FF_LOSS_COLORSPACE;
00527         break;
00528     case FF_COLOR_YUV:
00529         if (ps->color_type != FF_COLOR_YUV)
00530             loss |= FF_LOSS_COLORSPACE;
00531         break;
00532     case FF_COLOR_YUV_JPEG:
00533         if (ps->color_type != FF_COLOR_YUV_JPEG &&
00534             ps->color_type != FF_COLOR_YUV &&
00535             ps->color_type != FF_COLOR_GRAY)
00536             loss |= FF_LOSS_COLORSPACE;
00537         break;
00538     default:
00539         /* fail safe test */
00540         if (ps->color_type != pf->color_type)
00541             loss |= FF_LOSS_COLORSPACE;
00542         break;
00543     }
00544     if (pf->color_type == FF_COLOR_GRAY &&
00545         ps->color_type != FF_COLOR_GRAY)
00546         loss |= FF_LOSS_CHROMA;
00547     if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00548         loss |= FF_LOSS_ALPHA;
00549     if (pf->pixel_type == FF_PIXEL_PALETTE &&
00550         (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00551         loss |= FF_LOSS_COLORQUANT;
00552     return loss;
00553 }
00554 
00555 static int avg_bits_per_pixel(enum PixelFormat pix_fmt)
00556 {
00557     int bits;
00558     const PixFmtInfo *pf;
00559     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00560 
00561     pf = &pix_fmt_info[pix_fmt];
00562     switch(pf->pixel_type) {
00563     case FF_PIXEL_PACKED:
00564         switch(pix_fmt) {
00565         case PIX_FMT_YUYV422:
00566         case PIX_FMT_UYVY422:
00567         case PIX_FMT_RGB565BE:
00568         case PIX_FMT_RGB565LE:
00569         case PIX_FMT_RGB555BE:
00570         case PIX_FMT_RGB555LE:
00571         case PIX_FMT_RGB444BE:
00572         case PIX_FMT_RGB444LE:
00573         case PIX_FMT_BGR565BE:
00574         case PIX_FMT_BGR565LE:
00575         case PIX_FMT_BGR555BE:
00576         case PIX_FMT_BGR555LE:
00577         case PIX_FMT_BGR444BE:
00578         case PIX_FMT_BGR444LE:
00579             bits = 16;
00580             break;
00581         case PIX_FMT_UYYVYY411:
00582             bits = 12;
00583             break;
00584         default:
00585             bits = pf->depth * pf->nb_channels;
00586             break;
00587         }
00588         break;
00589     case FF_PIXEL_PLANAR:
00590         if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
00591             bits = pf->depth * pf->nb_channels;
00592         } else {
00593             bits = pf->depth + ((2 * pf->depth) >>
00594                                 (desc->log2_chroma_w + desc->log2_chroma_h));
00595         }
00596         break;
00597     case FF_PIXEL_PALETTE:
00598         bits = 8;
00599         break;
00600     default:
00601         bits = -1;
00602         break;
00603     }
00604     return bits;
00605 }
00606 
00607 static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
00608                                       enum PixelFormat src_pix_fmt,
00609                                       int has_alpha,
00610                                       int loss_mask)
00611 {
00612     int dist, i, loss, min_dist;
00613     enum PixelFormat dst_pix_fmt;
00614 
00615     /* find exact color match with smallest size */
00616     dst_pix_fmt = PIX_FMT_NONE;
00617     min_dist = 0x7fffffff;
00618     for(i = 0;i < PIX_FMT_NB; i++) {
00619         if (pix_fmt_mask & (1ULL << i)) {
00620             loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00621             if (loss == 0) {
00622                 dist = avg_bits_per_pixel(i);
00623                 if (dist < min_dist) {
00624                     min_dist = dist;
00625                     dst_pix_fmt = i;
00626                 }
00627             }
00628         }
00629     }
00630     return dst_pix_fmt;
00631 }
00632 
00633 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
00634                               int has_alpha, int *loss_ptr)
00635 {
00636     enum PixelFormat dst_pix_fmt;
00637     int loss_mask, i;
00638     static const int loss_mask_order[] = {
00639         ~0, /* no loss first */
00640         ~FF_LOSS_ALPHA,
00641         ~FF_LOSS_RESOLUTION,
00642         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00643         ~FF_LOSS_COLORQUANT,
00644         ~FF_LOSS_DEPTH,
00645         0,
00646     };
00647 
00648     /* try with successive loss */
00649     i = 0;
00650     for(;;) {
00651         loss_mask = loss_mask_order[i++];
00652         dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00653                                                  has_alpha, loss_mask);
00654         if (dst_pix_fmt >= 0)
00655             goto found;
00656         if (loss_mask == 0)
00657             break;
00658     }
00659     return PIX_FMT_NONE;
00660  found:
00661     if (loss_ptr)
00662         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00663     return dst_pix_fmt;
00664 }
00665 
00666 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00667                      enum PixelFormat pix_fmt, int width, int height)
00668 {
00669     av_image_copy(dst->data, dst->linesize, src->data,
00670                   src->linesize, pix_fmt, width, height);
00671 }
00672 
00673 /* 2x2 -> 1x1 */
00674 void ff_shrink22(uint8_t *dst, int dst_wrap,
00675                      const uint8_t *src, int src_wrap,
00676                      int width, int height)
00677 {
00678     int w;
00679     const uint8_t *s1, *s2;
00680     uint8_t *d;
00681 
00682     for(;height > 0; height--) {
00683         s1 = src;
00684         s2 = s1 + src_wrap;
00685         d = dst;
00686         for(w = width;w >= 4; w-=4) {
00687             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00688             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
00689             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
00690             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
00691             s1 += 8;
00692             s2 += 8;
00693             d += 4;
00694         }
00695         for(;w > 0; w--) {
00696             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00697             s1 += 2;
00698             s2 += 2;
00699             d++;
00700         }
00701         src += 2 * src_wrap;
00702         dst += dst_wrap;
00703     }
00704 }
00705 
00706 /* 4x4 -> 1x1 */
00707 void ff_shrink44(uint8_t *dst, int dst_wrap,
00708                      const uint8_t *src, int src_wrap,
00709                      int width, int height)
00710 {
00711     int w;
00712     const uint8_t *s1, *s2, *s3, *s4;
00713     uint8_t *d;
00714 
00715     for(;height > 0; height--) {
00716         s1 = src;
00717         s2 = s1 + src_wrap;
00718         s3 = s2 + src_wrap;
00719         s4 = s3 + src_wrap;
00720         d = dst;
00721         for(w = width;w > 0; w--) {
00722             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
00723                     s2[0] + s2[1] + s2[2] + s2[3] +
00724                     s3[0] + s3[1] + s3[2] + s3[3] +
00725                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
00726             s1 += 4;
00727             s2 += 4;
00728             s3 += 4;
00729             s4 += 4;
00730             d++;
00731         }
00732         src += 4 * src_wrap;
00733         dst += dst_wrap;
00734     }
00735 }
00736 
00737 /* 8x8 -> 1x1 */
00738 void ff_shrink88(uint8_t *dst, int dst_wrap,
00739                      const uint8_t *src, int src_wrap,
00740                      int width, int height)
00741 {
00742     int w, i;
00743 
00744     for(;height > 0; height--) {
00745         for(w = width;w > 0; w--) {
00746             int tmp=0;
00747             for(i=0; i<8; i++){
00748                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
00749                 src += src_wrap;
00750             }
00751             *(dst++) = (tmp + 32)>>6;
00752             src += 8 - 8*src_wrap;
00753         }
00754         src += 8*src_wrap - 8*width;
00755         dst += dst_wrap - width;
00756     }
00757 }
00758 
00759 
00760 int avpicture_alloc(AVPicture *picture,
00761                     enum PixelFormat pix_fmt, int width, int height)
00762 {
00763     int ret;
00764 
00765     if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
00766         memset(picture, 0, sizeof(AVPicture));
00767         return ret;
00768     }
00769 
00770     return 0;
00771 }
00772 
00773 void avpicture_free(AVPicture *picture)
00774 {
00775     av_free(picture->data[0]);
00776 }
00777 
00778 /* return true if yuv planar */
00779 static inline int is_yuv_planar(const PixFmtInfo *ps)
00780 {
00781     return (ps->color_type == FF_COLOR_YUV ||
00782             ps->color_type == FF_COLOR_YUV_JPEG) &&
00783         ps->pixel_type == FF_PIXEL_PLANAR;
00784 }
00785 
00786 int av_picture_crop(AVPicture *dst, const AVPicture *src,
00787                     enum PixelFormat pix_fmt, int top_band, int left_band)
00788 {
00789     int y_shift;
00790     int x_shift;
00791 
00792     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
00793         return -1;
00794 
00795     y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00796     x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00797 
00798     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
00799     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
00800     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
00801 
00802     dst->linesize[0] = src->linesize[0];
00803     dst->linesize[1] = src->linesize[1];
00804     dst->linesize[2] = src->linesize[2];
00805     return 0;
00806 }
00807 
00808 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
00809                    enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
00810             int *color)
00811 {
00812     uint8_t *optr;
00813     int y_shift;
00814     int x_shift;
00815     int yheight;
00816     int i, y;
00817 
00818     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
00819         !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
00820 
00821     for (i = 0; i < 3; i++) {
00822         x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
00823         y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
00824 
00825         if (padtop || padleft) {
00826             memset(dst->data[i], color[i],
00827                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
00828         }
00829 
00830         if (padleft || padright) {
00831             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00832                 (dst->linesize[i] - (padright >> x_shift));
00833             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00834             for (y = 0; y < yheight; y++) {
00835                 memset(optr, color[i], (padleft + padright) >> x_shift);
00836                 optr += dst->linesize[i];
00837             }
00838         }
00839 
00840         if (src) { /* first line */
00841             uint8_t *iptr = src->data[i];
00842             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00843                     (padleft >> x_shift);
00844             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
00845             iptr += src->linesize[i];
00846             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00847                 (dst->linesize[i] - (padright >> x_shift));
00848             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00849             for (y = 0; y < yheight; y++) {
00850                 memset(optr, color[i], (padleft + padright) >> x_shift);
00851                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
00852                        (width - padleft - padright) >> x_shift);
00853                 iptr += src->linesize[i];
00854                 optr += dst->linesize[i];
00855             }
00856         }
00857 
00858         if (padbottom || padright) {
00859             optr = dst->data[i] + dst->linesize[i] *
00860                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
00861             memset(optr, color[i],dst->linesize[i] *
00862                 (padbottom >> y_shift) + (padright >> x_shift));
00863         }
00864     }
00865     return 0;
00866 }
00867 
00868 /* NOTE: we scan all the pixels to have an exact information */
00869 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
00870 {
00871     const unsigned char *p;
00872     int src_wrap, ret, x, y;
00873     unsigned int a;
00874     uint32_t *palette = (uint32_t *)src->data[1];
00875 
00876     p = src->data[0];
00877     src_wrap = src->linesize[0] - width;
00878     ret = 0;
00879     for(y=0;y<height;y++) {
00880         for(x=0;x<width;x++) {
00881             a = palette[p[0]] >> 24;
00882             if (a == 0x00) {
00883                 ret |= FF_ALPHA_TRANSP;
00884             } else if (a != 0xff) {
00885                 ret |= FF_ALPHA_SEMI_TRANSP;
00886             }
00887             p++;
00888         }
00889         p += src_wrap;
00890     }
00891     return ret;
00892 }
00893 
00894 int img_get_alpha_info(const AVPicture *src,
00895                        enum PixelFormat pix_fmt, int width, int height)
00896 {
00897     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00898     int ret;
00899 
00900     /* no alpha can be represented in format */
00901     if (!pf->is_alpha)
00902         return 0;
00903     switch(pix_fmt) {
00904     case PIX_FMT_PAL8:
00905         ret = get_alpha_info_pal8(src, width, height);
00906         break;
00907     default:
00908         /* we do not know, so everything is indicated */
00909         ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
00910         break;
00911     }
00912     return ret;
00913 }
00914 
00915 #if !(HAVE_MMX && HAVE_YASM)
00916 /* filter parameters: [-1 4 2 4 -1] // 8 */
00917 static void deinterlace_line_c(uint8_t *dst,
00918                              const uint8_t *lum_m4, const uint8_t *lum_m3,
00919                              const uint8_t *lum_m2, const uint8_t *lum_m1,
00920                              const uint8_t *lum,
00921                              int size)
00922 {
00923     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00924     int sum;
00925 
00926     for(;size > 0;size--) {
00927         sum = -lum_m4[0];
00928         sum += lum_m3[0] << 2;
00929         sum += lum_m2[0] << 1;
00930         sum += lum_m1[0] << 2;
00931         sum += -lum[0];
00932         dst[0] = cm[(sum + 4) >> 3];
00933         lum_m4++;
00934         lum_m3++;
00935         lum_m2++;
00936         lum_m1++;
00937         lum++;
00938         dst++;
00939     }
00940 }
00941 
00942 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
00943                                        uint8_t *lum_m2, uint8_t *lum_m1,
00944                                        uint8_t *lum, int size)
00945 {
00946     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00947     int sum;
00948 
00949     for(;size > 0;size--) {
00950         sum = -lum_m4[0];
00951         sum += lum_m3[0] << 2;
00952         sum += lum_m2[0] << 1;
00953         lum_m4[0]=lum_m2[0];
00954         sum += lum_m1[0] << 2;
00955         sum += -lum[0];
00956         lum_m2[0] = cm[(sum + 4) >> 3];
00957         lum_m4++;
00958         lum_m3++;
00959         lum_m2++;
00960         lum_m1++;
00961         lum++;
00962     }
00963 }
00964 #endif
00965 
00966 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
00967    top field is copied as is, but the bottom field is deinterlaced
00968    against the top field. */
00969 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
00970                                     const uint8_t *src1, int src_wrap,
00971                                     int width, int height)
00972 {
00973     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
00974     int y;
00975 
00976     src_m2 = src1;
00977     src_m1 = src1;
00978     src_0=&src_m1[src_wrap];
00979     src_p1=&src_0[src_wrap];
00980     src_p2=&src_p1[src_wrap];
00981     for(y=0;y<(height-2);y+=2) {
00982         memcpy(dst,src_m1,width);
00983         dst += dst_wrap;
00984         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
00985         src_m2 = src_0;
00986         src_m1 = src_p1;
00987         src_0 = src_p2;
00988         src_p1 += 2*src_wrap;
00989         src_p2 += 2*src_wrap;
00990         dst += dst_wrap;
00991     }
00992     memcpy(dst,src_m1,width);
00993     dst += dst_wrap;
00994     /* do last line */
00995     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
00996 }
00997 
00998 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
00999                                              int width, int height)
01000 {
01001     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
01002     int y;
01003     uint8_t *buf;
01004     buf = (uint8_t*)av_malloc(width);
01005 
01006     src_m1 = src1;
01007     memcpy(buf,src_m1,width);
01008     src_0=&src_m1[src_wrap];
01009     src_p1=&src_0[src_wrap];
01010     src_p2=&src_p1[src_wrap];
01011     for(y=0;y<(height-2);y+=2) {
01012         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
01013         src_m1 = src_p1;
01014         src_0 = src_p2;
01015         src_p1 += 2*src_wrap;
01016         src_p2 += 2*src_wrap;
01017     }
01018     /* do last line */
01019     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
01020     av_free(buf);
01021 }
01022 
01023 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
01024                           enum PixelFormat pix_fmt, int width, int height)
01025 {
01026     int i;
01027 
01028     if (pix_fmt != PIX_FMT_YUV420P &&
01029         pix_fmt != PIX_FMT_YUVJ420P &&
01030         pix_fmt != PIX_FMT_YUV422P &&
01031         pix_fmt != PIX_FMT_YUVJ422P &&
01032         pix_fmt != PIX_FMT_YUV444P &&
01033         pix_fmt != PIX_FMT_YUV411P &&
01034         pix_fmt != PIX_FMT_GRAY8)
01035         return -1;
01036     if ((width & 3) != 0 || (height & 3) != 0)
01037         return -1;
01038 
01039     for(i=0;i<3;i++) {
01040         if (i == 1) {
01041             switch(pix_fmt) {
01042             case PIX_FMT_YUVJ420P:
01043             case PIX_FMT_YUV420P:
01044                 width >>= 1;
01045                 height >>= 1;
01046                 break;
01047             case PIX_FMT_YUV422P:
01048             case PIX_FMT_YUVJ422P:
01049                 width >>= 1;
01050                 break;
01051             case PIX_FMT_YUV411P:
01052                 width >>= 2;
01053                 break;
01054             default:
01055                 break;
01056             }
01057             if (pix_fmt == PIX_FMT_GRAY8) {
01058                 break;
01059             }
01060         }
01061         if (src == dst) {
01062             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
01063                                  width, height);
01064         } else {
01065             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
01066                                         src->data[i], src->linesize[i],
01067                                         width, height);
01068         }
01069     }
01070     emms_c();
01071     return 0;
01072 }
01073