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