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 
00022 /**
00023  * @file imgconvert.c
00024  * misc image conversion routines
00025  */
00026 
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 #ifdef HAVE_MMX
00038 #include "i386/mmx.h"
00039 #endif
00040 
00041 #define xglue(x, y) x ## y
00042 #define glue(x, y) xglue(x, y)
00043 
00044 #define FF_COLOR_RGB      0 /**< RGB color space */
00045 #define FF_COLOR_GRAY     1 /**< gray color space */
00046 #define FF_COLOR_YUV      2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
00047 #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
00048 
00049 #define FF_PIXEL_PLANAR   0 /**< each channel has one component in AVPicture */
00050 #define FF_PIXEL_PACKED   1 /**< only one components containing all the channels */
00051 #define FF_PIXEL_PALETTE  2  /**< one components containing indexes for a palette */
00052 
00053 typedef struct PixFmtInfo {
00054     const char *name;
00055     uint8_t nb_channels;     /**< number of channels (including alpha) */
00056     uint8_t color_type;      /**< color type (see FF_COLOR_xxx constants) */
00057     uint8_t pixel_type;      /**< pixel storage type (see FF_PIXEL_xxx constants) */
00058     uint8_t is_alpha : 1;    /**< true if alpha can be specified */
00059     uint8_t x_chroma_shift;  /**< X chroma subsampling factor is 2 ^ shift */
00060     uint8_t y_chroma_shift;  /**< Y chroma subsampling factor is 2 ^ shift */
00061     uint8_t depth;           /**< bit depth of the color components */
00062 } PixFmtInfo;
00063 
00064 /* this table gives more information about formats */
00065 static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
00066     /* YUV formats */
00067     [PIX_FMT_YUV420P] = {
00068         .name = "yuv420p",
00069         .nb_channels = 3,
00070         .color_type = FF_COLOR_YUV,
00071         .pixel_type = FF_PIXEL_PLANAR,
00072         .depth = 8,
00073         .x_chroma_shift = 1, .y_chroma_shift = 1,
00074     },
00075     [PIX_FMT_YUV422P] = {
00076         .name = "yuv422p",
00077         .nb_channels = 3,
00078         .color_type = FF_COLOR_YUV,
00079         .pixel_type = FF_PIXEL_PLANAR,
00080         .depth = 8,
00081         .x_chroma_shift = 1, .y_chroma_shift = 0,
00082     },
00083     [PIX_FMT_YUV444P] = {
00084         .name = "yuv444p",
00085         .nb_channels = 3,
00086         .color_type = FF_COLOR_YUV,
00087         .pixel_type = FF_PIXEL_PLANAR,
00088         .depth = 8,
00089         .x_chroma_shift = 0, .y_chroma_shift = 0,
00090     },
00091     [PIX_FMT_YUYV422] = {
00092         .name = "yuyv422",
00093         .nb_channels = 1,
00094         .color_type = FF_COLOR_YUV,
00095         .pixel_type = FF_PIXEL_PACKED,
00096         .depth = 8,
00097         .x_chroma_shift = 1, .y_chroma_shift = 0,
00098     },
00099     [PIX_FMT_UYVY422] = {
00100         .name = "uyvy422",
00101         .nb_channels = 1,
00102         .color_type = FF_COLOR_YUV,
00103         .pixel_type = FF_PIXEL_PACKED,
00104         .depth = 8,
00105         .x_chroma_shift = 1, .y_chroma_shift = 0,
00106     },
00107     [PIX_FMT_YUV410P] = {
00108         .name = "yuv410p",
00109         .nb_channels = 3,
00110         .color_type = FF_COLOR_YUV,
00111         .pixel_type = FF_PIXEL_PLANAR,
00112         .depth = 8,
00113         .x_chroma_shift = 2, .y_chroma_shift = 2,
00114     },
00115     [PIX_FMT_YUV411P] = {
00116         .name = "yuv411p",
00117         .nb_channels = 3,
00118         .color_type = FF_COLOR_YUV,
00119         .pixel_type = FF_PIXEL_PLANAR,
00120         .depth = 8,
00121         .x_chroma_shift = 2, .y_chroma_shift = 0,
00122     },
00123     [PIX_FMT_YUV440P] = {
00124         .name = "yuv440p",
00125         .nb_channels = 3,
00126         .color_type = FF_COLOR_YUV,
00127         .pixel_type = FF_PIXEL_PLANAR,
00128         .depth = 8,
00129         .x_chroma_shift = 0, .y_chroma_shift = 1,
00130     },
00131 
00132     /* YUV formats with alpha plane */
00133     [PIX_FMT_YUVA420P] = {
00134         .name = "yuva420p",
00135         .nb_channels = 4,
00136         .color_type = FF_COLOR_YUV,
00137         .pixel_type = FF_PIXEL_PLANAR,
00138         .depth = 8,
00139         .x_chroma_shift = 1, .y_chroma_shift = 1,
00140     },
00141 
00142     /* JPEG YUV */
00143     [PIX_FMT_YUVJ420P] = {
00144         .name = "yuvj420p",
00145         .nb_channels = 3,
00146         .color_type = FF_COLOR_YUV_JPEG,
00147         .pixel_type = FF_PIXEL_PLANAR,
00148         .depth = 8,
00149         .x_chroma_shift = 1, .y_chroma_shift = 1,
00150     },
00151     [PIX_FMT_YUVJ422P] = {
00152         .name = "yuvj422p",
00153         .nb_channels = 3,
00154         .color_type = FF_COLOR_YUV_JPEG,
00155         .pixel_type = FF_PIXEL_PLANAR,
00156         .depth = 8,
00157         .x_chroma_shift = 1, .y_chroma_shift = 0,
00158     },
00159     [PIX_FMT_YUVJ444P] = {
00160         .name = "yuvj444p",
00161         .nb_channels = 3,
00162         .color_type = FF_COLOR_YUV_JPEG,
00163         .pixel_type = FF_PIXEL_PLANAR,
00164         .depth = 8,
00165         .x_chroma_shift = 0, .y_chroma_shift = 0,
00166     },
00167     [PIX_FMT_YUVJ440P] = {
00168         .name = "yuvj440p",
00169         .nb_channels = 3,
00170         .color_type = FF_COLOR_YUV_JPEG,
00171         .pixel_type = FF_PIXEL_PLANAR,
00172         .depth = 8,
00173         .x_chroma_shift = 0, .y_chroma_shift = 1,
00174     },
00175 
00176     /* RGB formats */
00177     [PIX_FMT_RGB24] = {
00178         .name = "rgb24",
00179         .nb_channels = 3,
00180         .color_type = FF_COLOR_RGB,
00181         .pixel_type = FF_PIXEL_PACKED,
00182         .depth = 8,
00183         .x_chroma_shift = 0, .y_chroma_shift = 0,
00184     },
00185     [PIX_FMT_BGR24] = {
00186         .name = "bgr24",
00187         .nb_channels = 3,
00188         .color_type = FF_COLOR_RGB,
00189         .pixel_type = FF_PIXEL_PACKED,
00190         .depth = 8,
00191         .x_chroma_shift = 0, .y_chroma_shift = 0,
00192     },
00193     [PIX_FMT_RGB32] = {
00194         .name = "rgb32",
00195         .nb_channels = 4, .is_alpha = 1,
00196         .color_type = FF_COLOR_RGB,
00197         .pixel_type = FF_PIXEL_PACKED,
00198         .depth = 8,
00199         .x_chroma_shift = 0, .y_chroma_shift = 0,
00200     },
00201     [PIX_FMT_RGB565] = {
00202         .name = "rgb565",
00203         .nb_channels = 3,
00204         .color_type = FF_COLOR_RGB,
00205         .pixel_type = FF_PIXEL_PACKED,
00206         .depth = 5,
00207         .x_chroma_shift = 0, .y_chroma_shift = 0,
00208     },
00209     [PIX_FMT_RGB555] = {
00210         .name = "rgb555",
00211         .nb_channels = 3,
00212         .color_type = FF_COLOR_RGB,
00213         .pixel_type = FF_PIXEL_PACKED,
00214         .depth = 5,
00215         .x_chroma_shift = 0, .y_chroma_shift = 0,
00216     },
00217 
00218     /* gray / mono formats */
00219     [PIX_FMT_GRAY16BE] = {
00220         .name = "gray16be",
00221         .nb_channels = 1,
00222         .color_type = FF_COLOR_GRAY,
00223         .pixel_type = FF_PIXEL_PLANAR,
00224         .depth = 16,
00225     },
00226     [PIX_FMT_GRAY16LE] = {
00227         .name = "gray16le",
00228         .nb_channels = 1,
00229         .color_type = FF_COLOR_GRAY,
00230         .pixel_type = FF_PIXEL_PLANAR,
00231         .depth = 16,
00232     },
00233     [PIX_FMT_GRAY8] = {
00234         .name = "gray",
00235         .nb_channels = 1,
00236         .color_type = FF_COLOR_GRAY,
00237         .pixel_type = FF_PIXEL_PLANAR,
00238         .depth = 8,
00239     },
00240     [PIX_FMT_MONOWHITE] = {
00241         .name = "monow",
00242         .nb_channels = 1,
00243         .color_type = FF_COLOR_GRAY,
00244         .pixel_type = FF_PIXEL_PLANAR,
00245         .depth = 1,
00246     },
00247     [PIX_FMT_MONOBLACK] = {
00248         .name = "monob",
00249         .nb_channels = 1,
00250         .color_type = FF_COLOR_GRAY,
00251         .pixel_type = FF_PIXEL_PLANAR,
00252         .depth = 1,
00253     },
00254 
00255     /* paletted formats */
00256     [PIX_FMT_PAL8] = {
00257         .name = "pal8",
00258         .nb_channels = 4, .is_alpha = 1,
00259         .color_type = FF_COLOR_RGB,
00260         .pixel_type = FF_PIXEL_PALETTE,
00261         .depth = 8,
00262     },
00263     [PIX_FMT_XVMC_MPEG2_MC] = {
00264         .name = "xvmcmc",
00265     },
00266     [PIX_FMT_XVMC_MPEG2_IDCT] = {
00267         .name = "xvmcidct",
00268     },
00269     [PIX_FMT_UYYVYY411] = {
00270         .name = "uyyvyy411",
00271         .nb_channels = 1,
00272         .color_type = FF_COLOR_YUV,
00273         .pixel_type = FF_PIXEL_PACKED,
00274         .depth = 8,
00275         .x_chroma_shift = 2, .y_chroma_shift = 0,
00276     },
00277     [PIX_FMT_BGR32] = {
00278         .name = "bgr32",
00279         .nb_channels = 4, .is_alpha = 1,
00280         .color_type = FF_COLOR_RGB,
00281         .pixel_type = FF_PIXEL_PACKED,
00282         .depth = 8,
00283         .x_chroma_shift = 0, .y_chroma_shift = 0,
00284     },
00285     [PIX_FMT_BGR565] = {
00286         .name = "bgr565",
00287         .nb_channels = 3,
00288         .color_type = FF_COLOR_RGB,
00289         .pixel_type = FF_PIXEL_PACKED,
00290         .depth = 5,
00291         .x_chroma_shift = 0, .y_chroma_shift = 0,
00292     },
00293     [PIX_FMT_BGR555] = {
00294         .name = "bgr555",
00295         .nb_channels = 3,
00296         .color_type = FF_COLOR_RGB,
00297         .pixel_type = FF_PIXEL_PACKED,
00298         .depth = 5,
00299         .x_chroma_shift = 0, .y_chroma_shift = 0,
00300     },
00301     [PIX_FMT_RGB8] = {
00302         .name = "rgb8",
00303         .nb_channels = 1,
00304         .color_type = FF_COLOR_RGB,
00305         .pixel_type = FF_PIXEL_PACKED,
00306         .depth = 8,
00307         .x_chroma_shift = 0, .y_chroma_shift = 0,
00308     },
00309     [PIX_FMT_RGB4] = {
00310         .name = "rgb4",
00311         .nb_channels = 1,
00312         .color_type = FF_COLOR_RGB,
00313         .pixel_type = FF_PIXEL_PACKED,
00314         .depth = 4,
00315         .x_chroma_shift = 0, .y_chroma_shift = 0,
00316     },
00317     [PIX_FMT_RGB4_BYTE] = {
00318         .name = "rgb4_byte",
00319         .nb_channels = 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_BGR8] = {
00326         .name = "bgr8",
00327         .nb_channels = 1,
00328         .color_type = FF_COLOR_RGB,
00329         .pixel_type = FF_PIXEL_PACKED,
00330         .depth = 8,
00331         .x_chroma_shift = 0, .y_chroma_shift = 0,
00332     },
00333     [PIX_FMT_BGR4] = {
00334         .name = "bgr4",
00335         .nb_channels = 1,
00336         .color_type = FF_COLOR_RGB,
00337         .pixel_type = FF_PIXEL_PACKED,
00338         .depth = 4,
00339         .x_chroma_shift = 0, .y_chroma_shift = 0,
00340     },
00341     [PIX_FMT_BGR4_BYTE] = {
00342         .name = "bgr4_byte",
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_NV12] = {
00350         .name = "nv12",
00351         .nb_channels = 2,
00352         .color_type = FF_COLOR_YUV,
00353         .pixel_type = FF_PIXEL_PLANAR,
00354         .depth = 8,
00355         .x_chroma_shift = 1, .y_chroma_shift = 1,
00356     },
00357     [PIX_FMT_NV21] = {
00358         .name = "nv12",
00359         .nb_channels = 2,
00360         .color_type = FF_COLOR_YUV,
00361         .pixel_type = FF_PIXEL_PLANAR,
00362         .depth = 8,
00363         .x_chroma_shift = 1, .y_chroma_shift = 1,
00364     },
00365 
00366     [PIX_FMT_BGR32_1] = {
00367         .name = "bgr32_1",
00368         .nb_channels = 4, .is_alpha = 1,
00369         .color_type = FF_COLOR_RGB,
00370         .pixel_type = FF_PIXEL_PACKED,
00371         .depth = 8,
00372         .x_chroma_shift = 0, .y_chroma_shift = 0,
00373     },
00374     [PIX_FMT_RGB32_1] = {
00375         .name = "rgb32_1",
00376         .nb_channels = 4, .is_alpha = 1,
00377         .color_type = FF_COLOR_RGB,
00378         .pixel_type = FF_PIXEL_PACKED,
00379         .depth = 8,
00380         .x_chroma_shift = 0, .y_chroma_shift = 0,
00381     },
00382 };
00383 
00384 void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
00385 {
00386     *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
00387     *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
00388 }
00389 
00390 const char *avcodec_get_pix_fmt_name(int pix_fmt)
00391 {
00392     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
00393         return "???";
00394     else
00395         return pix_fmt_info[pix_fmt].name;
00396 }
00397 
00398 enum PixelFormat avcodec_get_pix_fmt(const char* name)
00399 {
00400     int i;
00401 
00402     for (i=0; i < PIX_FMT_NB; i++)
00403          if (!strcmp(pix_fmt_info[i].name, name))
00404              break;
00405     return i;
00406 }
00407 
00408 void avcodec_pix_fmt_string (char *buf, int buf_size, int pix_fmt)
00409 {
00410     /* print header */
00411     if (pix_fmt < 0)
00412         snprintf (buf, buf_size,
00413                   "name      " " nb_channels" " depth" " is_alpha"
00414             );
00415     else{
00416         PixFmtInfo info= pix_fmt_info[pix_fmt];
00417 
00418         char is_alpha_char= info.is_alpha ? 'y' : 'n';
00419 
00420         snprintf (buf, buf_size,
00421                   "%-10s" "      %1d     " "   %2d " "     %c   ",
00422                   info.name,
00423                   info.nb_channels,
00424                   info.depth,
00425                   is_alpha_char
00426             );
00427     }
00428 }
00429 
00430 int ff_fill_linesize(AVPicture *picture, int pix_fmt, int width)
00431 {
00432     int w2;
00433     const PixFmtInfo *pinfo;
00434 
00435     memset(picture->linesize, 0, sizeof(picture->linesize));
00436 
00437     pinfo = &pix_fmt_info[pix_fmt];
00438     switch(pix_fmt) {
00439     case PIX_FMT_YUV420P:
00440     case PIX_FMT_YUV422P:
00441     case PIX_FMT_YUV444P:
00442     case PIX_FMT_YUV410P:
00443     case PIX_FMT_YUV411P:
00444     case PIX_FMT_YUV440P:
00445     case PIX_FMT_YUVJ420P:
00446     case PIX_FMT_YUVJ422P:
00447     case PIX_FMT_YUVJ444P:
00448     case PIX_FMT_YUVJ440P:
00449         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
00450         picture->linesize[0] = width;
00451         picture->linesize[1] = w2;
00452         picture->linesize[2] = w2;
00453         break;
00454     case PIX_FMT_YUVA420P:
00455         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
00456         picture->linesize[0] = width;
00457         picture->linesize[1] = w2;
00458         picture->linesize[2] = w2;
00459         picture->linesize[3] = width;
00460         break;
00461     case PIX_FMT_NV12:
00462     case PIX_FMT_NV21:
00463         w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
00464         picture->linesize[0] = width;
00465         picture->linesize[1] = w2;
00466         break;
00467     case PIX_FMT_RGB24:
00468     case PIX_FMT_BGR24:
00469         picture->linesize[0] = width * 3;
00470         break;
00471     case PIX_FMT_RGB32:
00472     case PIX_FMT_BGR32:
00473     case PIX_FMT_RGB32_1:
00474     case PIX_FMT_BGR32_1:
00475         picture->linesize[0] = width * 4;
00476         break;
00477     case PIX_FMT_GRAY16BE:
00478     case PIX_FMT_GRAY16LE:
00479     case PIX_FMT_BGR555:
00480     case PIX_FMT_BGR565:
00481     case PIX_FMT_RGB555:
00482     case PIX_FMT_RGB565:
00483     case PIX_FMT_YUYV422:
00484         picture->linesize[0] = width * 2;
00485         break;
00486     case PIX_FMT_UYVY422:
00487         picture->linesize[0] = width * 2;
00488         break;
00489     case PIX_FMT_UYYVYY411:
00490         picture->linesize[0] = width + width/2;
00491         break;
00492     case PIX_FMT_RGB8:
00493     case PIX_FMT_BGR8:
00494     case PIX_FMT_RGB4_BYTE:
00495     case PIX_FMT_BGR4_BYTE:
00496     case PIX_FMT_GRAY8:
00497         picture->linesize[0] = width;
00498         break;
00499     case PIX_FMT_RGB4:
00500     case PIX_FMT_BGR4:
00501         picture->linesize[0] = width / 2;
00502         break;
00503     case PIX_FMT_MONOWHITE:
00504     case PIX_FMT_MONOBLACK:
00505         picture->linesize[0] = (width + 7) >> 3;
00506         break;
00507     case PIX_FMT_PAL8:
00508         picture->linesize[0] = width;
00509         picture->linesize[1] = 4;
00510         break;
00511     default:
00512         return -1;
00513     }
00514     return 0;
00515 }
00516 
00517 int ff_fill_pointer(AVPicture *picture, uint8_t *ptr, int pix_fmt,
00518                     int height)
00519 {
00520     int size, h2, size2;
00521     const PixFmtInfo *pinfo;
00522 
00523     pinfo = &pix_fmt_info[pix_fmt];
00524     size = picture->linesize[0] * height;
00525     switch(pix_fmt) {
00526     case PIX_FMT_YUV420P:
00527     case PIX_FMT_YUV422P:
00528     case PIX_FMT_YUV444P:
00529     case PIX_FMT_YUV410P:
00530     case PIX_FMT_YUV411P:
00531     case PIX_FMT_YUV440P:
00532     case PIX_FMT_YUVJ420P:
00533     case PIX_FMT_YUVJ422P:
00534     case PIX_FMT_YUVJ444P:
00535     case PIX_FMT_YUVJ440P:
00536         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
00537         size2 = picture->linesize[1] * h2;
00538         picture->data[0] = ptr;
00539         picture->data[1] = picture->data[0] + size;
00540         picture->data[2] = picture->data[1] + size2;
00541         picture->data[3] = NULL;
00542         return size + 2 * size2;
00543     case PIX_FMT_YUVA420P:
00544         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
00545         size2 = picture->linesize[1] * h2;
00546         picture->data[0] = ptr;
00547         picture->data[1] = picture->data[0] + size;
00548         picture->data[2] = picture->data[1] + size2;
00549         picture->data[3] = picture->data[1] + size2 + size2;
00550         return 2 * size + 2 * size2;
00551     case PIX_FMT_NV12:
00552     case PIX_FMT_NV21:
00553         h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
00554         size2 = picture->linesize[1] * h2 * 2;
00555         picture->data[0] = ptr;
00556         picture->data[1] = picture->data[0] + size;
00557         picture->data[2] = NULL;
00558         picture->data[3] = NULL;
00559         return size + 2 * size2;
00560     case PIX_FMT_RGB24:
00561     case PIX_FMT_BGR24:
00562     case PIX_FMT_RGB32:
00563     case PIX_FMT_BGR32:
00564     case PIX_FMT_RGB32_1:
00565     case PIX_FMT_BGR32_1:
00566     case PIX_FMT_GRAY16BE:
00567     case PIX_FMT_GRAY16LE:
00568     case PIX_FMT_BGR555:
00569     case PIX_FMT_BGR565:
00570     case PIX_FMT_RGB555:
00571     case PIX_FMT_RGB565:
00572     case PIX_FMT_YUYV422:
00573     case PIX_FMT_UYVY422:
00574     case PIX_FMT_UYYVYY411:
00575     case PIX_FMT_RGB8:
00576     case PIX_FMT_BGR8:
00577     case PIX_FMT_RGB4_BYTE:
00578     case PIX_FMT_BGR4_BYTE:
00579     case PIX_FMT_GRAY8:
00580     case PIX_FMT_RGB4:
00581     case PIX_FMT_BGR4:
00582     case PIX_FMT_MONOWHITE:
00583     case PIX_FMT_MONOBLACK:
00584         picture->data[0] = ptr;
00585         picture->data[1] = NULL;
00586         picture->data[2] = NULL;
00587         picture->data[3] = NULL;
00588         return size;
00589     case PIX_FMT_PAL8:
00590         size2 = (size + 3) & ~3;
00591         picture->data[0] = ptr;
00592         picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
00593         picture->data[2] = NULL;
00594         picture->data[3] = NULL;
00595         return size2 + 256 * 4;
00596     default:
00597         picture->data[0] = NULL;
00598         picture->data[1] = NULL;
00599         picture->data[2] = NULL;
00600         picture->data[3] = NULL;
00601         return -1;
00602     }
00603 }
00604 
00605 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
00606                    int pix_fmt, int width, int height)
00607 {
00608 
00609     if(avcodec_check_dimensions(NULL, width, height))
00610         return -1;
00611 
00612     if (ff_fill_linesize(picture, pix_fmt, width))
00613         return -1;
00614 
00615     return ff_fill_pointer(picture, ptr, pix_fmt, height);
00616 }
00617 
00618 int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
00619                      unsigned char *dest, int dest_size)
00620 {
00621     const PixFmtInfo* pf = &pix_fmt_info[pix_fmt];
00622     int i, j, w, h, data_planes;
00623     const unsigned char* s;
00624     int size = avpicture_get_size(pix_fmt, width, height);
00625 
00626     if (size > dest_size || size < 0)
00627         return -1;
00628 
00629     if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
00630         if (pix_fmt == PIX_FMT_YUYV422 ||
00631             pix_fmt == PIX_FMT_UYVY422 ||
00632             pix_fmt == PIX_FMT_BGR565 ||
00633             pix_fmt == PIX_FMT_BGR555 ||
00634             pix_fmt == PIX_FMT_RGB565 ||
00635             pix_fmt == PIX_FMT_RGB555)
00636             w = width * 2;
00637         else if (pix_fmt == PIX_FMT_UYYVYY411)
00638           w = width + width/2;
00639         else if (pix_fmt == PIX_FMT_PAL8)
00640           w = width;
00641         else
00642           w = width * (pf->depth * pf->nb_channels / 8);
00643 
00644         data_planes = 1;
00645         h = height;
00646     } else {
00647         data_planes = pf->nb_channels;
00648         w = (width*pf->depth + 7)/8;
00649         h = height;
00650     }
00651 
00652     for (i=0; i<data_planes; i++) {
00653          if (i == 1) {
00654              w = width >> pf->x_chroma_shift;
00655              h = height >> pf->y_chroma_shift;
00656          }
00657          s = src->data[i];
00658          for(j=0; j<h; j++) {
00659              memcpy(dest, s, w);
00660              dest += w;
00661              s += src->linesize[i];
00662          }
00663     }
00664 
00665     if (pf->pixel_type == FF_PIXEL_PALETTE)
00666         memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
00667 
00668     return size;
00669 }
00670 
00671 int avpicture_get_size(int pix_fmt, int width, int height)
00672 {
00673     AVPicture dummy_pict;
00674     return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
00675 }
00676 
00677 int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
00678                              int has_alpha)
00679 {
00680     const PixFmtInfo *pf, *ps;
00681     int loss;
00682 
00683     ps = &pix_fmt_info[src_pix_fmt];
00684     pf = &pix_fmt_info[dst_pix_fmt];
00685 
00686     /* compute loss */
00687     loss = 0;
00688     pf = &pix_fmt_info[dst_pix_fmt];
00689     if (pf->depth < ps->depth ||
00690         (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
00691         loss |= FF_LOSS_DEPTH;
00692     if (pf->x_chroma_shift > ps->x_chroma_shift ||
00693         pf->y_chroma_shift > ps->y_chroma_shift)
00694         loss |= FF_LOSS_RESOLUTION;
00695     switch(pf->color_type) {
00696     case FF_COLOR_RGB:
00697         if (ps->color_type != FF_COLOR_RGB &&
00698             ps->color_type != FF_COLOR_GRAY)
00699             loss |= FF_LOSS_COLORSPACE;
00700         break;
00701     case FF_COLOR_GRAY:
00702         if (ps->color_type != FF_COLOR_GRAY)
00703             loss |= FF_LOSS_COLORSPACE;
00704         break;
00705     case FF_COLOR_YUV:
00706         if (ps->color_type != FF_COLOR_YUV)
00707             loss |= FF_LOSS_COLORSPACE;
00708         break;
00709     case FF_COLOR_YUV_JPEG:
00710         if (ps->color_type != FF_COLOR_YUV_JPEG &&
00711             ps->color_type != FF_COLOR_YUV &&
00712             ps->color_type != FF_COLOR_GRAY)
00713             loss |= FF_LOSS_COLORSPACE;
00714         break;
00715     default:
00716         /* fail safe test */
00717         if (ps->color_type != pf->color_type)
00718             loss |= FF_LOSS_COLORSPACE;
00719         break;
00720     }
00721     if (pf->color_type == FF_COLOR_GRAY &&
00722         ps->color_type != FF_COLOR_GRAY)
00723         loss |= FF_LOSS_CHROMA;
00724     if (!pf->is_alpha && (ps->is_alpha && has_alpha))
00725         loss |= FF_LOSS_ALPHA;
00726     if (pf->pixel_type == FF_PIXEL_PALETTE &&
00727         (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
00728         loss |= FF_LOSS_COLORQUANT;
00729     return loss;
00730 }
00731 
00732 static int avg_bits_per_pixel(int pix_fmt)
00733 {
00734     int bits;
00735     const PixFmtInfo *pf;
00736 
00737     pf = &pix_fmt_info[pix_fmt];
00738     switch(pf->pixel_type) {
00739     case FF_PIXEL_PACKED:
00740         switch(pix_fmt) {
00741         case PIX_FMT_YUYV422:
00742         case PIX_FMT_UYVY422:
00743         case PIX_FMT_RGB565:
00744         case PIX_FMT_RGB555:
00745         case PIX_FMT_BGR565:
00746         case PIX_FMT_BGR555:
00747             bits = 16;
00748             break;
00749         case PIX_FMT_UYYVYY411:
00750             bits = 12;
00751             break;
00752         default:
00753             bits = pf->depth * pf->nb_channels;
00754             break;
00755         }
00756         break;
00757     case FF_PIXEL_PLANAR:
00758         if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
00759             bits = pf->depth * pf->nb_channels;
00760         } else {
00761             bits = pf->depth + ((2 * pf->depth) >>
00762                                 (pf->x_chroma_shift + pf->y_chroma_shift));
00763         }
00764         break;
00765     case FF_PIXEL_PALETTE:
00766         bits = 8;
00767         break;
00768     default:
00769         bits = -1;
00770         break;
00771     }
00772     return bits;
00773 }
00774 
00775 static int avcodec_find_best_pix_fmt1(int pix_fmt_mask,
00776                                       int src_pix_fmt,
00777                                       int has_alpha,
00778                                       int loss_mask)
00779 {
00780     int dist, i, loss, min_dist, dst_pix_fmt;
00781 
00782     /* find exact color match with smallest size */
00783     dst_pix_fmt = -1;
00784     min_dist = 0x7fffffff;
00785     for(i = 0;i < PIX_FMT_NB; i++) {
00786         if (pix_fmt_mask & (1 << i)) {
00787             loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
00788             if (loss == 0) {
00789                 dist = avg_bits_per_pixel(i);
00790                 if (dist < min_dist) {
00791                     min_dist = dist;
00792                     dst_pix_fmt = i;
00793                 }
00794             }
00795         }
00796     }
00797     return dst_pix_fmt;
00798 }
00799 
00800 int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
00801                               int has_alpha, int *loss_ptr)
00802 {
00803     int dst_pix_fmt, loss_mask, i;
00804     static const int loss_mask_order[] = {
00805         ~0, /* no loss first */
00806         ~FF_LOSS_ALPHA,
00807         ~FF_LOSS_RESOLUTION,
00808         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
00809         ~FF_LOSS_COLORQUANT,
00810         ~FF_LOSS_DEPTH,
00811         0,
00812     };
00813 
00814     /* try with successive loss */
00815     i = 0;
00816     for(;;) {
00817         loss_mask = loss_mask_order[i++];
00818         dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
00819                                                  has_alpha, loss_mask);
00820         if (dst_pix_fmt >= 0)
00821             goto found;
00822         if (loss_mask == 0)
00823             break;
00824     }
00825     return -1;
00826  found:
00827     if (loss_ptr)
00828         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
00829     return dst_pix_fmt;
00830 }
00831 
00832 void ff_img_copy_plane(uint8_t *dst, int dst_wrap,
00833                            const uint8_t *src, int src_wrap,
00834                            int width, int height)
00835 {
00836     if((!dst) || (!src))
00837         return;
00838     for(;height > 0; height--) {
00839         memcpy(dst, src, width);
00840         dst += dst_wrap;
00841         src += src_wrap;
00842     }
00843 }
00844 
00845 int ff_get_plane_bytewidth(enum PixelFormat pix_fmt, int width, int plane)
00846 {
00847     int bits;
00848     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00849 
00850     pf = &pix_fmt_info[pix_fmt];
00851     switch(pf->pixel_type) {
00852     case FF_PIXEL_PACKED:
00853         switch(pix_fmt) {
00854         case PIX_FMT_YUYV422:
00855         case PIX_FMT_UYVY422:
00856         case PIX_FMT_RGB565:
00857         case PIX_FMT_RGB555:
00858         case PIX_FMT_BGR565:
00859         case PIX_FMT_BGR555:
00860             bits = 16;
00861             break;
00862         case PIX_FMT_UYYVYY411:
00863             bits = 12;
00864             break;
00865         default:
00866             bits = pf->depth * pf->nb_channels;
00867             break;
00868         }
00869         return (width * bits + 7) >> 3;
00870         break;
00871     case FF_PIXEL_PLANAR:
00872             if (plane == 1 || plane == 2)
00873                 width >>= pf->x_chroma_shift;
00874 
00875             return (width * pf->depth + 7) >> 3;
00876         break;
00877     case FF_PIXEL_PALETTE:
00878         if (plane == 0)
00879             return width;
00880         break;
00881     }
00882 
00883     return -1;
00884 }
00885 
00886 void av_picture_copy(AVPicture *dst, const AVPicture *src,
00887               int pix_fmt, int width, int height)
00888 {
00889     int i;
00890     const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
00891 
00892     pf = &pix_fmt_info[pix_fmt];
00893     switch(pf->pixel_type) {
00894     case FF_PIXEL_PACKED:
00895     case FF_PIXEL_PLANAR:
00896         for(i = 0; i < pf->nb_channels; i++) {
00897             int w, h;
00898             int bwidth = ff_get_plane_bytewidth(pix_fmt, width, i);
00899             if (bwidth < 0)
00900                 continue; /* unknown pixel type, ignore */
00901             w = width;
00902             h = height;
00903             if (i == 1 || i == 2) {
00904                 w >>= pf->x_chroma_shift;
00905                 h >>= pf->y_chroma_shift;
00906             }
00907             ff_img_copy_plane(dst->data[i], dst->linesize[i],
00908                            src->data[i], src->linesize[i],
00909                            bwidth, h);
00910         }
00911         break;
00912     case FF_PIXEL_PALETTE:
00913         ff_img_copy_plane(dst->data[0], dst->linesize[0],
00914                        src->data[0], src->linesize[0],
00915                        width, height);
00916         /* copy the palette */
00917         ff_img_copy_plane(dst->data[1], dst->linesize[1],
00918                        src->data[1], src->linesize[1],
00919                        4, 256);
00920         break;
00921     }
00922 }
00923 
00924 /* XXX: totally non optimized */
00925 
00926 static void yuyv422_to_yuv420p(AVPicture *dst, const AVPicture *src,
00927                               int width, int height)
00928 {
00929     const uint8_t *p, *p1;
00930     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00931     int w;
00932 
00933     p1 = src->data[0];
00934     lum1 = dst->data[0];
00935     cb1 = dst->data[1];
00936     cr1 = dst->data[2];
00937 
00938     for(;height >= 1; height -= 2) {
00939         p = p1;
00940         lum = lum1;
00941         cb = cb1;
00942         cr = cr1;
00943         for(w = width; w >= 2; w -= 2) {
00944             lum[0] = p[0];
00945             cb[0] = p[1];
00946             lum[1] = p[2];
00947             cr[0] = p[3];
00948             p += 4;
00949             lum += 2;
00950             cb++;
00951             cr++;
00952         }
00953         if (w) {
00954             lum[0] = p[0];
00955             cb[0] = p[1];
00956             cr[0] = p[3];
00957             cb++;
00958             cr++;
00959         }
00960         p1 += src->linesize[0];
00961         lum1 += dst->linesize[0];
00962         if (height>1) {
00963             p = p1;
00964             lum = lum1;
00965             for(w = width; w >= 2; w -= 2) {
00966                 lum[0] = p[0];
00967                 lum[1] = p[2];
00968                 p += 4;
00969                 lum += 2;
00970             }
00971             if (w) {
00972                 lum[0] = p[0];
00973             }
00974             p1 += src->linesize[0];
00975             lum1 += dst->linesize[0];
00976         }
00977         cb1 += dst->linesize[1];
00978         cr1 += dst->linesize[2];
00979     }
00980 }
00981 
00982 static void uyvy422_to_yuv420p(AVPicture *dst, const AVPicture *src,
00983                               int width, int height)
00984 {
00985     const uint8_t *p, *p1;
00986     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
00987     int w;
00988 
00989     p1 = src->data[0];
00990 
00991     lum1 = dst->data[0];
00992     cb1 = dst->data[1];
00993     cr1 = dst->data[2];
00994 
00995     for(;height >= 1; height -= 2) {
00996         p = p1;
00997         lum = lum1;
00998         cb = cb1;
00999         cr = cr1;
01000         for(w = width; w >= 2; w -= 2) {
01001             lum[0] = p[1];
01002             cb[0] = p[0];
01003             lum[1] = p[3];
01004             cr[0] = p[2];
01005             p += 4;
01006             lum += 2;
01007             cb++;
01008             cr++;
01009         }
01010         if (w) {
01011             lum[0] = p[1];
01012             cb[0] = p[0];
01013             cr[0] = p[2];
01014             cb++;
01015             cr++;
01016         }
01017         p1 += src->linesize[0];
01018         lum1 += dst->linesize[0];
01019         if (height>1) {
01020             p = p1;
01021             lum = lum1;
01022             for(w = width; w >= 2; w -= 2) {
01023                 lum[0] = p[1];
01024                 lum[1] = p[3];
01025                 p += 4;
01026                 lum += 2;
01027             }
01028             if (w) {
01029                 lum[0] = p[1];
01030             }
01031             p1 += src->linesize[0];
01032             lum1 += dst->linesize[0];
01033         }
01034         cb1 += dst->linesize[1];
01035         cr1 += dst->linesize[2];
01036     }
01037 }
01038 
01039 
01040 static void uyvy422_to_yuv422p(AVPicture *dst, const AVPicture *src,
01041                               int width, int height)
01042 {
01043     const uint8_t *p, *p1;
01044     uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
01045     int w;
01046 
01047     p1 = src->data[0];
01048     lum1 = dst->data[0];
01049     cb1 = dst->data[1];
01050     cr1 = dst->data[2];
01051     for(;height > 0; height--) {
01052         p = p1;
01053         lum = lum1;
01054         cb = cb1;
01055         cr = cr1;
01056         for(w = width; w >= 2; w -= 2) {
01057             lum[0] = p[1];
01058             cb[0] = p[0];
01059             lum[1] = p[3];
01060             cr[0] = p[2];
01061             p += 4;
01062             lum += 2;
01063             cb++;
01064