• 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 FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 /* TODO:
00028  * - write 'ffimg' program to test all the image related stuff
00029  * - move all api to slice based system
00030  * - integrate deinterlacing, postprocessing and scaling in the conversion process
00031  */
00032 
00033 #include "avcodec.h"
00034 #include "dsputil.h"
00035 #include "internal.h"
00036 #include "imgconvert.h"
00037 #include "libavutil/colorspace.h"
00038 #include "libavutil/pixdesc.h"
00039 #include "libavutil/imgutils.h"
00040 
00041 #if HAVE_MMX && HAVE_YASM
00042 #include "x86/dsputil_mmx.h"
00043 #endif
00044 
00045 #define 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 #if LIBAVCODEC_VERSION_MAJOR < 53
00428 enum PixelFormat avcodec_get_pix_fmt(const char *name)
00429 {
00430     return av_get_pix_fmt(name);
00431 }
00432 
00433 void avcodec_pix_fmt_string (char *buf, int buf_size, enum PixelFormat pix_fmt)
00434 {
00435     av_get_pix_fmt_string(buf, buf_size, pix_fmt);
00436 }
00437 #endif
00438 
00439 int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
00440 {
00441     return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
00442 }
00443 
00444 #if LIBAVCODEC_VERSION_MAJOR < 53
00445 int ff_set_systematic_pal(uint32_t pal[256], enum PixelFormat pix_fmt){
00446     return ff_set_systematic_pal2(pal, pix_fmt);
00447 }
00448 
00449 int ff_fill_linesize(AVPicture *picture, enum PixelFormat pix_fmt, int width)
00450 {
00451     return av_image_fill_linesizes(picture->linesize, pix_fmt, width);
00452 }
00453 
00454 int ff_fill_pointer(AVPicture *picture, uint8_t *ptr, enum PixelFormat pix_fmt,
00455                     int height)
00456 {
00457     return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
00458 }
00459 #endif
00460 
00461 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00462                    enum PixelFormat pix_fmt, int width, int height)
00463 {
00464     int ret;
00465 
00466     if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
00467         return ret;
00468 
00469     if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0)
00470         return ret;
00471 
00472     return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
00473 }
00474 
00475 int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
00476                      unsigned char *dest, int dest_size)
00477 {
00478     int i, j, nb_planes = 0, linesizes[4];
00479     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00480     int size = avpicture_get_size(pix_fmt, width, height);
00481 
00482     if (size > dest_size || size < 0)
00483         return AVERROR(EINVAL);
00484 
00485     for (i = 0; i < desc->nb_components; i++)
00486         nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
00487     nb_planes++;
00488 
00489     av_image_fill_linesizes(linesizes, pix_fmt, width);
00490     for (i = 0; i < nb_planes; i++) {
00491         int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
00492         const unsigned char *s = src->data[i];
00493         h = (height + (1 << shift) - 1) >> shift;
00494 
00495         for (j = 0; j < h; j++) {
00496             memcpy(dest, s, linesizes[i]);
00497             dest += linesizes[i];
00498             s += src->linesize[i];
00499         }
00500     }
00501 
00502     switch (pix_fmt) {
00503     case PIX_FMT_RGB8:
00504     case PIX_FMT_BGR8:
00505     case PIX_FMT_RGB4_BYTE:
00506     case PIX_FMT_BGR4_BYTE:
00507     case PIX_FMT_GRAY8:
00508         // do not include palette for these pseudo-paletted formats
00509         return size;
00510     }
00511 
00512     if (desc->flags & PIX_FMT_PAL)
00513         memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00514 
00515     return size;
00516 }
00517 
00518 int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height)
00519 {
00520     AVPicture dummy_pict;
00521     if(av_image_check_size(width, height, 0, NULL))
00522         return -1;
00523     switch (pix_fmt) {
00524     case PIX_FMT_RGB8:
00525     case PIX_FMT_BGR8:
00526     case PIX_FMT_RGB4_BYTE:
00527     case PIX_FMT_BGR4_BYTE:
00528     case PIX_FMT_GRAY8:
00529         // do not include palette for these pseudo-paletted formats
00530         return width * height;
00531     }
00532     return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00533 }
00534 
00535 int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
00536                              int has_alpha)
00537 {
00538     const PixFmtInfo *pf, *ps;
00539     const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
00540     const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
00541     int loss;
00542 
00543     ps = &pix_fmt_info[src_pix_fmt];
00544 
00545     /* compute loss */
00546     loss = 0;
00547     pf = &pix_fmt_info[dst_pix_fmt];
00548     if (pf->depth < ps->depth ||
00549         ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE ||
00550           dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) &&
00551          (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE ||
00552           src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE)))
00553         loss |= FF_LOSS_DEPTH;
00554     if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
00555         dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
00556         loss |= FF_LOSS_RESOLUTION;
00557     switch(pf->color_type) {
00558     case FF_COLOR_RGB:
00559         if (ps->color_type != FF_COLOR_RGB &&
00560             ps->color_type != FF_COLOR_GRAY)
00561             loss |= FF_LOSS_COLORSPACE;
00562         break;
00563     case FF_COLOR_GRAY:
00564         if (ps->color_type != FF_COLOR_GRAY)
00565             loss |= FF_LOSS_COLORSPACE;
00566         break;
00567     case FF_COLOR_YUV:
00568         if (ps->color_type != FF_COLOR_YUV)
00569             loss |= FF_LOSS_COLORSPACE;
00570         break;
00571     case FF_COLOR_YUV_JPEG:
00572         if (ps->color_type != FF_COLOR_YUV_JPEG &&
00573             ps->color_type != FF_COLOR_YUV &&
00574             ps->color_type != FF_COLOR_GRAY)
00575             loss |= FF_LOSS_COLORSPACE;
00576         break;
00577     default:
00578         /* fail safe test */
00579         if (ps->color_type != pf->color_type)
00580             loss |= FF_LOSS_COLORSPACE;
00581         break;
00582     }
00583     if (pf->color_type == FF_COLOR_GRAY &&
00584         ps->color_type != FF_COLOR_GRAY)
00585         loss |= FF_LOSS_CHROMA;
00586     if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00587         loss |= FF_LOSS_ALPHA;
00588     if (pf->pixel_type == FF_PIXEL_PALETTE &&
00589         (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00590         loss |= FF_LOSS_COLORQUANT;
00591     return loss;
00592 }
00593 
00594 static int avg_bits_per_pixel(enum PixelFormat pix_fmt)
00595 {
00596     int bits;
00597     const PixFmtInfo *pf;
00598     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00599 
00600     pf = &pix_fmt_info[pix_fmt];
00601     switch(pf->pixel_type) {
00602     case FF_PIXEL_PACKED:
00603         switch(pix_fmt) {
00604         case PIX_FMT_YUYV422:
00605         case PIX_FMT_UYVY422:
00606         case PIX_FMT_RGB565BE:
00607         case PIX_FMT_RGB565LE:
00608         case PIX_FMT_RGB555BE:
00609         case PIX_FMT_RGB555LE:
00610         case PIX_FMT_RGB444BE:
00611         case PIX_FMT_RGB444LE:
00612         case PIX_FMT_BGR565BE:
00613         case PIX_FMT_BGR565LE:
00614         case PIX_FMT_BGR555BE:
00615         case PIX_FMT_BGR555LE:
00616         case PIX_FMT_BGR444BE:
00617         case PIX_FMT_BGR444LE:
00618             bits = 16;
00619             break;
00620         case PIX_FMT_UYYVYY411:
00621             bits = 12;
00622             break;
00623         default:
00624             bits = pf->depth * pf->nb_channels;
00625             break;
00626         }
00627         break;
00628     case FF_PIXEL_PLANAR:
00629         if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
00630             bits = pf->depth * pf->nb_channels;
00631         } else {
00632             bits = pf->depth + ((2 * pf->depth) >>
00633                                 (desc->log2_chroma_w + desc->log2_chroma_h));
00634         }
00635         break;
00636     case FF_PIXEL_PALETTE:
00637         bits = 8;
00638         break;
00639     default:
00640         bits = -1;
00641         break;
00642     }
00643     return bits;
00644 }
00645 
00646 static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
00647                                       enum PixelFormat src_pix_fmt,
00648                                       int has_alpha,
00649                                       int loss_mask)
00650 {
00651     int dist, i, loss, min_dist;
00652     enum PixelFormat dst_pix_fmt;
00653 
00654     /* find exact color match with smallest size */
00655     dst_pix_fmt = PIX_FMT_NONE;
00656     min_dist = 0x7fffffff;
00657     for(i = 0;i < PIX_FMT_NB; i++) {
00658         if (pix_fmt_mask & (1ULL << i)) {
00659             loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00660             if (loss == 0) {
00661                 dist = avg_bits_per_pixel(i);
00662                 if (dist < min_dist) {
00663                     min_dist = dist;
00664                     dst_pix_fmt = i;
00665                 }
00666             }
00667         }
00668     }
00669     return dst_pix_fmt;
00670 }
00671 
00672 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
00673                               int has_alpha, int *loss_ptr)
00674 {
00675     enum PixelFormat dst_pix_fmt;
00676     int loss_mask, i;
00677     static const int loss_mask_order[] = {
00678         ~0, /* no loss first */
00679         ~FF_LOSS_ALPHA,
00680         ~FF_LOSS_RESOLUTION,
00681         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00682         ~FF_LOSS_COLORQUANT,
00683         ~FF_LOSS_DEPTH,
00684         0,
00685     };
00686 
00687     /* try with successive loss */
00688     i = 0;
00689     for(;;) {
00690         loss_mask = loss_mask_order[i++];
00691         dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00692                                                  has_alpha, loss_mask);
00693         if (dst_pix_fmt >= 0)
00694             goto found;
00695         if (loss_mask == 0)
00696             break;
00697     }
00698     return PIX_FMT_NONE;
00699  found:
00700     if (loss_ptr)
00701         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00702     return dst_pix_fmt;
00703 }
00704 
00705 #if LIBAVCODEC_VERSION_MAJOR < 53
00706 void ff_img_copy_plane(uint8_t *dst, int dst_wrap,
00707                            const uint8_t *src, int src_wrap,
00708                            int width, int height)
00709 {
00710     av_image_copy_plane(dst, dst_wrap, src, src_wrap, width, height);
00711 }
00712 
00713 int ff_get_plane_bytewidth(enum PixelFormat pix_fmt, int width, int plane)
00714 {
00715     return av_image_get_linesize(pix_fmt, width, plane);
00716 }
00717 
00718 void av_picture_data_copy(uint8_t *dst_data[4], int dst_linesize[4],
00719                           uint8_t *src_data[4], int src_linesize[4],
00720                           enum PixelFormat pix_fmt, int width, int height)
00721 {
00722     av_image_copy(dst_data, dst_linesize, src_data, src_linesize,
00723                   pix_fmt, width, height);
00724 }
00725 #endif
00726 
00727 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00728                      enum PixelFormat pix_fmt, int width, int height)
00729 {
00730     av_image_copy(dst->data, dst->linesize, src->data,
00731                   src->linesize, pix_fmt, width, height);
00732 }
00733 
00734 /* 2x2 -> 1x1 */
00735 void ff_shrink22(uint8_t *dst, int dst_wrap,
00736                      const uint8_t *src, int src_wrap,
00737                      int width, int height)
00738 {
00739     int w;
00740     const uint8_t *s1, *s2;
00741     uint8_t *d;
00742 
00743     for(;height > 0; height--) {
00744         s1 = src;
00745         s2 = s1 + src_wrap;
00746         d = dst;
00747         for(w = width;w >= 4; w-=4) {
00748             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00749             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
00750             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
00751             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
00752             s1 += 8;
00753             s2 += 8;
00754             d += 4;
00755         }
00756         for(;w > 0; w--) {
00757             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
00758             s1 += 2;
00759             s2 += 2;
00760             d++;
00761         }
00762         src += 2 * src_wrap;
00763         dst += dst_wrap;
00764     }
00765 }
00766 
00767 /* 4x4 -> 1x1 */
00768 void ff_shrink44(uint8_t *dst, int dst_wrap,
00769                      const uint8_t *src, int src_wrap,
00770                      int width, int height)
00771 {
00772     int w;
00773     const uint8_t *s1, *s2, *s3, *s4;
00774     uint8_t *d;
00775 
00776     for(;height > 0; height--) {
00777         s1 = src;
00778         s2 = s1 + src_wrap;
00779         s3 = s2 + src_wrap;
00780         s4 = s3 + src_wrap;
00781         d = dst;
00782         for(w = width;w > 0; w--) {
00783             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
00784                     s2[0] + s2[1] + s2[2] + s2[3] +
00785                     s3[0] + s3[1] + s3[2] + s3[3] +
00786                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
00787             s1 += 4;
00788             s2 += 4;
00789             s3 += 4;
00790             s4 += 4;
00791             d++;
00792         }
00793         src += 4 * src_wrap;
00794         dst += dst_wrap;
00795     }
00796 }
00797 
00798 /* 8x8 -> 1x1 */
00799 void ff_shrink88(uint8_t *dst, int dst_wrap,
00800                      const uint8_t *src, int src_wrap,
00801                      int width, int height)
00802 {
00803     int w, i;
00804 
00805     for(;height > 0; height--) {
00806         for(w = width;w > 0; w--) {
00807             int tmp=0;
00808             for(i=0; i<8; i++){
00809                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
00810                 src += src_wrap;
00811             }
00812             *(dst++) = (tmp + 32)>>6;
00813             src += 8 - 8*src_wrap;
00814         }
00815         src += 8*src_wrap - 8*width;
00816         dst += dst_wrap - width;
00817     }
00818 }
00819 
00820 
00821 int avpicture_alloc(AVPicture *picture,
00822                     enum PixelFormat pix_fmt, int width, int height)
00823 {
00824     int ret;
00825 
00826     if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
00827         memset(picture, 0, sizeof(AVPicture));
00828         return ret;
00829     }
00830 
00831     return 0;
00832 }
00833 
00834 void avpicture_free(AVPicture *picture)
00835 {
00836     av_free(picture->data[0]);
00837 }
00838 
00839 /* return true if yuv planar */
00840 static inline int is_yuv_planar(const PixFmtInfo *ps)
00841 {
00842     return (ps->color_type == FF_COLOR_YUV ||
00843             ps->color_type == FF_COLOR_YUV_JPEG) &&
00844         ps->pixel_type == FF_PIXEL_PLANAR;
00845 }
00846 
00847 int av_picture_crop(AVPicture *dst, const AVPicture *src,
00848                     enum PixelFormat pix_fmt, int top_band, int left_band)
00849 {
00850     int y_shift;
00851     int x_shift;
00852 
00853     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
00854         return -1;
00855 
00856     y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00857     x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00858 
00859     if (is_yuv_planar(&pix_fmt_info[pix_fmt])) {
00860     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
00861     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
00862     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
00863     } else{
00864         if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
00865             return -1;
00866         if(left_band) //FIXME add support for this too
00867             return -1;
00868         dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
00869     }
00870 
00871     dst->linesize[0] = src->linesize[0];
00872     dst->linesize[1] = src->linesize[1];
00873     dst->linesize[2] = src->linesize[2];
00874     return 0;
00875 }
00876 
00877 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
00878                    enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
00879             int *color)
00880 {
00881     uint8_t *optr;
00882     int y_shift;
00883     int x_shift;
00884     int yheight;
00885     int i, y;
00886 
00887     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
00888         !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
00889 
00890     for (i = 0; i < 3; i++) {
00891         x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
00892         y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
00893 
00894         if (padtop || padleft) {
00895             memset(dst->data[i], color[i],
00896                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
00897         }
00898 
00899         if (padleft || padright) {
00900             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00901                 (dst->linesize[i] - (padright >> x_shift));
00902             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00903             for (y = 0; y < yheight; y++) {
00904                 memset(optr, color[i], (padleft + padright) >> x_shift);
00905                 optr += dst->linesize[i];
00906             }
00907         }
00908 
00909         if (src) { /* first line */
00910             uint8_t *iptr = src->data[i];
00911             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00912                     (padleft >> x_shift);
00913             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
00914             iptr += src->linesize[i];
00915             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
00916                 (dst->linesize[i] - (padright >> x_shift));
00917             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
00918             for (y = 0; y < yheight; y++) {
00919                 memset(optr, color[i], (padleft + padright) >> x_shift);
00920                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
00921                        (width - padleft - padright) >> x_shift);
00922                 iptr += src->linesize[i];
00923                 optr += dst->linesize[i];
00924             }
00925         }
00926 
00927         if (padbottom || padright) {
00928             optr = dst->data[i] + dst->linesize[i] *
00929                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
00930             memset(optr, color[i],dst->linesize[i] *
00931                 (padbottom >> y_shift) + (padright >> x_shift));
00932         }
00933     }
00934     return 0;
00935 }
00936 
00937 /* NOTE: we scan all the pixels to have an exact information */
00938 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
00939 {
00940     const unsigned char *p;
00941     int src_wrap, ret, x, y;
00942     unsigned int a;
00943     uint32_t *palette = (uint32_t *)src->data[1];
00944 
00945     p = src->data[0];
00946     src_wrap = src->linesize[0] - width;
00947     ret = 0;
00948     for(y=0;y<height;y++) {
00949         for(x=0;x<width;x++) {
00950             a = palette[p[0]] >> 24;
00951             if (a == 0x00) {
00952                 ret |= FF_ALPHA_TRANSP;
00953             } else if (a != 0xff) {
00954                 ret |= FF_ALPHA_SEMI_TRANSP;
00955             }
00956             p++;
00957         }
00958         p += src_wrap;
00959     }
00960     return ret;
00961 }
00962 
00963 int img_get_alpha_info(const AVPicture *src,
00964                        enum PixelFormat pix_fmt, int width, int height)
00965 {
00966     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00967     int ret;
00968 
00969     /* no alpha can be represented in format */
00970     if (!pf->is_alpha)
00971         return 0;
00972     switch(pix_fmt) {
00973     case PIX_FMT_PAL8:
00974         ret = get_alpha_info_pal8(src, width, height);
00975         break;
00976     default:
00977         /* we do not know, so everything is indicated */
00978         ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
00979         break;
00980     }
00981     return ret;
00982 }
00983 
00984 #if !(HAVE_MMX && HAVE_YASM)
00985 /* filter parameters: [-1 4 2 4 -1] // 8 */
00986 static void deinterlace_line_c(uint8_t *dst,
00987                              const uint8_t *lum_m4, const uint8_t *lum_m3,
00988                              const uint8_t *lum_m2, const uint8_t *lum_m1,
00989                              const uint8_t *lum,
00990                              int size)
00991 {
00992     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00993     int sum;
00994 
00995     for(;size > 0;size--) {
00996         sum = -lum_m4[0];
00997         sum += lum_m3[0] << 2;
00998         sum += lum_m2[0] << 1;
00999         sum += lum_m1[0] << 2;
01000         sum += -lum[0];
01001         dst[0] = cm[(sum + 4) >> 3];
01002         lum_m4++;
01003         lum_m3++;
01004         lum_m2++;
01005         lum_m1++;
01006         lum++;
01007         dst++;
01008     }
01009 }
01010 
01011 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
01012                                        uint8_t *lum_m2, uint8_t *lum_m1,
01013                                        uint8_t *lum, int size)
01014 {
01015     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
01016     int sum;
01017 
01018     for(;size > 0;size--) {
01019         sum = -lum_m4[0];
01020         sum += lum_m3[0] << 2;
01021         sum += lum_m2[0] << 1;
01022         lum_m4[0]=lum_m2[0];
01023         sum += lum_m1[0] << 2;
01024         sum += -lum[0];
01025         lum_m2[0] = cm[(sum + 4) >> 3];
01026         lum_m4++;
01027         lum_m3++;
01028         lum_m2++;
01029         lum_m1++;
01030         lum++;
01031     }
01032 }
01033 #endif
01034 
01035 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
01036    top field is copied as is, but the bottom field is deinterlaced
01037    against the top field. */
01038 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
01039                                     const uint8_t *src1, int src_wrap,
01040                                     int width, int height)
01041 {
01042     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
01043     int y;
01044 
01045     src_m2 = src1;
01046     src_m1 = src1;
01047     src_0=&src_m1[src_wrap];
01048     src_p1=&src_0[src_wrap];
01049     src_p2=&src_p1[src_wrap];
01050     for(y=0;y<(height-2);y+=2) {
01051         memcpy(dst,src_m1,width);
01052         dst += dst_wrap;
01053         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
01054         src_m2 = src_0;
01055         src_m1 = src_p1;
01056         src_0 = src_p2;
01057         src_p1 += 2*src_wrap;
01058         src_p2 += 2*src_wrap;
01059         dst += dst_wrap;
01060     }
01061     memcpy(dst,src_m1,width);
01062     dst += dst_wrap;
01063     /* do last line */
01064     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
01065 }
01066 
01067 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
01068                                              int width, int height)
01069 {
01070     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
01071     int y;
01072     uint8_t *buf;
01073     buf = (uint8_t*)av_malloc(width);
01074 
01075     src_m1 = src1;
01076     memcpy(buf,src_m1,width);
01077     src_0=&src_m1[src_wrap];
01078     src_p1=&src_0[src_wrap];
01079     src_p2=&src_p1[src_wrap];
01080     for(y=0;y<(height-2);y+=2) {
01081         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
01082         src_m1 = src_p1;
01083         src_0 = src_p2;
01084         src_p1 += 2*src_wrap;
01085         src_p2 += 2*src_wrap;
01086     }
01087     /* do last line */
01088     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
01089     av_free(buf);
01090 }
01091 
01092 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
01093                           enum PixelFormat pix_fmt, int width, int height)
01094 {
01095     int i;
01096 
01097     if (pix_fmt != PIX_FMT_YUV420P &&
01098         pix_fmt != PIX_FMT_YUVJ420P &&
01099         pix_fmt != PIX_FMT_YUV422P &&
01100         pix_fmt != PIX_FMT_YUVJ422P &&
01101         pix_fmt != PIX_FMT_YUV444P &&
01102         pix_fmt != PIX_FMT_YUV411P &&
01103         pix_fmt != PIX_FMT_GRAY8)
01104         return -1;
01105     if ((width & 3) != 0 || (height & 3) != 0)
01106         return -1;
01107 
01108     for(i=0;i<3;i++) {
01109         if (i == 1) {
01110             switch(pix_fmt) {
01111             case PIX_FMT_YUVJ420P:
01112             case PIX_FMT_YUV420P:
01113                 width >>= 1;
01114                 height >>= 1;
01115                 break;
01116             case PIX_FMT_YUV422P:
01117             case PIX_FMT_YUVJ422P:
01118                 width >>= 1;
01119                 break;
01120             case PIX_FMT_YUV411P:
01121                 width >>= 2;
01122                 break;
01123             default:
01124                 break;
01125             }
01126             if (pix_fmt == PIX_FMT_GRAY8) {
01127                 break;
01128             }
01129         }
01130         if (src == dst) {
01131             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
01132                                  width, height);
01133         } else {
01134             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
01135                                         src->data[i], src->linesize[i],
01136                                         width, height);
01137         }
01138     }
01139     emms_c();
01140     return 0;
01141 }
01142 

Generated on Wed Apr 11 2012 07:31:33 for FFmpeg by  doxygen 1.7.1