• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

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     for(i = 0;i < PIX_FMT_NB; i++) {
00616         if (pix_fmt_mask & (1ULL << i)) {
00617             loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00618             if (loss == 0) {
00619                 dist = avg_bits_per_pixel(i);
00620                 if (dist < min_dist) {
00621                     min_dist = dist;
00622                     dst_pix_fmt = i;
00623                 }
00624             }
00625         }
00626     }
00627     return dst_pix_fmt;
00628 }
00629 
00630 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
00631                               int has_alpha, int *loss_ptr)
00632 {
00633     enum PixelFormat dst_pix_fmt;
00634     int loss_mask, i;
00635     static const int loss_mask_order[] = {
00636         ~0, /* no loss first */
00637         ~FF_LOSS_ALPHA,
00638         ~FF_LOSS_RESOLUTION,
00639         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00640         ~FF_LOSS_COLORQUANT,
00641         ~FF_LOSS_DEPTH,
00642         0,
00643     };
00644 
00645     /* try with successive loss */
00646     i = 0;
00647     for(;;) {
00648         loss_mask = loss_mask_order[i++];
00649         dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00650                                                  has_alpha, loss_mask);
00651         if (dst_pix_fmt >= 0)
00652             goto found;
00653         if (loss_mask == 0)
00654             break;
00655     }
00656     return PIX_FMT_NONE;
00657  found:
00658     if (loss_ptr)
00659         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00660     return dst_pix_fmt;
00661 }
00662 
00663 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00664                      enum PixelFormat pix_fmt, int width, int height)
00665 {
00666     av_image_copy(dst->data, dst->linesize, src->data,
00667                   src->linesize, pix_fmt, width, height);
00668 }
00669 
00670 /* 2x2 -> 1x1 */
00671 void ff_shrink22(uint8_t *dst, int dst_wrap,
00672                      const uint8_t *src, int src_wrap,
00673                      int width, int height)
00674 {
00675     int w;
00676     const uint8_t *s1, *s2;
00677     uint8_t *d;
00678 
00679     for(;height > 0; height--) {
00680         s1 = src;
00681         s2 = s1 + src_wrap;
00682         d = dst;
00683         for(w = width;w >= 4; w-=4) {
00684             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00685             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
00686             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
00687             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
00688             s1 += 8;
00689             s2 += 8;
00690             d += 4;
00691         }
00692         for(;w > 0; w--) {
00693             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00694             s1 += 2;
00695             s2 += 2;
00696             d++;
00697         }
00698         src += 2 * src_wrap;
00699         dst += dst_wrap;
00700     }
00701 }
00702 
00703 /* 4x4 -> 1x1 */
00704 void ff_shrink44(uint8_t *dst, int dst_wrap,
00705                      const uint8_t *src, int src_wrap,
00706                      int width, int height)
00707 {
00708     int w;
00709     const uint8_t *s1, *s2, *s3, *s4;
00710     uint8_t *d;
00711 
00712     for(;height > 0; height--) {
00713         s1 = src;
00714         s2 = s1 + src_wrap;
00715         s3 = s2 + src_wrap;
00716         s4 = s3 + src_wrap;
00717         d = dst;
00718         for(w = width;w > 0; w--) {
00719             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
00720                     s2[0] + s2[1] + s2[2] + s2[3] +
00721                     s3[0] + s3[1] + s3[2] + s3[3] +
00722                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
00723             s1 += 4;
00724             s2 += 4;
00725             s3 += 4;
00726             s4 += 4;
00727             d++;
00728         }
00729         src += 4 * src_wrap;
00730         dst += dst_wrap;
00731     }
00732 }
00733 
00734 /* 8x8 -> 1x1 */
00735 void ff_shrink88(uint8_t *dst, int dst_wrap,
00736                      const uint8_t *src, int src_wrap,
00737                      int width, int height)
00738 {
00739     int w, i;
00740 
00741     for(;height > 0; height--) {
00742         for(w = width;w > 0; w--) {
00743             int tmp=0;
00744             for(i=0; i<8; i++){
00745                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
00746                 src += src_wrap;
00747             }
00748             *(dst++) = (tmp + 32)>>6;
00749             src += 8 - 8*src_wrap;
00750         }
00751         src += 8*src_wrap - 8*width;
00752         dst += dst_wrap - width;
00753     }
00754 }
00755 
00756 
00757 int avpicture_alloc(AVPicture *picture,
00758                     enum PixelFormat pix_fmt, int width, int height)
00759 {
00760     int ret;
00761 
00762     if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
00763         memset(picture, 0, sizeof(AVPicture));
00764         return ret;
00765     }
00766 
00767     return 0;
00768 }
00769 
00770 void avpicture_free(AVPicture *picture)
00771 {
00772     av_free(picture->data[0]);
00773 }
00774 
00775 /* return true if yuv planar */
00776 static inline int is_yuv_planar(const PixFmtInfo *ps)
00777 {
00778     return (ps->color_type == FF_COLOR_YUV ||
00779             ps->color_type == FF_COLOR_YUV_JPEG) &&
00780         ps->pixel_type == FF_PIXEL_PLANAR;
00781 }
00782 
00783 int av_picture_crop(AVPicture *dst, const AVPicture *src,
00784                     enum PixelFormat pix_fmt, int top_band, int left_band)
00785 {
00786     int y_shift;
00787     int x_shift;
00788 
00789     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
00790         return -1;
00791 
00792     y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00793     x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00794 
00795     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
00796     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
00797     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
00798 
00799     dst->linesize[0] = src->linesize[0];
00800     dst->linesize[1] = src->linesize[1];
00801     dst->linesize[2] = src->linesize[2];
00802     return 0;
00803 }
00804 
00805 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
00806                    enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
00807             int *color)
00808 {
00809     uint8_t *optr;
00810     int y_shift;
00811     int x_shift;
00812     int yheight;
00813     int i, y;
00814 
00815     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
00816         !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
00817 
00818     for (i = 0; i < 3; i++) {
00819         x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
00820         y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
00821 
00822         if (padtop || padleft) {
00823             memset(dst->data[i], color[i],
00824                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
00825         }
00826 
00827         if (padleft || padright) {
00828             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00829                 (dst->linesize[i] - (padright >> x_shift));
00830             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00831             for (y = 0; y < yheight; y++) {
00832                 memset(optr, color[i], (padleft + padright) >> x_shift);
00833                 optr += dst->linesize[i];
00834             }
00835         }
00836 
00837         if (src) { /* first line */
00838             uint8_t *iptr = src->data[i];
00839             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00840                     (padleft >> x_shift);
00841             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
00842             iptr += src->linesize[i];
00843             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00844                 (dst->linesize[i] - (padright >> x_shift));
00845             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00846             for (y = 0; y < yheight; y++) {
00847                 memset(optr, color[i], (padleft + padright) >> x_shift);
00848                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
00849                        (width - padleft - padright) >> x_shift);
00850                 iptr += src->linesize[i];
00851                 optr += dst->linesize[i];
00852             }
00853         }
00854 
00855         if (padbottom || padright) {
00856             optr = dst->data[i] + dst->linesize[i] *
00857                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
00858             memset(optr, color[i],dst->linesize[i] *
00859                 (padbottom >> y_shift) + (padright >> x_shift));
00860         }
00861     }
00862     return 0;
00863 }
00864 
00865 #if FF_API_GET_ALPHA_INFO
00866 /* NOTE: we scan all the pixels to have an exact information */
00867 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
00868 {
00869     const unsigned char *p;
00870     int src_wrap, ret, x, y;
00871     unsigned int a;
00872     uint32_t *palette = (uint32_t *)src->data[1];
00873 
00874     p = src->data[0];
00875     src_wrap = src->linesize[0] - width;
00876     ret = 0;
00877     for(y=0;y<height;y++) {
00878         for(x=0;x<width;x++) {
00879             a = palette[p[0]] >> 24;
00880             if (a == 0x00) {
00881                 ret |= FF_ALPHA_TRANSP;
00882             } else if (a != 0xff) {
00883                 ret |= FF_ALPHA_SEMI_TRANSP;
00884             }
00885             p++;
00886         }
00887         p += src_wrap;
00888     }
00889     return ret;
00890 }
00891 
00892 int img_get_alpha_info(const AVPicture *src,
00893                        enum PixelFormat pix_fmt, int width, int height)
00894 {
00895     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00896     int ret;
00897 
00898     /* no alpha can be represented in format */
00899     if (!pf->is_alpha)
00900         return 0;
00901     switch(pix_fmt) {
00902     case PIX_FMT_PAL8:
00903         ret = get_alpha_info_pal8(src, width, height);
00904         break;
00905     default:
00906         /* we do not know, so everything is indicated */
00907         ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
00908         break;
00909     }
00910     return ret;
00911 }
00912 #endif
00913 
00914 #if !(HAVE_MMX && HAVE_YASM)
00915 /* filter parameters: [-1 4 2 4 -1] // 8 */
00916 static void deinterlace_line_c(uint8_t *dst,
00917                              const uint8_t *lum_m4, const uint8_t *lum_m3,
00918                              const uint8_t *lum_m2, const uint8_t *lum_m1,
00919                              const uint8_t *lum,
00920                              int size)
00921 {
00922     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00923     int sum;
00924 
00925     for(;size > 0;size--) {
00926         sum = -lum_m4[0];
00927         sum += lum_m3[0] << 2;
00928         sum += lum_m2[0] << 1;
00929         sum += lum_m1[0] << 2;
00930         sum += -lum[0];
00931         dst[0] = cm[(sum + 4) >> 3];
00932         lum_m4++;
00933         lum_m3++;
00934         lum_m2++;
00935         lum_m1++;
00936         lum++;
00937         dst++;
00938     }
00939 }
00940 
00941 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
00942                                        uint8_t *lum_m2, uint8_t *lum_m1,
00943                                        uint8_t *lum, int size)
00944 {
00945     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00946     int sum;
00947 
00948     for(;size > 0;size--) {
00949         sum = -lum_m4[0];
00950         sum += lum_m3[0] << 2;
00951         sum += lum_m2[0] << 1;
00952         lum_m4[0]=lum_m2[0];
00953         sum += lum_m1[0] << 2;
00954         sum += -lum[0];
00955         lum_m2[0] = cm[(sum + 4) >> 3];
00956         lum_m4++;
00957         lum_m3++;
00958         lum_m2++;
00959         lum_m1++;
00960         lum++;
00961     }
00962 }
00963 #endif
00964 
00965 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
00966    top field is copied as is, but the bottom field is deinterlaced
00967    against the top field. */
00968 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
00969                                     const uint8_t *src1, int src_wrap,
00970                                     int width, int height)
00971 {
00972     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
00973     int y;
00974 
00975     src_m2 = src1;
00976     src_m1 = src1;
00977     src_0=&src_m1[src_wrap];
00978     src_p1=&src_0[src_wrap];
00979     src_p2=&src_p1[src_wrap];
00980     for(y=0;y<(height-2);y+=2) {
00981         memcpy(dst,src_m1,width);
00982         dst += dst_wrap;
00983         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
00984         src_m2 = src_0;
00985         src_m1 = src_p1;
00986         src_0 = src_p2;
00987         src_p1 += 2*src_wrap;
00988         src_p2 += 2*src_wrap;
00989         dst += dst_wrap;
00990     }
00991     memcpy(dst,src_m1,width);
00992     dst += dst_wrap;
00993     /* do last line */
00994     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
00995 }
00996 
00997 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
00998                                              int width, int height)
00999 {
01000     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
01001     int y;
01002     uint8_t *buf;
01003     buf = av_malloc(width);
01004 
01005     src_m1 = src1;
01006     memcpy(buf,src_m1,width);
01007     src_0=&src_m1[src_wrap];
01008     src_p1=&src_0[src_wrap];
01009     src_p2=&src_p1[src_wrap];
01010     for(y=0;y<(height-2);y+=2) {
01011         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
01012         src_m1 = src_p1;
01013         src_0 = src_p2;
01014         src_p1 += 2*src_wrap;
01015         src_p2 += 2*src_wrap;
01016     }
01017     /* do last line */
01018     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
01019     av_free(buf);
01020 }
01021 
01022 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
01023                           enum PixelFormat pix_fmt, int width, int height)
01024 {
01025     int i;
01026 
01027     if (pix_fmt != PIX_FMT_YUV420P &&
01028         pix_fmt != PIX_FMT_YUVJ420P &&
01029         pix_fmt != PIX_FMT_YUV422P &&
01030         pix_fmt != PIX_FMT_YUVJ422P &&
01031         pix_fmt != PIX_FMT_YUV444P &&
01032         pix_fmt != PIX_FMT_YUV411P &&
01033         pix_fmt != PIX_FMT_GRAY8)
01034         return -1;
01035     if ((width & 3) != 0 || (height & 3) != 0)
01036         return -1;
01037 
01038     for(i=0;i<3;i++) {
01039         if (i == 1) {
01040             switch(pix_fmt) {
01041             case PIX_FMT_YUVJ420P:
01042             case PIX_FMT_YUV420P:
01043                 width >>= 1;
01044                 height >>= 1;
01045                 break;
01046             case PIX_FMT_YUV422P:
01047             case PIX_FMT_YUVJ422P:
01048                 width >>= 1;
01049                 break;
01050             case PIX_FMT_YUV411P:
01051                 width >>= 2;
01052                 break;
01053             default:
01054                 break;
01055             }
01056             if (pix_fmt == PIX_FMT_GRAY8) {
01057                 break;
01058             }
01059         }
01060         if (src == dst) {
01061             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
01062                                  width, height);
01063         } else {
01064             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
01065                                         src->data[i], src->linesize[i],
01066                                         width, height);
01067         }
01068     }
01069     emms_c();
01070     return 0;
01071 }
01072 
Generated on Sun Apr 22 2012 21:54:01 for Libav by doxygen 1.7.1