• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • 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 "colorspace.h"
00036 
00037 #if HAVE_MMX
00038 #include "x86/mmx.h"
00039 #include "x86/dsputil_mmx.h"
00040 #endif
00041 
00042 #define xglue(x, y) x ## y
00043 #define glue(x, y) xglue(x, y)
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 typedef struct PixFmtInfo {
00055     const char *name;
00056     uint8_t nb_channels;     
00057     uint8_t color_type;      
00058     uint8_t pixel_type;      
00059     uint8_t is_alpha : 1;    
00060     uint8_t is_hwaccel : 1;  
00061     uint8_t x_chroma_shift;  
00062     uint8_t y_chroma_shift;  
00063     uint8_t depth;           
00064 } PixFmtInfo;
00065 
00066 /* this table gives more information about formats */
00067 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
00068     /* YUV formats */
00069     [PIX_FMT_YUV420P] = {
00070         .name = "yuv420p",
00071         .nb_channels = 3,
00072         .color_type = FF_COLOR_YUV,
00073         .pixel_type = FF_PIXEL_PLANAR,
00074         .depth = 8,
00075         .x_chroma_shift = 1, .y_chroma_shift = 1,
00076     },
00077     [PIX_FMT_YUV422P] = {
00078         .name = "yuv422p",
00079         .nb_channels = 3,
00080         .color_type = FF_COLOR_YUV,
00081         .pixel_type = FF_PIXEL_PLANAR,
00082         .depth = 8,
00083         .x_chroma_shift = 1, .y_chroma_shift = 0,
00084     },
00085     [PIX_FMT_YUV444P] = {
00086         .name = "yuv444p",
00087         .nb_channels = 3,
00088         .color_type = FF_COLOR_YUV,
00089         .pixel_type = FF_PIXEL_PLANAR,
00090         .depth = 8,
00091         .x_chroma_shift = 0, .y_chroma_shift = 0,
00092     },
00093     [PIX_FMT_YUYV422] = {
00094         .name = "yuyv422",
00095         .nb_channels = 1,
00096         .color_type = FF_COLOR_YUV,
00097         .pixel_type = FF_PIXEL_PACKED,
00098         .depth = 8,
00099         .x_chroma_shift = 1, .y_chroma_shift = 0,
00100     },
00101     [PIX_FMT_UYVY422] = {
00102         .name = "uyvy422",
00103         .nb_channels = 1,
00104         .color_type = FF_COLOR_YUV,
00105         .pixel_type = FF_PIXEL_PACKED,
00106         .depth = 8,
00107         .x_chroma_shift = 1, .y_chroma_shift = 0,
00108     },
00109     [PIX_FMT_YUV410P] = {
00110         .name = "yuv410p",
00111         .nb_channels = 3,
00112         .color_type = FF_COLOR_YUV,
00113         .pixel_type = FF_PIXEL_PLANAR,
00114         .depth = 8,
00115         .x_chroma_shift = 2, .y_chroma_shift = 2,
00116     },
00117     [PIX_FMT_YUV411P] = {
00118         .name = "yuv411p",
00119         .nb_channels = 3,
00120         .color_type = FF_COLOR_YUV,
00121         .pixel_type = FF_PIXEL_PLANAR,
00122         .depth = 8,
00123         .x_chroma_shift = 2, .y_chroma_shift = 0,
00124     },
00125     [PIX_FMT_YUV440P] = {
00126         .name = "yuv440p",
00127         .nb_channels = 3,
00128         .color_type = FF_COLOR_YUV,
00129         .pixel_type = FF_PIXEL_PLANAR,
00130         .depth = 8,
00131         .x_chroma_shift = 0, .y_chroma_shift = 1,
00132     },
00133 
00134     /* YUV formats with alpha plane */
00135     [PIX_FMT_YUVA420P] = {
00136         .name = "yuva420p",
00137         .nb_channels = 4,
00138         .color_type = FF_COLOR_YUV,
00139         .pixel_type = FF_PIXEL_PLANAR,
00140         .depth = 8,
00141         .x_chroma_shift = 1, .y_chroma_shift = 1,
00142     },
00143 
00144     /* JPEG YUV */
00145     [PIX_FMT_YUVJ420P] = {
00146         .name = "yuvj420p",
00147         .nb_channels = 3,
00148         .color_type = FF_COLOR_YUV_JPEG,
00149         .pixel_type = FF_PIXEL_PLANAR,
00150         .depth = 8,
00151         .x_chroma_shift = 1, .y_chroma_shift = 1,
00152     },
00153     [PIX_FMT_YUVJ422P] = {
00154         .name = "yuvj422p",
00155         .nb_channels = 3,
00156         .color_type = FF_COLOR_YUV_JPEG,
00157         .pixel_type = FF_PIXEL_PLANAR,
00158         .depth = 8,
00159         .x_chroma_shift = 1, .y_chroma_shift = 0,
00160     },
00161     [PIX_FMT_YUVJ444P] = {
00162         .name = "yuvj444p",
00163         .nb_channels = 3,
00164         .color_type = FF_COLOR_YUV_JPEG,
00165         .pixel_type = FF_PIXEL_PLANAR,
00166         .depth = 8,
00167         .x_chroma_shift = 0, .y_chroma_shift = 0,
00168     },
00169     [PIX_FMT_YUVJ440P] = {
00170         .name = "yuvj440p",
00171         .nb_channels = 3,
00172         .color_type = FF_COLOR_YUV_JPEG,
00173         .pixel_type = FF_PIXEL_PLANAR,
00174         .depth = 8,
00175         .x_chroma_shift = 0, .y_chroma_shift = 1,
00176     },
00177 
00178     /* RGB formats */
00179     [PIX_FMT_RGB24] = {
00180         .name = "rgb24",
00181         .nb_channels = 3,
00182         .color_type = FF_COLOR_RGB,
00183         .pixel_type = FF_PIXEL_PACKED,
00184         .depth = 8,
00185         .x_chroma_shift = 0, .y_chroma_shift = 0,
00186     },
00187     [PIX_FMT_BGR24] = {
00188         .name = "bgr24",
00189         .nb_channels = 3,
00190         .color_type = FF_COLOR_RGB,
00191         .pixel_type = FF_PIXEL_PACKED,
00192         .depth = 8,
00193         .x_chroma_shift = 0, .y_chroma_shift = 0,
00194     },
00195     [PIX_FMT_RGB32] = {
00196         .name = "rgb32",
00197         .nb_channels = 4, .is_alpha = 1,
00198         .color_type = FF_COLOR_RGB,
00199         .pixel_type = FF_PIXEL_PACKED,
00200         .depth = 8,
00201         .x_chroma_shift = 0, .y_chroma_shift = 0,
00202     },
00203     [PIX_FMT_RGB48BE] = {
00204         .name = "rgb48be",
00205         .nb_channels = 3,
00206         .color_type = FF_COLOR_RGB,
00207         .pixel_type = FF_PIXEL_PACKED,
00208         .depth = 16,
00209         .x_chroma_shift = 0, .y_chroma_shift = 0,
00210     },
00211     [PIX_FMT_RGB48LE] = {
00212         .name = "rgb48le",
00213         .nb_channels = 3,
00214         .color_type = FF_COLOR_RGB,
00215         .pixel_type = FF_PIXEL_PACKED,
00216         .depth = 16,
00217         .x_chroma_shift = 0, .y_chroma_shift = 0,
00218     },
00219     [PIX_FMT_RGB565] = {
00220         .name = "rgb565",
00221         .nb_channels = 3,
00222         .color_type = FF_COLOR_RGB,
00223         .pixel_type = FF_PIXEL_PACKED,
00224         .depth = 5,
00225         .x_chroma_shift = 0, .y_chroma_shift = 0,
00226     },
00227     [PIX_FMT_RGB555] = {
00228         .name = "rgb555",
00229         .nb_channels = 3,
00230         .color_type = FF_COLOR_RGB,
00231         .pixel_type = FF_PIXEL_PACKED,
00232         .depth = 5,
00233         .x_chroma_shift = 0, .y_chroma_shift = 0,
00234     },
00235 
00236     /* gray / mono formats */
00237     [PIX_FMT_GRAY16BE] = {
00238         .name = "gray16be",
00239         .nb_channels = 1,
00240         .color_type = FF_COLOR_GRAY,
00241         .pixel_type = FF_PIXEL_PLANAR,
00242         .depth = 16,
00243     },
00244     [PIX_FMT_GRAY16LE] = {
00245         .name = "gray16le",
00246         .nb_channels = 1,
00247         .color_type = FF_COLOR_GRAY,
00248         .pixel_type = FF_PIXEL_PLANAR,
00249         .depth = 16,
00250     },
00251     [PIX_FMT_GRAY8] = {
00252         .name = "gray",
00253         .nb_channels = 1,
00254         .color_type = FF_COLOR_GRAY,
00255         .pixel_type = FF_PIXEL_PLANAR,
00256         .depth = 8,
00257     },
00258     [PIX_FMT_MONOWHITE] = {
00259         .name = "monow",
00260         .nb_channels = 1,
00261         .color_type = FF_COLOR_GRAY,
00262         .pixel_type = FF_PIXEL_PLANAR,
00263         .depth = 1,
00264     },
00265     [PIX_FMT_MONOBLACK] = {
00266         .name = "monob",
00267         .nb_channels = 1,
00268         .color_type = FF_COLOR_GRAY,
00269         .pixel_type = FF_PIXEL_PLANAR,
00270         .depth = 1,
00271     },
00272 
00273     /* paletted formats */
00274     [PIX_FMT_PAL8] = {
00275         .name = "pal8",
00276         .nb_channels = 4, .is_alpha = 1,
00277         .color_type = FF_COLOR_RGB,
00278         .pixel_type = FF_PIXEL_PALETTE,
00279         .depth = 8,
00280     },
00281     [PIX_FMT_XVMC_MPEG2_MC] = {
00282         .name = "xvmcmc",
00283         .is_hwaccel = 1,
00284     },
00285     [PIX_FMT_XVMC_MPEG2_IDCT] = {
00286         .name = "xvmcidct",
00287         .is_hwaccel = 1,
00288     },
00289     [PIX_FMT_VDPAU_MPEG1] = {
00290         .name = "vdpau_mpeg1",
00291         .is_hwaccel = 1,
00292     },
00293     [PIX_FMT_VDPAU_MPEG2] = {
00294         .name = "vdpau_mpeg2",
00295         .is_hwaccel = 1,
00296     },
00297     [PIX_FMT_VDPAU_H264] = {
00298         .name = "vdpau_h264",
00299         .is_hwaccel = 1,
00300     },
00301     [PIX_FMT_VDPAU_WMV3] = {
00302         .name = "vdpau_wmv3",
00303         .is_hwaccel = 1,
00304     },
00305     [PIX_FMT_VDPAU_VC1] = {
00306         .name = "vdpau_vc1",
00307         .is_hwaccel = 1,
00308     },
00309     [PIX_FMT_UYYVYY411] = {
00310         .name = "uyyvyy411",
00311         .nb_channels = 1,
00312         .color_type = FF_COLOR_YUV,
00313         .pixel_type = FF_PIXEL_PACKED,
00314         .depth = 8,
00315         .x_chroma_shift = 2, .y_chroma_shift = 0,
00316     },
00317     [PIX_FMT_BGR32] = {
00318         .name = "bgr32",
00319         .nb_channels = 4, .is_alpha = 1,
00320         .color_type = FF_COLOR_RGB,
00321         .pixel_type = FF_PIXEL_PACKED,
00322         .depth = 8,
00323         .x_chroma_shift = 0, .y_chroma_shift = 0,
00324     },
00325     [PIX_FMT_BGR565] = {
00326         .name = "bgr565",
00327         .nb_channels = 3,
00328         .color_type = FF_COLOR_RGB,
00329         .pixel_type = FF_PIXEL_PACKED,
00330         .depth = 5,
00331         .x_chroma_shift = 0, .y_chroma_shift = 0,
00332     },
00333     [PIX_FMT_BGR555] = {
00334         .name = "bgr555",
00335         .nb_channels = 3,
00336         .color_type = FF_COLOR_RGB,
00337         .pixel_type = FF_PIXEL_PACKED,
00338         .depth = 5,
00339         .x_chroma_shift = 0, .y_chroma_shift = 0,
00340     },
00341     [PIX_FMT_RGB8] = {
00342         .name = "rgb8",
00343         .nb_channels = 1,
00344         .color_type = FF_COLOR_RGB,
00345         .pixel_type = FF_PIXEL_PACKED,
00346         .depth = 8,
00347         .x_chroma_shift = 0, .y_chroma_shift = 0,
00348     },
00349     [PIX_FMT_RGB4] = {
00350         .name = "rgb4",
00351         .nb_channels = 1,
00352         .color_type = FF_COLOR_RGB,
00353         .pixel_type = FF_PIXEL_PACKED,
00354         .depth = 4,
00355         .x_chroma_shift = 0, .y_chroma_shift = 0,
00356     },
00357     [PIX_FMT_RGB4_BYTE] = {
00358         .name = "rgb4_byte",
00359         .nb_channels = 1,
00360         .color_type = FF_COLOR_RGB,
00361         .pixel_type = FF_PIXEL_PACKED,
00362         .depth = 8,
00363         .x_chroma_shift = 0, .y_chroma_shift = 0,
00364     },
00365     [PIX_FMT_BGR8] = {
00366         .name = "bgr8",
00367         .nb_channels = 1,
00368         .color_type = FF_COLOR_RGB,
00369         .pixel_type = FF_PIXEL_PACKED,
00370         .depth = 8,
00371         .x_chroma_shift = 0, .y_chroma_shift = 0,
00372     },
00373     [PIX_FMT_BGR4] = {
00374         .name = "bgr4",
00375         .nb_channels = 1,
00376         .color_type = FF_COLOR_RGB,
00377         .pixel_type = FF_PIXEL_PACKED,
00378         .depth = 4,
00379         .x_chroma_shift = 0, .y_chroma_shift = 0,
00380     },
00381     [PIX_FMT_BGR4_BYTE] = {
00382         .name = "bgr4_byte",
00383         .nb_channels = 1,
00384         .color_type = FF_COLOR_RGB,
00385         .pixel_type = FF_PIXEL_PACKED,
00386         .depth = 8,
00387         .x_chroma_shift = 0, .y_chroma_shift = 0,
00388     },
00389     [PIX_FMT_NV12] = {
00390         .name = "nv12",
00391         .nb_channels = 2,
00392         .color_type = FF_COLOR_YUV,
00393         .pixel_type = FF_PIXEL_PLANAR,
00394         .depth = 8,
00395         .x_chroma_shift = 1, .y_chroma_shift = 1,
00396     },
00397     [PIX_FMT_NV21] = {
00398         .name = "nv12",
00399         .nb_channels = 2,
00400         .color_type = FF_COLOR_YUV,
00401         .pixel_type = FF_PIXEL_PLANAR,
00402         .depth = 8,
00403         .x_chroma_shift = 1, .y_chroma_shift = 1,
00404     },
00405 
00406     [PIX_FMT_BGR32_1] = {
00407         .name = "bgr32_1",
00408         .nb_channels = 4, .is_alpha = 1,
00409         .color_type = FF_COLOR_RGB,
00410         .pixel_type = FF_PIXEL_PACKED,
00411         .depth = 8,
00412         .x_chroma_shift = 0, .y_chroma_shift = 0,
00413     },
00414     [PIX_FMT_RGB32_1] = {
00415         .name = "rgb32_1",
00416         .nb_channels = 4, .is_alpha = 1,
00417         .color_type = FF_COLOR_RGB,
00418         .pixel_type = FF_PIXEL_PACKED,
00419         .depth = 8,
00420         .x_chroma_shift = 0, .y_chroma_shift = 0,
00421     },
00422 
00423     /* VA API formats */
00424     [PIX_FMT_VAAPI_MOCO] = {
00425         .name = "vaapi_moco",
00426         .is_hwaccel = 1,
00427     },
00428     [PIX_FMT_VAAPI_IDCT] = {
00429         .name = "vaapi_idct",
00430         .is_hwaccel = 1,
00431     },
00432     [PIX_FMT_VAAPI_VLD] = {
00433         .name = "vaapi_vld",
00434         .is_hwaccel = 1,
00435     },
00436 };
00437 
00438 void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
00439 {
00440     *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
00441     *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
00442 }
00443 
00444 const char *avcodec_get_pix_fmt_name(int pix_fmt)
00445 {
00446     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
00447         return NULL;
00448     else
00449         return pix_fmt_info[pix_fmt].name;
00450 }
00451 
00452 enum PixelFormat avcodec_get_pix_fmt(const char* name)
00453 {
00454     int i;
00455 
00456     for (i=0; i < PIX_FMT_NB; i++)
00457          if (!strcmp(pix_fmt_info[i].name, name))
00458              return i;
00459     return PIX_FMT_NONE;
00460 }
00461 
00462 void avcodec_pix_fmt_string (char *buf, int buf_size, int pix_fmt)
00463 {
00464     /* print header */
00465     if (pix_fmt < 0)
00466         snprintf (buf, buf_size,
00467                   "name      " " nb_channels" " depth" " is_alpha"
00468             );
00469     else{
00470         PixFmtInfo info= pix_fmt_info[pix_fmt];
00471 
00472         char is_alpha_char= info.is_alpha ? 'y' : 'n';
00473 
00474         snprintf (buf, buf_size,
00475                   "%-10s" "      %1d     " "   %2d " "     %c   ",
00476                   info.name,
00477                   info.nb_channels,
00478                   info.depth,
00479                   is_alpha_char
00480             );
00481     }
00482 }
00483 
00484 int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
00485 {
00486     return pix_fmt_info[pix_fmt].is_hwaccel;
00487 }
00488 
00489 int ff_set_systematic_pal(uint32_t pal[256], enum PixelFormat pix_fmt){
00490     int i;
00491 
00492     for(i=0; i<256; i++){
00493         int r,g,b;
00494 
00495         switch(pix_fmt) {
00496         case PIX_FMT_RGB8:
00497             r= (i>>5    )*36;
00498             g= ((i>>2)&7)*36;
00499             b= (i&3     )*85;
00500             break;
00501         case PIX_FMT_BGR8:
00502             b= (i>>6    )*85;
00503             g= ((i>>3)&7)*36;
00504             r= (i&7     )*36;
00505             break;
00506         case PIX_FMT_RGB4_BYTE:
00507             r= (i>>3    )*255;
00508             g= ((i>>1)&3)*85;
00509             b= (i&1     )*255;
00510             break;
00511         case PIX_FMT_BGR4_BYTE:
00512             b= (i>>3    )*255;
00513             g= ((i>>1)&3)*85;
00514             r= (i&1     )*255;
00515             break;
00516         case PIX_FMT_GRAY8:
00517             r=b=g= i;
00518             break;
00519         default:
00520             return -1;
00521         }
00522         pal[i] =  b + (g<<8) + (r<<16);
00523     }
00524 
00525     return 0;
00526 }
00527 
00528 int ff_fill_linesize(AVPicture *picture, int pix_fmt, int width)
00529 {
00530     int w2;
00531     const PixFmtInfo *pinfo;
00532 
00533     memset(picture->linesize, 0, sizeof(picture->linesize));
00534 
00535     pinfo = &pix_fmt_info[pix_fmt];
00536     switch(pix_fmt) {
00537     case PIX_FMT_YUV420P:
00538     case PIX_FMT_YUV422P:
00539     case PIX_FMT_YUV444P:
00540     case PIX_FMT_YUV410P:
00541     case PIX_FMT_YUV411P:
00542     case PIX_FMT_YUV440P:
00543     case PIX_FMT_YUVJ420P:
00544     case PIX_FMT_YUVJ422P:
00545     case PIX_FMT_YUVJ444P:
00546     case PIX_FMT_YUVJ440P:
00547         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
00548         picture->linesize[0] = width;
00549         picture->linesize[1] = w2;
00550         picture->linesize[2] = w2;
00551         break;
00552     case PIX_FMT_YUVA420P:
00553         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
00554         picture->linesize[0] = width;
00555         picture->linesize[1] = w2;
00556         picture->linesize[2] = w2;
00557         picture->linesize[3] = width;
00558         break;
00559     case PIX_FMT_NV12:
00560     case PIX_FMT_NV21:
00561         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
00562         picture->linesize[0] = width;
00563         picture->linesize[1] = w2;
00564         break;
00565     case PIX_FMT_RGB24:
00566     case PIX_FMT_BGR24:
00567         picture->linesize[0] = width * 3;
00568         break;
00569     case PIX_FMT_RGB32:
00570     case PIX_FMT_BGR32:
00571     case PIX_FMT_RGB32_1:
00572     case PIX_FMT_BGR32_1:
00573         picture->linesize[0] = width * 4;
00574         break;
00575     case PIX_FMT_RGB48BE:
00576     case PIX_FMT_RGB48LE:
00577         picture->linesize[0] = width * 6;
00578         break;
00579     case PIX_FMT_GRAY16BE:
00580     case PIX_FMT_GRAY16LE:
00581     case PIX_FMT_BGR555:
00582     case PIX_FMT_BGR565:
00583     case PIX_FMT_RGB555:
00584     case PIX_FMT_RGB565:
00585     case PIX_FMT_YUYV422:
00586         picture->linesize[0] = width * 2;
00587         break;
00588     case PIX_FMT_UYVY422:
00589         picture->linesize[0] = width * 2;
00590         break;
00591     case PIX_FMT_UYYVYY411:
00592         picture->linesize[0] = width + width/2;
00593         break;
00594     case PIX_FMT_RGB4:
00595     case PIX_FMT_BGR4:
00596         picture->linesize[0] = width / 2;
00597         break;
00598     case PIX_FMT_MONOWHITE:
00599     case PIX_FMT_MONOBLACK:
00600         picture->linesize[0] = (width + 7) >> 3;
00601         break;
00602     case PIX_FMT_PAL8:
00603     case PIX_FMT_RGB8:
00604     case PIX_FMT_BGR8:
00605     case PIX_FMT_RGB4_BYTE:
00606     case PIX_FMT_BGR4_BYTE:
00607     case PIX_FMT_GRAY8:
00608         picture->linesize[0] = width;
00609         picture->linesize[1] = 4;
00610         break;
00611     default:
00612         return -1;
00613     }
00614     return 0;
00615 }
00616 
00617 int ff_fill_pointer(AVPicture *picture, uint8_t *ptr, int pix_fmt,
00618                     int height)
00619 {
00620     int size, h2, size2;
00621     const PixFmtInfo *pinfo;
00622 
00623     pinfo = &pix_fmt_info[pix_fmt];
00624     size = picture->linesize[0] * height;
00625     switch(pix_fmt) {
00626     case PIX_FMT_YUV420P:
00627     case PIX_FMT_YUV422P:
00628     case PIX_FMT_YUV444P:
00629     case PIX_FMT_YUV410P:
00630     case PIX_FMT_YUV411P:
00631     case PIX_FMT_YUV440P:
00632     case PIX_FMT_YUVJ420P:
00633     case PIX_FMT_YUVJ422P:
00634     case PIX_FMT_YUVJ444P:
00635     case PIX_FMT_YUVJ440P:
00636         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
00637         size2 = picture->linesize[1] * h2;
00638         picture->data[0] = ptr;
00639         picture->data[1] = picture->data[0] + size;
00640         picture->data[2] = picture->data[1] + size2;
00641         picture->data[3] = NULL;
00642         return size + 2 * size2;
00643     case PIX_FMT_YUVA420P:
00644         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
00645         size2 = picture->linesize[1] * h2;
00646         picture->data[0] = ptr;
00647         picture->data[1] = picture->data[0] + size;
00648         picture->data[2] = picture->data[1] + size2;
00649         picture->data[3] = picture->data[1] + size2 + size2;
00650         return 2 * size + 2 * size2;
00651     case PIX_FMT_NV12:
00652     case PIX_FMT_NV21:
00653         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
00654         size2 = picture->linesize[1] * h2 * 2;
00655         picture->data[0] = ptr;
00656         picture->data[1] = picture->data[0] + size;
00657         picture->data[2] = NULL;
00658         picture->data[3] = NULL;
00659         return size + 2 * size2;
00660     case PIX_FMT_RGB24:
00661     case PIX_FMT_BGR24:
00662     case PIX_FMT_RGB32:
00663     case PIX_FMT_BGR32:
00664     case PIX_FMT_RGB32_1:
00665     case PIX_FMT_BGR32_1:
00666     case PIX_FMT_RGB48BE:
00667     case PIX_FMT_RGB48LE:
00668     case PIX_FMT_GRAY16BE:
00669     case PIX_FMT_GRAY16LE:
00670     case PIX_FMT_BGR555:
00671     case PIX_FMT_BGR565:
00672     case PIX_FMT_RGB555:
00673     case PIX_FMT_RGB565:
00674     case PIX_FMT_YUYV422:
00675     case PIX_FMT_UYVY422:
00676     case PIX_FMT_UYYVYY411:
00677     case PIX_FMT_RGB4:
00678     case PIX_FMT_BGR4:
00679     case PIX_FMT_MONOWHITE:
00680     case PIX_FMT_MONOBLACK:
00681         picture->data[0] = ptr;
00682         picture->data[1] = NULL;
00683         picture->data[2] = NULL;
00684         picture->data[3] = NULL;
00685         return size;
00686     case PIX_FMT_PAL8:
00687     case PIX_FMT_RGB8:
00688     case PIX_FMT_BGR8:
00689     case PIX_FMT_RGB4_BYTE:
00690     case PIX_FMT_BGR4_BYTE:
00691     case PIX_FMT_GRAY8:
00692         size2 = (size + 3) & ~3;
00693         picture->data[0] = ptr;
00694         picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
00695         picture->data[2] = NULL;
00696         picture->data[3] = NULL;
00697         return size2 + 256 * 4;
00698     default:
00699         picture->data[0] = NULL;
00700         picture->data[1] = NULL;
00701         picture->data[2] = NULL;
00702         picture->data[3] = NULL;
00703         return -1;
00704     }
00705 }
00706 
00707 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00708                    int pix_fmt, int width, int height)
00709 {
00710 
00711     if(avcodec_check_dimensions(NULL, width, height))
00712         return -1;
00713 
00714     if (ff_fill_linesize(picture, pix_fmt, width))
00715         return -1;
00716 
00717     return ff_fill_pointer(picture, ptr, pix_fmt, height);
00718 }
00719 
00720 int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
00721                      unsigned char *dest, int dest_size)
00722 {
00723     const PixFmtInfo* pf = &pix_fmt_info[pix_fmt];
00724     int i, j, w, ow, h, oh, data_planes;
00725     const unsigned char* s;
00726     int size = avpicture_get_size(pix_fmt, width, height);
00727 
00728     if (size > dest_size || size < 0)
00729         return -1;
00730 
00731     if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
00732         if (pix_fmt == PIX_FMT_YUYV422 ||
00733             pix_fmt == PIX_FMT_UYVY422 ||
00734             pix_fmt == PIX_FMT_BGR565 ||
00735             pix_fmt == PIX_FMT_BGR555 ||
00736             pix_fmt == PIX_FMT_RGB565 ||
00737             pix_fmt == PIX_FMT_RGB555)
00738             w = width * 2;
00739         else if (pix_fmt == PIX_FMT_UYYVYY411)
00740           w = width + width/2;
00741         else if (pix_fmt == PIX_FMT_PAL8)
00742           w = width;
00743         else
00744           w = width * (pf->depth * pf->nb_channels / 8);
00745 
00746         data_planes = 1;
00747         h = height;
00748     } else {
00749         data_planes = pf->nb_channels;
00750         w = (width*pf->depth + 7)/8;
00751         h = height;
00752     }
00753 
00754     ow = w;
00755     oh = h;
00756 
00757     for (i=0; i<data_planes; i++) {
00758          if (i == 1) {
00759              w = width >> pf->x_chroma_shift;
00760              h = height >> pf->y_chroma_shift;
00761          } else if (i == 3) {
00762              w = ow;
00763              h = oh;
00764          }
00765          s = src->data[i];
00766          for(j=0; j<h; j++) {
00767              memcpy(dest, s, w);
00768              dest += w;
00769              s += src->linesize[i];
00770          }
00771     }
00772 
00773     if (pf->pixel_type == FF_PIXEL_PALETTE)
00774         memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00775 
00776     return size;
00777 }
00778 
00779 int avpicture_get_size(int pix_fmt, int width, int height)
00780 {
00781     AVPicture dummy_pict;
00782     return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00783 }
00784 
00785 int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
00786                              int has_alpha)
00787 {
00788     const PixFmtInfo *pf, *ps;
00789     int loss;
00790 
00791     ps = &pix_fmt_info[src_pix_fmt];
00792     pf = &pix_fmt_info[dst_pix_fmt];
00793 
00794     /* compute loss */
00795     loss = 0;
00796     pf = &pix_fmt_info[dst_pix_fmt];
00797     if (pf->depth < ps->depth ||
00798         (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
00799         loss |= FF_LOSS_DEPTH;
00800     if (pf->x_chroma_shift > ps->x_chroma_shift ||
00801         pf->y_chroma_shift > ps->y_chroma_shift)
00802         loss |= FF_LOSS_RESOLUTION;
00803     switch(pf->color_type) {
00804     case FF_COLOR_RGB:
00805         if (ps->color_type != FF_COLOR_RGB &&
00806             ps->color_type != FF_COLOR_GRAY)
00807             loss |= FF_LOSS_COLORSPACE;
00808         break;
00809     case FF_COLOR_GRAY:
00810         if (ps->color_type != FF_COLOR_GRAY)
00811             loss |= FF_LOSS_COLORSPACE;
00812         break;
00813     case FF_COLOR_YUV:
00814         if (ps->color_type != FF_COLOR_YUV)
00815             loss |= FF_LOSS_COLORSPACE;
00816         break;
00817     case FF_COLOR_YUV_JPEG:
00818         if (ps->color_type != FF_COLOR_YUV_JPEG &&
00819             ps->color_type != FF_COLOR_YUV &&
00820             ps->color_type != FF_COLOR_GRAY)
00821             loss |= FF_LOSS_COLORSPACE;
00822         break;
00823     default:
00824         /* fail safe test */
00825         if (ps->color_type != pf->color_type)
00826             loss |= FF_LOSS_COLORSPACE;
00827         break;
00828     }
00829     if (pf->color_type == FF_COLOR_GRAY &&
00830         ps->color_type != FF_COLOR_GRAY)
00831         loss |= FF_LOSS_CHROMA;
00832     if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00833         loss |= FF_LOSS_ALPHA;
00834     if (pf->pixel_type == FF_PIXEL_PALETTE &&
00835         (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00836         loss |= FF_LOSS_COLORQUANT;
00837     return loss;
00838 }
00839 
00840 static int avg_bits_per_pixel(int pix_fmt)
00841 {
00842     int bits;
00843     const PixFmtInfo *pf;
00844 
00845     pf = &pix_fmt_info[pix_fmt];
00846     switch(pf->pixel_type) {
00847     case FF_PIXEL_PACKED:
00848         switch(pix_fmt) {
00849         case PIX_FMT_YUYV422:
00850         case PIX_FMT_UYVY422:
00851         case PIX_FMT_RGB565:
00852         case PIX_FMT_RGB555:
00853         case PIX_FMT_BGR565:
00854         case PIX_FMT_BGR555:
00855             bits = 16;
00856             break;
00857         case PIX_FMT_UYYVYY411:
00858             bits = 12;
00859             break;
00860         default:
00861             bits = pf->depth * pf->nb_channels;
00862             break;
00863         }
00864         break;
00865     case FF_PIXEL_PLANAR:
00866         if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
00867             bits = pf->depth * pf->nb_channels;
00868         } else {
00869             bits = pf->depth + ((2 * pf->depth) >>
00870                                 (pf->x_chroma_shift + pf->y_chroma_shift));
00871         }
00872         break;
00873     case FF_PIXEL_PALETTE:
00874         bits = 8;
00875         break;
00876     default:
00877         bits = -1;
00878         break;
00879     }
00880     return bits;
00881 }
00882 
00883 static int avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
00884                                       int src_pix_fmt,
00885                                       int has_alpha,
00886                                       int loss_mask)
00887 {
00888     int dist, i, loss, min_dist, dst_pix_fmt;
00889 
00890     /* find exact color match with smallest size */
00891     dst_pix_fmt = -1;
00892     min_dist = 0x7fffffff;
00893     /* test only the first 64 pixel formats to avoid undefined behaviour */
00894     for (i = 0; i < 64; i++) {
00895         if (pix_fmt_mask & (1ULL << i)) {
00896             loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00897             if (loss == 0) {
00898                 dist = avg_bits_per_pixel(i);
00899                 if (dist < min_dist) {
00900                     min_dist = dist;
00901                     dst_pix_fmt = i;
00902                 }
00903             }
00904         }
00905     }
00906     return dst_pix_fmt;
00907 }
00908 
00909 int avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, int src_pix_fmt,
00910                               int has_alpha, int *loss_ptr)
00911 {
00912     int dst_pix_fmt, loss_mask, i;
00913     static const int loss_mask_order[] = {
00914         ~0, /* no loss first */
00915         ~FF_LOSS_ALPHA,
00916         ~FF_LOSS_RESOLUTION,
00917         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00918         ~FF_LOSS_COLORQUANT,
00919         ~FF_LOSS_DEPTH,
00920         0,
00921     };
00922 
00923     /* try with successive loss */
00924     i = 0;
00925     for(;;) {
00926         loss_mask = loss_mask_order[i++];
00927         dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00928                                                  has_alpha, loss_mask);
00929         if (dst_pix_fmt >= 0)
00930             goto found;
00931         if (loss_mask == 0)
00932             break;
00933     }
00934     return -1;
00935  found:
00936     if (loss_ptr)
00937         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00938     return dst_pix_fmt;
00939 }
00940 
00941 void ff_img_copy_plane(uint8_t *dst, int dst_wrap,
00942                            const uint8_t *src, int src_wrap,
00943                            int width, int height)
00944 {
00945     if((!dst) || (!src))
00946         return;
00947     for(;height > 0; height--) {
00948         memcpy(dst, src, width);
00949         dst += dst_wrap;
00950         src += src_wrap;
00951     }
00952 }
00953 
00954 int ff_get_plane_bytewidth(enum PixelFormat pix_fmt, int width, int plane)
00955 {
00956     int bits;
00957     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00958 
00959     pf = &pix_fmt_info[pix_fmt];
00960     switch(pf->pixel_type) {
00961     case FF_PIXEL_PACKED:
00962         switch(pix_fmt) {
00963         case PIX_FMT_YUYV422:
00964         case PIX_FMT_UYVY422:
00965         case PIX_FMT_RGB565:
00966         case PIX_FMT_RGB555:
00967         case PIX_FMT_BGR565:
00968         case PIX_FMT_BGR555:
00969             bits = 16;
00970             break;
00971         case PIX_FMT_UYYVYY411:
00972             bits = 12;
00973             break;
00974         default:
00975             bits = pf->depth * pf->nb_channels;
00976             break;
00977         }
00978         return (width * bits + 7) >> 3;
00979         break;
00980     case FF_PIXEL_PLANAR:
00981             if (plane == 1 || plane == 2)
00982                 width= -((-width)>>pf->x_chroma_shift);
00983 
00984             return (width * pf->depth + 7) >> 3;
00985         break;
00986     case FF_PIXEL_PALETTE:
00987         if (plane == 0)
00988             return width;
00989         break;
00990     }
00991 
00992     return -1;
00993 }
00994 
00995 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00996               int pix_fmt, int width, int height)
00997 {
00998     int i;
00999     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
01000 
01001     pf = &pix_fmt_info[pix_fmt];
01002     switch(pf->pixel_type) {
01003     case FF_PIXEL_PACKED:
01004     case FF_PIXEL_PLANAR:
01005         for(i = 0; i < pf->nb_channels; i++) {
01006             int h;
01007             int bwidth = ff_get_plane_bytewidth(pix_fmt, width, i);
01008             h = height;
01009             if (i == 1 || i == 2) {
01010                 h= -((-height)>>pf->y_chroma_shift);
01011             }
01012             ff_img_copy_plane(dst->data[i], dst->linesize[i],
01013                            src->data[i], src->linesize[i],
01014                            bwidth, h);
01015         }
01016         break;
01017     case FF_PIXEL_PALETTE:
01018         ff_img_copy_plane(dst->data[0], dst->linesize[0],
01019                        src->data[0], src->linesize[0],
01020                        width, height);
01021         /* copy the palette */
01022         ff_img_copy_plane(dst->data[1], dst->linesize[1],
01023                        src->data[1], src->linesize[1],
01024                        4, 256);
01025         break;
01026     }
01027 }
01028 
01029 /* XXX: totally non optimized */
01030 
01031 static void yuyv422_to_yuv420p(AVPicture *dst, const AVPicture *src,
01032                               int width, int height)
01033 {
01034     const uint8_t *p, *p1;
01035     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01036     int w;
01037 
01038     p1 = src->data[0];
01039     lum1 = dst->data[0];
01040     cb1 = dst->data[1];
01041     cr1 = dst->data[2];
01042 
01043     for(;height >= 1; height -= 2) {
01044         p = p1;
01045         lum = lum1;
01046         cb = cb1;
01047         cr = cr1;
01048         for(w = width; w >= 2; w -= 2) {
01049             lum[0] = p[0];
01050             cb[0] = p[1];
01051             lum[1] = p[2];
01052             cr[0] = p[3];
01053             p += 4;
01054             lum += 2;
01055             cb++;
01056             cr++;
01057         }
01058         if (w) {
01059             lum[0] = p[0];
01060             cb[0] = p[1];
01061             cr[0] = p[3];
01062             cb++;
01063             cr++;
01064         }
01065         p1 += src->linesize[0];
01066         lum1 += dst->linesize[0];
01067         if (height>1) {
01068             p = p1;
01069             lum = lum1;
01070             for(w = width; w >= 2; w -= 2) {
01071                 lum[0] = p[0];
01072                 lum[1] = p[2];
01073                 p += 4;
01074                 lum += 2;
01075             }
01076             if (w) {
01077                 lum[0] = p[0];
01078             }
01079             p1 += src->linesize[0];
01080             lum1 += dst->linesize[0];
01081         }
01082         cb1 += dst->linesize[1];
01083         cr1 += dst->linesize[2];
01084     }
01085 }
01086 
01087 static void uyvy422_to_yuv420p(AVPicture *dst, const AVPicture *src,
01088                               int width, int height)
01089 {
01090     const uint8_t *p, *p1;
01091     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01092     int w;
01093 
01094     p1 = src->data[0];
01095 
01096     lum1 = dst->data[0];
01097     cb1 = dst->data[1];
01098     cr1 = dst->data[2];
01099 
01100     for(;height >= 1; height -= 2) {
01101         p = p1;
01102         lum = lum1;
01103         cb = cb1;
01104         cr = cr1;
01105         for(w = width; w >= 2; w -= 2) {
01106             lum[0] = p[1];
01107             cb[0] = p[0];
01108             lum[1] = p[3];
01109             cr[0] = p[2];
01110             p += 4;
01111             lum += 2;
01112             cb++;
01113             cr++;
01114         }
01115         if (w) {
01116             lum[0] = p[1];
01117             cb[0] = p[0];
01118             cr[0] = p[2];
01119             cb++;
01120             cr++;
01121         }
01122         p1 += src->linesize[0];
01123         lum1 += dst->linesize[0];
01124         if (height>1) {
01125             p = p1;
01126             lum = lum1;
01127             for(w = width; w >= 2; w -= 2) {
01128                 lum[0] = p[1];
01129                 lum[1] = p[3];
01130                 p += 4;
01131                 lum += 2;
01132             }
01133             if (w) {
01134                 lum[0] = p[1];
01135             }
01136             p1 += src->linesize[0];
01137             lum1 += dst->linesize[0];
01138         }
01139         cb1 += dst->linesize[1];
01140         cr1 += dst->linesize[2];
01141     }
01142 }
01143 
01144 
01145 static void uyvy422_to_yuv422p(AVPicture *dst, const AVPicture *src,
01146                               int width, int height)
01147 {
01148     const uint8_t *p, *p1;
01149     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01150     int w;
01151 
01152     p1 = src->data[0];
01153     lum1 = dst->data[0];
01154     cb1 = dst->data[1];
01155     cr1 = dst->data[2];
01156     for(;height > 0; height--) {
01157         p = p1;
01158         lum = lum1;
01159         cb = cb1;
01160         cr = cr1;
01161         for(w = width; w >= 2; w -= 2) {
01162             lum[0] = p[1];
01163             cb[0] = p[0];
01164             lum[1] = p[3];
01165             cr[0] = p[2];
01166             p += 4;
01167             lum += 2;
01168             cb++;
01169             cr++;
01170         }
01171         p1 += src->linesize[0];
01172         lum1 += dst->linesize[0];
01173         cb1 += dst->linesize[1];
01174         cr1 += dst->linesize[2];
01175     }
01176 }
01177 
01178 
01179 static void yuyv422_to_yuv422p(AVPicture *dst, const AVPicture *src,
01180                               int width, int height)
01181 {
01182     const uint8_t *p, *p1;
01183     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01184     int w;
01185 
01186     p1 = src->data[0];
01187     lum1 = dst->data[0];
01188     cb1 = dst->data[1];
01189     cr1 = dst->data[2];
01190     for(;height > 0; height--) {
01191         p = p1;
01192         lum = lum1;
01193         cb = cb1;
01194         cr = cr1;
01195         for(w = width; w >= 2; w -= 2) {
01196             lum[0] = p[0];
01197             cb[0] = p[1];
01198             lum[1] = p[2];
01199             cr[0] = p[3];
01200             p += 4;
01201             lum += 2;
01202             cb++;
01203             cr++;
01204         }
01205         p1 += src->linesize[0];
01206         lum1 += dst->linesize[0];
01207         cb1 += dst->linesize[1];
01208         cr1 += dst->linesize[2];
01209     }
01210 }
01211 
01212 static void yuv422p_to_yuyv422(AVPicture *dst, const AVPicture *src,
01213                               int width, int height)
01214 {
01215     uint8_t *p, *p1;
01216     const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01217     int w;
01218 
01219     p1 = dst->data[0];
01220     lum1 = src->data[0];
01221     cb1 = src->data[1];
01222     cr1 = src->data[2];
01223     for(;height > 0; height--) {
01224         p = p1;
01225         lum = lum1;
01226         cb = cb1;
01227         cr = cr1;
01228         for(w = width; w >= 2; w -= 2) {
01229             p[0] = lum[0];
01230             p[1] = cb[0];
01231             p[2] = lum[1];
01232             p[3] = cr[0];
01233             p += 4;
01234             lum += 2;
01235             cb++;
01236             cr++;
01237         }
01238         p1 += dst->linesize[0];
01239         lum1 += src->linesize[0];
01240         cb1 += src->linesize[1];
01241         cr1 += src->linesize[2];
01242     }
01243 }
01244 
01245 static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src,
01246                               int width, int height)
01247 {
01248     uint8_t *p, *p1;
01249     const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01250     int w;
01251 
01252     p1 = dst->data[0];
01253     lum1 = src->data[0];
01254     cb1 = src->data[1];
01255     cr1 = src->data[2];
01256     for(;height > 0; height--) {
01257         p = p1;
01258         lum = lum1;
01259         cb = cb1;
01260         cr = cr1;
01261         for(w = width; w >= 2; w -= 2) {
01262             p[1] = lum[0];
01263             p[0] = cb[0];
01264             p[3] = lum[1];
01265             p[2] = cr[0];
01266             p += 4;
01267             lum += 2;
01268             cb++;
01269             cr++;
01270         }
01271         p1 += dst->linesize[0];
01272         lum1 += src->linesize[0];
01273         cb1 += src->linesize[1];
01274         cr1 += src->linesize[2];
01275     }
01276 }
01277 
01278 static void uyyvyy411_to_yuv411p(AVPicture *dst, const AVPicture *src,
01279                               int width, int height)
01280 {
01281     const uint8_t *p, *p1;
01282     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01283     int w;
01284 
01285     p1 = src->data[0];
01286     lum1 = dst->data[0];
01287     cb1 = dst->data[1];
01288     cr1 = dst->data[2];
01289     for(;height > 0; height--) {
01290         p = p1;
01291         lum = lum1;
01292         cb = cb1;
01293         cr = cr1;
01294         for(w = width; w >= 4; w -= 4) {
01295             cb[0] = p[0];
01296             lum[0] = p[1];
01297             lum[1] = p[2];
01298             cr[0] = p[3];
01299             lum[2] = p[4];
01300             lum[3] = p[5];
01301             p += 6;
01302             lum += 4;
01303             cb++;
01304             cr++;
01305         }
01306         p1 += src->linesize[0];
01307         lum1 += dst->linesize[0];
01308         cb1 += dst->linesize[1];
01309         cr1 += dst->linesize[2];
01310     }
01311 }
01312 
01313 
01314 static void yuv420p_to_yuyv422(AVPicture *dst, const AVPicture *src,
01315                               int width, int height)
01316 {
01317     int w, h;
01318     uint8_t *line1, *line2, *linesrc = dst->data[0];
01319     uint8_t *lum1, *lum2, *lumsrc = src->data[0];
01320     uint8_t *cb1, *cb2 = src->data[1];
01321     uint8_t *cr1, *cr2 = src->data[2];
01322 
01323     for(h = height / 2; h--;) {
01324         line1 = linesrc;
01325         line2 = linesrc + dst->linesize[0];
01326 
01327         lum1 = lumsrc;
01328         lum2 = lumsrc + src->linesize[0];
01329 
01330         cb1 = cb2;
01331         cr1 = cr2;
01332 
01333         for(w = width / 2; w--;) {
01334                 *line1++ = *lum1++; *line2++ = *lum2++;
01335                 *line1++ =          *line2++ = *cb1++;
01336                 *line1++ = *lum1++; *line2++ = *lum2++;
01337                 *line1++ =          *line2++ = *cr1++;
01338         }
01339 
01340         linesrc += dst->linesize[0] * 2;
01341         lumsrc += src->linesize[0] * 2;
01342         cb2 += src->linesize[1];
01343         cr2 += src->linesize[2];
01344     }
01345 }
01346 
01347 static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src,
01348                               int width, int height)
01349 {
01350     int w, h;
01351     uint8_t *line1, *line2, *linesrc = dst->data[0];
01352     uint8_t *lum1, *lum2, *lumsrc = src->data[0];
01353     uint8_t *cb1, *cb2 = src->data[1];
01354     uint8_t *cr1, *cr2 = src->data[2];
01355 
01356     for(h = height / 2; h--;) {
01357         line1 = linesrc;
01358         line2 = linesrc + dst->linesize[0];
01359 
01360         lum1 = lumsrc;
01361         lum2 = lumsrc + src->linesize[0];
01362 
01363         cb1 = cb2;
01364         cr1 = cr2;
01365 
01366         for(w = width / 2; w--;) {
01367                 *line1++ =          *line2++ = *cb1++;
01368                 *line1++ = *lum1++; *line2++ = *lum2++;
01369                 *line1++ =          *line2++ = *cr1++;
01370                 *line1++ = *lum1++; *line2++ = *lum2++;
01371         }
01372 
01373         linesrc += dst->linesize[0] * 2;
01374         lumsrc += src->linesize[0] * 2;
01375         cb2 += src->linesize[1];
01376         cr2 += src->linesize[2];
01377     }
01378 }
01379 
01380 /* 2x2 -> 1x1 */
01381 void ff_shrink22(uint8_t *dst, int dst_wrap,
01382                      const uint8_t *src, int src_wrap,
01383                      int width, int height)
01384 {
01385     int w;
01386     const uint8_t *s1, *s2;
01387     uint8_t *d;
01388 
01389     for(;height > 0; height--) {
01390         s1 = src;
01391         s2 = s1 + src_wrap;
01392         d = dst;
01393         for(w = width;w >= 4; w-=4) {
01394             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
01395             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
01396             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
01397             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
01398             s1 += 8;
01399             s2 += 8;
01400             d += 4;
01401         }
01402         for(;w > 0; w--) {
01403             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
01404             s1 += 2;
01405             s2 += 2;
01406             d++;
01407         }
01408         src += 2 * src_wrap;
01409         dst += dst_wrap;
01410     }
01411 }
01412 
01413 /* 4x4 -> 1x1 */
01414 void ff_shrink44(uint8_t *dst, int dst_wrap,
01415                      const uint8_t *src, int src_wrap,
01416                      int width, int height)
01417 {
01418     int w;
01419     const uint8_t *s1, *s2, *s3, *s4;
01420     uint8_t *d;
01421 
01422     for(;height > 0; height--) {
01423         s1 = src;
01424         s2 = s1 + src_wrap;
01425         s3 = s2 + src_wrap;
01426         s4 = s3 + src_wrap;
01427         d = dst;
01428         for(w = width;w > 0; w--) {
01429             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
01430                     s2[0] + s2[1] + s2[2] + s2[3] +
01431                     s3[0] + s3[1] + s3[2] + s3[3] +
01432                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
01433             s1 += 4;
01434             s2 += 4;
01435             s3 += 4;
01436             s4 += 4;
01437             d++;
01438         }
01439         src += 4 * src_wrap;
01440         dst += dst_wrap;
01441     }
01442 }
01443 
01444 /* 8x8 -> 1x1 */
01445 void ff_shrink88(uint8_t *dst, int dst_wrap,
01446                      const uint8_t *src, int src_wrap,
01447                      int width, int height)
01448 {
01449     int w, i;
01450 
01451     for(;height > 0; height--) {
01452         for(w = width;w > 0; w--) {
01453             int tmp=0;
01454             for(i=0; i<8; i++){
01455                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
01456                 src += src_wrap;
01457             }
01458             *(dst++) = (tmp + 32)>>6;
01459             src += 8 - 8*src_wrap;
01460         }
01461         src += 8*src_wrap - 8*width;
01462         dst += dst_wrap - width;
01463     }
01464 }
01465 
01466 /* XXX: add jpeg quantize code */
01467 
01468 #define TRANSP_INDEX (6*6*6)
01469 
01470 /* this is maybe slow, but allows for extensions */
01471 static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
01472 {
01473     return (((r) / 47) % 6) * 6 * 6 + (((g) / 47) % 6) * 6 + (((b) / 47) % 6);
01474 }
01475 
01476 static void build_rgb_palette(uint8_t *palette, int has_alpha)
01477 {
01478     uint32_t *pal;
01479     static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
01480     int i, r, g, b;
01481 
01482     pal = (uint32_t *)palette;
01483     i = 0;
01484     for(r = 0; r < 6; r++) {
01485         for(g = 0; g < 6; g++) {
01486             for(b = 0; b < 6; b++) {
01487                 pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
01488                     (pal_value[g] << 8) | pal_value[b];
01489             }
01490         }
01491     }
01492     if (has_alpha)
01493         pal[i++] = 0;
01494     while (i < 256)
01495         pal[i++] = 0xff000000;
01496 }
01497 
01498 /* copy bit n to bits 0 ... n - 1 */
01499 static inline unsigned int bitcopy_n(unsigned int a, int n)
01500 {
01501     int mask;
01502     mask = (1 << n) - 1;
01503     return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
01504 }
01505 
01506 /* rgb555 handling */
01507 
01508 #define RGB_NAME rgb555
01509 
01510 #define RGB_IN(r, g, b, s)\
01511 {\
01512     unsigned int v = ((const uint16_t *)(s))[0];\
01513     r = bitcopy_n(v >> (10 - 3), 3);\
01514     g = bitcopy_n(v >> (5 - 3), 3);\
01515     b = bitcopy_n(v << 3, 3);\
01516 }
01517 
01518 
01519 #define RGB_OUT(d, r, g, b)\
01520 {\
01521     ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);\
01522 }
01523 
01524 #define BPP 2
01525 
01526 #include "imgconvert_template.c"
01527 
01528 /* rgb565 handling */
01529 
01530 #define RGB_NAME rgb565
01531 
01532 #define RGB_IN(r, g, b, s)\
01533 {\
01534     unsigned int v = ((const uint16_t *)(s))[0];\
01535     r = bitcopy_n(v >> (11 - 3), 3);\
01536     g = bitcopy_n(v >> (5 - 2), 2);\
01537     b = bitcopy_n(v << 3, 3);\
01538 }
01539 
01540 #define RGB_OUT(d, r, g, b)\
01541 {\
01542     ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
01543 }
01544 
01545 #define BPP 2
01546 
01547 #include "imgconvert_template.c"
01548 
01549 /* bgr24 handling */
01550 
01551 #define RGB_NAME bgr24
01552 
01553 #define RGB_IN(r, g, b, s)\
01554 {\
01555     b = (s)[0];\
01556     g = (s)[1];\
01557     r = (s)[2];\
01558 }
01559 
01560 #define RGB_OUT(d, r, g, b)\
01561 {\
01562     (d)[0] = b;\
01563     (d)[1] = g;\
01564     (d)[2] = r;\
01565 }
01566 
01567 #define BPP 3
01568 
01569 #include "imgconvert_template.c"
01570 
01571 #undef RGB_IN
01572 #undef RGB_OUT
01573 #undef BPP
01574 
01575 /* rgb24 handling */
01576 
01577 #define RGB_NAME rgb24
01578 #define FMT_RGB24
01579 
01580 #define RGB_IN(r, g, b, s)\
01581 {\
01582     r = (s)[0];\
01583     g = (s)[1];\
01584     b = (s)[2];\
01585 }
01586 
01587 #define RGB_OUT(d, r, g, b)\
01588 {\
01589     (d)[0] = r;\
01590     (d)[1] = g;\
01591     (d)[2] = b;\
01592 }
01593 
01594 #define BPP 3
01595 
01596 #include "imgconvert_template.c"
01597 
01598 /* rgb32 handling */
01599 
01600 #define RGB_NAME rgb32
01601 #define FMT_RGB32
01602 
01603 #define RGB_IN(r, g, b, s)\
01604 {\
01605     unsigned int v = ((const uint32_t *)(s))[0];\
01606     r = (v >> 16) & 0xff;\
01607     g = (v >> 8) & 0xff;\
01608     b = v & 0xff;\
01609 }
01610 
01611 #define RGBA_IN(r, g, b, a, s)\
01612 {\
01613     unsigned int v = ((const uint32_t *)(s))[0];\
01614     a = (v >> 24) & 0xff;\
01615     r = (v >> 16) & 0xff;\
01616     g = (v >> 8) & 0xff;\
01617     b = v & 0xff;\
01618 }
01619 
01620 #define RGBA_OUT(d, r, g, b, a)\
01621 {\
01622     ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
01623 }
01624 
01625 #define BPP 4
01626 
01627 #include "imgconvert_template.c"
01628 
01629 static void mono_to_gray(AVPicture *dst, const AVPicture *src,
01630                          int width, int height, int xor_mask)
01631 {
01632     const unsigned char *p;
01633     unsigned char *q;
01634     int v, dst_wrap, src_wrap;
01635     int y, w;
01636 
01637     p = src->data[0];
01638     src_wrap = src->linesize[0] - ((width + 7) >> 3);
01639 
01640     q = dst->data[0];
01641     dst_wrap = dst->linesize[0] - width;
01642     for(y=0;y<height;y++) {
01643         w = width;
01644         while (w >= 8) {
01645             v = *p++ ^ xor_mask;
01646             q[0] = -(v >> 7);
01647             q[1] = -((v >> 6) & 1);
01648             q[2] = -((v >> 5) & 1);
01649             q[3] = -((v >> 4) & 1);
01650             q[4] = -((v >> 3) & 1);
01651             q[5] = -((v >> 2) & 1);
01652             q[6] = -((v >> 1) & 1);
01653             q[7] = -((v >> 0) & 1);
01654             w -= 8;
01655             q += 8;
01656         }
01657         if (w > 0) {
01658             v = *p++ ^ xor_mask;
01659             do {
01660                 q[0] = -((v >> 7) & 1);
01661                 q++;
01662                 v <<= 1;
01663             } while (--w);
01664         }
01665         p += src_wrap;
01666         q += dst_wrap;
01667     }
01668 }
01669 
01670 static void monowhite_to_gray(AVPicture *dst, const AVPicture *src,
01671                                int width, int height)
01672 {
01673     mono_to_gray(dst, src, width, height, 0xff);
01674 }
01675 
01676 static void monoblack_to_gray(AVPicture *dst, const AVPicture *src,
01677                                int width, int height)
01678 {
01679     mono_to_gray(dst, src, width, height, 0x00);
01680 }
01681 
01682 static void gray_to_mono(AVPicture *dst, const AVPicture *src,
01683                          int width, int height, int xor_mask)
01684 {
01685     int n;
01686     const uint8_t *s;
01687     uint8_t *d;
01688     int j, b, v, n1, src_wrap, dst_wrap, y;
01689 
01690     s = src->data[0];
01691     src_wrap = src->linesize[0] - width;
01692 
01693     d = dst->data[0];
01694     dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
01695 
01696     for(y=0;y<height;y++) {
01697         n = width;
01698         while (n >= 8) {
01699             v = 0;
01700             for(j=0;j<8;j++) {
01701                 b = s[0];
01702                 s++;
01703                 v = (v << 1) | (b >> 7);
01704             }
01705             d[0] = v ^ xor_mask;
01706             d++;
01707             n -= 8;
01708         }
01709         if (n > 0) {
01710             n1 = n;
01711             v = 0;
01712             while (n > 0) {
01713                 b = s[0];
01714                 s++;
01715                 v = (v << 1) | (b >> 7);
01716                 n--;
01717             }
01718             d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
01719             d++;
01720         }
01721         s += src_wrap;
01722         d += dst_wrap;
01723     }
01724 }
01725 
01726 static void gray_to_monowhite(AVPicture *dst, const AVPicture *src,
01727                               int width, int height)
01728 {
01729     gray_to_mono(dst, src, width, height, 0xff);
01730 }
01731 
01732 static void gray_to_monoblack(AVPicture *dst, const AVPicture *src,
01733                               int width, int height)
01734 {
01735     gray_to_mono(dst, src, width, height, 0x00);
01736 }
01737 
01738 static void gray_to_gray16(AVPicture *dst, const AVPicture *src,
01739                               int width, int height)
01740 {
01741     int x, y, src_wrap, dst_wrap;
01742     uint8_t *s, *d;
01743     s = src->data[0];
01744     src_wrap = src->linesize[0] - width;
01745     d = dst->data[0];
01746     dst_wrap = dst->linesize[0] - width * 2;
01747     for(y=0; y<height; y++){
01748         for(x=0; x<width; x++){
01749             *d++ = *s;
01750             *d++ = *s++;
01751         }
01752         s += src_wrap;
01753         d += dst_wrap;
01754     }
01755 }
01756 
01757 static void gray16_to_gray(AVPicture *dst, const AVPicture *src,
01758                               int width, int height)
01759 {
01760     int x, y, src_wrap, dst_wrap;
01761     uint8_t *s, *d;
01762     s = src->data[0];
01763     src_wrap = src->linesize[0] - width * 2;
01764     d = dst->data[0];
01765     dst_wrap = dst->linesize[0] - width;
01766     for(y=0; y<height; y++){
01767         for(x=0; x<width; x++){
01768             *d++ = *s;
01769             s += 2;
01770         }
01771         s += src_wrap;
01772         d += dst_wrap;
01773     }
01774 }
01775 
01776 static void gray16be_to_gray(AVPicture *dst, const AVPicture *src,
01777                               int width, int height)
01778 {
01779     gray16_to_gray(dst, src, width, height);
01780 }
01781 
01782 static void gray16le_to_gray(AVPicture *dst, const AVPicture *src,
01783                               int width, int height)
01784 {
01785     AVPicture tmpsrc = *src;
01786     tmpsrc.data[0]++;
01787     gray16_to_gray(dst, &tmpsrc, width, height);
01788 }
01789 
01790 static void gray16_to_gray16(AVPicture *dst, const AVPicture *src,
01791                               int width, int height)
01792 {
01793     int x, y, src_wrap, dst_wrap;
01794     uint16_t *s, *d;
01795     s = (uint16_t*)src->data[0];
01796     src_wrap = (src->linesize[0] - width * 2)/2;
01797     d = (uint16_t*)dst->data[0];
01798     dst_wrap = (dst->linesize[0] - width * 2)/2;
01799     for(y=0; y<height; y++){
01800         for(x=0; x<width; x++){
01801             *d++ = bswap_16(*s++);
01802         }
01803         s += src_wrap;
01804         d += dst_wrap;
01805     }
01806 }
01807 
01808 
01809 typedef struct ConvertEntry {
01810     void (*convert)(AVPicture *dst,
01811                     const AVPicture *src, int width, int height);
01812 } ConvertEntry;
01813 
01814 /* Add each new conversion function in this table. In order to be able
01815    to convert from any format to any format, the following constraints
01816    must be satisfied:
01817 
01818    - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24
01819 
01820    - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8
01821 
01822    - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGB32
01823 
01824    - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from
01825      PIX_FMT_RGB24.
01826 
01827    - PIX_FMT_422 must convert to and from PIX_FMT_422P.
01828 
01829    The other conversion functions are just optimizations for common cases.
01830 */
01831 static const ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
01832     [PIX_FMT_YUV420P] = {
01833         [PIX_FMT_YUYV422] = {
01834             .convert = yuv420p_to_yuyv422,
01835         },
01836         [PIX_FMT_RGB555] = {
01837             .convert = yuv420p_to_rgb555
01838         },
01839         [PIX_FMT_RGB565] = {
01840             .convert = yuv420p_to_rgb565
01841         },
01842         [PIX_FMT_BGR24] = {
01843             .convert = yuv420p_to_bgr24
01844         },
01845         [PIX_FMT_RGB24] = {
01846             .convert = yuv420p_to_rgb24
01847         },
01848         [PIX_FMT_RGB32] = {
01849             .convert = yuv420p_to_rgb32
01850         },
01851         [PIX_FMT_UYVY422] = {
01852             .convert = yuv420p_to_uyvy422,
01853         },
01854     },
01855     [PIX_FMT_YUV422P] = {
01856         [PIX_FMT_YUYV422] = {
01857             .convert = yuv422p_to_yuyv422,
01858         },
01859         [PIX_FMT_UYVY422] = {
01860             .convert = yuv422p_to_uyvy422,
01861         },
01862     },
01863     [PIX_FMT_YUV444P] = {
01864         [PIX_FMT_RGB24] = {
01865             .convert = yuv444p_to_rgb24
01866         },
01867     },
01868     [PIX_FMT_YUVJ420P] = {
01869         [PIX_FMT_RGB555] = {
01870             .convert = yuvj420p_to_rgb555
01871         },
01872         [PIX_FMT_RGB565] = {
01873             .convert = yuvj420p_to_rgb565
01874         },
01875         [PIX_FMT_BGR24] = {
01876             .convert = yuvj420p_to_bgr24
01877         },
01878         [PIX_FMT_RGB24] = {
01879             .convert = yuvj420p_to_rgb24
01880         },
01881         [PIX_FMT_RGB32] = {
01882             .convert = yuvj420p_to_rgb32
01883         },
01884     },
01885     [PIX_FMT_YUVJ444P] = {
01886         [PIX_FMT_RGB24] = {
01887             .convert = yuvj444p_to_rgb24
01888         },
01889     },
01890     [PIX_FMT_YUYV422] = {
01891         [PIX_FMT_YUV420P] = {
01892             .convert = yuyv422_to_yuv420p,
01893         },
01894         [PIX_FMT_YUV422P] = {
01895             .convert = yuyv422_to_yuv422p,
01896         },
01897     },
01898     [PIX_FMT_UYVY422] = {
01899         [PIX_FMT_YUV420P] = {
01900             .convert = uyvy422_to_yuv420p,
01901         },
01902         [PIX_FMT_YUV422P] = {
01903             .convert = uyvy422_to_yuv422p,
01904         },
01905     },
01906     [PIX_FMT_RGB24] = {
01907         [PIX_FMT_YUV420P] = {
01908             .convert = rgb24_to_yuv420p
01909         },
01910         [PIX_FMT_RGB565] = {
01911             .convert = rgb24_to_rgb565
01912         },
01913         [PIX_FMT_RGB555] = {
01914             .convert = rgb24_to_rgb555
01915         },
01916         [PIX_FMT_RGB32] = {
01917             .convert = rgb24_to_rgb32
01918         },
01919         [PIX_FMT_BGR24] = {
01920             .convert = rgb24_to_bgr24
01921         },
01922         [PIX_FMT_GRAY8] = {
01923             .convert = rgb24_to_gray
01924         },
01925         [PIX_FMT_PAL8] = {
01926             .convert = rgb24_to_pal8
01927         },
01928         [PIX_FMT_YUV444P] = {
01929             .convert = rgb24_to_yuv444p
01930         },
01931         [PIX_FMT_YUVJ420P] = {
01932             .convert = rgb24_to_yuvj420p
01933         },
01934         [PIX_FMT_YUVJ444P] = {
01935             .convert = rgb24_to_yuvj444p
01936         },
01937     },
01938     [PIX_FMT_RGB32] = {
01939         [PIX_FMT_RGB24] = {
01940             .convert = rgb32_to_rgb24
01941         },
01942         [PIX_FMT_BGR24] = {
01943             .convert = rgb32_to_bgr24
01944         },
01945         [PIX_FMT_RGB565] = {
01946             .convert = rgb32_to_rgb565
01947         },
01948         [PIX_FMT_RGB555] = {
01949             .convert = rgb32_to_rgb555
01950         },
01951         [PIX_FMT_PAL8] = {
01952             .convert = rgb32_to_pal8
01953         },
01954         [PIX_FMT_YUV420P] = {
01955             .convert = rgb32_to_yuv420p
01956         },
01957         [PIX_FMT_GRAY8] = {
01958             .convert = rgb32_to_gray
01959         },
01960     },
01961     [PIX_FMT_BGR24] = {
01962         [PIX_FMT_RGB32] = {
01963             .convert = bgr24_to_rgb32
01964         },
01965         [PIX_FMT_RGB24] = {
01966             .convert = bgr24_to_rgb24
01967         },
01968         [PIX_FMT_YUV420P] = {
01969             .convert = bgr24_to_yuv420p
01970         },
01971         [PIX_FMT_GRAY8] = {
01972             .convert = bgr24_to_gray
01973         },
01974     },
01975     [PIX_FMT_RGB555] = {
01976         [PIX_FMT_RGB24] = {
01977             .convert = rgb555_to_rgb24
01978         },
01979         [PIX_FMT_RGB32] = {
01980             .convert = rgb555_to_rgb32
01981         },
01982         [PIX_FMT_YUV420P] = {
01983             .convert = rgb555_to_yuv420p
01984         },
01985         [PIX_FMT_GRAY8] = {
01986             .convert = rgb555_to_gray
01987         },
01988     },
01989     [PIX_FMT_RGB565] = {
01990         [PIX_FMT_RGB32] = {
01991             .convert = rgb565_to_rgb32
01992         },
01993         [PIX_FMT_RGB24] = {
01994             .convert = rgb565_to_rgb24
01995         },
01996         [PIX_FMT_YUV420P] = {
01997             .convert = rgb565_to_yuv420p
01998         },
01999         [PIX_FMT_GRAY8] = {
02000             .convert = rgb565_to_gray
02001         },
02002     },
02003     [PIX_FMT_GRAY16BE] = {
02004         [PIX_FMT_GRAY8] = {
02005             .convert = gray16be_to_gray
02006         },
02007         [PIX_FMT_GRAY16LE] = {
02008             .convert = gray16_to_gray16
02009         },
02010     },
02011     [PIX_FMT_GRAY16LE] = {
02012         [PIX_FMT_GRAY8] = {
02013             .convert = gray16le_to_gray
02014         },
02015         [PIX_FMT_GRAY16BE] = {
02016             .convert = gray16_to_gray16
02017         },
02018     },
02019     [PIX_FMT_GRAY8] = {
02020         [PIX_FMT_RGB555] = {
02021             .convert = gray_to_rgb555
02022         },
02023         [PIX_FMT_RGB565] = {
02024             .convert = gray_to_rgb565
02025         },
02026         [PIX_FMT_RGB24] = {
02027             .convert = gray_to_rgb24
02028         },
02029         [PIX_FMT_BGR24] = {
02030             .convert = gray_to_bgr24
02031         },
02032         [PIX_FMT_RGB32] = {
02033             .convert = gray_to_rgb32
02034         },
02035         [PIX_FMT_MONOWHITE] = {
02036             .convert = gray_to_monowhite
02037         },
02038         [PIX_FMT_MONOBLACK] = {
02039             .convert = gray_to_monoblack
02040         },
02041         [PIX_FMT_GRAY16LE] = {
02042             .convert = gray_to_gray16
02043         },
02044         [PIX_FMT_GRAY16BE] = {
02045             .convert = gray_to_gray16
02046         },
02047     },
02048     [PIX_FMT_MONOWHITE] = {
02049         [PIX_FMT_GRAY8] = {
02050             .convert = monowhite_to_gray
02051         },
02052     },
02053     [PIX_FMT_MONOBLACK] = {
02054         [PIX_FMT_GRAY8] = {
02055             .convert = monoblack_to_gray
02056         },
02057     },
02058     [PIX_FMT_PAL8] = {
02059         [PIX_FMT_RGB555] = {
02060             .convert = pal8_to_rgb555
02061         },
02062         [PIX_FMT_RGB565] = {
02063             .convert = pal8_to_rgb565
02064         },
02065         [PIX_FMT_BGR24] = {
02066             .convert = pal8_to_bgr24
02067         },
02068         [PIX_FMT_RGB24] = {
02069             .convert = pal8_to_rgb24
02070         },
02071         [PIX_FMT_RGB32] = {
02072             .convert = pal8_to_rgb32
02073         },
02074     },
02075     [PIX_FMT_UYYVYY411] = {
02076         [PIX_FMT_YUV411P] = {
02077             .convert = uyyvyy411_to_yuv411p,
02078         },
02079     },
02080 
02081 };
02082 
02083 int avpicture_alloc(AVPicture *picture,
02084                            int pix_fmt, int width, int height)
02085 {
02086     int size;
02087     void *ptr;
02088 
02089     size = avpicture_get_size(pix_fmt, width, height);
02090     if(size<0)
02091         goto fail;
02092     ptr = av_malloc(size);
02093     if (!ptr)
02094         goto fail;
02095     avpicture_fill(picture, ptr, pix_fmt, width, height);
02096     if(picture->data[1] && !picture->data[2])
02097         ff_set_systematic_pal((uint32_t*)picture->data[1], pix_fmt);
02098 
02099     return 0;
02100  fail:
02101     memset(picture, 0, sizeof(AVPicture));
02102     return -1;
02103 }
02104 
02105 void avpicture_free(AVPicture *picture)
02106 {
02107     av_free(picture->data[0]);
02108 }
02109 
02110 /* return true if yuv planar */
02111 static inline int is_yuv_planar(const PixFmtInfo *ps)
02112 {
02113     return (ps->color_type == FF_COLOR_YUV ||
02114             ps->color_type == FF_COLOR_YUV_JPEG) &&
02115         ps->pixel_type == FF_PIXEL_PLANAR;
02116 }
02117 
02118 int av_picture_crop(AVPicture *dst, const AVPicture *src,
02119               int pix_fmt, int top_band, int left_band)
02120 {
02121     int y_shift;
02122     int x_shift;
02123 
02124     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
02125         return -1;
02126 
02127     y_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
02128     x_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
02129 
02130     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
02131     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
02132     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
02133 
02134     dst->linesize[0] = src->linesize[0];
02135     dst->linesize[1] = src->linesize[1];
02136     dst->linesize[2] = src->linesize[2];
02137     return 0;
02138 }
02139 
02140 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
02141             int pix_fmt, int padtop, int padbottom, int padleft, int padright,
02142             int *color)
02143 {
02144     uint8_t *optr;
02145     int y_shift;
02146     int x_shift;
02147     int yheight;
02148     int i, y;
02149 
02150     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
02151         !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
02152 
02153     for (i = 0; i < 3; i++) {
02154         x_shift = i ? pix_fmt_info[pix_fmt].x_chroma_shift : 0;
02155         y_shift = i ? pix_fmt_info[pix_fmt].y_chroma_shift : 0;
02156 
02157         if (padtop || padleft) {
02158             memset(dst->data[i], color[i],
02159                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
02160         }
02161 
02162         if (padleft || padright) {
02163             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
02164                 (dst->linesize[i] - (padright >> x_shift));
02165             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
02166             for (y = 0; y < yheight; y++) {
02167                 memset(optr, color[i], (padleft + padright) >> x_shift);
02168                 optr += dst->linesize[i];
02169             }
02170         }
02171 
02172         if (src) { /* first line */
02173             uint8_t *iptr = src->data[i];
02174             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
02175                     (padleft >> x_shift);
02176             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
02177             iptr += src->linesize[i];
02178             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
02179                 (dst->linesize[i] - (padright >> x_shift));
02180             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
02181             for (y = 0; y < yheight; y++) {
02182                 memset(optr, color[i], (padleft + padright) >> x_shift);
02183                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
02184                        (width - padleft - padright) >> x_shift);
02185                 iptr += src->linesize[i];
02186                 optr += dst->linesize[i];
02187             }
02188         }
02189 
02190         if (padbottom || padright) {
02191             optr = dst->data[i] + dst->linesize[i] *
02192                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
02193             memset(optr, color[i],dst->linesize[i] *
02194                 (padbottom >> y_shift) + (padright >> x_shift));
02195         }
02196     }
02197     return 0;
02198 }
02199 
02200 #if !CONFIG_SWSCALE
02201 static uint8_t y_ccir_to_jpeg[256];
02202 static uint8_t y_jpeg_to_ccir[256];
02203 static uint8_t c_ccir_to_jpeg[256];
02204 static uint8_t c_jpeg_to_ccir[256];
02205 
02206 /* init various conversion tables */
02207 static av_cold void img_convert_init(void)
02208 {
02209     int i;
02210     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
02211 
02212     for(i = 0;i < 256; i++) {
02213         y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i);
02214         y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i);
02215         c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i);
02216         c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i);
02217     }
02218 }
02219 
02220 /* apply to each pixel the given table */
02221 static void img_apply_table(uint8_t *dst, int dst_wrap,
02222                             const uint8_t *src, int src_wrap,
02223                             int width, int height, const uint8_t *table1)
02224 {
02225     int n;
02226     const uint8_t *s;
02227     uint8_t *d;
02228     const uint8_t *table;
02229 
02230     table = table1;
02231     for(;height > 0; height--) {
02232         s = src;
02233         d = dst;
02234         n = width;
02235         while (n >= 4) {
02236             d[0] = table[s[0]];
02237             d[1] = table[s[1]];
02238             d[2] = table[s[2]];
02239             d[3] = table[s[3]];
02240             d += 4;
02241             s += 4;
02242             n -= 4;
02243         }
02244         while (n > 0) {
02245             d[0] = table[s[0]];
02246             d++;
02247             s++;
02248             n--;
02249         }
02250         dst += dst_wrap;
02251         src += src_wrap;
02252     }
02253 }
02254 
02255 /* XXX: use generic filter ? */
02256 /* XXX: in most cases, the sampling position is incorrect */
02257 
02258 /* 4x1 -> 1x1 */
02259 static void shrink41(uint8_t *dst, int dst_wrap,
02260                      const uint8_t *src, int src_wrap,
02261                      int width, int height)
02262 {
02263     int w;
02264     const uint8_t *s;
02265     uint8_t *d;
02266 
02267     for(;height > 0; height--) {
02268         s = src;
02269         d = dst;
02270         for(w = width;w > 0; w--) {
02271             d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2;
02272             s += 4;
02273             d++;
02274         }
02275         src += src_wrap;
02276         dst += dst_wrap;
02277     }
02278 }
02279 
02280 /* 2x1 -> 1x1 */
02281 static void shrink21(uint8_t *dst, int dst_wrap,
02282                      const uint8_t *src, int src_wrap,
02283                      int width, int height)
02284 {
02285     int w;
02286     const uint8_t *s;
02287     uint8_t *d;
02288 
02289     for(;height > 0; height--) {
02290         s = src;
02291         d = dst;
02292         for(w = width;w > 0; w--) {
02293             d[0] = (s[0] + s[1]) >> 1;
02294             s += 2;
02295             d++;
02296         }
02297         src += src_wrap;
02298         dst += dst_wrap;
02299     }
02300 }
02301 
02302 /* 1x2 -> 1x1 */
02303 static void shrink12(uint8_t *dst, int dst_wrap,
02304                      const uint8_t *src, int src_wrap,
02305                      int width, int height)
02306 {
02307     int w;
02308     uint8_t *d;
02309     const uint8_t *s1, *s2;
02310 
02311     for(;height > 0; height--) {
02312         s1 = src;
02313         s2 = s1 + src_wrap;
02314         d = dst;
02315         for(w = width;w >= 4; w-=4) {
02316             d[0] = (s1[0] + s2[0]) >> 1;
02317             d[1] = (s1[1] + s2[1]) >> 1;
02318             d[2] = (s1[2] + s2[2]) >> 1;
02319             d[3] = (s1[3] + s2[3]) >> 1;
02320             s1 += 4;
02321             s2 += 4;
02322             d += 4;
02323         }
02324         for(;w > 0; w--) {
02325             d[0] = (s1[0] + s2[0]) >> 1;
02326             s1++;
02327             s2++;
02328             d++;
02329         }
02330         src += 2 * src_wrap;
02331         dst += dst_wrap;
02332     }
02333 }
02334 
02335 static void grow21_line(uint8_t *dst, const uint8_t *src,
02336                         int width)
02337 {
02338     int w;
02339     const uint8_t *s1;
02340     uint8_t *d;
02341 
02342     s1 = src;
02343     d = dst;
02344     for(w = width;w >= 4; w-=4) {
02345         d[1] = d[0] = s1[0];
02346         d[3] = d[2] = s1[1];
02347         s1 += 2;
02348         d += 4;
02349     }
02350     for(;w >= 2; w -= 2) {
02351         d[1] = d[0] = s1[0];
02352         s1 ++;
02353         d += 2;
02354     }
02355     /* only needed if width is not a multiple of two */
02356     /* XXX: veryfy that */
02357     if (w) {
02358         d[0] = s1[0];
02359     }
02360 }
02361 
02362 static void grow41_line(uint8_t *dst, const uint8_t *src,
02363                         int width)
02364 {
02365     int w, v;
02366     const uint8_t *s1;
02367     uint8_t *d;
02368 
02369     s1 = src;
02370     d = dst;
02371     for(w = width;w >= 4; w-=4) {
02372         v = s1[0];
02373         d[0] = v;
02374         d[1] = v;
02375         d[2] = v;
02376         d[3] = v;
02377         s1 ++;
02378         d += 4;
02379     }
02380 }
02381 
02382 /* 1x1 -> 2x1 */
02383 static void grow21(uint8_t *dst, int dst_wrap,
02384                    const uint8_t *src, int src_wrap,
02385                    int width, int height)
02386 {
02387     for(;height > 0; height--) {
02388         grow21_line(dst, src, width);
02389         src += src_wrap;
02390         dst += dst_wrap;
02391     }
02392 }
02393 
02394 /* 1x1 -> 1x2 */
02395 static void grow12(uint8_t *dst, int dst_wrap,
02396                    const uint8_t *src, int src_wrap,
02397                    int width, int height)
02398 {
02399     for(;height > 0; height-=2) {
02400         memcpy(dst, src, width);
02401         dst += dst_wrap;
02402         memcpy(dst, src, width);
02403         dst += dst_wrap;
02404         src += src_wrap;
02405     }
02406 }
02407 
02408 /* 1x1 -> 2x2 */
02409 static void grow22(uint8_t *dst, int dst_wrap,
02410                    const uint8_t *src, int src_wrap,
02411                    int width, int height)
02412 {
02413     for(;height > 0; height--) {
02414         grow21_line(dst, src, width);
02415         if (height%2)
02416             src += src_wrap;
02417         dst += dst_wrap;
02418     }
02419 }
02420 
02421 /* 1x1 -> 4x1 */
02422 static void grow41(uint8_t *dst, int dst_wrap,
02423                    const uint8_t *src, int src_wrap,
02424                    int width, int height)
02425 {
02426     for(;height > 0; height--) {
02427         grow41_line(dst, src, width);
02428         src += src_wrap;
02429         dst += dst_wrap;
02430     }
02431 }
02432 
02433 /* 1x1 -> 4x4 */
02434 static void grow44(uint8_t *dst, int dst_wrap,
02435                    const uint8_t *src, int src_wrap,
02436                    int width, int height)
02437 {
02438     for(;height > 0; height--) {
02439         grow41_line(dst, src, width);
02440         if ((height & 3) == 1)
02441             src += src_wrap;
02442         dst += dst_wrap;
02443     }
02444 }
02445 
02446 /* 1x2 -> 2x1 */
02447 static void conv411(uint8_t *dst, int dst_wrap,
02448                     const uint8_t *src, int src_wrap,
02449                     int width, int height)
02450 {
02451     int w, c;
02452     const uint8_t *s1, *s2;
02453     uint8_t *d;
02454 
02455     width>>=1;
02456 
02457     for(;height > 0; height--) {
02458         s1 = src;
02459         s2 = src + src_wrap;
02460         d = dst;
02461         for(w = width;w > 0; w--) {
02462             c = (s1[0] + s2[0]) >> 1;
02463             d[0] = c;
02464             d[1] = c;
02465             s1++;
02466             s2++;
02467             d += 2;
02468         }
02469         src += src_wrap * 2;
02470         dst += dst_wrap;
02471     }
02472 }
02473 
02474 /* XXX: always use linesize. Return -1 if not supported */
02475 int img_convert(AVPicture *dst, int dst_pix_fmt,
02476                 const AVPicture *src, int src_pix_fmt,
02477                 int src_width, int src_height)
02478 {
02479     static int initialized;
02480     int i, ret, dst_width, dst_height, int_pix_fmt;
02481     const PixFmtInfo *src_pix, *dst_pix;
02482     const ConvertEntry *ce;
02483     AVPicture tmp1, *tmp = &tmp1;
02484 
02485     if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
02486         dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
02487         return -1;
02488     if (src_width <= 0 || src_height <= 0)
02489         return 0;
02490 
02491     if (!initialized) {
02492         initialized = 1;
02493         img_convert_init();
02494     }
02495 
02496     dst_width = src_width;
02497     dst_height = src_height;
02498 
02499     dst_pix = &pix_fmt_info[dst_pix_fmt];
02500     src_pix = &pix_fmt_info[src_pix_fmt];
02501     if (src_pix_fmt == dst_pix_fmt) {
02502         /* no conversion needed: just copy */
02503         av_picture_copy(dst, src, dst_pix_fmt, dst_width, dst_height);
02504         return 0;
02505     }
02506 
02507     ce = &convert_table[src_pix_fmt][dst_pix_fmt];
02508     if (ce->convert) {
02509         /* specific conversion routine */
02510         ce->convert(dst, src, dst_width, dst_height);
02511         return 0;
02512     }
02513 
02514     /* gray to YUV */
02515     if (is_yuv_planar(dst_pix) &&
02516         src_pix_fmt == PIX_FMT_GRAY8) {
02517         int w, h, y;
02518         uint8_t *d;
02519 
02520         if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
02521             ff_img_copy_plane(dst->data[0], dst->linesize[0],
02522                      src->data[0], src->linesize[0],
02523                      dst_width, dst_height);
02524         } else {
02525             img_apply_table(dst->data[0], dst->linesize[0],
02526                             src->data[0], src->linesize[0],
02527                             dst_width, dst_height,
02528                             y_jpeg_to_ccir);
02529         }
02530         /* fill U and V with 128 */
02531         w = dst_width;
02532         h = dst_height;
02533         w >>= dst_pix->x_chroma_shift;
02534         h >>= dst_pix->y_chroma_shift;
02535         for(i = 1; i <= 2; i++) {
02536             d = dst->data[i];
02537             for(y = 0; y< h; y++) {
02538                 memset(d, 128, w);
02539                 d += dst->linesize[i];
02540             }
02541         }
02542         return 0;
02543     }
02544 
02545     /* YUV to gray */
02546     if (is_yuv_planar(src_pix) &&
02547         dst_pix_fmt == PIX_FMT_GRAY8) {
02548         if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
02549             ff_img_copy_plane(dst->data[0], dst->linesize[0],
02550                      src->data[0], src->linesize[0],
02551                      dst_width, dst_height);
02552         } else {
02553             img_apply_table(dst->data[0], dst->linesize[0],
02554                             src->data[0], src->linesize[0],
02555                             dst_width, dst_height,
02556                             y_ccir_to_jpeg);
02557         }
02558         return 0;
02559     }
02560 
02561     /* YUV to YUV planar */
02562     if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) {
02563         int x_shift, y_shift, w, h, xy_shift;
02564         void (*resize_func)(uint8_t *dst, int dst_wrap,
02565                             const uint8_t *src, int src_wrap,
02566                             int width, int height);
02567 
02568         /* compute chroma size of the smallest dimensions */
02569         w = dst_width;
02570         h = dst_height;
02571         if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
02572             w >>= dst_pix->x_chroma_shift;
02573         else
02574             w >>= src_pix->x_chroma_shift;
02575         if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
02576             h >>= dst_pix->y_chroma_shift;
02577         else
02578             h >>= src_pix->y_chroma_shift;
02579 
02580         x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
02581         y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
02582         xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf);
02583         /* there must be filters for conversion at least from and to
02584            YUV444 format */
02585         switch(xy_shift) {
02586         case 0x00:
02587             resize_func = ff_img_copy_plane;
02588             break;
02589         case 0x10:
02590             resize_func = shrink21;
02591             break;
02592         case 0x20:
02593             resize_func = shrink41;
02594             break;
02595         case 0x01:
02596             resize_func = shrink12;
02597             break;
02598         case 0x11:
02599             resize_func = ff_shrink22;
02600             break;
02601         case 0x22:
02602             resize_func = ff_shrink44;
02603             break;
02604         case 0xf0:
02605             resize_func = grow21;
02606             break;
02607         case 0x0f:
02608             resize_func = grow12;
02609             break;
02610         case 0xe0:
02611             resize_func = grow41;
02612             break;
02613         case 0xff:
02614             resize_func = grow22;
02615             break;
02616         case 0xee:
02617             resize_func = grow44;
02618             break;
02619         case 0xf1:
02620             resize_func = conv411;
02621             break;
02622         default:
02623             /* currently not handled */
02624             goto no_chroma_filter;
02625         }
02626 
02627         ff_img_copy_plane(dst->data[0], dst->linesize[0],
02628                        src->data[0], src->linesize[0],
02629                        dst_width, dst_height);
02630 
02631         for(i = 1;i <= 2; i++)
02632             resize_func(dst->data[i], dst->linesize[i],
02633                         src->data[i], src->linesize[i],
02634                         dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
02635         /* if yuv color space conversion is needed, we do it here on
02636            the destination image */
02637         if (dst_pix->color_type != src_pix->color_type) {
02638             const uint8_t *y_table, *c_table;
02639             if (dst_pix->color_type == FF_COLOR_YUV) {
02640                 y_table = y_jpeg_to_ccir;
02641                 c_table = c_jpeg_to_ccir;
02642             } else {
02643                 y_table = y_ccir_to_jpeg;
02644                 c_table = c_ccir_to_jpeg;
02645             }
02646             img_apply_table(dst->data[0], dst->linesize[0],
02647                             dst->data[0], dst->linesize[0],
02648                             dst_width, dst_height,
02649                             y_table);
02650 
02651             for(i = 1;i <= 2; i++)
02652                 img_apply_table(dst->data[i], dst->linesize[i],
02653                                 dst->data[i], dst->linesize[i],
02654                                 dst_width>>dst_pix->x_chroma_shift,
02655                                 dst_height>>dst_pix->y_chroma_shift,
02656                                 c_table);
02657         }
02658         return 0;
02659     }
02660  no_chroma_filter:
02661 
02662     /* try to use an intermediate format */
02663     if (src_pix_fmt == PIX_FMT_YUYV422 ||
02664         dst_pix_fmt == PIX_FMT_YUYV422) {
02665         /* specific case: convert to YUV422P first */
02666         int_pix_fmt = PIX_FMT_YUV422P;
02667     } else if (src_pix_fmt == PIX_FMT_UYVY422 ||
02668         dst_pix_fmt == PIX_FMT_UYVY422) {
02669         /* specific case: convert to YUV422P first */
02670         int_pix_fmt = PIX_FMT_YUV422P;
02671     } else if (src_pix_fmt == PIX_FMT_UYYVYY411 ||
02672         dst_pix_fmt == PIX_FMT_UYYVYY411) {
02673         /* specific case: convert to YUV411P first */
02674         int_pix_fmt = PIX_FMT_YUV411P;
02675     } else if ((src_pix->color_type == FF_COLOR_GRAY &&
02676                 src_pix_fmt != PIX_FMT_GRAY8) ||
02677                (dst_pix->color_type == FF_COLOR_GRAY &&
02678                 dst_pix_fmt != PIX_FMT_GRAY8)) {
02679         /* gray8 is the normalized format */
02680         int_pix_fmt = PIX_FMT_GRAY8;
02681     } else if ((is_yuv_planar(src_pix) &&
02682                 src_pix_fmt != PIX_FMT_YUV444P &&
02683                 src_pix_fmt != PIX_FMT_YUVJ444P)) {
02684         /* yuv444 is the normalized format */
02685         if (src_pix->color_type == FF_COLOR_YUV_JPEG)
02686             int_pix_fmt = PIX_FMT_YUVJ444P;
02687         else
02688             int_pix_fmt = PIX_FMT_YUV444P;
02689     } else if ((is_yuv_planar(dst_pix) &&
02690                 dst_pix_fmt != PIX_FMT_YUV444P &&
02691                 dst_pix_fmt != PIX_FMT_YUVJ444P)) {
02692         /* yuv444 is the normalized format */
02693         if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
02694             int_pix_fmt = PIX_FMT_YUVJ444P;
02695         else
02696             int_pix_fmt = PIX_FMT_YUV444P;
02697     } else {
02698         /* the two formats are rgb or gray8 or yuv[j]444p */
02699         if (src_pix->is_alpha && dst_pix->is_alpha)
02700             int_pix_fmt = PIX_FMT_RGB32;
02701         else
02702             int_pix_fmt = PIX_FMT_RGB24;
02703     }
02704     if (src_pix_fmt == int_pix_fmt)
02705         return -1;
02706     if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
02707         return -1;
02708     ret = -1;
02709     if (img_convert(tmp, int_pix_fmt,
02710                     src, src_pix_fmt, src_width, src_height) < 0)
02711         goto fail1;
02712     if (img_convert(dst, dst_pix_fmt,
02713                     tmp, int_pix_fmt, dst_width, dst_height) < 0)
02714         goto fail1;
02715     ret = 0;
02716  fail1:
02717     avpicture_free(tmp);
02718     return ret;
02719 }
02720 #endif
02721 
02722 /* NOTE: we scan all the pixels to have an exact information */
02723 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
02724 {
02725     const unsigned char *p;
02726     int src_wrap, ret, x, y;
02727     unsigned int a;
02728     uint32_t *palette = (uint32_t *)src->data[1];
02729 
02730     p = src->data[0];
02731     src_wrap = src->linesize[0] - width;
02732     ret = 0;
02733     for(y=0;y<height;y++) {
02734         for(x=0;x<width;x++) {
02735             a = palette[p[0]] >> 24;
02736             if (a == 0x00) {
02737                 ret |= FF_ALPHA_TRANSP;
02738             } else if (a != 0xff) {
02739                 ret |= FF_ALPHA_SEMI_TRANSP;
02740             }
02741             p++;
02742         }
02743         p += src_wrap;
02744     }
02745     return ret;
02746 }
02747 
02748 int img_get_alpha_info(const AVPicture *src,
02749                        int pix_fmt, int width, int height)
02750 {
02751     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
02752     int ret;
02753 
02754     pf = &pix_fmt_info[pix_fmt];
02755     /* no alpha can be represented in format */
02756     if (!pf->is_alpha)
02757         return 0;
02758     switch(pix_fmt) {
02759     case PIX_FMT_RGB32:
02760         ret = get_alpha_info_rgb32(src, width, height);
02761         break;
02762     case PIX_FMT_PAL8:
02763         ret = get_alpha_info_pal8(src, width, height);
02764         break;
02765     default:
02766         /* we do not know, so everything is indicated */
02767         ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
02768         break;
02769     }
02770     return ret;
02771 }
02772 
02773 #if HAVE_MMX
02774 #define DEINT_INPLACE_LINE_LUM \
02775                     movd_m2r(lum_m4[0],mm0);\
02776                     movd_m2r(lum_m3[0],mm1);\
02777                     movd_m2r(lum_m2[0],mm2);\
02778                     movd_m2r(lum_m1[0],mm3);\
02779                     movd_m2r(lum[0],mm4);\
02780                     punpcklbw_r2r(mm7,mm0);\
02781                     movd_r2m(mm2,lum_m4[0]);\
02782                     punpcklbw_r2r(mm7,mm1);\
02783                     punpcklbw_r2r(mm7,mm2);\
02784                     punpcklbw_r2r(mm7,mm3);\
02785                     punpcklbw_r2r(mm7,mm4);\
02786                     paddw_r2r(mm3,mm1);\
02787                     psllw_i2r(1,mm2);\
02788                     paddw_r2r(mm4,mm0);\
02789                     psllw_i2r(2,mm1);\
02790                     paddw_r2r(mm6,mm2);\
02791                     paddw_r2r(mm2,mm1);\
02792                     psubusw_r2r(mm0,mm1);\
02793                     psrlw_i2r(3,mm1);\
02794                     packuswb_r2r(mm7,mm1);\
02795                     movd_r2m(mm1,lum_m2[0]);
02796 
02797 #define DEINT_LINE_LUM \
02798                     movd_m2r(lum_m4[0],mm0);\
02799                     movd_m2r(lum_m3[0],mm1);\
02800                     movd_m2r(lum_m2[0],mm2);\
02801                     movd_m2r(lum_m1[0],mm3);\
02802                     movd_m2r(lum[0],mm4);\
02803                     punpcklbw_r2r(mm7,mm0);\
02804                     punpcklbw_r2r(mm7,mm1);\
02805                     punpcklbw_r2r(mm7,mm2);\
02806                     punpcklbw_r2r(mm7,mm3);\
02807                     punpcklbw_r2r(mm7,mm4);\
02808                     paddw_r2r(mm3,mm1);\
02809                     psllw_i2r(1,mm2);\
02810                     paddw_r2r(mm4,mm0);\
02811                     psllw_i2r(2,mm1);\
02812                     paddw_r2r(mm6,mm2);\
02813                     paddw_r2r(mm2,mm1);\
02814                     psubusw_r2r(mm0,mm1);\
02815                     psrlw_i2r(3,mm1);\
02816                     packuswb_r2r(mm7,mm1);\
02817                     movd_r2m(mm1,dst[0]);
02818 #endif
02819 
02820 /* filter parameters: [-1 4 2 4 -1] // 8 */
02821 static void deinterlace_line(uint8_t *dst,
02822                              const uint8_t *lum_m4, const uint8_t *lum_m3,
02823                              const uint8_t *lum_m2, const uint8_t *lum_m1,
02824                              const uint8_t *lum,
02825                              int size)
02826 {
02827 #if !HAVE_MMX
02828     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
02829     int sum;
02830 
02831     for(;size > 0;size--) {
02832         sum = -lum_m4[0];
02833         sum += lum_m3[0] << 2;
02834         sum += lum_m2[0] << 1;
02835         sum += lum_m1[0] << 2;
02836         sum += -lum[0];
02837         dst[0] = cm[(sum + 4) >> 3];
02838         lum_m4++;
02839         lum_m3++;
02840         lum_m2++;
02841         lum_m1++;
02842         lum++;
02843         dst++;
02844     }
02845 #else
02846 
02847     {
02848         pxor_r2r(mm7,mm7);
02849         movq_m2r(ff_pw_4,mm6);
02850     }
02851     for (;size > 3; size-=4) {
02852         DEINT_LINE_LUM
02853         lum_m4+=4;
02854         lum_m3+=4;
02855         lum_m2+=4;
02856         lum_m1+=4;
02857         lum+=4;
02858         dst+=4;
02859     }
02860 #endif
02861 }
02862 static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
02863                              int size)
02864 {
02865 #if !HAVE_MMX
02866     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
02867     int sum;
02868 
02869     for(;size > 0;size--) {
02870         sum = -lum_m4[0];
02871         sum += lum_m3[0] << 2;
02872         sum += lum_m2[0] << 1;
02873         lum_m4[0]=lum_m2[0];
02874         sum += lum_m1[0] << 2;
02875         sum += -lum[0];
02876         lum_m2[0] = cm[(sum + 4) >> 3];
02877         lum_m4++;
02878         lum_m3++;
02879         lum_m2++;
02880         lum_m1++;
02881         lum++;
02882     }
02883 #else
02884 
02885     {
02886         pxor_r2r(mm7,mm7);
02887         movq_m2r(ff_pw_4,mm6);
02888     }
02889     for (;size > 3; size-=4) {
02890         DEINT_INPLACE_LINE_LUM
02891         lum_m4+=4;
02892         lum_m3+=4;
02893         lum_m2+=4;
02894         lum_m1+=4;
02895         lum+=4;
02896     }
02897 #endif
02898 }
02899 
02900 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
02901    top field is copied as is, but the bottom field is deinterlaced
02902    against the top field. */
02903 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
02904                                     const uint8_t *src1, int src_wrap,
02905                                     int width, int height)
02906 {
02907     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
02908     int y;
02909 
02910     src_m2 = src1;
02911     src_m1 = src1;
02912     src_0=&src_m1[src_wrap];
02913     src_p1=&src_0[src_wrap];
02914     src_p2=&src_p1[src_wrap];
02915     for(y=0;y<(height-2);y+=2) {
02916         memcpy(dst,src_m1,width);
02917         dst += dst_wrap;
02918         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
02919         src_m2 = src_0;
02920         src_m1 = src_p1;
02921         src_0 = src_p2;
02922         src_p1 += 2*src_wrap;
02923         src_p2 += 2*src_wrap;
02924         dst += dst_wrap;
02925     }
02926     memcpy(dst,src_m1,width);
02927     dst += dst_wrap;
02928     /* do last line */
02929     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
02930 }
02931 
02932 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
02933                                              int width, int height)
02934 {
02935     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
02936     int y;
02937     uint8_t *buf;
02938     buf = (uint8_t*)av_malloc(width);
02939 
02940     src_m1 = src1;
02941     memcpy(buf,src_m1,width);
02942     src_0=&src_m1[src_wrap];
02943     src_p1=&src_0[src_wrap];
02944     src_p2=&src_p1[src_wrap];
02945     for(y=0;y<(height-2);y+=2) {
02946         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
02947         src_m1 = src_p1;
02948         src_0 = src_p2;
02949         src_p1 += 2*src_wrap;
02950         src_p2 += 2*src_wrap;
02951     }
02952     /* do last line */
02953     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
02954     av_free(buf);
02955 }
02956 
02957 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
02958                           int pix_fmt, int width, int height)
02959 {
02960     int i;
02961 
02962     if (pix_fmt != PIX_FMT_YUV420P &&
02963         pix_fmt != PIX_FMT_YUV422P &&
02964         pix_fmt != PIX_FMT_YUV444P &&
02965         pix_fmt != PIX_FMT_YUV411P &&
02966         pix_fmt != PIX_FMT_GRAY8)
02967         return -1;
02968     if ((width & 3) != 0 || (height & 3) != 0)
02969         return -1;
02970 
02971     for(i=0;i<3;i++) {
02972         if (i == 1) {
02973             switch(pix_fmt) {
02974             case PIX_FMT_YUV420P:
02975                 width >>= 1;
02976                 height >>= 1;
02977                 break;
02978             case PIX_FMT_YUV422P:
02979                 width >>= 1;
02980                 break;
02981             case PIX_FMT_YUV411P:
02982                 width >>= 2;
02983                 break;
02984             default:
02985                 break;
02986             }
02987             if (pix_fmt == PIX_FMT_GRAY8) {
02988                 break;
02989             }
02990         }
02991         if (src == dst) {
02992             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
02993                                  width, height);
02994         } else {
02995             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
02996                                         src->data[i], src->linesize[i],
02997                                         width, height);
02998         }
02999     }
03000     emms_c();
03001     return 0;
03002 }
03003 

Generated on Tue Nov 4 2014 12:59:22 for ffmpeg by  doxygen 1.7.1