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

Generated on Fri Feb 22 2013 07:24:27 for FFmpeg by  doxygen 1.7.1