share some more convs between sdl3, to_lavc, testc

1. to SDL3 nv12 (not supported before)

2. to_lavc - use rgba_to_bgra - the vc_copyline version was not keeping alpha
(if ever used - this may cause regressions, unfortunately, if alpha is
assumed to be 100%, because the orig version set it always)

3. uyvy_to_i420 use by testcard and to_lavc

uyvy_to_i420: do not write out of bounds

If width % 2 = 1, 1 extra luma on first line of pair will override the
first luma on the second.
This commit is contained in:
Martin Pulec
2025-02-14 12:36:58 +01:00
parent 6bdc223e15
commit fa764db2d6
5 changed files with 258 additions and 257 deletions

View File

@@ -79,51 +79,8 @@
static void uyvy_to_yuv420p(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height)
{
int y;
for (y = 0; y < height - 1; y += 2) {
/* every even row */
const unsigned char *src = in_data + y * (((width + 1) & ~1) * 2);
/* every odd row */
const unsigned char *src2 = in_data + (y + 1) * (((width + 1) & ~1) * 2);
unsigned char *dst_y = out_frame->data[0] + out_frame->linesize[0] * y;
unsigned char *dst_y2 = out_frame->data[0] + out_frame->linesize[0] * (y + 1);
unsigned char *dst_cb = out_frame->data[1] + out_frame->linesize[1] * (y / 2);
unsigned char *dst_cr = out_frame->data[2] + out_frame->linesize[2] * (y / 2);
int x;
OPTIMIZED_FOR (x = 0; x < width - 1; x += 2) {
*dst_cb++ = (*src++ + *src2++) / 2;
*dst_y++ = *src++;
*dst_y2++ = *src2++;
*dst_cr++ = (*src++ + *src2++) / 2;
*dst_y++ = *src++;
*dst_y2++ = *src2++;
}
if (x < width) {
*dst_cb++ = (*src++ + *src2++) / 2;
*dst_y++ = *src++;
*dst_y2++ = *src2++;
*dst_cr++ = (*src++ + *src2++) / 2;
}
}
if (y < height) {
const unsigned char *src = in_data + y * (((width + 1) & ~1) * 2);
unsigned char *dst_y = out_frame->data[0] + out_frame->linesize[0] * y;
unsigned char *dst_cb = out_frame->data[1] + out_frame->linesize[1] * (y / 2);
unsigned char *dst_cr = out_frame->data[2] + out_frame->linesize[2] * (y / 2);
int x;
OPTIMIZED_FOR (x = 0; x < width - 1; x += 2) {
*dst_cb++ = *src++;
*dst_y++ = *src++;
*dst_cr++ = *src++;
*dst_y++ = *src++;
}
if (x < width) {
*dst_cb++ = *src++;
*dst_y++ = *src++;
*dst_cr++ = *src++;
}
}
uyvy_to_i420(out_frame->data, out_frame->linesize, in_data, width,
height);
}
static void uyvy_to_yuv422p(AVFrame * __restrict out_frame, const unsigned char * __restrict src, int width, int height)
@@ -181,86 +138,10 @@ static void uyvy_to_yuv444p(AVFrame * __restrict out_frame, const unsigned char
}
}
static void uyvy_to_nv12(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height)
static void to_lavc_uyvy_to_nv12(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height)
{
for(int y = 0; y < height; y += 2) {
/* every even row */
const unsigned char *src = in_data + y * (width * 2);
/* every odd row */
const unsigned char *src2 = in_data + (y + 1) * (width * 2);
unsigned char *dst_y = out_frame->data[0] + out_frame->linesize[0] * y;
unsigned char *dst_y2 = out_frame->data[0] + out_frame->linesize[0] * (y + 1);
unsigned char *dst_cbcr = out_frame->data[1] + out_frame->linesize[1] * y / 2;
int x = 0;
#ifdef __SSE3__
__m128i yuv;
__m128i yuv2;
__m128i y1;
__m128i y2;
__m128i y3;
__m128i y4;
__m128i uv;
__m128i uv2;
__m128i uv3;
__m128i uv4;
__m128i ymask = _mm_set1_epi32(0xFF00FF00);
__m128i dsty;
__m128i dsty2;
__m128i dstuv;
for (; x < (width - 15); x += 16){
yuv = _mm_lddqu_si128((__m128i const*)(const void *) src);
yuv2 = _mm_lddqu_si128((__m128i const*)(const void *) src2);
src += 16;
src2 += 16;
y1 = _mm_and_si128(ymask, yuv);
y1 = _mm_bsrli_si128(y1, 1);
y2 = _mm_and_si128(ymask, yuv2);
y2 = _mm_bsrli_si128(y2, 1);
uv = _mm_andnot_si128(ymask, yuv);
uv2 = _mm_andnot_si128(ymask, yuv2);
uv = _mm_avg_epu8(uv, uv2);
yuv = _mm_lddqu_si128((__m128i const*)(const void *) src);
yuv2 = _mm_lddqu_si128((__m128i const*)(const void *) src2);
src += 16;
src2 += 16;
y3 = _mm_and_si128(ymask, yuv);
y3 = _mm_bsrli_si128(y3, 1);
y4 = _mm_and_si128(ymask, yuv2);
y4 = _mm_bsrli_si128(y4, 1);
uv3 = _mm_andnot_si128(ymask, yuv);
uv4 = _mm_andnot_si128(ymask, yuv2);
uv3 = _mm_avg_epu8(uv3, uv4);
dsty = _mm_packus_epi16(y1, y3);
dsty2 = _mm_packus_epi16(y2, y4);
dstuv = _mm_packus_epi16(uv, uv3);
_mm_storeu_si128((__m128i *)(void *) dst_y, dsty);
_mm_storeu_si128((__m128i *)(void *) dst_y2, dsty2);
_mm_storeu_si128((__m128i *)(void *) dst_cbcr, dstuv);
dst_y += 16;
dst_y2 += 16;
dst_cbcr += 16;
}
#endif
OPTIMIZED_FOR (; x < width - 1; x += 2) {
*dst_cbcr++ = (*src++ + *src2++) / 2;
*dst_y++ = *src++;
*dst_y2++ = *src2++;
*dst_cbcr++ = (*src++ + *src2++) / 2;
*dst_y++ = *src++;
*dst_y2++ = *src2++;
}
}
uyvy_to_nv12(out_frame->data, out_frame->linesize, in_data, width,
height);
}
static void v210_to_yuv420p10le(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height)
@@ -547,9 +428,8 @@ to_lavc_v210_to_p010le(AVFrame *__restrict out_frame,
const unsigned char *__restrict in_data, int width,
int height)
{
char *out_data[2] = { (char *) out_frame->data[0], (char *) out_frame->data[1]};
v210_to_p010le(out_data, out_frame->linesize, (const char *) in_data,
width, height);
v210_to_p010le(out_frame->data, out_frame->linesize, in_data, width,
height);
}
static void
@@ -557,9 +437,8 @@ to_lavc_y216_to_p010le(AVFrame *__restrict out_frame,
const unsigned char *__restrict in_data, int width,
int height)
{
char *out_data[2] = { (char *) out_frame->data[0], (char *) out_frame->data[1]};
y216_to_p010le(out_data, out_frame->linesize, (const char *) in_data,
width, height);
y216_to_p010le(out_frame->data, out_frame->linesize, in_data, width,
height);
}
#if P210_PRESENT
@@ -1092,14 +971,13 @@ static void rgba_to_gbrp(AVFrame * __restrict out_frame, const unsigned char * _
rgb_rgba_to_gbrp(out_frame, in_data, width, height, 4);
}
static void rgba_to_bgra(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height)
static void
to_lavc_rgba_to_bgra(AVFrame *__restrict out_frame,
const unsigned char *__restrict in_data, int width,
int height)
{
int linesize = vc_get_linesize(width, RGBA);
for (ptrdiff_t y = 0; y < height; ++y) {
const unsigned char *src = in_data + y * linesize;
unsigned char *dst = out_frame->data[0] + out_frame->linesize[0] * y;
vc_copylineRGBA(dst, src, linesize, 16, 8, 0);
}
rgba_to_bgra(out_frame->data, out_frame->linesize, in_data, width,
height);
}
#if defined __GNUC__
@@ -1311,7 +1189,7 @@ static const struct uv_to_av_conversion *get_uv_to_av_conversions() {
#endif
{ UYVY, AV_PIX_FMT_YUV420P, uyvy_to_yuv420p },
{ UYVY, AV_PIX_FMT_YUVJ420P, uyvy_to_yuv420p },
{ UYVY, AV_PIX_FMT_NV12, uyvy_to_nv12 },
{ UYVY, AV_PIX_FMT_NV12, to_lavc_uyvy_to_nv12 },
{ UYVY, AV_PIX_FMT_YUV444P, uyvy_to_yuv444p },
{ UYVY, AV_PIX_FMT_YUVJ444P, uyvy_to_yuv444p },
{ Y216, AV_PIX_FMT_YUV422P10LE, y216_to_yuv422p10le },
@@ -1321,7 +1199,7 @@ static const struct uv_to_av_conversion *get_uv_to_av_conversions() {
{ RGB, AV_PIX_FMT_GBRP, rgb_to_gbrp },
{ RGB, AV_PIX_FMT_YUV444P, rgb_to_yuv444p },
{ RGBA, AV_PIX_FMT_GBRP, rgba_to_gbrp },
{ RGBA, AV_PIX_FMT_BGRA, rgba_to_bgra },
{ RGBA, AV_PIX_FMT_BGRA, to_lavc_rgba_to_bgra },
{ R10k, AV_PIX_FMT_BGR0, r10k_to_bgr0 },
{ R10k, AV_PIX_FMT_GBRP10LE, r10k_to_gbrp10le },
{ R10k, AV_PIX_FMT_GBRP16LE, r10k_to_gbrp16le },

View File

@@ -64,6 +64,9 @@
#include "utils/macros.h" // to_fourcc, OPTIMEZED_FOR, CLAMP
#include "video_codec.h"
#ifdef __SSE3__
#include "pmmintrin.h"
#endif
#ifdef __SSSE3__
#include "tmmintrin.h"
#endif
@@ -3074,9 +3077,9 @@ decoder_t get_best_decoder_from(codec_t in, const codec_t *out_candidates, codec
* neither input nor output need to be padded
*/
void
v210_to_p010le(char *__restrict *__restrict out_data,
v210_to_p010le(unsigned char *__restrict *__restrict out_data,
const int *__restrict out_linesize,
const char *__restrict in_data, int width, int height)
const unsigned char *__restrict in_data, int width, int height)
{
assert((uintptr_t) in_data % 4 == 0);
assert(out_linesize[0] % 2 == 0);
@@ -3168,9 +3171,9 @@ v210_to_p010le(char *__restrict *__restrict out_data,
}
void
y216_to_p010le(char *__restrict *__restrict out_data,
y216_to_p010le(unsigned char *__restrict *__restrict out_data,
const int *__restrict out_linesize,
const char *__restrict in_data, int width, int height)
const unsigned char *__restrict in_data, int width, int height)
{
const size_t src_linesize = vc_get_linesize(width, Y216);
for (int i = 0; i < height / 2; ++i) {
@@ -3195,4 +3198,153 @@ y216_to_p010le(char *__restrict *__restrict out_data,
}
}
void
uyvy_to_nv12(unsigned char *__restrict *__restrict out_data,
const int *__restrict out_linesize,
const unsigned char *__restrict in_data, int width, int height)
{
for (size_t y = 0; y < (size_t) height; y += 2) {
/* every even row */
const unsigned char *src = in_data + (y * ((size_t) width * 2));
/* every odd row */
const unsigned char *src2 = src + ((size_t) width * 2);
unsigned char *dst_y = out_data[0] + (out_linesize[0] * y);
unsigned char *dst_y2 = dst_y + out_linesize[0];
unsigned char *dst_cbcr =
out_data[1] + (out_linesize[1] * (y / 2));
int x = 0;
#ifdef __SSE3__
__m128i yuv;
__m128i yuv2;
__m128i y1;
__m128i y2;
__m128i y3;
__m128i y4;
__m128i uv;
__m128i uv2;
__m128i uv3;
__m128i uv4;
__m128i ymask = _mm_set1_epi32(0xFF00FF00);
__m128i dsty;
__m128i dsty2;
__m128i dstuv;
for (; x < (width - 15); x += 16){
yuv = _mm_lddqu_si128((__m128i const*)(const void *) src);
yuv2 = _mm_lddqu_si128((__m128i const*)(const void *) src2);
src += 16;
src2 += 16;
y1 = _mm_and_si128(ymask, yuv);
y1 = _mm_bsrli_si128(y1, 1);
y2 = _mm_and_si128(ymask, yuv2);
y2 = _mm_bsrli_si128(y2, 1);
uv = _mm_andnot_si128(ymask, yuv);
uv2 = _mm_andnot_si128(ymask, yuv2);
uv = _mm_avg_epu8(uv, uv2);
yuv = _mm_lddqu_si128((__m128i const*)(const void *) src);
yuv2 = _mm_lddqu_si128((__m128i const*)(const void *) src2);
src += 16;
src2 += 16;
y3 = _mm_and_si128(ymask, yuv);
y3 = _mm_bsrli_si128(y3, 1);
y4 = _mm_and_si128(ymask, yuv2);
y4 = _mm_bsrli_si128(y4, 1);
uv3 = _mm_andnot_si128(ymask, yuv);
uv4 = _mm_andnot_si128(ymask, yuv2);
uv3 = _mm_avg_epu8(uv3, uv4);
dsty = _mm_packus_epi16(y1, y3);
dsty2 = _mm_packus_epi16(y2, y4);
dstuv = _mm_packus_epi16(uv, uv3);
_mm_storeu_si128((__m128i *)(void *) dst_y, dsty);
_mm_storeu_si128((__m128i *)(void *) dst_y2, dsty2);
_mm_storeu_si128((__m128i *)(void *) dst_cbcr, dstuv);
dst_y += 16;
dst_y2 += 16;
dst_cbcr += 16;
}
#endif
OPTIMIZED_FOR (; x < width - 1; x += 2) {
*dst_cbcr++ = (*src++ + *src2++) / 2;
*dst_y++ = *src++;
*dst_y2++ = *src2++;
*dst_cbcr++ = (*src++ + *src2++) / 2;
*dst_y++ = *src++;
*dst_y2++ = *src2++;
}
}
}
void
rgba_to_bgra(unsigned char *__restrict *__restrict out_data,
const int *__restrict out_linesize,
const unsigned char *__restrict in_data, int width, int height)
{
const size_t src_linesize = vc_get_linesize(width, RGBA);
for (size_t i = 0; i < (size_t) height; ++i) {
const uint8_t *in = in_data + (i * src_linesize);
uint8_t *out = out_data[0] + (i * out_linesize[0]);
for (int i = 0; i < width; ++i) {
*out++ = in[2]; // B
*out++ = in[1]; // G
*out++ = in[0]; // R
*out++ = in[3]; // A
in += 4;
}
}
}
/**
* converts UYVY to planar YUV 4:2:0
*
* @sa uyvy_to_i422
*/
void
uyvy_to_i420(unsigned char *__restrict *__restrict out_data,
const int *__restrict out_linesize, const unsigned char *__restrict in_data,
int width, int height)
{
size_t src_linesize = vc_get_linesize(width, UYVY);
for (size_t i = 0; i < (size_t) (height + 1) / 2; ++i) {
const unsigned char *in1 = in_data + (2 * i * src_linesize);
const unsigned char *in2 = in1 + src_linesize;
unsigned char *y1 =
out_data[0] + ((2ULL * i) * out_linesize[0]);
unsigned char *y2 = y1 + out_linesize[0];
unsigned char *u = out_data[1] + (i * out_linesize[1]);
unsigned char *v = out_data[2] + (i * out_linesize[2]);
// handle height % 2 == 1
if (i + 1 == (size_t) height) {
y2 = y1;
in2 = in1;
}
int j = 0;
for (; j < width / 2; ++j) {
*u++ = (*in1++ + *in2++ + 1) / 2;
*y1++ = *in1++;
*y2++ = *in2++;
*v++ = (*in1++ + *in2++ + 1) / 2;
*y1++ = *in1++;
*y2++ = *in2++;
}
if (width % 2 == 1) { // do not overwrite EOL
*u++ = (*in1++ + *in2++ + 1) / 2;
*y1++ = *in1++;
*y2++ = *in2++;
*v++ = (*in1++ + *in2++ + 1) / 2;
}
}
}
/* vim: set expandtab sw=8: */

View File

@@ -106,12 +106,18 @@ decoder_func_t vc_copylineUYVYtoGrayscale;
/// dummy conversion - ptr to it returned if no conversion needed
decoder_func_t vc_memcpy;
void v210_to_p010le(char *__restrict *__restrict out_data,
const int *__restrict out_linesize,
const char *__restrict in_data, int width, int height);
void y216_to_p010le(char *__restrict *__restrict out_data,
const int *__restrict out_linesize,
const char *__restrict in_data, int width, int height);
typedef void
decode_buffer_func_t(unsigned char *__restrict *__restrict out_data,
const int *__restrict out_linesize,
const unsigned char *__restrict in_data, int width,
int height);
decode_buffer_func_t v210_to_p010le;
decode_buffer_func_t y216_to_p010le;
decode_buffer_func_t uyvy_to_nv12;
decode_buffer_func_t rgba_to_bgra;
// other packed->planar convs are histaorically in video_codec.[ch]
decode_buffer_func_t uyvy_to_i420;
#ifdef __cplusplus
}

View File

@@ -71,46 +71,21 @@ void testcard_fillRect(struct testcard_pixmap *s, struct testcard_rect *r, uint3
/**
* @param[in] in buffer in UYVY
* @retval buffer in I420 (must be deallocated by the caller)
* @note
* Caller must deallocate returned buffer
* @retval buffer in I420
*/
static void toI420(unsigned char *out, const unsigned char *input, int width, int height)
static void
toI420(unsigned char *out, const unsigned char *input, int width, int height)
{
const unsigned char *in = (const unsigned char *) input;
int w_ch = (width + 1) / 2;
int h_ch = (height + 1) / 2;
unsigned char *y = out;
unsigned char *u0 = out + width * height;
unsigned char *v0 = out + width * height + w_ch * h_ch;
unsigned char *u1 = u0, *v1 = v0;
for (int i = 0; i < height; i += 1) {
for (int j = 0; j < ((width + 1) & ~1); j += 2) {
// U
if (i % 2 == 0) {
*u0++ = *in++;
} else { // average with every 2nd row
*u1 = (*u1 + *in++) / 2;
u1++;
}
// Y
*y++ = *in++;
// V
if (i % 2 == 0) {
*v0++ = *in++;
} else { // average with every 2nd row
*v1 = (*v1 + *in++) / 2;
v1++;
}
// Y
if (j + 1 == width) {
in++;
} else {
*y++ = *in++;
}
}
}
const size_t y_h = height;
const size_t chr_h = (y_h + 1) / 2;
int out_linesize[3] = { width,
(width + 1) / 2,
(width + 1) / 2 };
unsigned char *out_data[3] = { out,
out + (y_h * out_linesize[0]),
out + (y_h * out_linesize[0]) +
(chr_h * out_linesize[1]) };
uyvy_to_i420(out_data, out_linesize, input, width, height);
}
void testcard_convert_buffer(codec_t in_c, codec_t out_c, unsigned char *out, unsigned const char *in, int width, int height)

View File

@@ -95,22 +95,24 @@ struct video_frame_sdl3_data {
};
static void convert_UYVY_IYUV(const struct video_frame *uv_frame,
char *tex_data, size_t y_pitch);
unsigned char *tex_data, size_t y_pitch);
static void convert_UYVY_NV12(const struct video_frame *uv_frame,
unsigned char *tex_data, size_t y_pitch);
static void convert_R10k_ARGB2101010(const struct video_frame *uv_frame,
char *tex_data, size_t y_pitch);
unsigned char *tex_data, size_t y_pitch);
static void convert_R10k_ABGR2101010(const struct video_frame *uv_frame,
char *tex_data, size_t y_pitch);
unsigned char *tex_data, size_t y_pitch);
static void convert_RGBA_BGRA(const struct video_frame *uv_frame,
char *tex_data, size_t y_pitch);
static void convert_Y216_P010(const struct video_frame *uv_frame, char *tex_data,
size_t y_pitch);
static void convert_v210_P010(const struct video_frame *uv_frame, char *tex_data,
size_t y_pitch);
unsigned char *tex_data, size_t y_pitch);
static void convert_Y216_P010(const struct video_frame *uv_frame,
unsigned char *tex_data, size_t y_pitch);
static void convert_v210_P010(const struct video_frame *uv_frame,
unsigned char *tex_data, size_t y_pitch);
struct fmt_data {
codec_t ug_codec;
enum SDL_PixelFormat sdl_tex_fmt;
void (*convert)(const struct video_frame *uv_frame, char *tex_data,
size_t tex_pitch);
void (*convert)(const struct video_frame *uv_frame,
unsigned char *tex_data, size_t tex_pitch);
};
// order matters relative to fixed ug codec - first usable SDL fmt is used
static const struct fmt_data pf_mapping_template[] = {
@@ -121,6 +123,7 @@ static const struct fmt_data pf_mapping_template[] = {
{ RGBA, SDL_PIXELFORMAT_BGRX32, convert_RGBA_BGRA }, // gles2,ogl,gpu,sw,vk,d3d12
{ UYVY, SDL_PIXELFORMAT_UYVY, NULL }, // mac ogl
{ UYVY, SDL_PIXELFORMAT_IYUV, convert_UYVY_IYUV }, // fallback
{ UYVY, SDL_PIXELFORMAT_NV12, convert_UYVY_NV12 }, // ditto
{ YUYV, SDL_PIXELFORMAT_YUY2, NULL },
{ RGB, SDL_PIXELFORMAT_RGB24, NULL },
{ BGR, SDL_PIXELFORMAT_BGR24, NULL },
@@ -230,7 +233,7 @@ display_frame(struct state_sdl3 *s, struct video_frame *frame)
int pitch = 0;
if (s->cs_data->convert != NULL) {
char *tex_data = NULL;
unsigned char *tex_data = NULL;
SDL_CHECK(SDL_LockTexture(frame_data->texture, NULL,
(void **) &tex_data, &pitch));
s->cs_data->convert(frame, tex_data, pitch);
@@ -1093,8 +1096,8 @@ display_sdl3_getf(void *state)
}
static void
convert_R10k_ARGB2101010(const struct video_frame *uv_frame, char *tex_data,
size_t pitch)
convert_R10k_ARGB2101010(const struct video_frame *uv_frame,
unsigned char *tex_data, size_t pitch)
{
assert(pitch == (size_t) uv_frame->tiles[0].width * 4);
assert((uintptr_t) uv_frame->tiles[0].data % 4 == 0);
@@ -1121,8 +1124,8 @@ convert_R10k_ARGB2101010(const struct video_frame *uv_frame, char *tex_data,
}
static void
convert_R10k_ABGR2101010(const struct video_frame *uv_frame, char *tex_data,
size_t pitch)
convert_R10k_ABGR2101010(const struct video_frame *uv_frame,
unsigned char *tex_data, size_t pitch)
{
const size_t src_linesize = vc_get_linesize(uv_frame->tiles[0].width, R10k);
for (unsigned i = 0; i < uv_frame->tiles[0].height; ++i) {
@@ -1142,58 +1145,45 @@ convert_R10k_ABGR2101010(const struct video_frame *uv_frame, char *tex_data,
}
static void
convert_RGBA_BGRA(const struct video_frame *uv_frame, char *tex_data,
convert_RGBA_BGRA(const struct video_frame *uv_frame, unsigned char *tex_data,
size_t pitch)
{
const size_t src_linesize = vc_get_linesize(uv_frame->tiles[0].width, RGBA);
for (unsigned i = 0; i < uv_frame->tiles[0].height; ++i) {
const uint8_t *in =
(uint8_t *) uv_frame->tiles[0].data + (i * src_linesize);
uint8_t *out = (uint8_t *) tex_data + (i * pitch);
for (unsigned i = 0; i < uv_frame->tiles[0].width ; ++i) {
*out++ = in[2]; // B
*out++ = in[1]; // G
*out++ = in[0]; // R
*out++ = in[3]; // A
in += 4;
}
}
unsigned char *out_data[2] = { tex_data, 0 };
int out_linesize[2] = { (int) pitch, 0 };
rgba_to_bgra(
out_data, out_linesize, (unsigned char *) uv_frame->tiles[0].data,
(int) uv_frame->tiles[0].width, (int) uv_frame->tiles[0].height);
}
static void
convert_UYVY_IYUV(const struct video_frame *uv_frame, char *tex_data,
convert_UYVY_IYUV(const struct video_frame *uv_frame, unsigned char *tex_data,
size_t y_pitch)
{
size_t cr_pitch = (y_pitch + 1) / 2;
char *ubase = tex_data + (y_pitch * uv_frame->tiles[0].height);
char *vbase =
ubase + (cr_pitch * ((uv_frame->tiles[0].height + 1) / 2));
const char *in = uv_frame->tiles[0].data;
for (unsigned i = 0; i < (uv_frame->tiles[0].height + 1) / 2; ++i) {
char *y1 = tex_data + ((2ULL * i) * y_pitch);
char *y2 = y1 + y_pitch;
char *u = ubase + (i * cr_pitch);
char *v = vbase + (i * cr_pitch);
for (unsigned j = 0; j < (uv_frame->tiles[0].width + 1) / 2;
++j) {
*u++ = *in++;
*y1++ = *in++;
*v++ = *in++;
*y1++ = *in++;
}
// last line when height % 2 == 1
if (i * 2 + 1 == uv_frame->tiles[0].height) {
break;
}
// take just lumas from second
for (unsigned j = 0; j < (uv_frame->tiles[0].width + 1) / 2;
++j) {
in++; // drop U
*y2++ = *in++;
in++; // drop V
*y2++ = *in++;
}
}
const size_t y_h = uv_frame->tiles[0].height;
const size_t chr_h = (y_h + 1) / 2;
int out_linesize[3] = { (int) y_pitch,
(int) (y_pitch + 1) / 2,
(int) (y_pitch + 1) / 2 };
unsigned char *out_data[3] = { tex_data,
tex_data + (y_h * out_linesize[0]),
tex_data + (y_h * out_linesize[0]) +
(chr_h * out_linesize[1]) };
uyvy_to_i420(
out_data, out_linesize, (unsigned char *) uv_frame->tiles[0].data,
(int) uv_frame->tiles[0].width, (int) uv_frame->tiles[0].height);
}
static void
convert_UYVY_NV12(const struct video_frame *uv_frame, unsigned char *tex_data,
size_t y_pitch)
{
unsigned char *out_data[2] = {
tex_data, tex_data + (y_pitch * uv_frame->tiles[0].height)
};
int out_linesize[2] = { (int) y_pitch, (int) ((y_pitch + 1) / 2) * 2 };
uyvy_to_nv12(
out_data, out_linesize, (unsigned char *) uv_frame->tiles[0].data,
(int) uv_frame->tiles[0].width, (int) uv_frame->tiles[0].height);
}
/**
@@ -1201,30 +1191,30 @@ convert_UYVY_IYUV(const struct video_frame *uv_frame, char *tex_data,
* currently seem to work only on Metal
*/
static void
convert_Y216_P010(const struct video_frame *uv_frame, char *tex_data,
convert_Y216_P010(const struct video_frame *uv_frame, unsigned char *tex_data,
size_t y_pitch)
{
char *out_data[2] = {
unsigned char *out_data[2] = {
tex_data, tex_data + (y_pitch * uv_frame->tiles[0].height)
};
int out_linesize[2] = { (int) y_pitch, (int) ((y_pitch + 1) / 2) * 2 };
y216_to_p010le(out_data, out_linesize, uv_frame->tiles[0].data,
(int) uv_frame->tiles[0].width,
(int) uv_frame->tiles[0].height);
y216_to_p010le(
out_data, out_linesize, (unsigned char *) uv_frame->tiles[0].data,
(int) uv_frame->tiles[0].width, (int) uv_frame->tiles[0].height);
}
/// @copydoc convert_Y216_P010
static void
convert_v210_P010(const struct video_frame *uv_frame, char *tex_data,
convert_v210_P010(const struct video_frame *uv_frame, unsigned char *tex_data,
size_t y_pitch)
{
char *out_data[2] = {
unsigned char *out_data[2] = {
tex_data, tex_data + (y_pitch * uv_frame->tiles[0].height)
};
int out_linesize[2] = { (int) y_pitch, (int) ((y_pitch + 1) / 2) * 2 };
v210_to_p010le(out_data, out_linesize, uv_frame->tiles[0].data,
(int) uv_frame->tiles[0].width,
(int) uv_frame->tiles[0].height);
v210_to_p010le(
out_data, out_linesize, (unsigned char *) uv_frame->tiles[0].data,
(int) uv_frame->tiles[0].width, (int) uv_frame->tiles[0].height);
}
static bool