You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
8.9 KiB
291 lines
8.9 KiB
4 years ago
|
/*
|
||
|
* img_yuv_packed.c - YUV packed image format conversion routines
|
||
|
* Written by Andrew Church <achurch@achurch.org>
|
||
|
*
|
||
|
* This file is part of transcode, a video stream processing tool.
|
||
|
* transcode is free software, distributable under the terms of the GNU
|
||
|
* General Public License (version 2 or later). See the file COPYING
|
||
|
* for details.
|
||
|
*/
|
||
|
|
||
|
#include "ac.h"
|
||
|
#include "imgconvert.h"
|
||
|
#include "img_internal.h"
|
||
|
|
||
|
/*************************************************************************/
|
||
|
/*************************************************************************/
|
||
|
|
||
|
/* Standard C implementations */
|
||
|
|
||
|
/*************************************************************************/
|
||
|
|
||
|
/* Identity transformation, works when src==dest */
|
||
|
static int yuv16_copy(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ac_memcpy(dest[0], src[0], width*height*2);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* Used for YUY2->UYVY and UYVY->YUY2, works when src==dest */
|
||
|
static int yuv16_swap16(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
uint16_t *srcp = (uint16_t *)src[0];
|
||
|
uint16_t *destp = (uint16_t *)dest[0];
|
||
|
int i;
|
||
|
for (i = 0; i < width*height; i++)
|
||
|
destp[i] = srcp[i]>>8 | srcp[i]<<8;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* Used for YUY2->YVYU and YVYU->YUY2, works when src==dest */
|
||
|
static int yuv16_swapuv(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
int i;
|
||
|
for (i = 0; i < width*height/2; i++) {
|
||
|
uint8_t tmp = src[0][i*4+1];
|
||
|
dest[0][i*4 ] = src[0][i*4 ];
|
||
|
dest[0][i*4+1] = src[0][i*4+3];
|
||
|
dest[0][i*4+2] = src[0][i*4+2];
|
||
|
dest[0][i*4+3] = tmp;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************/
|
||
|
|
||
|
static int uyvy_yvyu(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
int i;
|
||
|
for (i = 0; i < width*height/2; i++) {
|
||
|
dest[0][i*4 ] = src[0][i*4+1];
|
||
|
dest[0][i*4+1] = src[0][i*4+2];
|
||
|
dest[0][i*4+2] = src[0][i*4+3];
|
||
|
dest[0][i*4+3] = src[0][i*4 ];
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int yvyu_uyvy(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
int i;
|
||
|
for (i = 0; i < width*height/2; i++) {
|
||
|
dest[0][i*4 ] = src[0][i*4+3];
|
||
|
dest[0][i*4+1] = src[0][i*4 ];
|
||
|
dest[0][i*4+2] = src[0][i*4+1];
|
||
|
dest[0][i*4+3] = src[0][i*4+2];
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************/
|
||
|
/*************************************************************************/
|
||
|
|
||
|
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
||
|
|
||
|
/* Common macros/data for x86 code */
|
||
|
#define DEFINE_MASK_DATA
|
||
|
#include "img_x86_common.h"
|
||
|
|
||
|
/*************************************************************************/
|
||
|
|
||
|
/* Basic assembly routines */
|
||
|
|
||
|
static int yuv16_swap16_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_SWAP16_2_X86(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int yuv16_swapuv_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_SWAP32_13_X86(width*height/2);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int uyvy_yvyu_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_ROR32_X86(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int yvyu_uyvy_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_ROL32_X86(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************/
|
||
|
|
||
|
/* MMX routines */
|
||
|
|
||
|
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */
|
||
|
|
||
|
static int yuv16_swap16_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_SWAP16_2_MMX(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int yuv16_swapuv_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_SWAP32_13_MMX(width*height/2);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int uyvy_yvyu_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_ROR32_MMX(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int yvyu_uyvy_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_ROL32_MMX(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
#endif /* HAVE_ASM_MMX && ARCH_X86 */
|
||
|
|
||
|
/*************************************************************************/
|
||
|
|
||
|
/* SSE2 routines */
|
||
|
|
||
|
#if defined(HAVE_ASM_SSE2)
|
||
|
|
||
|
static int yuv16_swap16_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_SWAP16_2_SSE2(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int yuv16_swapuv_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_SWAP32_13_SSE2(width*height/2);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int uyvy_yvyu_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_ROR32_SSE2(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int yvyu_uyvy_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||
|
{
|
||
|
ASM_ROL32_SSE2(width*height/2);
|
||
|
if (width*height % 1)
|
||
|
((uint16_t *)(dest[0]))[width*height-1] =
|
||
|
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
#endif /* HAVE_ASM_SSE2 */
|
||
|
|
||
|
/*************************************************************************/
|
||
|
|
||
|
#endif /* ARCH_X86 || ARCH_X86_64 */
|
||
|
|
||
|
/*************************************************************************/
|
||
|
/*************************************************************************/
|
||
|
|
||
|
/* Initialization */
|
||
|
|
||
|
int ac_imgconvert_init_yuv_packed(int accel)
|
||
|
{
|
||
|
if (!register_conversion(IMG_YUY2, IMG_YUY2, yuv16_copy)
|
||
|
|| !register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16)
|
||
|
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv)
|
||
|
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_UYVY, yuv16_copy)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu)
|
||
|
|
||
|
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_YVYU, yuv16_copy)
|
||
|
) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
||
|
if (accel & (AC_IA32ASM | AC_AMD64ASM)) {
|
||
|
if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_x86)
|
||
|
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_x86)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_x86)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_x86)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_x86)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_x86)
|
||
|
) {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86)
|
||
|
if (accel & AC_MMX) {
|
||
|
if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_mmx)
|
||
|
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_mmx)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_mmx)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_mmx)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_mmx)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_mmx)
|
||
|
) {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if defined(HAVE_ASM_SSE2)
|
||
|
if (accel & AC_SSE2) {
|
||
|
if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_sse2)
|
||
|
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_sse2)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_sse2)
|
||
|
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_sse2)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_sse2)
|
||
|
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_sse2)
|
||
|
) {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif /* ARCH_X86 || ARCH_X86_64 */
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************/
|
||
|
|
||
|
/*
|
||
|
* Local variables:
|
||
|
* c-file-style: "stroustrup"
|
||
|
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||
|
* indent-tabs-mode: nil
|
||
|
* End:
|
||
|
*
|
||
|
* vim: expandtab shiftwidth=4:
|
||
|
*/
|