1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
/*
* yuv2rgb.c, Software YUV <-> RGB coverter
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include "common/math.h"
#include "csconvert.h"
#include "yuv2rgb.h"
#include "gen_conv.h"
#include "zmisc.h"
#include "libtv/cpu.h"
#include "globals.h"
#define MODE_RGB 0x1
#define MODE_BGR 0x2
/* Won't run on x86-64. */
#if defined (HAVE_X86) && defined (CAN_COMPILE_SSE)
typedef void
packed2planar_fn (uint8_t *py,
uint8_t *pu,
uint8_t *pv,
const uint8_t *image,
int h_size,
int v_size,
unsigned int y_stride,
unsigned int uv_stride,
unsigned int rgb_stride);
typedef void
packed2packed_fn (uint8_t *dst,
const uint8_t *src,
int h_size,
int v_size,
unsigned int dest_stride,
unsigned int src_stride);
static void *
rgb_to_yuv420_function (tv_pixfmt pixfmt)
{
if (cpu_features & CPU_FEATURE_MMX)
switch (pixfmt)
{
case TV_PIXFMT_RGBA16_LE: return mmx_rgb5551_yuv420;
case TV_PIXFMT_BGRA16_LE: return mmx_bgr5551_yuv420;
case TV_PIXFMT_RGB16_LE: return mmx_rgb565_yuv420;
case TV_PIXFMT_BGR16_LE: return mmx_bgr565_yuv420;
case TV_PIXFMT_RGB24_LE: return mmx_rgb24_yuv420;
case TV_PIXFMT_BGR24_LE: return mmx_bgr24_yuv420;
case TV_PIXFMT_RGBA32_LE: return mmx_rgb32_yuv420;
case TV_PIXFMT_BGRA32_LE: return mmx_bgr32_yuv420;
default: break;
}
return NULL;
}
static void *
rgb_to_yuyv_function (tv_pixfmt pixfmt)
{
if (cpu_features & CPU_FEATURE_MMX)
switch (pixfmt)
{
case TV_PIXFMT_RGBA16_LE: return mmx_rgb5551_yuyv;
case TV_PIXFMT_BGRA16_LE: return mmx_bgr5551_yuyv;
case TV_PIXFMT_RGB16_LE: return mmx_rgb565_yuyv;
case TV_PIXFMT_BGR16_LE: return mmx_bgr565_yuyv;
case TV_PIXFMT_RGB24_LE: return mmx_rgb24_yuyv;
case TV_PIXFMT_BGR24_LE: return mmx_bgr24_yuyv;
case TV_PIXFMT_RGBA32_LE: return mmx_rgb32_yuyv;
case TV_PIXFMT_BGRA32_LE: return mmx_bgr32_yuyv;
default: break;
}
return NULL;
}
static void
packed2planar_proxy (void * dst_image,
const tv_image_format *dst_format,
const void * src_image,
const tv_image_format *src_format,
const void * user_data)
{
packed2planar_fn *f = user_data;
f ((uint8_t *) dst_image + dst_format->offset[0],
(uint8_t *) dst_image + dst_format->offset[1],
(uint8_t *) dst_image + dst_format->offset[2],
(const uint8_t *) src_image + src_format->offset[0],
MIN (dst_format->width, src_format->width),
MIN (dst_format->height, src_format->height),
dst_format->bytes_per_line[0],
dst_format->bytes_per_line[1],
src_format->bytes_per_line[0]);
}
static void
packed2packed_proxy (void * dst_image,
const tv_image_format *dst_format,
const void * src_image,
const tv_image_format *src_format,
const void * user_data)
{
packed2packed_fn *f = user_data;
f ((uint8_t *) dst_image + dst_format->offset[0],
(const uint8_t *) src_image + src_format->offset[0],
MIN (dst_format->width, src_format->width),
MIN (dst_format->height, src_format->height),
dst_format->bytes_per_line[0],
src_format->bytes_per_line[0]);
}
static void
mmx_register_converters (void)
{
static tv_pixfmt pixfmts [] = {
TV_PIXFMT_RGBA16_LE,
TV_PIXFMT_BGRA16_LE,
TV_PIXFMT_RGB16_LE,
TV_PIXFMT_BGR16_LE,
TV_PIXFMT_RGB24_LE,
TV_PIXFMT_BGR24_LE,
TV_PIXFMT_RGBA32_LE,
TV_PIXFMT_BGRA32_LE,
};
unsigned int i;
void *p;
for (i = 0; i < N_ELEMENTS (pixfmts); ++i)
{
if ((p = rgb_to_yuv420_function (pixfmts[i])))
{
register_converter ("-yuv420",
pixfmts[i], TV_PIXFMT_YUV420,
packed2planar_proxy, p);
register_converter ("-yvu420",
pixfmts[i], TV_PIXFMT_YVU420,
packed2planar_proxy, p);
}
if ((p = rgb_to_yuyv_function (pixfmts[i])))
register_converter ("-yuyv",
pixfmts[i], TV_PIXFMT_YUYV,
packed2packed_proxy, p);
}
}
#else /* !(HAVE_X86 && CAN_COMPILE_SSE) */
static void
mmx_register_converters (void)
{
}
#endif /* !(HAVE_X86 && CAN_COMPILE_SSE) */
void startup_yuv2rgb (void)
{
mmx_register_converters ();
}
void shutdown_yuv2rgb (void)
{
}
|