X-Git-Url: http://git.maemo.org/git/?p=mafwsubrenderer;a=blobdiff_plain;f=gst-plugins-base-subtitles0.10%2Fgst%2Fffmpegcolorspace%2Fimgconvert.c;fp=gst-plugins-base-subtitles0.10%2Fgst%2Fffmpegcolorspace%2Fimgconvert.c;h=cb145bb5c817f79eba8a0d3368a6dab13a060db2;hp=0000000000000000000000000000000000000000;hb=57ba96e291a055f69dbfd4ae9f1ae2390e36986e;hpb=be2c98fb83895d10ac44af7b9a9c3e00ca54bf49 diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert.c b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert.c new file mode 100644 index 0000000..cb145bb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert.c @@ -0,0 +1,4126 @@ +/* + * Misc image convertion routines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file imgconvert.c + * Misc image convertion routines. + */ + +/* TODO: + * - write 'ffimg' program to test all the image related stuff + * - move all api to slice based system + * - integrate deinterlacing, postprocessing and scaling in the conversion process + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "gstffmpegcodecmap.h" + +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (ffmpegcolorspace_performance); + +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) + +/* this table gives more information about formats */ +/* FIXME, this table is also in ffmpegcodecmap */ +static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { + /* YUV formats */ + /* [PIX_FMT_YUV420P] = */ { + /* .format = */ PIX_FMT_YUV420P, + /* .name = */ "yuv420p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_YVU420P] = */ { + /* .format = */ PIX_FMT_YVU420P, + /* .name = */ "yvu420p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_NV12] = */ { + /* .format = */ PIX_FMT_NV12, + /* .name = */ "nv12", + /* .nb_channels = */ 2, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_NV21] = */ { + /* .format = */ PIX_FMT_NV21, + /* .name = */ "nv21", + /* .nb_channels = */ 2, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV422P] = */ { + /* .format = */ PIX_FMT_YUV422P, + /* .name = */ "yuv422p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV444P] = */ { + /* .format = */ PIX_FMT_YUV444P, + /* .name = */ "yuv444p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV422] = */ { + /* .format = */ PIX_FMT_YUV422, + /* .name = */ "yuv422", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_UYVY422] = */ { + /* .format = */ PIX_FMT_UYVY422, + /* .name = */ "uyvy422", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YVYU422] = */ { + /* .format = */ PIX_FMT_YVYU422, + /* .name = */ "yvyu422", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_V308] = */ { + /* .format = */ PIX_FMT_V308, + /* .name = */ "v308", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV410P] = */ { + /* .format = */ PIX_FMT_YUV410P, + /* .name = */ "yuv410p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 2, + /* .depth = */ 8, + }, + /* [PIX_FMT_YVU410P] = */ { + /* .format = */ PIX_FMT_YVU410P, + /* .name = */ "yvu410p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 2, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV411P] = */ { + /* .format = */ PIX_FMT_YUV411P, + /* .name = */ "yuv411p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_Y800] = */ { + /* .format = */ PIX_FMT_Y800, + /* .name = */ "y800", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_Y16] = */ { + /* .format = */ PIX_FMT_Y16, + /* .name = */ "y16", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 16, + }, + + /* JPEG YUV */ + /* [PIX_FMT_YUVJ420P] = */ { + /* .format = */ PIX_FMT_YUVJ420P, + /* .name = */ "yuvj420p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV_JPEG, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUVJ422P] = */ { + /* .format = */ PIX_FMT_YUVJ422P, + /* .name = */ "yuvj422p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV_JPEG, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUVJ444P] = */ { + /* .format = */ PIX_FMT_YUVJ444P, + /* .name = */ "yuvj444p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV_JPEG, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + + /* RGB formats */ + /* [PIX_FMT_RGB24] = */ { + /* .format = */ PIX_FMT_RGB24, + /* .name = */ "rgb24", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGR24] = */ { + /* .format = */ PIX_FMT_BGR24, + /* .name = */ "bgr24", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGB32] = */ { + /* .format = */ PIX_FMT_RGB32, + /* .name = */ "rgb32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGR32] = */ { + /* .format = */ PIX_FMT_BGR32, + /* .name = */ "bgr32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGB32] = */ { + /* .format = */ PIX_FMT_xRGB32, + /* .name = */ "xrgb32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGR32] = */ { + /* .format = */ PIX_FMT_BGRx32, + /* .name = */ "bgrx32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGBA32] = */ { + /* .format = */ PIX_FMT_RGBA32, + /* .name = */ "rgba32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGRA32] = */ { + /* .format = */ PIX_FMT_BGRA32, + /* .name = */ "bgra32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_ARGB32] = */ { + /* .format = */ PIX_FMT_ARGB32, + /* .name = */ "argb32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_ABGR32] = */ { + /* .format = */ PIX_FMT_ABGR32, + /* .name = */ "abgr32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGB565] = */ { + /* .format = */ PIX_FMT_RGB565, + /* .name = */ "rgb565", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 5, + }, + /* [PIX_FMT_RGB555] = */ { + /* .format = */ PIX_FMT_RGB555, + /* .name = */ "rgb555", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 5, + }, + + /* gray / mono formats */ + /* [PIX_FMT_GRAY8] = */ { + /* .format = */ PIX_FMT_GRAY8, + /* .name = */ "gray", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_GRAY16_L] = */ { + /* .format = */ PIX_FMT_GRAY16_L, + /* .name = */ "gray", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 16, + }, + /* [PIX_FMT_GRAY16_B] = */ { + /* .format = */ PIX_FMT_GRAY16_B, + /* .name = */ "gray", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 16, + }, + /* [PIX_FMT_MONOWHITE] = */ { + /* .format = */ PIX_FMT_MONOWHITE, + /* .name = */ "monow", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 1, + }, + /* [PIX_FMT_MONOBLACK] = */ { + /* .format = */ PIX_FMT_MONOBLACK, + /* .name = */ "monob", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 1, + }, + + /* paletted formats */ + /* [PIX_FMT_PAL8] = */ { + /* .format = */ PIX_FMT_PAL8, + /* .name = */ "pal8", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PALETTE, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_XVMC_MPEG2_MC] = */ { + /* .format = */ PIX_FMT_XVMC_MPEG2_MC, + /* .name = */ "xvmcmc", + }, + /* [PIX_FMT_XVMC_MPEG2_IDCT] = */ { + /* .format = */ PIX_FMT_XVMC_MPEG2_IDCT, + /* .name = */ "xvmcidct", + }, + /* [PIX_FMT_UYVY411] = */ { + /* .format = */ PIX_FMT_UYVY411, + /* .name = */ "uyvy411", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_AYUV4444] = */ { + /* .format = */ PIX_FMT_AYUV4444, + /* .name = */ "ayuv4444", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /*.depth = */ 8 + }, + /* [PIX_FMT_YUVA420P] = */ { + /* .format = */ PIX_FMT_YUVA420P, + /* .name = */ "yuva420p", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + } +}; + +/* returns NULL if not found */ +/* undid static since this is also used in gstffmpegcodecmap.c */ +PixFmtInfo * +get_pix_fmt_info (enum PixelFormat format) +{ + int i; + + for (i = 0; i < sizeof (pix_fmt_info) / sizeof (pix_fmt_info[0]); i++) { + if (pix_fmt_info[i].format == format) { + return pix_fmt_info + i; + } + } + + /* since this doesn't get checked *anywhere*, we might as well warn + here if we return NULL so you have *some* idea what's going on */ + g_warning + ("Could not find info for pixel format %d out of %d known pixel formats. One segfault coming up", + format, PIX_FMT_NB); + return NULL; +} + +void +avcodec_get_chroma_sub_sample (int pix_fmt, int *h_shift, int *v_shift) +{ + *h_shift = get_pix_fmt_info (pix_fmt)->x_chroma_shift; + *v_shift = get_pix_fmt_info (pix_fmt)->y_chroma_shift; +} + +const char * +avcodec_get_pix_fmt_name (int pix_fmt) +{ + if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB) + return "???"; + else + return get_pix_fmt_info (pix_fmt)->name; +} + +enum PixelFormat +avcodec_get_pix_fmt (const char *name) +{ + int i; + + for (i = 0; i < PIX_FMT_NB; i++) + if (!strcmp (pix_fmt_info[i].name, name)) + break; + return pix_fmt_info[i].format; +} + +#if 0 +static int +avpicture_layout (const AVPicture * src, int pix_fmt, int width, int height, + unsigned char *dest, int dest_size) +{ + PixFmtInfo *pf = get_pix_fmt_info (pix_fmt); + int i, j, w, h, data_planes; + const unsigned char *s; + int size = avpicture_get_size (pix_fmt, width, height); + + if (size > dest_size) + return -1; + + if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) { + if (pix_fmt == PIX_FMT_YUV422 || + pix_fmt == PIX_FMT_UYVY422 || + pix_fmt == PIX_FMT_RGB565 || pix_fmt == PIX_FMT_RGB555) + w = width * 2; + else if (pix_fmt == PIX_FMT_UYVY411) + w = width + width / 2; + else if (pix_fmt == PIX_FMT_PAL8) + w = width; + else + w = width * (pf->depth * pf->nb_channels / 8); + + data_planes = 1; + h = height; + } else { + data_planes = pf->nb_channels; + w = (width * pf->depth + 7) / 8; + h = height; + } + + for (i = 0; i < data_planes; i++) { + if (i == 1) { + w = width >> pf->x_chroma_shift; + h = height >> pf->y_chroma_shift; + } + s = src->data[i]; + for (j = 0; j < h; j++) { + memcpy (dest, s, w); + dest += w; + s += src->linesize[i]; + } + } + + if (pf->pixel_type == FF_PIXEL_PALETTE) + memcpy ((unsigned char *) (((size_t) dest + 3) & ~3), src->data[1], + 256 * 4); + + return size; +} +#endif + +int +avpicture_get_size (int pix_fmt, int width, int height) +{ + AVPicture dummy_pict; + + return gst_ffmpegcsp_avpicture_fill (&dummy_pict, NULL, pix_fmt, width, + height, FALSE); +} + +/** + * compute the loss when converting from a pixel format to another + */ +int +avcodec_get_pix_fmt_loss (int dst_pix_fmt, int src_pix_fmt, int has_alpha) +{ + const PixFmtInfo *pf, *ps; + int loss; + + ps = get_pix_fmt_info (src_pix_fmt); + pf = get_pix_fmt_info (dst_pix_fmt); + + /* compute loss */ + loss = 0; + if (pf->depth < ps->depth || + (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565)) + loss |= FF_LOSS_DEPTH; + if (pf->x_chroma_shift > ps->x_chroma_shift || + pf->y_chroma_shift > ps->y_chroma_shift) + loss |= FF_LOSS_RESOLUTION; + switch (pf->color_type) { + case FF_COLOR_RGB: + if (ps->color_type != FF_COLOR_RGB && ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_GRAY: + if (ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV: + if (ps->color_type != FF_COLOR_YUV) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV_JPEG: + if (ps->color_type != FF_COLOR_YUV_JPEG && + ps->color_type != FF_COLOR_YUV && ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + default: + /* fail safe test */ + if (ps->color_type != pf->color_type) + loss |= FF_LOSS_COLORSPACE; + break; + } + if (pf->color_type == FF_COLOR_GRAY && ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_CHROMA; + if (!pf->is_alpha && (ps->is_alpha && has_alpha)) + loss |= FF_LOSS_ALPHA; + if (pf->pixel_type == FF_PIXEL_PALETTE && + (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY)) + loss |= FF_LOSS_COLORQUANT; + return loss; +} + +static int +avg_bits_per_pixel (int pix_fmt) +{ + int bits; + const PixFmtInfo *pf; + + pf = get_pix_fmt_info (pix_fmt); + switch (pf->pixel_type) { + case FF_PIXEL_PACKED: + switch (pix_fmt) { + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_YVYU422: + case PIX_FMT_RGB565: + case PIX_FMT_RGB555: + bits = 16; + break; + case PIX_FMT_UYVY411: + bits = 12; + break; + default: + bits = pf->depth * pf->nb_channels; + break; + } + break; + case FF_PIXEL_PLANAR: + if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) { + bits = pf->depth * pf->nb_channels; + } else { + bits = pf->depth + ((2 * pf->depth) >> + (pf->x_chroma_shift + pf->y_chroma_shift)); + } + break; + case FF_PIXEL_PALETTE: + bits = 8; + break; + default: + bits = -1; + break; + } + return bits; +} + +static int +avcodec_find_best_pix_fmt1 (int pix_fmt_mask, + int src_pix_fmt, int has_alpha, int loss_mask) +{ + int dist, i, loss, min_dist, dst_pix_fmt; + + /* find exact color match with smallest size */ + dst_pix_fmt = -1; + min_dist = 0x7fffffff; + for (i = 0; i < PIX_FMT_NB; i++) { + if (pix_fmt_mask & (1 << i)) { + loss = avcodec_get_pix_fmt_loss (i, src_pix_fmt, has_alpha) & loss_mask; + if (loss == 0) { + dist = avg_bits_per_pixel (i); + if (dist < min_dist) { + min_dist = dist; + dst_pix_fmt = i; + } + } + } + } + return dst_pix_fmt; +} + +/** + * find best pixel format to convert to. Return -1 if none found + */ +int +avcodec_find_best_pix_fmt (int pix_fmt_mask, int src_pix_fmt, + int has_alpha, int *loss_ptr) +{ + int dst_pix_fmt, loss_mask, i; + static const int loss_mask_order[] = { + ~0, /* no loss first */ + ~FF_LOSS_ALPHA, + ~FF_LOSS_RESOLUTION, + ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION), + ~FF_LOSS_COLORQUANT, + ~FF_LOSS_DEPTH, + 0, + }; + + /* try with successive loss */ + i = 0; + for (;;) { + loss_mask = loss_mask_order[i++]; + dst_pix_fmt = avcodec_find_best_pix_fmt1 (pix_fmt_mask, src_pix_fmt, + has_alpha, loss_mask); + if (dst_pix_fmt >= 0) + goto found; + if (loss_mask == 0) + break; + } + return -1; +found: + if (loss_ptr) + *loss_ptr = avcodec_get_pix_fmt_loss (dst_pix_fmt, src_pix_fmt, has_alpha); + return dst_pix_fmt; +} + +static void +img_copy_plane (uint8_t * dst, int dst_wrap, + const uint8_t * src, int src_wrap, int width, int height) +{ + for (; height > 0; height--) { + memcpy (dst, src, width); + dst += dst_wrap; + src += src_wrap; + } +} + +/** + * Copy image 'src' to 'dst'. + */ +static void +img_copy (AVPicture * dst, const AVPicture * src, + int pix_fmt, int width, int height) +{ + int bwidth, bits, i; + const PixFmtInfo *pf; + + pf = get_pix_fmt_info (pix_fmt); + switch (pf->pixel_type) { + case FF_PIXEL_PACKED: + switch (pix_fmt) { + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_YVYU422: + case PIX_FMT_RGB565: + case PIX_FMT_RGB555: + bits = 16; + break; + case PIX_FMT_UYVY411: + bits = 12; + break; + default: + bits = pf->depth * pf->nb_channels; + break; + } + bwidth = (width * bits + 7) >> 3; + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], bwidth, height); + break; + case FF_PIXEL_PLANAR: + for (i = 0; i < pf->nb_channels; i++) { + int w, h; + + w = width; + h = height; + if (i == 1 || i == 2) { + w >>= pf->x_chroma_shift; + h >>= pf->y_chroma_shift; + } + bwidth = (w * pf->depth + 7) >> 3; + img_copy_plane (dst->data[i], dst->linesize[i], + src->data[i], src->linesize[i], bwidth, h); + } + break; + case FF_PIXEL_PALETTE: + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], width, height); + /* copy the palette */ + img_copy_plane (dst->data[1], dst->linesize[1], + src->data[1], src->linesize[1], 4, 256); + break; + } +} + +/* XXX: totally non optimized */ + +static void +yuv422_to_yuv420p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[1]; + cr[0] = p[3]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + if (w) { + lum[0] = p[0]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +uyvy422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *lum1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + lum[1] = p[3]; + p += 4; + lum += 2; + } + + if (w) + lum[0] = p[1]; + + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } +} + + +static void +uyvy422_to_yuv420p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + cb[0] = p[0]; + lum[1] = p[3]; + cr[0] = p[2]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[1]; + cb[0] = p[0]; + cr[0] = p[2]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + lum[1] = p[3]; + p += 4; + lum += 2; + } + if (w) { + lum[0] = p[1]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + + +static void +uyvy422_to_yuv422p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + cb[0] = p[0]; + lum[1] = p[3]; + cr[0] = p[2]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[1]; + cb[0] = p[0]; + cr[0] = p[2]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yvyu422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *lum1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + + if (w) + lum[0] = p[0]; + + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } +} + +static void +yvyu422_to_yuv420p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[3]; + lum[1] = p[2]; + cr[0] = p[1]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[3]; + cr[0] = p[1]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + if (w) { + lum[0] = p[0]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yvyu422_to_yuv422p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[3]; + lum[1] = p[2]; + cr[0] = p[1]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[3]; + cr[0] = p[1]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yuv422_to_yuv422p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[1]; + cr[0] = p[3]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yuv422p_to_yuv422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + p[0] = lum[0]; + p[1] = cb[0]; + p[2] = lum[1]; + p[3] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + p[0] = lum[0]; + p[1] = cb[0]; + p[3] = cr[0]; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +yuv422p_to_uyvy422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + p[1] = lum[0]; + p[0] = cb[0]; + p[3] = lum[1]; + p[2] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + p[1] = lum[0]; + p[0] = cb[0]; + p[2] = cr[0]; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +yuv422p_to_yvyu422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + p[0] = lum[0]; + p[3] = cb[0]; + p[2] = lum[1]; + p[1] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + p[0] = lum[0]; + p[3] = cb[0]; + p[1] = cr[0]; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +uyvy411_to_yuv411p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 4; w -= 4) { + cb[0] = p[0]; + lum[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + lum[2] = p[4]; + lum[3] = p[5]; + p += 6; + lum += 4; + cb++; + cr++; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yuv411p_to_uyvy411 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 4; w -= 4) { + p[0] = cb[0]; + p[1] = lum[0]; + p[2] = lum[1]; + p[3] = cr[0]; + p[4] = lum[2]; + p[5] = lum[3]; + p += 6; + lum += 4; + cb++; + cr++; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +yuv420p_to_yuv422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int w, h; + uint8_t *line1, *line2, *linesrc = dst->data[0]; + uint8_t *lum1, *lum2, *lumsrc = src->data[0]; + uint8_t *cb1, *cb2 = src->data[1]; + uint8_t *cr1, *cr2 = src->data[2]; + + for (h = height / 2; h--;) { + line1 = linesrc; + line2 = linesrc + dst->linesize[0]; + + lum1 = lumsrc; + lum2 = lumsrc + src->linesize[0]; + + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + } + + linesrc += dst->linesize[0] * 2; + lumsrc += src->linesize[0] * 2; + cb2 += src->linesize[1]; + cr2 += src->linesize[2]; + } + /* odd height */ + if (height % 2 != 0) { + line1 = linesrc; + lum1 = lumsrc; + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line1++ = *cb1++; + *line1++ = *lum1++; + *line1++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line1++ = *cb1++; + } + } +} + +static void +nv12_to_nv21 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const uint8_t *s_c_ptr; + uint8_t *d_c_ptr; + int w, c_wrap; + + memcpy (dst->data[0], src->data[0], src->linesize[0] * height); + + s_c_ptr = src->data[1]; + d_c_ptr = dst->data[1]; + c_wrap = src->linesize[1] - ((width + 1) & ~0x01); + + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + + /* handle odd width */ + if (w) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + s_c_ptr += c_wrap; + d_c_ptr += c_wrap; + } + + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + + /* handle odd width */ + if (w) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + } +} + +static void +nv12_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height) +{ + int w, h; + uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0]; + uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1]; + uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2]; + uint8_t *lum1, *lum2, *src_lum_line = src->data[0]; + uint8_t *src_c1, *src_c_line = src->data[1]; + uint8_t cb, cr; + + for (h = height / 2; h--;) { + dst_lum1 = dst_line; + dst_lum2 = dst_line + dst->linesize[0]; + + dst_cb1 = dst_cb_line; + dst_cb2 = dst_cb_line + dst->linesize[1]; + dst_cr1 = dst_cr_line; + dst_cr2 = dst_cr_line + dst->linesize[2]; + + lum1 = src_lum_line; + lum2 = src_lum_line + src->linesize[0]; + + src_c1 = src_c_line; + + for (w = width / 2; w--;) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = *src_c1++; + *dst_cr1++ = *dst_cr2++ = *src_c1++; + } + + dst_line += dst->linesize[0] * 2; + dst_cb_line += dst->linesize[1] * 2; + dst_cr_line += dst->linesize[2] * 2; + src_lum_line += src->linesize[0] * 2; + src_c_line += src->linesize[1]; + } + + /* odd height */ + if (height % 2 != 0) { + dst_lum1 = dst_line; + lum1 = src_lum_line; + src_c1 = src_c_line; + dst_cb1 = dst_cb_line; + dst_cr1 = dst_cr_line; + + for (w = width / 2; w--;) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + } +} + +#define nv21_to_nv12 nv12_to_nv21 + +static void +nv21_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height) +{ + int w, h; + uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0]; + uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1]; + uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2]; + uint8_t *lum1, *lum2, *src_lum_line = src->data[0]; + uint8_t *src_c1, *src_c_line = src->data[1]; + uint8_t cb, cr; + + for (h = height / 2; h--;) { + dst_lum1 = dst_line; + dst_lum2 = dst_line + dst->linesize[0]; + + dst_cb1 = dst_cb_line; + dst_cb2 = dst_cb_line + dst->linesize[1]; + dst_cr1 = dst_cr_line; + dst_cr2 = dst_cr_line + dst->linesize[2]; + + lum1 = src_lum_line; + lum2 = src_lum_line + src->linesize[0]; + + src_c1 = src_c_line; + + for (w = width / 2; w--;) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = *src_c1++; + *dst_cr1++ = *dst_cr2++ = *src_c1++; + } + + dst_line += dst->linesize[0] * 2; + dst_cb_line += dst->linesize[1] * 2; + dst_cr_line += dst->linesize[2] * 2; + src_lum_line += src->linesize[0] * 2; + src_c_line += src->linesize[1]; + } + + /* odd height */ + if (height % 2 != 0) { + dst_lum1 = dst_line; + lum1 = src_lum_line; + src_c1 = src_c_line; + + dst_cb1 = dst_cb_line; + dst_cr1 = dst_cr_line; + + for (w = width / 2; w--;) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + } +} + +static void +yuva420p_to_yuv420p (AVPicture * dst, const AVPicture * src, int width, + int height) +{ + memcpy (dst->data[0], src->data[0], dst->linesize[0] * height); + memcpy (dst->data[1], src->data[1], dst->linesize[1] * ((height + 1) / 2)); + memcpy (dst->data[2], src->data[2], dst->linesize[2] * ((height + 1) / 2)); +} + +static void +yuva420p_to_yuv422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int w, h; + uint8_t *line1, *line2, *linesrc = dst->data[0]; + uint8_t *lum1, *lum2, *lumsrc = src->data[0]; + uint8_t *cb1, *cb2 = src->data[1]; + uint8_t *cr1, *cr2 = src->data[2]; + + for (h = height / 2; h--;) { + line1 = linesrc; + line2 = linesrc + dst->linesize[0]; + + lum1 = lumsrc; + lum2 = lumsrc + src->linesize[0]; + + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + } + + linesrc += dst->linesize[0] * 2; + lumsrc += src->linesize[0] * 2; + cb2 += src->linesize[1]; + cr2 += src->linesize[2]; + } + /* odd height */ + if (height % 2 != 0) { + line1 = linesrc; + lum1 = lumsrc; + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line1++ = *cb1++; + *line1++ = *lum1++; + *line1++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line1++ = *cb1++; + } + } +} + +#define SCALEBITS 10 +#define ONE_HALF (1 << (SCALEBITS - 1)) +#define FIX(x) ((int) ((x) * (1<> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define YUV_TO_RGB1(cb1, cr1)\ +{\ + cb = (cb1) - 128;\ + cr = (cr1) - 128;\ + r_add = FIX(1.40200) * cr + ONE_HALF;\ + g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ + b_add = FIX(1.77200) * cb + ONE_HALF;\ +} + +#define YUV_TO_RGB2(r, g, b, y1)\ +{\ + y = (y1) << SCALEBITS;\ + r = cm[(y + r_add) >> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define Y_CCIR_TO_JPEG(y)\ + cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] + +#define Y_JPEG_TO_CCIR(y)\ + (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define C_CCIR_TO_JPEG(y)\ + cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] + +/* NOTE: the clamp is really necessary! */ +static inline int +C_JPEG_TO_CCIR (int y) +{ + y = (((y - 128) * FIX (112.0 / 127.0) + (ONE_HALF + + (128 << SCALEBITS))) >> SCALEBITS); + if (y < 16) + y = 16; + return y; +} + + +#define RGB_TO_Y(r, g, b) \ +((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ + FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) + +#define RGB_TO_U(r1, g1, b1, shift)\ +(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ + FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V(r1, g1, b1, shift)\ +(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ + FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_Y_CCIR(r, g, b) \ +((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ + FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ +(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ + FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ +(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ + FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +static uint8_t y_ccir_to_jpeg[256]; +static uint8_t y_jpeg_to_ccir[256]; +static uint8_t c_ccir_to_jpeg[256]; +static uint8_t c_jpeg_to_ccir[256]; + +/* init various conversion tables */ +static void +img_convert_init (void) +{ + int i; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + + for (i = 0; i < 256; i++) { + y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG (i); + y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR (i); + c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG (i); + c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR (i); + } +} + +/* apply to each pixel the given table */ +static void +img_apply_table (uint8_t * dst, int dst_wrap, + const uint8_t * src, int src_wrap, + int width, int height, const uint8_t * table1) +{ + int n; + const uint8_t *s; + uint8_t *d; + const uint8_t *table; + + table = table1; + for (; height > 0; height--) { + s = src; + d = dst; + n = width; + while (n >= 4) { + d[0] = table[s[0]]; + d[1] = table[s[1]]; + d[2] = table[s[2]]; + d[3] = table[s[3]]; + d += 4; + s += 4; + n -= 4; + } + while (n > 0) { + d[0] = table[s[0]]; + d++; + s++; + n--; + } + dst += dst_wrap; + src += src_wrap; + } +} + +/* XXX: use generic filter ? */ +/* XXX: in most cases, the sampling position is incorrect */ + +static void +img_copy_plane_resize (uint8_t * dst, int dst_wrap, int dst_width, + int dst_height, const uint8_t * src, int src_wrap, int src_width, + int src_height) +{ + img_copy_plane (dst, dst_wrap, src, src_wrap, dst_width, dst_height); +} + +/* 4x1 -> 1x1 */ +static void +shrink41 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, s_w; + const uint8_t *s; + uint8_t *d; + + for (; dst_height > 0; dst_height--) { + s = src; + d = dst; + for (s_w = src_width, w = dst_width; w > 0 && s_w > 3; w--, s_w -= 4) { + d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2; + s += 4; + d++; + } + + if (w) { + if (s_w == 3) + d[0] = (s[0] + s[1] + s[2]) / 3; + else if (s_w == 2) + d[0] = (s[0] + s[1]) / 2; + else /* s_w == 1 */ + d[0] = s[0]; + } + + src += src_wrap; + dst += dst_wrap; + } +} + +/* 2x1 -> 1x1 */ +static void +shrink21 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, s_w; + const uint8_t *s; + uint8_t *d; + + for (; dst_height > 0; dst_height--) { + s = src; + d = dst; + for (s_w = src_width, w = dst_width; w > 0 && s_w > 1; w--, s_w -= 2) { + d[0] = (s[0] + s[1]) >> 1; + s += 2; + d++; + } + + if (w) /* s_w == 1 */ + d[0] = s[0]; + + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x2 -> 1x1 */ +static void +shrink12 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w; + uint8_t *d; + const uint8_t *s1, *s2; + + for (; dst_height > 0; dst_height--, src_height -= 2) { + s1 = src; + s2 = s1 + (src_height > 1 ? src_wrap : 0); + d = dst; + for (w = dst_width; w >= 4; w -= 4) { + d[0] = (s1[0] + s2[0]) >> 1; + d[1] = (s1[1] + s2[1]) >> 1; + d[2] = (s1[2] + s2[2]) >> 1; + d[3] = (s1[3] + s2[3]) >> 1; + s1 += 4; + s2 += 4; + d += 4; + } + for (; w > 0; w--) { + d[0] = (s1[0] + s2[0]) >> 1; + s1++; + s2++; + d++; + } + src += 2 * src_wrap; + dst += dst_wrap; + } +} + +/* 2x2 -> 1x1 */ +static void +shrink22 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, s_w; + const uint8_t *s1, *s2; + uint8_t *d; + + for (; dst_height > 0; dst_height--, src_height -= 2) { + s1 = src; + s2 = s1 + (src_height > 1 ? src_wrap : 0); + d = dst; + for (s_w = src_width, w = dst_width; w >= 4; w -= 4, s_w -= 8) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; + d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; + d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; + s1 += 8; + s2 += 8; + d += 4; + } + for (; w > 0 && s_w > 1; w--, s_w -= 2) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + s1 += 2; + s2 += 2; + d++; + } + + if (w) + d[0] = (s1[0] + s2[0] + 1) >> 1; + + src += 2 * src_wrap; + dst += dst_wrap; + } +} + +/* 4x4 -> 1x1 */ +static void +shrink44 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int s_w, w; + const uint8_t *s1, *s2, *s3, *s4; + uint8_t *d; + + for (; dst_height > 0; dst_height--, src_height -= 4) { + s1 = src; + s2 = s1 + (src_height > 1 ? src_wrap : 0); + s3 = s2 + (src_height > 2 ? src_wrap : 0); + s4 = s3 + (src_height > 3 ? src_wrap : 0); + d = dst; + for (s_w = src_width, w = dst_width; s_w > 3 && w > 0; w--, s_w -= 4) { + d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + + s2[0] + s2[1] + s2[2] + s2[3] + + s3[0] + s3[1] + s3[2] + s3[3] + + s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; + s1 += 4; + s2 += 4; + s3 += 4; + s4 += 4; + d++; + } + + if (w) { + if (s_w == 3) + d[0] = (s1[0] + s1[1] + s1[2] + + s2[0] + s2[1] + s2[2] + + s3[0] + s3[1] + s3[2] + s4[0] + s4[1] + s4[2]) / 12; + else if (s_w == 2) + d[0] = (s1[0] + s1[1] + + s2[0] + s2[1] + s3[0] + s3[1] + s4[0] + s4[1]) / 8; + else /* s_w == 1 */ + d[0] = (s1[0] + s2[0] + s3[0] + s4[0]) / 4; + } + + src += 4 * src_wrap; + dst += dst_wrap; + } +} + +static void +grow21_line (uint8_t * dst, const uint8_t * src, int width) +{ + int w; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for (w = width; w >= 4; w -= 4) { + d[1] = d[0] = s1[0]; + d[3] = d[2] = s1[1]; + s1 += 2; + d += 4; + } + for (; w >= 2; w -= 2) { + d[1] = d[0] = s1[0]; + s1++; + d += 2; + } + /* only needed if width is not a multiple of two */ + if (w) { + d[0] = s1[0]; + } +} + +static void +grow41_line (uint8_t * dst, const uint8_t * src, int width) +{ + int w, v; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for (w = width; w >= 4; w -= 4) { + v = s1[0]; + d[0] = v; + d[1] = v; + d[2] = v; + d[3] = v; + s1++; + d += 4; + } + for (; w > 0; w--) { + d[0] = s1[0]; + d++; + } +} + +/* 1x1 -> 2x1 */ +static void +grow21 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow21_line (dst, src, dst_width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 2x2 */ +static void +grow22 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow21_line (dst, src, dst_width); + if (dst_height % 2) + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 4x1 */ +static void +grow41 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow41_line (dst, src, dst_width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 4x4 */ +static void +grow44 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow41_line (dst, src, dst_width); + if ((dst_height & 3) == 1) + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x2 -> 2x1 */ +static void +conv411 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, c; + const uint8_t *s1, *s2; + uint8_t *d; + + for (; dst_height > 0; dst_height--, src_height -= 2) { + s1 = src; + s2 = src + (src_height > 1 ? src_wrap : 0); + d = dst; + for (w = dst_width; w > 1; w -= 2) { + c = (s1[0] + s2[0]) >> 1; + d[0] = c; + d[1] = c; + s1++; + s2++; + d += 2; + } + + if (w) { + d[0] = (s1[0] + s2[0]) >> 1; + } + + src += src_wrap * 2; + dst += dst_wrap; + } +} + +/* XXX: add jpeg quantize code */ + +#define TRANSP_INDEX (6*6*6) + +/* this is maybe slow, but allows for extensions */ +static inline unsigned char +gif_clut_index (uint8_t r, uint8_t g, uint8_t b) +{ + return ((((r) / 47) % 6) * 6 * 6 + (((g) / 47) % 6) * 6 + (((b) / 47) % 6)); +} + +static void +build_rgb_palette (uint8_t * palette, int has_alpha) +{ + uint32_t *pal; + static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; + int i, r, g, b; + + pal = (uint32_t *) palette; + i = 0; + for (r = 0; r < 6; r++) { + for (g = 0; g < 6; g++) { + for (b = 0; b < 6; b++) { + pal[i++] = (0xffU << 24) | (pal_value[r] << 16) | + (pal_value[g] << 8) | pal_value[b]; + } + } + } + if (has_alpha) + pal[i++] = 0; + while (i < 256) + pal[i++] = 0xff000000; +} + +/* copy bit n to bits 0 ... n - 1 */ +static inline unsigned int +bitcopy_n (unsigned int a, int n) +{ + int mask; + + mask = (1 << n) - 1; + return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask); +} + +/* rgb555 handling */ + +#define RGB_NAME rgb555 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (10 - 3), 3);\ + g = bitcopy_n(v >> (5 - 3), 3);\ + b = bitcopy_n(v << 3, 3);\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (10 - 3), 3);\ + g = bitcopy_n(v >> (5 - 3), 3);\ + b = bitcopy_n(v << 3, 3);\ + a = (-(v >> 15)) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \ + ((a << 8) & 0x8000);\ +} + +#define BPP 2 + +#include "imgconvert_template.h" + +/* rgb565 handling */ + +#define RGB_NAME rgb565 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (11 - 3), 3);\ + g = bitcopy_n(v >> (5 - 2), 2);\ + b = bitcopy_n(v << 3, 3);\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\ +} + +#define BPP 2 + +#include "imgconvert_template.h" + +/* bgr24 handling */ + +#define RGB_NAME bgr24 + +#define RGB_IN(r, g, b, s)\ +{\ + b = (s)[0];\ + g = (s)[1];\ + r = (s)[2];\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + (d)[0] = b;\ + (d)[1] = g;\ + (d)[2] = r;\ +} + +#define BPP 3 + +#include "imgconvert_template.h" + +#undef RGB_IN +#undef RGB_OUT +#undef BPP + +/* rgb24 handling */ + +#define RGB_NAME rgb24 +#define FMT_RGB24 + +#define RGB_IN(r, g, b, s)\ +{\ + r = (s)[0];\ + g = (s)[1];\ + b = (s)[2];\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + (d)[0] = r;\ + (d)[1] = g;\ + (d)[2] = b;\ +} + +#define BPP 3 + +#include "imgconvert_template.h" + +/* rgb32 handling */ + +#define RGB_NAME rgb32 +#define FMT_RGBA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* bgr32 handling */ + +#define RGB_NAME bgr32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = a | (r << 8) | (g << 16) | (b << 24);\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* xrgb32 handling */ + +#define RGB_NAME xrgb32 +#define FMT_RGBA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (r << 24) | (g << 16) | (b << 8) | a;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* bgrx32 handling */ + +#define RGB_NAME bgrx32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = r | (g << 8) | (b << 16) | (a << 24);\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* rgba32 handling */ + +#define RGB_NAME rgba32 +#define FMT_RGBA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = (v >> 24) & 0xff;\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* bgra32 handling */ + +#define RGB_NAME bgra32 +#define FMT_BGRA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = v & 0xff;\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = a | (r << 8) | (g << 16) | (b << 24 );\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* argb32 handling */ + +#define RGB_NAME argb32 +#define FMT_ARGB32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ + a = v & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (r << 24) | (g << 16) | (b << 8) | a;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* abgr32 handling */ + +#define RGB_NAME abgr32 +#define FMT_ABGR32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = v & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = v & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ + a = (v >> 24) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = r | (g << 8) | (b << 16) | (a << 24 );\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +static void +gray_to_gray16_l (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + GST_WRITE_UINT16_LE (q, (*p << 8)); + q += 2; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray_to_gray16_b (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + GST_WRITE_UINT16_BE (q, (*p << 8)); + q += 2; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray16_l_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = GST_READ_UINT16_LE (p) >> 8; + q++; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray16_b_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = GST_READ_UINT16_BE (p) >> 8; + q++; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray16_b_to_gray16_l (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = p[1]; + q[1] = p[0]; + q += 2; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +mono_to_gray (AVPicture * dst, const AVPicture * src, + int width, int height, int xor_mask) +{ + const unsigned char *p; + unsigned char *q; + int v, dst_wrap, src_wrap; + int y, w; + + p = src->data[0]; + src_wrap = src->linesize[0] - ((width + 7) >> 3); + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + for (y = 0; y < height; y++) { + w = width; + while (w >= 8) { + v = *p++ ^ xor_mask; + q[0] = -(v >> 7); + q[1] = -((v >> 6) & 1); + q[2] = -((v >> 5) & 1); + q[3] = -((v >> 4) & 1); + q[4] = -((v >> 3) & 1); + q[5] = -((v >> 2) & 1); + q[6] = -((v >> 1) & 1); + q[7] = -((v >> 0) & 1); + w -= 8; + q += 8; + } + if (w > 0) { + v = *p++ ^ xor_mask; + do { + q[0] = -((v >> 7) & 1); + q++; + v <<= 1; + } while (--w); + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +monowhite_to_gray (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + mono_to_gray (dst, src, width, height, 0xff); +} + +static void +monoblack_to_gray (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + mono_to_gray (dst, src, width, height, 0x00); +} + +static void +gray_to_mono (AVPicture * dst, const AVPicture * src, + int width, int height, int xor_mask) +{ + int n; + const uint8_t *s; + uint8_t *d; + int j, b, v, n1, src_wrap, dst_wrap, y; + + s = src->data[0]; + src_wrap = src->linesize[0] - width; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - ((width + 7) >> 3); + + for (y = 0; y < height; y++) { + n = width; + while (n >= 8) { + v = 0; + for (j = 0; j < 8; j++) { + b = s[0]; + s++; + v = (v << 1) | (b >> 7); + } + d[0] = v ^ xor_mask; + d++; + n -= 8; + } + if (n > 0) { + n1 = n; + v = 0; + while (n > 0) { + b = s[0]; + s++; + v = (v << 1) | (b >> 7); + n--; + } + d[0] = (v << (8 - (n1 & 7))) ^ xor_mask; + d++; + } + s += src_wrap; + d += dst_wrap; + } +} + +static void +gray_to_monowhite (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + gray_to_mono (dst, src, width, height, 0xff); +} + +static void +gray_to_monoblack (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + gray_to_mono (dst, src, width, height, 0x00); +} + +static void +y800_to_y16 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + GST_WRITE_UINT16_LE (q, (*p << 8)); + q += 2; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +y16_to_y800 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = GST_READ_UINT16_LE (p) >> 8; + q++; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +yuva420p_to_ayuv4444 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *a1_ptr, *a2_ptr; + uint8_t *d, *d1, *d2; + int w, width2; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + a1_ptr = src->data[3]; + width2 = (width + 1) >> 1; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + a2_ptr = a1_ptr + src->linesize[3]; + for (w = width; w >= 2; w -= 2) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d1[4 + 0] = a1_ptr[1]; + d1[4 + 1] = y1_ptr[1]; + d1[4 + 2] = cb_ptr[0]; + d1[4 + 3] = cr_ptr[0]; + + d2[0] = a2_ptr[0]; + d2[1] = y2_ptr[0]; + d2[2] = cb_ptr[0]; + d2[3] = cr_ptr[0]; + + d2[4 + 0] = a2_ptr[1]; + d2[4 + 1] = y2_ptr[1]; + d2[4 + 2] = cb_ptr[0]; + d2[4 + 3] = cr_ptr[0]; + + d1 += 2 * 4; + d2 += 2 * 4; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + a2_ptr += 2; + } + /* handle odd width */ + if (w) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d2[0] = a2_ptr[0]; + d2[1] = y2_ptr[0]; + d2[2] = cb_ptr[0]; + d2[3] = cr_ptr[0]; + + d1 += 4; + d2 += 4; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + a2_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + a1_ptr += 2 * src->linesize[3] - width; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d1[4 + 0] = a1_ptr[1]; + d1[4 + 1] = y1_ptr[1]; + d1[4 + 2] = cb_ptr[0]; + d1[4 + 3] = cr_ptr[0]; + + d1 += 2 * 4; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + } + /* handle width */ + if (w) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + d1 += 4; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + } + } +} + +static void +ayuv4444_to_yuva420p (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + int wrap, wrap3, width2; + int u1, v1, w; + uint8_t *lum, *cb, *cr, *a; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + a = dst->data[3]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + p += wrap3; + lum += wrap; + a += wrap; + + a[0] = p[0]; + lum[0] = p[1]; + u1 += p[2]; + v1 += p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + + cb[0] = u1 >> 2; + cr[0] = v1 >> 2; + + cb++; + cr++; + p += -wrap3 + 2 * 4; + lum += -wrap + 2; + a += -wrap + 2; + } + if (w) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + p += wrap3; + lum += wrap; + a += wrap; + + a[0] = p[0]; + lum[0] = p[1]; + u1 += p[2]; + v1 += p[3]; + + cb[0] = u1 >> 1; + cr[0] = v1 >> 1; + cb++; + cr++; + p += -wrap3 + 4; + lum += -wrap + 1; + a += -wrap + 1; + } + p += wrap3 + (wrap3 - width * 4); + lum += wrap + (wrap - width); + a += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + cb[0] = u1 >> 1; + cr[0] = v1 >> 1; + cb++; + cr++; + p += 2 * 4; + lum += 2; + a += 2; + } + if (w) { + a[0] = p[0]; + lum[0] = p[1]; + cb[0] = p[2]; + cr[0] = p[3]; + } + } +} + +typedef struct ConvertEntry +{ + enum PixelFormat src; + enum PixelFormat dest; + void (*convert) (AVPicture * dst, + const AVPicture * src, int width, int height); +} ConvertEntry; + +/* Add each new convertion function in this table. In order to be able + to convert from any format to any format, the following constraints + must be satisfied: + + - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24 + + - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8 + + - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32 + + - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from + PIX_FMT_RGB24. + + - PIX_FMT_422 must convert to and from PIX_FMT_422P. + + The other conversion functions are just optimisations for common cases. +*/ +static ConvertEntry convert_table[] = { + {PIX_FMT_YUV420P, PIX_FMT_YUV422, yuv420p_to_yuv422}, + {PIX_FMT_YUV420P, PIX_FMT_RGB555, yuv420p_to_rgb555}, + {PIX_FMT_YUV420P, PIX_FMT_RGB565, yuv420p_to_rgb565}, + {PIX_FMT_YUV420P, PIX_FMT_BGR24, yuv420p_to_bgr24}, + {PIX_FMT_YUV420P, PIX_FMT_RGB24, yuv420p_to_rgb24}, + {PIX_FMT_YUV420P, PIX_FMT_RGB32, yuv420p_to_rgb32}, + {PIX_FMT_YUV420P, PIX_FMT_BGR32, yuv420p_to_bgr32}, + {PIX_FMT_YUV420P, PIX_FMT_xRGB32, yuv420p_to_xrgb32}, + {PIX_FMT_YUV420P, PIX_FMT_BGRx32, yuv420p_to_bgrx32}, + {PIX_FMT_YUV420P, PIX_FMT_RGBA32, yuv420p_to_rgba32}, + {PIX_FMT_YUV420P, PIX_FMT_BGRA32, yuv420p_to_bgra32}, + {PIX_FMT_YUV420P, PIX_FMT_ARGB32, yuv420p_to_argb32}, + {PIX_FMT_YUV420P, PIX_FMT_ABGR32, yuv420p_to_abgr32}, + + {PIX_FMT_NV12, PIX_FMT_RGB555, nv12_to_rgb555}, + {PIX_FMT_NV12, PIX_FMT_RGB565, nv12_to_rgb565}, + {PIX_FMT_NV12, PIX_FMT_BGR24, nv12_to_bgr24}, + {PIX_FMT_NV12, PIX_FMT_RGB24, nv12_to_rgb24}, + {PIX_FMT_NV12, PIX_FMT_RGB32, nv12_to_rgb32}, + {PIX_FMT_NV12, PIX_FMT_BGR32, nv12_to_bgr32}, + {PIX_FMT_NV12, PIX_FMT_xRGB32, nv12_to_xrgb32}, + {PIX_FMT_NV12, PIX_FMT_BGRx32, nv12_to_bgrx32}, + {PIX_FMT_NV12, PIX_FMT_RGBA32, nv12_to_rgba32}, + {PIX_FMT_NV12, PIX_FMT_BGRA32, nv12_to_bgra32}, + {PIX_FMT_NV12, PIX_FMT_ARGB32, nv12_to_argb32}, + {PIX_FMT_NV12, PIX_FMT_ABGR32, nv12_to_abgr32}, + {PIX_FMT_NV12, PIX_FMT_NV21, nv12_to_nv21}, + {PIX_FMT_NV12, PIX_FMT_YUV444P, nv12_to_yuv444p}, + + {PIX_FMT_NV21, PIX_FMT_RGB555, nv21_to_rgb555}, + {PIX_FMT_NV21, PIX_FMT_RGB565, nv21_to_rgb565}, + {PIX_FMT_NV21, PIX_FMT_BGR24, nv21_to_bgr24}, + {PIX_FMT_NV21, PIX_FMT_RGB24, nv21_to_rgb24}, + {PIX_FMT_NV21, PIX_FMT_RGB32, nv21_to_rgb32}, + {PIX_FMT_NV21, PIX_FMT_BGR32, nv21_to_bgr32}, + {PIX_FMT_NV21, PIX_FMT_xRGB32, nv21_to_xrgb32}, + {PIX_FMT_NV21, PIX_FMT_BGRx32, nv21_to_bgrx32}, + {PIX_FMT_NV21, PIX_FMT_RGBA32, nv21_to_rgba32}, + {PIX_FMT_NV21, PIX_FMT_BGRA32, nv21_to_bgra32}, + {PIX_FMT_NV21, PIX_FMT_ARGB32, nv21_to_argb32}, + {PIX_FMT_NV21, PIX_FMT_ABGR32, nv21_to_abgr32}, + {PIX_FMT_NV21, PIX_FMT_YUV444P, nv21_to_yuv444p}, + {PIX_FMT_NV21, PIX_FMT_NV12, nv21_to_nv12}, + + {PIX_FMT_YUV422P, PIX_FMT_YUV422, yuv422p_to_yuv422}, + {PIX_FMT_YUV422P, PIX_FMT_UYVY422, yuv422p_to_uyvy422}, + {PIX_FMT_YUV422P, PIX_FMT_YVYU422, yuv422p_to_yvyu422}, + + {PIX_FMT_YUV444P, PIX_FMT_RGB24, yuv444p_to_rgb24}, + + {PIX_FMT_YUVJ420P, PIX_FMT_RGB555, yuvj420p_to_rgb555}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB565, yuvj420p_to_rgb565}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGR24, yuvj420p_to_bgr24}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB24, yuvj420p_to_rgb24}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB32, yuvj420p_to_rgb32}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGR32, yuvj420p_to_bgr32}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB32, yuvj420p_to_xrgb32}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGR32, yuvj420p_to_bgrx32}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGBA32, yuvj420p_to_rgba32}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGRA32, yuvj420p_to_bgra32}, + {PIX_FMT_YUVJ420P, PIX_FMT_ARGB32, yuvj420p_to_argb32}, + {PIX_FMT_YUVJ420P, PIX_FMT_ABGR32, yuvj420p_to_abgr32}, + + {PIX_FMT_YUVJ444P, PIX_FMT_RGB24, yuvj444p_to_rgb24}, + + {PIX_FMT_YUV422, PIX_FMT_YUV420P, yuv422_to_yuv420p}, + {PIX_FMT_YUV422, PIX_FMT_YUV422P, yuv422_to_yuv422p}, + {PIX_FMT_YUV422, PIX_FMT_GRAY8, yvyu422_to_gray}, + {PIX_FMT_YUV422, PIX_FMT_RGB555, yuv422_to_rgb555}, + {PIX_FMT_YUV422, PIX_FMT_RGB565, yuv422_to_rgb565}, + {PIX_FMT_YUV422, PIX_FMT_BGR24, yuv422_to_bgr24}, + {PIX_FMT_YUV422, PIX_FMT_RGB24, yuv422_to_rgb24}, + {PIX_FMT_YUV422, PIX_FMT_BGR32, yuv422_to_bgr32}, + {PIX_FMT_YUV422, PIX_FMT_RGB32, yuv422_to_rgb32}, + {PIX_FMT_YUV422, PIX_FMT_xRGB32, yuv422_to_xrgb32}, + {PIX_FMT_YUV422, PIX_FMT_BGRx32, yuv422_to_bgrx32}, + {PIX_FMT_YUV422, PIX_FMT_BGRA32, yuv422_to_bgra32}, + {PIX_FMT_YUV422, PIX_FMT_RGBA32, yuv422_to_rgba32}, + {PIX_FMT_YUV422, PIX_FMT_ABGR32, yuv422_to_abgr32}, + {PIX_FMT_YUV422, PIX_FMT_ARGB32, yuv422_to_argb32}, + + {PIX_FMT_UYVY422, PIX_FMT_YUV420P, uyvy422_to_yuv420p}, + {PIX_FMT_UYVY422, PIX_FMT_YUV422P, uyvy422_to_yuv422p}, + {PIX_FMT_UYVY422, PIX_FMT_GRAY8, uyvy422_to_gray}, + {PIX_FMT_UYVY422, PIX_FMT_RGB555, uyvy422_to_rgb555}, + {PIX_FMT_UYVY422, PIX_FMT_RGB565, uyvy422_to_rgb565}, + {PIX_FMT_UYVY422, PIX_FMT_BGR24, uyvy422_to_bgr24}, + {PIX_FMT_UYVY422, PIX_FMT_RGB24, uyvy422_to_rgb24}, + {PIX_FMT_UYVY422, PIX_FMT_RGB32, uyvy422_to_rgb32}, + {PIX_FMT_UYVY422, PIX_FMT_BGR32, uyvy422_to_bgr32}, + {PIX_FMT_UYVY422, PIX_FMT_xRGB32, uyvy422_to_xrgb32}, + {PIX_FMT_UYVY422, PIX_FMT_BGRx32, uyvy422_to_bgrx32}, + {PIX_FMT_UYVY422, PIX_FMT_RGBA32, uyvy422_to_rgba32}, + {PIX_FMT_UYVY422, PIX_FMT_BGRA32, uyvy422_to_bgra32}, + {PIX_FMT_UYVY422, PIX_FMT_ARGB32, uyvy422_to_argb32}, + {PIX_FMT_UYVY422, PIX_FMT_ABGR32, uyvy422_to_abgr32}, + + {PIX_FMT_YVYU422, PIX_FMT_YUV420P, yvyu422_to_yuv420p}, + {PIX_FMT_YVYU422, PIX_FMT_YUV422P, yvyu422_to_yuv422p}, + {PIX_FMT_YVYU422, PIX_FMT_GRAY8, yvyu422_to_gray}, + {PIX_FMT_YVYU422, PIX_FMT_RGB555, yvyu422_to_rgb555}, + {PIX_FMT_YVYU422, PIX_FMT_RGB565, yvyu422_to_rgb565}, + {PIX_FMT_YVYU422, PIX_FMT_BGR24, yvyu422_to_bgr24}, + {PIX_FMT_YVYU422, PIX_FMT_RGB24, yvyu422_to_rgb24}, + {PIX_FMT_YVYU422, PIX_FMT_BGR32, yvyu422_to_bgr32}, + {PIX_FMT_YVYU422, PIX_FMT_RGB32, yvyu422_to_rgb32}, + {PIX_FMT_YVYU422, PIX_FMT_xRGB32, yvyu422_to_xrgb32}, + {PIX_FMT_YVYU422, PIX_FMT_BGRx32, yvyu422_to_bgrx32}, + {PIX_FMT_YVYU422, PIX_FMT_BGRA32, yvyu422_to_bgra32}, + {PIX_FMT_YVYU422, PIX_FMT_RGBA32, yvyu422_to_rgba32}, + {PIX_FMT_YVYU422, PIX_FMT_ABGR32, yvyu422_to_abgr32}, + {PIX_FMT_YVYU422, PIX_FMT_ARGB32, yvyu422_to_argb32}, + + {PIX_FMT_RGB24, PIX_FMT_YUV420P, rgb24_to_yuv420p}, + {PIX_FMT_RGB24, PIX_FMT_YUVA420P, rgb24_to_yuva420p}, + {PIX_FMT_RGB24, PIX_FMT_NV12, rgb24_to_nv12}, + {PIX_FMT_RGB24, PIX_FMT_NV21, rgb24_to_nv21}, + {PIX_FMT_RGB24, PIX_FMT_RGB565, rgb24_to_rgb565}, + {PIX_FMT_RGB24, PIX_FMT_RGB555, rgb24_to_rgb555}, + {PIX_FMT_RGB24, PIX_FMT_RGB32, rgb24_to_rgb32}, + {PIX_FMT_RGB24, PIX_FMT_BGR32, rgb24_to_bgr32}, + {PIX_FMT_RGB24, PIX_FMT_xRGB32, rgb24_to_xrgb32}, + {PIX_FMT_RGB24, PIX_FMT_BGRx32, rgb24_to_bgrx32}, + {PIX_FMT_RGB24, PIX_FMT_RGBA32, rgb24_to_rgba32}, + {PIX_FMT_RGB24, PIX_FMT_BGR24, rgb24_to_bgr24}, + {PIX_FMT_RGB24, PIX_FMT_BGRA32, rgb24_to_bgra32}, + {PIX_FMT_RGB24, PIX_FMT_ARGB32, rgb24_to_argb32}, + {PIX_FMT_RGB24, PIX_FMT_ABGR32, rgb24_to_abgr32}, + {PIX_FMT_RGB24, PIX_FMT_Y800, rgb24_to_y800}, + {PIX_FMT_RGB24, PIX_FMT_Y16, rgb24_to_y16}, + {PIX_FMT_RGB24, PIX_FMT_GRAY8, rgb24_to_gray}, + {PIX_FMT_RGB24, PIX_FMT_GRAY16_L, rgb24_to_gray16_l}, + {PIX_FMT_RGB24, PIX_FMT_GRAY16_B, rgb24_to_gray16_b}, + {PIX_FMT_RGB24, PIX_FMT_PAL8, rgb24_to_pal8}, + {PIX_FMT_RGB24, PIX_FMT_YUV444P, rgb24_to_yuv444p}, + {PIX_FMT_RGB24, PIX_FMT_YUVJ420P, rgb24_to_yuvj420p}, + {PIX_FMT_RGB24, PIX_FMT_YUVJ444P, rgb24_to_yuvj444p}, + {PIX_FMT_RGB24, PIX_FMT_AYUV4444, rgb24_to_ayuv4444}, + {PIX_FMT_RGB24, PIX_FMT_V308, rgb24_to_v308}, + + {PIX_FMT_RGB32, PIX_FMT_RGB24, rgb32_to_rgb24}, + {PIX_FMT_RGB32, PIX_FMT_RGB555, rgba32_to_rgb555}, + {PIX_FMT_RGB32, PIX_FMT_PAL8, rgb32_to_pal8}, + {PIX_FMT_RGB32, PIX_FMT_YUV420P, rgb32_to_yuv420p}, + {PIX_FMT_RGB32, PIX_FMT_YUVA420P, rgb32_to_yuva420p}, + {PIX_FMT_RGB32, PIX_FMT_NV12, rgb32_to_nv12}, + {PIX_FMT_RGB32, PIX_FMT_NV21, rgb32_to_nv21}, + {PIX_FMT_RGB32, PIX_FMT_Y800, rgb32_to_y800}, + {PIX_FMT_RGB32, PIX_FMT_Y16, rgb32_to_y16}, + {PIX_FMT_RGB32, PIX_FMT_GRAY8, rgb32_to_gray}, + {PIX_FMT_RGB32, PIX_FMT_GRAY16_L, rgb32_to_gray16_l}, + {PIX_FMT_RGB32, PIX_FMT_GRAY16_B, rgb32_to_gray16_b}, + + {PIX_FMT_xRGB32, PIX_FMT_RGB24, xrgb32_to_rgb24}, + {PIX_FMT_xRGB32, PIX_FMT_PAL8, xrgb32_to_pal8}, + {PIX_FMT_xRGB32, PIX_FMT_YUV420P, xrgb32_to_yuv420p}, + {PIX_FMT_xRGB32, PIX_FMT_YUVA420P, xrgb32_to_yuva420p}, + {PIX_FMT_xRGB32, PIX_FMT_NV12, xrgb32_to_nv12}, + {PIX_FMT_xRGB32, PIX_FMT_NV21, xrgb32_to_nv21}, + {PIX_FMT_xRGB32, PIX_FMT_Y800, xrgb32_to_y800}, + {PIX_FMT_xRGB32, PIX_FMT_Y16, xrgb32_to_y16}, + {PIX_FMT_xRGB32, PIX_FMT_GRAY8, xrgb32_to_gray}, + {PIX_FMT_xRGB32, PIX_FMT_GRAY16_L, xrgb32_to_gray16_l}, + {PIX_FMT_xRGB32, PIX_FMT_GRAY16_B, xrgb32_to_gray16_b}, + + {PIX_FMT_RGBA32, PIX_FMT_BGRA32, rgba32_to_bgra32}, + {PIX_FMT_RGBA32, PIX_FMT_ABGR32, rgba32_to_abgr32}, + {PIX_FMT_RGBA32, PIX_FMT_ARGB32, rgba32_to_argb32}, + {PIX_FMT_RGBA32, PIX_FMT_BGR32, rgba32_to_bgr32}, + {PIX_FMT_RGBA32, PIX_FMT_BGRx32, rgba32_to_bgrx32}, + {PIX_FMT_RGBA32, PIX_FMT_ABGR32, rgba32_to_abgr32}, + {PIX_FMT_RGBA32, PIX_FMT_RGB24, rgba32_to_rgb24}, + {PIX_FMT_RGBA32, PIX_FMT_RGB555, rgba32_to_rgb555}, + {PIX_FMT_RGBA32, PIX_FMT_PAL8, rgba32_to_pal8}, + {PIX_FMT_RGBA32, PIX_FMT_YUV420P, rgba32_to_yuv420p}, + {PIX_FMT_RGBA32, PIX_FMT_YUVA420P, rgba32_to_yuva420p}, + {PIX_FMT_RGBA32, PIX_FMT_NV12, rgba32_to_nv12}, + {PIX_FMT_RGBA32, PIX_FMT_NV21, rgba32_to_nv21}, + {PIX_FMT_RGBA32, PIX_FMT_Y800, rgba32_to_y800}, + {PIX_FMT_RGBA32, PIX_FMT_Y16, rgba32_to_y16}, + {PIX_FMT_RGBA32, PIX_FMT_GRAY8, rgba32_to_gray}, + {PIX_FMT_RGBA32, PIX_FMT_GRAY16_L, rgba32_to_gray16_l}, + {PIX_FMT_RGBA32, PIX_FMT_GRAY16_B, rgba32_to_gray16_b}, + {PIX_FMT_RGBA32, PIX_FMT_AYUV4444, rgba32_to_ayuv4444}, + + {PIX_FMT_BGR24, PIX_FMT_RGB24, bgr24_to_rgb24}, + {PIX_FMT_BGR24, PIX_FMT_YUV420P, bgr24_to_yuv420p}, + {PIX_FMT_BGR24, PIX_FMT_YUVA420P, bgr24_to_yuva420p}, + {PIX_FMT_BGR24, PIX_FMT_NV12, bgr24_to_nv12}, + {PIX_FMT_BGR24, PIX_FMT_NV21, bgr24_to_nv21}, + {PIX_FMT_BGR24, PIX_FMT_Y800, bgr24_to_y800}, + {PIX_FMT_BGR24, PIX_FMT_Y16, bgr24_to_y16}, + {PIX_FMT_BGR24, PIX_FMT_GRAY8, bgr24_to_gray}, + {PIX_FMT_BGR24, PIX_FMT_GRAY16_L, bgr24_to_gray16_l}, + {PIX_FMT_BGR24, PIX_FMT_GRAY16_B, bgr24_to_gray16_b}, + + {PIX_FMT_BGR32, PIX_FMT_RGB24, bgr32_to_rgb24}, + {PIX_FMT_BGR32, PIX_FMT_RGBA32, bgr32_to_rgba32}, + {PIX_FMT_BGR32, PIX_FMT_YUV420P, bgr32_to_yuv420p}, + {PIX_FMT_BGR32, PIX_FMT_YUVA420P, bgr32_to_yuva420p}, + {PIX_FMT_BGR32, PIX_FMT_NV12, bgr32_to_nv12}, + {PIX_FMT_BGR32, PIX_FMT_NV21, bgr32_to_nv21}, + {PIX_FMT_BGR32, PIX_FMT_Y800, bgr32_to_y800}, + {PIX_FMT_BGR32, PIX_FMT_Y16, bgr32_to_y16}, + {PIX_FMT_BGR32, PIX_FMT_GRAY8, bgr32_to_gray}, + {PIX_FMT_BGR32, PIX_FMT_GRAY16_L, bgr32_to_gray16_l}, + {PIX_FMT_BGR32, PIX_FMT_GRAY16_B, bgr32_to_gray16_b}, + + {PIX_FMT_BGRx32, PIX_FMT_RGB24, bgrx32_to_rgb24}, + {PIX_FMT_BGRx32, PIX_FMT_RGBA32, bgrx32_to_rgba32}, + {PIX_FMT_BGRx32, PIX_FMT_YUV420P, bgrx32_to_yuv420p}, + {PIX_FMT_BGRx32, PIX_FMT_YUVA420P, bgrx32_to_yuva420p}, + {PIX_FMT_BGRx32, PIX_FMT_NV12, bgrx32_to_nv12}, + {PIX_FMT_BGRx32, PIX_FMT_NV21, bgrx32_to_nv21}, + {PIX_FMT_BGRx32, PIX_FMT_Y800, bgrx32_to_y800}, + {PIX_FMT_BGRx32, PIX_FMT_Y16, bgrx32_to_y16}, + {PIX_FMT_BGRx32, PIX_FMT_GRAY8, bgrx32_to_gray}, + {PIX_FMT_BGRx32, PIX_FMT_GRAY16_L, bgrx32_to_gray16_l}, + {PIX_FMT_BGRx32, PIX_FMT_GRAY16_B, bgrx32_to_gray16_b}, + + {PIX_FMT_BGRA32, PIX_FMT_RGB24, bgra32_to_rgb24}, + {PIX_FMT_BGRA32, PIX_FMT_RGBA32, bgra32_to_rgba32}, + {PIX_FMT_BGRA32, PIX_FMT_YUV420P, bgra32_to_yuv420p}, + {PIX_FMT_BGRA32, PIX_FMT_YUVA420P, bgra32_to_yuva420p}, + {PIX_FMT_BGRA32, PIX_FMT_NV12, bgra32_to_nv12}, + {PIX_FMT_BGRA32, PIX_FMT_NV21, bgra32_to_nv21}, + {PIX_FMT_BGRA32, PIX_FMT_Y800, bgra32_to_y800}, + {PIX_FMT_BGRA32, PIX_FMT_Y16, bgra32_to_y16}, + {PIX_FMT_BGRA32, PIX_FMT_GRAY8, bgra32_to_gray}, + {PIX_FMT_BGRA32, PIX_FMT_GRAY16_L, bgra32_to_gray16_l}, + {PIX_FMT_BGRA32, PIX_FMT_GRAY16_B, bgra32_to_gray16_b}, + {PIX_FMT_BGRA32, PIX_FMT_AYUV4444, bgra32_to_ayuv4444}, + + {PIX_FMT_ABGR32, PIX_FMT_RGB24, abgr32_to_rgb24}, + {PIX_FMT_ABGR32, PIX_FMT_RGBA32, abgr32_to_rgba32}, + {PIX_FMT_ABGR32, PIX_FMT_YUV420P, abgr32_to_yuv420p}, + {PIX_FMT_ABGR32, PIX_FMT_YUVA420P, abgr32_to_yuva420p}, + {PIX_FMT_ABGR32, PIX_FMT_NV12, abgr32_to_nv12}, + {PIX_FMT_ABGR32, PIX_FMT_NV21, abgr32_to_nv21}, + {PIX_FMT_ABGR32, PIX_FMT_Y800, abgr32_to_y800}, + {PIX_FMT_ABGR32, PIX_FMT_Y16, abgr32_to_y16}, + {PIX_FMT_ABGR32, PIX_FMT_GRAY8, abgr32_to_gray}, + {PIX_FMT_ABGR32, PIX_FMT_GRAY16_L, abgr32_to_gray16_l}, + {PIX_FMT_ABGR32, PIX_FMT_GRAY16_B, abgr32_to_gray16_b}, + {PIX_FMT_ABGR32, PIX_FMT_AYUV4444, abgr32_to_ayuv4444}, + + {PIX_FMT_ARGB32, PIX_FMT_RGB24, argb32_to_rgb24}, + {PIX_FMT_ARGB32, PIX_FMT_RGBA32, argb32_to_rgba32}, + {PIX_FMT_ARGB32, PIX_FMT_YUV420P, argb32_to_yuv420p}, + {PIX_FMT_ARGB32, PIX_FMT_YUVA420P, argb32_to_yuva420p}, + {PIX_FMT_ARGB32, PIX_FMT_NV12, argb32_to_nv12}, + {PIX_FMT_ARGB32, PIX_FMT_NV21, argb32_to_nv21}, + {PIX_FMT_ARGB32, PIX_FMT_Y800, argb32_to_y800}, + {PIX_FMT_ARGB32, PIX_FMT_Y16, argb32_to_y16}, + {PIX_FMT_ARGB32, PIX_FMT_GRAY8, argb32_to_gray}, + {PIX_FMT_ARGB32, PIX_FMT_GRAY16_L, argb32_to_gray16_l}, + {PIX_FMT_ARGB32, PIX_FMT_GRAY16_B, argb32_to_gray16_b}, + {PIX_FMT_ARGB32, PIX_FMT_AYUV4444, argb32_to_ayuv4444}, + + {PIX_FMT_RGB555, PIX_FMT_RGB24, rgb555_to_rgb24}, + {PIX_FMT_RGB555, PIX_FMT_RGB32, rgb555_to_rgba32}, + {PIX_FMT_RGB555, PIX_FMT_RGBA32, rgb555_to_rgba32}, + {PIX_FMT_RGB555, PIX_FMT_YUV420P, rgb555_to_yuv420p}, + {PIX_FMT_RGB555, PIX_FMT_YUVA420P, rgb555_to_yuva420p}, + {PIX_FMT_RGB555, PIX_FMT_NV12, rgb555_to_nv12}, + {PIX_FMT_RGB555, PIX_FMT_NV21, rgb555_to_nv21}, + {PIX_FMT_RGB555, PIX_FMT_Y800, rgb555_to_y800}, + {PIX_FMT_RGB555, PIX_FMT_Y16, rgb555_to_y16}, + {PIX_FMT_RGB555, PIX_FMT_GRAY8, rgb555_to_gray}, + {PIX_FMT_RGB555, PIX_FMT_GRAY16_L, rgb555_to_gray16_l}, + {PIX_FMT_RGB555, PIX_FMT_GRAY16_B, rgb555_to_gray16_b}, + + {PIX_FMT_RGB565, PIX_FMT_RGB24, rgb565_to_rgb24}, + {PIX_FMT_RGB565, PIX_FMT_YUV420P, rgb565_to_yuv420p}, + {PIX_FMT_RGB565, PIX_FMT_YUVA420P, rgb565_to_yuva420p}, + {PIX_FMT_RGB565, PIX_FMT_NV12, rgb565_to_nv12}, + {PIX_FMT_RGB565, PIX_FMT_NV21, rgb565_to_nv21}, + {PIX_FMT_RGB565, PIX_FMT_Y800, rgb565_to_y800}, + {PIX_FMT_RGB565, PIX_FMT_Y16, rgb565_to_y16}, + {PIX_FMT_RGB565, PIX_FMT_GRAY8, rgb565_to_gray}, + {PIX_FMT_RGB565, PIX_FMT_GRAY16_L, rgb565_to_gray16_l}, + {PIX_FMT_RGB565, PIX_FMT_GRAY16_B, rgb565_to_gray16_b}, + + {PIX_FMT_Y800, PIX_FMT_RGB555, y800_to_rgb555}, + {PIX_FMT_Y800, PIX_FMT_RGB565, y800_to_rgb565}, + {PIX_FMT_Y800, PIX_FMT_BGR24, y800_to_bgr24}, + {PIX_FMT_Y800, PIX_FMT_RGB24, y800_to_rgb24}, + {PIX_FMT_Y800, PIX_FMT_RGB32, y800_to_rgb32}, + {PIX_FMT_Y800, PIX_FMT_BGR32, y800_to_bgr32}, + {PIX_FMT_Y800, PIX_FMT_RGB32, y800_to_xrgb32}, + {PIX_FMT_Y800, PIX_FMT_BGR32, y800_to_bgrx32}, + {PIX_FMT_Y800, PIX_FMT_RGBA32, y800_to_rgba32}, + {PIX_FMT_Y800, PIX_FMT_BGRA32, y800_to_bgra32}, + {PIX_FMT_Y800, PIX_FMT_ARGB32, y800_to_argb32}, + {PIX_FMT_Y800, PIX_FMT_ABGR32, y800_to_abgr32}, + {PIX_FMT_Y800, PIX_FMT_Y16, y800_to_y16}, + + {PIX_FMT_Y16, PIX_FMT_RGB555, y16_to_rgb555}, + {PIX_FMT_Y16, PIX_FMT_RGB565, y16_to_rgb565}, + {PIX_FMT_Y16, PIX_FMT_BGR24, y16_to_bgr24}, + {PIX_FMT_Y16, PIX_FMT_RGB24, y16_to_rgb24}, + {PIX_FMT_Y16, PIX_FMT_RGB32, y16_to_rgb32}, + {PIX_FMT_Y16, PIX_FMT_BGR32, y16_to_bgr32}, + {PIX_FMT_Y16, PIX_FMT_RGB32, y16_to_xrgb32}, + {PIX_FMT_Y16, PIX_FMT_BGR32, y16_to_bgrx32}, + {PIX_FMT_Y16, PIX_FMT_RGBA32, y16_to_rgba32}, + {PIX_FMT_Y16, PIX_FMT_BGRA32, y16_to_bgra32}, + {PIX_FMT_Y16, PIX_FMT_ARGB32, y16_to_argb32}, + {PIX_FMT_Y16, PIX_FMT_ABGR32, y16_to_abgr32}, + {PIX_FMT_Y16, PIX_FMT_Y800, y16_to_y800}, + + {PIX_FMT_GRAY8, PIX_FMT_RGB555, gray_to_rgb555}, + {PIX_FMT_GRAY8, PIX_FMT_RGB565, gray_to_rgb565}, + {PIX_FMT_GRAY8, PIX_FMT_RGB24, gray_to_rgb24}, + {PIX_FMT_GRAY8, PIX_FMT_BGR24, gray_to_bgr24}, + {PIX_FMT_GRAY8, PIX_FMT_RGB32, gray_to_rgb32}, + {PIX_FMT_GRAY8, PIX_FMT_BGR32, gray_to_bgr32}, + {PIX_FMT_GRAY8, PIX_FMT_xRGB32, gray_to_xrgb32}, + {PIX_FMT_GRAY8, PIX_FMT_BGRx32, gray_to_bgrx32}, + {PIX_FMT_GRAY8, PIX_FMT_RGBA32, gray_to_rgba32}, + {PIX_FMT_GRAY8, PIX_FMT_BGRA32, gray_to_bgra32}, + {PIX_FMT_GRAY8, PIX_FMT_ARGB32, gray_to_argb32}, + {PIX_FMT_GRAY8, PIX_FMT_ABGR32, gray_to_abgr32}, + {PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, gray_to_monowhite}, + {PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, gray_to_monoblack}, + {PIX_FMT_GRAY8, PIX_FMT_GRAY16_L, gray_to_gray16_l}, + {PIX_FMT_GRAY8, PIX_FMT_GRAY16_B, gray_to_gray16_b}, + + {PIX_FMT_MONOWHITE, PIX_FMT_GRAY8, monowhite_to_gray}, + + {PIX_FMT_MONOBLACK, PIX_FMT_GRAY8, monoblack_to_gray}, + + {PIX_FMT_GRAY16_L, PIX_FMT_GRAY8, gray16_l_to_gray}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB555, gray16_l_to_rgb555}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB565, gray16_l_to_rgb565}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGR24, gray16_l_to_bgr24}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB24, gray16_l_to_rgb24}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGR32, gray16_l_to_bgr32}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB32, gray16_l_to_rgb32}, + {PIX_FMT_GRAY16_L, PIX_FMT_xRGB32, gray16_l_to_xrgb32}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGRx32, gray16_l_to_bgrx32}, + {PIX_FMT_GRAY16_L, PIX_FMT_ABGR32, gray16_l_to_abgr32}, + {PIX_FMT_GRAY16_L, PIX_FMT_ARGB32, gray16_l_to_argb32}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGRA32, gray16_l_to_bgra32}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGBA32, gray16_l_to_rgba32}, + {PIX_FMT_GRAY16_L, PIX_FMT_GRAY16_B, gray16_b_to_gray16_l}, + + {PIX_FMT_GRAY16_B, PIX_FMT_GRAY8, gray16_b_to_gray}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB555, gray16_b_to_rgb555}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB565, gray16_b_to_rgb565}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGR24, gray16_b_to_bgr24}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB24, gray16_b_to_rgb24}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGR32, gray16_b_to_bgr32}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB32, gray16_b_to_rgb32}, + {PIX_FMT_GRAY16_B, PIX_FMT_xRGB32, gray16_b_to_xrgb32}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGRx32, gray16_b_to_bgrx32}, + {PIX_FMT_GRAY16_B, PIX_FMT_ABGR32, gray16_b_to_abgr32}, + {PIX_FMT_GRAY16_B, PIX_FMT_ARGB32, gray16_b_to_argb32}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGRA32, gray16_b_to_bgra32}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGBA32, gray16_b_to_rgba32}, + {PIX_FMT_GRAY16_B, PIX_FMT_GRAY16_L, gray16_b_to_gray16_l}, + + {PIX_FMT_PAL8, PIX_FMT_RGB555, pal8_to_rgb555}, + {PIX_FMT_PAL8, PIX_FMT_RGB565, pal8_to_rgb565}, + {PIX_FMT_PAL8, PIX_FMT_BGR24, pal8_to_bgr24}, + {PIX_FMT_PAL8, PIX_FMT_RGB24, pal8_to_rgb24}, + {PIX_FMT_PAL8, PIX_FMT_RGB32, pal8_to_rgb32}, + {PIX_FMT_PAL8, PIX_FMT_BGR32, pal8_to_bgr32}, + {PIX_FMT_PAL8, PIX_FMT_xRGB32, pal8_to_xrgb32}, + {PIX_FMT_PAL8, PIX_FMT_BGRx32, pal8_to_bgrx32}, + {PIX_FMT_PAL8, PIX_FMT_RGBA32, pal8_to_rgba32}, + {PIX_FMT_PAL8, PIX_FMT_BGRA32, pal8_to_bgra32}, + {PIX_FMT_PAL8, PIX_FMT_ARGB32, pal8_to_argb32}, + {PIX_FMT_PAL8, PIX_FMT_ABGR32, pal8_to_abgr32}, + + {PIX_FMT_UYVY411, PIX_FMT_YUV411P, uyvy411_to_yuv411p}, + {PIX_FMT_YUV411P, PIX_FMT_UYVY411, yuv411p_to_uyvy411}, + + {PIX_FMT_V308, PIX_FMT_RGB24, v308_to_rgb24}, + + {PIX_FMT_AYUV4444, PIX_FMT_RGBA32, ayuv4444_to_rgba32}, + {PIX_FMT_AYUV4444, PIX_FMT_ARGB32, ayuv4444_to_argb32}, + {PIX_FMT_AYUV4444, PIX_FMT_BGRA32, ayuv4444_to_bgra32}, + {PIX_FMT_AYUV4444, PIX_FMT_ABGR32, ayuv4444_to_abgr32}, + {PIX_FMT_AYUV4444, PIX_FMT_RGB24, ayuv4444_to_rgb24}, + {PIX_FMT_AYUV4444, PIX_FMT_YUVA420P, ayuv4444_to_yuva420p}, + + {PIX_FMT_YUVA420P, PIX_FMT_YUV420P, yuva420p_to_yuv420p}, + {PIX_FMT_YUVA420P, PIX_FMT_YUV422, yuva420p_to_yuv422}, + {PIX_FMT_YUVA420P, PIX_FMT_AYUV4444, yuva420p_to_ayuv4444}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB555, yuva420p_to_rgb555}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB565, yuva420p_to_rgb565}, + {PIX_FMT_YUVA420P, PIX_FMT_BGR24, yuva420p_to_bgr24}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB24, yuva420p_to_rgb24}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB32, yuva420p_to_rgb32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGR32, yuva420p_to_bgr32}, + {PIX_FMT_YUVA420P, PIX_FMT_xRGB32, yuva420p_to_xrgb32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGRx32, yuva420p_to_bgrx32}, + {PIX_FMT_YUVA420P, PIX_FMT_RGBA32, yuva420p_to_rgba32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGRA32, yuva420p_to_bgra32}, + {PIX_FMT_YUVA420P, PIX_FMT_ARGB32, yuva420p_to_argb32}, + {PIX_FMT_YUVA420P, PIX_FMT_ABGR32, yuva420p_to_abgr32}, +}; + +static ConvertEntry * +get_convert_table_entry (int src_pix_fmt, int dst_pix_fmt) +{ + int i; + + for (i = 0; i < sizeof (convert_table) / sizeof (convert_table[0]); i++) { + if (convert_table[i].src == src_pix_fmt && + convert_table[i].dest == dst_pix_fmt) { + return convert_table + i; + } + } + + return NULL; +} + +static int +avpicture_alloc (AVPicture * picture, int pix_fmt, int width, int height, + int interlaced) +{ + unsigned int size; + void *ptr; + + size = avpicture_get_size (pix_fmt, width, height); + ptr = av_malloc (size); + if (!ptr) + goto fail; + gst_ffmpegcsp_avpicture_fill (picture, ptr, pix_fmt, width, height, + interlaced); + return 0; +fail: + memset (picture, 0, sizeof (AVPicture)); + return -1; +} + +static void +avpicture_free (AVPicture * picture) +{ + av_free (picture->data[0]); +} + +/* return true if yuv planar */ +static inline int +is_yuv_planar (PixFmtInfo * ps) +{ + return (ps->color_type == FF_COLOR_YUV || + ps->color_type == FF_COLOR_YUV_JPEG) && ps->pixel_type == FF_PIXEL_PLANAR; +} + +/* XXX: always use linesize. Return -1 if not supported */ +int +img_convert (AVPicture * dst, int dst_pix_fmt, + const AVPicture * src, int src_pix_fmt, int src_width, int src_height) +{ + static int inited; + int i, ret, dst_width, dst_height, int_pix_fmt; + PixFmtInfo *src_pix, *dst_pix; + ConvertEntry *ce; + AVPicture tmp1, *tmp = &tmp1; + + if (G_UNLIKELY (src_width <= 0 || src_height <= 0)) + return 0; + + if (G_UNLIKELY (!inited)) { + inited = 1; + img_convert_init (); + } + + dst_width = src_width; + dst_height = src_height; + + dst_pix = get_pix_fmt_info (dst_pix_fmt); + src_pix = get_pix_fmt_info (src_pix_fmt); + if (G_UNLIKELY (src_pix_fmt == dst_pix_fmt)) { + /* no conversion needed: just copy */ + img_copy (dst, src, dst_pix_fmt, dst_width, dst_height); + return 0; + } + + ce = get_convert_table_entry (src_pix_fmt, dst_pix_fmt); + if (ce && ce->convert) { + /* specific conversion routine */ + ce->convert (dst, src, dst_width, dst_height); + return 0; + } + + /* gray to YUV */ + if (is_yuv_planar (dst_pix) && dst_pix_fmt != PIX_FMT_Y16 + && src_pix_fmt == PIX_FMT_GRAY8) { + int w, h, y; + uint8_t *d; + + if (dst_pix->color_type == FF_COLOR_YUV_JPEG) { + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], dst_width, dst_height); + } else { + img_apply_table (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], + dst_width, dst_height, y_jpeg_to_ccir); + } + /* fill U and V with 128 */ + w = dst_width; + h = dst_height; + w >>= dst_pix->x_chroma_shift; + h >>= dst_pix->y_chroma_shift; + for (i = 1; i <= 2; i++) { + d = dst->data[i]; + if (!d) + continue; + for (y = 0; y < h; y++) { + memset (d, 128, w); + d += dst->linesize[i]; + } + } + return 0; + } + + /* YUV to gray */ + if (is_yuv_planar (src_pix) && src_pix_fmt != PIX_FMT_Y16 + && dst_pix_fmt == PIX_FMT_GRAY8) { + if (src_pix->color_type == FF_COLOR_YUV_JPEG) { + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], dst_width, dst_height); + } else { + img_apply_table (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], + dst_width, dst_height, y_ccir_to_jpeg); + } + return 0; + } + + /* YUV to YUV planar */ + if (is_yuv_planar (dst_pix) && is_yuv_planar (src_pix) && + dst_pix->depth == src_pix->depth) { + int x_shift, y_shift, xy_shift; + void (*resize_func) (uint8_t * dst, int dst_wrap, int dst_width, + int dst_height, const uint8_t * src, int src_wrap, int src_width, + int src_height); + + x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift); + y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift); + xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf); + + /* there must be filters for conversion at least from and to + YUV444 format */ + switch (xy_shift) { + case 0x00: + resize_func = img_copy_plane_resize; + break; + case 0x10: + resize_func = shrink21; + break; + case 0x20: + resize_func = shrink41; + break; + case 0x01: + resize_func = shrink12; + break; + case 0x11: + resize_func = shrink22; + break; + case 0x22: + resize_func = shrink44; + break; + case 0xf0: + resize_func = grow21; + break; + case 0xe0: + resize_func = grow41; + break; + case 0xff: + resize_func = grow22; + break; + case 0xee: + resize_func = grow44; + break; + case 0xf1: + resize_func = conv411; + break; + default: + /* currently not handled */ + goto no_chroma_filter; + } + + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], dst_width, dst_height); + +#define GEN_MASK(x) ((1<<(x))-1) +#define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x)) + + for (i = 1; i <= 2; i++) { + gint w, h; + gint s_w, s_h; + + w = DIV_ROUND_UP_X (dst_width, dst_pix->x_chroma_shift); + h = DIV_ROUND_UP_X (dst_height, dst_pix->y_chroma_shift); + + s_w = DIV_ROUND_UP_X (src_width, src_pix->x_chroma_shift); + s_h = DIV_ROUND_UP_X (src_height, src_pix->y_chroma_shift); + + if (src->data[i] != NULL && dst->data[i] != NULL) { + resize_func (dst->data[i], dst->linesize[i], w, h, + src->data[i], src->linesize[i], s_w, s_h); + } else if (dst->data[i] != NULL) { + memset (dst->data[i], 128, dst->linesize[i] * h); + } + } + /* if yuv color space conversion is needed, we do it here on + the destination image */ + if (dst_pix->color_type != src_pix->color_type) { + const uint8_t *y_table, *c_table; + + if (dst_pix->color_type == FF_COLOR_YUV) { + y_table = y_jpeg_to_ccir; + c_table = c_jpeg_to_ccir; + } else { + y_table = y_ccir_to_jpeg; + c_table = c_ccir_to_jpeg; + } + img_apply_table (dst->data[0], dst->linesize[0], + dst->data[0], dst->linesize[0], dst_width, dst_height, y_table); + + for (i = 1; i <= 2; i++) + img_apply_table (dst->data[i], dst->linesize[i], + dst->data[i], dst->linesize[i], + dst_width >> dst_pix->x_chroma_shift, + dst_height >> dst_pix->y_chroma_shift, c_table); + } + return 0; + } +no_chroma_filter: + GST_CAT_INFO (ffmpegcolorspace_performance, + "no direct path to convert colorspace from %s -> %s", src_pix->name, + dst_pix->name); + + /* try to use an intermediate format */ + if (src_pix_fmt == PIX_FMT_YUV422 || dst_pix_fmt == PIX_FMT_YUV422) { + /* specific case: convert to YUV422P first */ + int_pix_fmt = PIX_FMT_YUV422P; + } else if (src_pix_fmt == PIX_FMT_UYVY422 || dst_pix_fmt == PIX_FMT_UYVY422 || + src_pix_fmt == PIX_FMT_YVYU422 || dst_pix_fmt == PIX_FMT_YVYU422) { + /* specific case: convert to YUV422P first */ + int_pix_fmt = PIX_FMT_YUV422P; + } else if (src_pix_fmt == PIX_FMT_UYVY411 || dst_pix_fmt == PIX_FMT_UYVY411) { + /* specific case: convert to YUV411P first */ + int_pix_fmt = PIX_FMT_YUV411P; + } else if ((src_pix->color_type == FF_COLOR_GRAY && + src_pix_fmt != PIX_FMT_GRAY8) || + (dst_pix->color_type == FF_COLOR_GRAY && dst_pix_fmt != PIX_FMT_GRAY8)) { + /* gray8 is the normalized format */ + int_pix_fmt = PIX_FMT_GRAY8; + } else if (src_pix_fmt == PIX_FMT_Y16 || dst_pix_fmt == PIX_FMT_Y16) { + /* y800 is the normalized format */ + int_pix_fmt = PIX_FMT_Y800; + } else if ((is_yuv_planar (src_pix) && + src_pix_fmt != PIX_FMT_YUV444P && src_pix_fmt != PIX_FMT_YUVJ444P)) { + /* yuv444 is the normalized format */ + if (src_pix->color_type == FF_COLOR_YUV_JPEG) + int_pix_fmt = PIX_FMT_YUVJ444P; + else + int_pix_fmt = PIX_FMT_YUV444P; + } else if ((is_yuv_planar (dst_pix) && + dst_pix_fmt != PIX_FMT_YUV444P && dst_pix_fmt != PIX_FMT_YUVJ444P)) { + /* yuv444 is the normalized format */ + if (dst_pix->color_type == FF_COLOR_YUV_JPEG) + int_pix_fmt = PIX_FMT_YUVJ444P; + else + int_pix_fmt = PIX_FMT_YUV444P; + } else { + /* the two formats are rgb or gray8 or yuv[j]444p */ + if (src_pix->is_alpha && dst_pix->is_alpha) + int_pix_fmt = PIX_FMT_RGBA32; + else + int_pix_fmt = PIX_FMT_RGB24; + } + if (avpicture_alloc (tmp, int_pix_fmt, dst_width, dst_height, + dst->interlaced) < 0) + return -1; + ret = -1; + if (img_convert (tmp, int_pix_fmt, + src, src_pix_fmt, src_width, src_height) < 0) + goto fail1; + + if (img_convert (dst, dst_pix_fmt, + tmp, int_pix_fmt, dst_width, dst_height) < 0) + goto fail1; + ret = 0; +fail1: + avpicture_free (tmp); + return ret; +} + +/* NOTE: we scan all the pixels to have an exact information */ +static int +get_alpha_info_pal8 (const AVPicture * src, int width, int height) +{ + const unsigned char *p; + int src_wrap, ret, x, y; + unsigned int a; + uint32_t *palette = (uint32_t *) src->data[1]; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + ret = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + a = palette[p[0]] >> 24; + if (a == 0x00) { + ret |= FF_ALPHA_TRANSP; + } else if (a != 0xff) { + ret |= FF_ALPHA_SEMI_TRANSP; + } + p++; + } + p += src_wrap; + } + return ret; +} + +/** + * Tell if an image really has transparent alpha values. + * @return ored mask of FF_ALPHA_xxx constants + */ +int +img_get_alpha_info (const AVPicture * src, int pix_fmt, int width, int height) +{ + const PixFmtInfo *pf; + int ret; + + pf = get_pix_fmt_info (pix_fmt); + /* no alpha can be represented in format */ + if (!pf->is_alpha) + return 0; + switch (pix_fmt) { + case PIX_FMT_RGB32: + ret = get_alpha_info_rgb32 (src, width, height); + break; + case PIX_FMT_BGR32: + ret = get_alpha_info_bgr32 (src, width, height); + break; + case PIX_FMT_xRGB32: + ret = get_alpha_info_xrgb32 (src, width, height); + break; + case PIX_FMT_BGRx32: + ret = get_alpha_info_bgrx32 (src, width, height); + break; + case PIX_FMT_RGBA32: + ret = get_alpha_info_rgba32 (src, width, height); + break; + case PIX_FMT_BGRA32: + ret = get_alpha_info_bgra32 (src, width, height); + break; + case PIX_FMT_ARGB32: + ret = get_alpha_info_argb32 (src, width, height); + break; + case PIX_FMT_ABGR32: + ret = get_alpha_info_abgr32 (src, width, height); + break; + case PIX_FMT_RGB555: + ret = get_alpha_info_rgb555 (src, width, height); + break; + case PIX_FMT_PAL8: + ret = get_alpha_info_pal8 (src, width, height); + break; + default: + /* we do not know, so everything is indicated */ + ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP; + break; + } + return ret; +} + +#ifdef HAVE_MMX +#define DEINT_INPLACE_LINE_LUM \ + movd_m2r(lum_m4[0],mm0);\ + movd_m2r(lum_m3[0],mm1);\ + movd_m2r(lum_m2[0],mm2);\ + movd_m2r(lum_m1[0],mm3);\ + movd_m2r(lum[0],mm4);\ + punpcklbw_r2r(mm7,mm0);\ + movd_r2m(mm2,lum_m4[0]);\ + punpcklbw_r2r(mm7,mm1);\ + punpcklbw_r2r(mm7,mm2);\ + punpcklbw_r2r(mm7,mm3);\ + punpcklbw_r2r(mm7,mm4);\ + paddw_r2r(mm3,mm1);\ + psllw_i2r(1,mm2);\ + paddw_r2r(mm4,mm0);\ + psllw_i2r(2,mm1);\ + paddw_r2r(mm6,mm2);\ + paddw_r2r(mm2,mm1);\ + psubusw_r2r(mm0,mm1);\ + psrlw_i2r(3,mm1);\ + packuswb_r2r(mm7,mm1);\ + movd_r2m(mm1,lum_m2[0]); + +#define DEINT_LINE_LUM \ + movd_m2r(lum_m4[0],mm0);\ + movd_m2r(lum_m3[0],mm1);\ + movd_m2r(lum_m2[0],mm2);\ + movd_m2r(lum_m1[0],mm3);\ + movd_m2r(lum[0],mm4);\ + punpcklbw_r2r(mm7,mm0);\ + punpcklbw_r2r(mm7,mm1);\ + punpcklbw_r2r(mm7,mm2);\ + punpcklbw_r2r(mm7,mm3);\ + punpcklbw_r2r(mm7,mm4);\ + paddw_r2r(mm3,mm1);\ + psllw_i2r(1,mm2);\ + paddw_r2r(mm4,mm0);\ + psllw_i2r(2,mm1);\ + paddw_r2r(mm6,mm2);\ + paddw_r2r(mm2,mm1);\ + psubusw_r2r(mm0,mm1);\ + psrlw_i2r(3,mm1);\ + packuswb_r2r(mm7,mm1);\ + movd_r2m(mm1,dst[0]); +#endif + +/* filter parameters: [-1 4 2 4 -1] // 8 */ +#if 0 +static void +deinterlace_line (uint8_t * dst, + const uint8_t * lum_m4, const uint8_t * lum_m3, + const uint8_t * lum_m2, const uint8_t * lum_m1, + const uint8_t * lum, int size) +{ +#ifndef HAVE_MMX + uint8_t *cm = cropTbl + MAX_NEG_CROP; + int sum; + + for (; size > 0; size--) { + sum = -lum_m4[0]; + sum += lum_m3[0] << 2; + sum += lum_m2[0] << 1; + sum += lum_m1[0] << 2; + sum += -lum[0]; + dst[0] = cm[(sum + 4) >> 3]; + lum_m4++; + lum_m3++; + lum_m2++; + lum_m1++; + lum++; + dst++; + } +#else + + { + mmx_t rounder; + + rounder.uw[0] = 4; + rounder.uw[1] = 4; + rounder.uw[2] = 4; + rounder.uw[3] = 4; + pxor_r2r (mm7, mm7); + movq_m2r (rounder, mm6); + } + for (; size > 3; size -= 4) { + DEINT_LINE_LUM lum_m4 += 4; + + lum_m3 += 4; + lum_m2 += 4; + lum_m1 += 4; + lum += 4; + dst += 4; + } +#endif +} + +static void +deinterlace_line_inplace (uint8_t * lum_m4, uint8_t * lum_m3, uint8_t * lum_m2, + uint8_t * lum_m1, uint8_t * lum, int size) +{ +#ifndef HAVE_MMX + uint8_t *cm = cropTbl + MAX_NEG_CROP; + int sum; + + for (; size > 0; size--) { + sum = -lum_m4[0]; + sum += lum_m3[0] << 2; + sum += lum_m2[0] << 1; + lum_m4[0] = lum_m2[0]; + sum += lum_m1[0] << 2; + sum += -lum[0]; + lum_m2[0] = cm[(sum + 4) >> 3]; + lum_m4++; + lum_m3++; + lum_m2++; + lum_m1++; + lum++; + } +#else + + { + mmx_t rounder; + + rounder.uw[0] = 4; + rounder.uw[1] = 4; + rounder.uw[2] = 4; + rounder.uw[3] = 4; + pxor_r2r (mm7, mm7); + movq_m2r (rounder, mm6); + } + for (; size > 3; size -= 4) { + DEINT_INPLACE_LINE_LUM lum_m4 += 4; + + lum_m3 += 4; + lum_m2 += 4; + lum_m1 += 4; + lum += 4; + } +#endif +} +#endif + +/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The + top field is copied as is, but the bottom field is deinterlaced + against the top field. */ +#if 0 +static void +deinterlace_bottom_field (uint8_t * dst, int dst_wrap, + const uint8_t * src1, int src_wrap, int width, int height) +{ + const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2; + int y; + + src_m2 = src1; + src_m1 = src1; + src_0 = &src_m1[src_wrap]; + src_p1 = &src_0[src_wrap]; + src_p2 = &src_p1[src_wrap]; + for (y = 0; y < (height - 2); y += 2) { + memcpy (dst, src_m1, width); + dst += dst_wrap; + deinterlace_line (dst, src_m2, src_m1, src_0, src_p1, src_p2, width); + src_m2 = src_0; + src_m1 = src_p1; + src_0 = src_p2; + src_p1 += 2 * src_wrap; + src_p2 += 2 * src_wrap; + dst += dst_wrap; + } + memcpy (dst, src_m1, width); + dst += dst_wrap; + /* do last line */ + deinterlace_line (dst, src_m2, src_m1, src_0, src_0, src_0, width); +} + +static void +deinterlace_bottom_field_inplace (uint8_t * src1, int src_wrap, + int width, int height) +{ + uint8_t *src_m1, *src_0, *src_p1, *src_p2; + int y; + uint8_t *buf; + + buf = (uint8_t *) av_malloc (width); + + src_m1 = src1; + memcpy (buf, src_m1, width); + src_0 = &src_m1[src_wrap]; + src_p1 = &src_0[src_wrap]; + src_p2 = &src_p1[src_wrap]; + for (y = 0; y < (height - 2); y += 2) { + deinterlace_line_inplace (buf, src_m1, src_0, src_p1, src_p2, width); + src_m1 = src_p1; + src_0 = src_p2; + src_p1 += 2 * src_wrap; + src_p2 += 2 * src_wrap; + } + /* do last line */ + deinterlace_line_inplace (buf, src_m1, src_0, src_0, src_0, width); + av_free (buf); +} +#endif + +/* deinterlace - if not supported return -1 */ +#if 0 +static int +avpicture_deinterlace (AVPicture * dst, const AVPicture * src, + int pix_fmt, int width, int height) +{ + int i; + + if (pix_fmt != PIX_FMT_YUV420P && + pix_fmt != PIX_FMT_YUV422P && + pix_fmt != PIX_FMT_YUV444P && pix_fmt != PIX_FMT_YUV411P) + return -1; + if ((width & 3) != 0 || (height & 3) != 0) + return -1; + + for (i = 0; i < 3; i++) { + if (i == 1) { + switch (pix_fmt) { + case PIX_FMT_YUV420P: + width >>= 1; + height >>= 1; + break; + case PIX_FMT_YUV422P: + width >>= 1; + break; + case PIX_FMT_YUV411P: + width >>= 2; + break; + default: + break; + } + } + if (src == dst) { + deinterlace_bottom_field_inplace (dst->data[i], dst->linesize[i], + width, height); + } else { + deinterlace_bottom_field (dst->data[i], dst->linesize[i], + src->data[i], src->linesize[i], width, height); + } + } +#ifdef HAVE_MMX + emms (); +#endif + return 0; +} +#endif + +#undef FIX