• 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 #include "internal.h"
00037 #include "imgconvert.h"
00038 #include "libavutil/pixdesc.h"
00039 
00040 #if HAVE_MMX
00041 #include "x86/mmx.h"
00042 #include "x86/dsputil_mmx.h"
00043 #endif
00044 
00045 #define xglue(x, y) x ## y
00046 #define glue(x, y) xglue(x, y)
00047 
00048 #define FF_COLOR_RGB      0 
00049 #define FF_COLOR_GRAY     1 
00050 #define FF_COLOR_YUV      2 
00051 #define FF_COLOR_YUV_JPEG 3 
00053 #define FF_PIXEL_PLANAR   0 
00054 #define FF_PIXEL_PACKED   1 
00055 #define FF_PIXEL_PALETTE  2  
00057 typedef struct PixFmtInfo {
00058     uint8_t nb_channels;     
00059     uint8_t color_type;      
00060     uint8_t pixel_type;      
00061     uint8_t is_alpha : 1;    
00062     uint8_t depth;           
00063 } PixFmtInfo;
00064 
00065 /* this table gives more information about formats */
00066 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
00067     /* YUV formats */
00068     [PIX_FMT_YUV420P] = {
00069         .nb_channels = 3,
00070         .color_type = FF_COLOR_YUV,
00071         .pixel_type = FF_PIXEL_PLANAR,
00072         .depth = 8,
00073     },
00074     [PIX_FMT_YUV422P] = {
00075         .nb_channels = 3,
00076         .color_type = FF_COLOR_YUV,
00077         .pixel_type = FF_PIXEL_PLANAR,
00078         .depth = 8,
00079     },
00080     [PIX_FMT_YUV444P] = {
00081         .nb_channels = 3,
00082         .color_type = FF_COLOR_YUV,
00083         .pixel_type = FF_PIXEL_PLANAR,
00084         .depth = 8,
00085     },
00086     [PIX_FMT_YUYV422] = {
00087         .nb_channels = 1,
00088         .color_type = FF_COLOR_YUV,
00089         .pixel_type = FF_PIXEL_PACKED,
00090         .depth = 8,
00091     },
00092     [PIX_FMT_UYVY422] = {
00093         .nb_channels = 1,
00094         .color_type = FF_COLOR_YUV,
00095         .pixel_type = FF_PIXEL_PACKED,
00096         .depth = 8,
00097     },
00098     [PIX_FMT_YUV410P] = {
00099         .nb_channels = 3,
00100         .color_type = FF_COLOR_YUV,
00101         .pixel_type = FF_PIXEL_PLANAR,
00102         .depth = 8,
00103     },
00104     [PIX_FMT_YUV411P] = {
00105         .nb_channels = 3,
00106         .color_type = FF_COLOR_YUV,
00107         .pixel_type = FF_PIXEL_PLANAR,
00108         .depth = 8,
00109     },
00110     [PIX_FMT_YUV440P] = {
00111         .nb_channels = 3,
00112         .color_type = FF_COLOR_YUV,
00113         .pixel_type = FF_PIXEL_PLANAR,
00114         .depth = 8,
00115     },
00116     [PIX_FMT_YUV420P16LE] = {
00117         .nb_channels = 3,
00118         .color_type = FF_COLOR_YUV,
00119         .pixel_type = FF_PIXEL_PLANAR,
00120         .depth = 16,
00121     },
00122     [PIX_FMT_YUV422P16LE] = {
00123         .nb_channels = 3,
00124         .color_type = FF_COLOR_YUV,
00125         .pixel_type = FF_PIXEL_PLANAR,
00126         .depth = 16,
00127     },
00128     [PIX_FMT_YUV444P16LE] = {
00129         .nb_channels = 3,
00130         .color_type = FF_COLOR_YUV,
00131         .pixel_type = FF_PIXEL_PLANAR,
00132         .depth = 16,
00133     },
00134     [PIX_FMT_YUV420P16BE] = {
00135         .nb_channels = 3,
00136         .color_type = FF_COLOR_YUV,
00137         .pixel_type = FF_PIXEL_PLANAR,
00138         .depth = 16,
00139     },
00140     [PIX_FMT_YUV422P16BE] = {
00141         .nb_channels = 3,
00142         .color_type = FF_COLOR_YUV,
00143         .pixel_type = FF_PIXEL_PLANAR,
00144         .depth = 16,
00145     },
00146     [PIX_FMT_YUV444P16BE] = {
00147         .nb_channels = 3,
00148         .color_type = FF_COLOR_YUV,
00149         .pixel_type = FF_PIXEL_PLANAR,
00150         .depth = 16,
00151     },
00152 
00153 
00154     /* YUV formats with alpha plane */
00155     [PIX_FMT_YUVA420P] = {
00156         .nb_channels = 4,
00157         .color_type = FF_COLOR_YUV,
00158         .pixel_type = FF_PIXEL_PLANAR,
00159         .depth = 8,
00160     },
00161 
00162     /* JPEG YUV */
00163     [PIX_FMT_YUVJ420P] = {
00164         .nb_channels = 3,
00165         .color_type = FF_COLOR_YUV_JPEG,
00166         .pixel_type = FF_PIXEL_PLANAR,
00167         .depth = 8,
00168     },
00169     [PIX_FMT_YUVJ422P] = {
00170         .nb_channels = 3,
00171         .color_type = FF_COLOR_YUV_JPEG,
00172         .pixel_type = FF_PIXEL_PLANAR,
00173         .depth = 8,
00174     },
00175     [PIX_FMT_YUVJ444P] = {
00176         .nb_channels = 3,
00177         .color_type = FF_COLOR_YUV_JPEG,
00178         .pixel_type = FF_PIXEL_PLANAR,
00179         .depth = 8,
00180     },
00181     [PIX_FMT_YUVJ440P] = {
00182         .nb_channels = 3,
00183         .color_type = FF_COLOR_YUV_JPEG,
00184         .pixel_type = FF_PIXEL_PLANAR,
00185         .depth = 8,
00186     },
00187 
00188     /* RGB formats */
00189     [PIX_FMT_RGB24] = {
00190         .nb_channels = 3,
00191         .color_type = FF_COLOR_RGB,
00192         .pixel_type = FF_PIXEL_PACKED,
00193         .depth = 8,
00194     },
00195     [PIX_FMT_BGR24] = {
00196         .nb_channels = 3,
00197         .color_type = FF_COLOR_RGB,
00198         .pixel_type = FF_PIXEL_PACKED,
00199         .depth = 8,
00200     },
00201     [PIX_FMT_ARGB] = {
00202         .nb_channels = 4, .is_alpha = 1,
00203         .color_type = FF_COLOR_RGB,
00204         .pixel_type = FF_PIXEL_PACKED,
00205         .depth = 8,
00206     },
00207     [PIX_FMT_RGB48BE] = {
00208         .nb_channels = 3,
00209         .color_type = FF_COLOR_RGB,
00210         .pixel_type = FF_PIXEL_PACKED,
00211         .depth = 16,
00212     },
00213     [PIX_FMT_RGB48LE] = {
00214         .nb_channels = 3,
00215         .color_type = FF_COLOR_RGB,
00216         .pixel_type = FF_PIXEL_PACKED,
00217         .depth = 16,
00218     },
00219     [PIX_FMT_RGB565BE] = {
00220         .nb_channels = 3,
00221         .color_type = FF_COLOR_RGB,
00222         .pixel_type = FF_PIXEL_PACKED,
00223         .depth = 5,
00224     },
00225     [PIX_FMT_RGB565LE] = {
00226         .nb_channels = 3,
00227         .color_type = FF_COLOR_RGB,
00228         .pixel_type = FF_PIXEL_PACKED,
00229         .depth = 5,
00230     },
00231     [PIX_FMT_RGB555BE] = {
00232         .nb_channels = 3,
00233         .color_type = FF_COLOR_RGB,
00234         .pixel_type = FF_PIXEL_PACKED,
00235         .depth = 5,
00236     },
00237     [PIX_FMT_RGB555LE] = {
00238         .nb_channels = 3,
00239         .color_type = FF_COLOR_RGB,
00240         .pixel_type = FF_PIXEL_PACKED,
00241         .depth = 5,
00242     },
00243     [PIX_FMT_RGB444BE] = {
00244         .nb_channels = 3,
00245         .color_type = FF_COLOR_RGB,
00246         .pixel_type = FF_PIXEL_PACKED,
00247         .depth = 4,
00248     },
00249     [PIX_FMT_RGB444LE] = {
00250         .nb_channels = 3,
00251         .color_type = FF_COLOR_RGB,
00252         .pixel_type = FF_PIXEL_PACKED,
00253         .depth = 4,
00254     },
00255 
00256     /* gray / mono formats */
00257     [PIX_FMT_GRAY16BE] = {
00258         .nb_channels = 1,
00259         .color_type = FF_COLOR_GRAY,
00260         .pixel_type = FF_PIXEL_PLANAR,
00261         .depth = 16,
00262     },
00263     [PIX_FMT_GRAY16LE] = {
00264         .nb_channels = 1,
00265         .color_type = FF_COLOR_GRAY,
00266         .pixel_type = FF_PIXEL_PLANAR,
00267         .depth = 16,
00268     },
00269     [PIX_FMT_GRAY8] = {
00270         .nb_channels = 1,
00271         .color_type = FF_COLOR_GRAY,
00272         .pixel_type = FF_PIXEL_PLANAR,
00273         .depth = 8,
00274     },
00275     [PIX_FMT_MONOWHITE] = {
00276         .nb_channels = 1,
00277         .color_type = FF_COLOR_GRAY,
00278         .pixel_type = FF_PIXEL_PLANAR,
00279         .depth = 1,
00280     },
00281     [PIX_FMT_MONOBLACK] = {
00282         .nb_channels = 1,
00283         .color_type = FF_COLOR_GRAY,
00284         .pixel_type = FF_PIXEL_PLANAR,
00285         .depth = 1,
00286     },
00287 
00288     /* paletted formats */
00289     [PIX_FMT_PAL8] = {
00290         .nb_channels = 4, .is_alpha = 1,
00291         .color_type = FF_COLOR_RGB,
00292         .pixel_type = FF_PIXEL_PALETTE,
00293         .depth = 8,
00294     },
00295     [PIX_FMT_UYYVYY411] = {
00296         .nb_channels = 1,
00297         .color_type = FF_COLOR_YUV,
00298         .pixel_type = FF_PIXEL_PACKED,
00299         .depth = 8,
00300     },
00301     [PIX_FMT_ABGR] = {
00302         .nb_channels = 4, .is_alpha = 1,
00303         .color_type = FF_COLOR_RGB,
00304         .pixel_type = FF_PIXEL_PACKED,
00305         .depth = 8,
00306     },
00307     [PIX_FMT_BGR565BE] = {
00308         .nb_channels = 3,
00309         .color_type = FF_COLOR_RGB,
00310         .pixel_type = FF_PIXEL_PACKED,
00311         .depth = 5,
00312     },
00313     [PIX_FMT_BGR565LE] = {
00314         .nb_channels = 3,
00315         .color_type = FF_COLOR_RGB,
00316         .pixel_type = FF_PIXEL_PACKED,
00317         .depth = 5,
00318     },
00319     [PIX_FMT_BGR555BE] = {
00320         .nb_channels = 3,
00321         .color_type = FF_COLOR_RGB,
00322         .pixel_type = FF_PIXEL_PACKED,
00323         .depth = 5,
00324     },
00325     [PIX_FMT_BGR555LE] = {
00326         .nb_channels = 3,
00327         .color_type = FF_COLOR_RGB,
00328         .pixel_type = FF_PIXEL_PACKED,
00329         .depth = 5,
00330     },
00331     [PIX_FMT_BGR444BE] = {
00332         .nb_channels = 3,
00333         .color_type = FF_COLOR_RGB,
00334         .pixel_type = FF_PIXEL_PACKED,
00335         .depth = 4,
00336     },
00337     [PIX_FMT_BGR444LE] = {
00338         .nb_channels = 3,
00339         .color_type = FF_COLOR_RGB,
00340         .pixel_type = FF_PIXEL_PACKED,
00341         .depth = 4,
00342     },
00343     [PIX_FMT_RGB8] = {
00344         .nb_channels = 1,
00345         .color_type = FF_COLOR_RGB,
00346         .pixel_type = FF_PIXEL_PACKED,
00347         .depth = 8,
00348     },
00349     [PIX_FMT_RGB4] = {
00350         .nb_channels = 1,
00351         .color_type = FF_COLOR_RGB,
00352         .pixel_type = FF_PIXEL_PACKED,
00353         .depth = 4,
00354     },
00355     [PIX_FMT_RGB4_BYTE] = {
00356         .nb_channels = 1,
00357         .color_type = FF_COLOR_RGB,
00358         .pixel_type = FF_PIXEL_PACKED,
00359         .depth = 8,
00360     },
00361     [PIX_FMT_BGR8] = {
00362         .nb_channels = 1,
00363         .color_type = FF_COLOR_RGB,
00364         .pixel_type = FF_PIXEL_PACKED,
00365         .depth = 8,
00366     },
00367     [PIX_FMT_BGR4] = {
00368         .nb_channels = 1,
00369         .color_type = FF_COLOR_RGB,
00370         .pixel_type = FF_PIXEL_PACKED,
00371         .depth = 4,
00372     },
00373     [PIX_FMT_BGR4_BYTE] = {
00374         .nb_channels = 1,
00375         .color_type = FF_COLOR_RGB,
00376         .pixel_type = FF_PIXEL_PACKED,
00377         .depth = 8,
00378     },
00379     [PIX_FMT_NV12] = {
00380         .nb_channels = 2,
00381         .color_type = FF_COLOR_YUV,
00382         .pixel_type = FF_PIXEL_PLANAR,
00383         .depth = 8,
00384     },
00385     [PIX_FMT_NV21] = {
00386         .nb_channels = 2,
00387         .color_type = FF_COLOR_YUV,
00388         .pixel_type = FF_PIXEL_PLANAR,
00389         .depth = 8,
00390     },
00391 
00392     [PIX_FMT_BGRA] = {
00393         .nb_channels = 4, .is_alpha = 1,
00394         .color_type = FF_COLOR_RGB,
00395         .pixel_type = FF_PIXEL_PACKED,
00396         .depth = 8,
00397     },
00398     [PIX_FMT_RGBA] = {
00399         .nb_channels = 4, .is_alpha = 1,
00400         .color_type = FF_COLOR_RGB,
00401         .pixel_type = FF_PIXEL_PACKED,
00402         .depth = 8,
00403     },
00404 };
00405 
00406 void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift)
00407 {
00408     *h_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
00409     *v_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
00410 }
00411 
00412 const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt)
00413 {
00414     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
00415         return NULL;
00416     else
00417         return av_pix_fmt_descriptors[pix_fmt].name;
00418 }
00419 
00420 #if LIBAVCODEC_VERSION_MAJOR < 53
00421 enum PixelFormat avcodec_get_pix_fmt(const char *name)
00422 {
00423     return av_get_pix_fmt(name);
00424 }
00425 #endif
00426 
00427 void avcodec_pix_fmt_string (char *buf, int buf_size, enum PixelFormat pix_fmt)
00428 {
00429     /* print header */
00430     if (pix_fmt < 0)
00431         snprintf (buf, buf_size,
00432                   "name      " " nb_channels" " depth" " is_alpha"
00433             );
00434     else{
00435         PixFmtInfo info= pix_fmt_info[pix_fmt];
00436 
00437         char is_alpha_char= info.is_alpha ? 'y' : 'n';
00438 
00439         snprintf (buf, buf_size,
00440                   "%-11s %5d %9d %6c",
00441                   av_pix_fmt_descriptors[pix_fmt].name,
00442                   info.nb_channels,
00443                   info.depth,
00444                   is_alpha_char
00445             );
00446     }
00447 }
00448 
00449 int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
00450 {
00451     return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
00452 }
00453 
00454 int ff_set_systematic_pal(uint32_t pal[256], enum PixelFormat pix_fmt){
00455     int i;
00456 
00457     for(i=0; i<256; i++){
00458         int r,g,b;
00459 
00460         switch(pix_fmt) {
00461         case PIX_FMT_RGB8:
00462             r= (i>>5    )*36;
00463             g= ((i>>2)&7)*36;
00464             b= (i&3     )*85;
00465             break;
00466         case PIX_FMT_BGR8:
00467             b= (i>>6    )*85;
00468             g= ((i>>3)&7)*36;
00469             r= (i&7     )*36;
00470             break;
00471         case PIX_FMT_RGB4_BYTE:
00472             r= (i>>3    )*255;
00473             g= ((i>>1)&3)*85;
00474             b= (i&1     )*255;
00475             break;
00476         case PIX_FMT_BGR4_BYTE:
00477             b= (i>>3    )*255;
00478             g= ((i>>1)&3)*85;
00479             r= (i&1     )*255;
00480             break;
00481         case PIX_FMT_GRAY8:
00482             r=b=g= i;
00483             break;
00484         default:
00485             return -1;
00486         }
00487         pal[i] =  b + (g<<8) + (r<<16);
00488     }
00489 
00490     return 0;
00491 }
00492 
00493 int ff_fill_linesize(AVPicture *picture, enum PixelFormat pix_fmt, int width)
00494 {
00495     int i;
00496     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00497     int max_plane_step     [4];
00498     int max_plane_step_comp[4];
00499 
00500     memset(picture->linesize, 0, sizeof(picture->linesize));
00501 
00502     if (desc->flags & PIX_FMT_HWACCEL)
00503         return -1;
00504 
00505     if (desc->flags & PIX_FMT_BITSTREAM) {
00506         picture->linesize[0] = (width * (desc->comp[0].step_minus1+1) + 7) >> 3;
00507         return 0;
00508     }
00509 
00510     memset(max_plane_step     , 0, sizeof(max_plane_step     ));
00511     memset(max_plane_step_comp, 0, sizeof(max_plane_step_comp));
00512     for (i = 0; i < 4; i++) {
00513         const AVComponentDescriptor *comp = &(desc->comp[i]);
00514         if ((comp->step_minus1+1) > max_plane_step[comp->plane]) {
00515             max_plane_step     [comp->plane] = comp->step_minus1+1;
00516             max_plane_step_comp[comp->plane] = i;
00517         }
00518     }
00519 
00520     for (i = 0; i < 4; i++) {
00521         int s = (max_plane_step_comp[i] == 1 || max_plane_step_comp[i] == 2) ? desc->log2_chroma_w : 0;
00522         picture->linesize[i] = max_plane_step[i] * (((width + (1 << s) - 1)) >> s);
00523     }
00524 
00525     return 0;
00526 }
00527 
00528 int ff_fill_pointer(AVPicture *picture, uint8_t *ptr, enum PixelFormat pix_fmt,
00529                     int height)
00530 {
00531     int size, h2, size2;
00532     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00533 
00534     size = picture->linesize[0] * height;
00535     switch(pix_fmt) {
00536     case PIX_FMT_YUV420P:
00537     case PIX_FMT_YUV422P:
00538     case PIX_FMT_YUV444P:
00539     case PIX_FMT_YUV410P:
00540     case PIX_FMT_YUV411P:
00541     case PIX_FMT_YUV440P:
00542     case PIX_FMT_YUVJ420P:
00543     case PIX_FMT_YUVJ422P:
00544     case PIX_FMT_YUVJ444P:
00545     case PIX_FMT_YUVJ440P:
00546     case PIX_FMT_YUV420P16LE:
00547     case PIX_FMT_YUV422P16LE:
00548     case PIX_FMT_YUV444P16LE:
00549     case PIX_FMT_YUV420P16BE:
00550     case PIX_FMT_YUV422P16BE:
00551     case PIX_FMT_YUV444P16BE:
00552         h2 = (height + (1 << desc->log2_chroma_h) - 1) >> desc->log2_chroma_h;
00553         size2 = picture->linesize[1] * h2;
00554         picture->data[0] = ptr;
00555         picture->data[1] = picture->data[0] + size;
00556         picture->data[2] = picture->data[1] + size2;
00557         picture->data[3] = NULL;
00558         return size + 2 * size2;
00559     case PIX_FMT_YUVA420P:
00560         h2 = (height + (1 << desc->log2_chroma_h) - 1) >> desc->log2_chroma_h;
00561         size2 = picture->linesize[1] * h2;
00562         picture->data[0] = ptr;
00563         picture->data[1] = picture->data[0] + size;
00564         picture->data[2] = picture->data[1] + size2;
00565         picture->data[3] = picture->data[1] + size2 + size2;
00566         return 2 * size + 2 * size2;
00567     case PIX_FMT_NV12:
00568     case PIX_FMT_NV21:
00569         h2 = (height + (1 << desc->log2_chroma_h) - 1) >> desc->log2_chroma_h;
00570         size2 = picture->linesize[1] * h2;
00571         picture->data[0] = ptr;
00572         picture->data[1] = picture->data[0] + size;
00573         picture->data[2] = NULL;
00574         picture->data[3] = NULL;
00575         return size + size2;
00576     case PIX_FMT_RGB24:
00577     case PIX_FMT_BGR24:
00578     case PIX_FMT_ARGB:
00579     case PIX_FMT_ABGR:
00580     case PIX_FMT_RGBA:
00581     case PIX_FMT_BGRA:
00582     case PIX_FMT_RGB48BE:
00583     case PIX_FMT_RGB48LE:
00584     case PIX_FMT_GRAY16BE:
00585     case PIX_FMT_GRAY16LE:
00586     case PIX_FMT_BGR444BE:
00587     case PIX_FMT_BGR444LE:
00588     case PIX_FMT_BGR555BE:
00589     case PIX_FMT_BGR555LE:
00590     case PIX_FMT_BGR565BE:
00591     case PIX_FMT_BGR565LE:
00592     case PIX_FMT_RGB444BE:
00593     case PIX_FMT_RGB444LE:
00594     case PIX_FMT_RGB555BE:
00595     case PIX_FMT_RGB555LE:
00596     case PIX_FMT_RGB565BE:
00597     case PIX_FMT_RGB565LE:
00598     case PIX_FMT_YUYV422:
00599     case PIX_FMT_UYVY422:
00600     case PIX_FMT_UYYVYY411:
00601     case PIX_FMT_RGB4:
00602     case PIX_FMT_BGR4:
00603     case PIX_FMT_MONOWHITE:
00604     case PIX_FMT_MONOBLACK:
00605     case PIX_FMT_Y400A:
00606         picture->data[0] = ptr;
00607         picture->data[1] = NULL;
00608         picture->data[2] = NULL;
00609         picture->data[3] = NULL;
00610         return size;
00611     case PIX_FMT_PAL8:
00612     case PIX_FMT_RGB8:
00613     case PIX_FMT_BGR8:
00614     case PIX_FMT_RGB4_BYTE:
00615     case PIX_FMT_BGR4_BYTE:
00616     case PIX_FMT_GRAY8:
00617         size2 = (size + 3) & ~3;
00618         picture->data[0] = ptr;
00619         picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
00620         picture->data[2] = NULL;
00621         picture->data[3] = NULL;
00622         return size2 + 256 * 4;
00623     default:
00624         picture->data[0] = NULL;
00625         picture->data[1] = NULL;
00626         picture->data[2] = NULL;
00627         picture->data[3] = NULL;
00628         return -1;
00629     }
00630 }
00631 
00632 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00633                    enum PixelFormat pix_fmt, int width, int height)
00634 {
00635 
00636     if(avcodec_check_dimensions(NULL, width, height))
00637         return -1;
00638 
00639     if (ff_fill_linesize(picture, pix_fmt, width))
00640         return -1;
00641 
00642     return ff_fill_pointer(picture, ptr, pix_fmt, height);
00643 }
00644 
00645 int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
00646                      unsigned char *dest, int dest_size)
00647 {
00648     const PixFmtInfo* pf = &pix_fmt_info[pix_fmt];
00649     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00650     int i, j, w, ow, h, oh, data_planes;
00651     const unsigned char* s;
00652     int size = avpicture_get_size(pix_fmt, width, height);
00653 
00654     if (size > dest_size || size < 0)
00655         return -1;
00656 
00657     if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
00658         if (pix_fmt == PIX_FMT_YUYV422 ||
00659             pix_fmt == PIX_FMT_UYVY422 ||
00660             pix_fmt == PIX_FMT_BGR565BE ||
00661             pix_fmt == PIX_FMT_BGR565LE ||
00662             pix_fmt == PIX_FMT_BGR555BE ||
00663             pix_fmt == PIX_FMT_BGR555LE ||
00664             pix_fmt == PIX_FMT_BGR444BE ||
00665             pix_fmt == PIX_FMT_BGR444LE ||
00666             pix_fmt == PIX_FMT_RGB565BE ||
00667             pix_fmt == PIX_FMT_RGB565LE ||
00668             pix_fmt == PIX_FMT_RGB555BE ||
00669             pix_fmt == PIX_FMT_RGB555LE ||
00670             pix_fmt == PIX_FMT_RGB444BE ||
00671             pix_fmt == PIX_FMT_RGB444LE)
00672             w = width * 2;
00673         else if (pix_fmt == PIX_FMT_UYYVYY411)
00674             w = width + width/2;
00675         else if (pix_fmt == PIX_FMT_PAL8)
00676             w = width;
00677         else
00678             w = width * (pf->depth * pf->nb_channels / 8);
00679 
00680         data_planes = 1;
00681         h = height;
00682     } else {
00683         data_planes = pf->nb_channels;
00684         w = (width*pf->depth + 7)/8;
00685         h = height;
00686     }
00687 
00688     ow = w;
00689     oh = h;
00690 
00691     for (i=0; i<data_planes; i++) {
00692         if (i == 1) {
00693             w = (- ((-width) >> desc->log2_chroma_w) * pf->depth + 7) / 8;
00694             h = -((-height) >> desc->log2_chroma_h);
00695             if (pix_fmt == PIX_FMT_NV12 || pix_fmt == PIX_FMT_NV21)
00696                 w <<= 1;
00697         } else if (i == 3) {
00698             w = ow;
00699             h = oh;
00700         }
00701         s = src->data[i];
00702         for(j=0; j<h; j++) {
00703             memcpy(dest, s, w);
00704             dest += w;
00705             s += src->linesize[i];
00706         }
00707     }
00708 
00709     if (pf->pixel_type == FF_PIXEL_PALETTE)
00710         memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00711 
00712     return size;
00713 }
00714 
00715 int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height)
00716 {
00717     AVPicture dummy_pict;
00718     if(avcodec_check_dimensions(NULL, width, height))
00719         return -1;
00720     switch (pix_fmt) {
00721     case PIX_FMT_RGB8:
00722     case PIX_FMT_BGR8:
00723     case PIX_FMT_RGB4_BYTE:
00724     case PIX_FMT_BGR4_BYTE:
00725     case PIX_FMT_GRAY8:
00726         // do not include palette for these pseudo-paletted formats
00727         return width * height;
00728     }
00729     return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00730 }
00731 
00732 int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
00733                              int has_alpha)
00734 {
00735     const PixFmtInfo *pf, *ps;
00736     const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
00737     const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
00738     int loss;
00739 
00740     ps = &pix_fmt_info[src_pix_fmt];
00741 
00742     /* compute loss */
00743     loss = 0;
00744     pf = &pix_fmt_info[dst_pix_fmt];
00745     if (pf->depth < ps->depth ||
00746         ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE ||
00747           dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) &&
00748          (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE ||
00749           src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE)))
00750         loss |= FF_LOSS_DEPTH;
00751     if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
00752         dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
00753         loss |= FF_LOSS_RESOLUTION;
00754     switch(pf->color_type) {
00755     case FF_COLOR_RGB:
00756         if (ps->color_type != FF_COLOR_RGB &&
00757             ps->color_type != FF_COLOR_GRAY)
00758             loss |= FF_LOSS_COLORSPACE;
00759         break;
00760     case FF_COLOR_GRAY:
00761         if (ps->color_type != FF_COLOR_GRAY)
00762             loss |= FF_LOSS_COLORSPACE;
00763         break;
00764     case FF_COLOR_YUV:
00765         if (ps->color_type != FF_COLOR_YUV)
00766             loss |= FF_LOSS_COLORSPACE;
00767         break;
00768     case FF_COLOR_YUV_JPEG:
00769         if (ps->color_type != FF_COLOR_YUV_JPEG &&
00770             ps->color_type != FF_COLOR_YUV &&
00771             ps->color_type != FF_COLOR_GRAY)
00772             loss |= FF_LOSS_COLORSPACE;
00773         break;
00774     default:
00775         /* fail safe test */
00776         if (ps->color_type != pf->color_type)
00777             loss |= FF_LOSS_COLORSPACE;
00778         break;
00779     }
00780     if (pf->color_type == FF_COLOR_GRAY &&
00781         ps->color_type != FF_COLOR_GRAY)
00782         loss |= FF_LOSS_CHROMA;
00783     if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00784         loss |= FF_LOSS_ALPHA;
00785     if (pf->pixel_type == FF_PIXEL_PALETTE &&
00786         (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00787         loss |= FF_LOSS_COLORQUANT;
00788     return loss;
00789 }
00790 
00791 static int avg_bits_per_pixel(enum PixelFormat pix_fmt)
00792 {
00793     int bits;
00794     const PixFmtInfo *pf;
00795     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00796 
00797     pf = &pix_fmt_info[pix_fmt];
00798     switch(pf->pixel_type) {
00799     case FF_PIXEL_PACKED:
00800         switch(pix_fmt) {
00801         case PIX_FMT_YUYV422:
00802         case PIX_FMT_UYVY422:
00803         case PIX_FMT_RGB565BE:
00804         case PIX_FMT_RGB565LE:
00805         case PIX_FMT_RGB555BE:
00806         case PIX_FMT_RGB555LE:
00807         case PIX_FMT_RGB444BE:
00808         case PIX_FMT_RGB444LE:
00809         case PIX_FMT_BGR565BE:
00810         case PIX_FMT_BGR565LE:
00811         case PIX_FMT_BGR555BE:
00812         case PIX_FMT_BGR555LE:
00813         case PIX_FMT_BGR444BE:
00814         case PIX_FMT_BGR444LE:
00815             bits = 16;
00816             break;
00817         case PIX_FMT_UYYVYY411:
00818             bits = 12;
00819             break;
00820         default:
00821             bits = pf->depth * pf->nb_channels;
00822             break;
00823         }
00824         break;
00825     case FF_PIXEL_PLANAR:
00826         if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
00827             bits = pf->depth * pf->nb_channels;
00828         } else {
00829             bits = pf->depth + ((2 * pf->depth) >>
00830                                 (desc->log2_chroma_w + desc->log2_chroma_h));
00831         }
00832         break;
00833     case FF_PIXEL_PALETTE:
00834         bits = 8;
00835         break;
00836     default:
00837         bits = -1;
00838         break;
00839     }
00840     return bits;
00841 }
00842 
00843 static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
00844                                       enum PixelFormat src_pix_fmt,
00845                                       int has_alpha,
00846                                       int loss_mask)
00847 {
00848     int dist, i, loss, min_dist;
00849     enum PixelFormat dst_pix_fmt;
00850 
00851     /* find exact color match with smallest size */
00852     dst_pix_fmt = PIX_FMT_NONE;
00853     min_dist = 0x7fffffff;
00854     for(i = 0;i < PIX_FMT_NB; i++) {
00855         if (pix_fmt_mask & (1ULL << i)) {
00856             loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00857             if (loss == 0) {
00858                 dist = avg_bits_per_pixel(i);
00859                 if (dist < min_dist) {
00860                     min_dist = dist;
00861                     dst_pix_fmt = i;
00862                 }
00863             }
00864         }
00865     }
00866     return dst_pix_fmt;
00867 }
00868 
00869 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
00870                               int has_alpha, int *loss_ptr)
00871 {
00872     enum PixelFormat dst_pix_fmt;
00873     int loss_mask, i;
00874     static const int loss_mask_order[] = {
00875         ~0, /* no loss first */
00876         ~FF_LOSS_ALPHA,
00877         ~FF_LOSS_RESOLUTION,
00878         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00879         ~FF_LOSS_COLORQUANT,
00880         ~FF_LOSS_DEPTH,
00881         0,
00882     };
00883 
00884     /* try with successive loss */
00885     i = 0;
00886     for(;;) {
00887         loss_mask = loss_mask_order[i++];
00888         dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00889                                                  has_alpha, loss_mask);
00890         if (dst_pix_fmt >= 0)
00891             goto found;
00892         if (loss_mask == 0)
00893             break;
00894     }
00895     return PIX_FMT_NONE;
00896  found:
00897     if (loss_ptr)
00898         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00899     return dst_pix_fmt;
00900 }
00901 
00902 void ff_img_copy_plane(uint8_t *dst, int dst_wrap,
00903                            const uint8_t *src, int src_wrap,
00904                            int width, int height)
00905 {
00906     if((!dst) || (!src))
00907         return;
00908     for(;height > 0; height--) {
00909         memcpy(dst, src, width);
00910         dst += dst_wrap;
00911         src += src_wrap;
00912     }
00913 }
00914 
00915 int ff_get_plane_bytewidth(enum PixelFormat pix_fmt, int width, int plane)
00916 {
00917     int bits;
00918     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00919     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00920 
00921     pf = &pix_fmt_info[pix_fmt];
00922     switch(pf->pixel_type) {
00923     case FF_PIXEL_PACKED:
00924         switch(pix_fmt) {
00925         case PIX_FMT_YUYV422:
00926         case PIX_FMT_UYVY422:
00927         case PIX_FMT_RGB565BE:
00928         case PIX_FMT_RGB565LE:
00929         case PIX_FMT_RGB555BE:
00930         case PIX_FMT_RGB555LE:
00931         case PIX_FMT_RGB444BE:
00932         case PIX_FMT_RGB444LE:
00933         case PIX_FMT_BGR565BE:
00934         case PIX_FMT_BGR565LE:
00935         case PIX_FMT_BGR555BE:
00936         case PIX_FMT_BGR555LE:
00937         case PIX_FMT_BGR444BE:
00938         case PIX_FMT_BGR444LE:
00939             bits = 16;
00940             break;
00941         case PIX_FMT_UYYVYY411:
00942             bits = 12;
00943             break;
00944         default:
00945             bits = pf->depth * pf->nb_channels;
00946             break;
00947         }
00948         return (width * bits + 7) >> 3;
00949         break;
00950     case FF_PIXEL_PLANAR:
00951             if (plane == 1 || plane == 2)
00952                 width= -((-width)>>desc->log2_chroma_w);
00953 
00954             return (width * pf->depth + 7) >> 3;
00955         break;
00956     case FF_PIXEL_PALETTE:
00957         if (plane == 0)
00958             return width;
00959         break;
00960     }
00961 
00962     return -1;
00963 }
00964 
00965 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00966                      enum PixelFormat pix_fmt, int width, int height)
00967 {
00968     int i;
00969     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00970     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
00971 
00972     switch(pf->pixel_type) {
00973     case FF_PIXEL_PACKED:
00974     case FF_PIXEL_PLANAR:
00975         for(i = 0; i < pf->nb_channels; i++) {
00976             int h;
00977             int bwidth = ff_get_plane_bytewidth(pix_fmt, width, i);
00978             h = height;
00979             if (i == 1 || i == 2) {
00980                 h= -((-height)>>desc->log2_chroma_h);
00981             }
00982             ff_img_copy_plane(dst->data[i], dst->linesize[i],
00983                            src->data[i], src->linesize[i],
00984                            bwidth, h);
00985         }
00986         break;
00987     case FF_PIXEL_PALETTE:
00988         ff_img_copy_plane(dst->data[0], dst->linesize[0],
00989                        src->data[0], src->linesize[0],
00990                        width, height);
00991         /* copy the palette */
00992         memcpy(dst->data[1], src->data[1], 4*256);
00993         break;
00994     }
00995 }
00996 
00997 /* 2x2 -> 1x1 */
00998 void ff_shrink22(uint8_t *dst, int dst_wrap,
00999                      const uint8_t *src, int src_wrap,
01000                      int width, int height)
01001 {
01002     int w;
01003     const uint8_t *s1, *s2;
01004     uint8_t *d;
01005 
01006     for(;height > 0; height--) {
01007         s1 = src;
01008         s2 = s1 + src_wrap;
01009         d = dst;
01010         for(w = width;w >= 4; w-=4) {
01011             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
01012             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
01013             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
01014             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
01015             s1 += 8;
01016             s2 += 8;
01017             d += 4;
01018         }
01019         for(;w > 0; w--) {
01020             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
01021             s1 += 2;
01022             s2 += 2;
01023             d++;
01024         }
01025         src += 2 * src_wrap;
01026         dst += dst_wrap;
01027     }
01028 }
01029 
01030 /* 4x4 -> 1x1 */
01031 void ff_shrink44(uint8_t *dst, int dst_wrap,
01032                      const uint8_t *src, int src_wrap,
01033                      int width, int height)
01034 {
01035     int w;
01036     const uint8_t *s1, *s2, *s3, *s4;
01037     uint8_t *d;
01038 
01039     for(;height > 0; height--) {
01040         s1 = src;
01041         s2 = s1 + src_wrap;
01042         s3 = s2 + src_wrap;
01043         s4 = s3 + src_wrap;
01044         d = dst;
01045         for(w = width;w > 0; w--) {
01046             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
01047                     s2[0] + s2[1] + s2[2] + s2[3] +
01048                     s3[0] + s3[1] + s3[2] + s3[3] +
01049                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
01050             s1 += 4;
01051             s2 += 4;
01052             s3 += 4;
01053             s4 += 4;
01054             d++;
01055         }
01056         src += 4 * src_wrap;
01057         dst += dst_wrap;
01058     }
01059 }
01060 
01061 /* 8x8 -> 1x1 */
01062 void ff_shrink88(uint8_t *dst, int dst_wrap,
01063                      const uint8_t *src, int src_wrap,
01064                      int width, int height)
01065 {
01066     int w, i;
01067 
01068     for(;height > 0; height--) {
01069         for(w = width;w > 0; w--) {
01070             int tmp=0;
01071             for(i=0; i<8; i++){
01072                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
01073                 src += src_wrap;
01074             }
01075             *(dst++) = (tmp + 32)>>6;
01076             src += 8 - 8*src_wrap;
01077         }
01078         src += 8*src_wrap - 8*width;
01079         dst += dst_wrap - width;
01080     }
01081 }
01082 
01083 
01084 int avpicture_alloc(AVPicture *picture,
01085                     enum PixelFormat pix_fmt, int width, int height)
01086 {
01087     int size;
01088     void *ptr;
01089 
01090     size = avpicture_fill(picture, NULL, pix_fmt, width, height);
01091     if(size<0)
01092         goto fail;
01093     ptr = av_malloc(size);
01094     if (!ptr)
01095         goto fail;
01096     avpicture_fill(picture, ptr, pix_fmt, width, height);
01097     if(picture->data[1] && !picture->data[2])
01098         ff_set_systematic_pal((uint32_t*)picture->data[1], pix_fmt);
01099 
01100     return 0;
01101  fail:
01102     memset(picture, 0, sizeof(AVPicture));
01103     return -1;
01104 }
01105 
01106 void avpicture_free(AVPicture *picture)
01107 {
01108     av_free(picture->data[0]);
01109 }
01110 
01111 /* return true if yuv planar */
01112 static inline int is_yuv_planar(const PixFmtInfo *ps)
01113 {
01114     return (ps->color_type == FF_COLOR_YUV ||
01115             ps->color_type == FF_COLOR_YUV_JPEG) &&
01116         ps->pixel_type == FF_PIXEL_PLANAR;
01117 }
01118 
01119 int av_picture_crop(AVPicture *dst, const AVPicture *src,
01120                     enum PixelFormat pix_fmt, int top_band, int left_band)
01121 {
01122     int y_shift;
01123     int x_shift;
01124 
01125     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
01126         return -1;
01127 
01128     y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
01129     x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
01130 
01131     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
01132     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
01133     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
01134 
01135     dst->linesize[0] = src->linesize[0];
01136     dst->linesize[1] = src->linesize[1];
01137     dst->linesize[2] = src->linesize[2];
01138     return 0;
01139 }
01140 
01141 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
01142                    enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
01143             int *color)
01144 {
01145     uint8_t *optr;
01146     int y_shift;
01147     int x_shift;
01148     int yheight;
01149     int i, y;
01150 
01151     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
01152         !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
01153 
01154     for (i = 0; i < 3; i++) {
01155         x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
01156         y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
01157 
01158         if (padtop || padleft) {
01159             memset(dst->data[i], color[i],
01160                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
01161         }
01162 
01163         if (padleft || padright) {
01164             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
01165                 (dst->linesize[i] - (padright >> x_shift));
01166             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
01167             for (y = 0; y < yheight; y++) {
01168                 memset(optr, color[i], (padleft + padright) >> x_shift);
01169                 optr += dst->linesize[i];
01170             }
01171         }
01172 
01173         if (src) { /* first line */
01174             uint8_t *iptr = src->data[i];
01175             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
01176                     (padleft >> x_shift);
01177             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
01178             iptr += src->linesize[i];
01179             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
01180                 (dst->linesize[i] - (padright >> x_shift));
01181             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
01182             for (y = 0; y < yheight; y++) {
01183                 memset(optr, color[i], (padleft + padright) >> x_shift);
01184                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
01185                        (width - padleft - padright) >> x_shift);
01186                 iptr += src->linesize[i];
01187                 optr += dst->linesize[i];
01188             }
01189         }
01190 
01191         if (padbottom || padright) {
01192             optr = dst->data[i] + dst->linesize[i] *
01193                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
01194             memset(optr, color[i],dst->linesize[i] *
01195                 (padbottom >> y_shift) + (padright >> x_shift));
01196         }
01197     }
01198     return 0;
01199 }
01200 
01201 /* NOTE: we scan all the pixels to have an exact information */
01202 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
01203 {
01204     const unsigned char *p;
01205     int src_wrap, ret, x, y;
01206     unsigned int a;
01207     uint32_t *palette = (uint32_t *)src->data[1];
01208 
01209     p = src->data[0];
01210     src_wrap = src->linesize[0] - width;
01211     ret = 0;
01212     for(y=0;y<height;y++) {
01213         for(x=0;x<width;x++) {
01214             a = palette[p[0]] >> 24;
01215             if (a == 0x00) {
01216                 ret |= FF_ALPHA_TRANSP;
01217             } else if (a != 0xff) {
01218                 ret |= FF_ALPHA_SEMI_TRANSP;
01219             }
01220             p++;
01221         }
01222         p += src_wrap;
01223     }
01224     return ret;
01225 }
01226 
01227 int img_get_alpha_info(const AVPicture *src,
01228                        enum PixelFormat pix_fmt, int width, int height)
01229 {
01230     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
01231     int ret;
01232 
01233     /* no alpha can be represented in format */
01234     if (!pf->is_alpha)
01235         return 0;
01236     switch(pix_fmt) {
01237     case PIX_FMT_PAL8:
01238         ret = get_alpha_info_pal8(src, width, height);
01239         break;
01240     default:
01241         /* we do not know, so everything is indicated */
01242         ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
01243         break;
01244     }
01245     return ret;
01246 }
01247 
01248 #if HAVE_MMX
01249 #define DEINT_INPLACE_LINE_LUM \
01250                     movd_m2r(lum_m4[0],mm0);\
01251                     movd_m2r(lum_m3[0],mm1);\
01252                     movd_m2r(lum_m2[0],mm2);\
01253                     movd_m2r(lum_m1[0],mm3);\
01254                     movd_m2r(lum[0],mm4);\
01255                     punpcklbw_r2r(mm7,mm0);\
01256                     movd_r2m(mm2,lum_m4[0]);\
01257                     punpcklbw_r2r(mm7,mm1);\
01258                     punpcklbw_r2r(mm7,mm2);\
01259                     punpcklbw_r2r(mm7,mm3);\
01260                     punpcklbw_r2r(mm7,mm4);\
01261                     paddw_r2r(mm3,mm1);\
01262                     psllw_i2r(1,mm2);\
01263                     paddw_r2r(mm4,mm0);\
01264                     psllw_i2r(2,mm1);\
01265                     paddw_r2r(mm6,mm2);\
01266                     paddw_r2r(mm2,mm1);\
01267                     psubusw_r2r(mm0,mm1);\
01268                     psrlw_i2r(3,mm1);\
01269                     packuswb_r2r(mm7,mm1);\
01270                     movd_r2m(mm1,lum_m2[0]);
01271 
01272 #define DEINT_LINE_LUM \
01273                     movd_m2r(lum_m4[0],mm0);\
01274                     movd_m2r(lum_m3[0],mm1);\
01275                     movd_m2r(lum_m2[0],mm2);\
01276                     movd_m2r(lum_m1[0],mm3);\
01277                     movd_m2r(lum[0],mm4);\
01278                     punpcklbw_r2r(mm7,mm0);\
01279                     punpcklbw_r2r(mm7,mm1);\
01280                     punpcklbw_r2r(mm7,mm2);\
01281                     punpcklbw_r2r(mm7,mm3);\
01282                     punpcklbw_r2r(mm7,mm4);\
01283                     paddw_r2r(mm3,mm1);\
01284                     psllw_i2r(1,mm2);\
01285                     paddw_r2r(mm4,mm0);\
01286                     psllw_i2r(2,mm1);\
01287                     paddw_r2r(mm6,mm2);\
01288                     paddw_r2r(mm2,mm1);\
01289                     psubusw_r2r(mm0,mm1);\
01290                     psrlw_i2r(3,mm1);\
01291                     packuswb_r2r(mm7,mm1);\
01292                     movd_r2m(mm1,dst[0]);
01293 #endif
01294 
01295 /* filter parameters: [-1 4 2 4 -1] // 8 */
01296 static void deinterlace_line(uint8_t *dst,
01297                              const uint8_t *lum_m4, const uint8_t *lum_m3,
01298                              const uint8_t *lum_m2, const uint8_t *lum_m1,
01299                              const uint8_t *lum,
01300                              int size)
01301 {
01302 #if !HAVE_MMX
01303     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
01304     int sum;
01305 
01306     for(;size > 0;size--) {
01307         sum = -lum_m4[0];
01308         sum += lum_m3[0] << 2;
01309         sum += lum_m2[0] << 1;
01310         sum += lum_m1[0] << 2;
01311         sum += -lum[0];
01312         dst[0] = cm[(sum + 4) >> 3];
01313         lum_m4++;
01314         lum_m3++;
01315         lum_m2++;
01316         lum_m1++;
01317         lum++;
01318         dst++;
01319     }
01320 #else
01321 
01322     {
01323         pxor_r2r(mm7,mm7);
01324         movq_m2r(ff_pw_4,mm6);
01325     }
01326     for (;size > 3; size-=4) {
01327         DEINT_LINE_LUM
01328         lum_m4+=4;
01329         lum_m3+=4;
01330         lum_m2+=4;
01331         lum_m1+=4;
01332         lum+=4;
01333         dst+=4;
01334     }
01335 #endif
01336 }
01337 static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
01338                              int size)
01339 {
01340 #if !HAVE_MMX
01341     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
01342     int sum;
01343 
01344     for(;size > 0;size--) {
01345         sum = -lum_m4[0];
01346         sum += lum_m3[0] << 2;
01347         sum += lum_m2[0] << 1;
01348         lum_m4[0]=lum_m2[0];
01349         sum += lum_m1[0] << 2;
01350         sum += -lum[0];
01351         lum_m2[0] = cm[(sum + 4) >> 3];
01352         lum_m4++;
01353         lum_m3++;
01354         lum_m2++;
01355         lum_m1++;
01356         lum++;
01357     }
01358 #else
01359 
01360     {
01361         pxor_r2r(mm7,mm7);
01362         movq_m2r(ff_pw_4,mm6);
01363     }
01364     for (;size > 3; size-=4) {
01365         DEINT_INPLACE_LINE_LUM
01366         lum_m4+=4;
01367         lum_m3+=4;
01368         lum_m2+=4;
01369         lum_m1+=4;
01370         lum+=4;
01371     }
01372 #endif
01373 }
01374 
01375 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
01376    top field is copied as is, but the bottom field is deinterlaced
01377    against the top field. */
01378 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
01379                                     const uint8_t *src1, int src_wrap,
01380                                     int width, int height)
01381 {
01382     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
01383     int y;
01384 
01385     src_m2 = src1;
01386     src_m1 = src1;
01387     src_0=&src_m1[src_wrap];
01388     src_p1=&src_0[src_wrap];
01389     src_p2=&src_p1[src_wrap];
01390     for(y=0;y<(height-2);y+=2) {
01391         memcpy(dst,src_m1,width);
01392         dst += dst_wrap;
01393         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
01394         src_m2 = src_0;
01395         src_m1 = src_p1;
01396         src_0 = src_p2;
01397         src_p1 += 2*src_wrap;
01398         src_p2 += 2*src_wrap;
01399         dst += dst_wrap;
01400     }
01401     memcpy(dst,src_m1,width);
01402     dst += dst_wrap;
01403     /* do last line */
01404     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
01405 }
01406 
01407 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
01408                                              int width, int height)
01409 {
01410     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
01411     int y;
01412     uint8_t *buf;
01413     buf = (uint8_t*)av_malloc(width);
01414 
01415     src_m1 = src1;
01416     memcpy(buf,src_m1,width);
01417     src_0=&src_m1[src_wrap];
01418     src_p1=&src_0[src_wrap];
01419     src_p2=&src_p1[src_wrap];
01420     for(y=0;y<(height-2);y+=2) {
01421         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
01422         src_m1 = src_p1;
01423         src_0 = src_p2;
01424         src_p1 += 2*src_wrap;
01425         src_p2 += 2*src_wrap;
01426     }
01427     /* do last line */
01428     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
01429     av_free(buf);
01430 }
01431 
01432 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
01433                           enum PixelFormat pix_fmt, int width, int height)
01434 {
01435     int i;
01436 
01437     if (pix_fmt != PIX_FMT_YUV420P &&
01438         pix_fmt != PIX_FMT_YUV422P &&
01439         pix_fmt != PIX_FMT_YUV444P &&
01440         pix_fmt != PIX_FMT_YUV411P &&
01441         pix_fmt != PIX_FMT_GRAY8)
01442         return -1;
01443     if ((width & 3) != 0 || (height & 3) != 0)
01444         return -1;
01445 
01446     for(i=0;i<3;i++) {
01447         if (i == 1) {
01448             switch(pix_fmt) {
01449             case PIX_FMT_YUV420P:
01450                 width >>= 1;
01451                 height >>= 1;
01452                 break;
01453             case PIX_FMT_YUV422P:
01454                 width >>= 1;
01455                 break;
01456             case PIX_FMT_YUV411P:
01457                 width >>= 2;
01458                 break;
01459             default:
01460                 break;
01461             }
01462             if (pix_fmt == PIX_FMT_GRAY8) {
01463                 break;
01464             }
01465         }
01466         if (src == dst) {
01467             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
01468                                  width, height);
01469         } else {
01470             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
01471                                         src->data[i], src->linesize[i],
01472                                         width, height);
01473         }
01474     }
01475     emms_c();
01476     return 0;
01477 }
01478 

Generated on Fri Sep 16 2011 17:17:38 for FFmpeg by  doxygen 1.7.1