webm/theora/yuv2rgb: Fix YUV conversion issues and add BGRP WEBM handling. (Now clang-format friendly.)
This should fix the various issues with colours in Ogg Theora and WEBM playback. (A reference project is attached to PR #26051, which this commit should be part of.) This version of the commit, rather than moving x->RGBA handling into libsimplewebm, uses a colourspace field added to libsimplewebm by a PR there. Thus, the commit that precedes this should be the synchronization & cleanup commit for that. Also, this version is now clang-format friendly. I hope.
This commit is contained in:
parent
006f6f5ba1
commit
b1f5cee7d9
3 changed files with 65 additions and 89 deletions
|
@ -94,15 +94,15 @@ void VideoStreamPlaybackTheora::video_write(void) {
|
||||||
|
|
||||||
if (px_fmt == TH_PF_444) {
|
if (px_fmt == TH_PF_444) {
|
||||||
|
|
||||||
yuv444_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0);
|
yuv444_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2);
|
||||||
|
|
||||||
} else if (px_fmt == TH_PF_422) {
|
} else if (px_fmt == TH_PF_422) {
|
||||||
|
|
||||||
yuv422_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0);
|
yuv422_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2);
|
||||||
|
|
||||||
} else if (px_fmt == TH_PF_420) {
|
} else if (px_fmt == TH_PF_420) {
|
||||||
|
|
||||||
yuv420_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[2].data, (uint8_t *)yuv[1].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0);
|
yuv420_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2);
|
||||||
};
|
};
|
||||||
|
|
||||||
format = Image::FORMAT_RGBA8;
|
format = Image::FORMAT_RGBA8;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "OpusVorbisDecoder.hpp"
|
#include "OpusVorbisDecoder.hpp"
|
||||||
#include "VPXDecoder.hpp"
|
#include "VPXDecoder.hpp"
|
||||||
|
#include <vpx/vpx_image.h>
|
||||||
|
|
||||||
#include "mkvparser/mkvparser.h"
|
#include "mkvparser/mkvparser.h"
|
||||||
|
|
||||||
|
@ -314,19 +315,37 @@ void VideoStreamPlaybackWebm::update(float p_delta) {
|
||||||
PoolVector<uint8_t>::Write w = frame_data.write();
|
PoolVector<uint8_t>::Write w = frame_data.write();
|
||||||
bool converted = false;
|
bool converted = false;
|
||||||
|
|
||||||
if (image.chromaShiftW == 1 && image.chromaShiftH == 1) {
|
if (image.chromaShiftW == 0 && image.chromaShiftH == 0 && image.cs == VPX_CS_SRGB) {
|
||||||
|
|
||||||
yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
|
uint8_t *wp = w.ptr();
|
||||||
|
unsigned char *rRow = image.planes[2];
|
||||||
|
unsigned char *gRow = image.planes[0];
|
||||||
|
unsigned char *bRow = image.planes[1];
|
||||||
|
for (size_t i = 0; i < image.h; i++) {
|
||||||
|
for (size_t j = 0; j < image.w; j++) {
|
||||||
|
*wp++ = rRow[j];
|
||||||
|
*wp++ = gRow[j];
|
||||||
|
*wp++ = bRow[j];
|
||||||
|
*wp++ = 255;
|
||||||
|
}
|
||||||
|
rRow += image.linesize[2];
|
||||||
|
gRow += image.linesize[0];
|
||||||
|
bRow += image.linesize[1];
|
||||||
|
}
|
||||||
|
converted = true;
|
||||||
|
} else if (image.chromaShiftW == 1 && image.chromaShiftH == 1) {
|
||||||
|
|
||||||
|
yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
||||||
// libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
// libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
||||||
converted = true;
|
converted = true;
|
||||||
} else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) {
|
} else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) {
|
||||||
|
|
||||||
yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
|
yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
||||||
// libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
// libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
||||||
converted = true;
|
converted = true;
|
||||||
} else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) {
|
} else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) {
|
||||||
|
|
||||||
yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
|
yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
||||||
// libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
// libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
||||||
converted = true;
|
converted = true;
|
||||||
} else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) {
|
} else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) {
|
||||||
|
|
121
thirdparty/misc/yuv2rgb.h
vendored
121
thirdparty/misc/yuv2rgb.h
vendored
|
@ -24,6 +24,14 @@ does not infringe any patents that apply in your area before you
|
||||||
ship it.
|
ship it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Please note that this version has been modified for various reasons:
|
||||||
|
* 1. Using the Godot core typedefs
|
||||||
|
* 2. At some point or another the code relied on the byte order of a uint32_t, this has been fixed
|
||||||
|
* 3. Output has been reordered to struct { uint8_t r, g, b, a; } precisely in accordance with the function names
|
||||||
|
* 4. Removing unused 'dither' parameter
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef YUV2RGB_H
|
#ifndef YUV2RGB_H
|
||||||
#define YUV2RGB_H
|
#define YUV2RGB_H
|
||||||
|
|
||||||
|
@ -803,6 +811,8 @@ static const uint32_t tables[256*3] = {
|
||||||
0xE6365800U
|
0xE6365800U
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* -- Common -- */
|
||||||
|
|
||||||
#define FLAGS 0x40080100
|
#define FLAGS 0x40080100
|
||||||
#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
|
#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
|
||||||
#define READY(Y) tables[Y]
|
#define READY(Y) tables[Y]
|
||||||
|
@ -820,12 +830,14 @@ do { \
|
||||||
|
|
||||||
#define STORE(Y,DSTPTR) \
|
#define STORE(Y,DSTPTR) \
|
||||||
do { \
|
do { \
|
||||||
*(DSTPTR)++ = (Y); \
|
|
||||||
*(DSTPTR)++ = (Y)>>22; \
|
|
||||||
*(DSTPTR)++ = (Y)>>11; \
|
*(DSTPTR)++ = (Y)>>11; \
|
||||||
*(DSTPTR)++ = 255; \
|
*(DSTPTR)++ = (Y)>>22; \
|
||||||
|
*(DSTPTR)++ = (Y); \
|
||||||
|
*(DSTPTR)++ = 255; \
|
||||||
} while (0 == 1)
|
} while (0 == 1)
|
||||||
|
|
||||||
|
/* -- End Common -- */
|
||||||
|
|
||||||
static void yuv422_2_rgb8888(uint8_t *dst_ptr,
|
static void yuv422_2_rgb8888(uint8_t *dst_ptr,
|
||||||
const uint8_t *y_ptr,
|
const uint8_t *y_ptr,
|
||||||
const uint8_t *u_ptr,
|
const uint8_t *u_ptr,
|
||||||
|
@ -834,8 +846,7 @@ static void yuv422_2_rgb8888(uint8_t *dst_ptr,
|
||||||
int32_t height,
|
int32_t height,
|
||||||
int32_t y_span,
|
int32_t y_span,
|
||||||
int32_t uv_span,
|
int32_t uv_span,
|
||||||
int32_t dst_span,
|
int32_t dst_span)
|
||||||
int32_t dither)
|
|
||||||
{
|
{
|
||||||
height -= 1;
|
height -= 1;
|
||||||
while (height > 0)
|
while (height > 0)
|
||||||
|
@ -909,35 +920,7 @@ static void yuv422_2_rgb8888(uint8_t *dst_ptr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void yuv420_2_rgb8888(uint8_t *dst_ptr,
|
||||||
#undef FLAGS
|
|
||||||
#undef READUV
|
|
||||||
#undef READY
|
|
||||||
#undef FIXUP
|
|
||||||
#undef STORE
|
|
||||||
|
|
||||||
|
|
||||||
#define FLAGS 0x40080100
|
|
||||||
#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
|
|
||||||
#define READY(Y) tables[Y]
|
|
||||||
#define FIXUP(Y) \
|
|
||||||
do { \
|
|
||||||
int tmp = (Y) & FLAGS; \
|
|
||||||
if (tmp != 0) \
|
|
||||||
{ \
|
|
||||||
tmp -= tmp>>8; \
|
|
||||||
(Y) |= tmp; \
|
|
||||||
tmp = FLAGS & ~(Y>>1); \
|
|
||||||
(Y) += tmp>>8; \
|
|
||||||
} \
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
#define STORE(Y,DSTPTR) \
|
|
||||||
do { \
|
|
||||||
(DSTPTR) = 0xFF000000 | (Y & 0xFF) | (0xFF00 & (Y>>14)) | (0xFF0000 & (Y<<5));\
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
|
|
||||||
const uint8_t *y_ptr,
|
const uint8_t *y_ptr,
|
||||||
const uint8_t *u_ptr,
|
const uint8_t *u_ptr,
|
||||||
const uint8_t *v_ptr,
|
const uint8_t *v_ptr,
|
||||||
|
@ -945,12 +928,9 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
|
||||||
int32_t height,
|
int32_t height,
|
||||||
int32_t y_span,
|
int32_t y_span,
|
||||||
int32_t uv_span,
|
int32_t uv_span,
|
||||||
int32_t dst_span,
|
int32_t dst_span)
|
||||||
int32_t dither)
|
|
||||||
{
|
{
|
||||||
uint32_t *dst_ptr = (uint32_t *)(void *)dst_ptr_;
|
/* The 'dst_ptr as uint32_t' thing is not endianness-aware, so that's been removed. */
|
||||||
dst_span >>= 2;
|
|
||||||
|
|
||||||
height -= 1;
|
height -= 1;
|
||||||
while (height > 0)
|
while (height > 0)
|
||||||
{
|
{
|
||||||
|
@ -960,36 +940,38 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
|
||||||
{
|
{
|
||||||
/* Do 2 column pairs */
|
/* Do 2 column pairs */
|
||||||
uint32_t uv, y0, y1;
|
uint32_t uv, y0, y1;
|
||||||
|
uint8_t * dst_ptr_1span = dst_ptr + dst_span;
|
||||||
|
|
||||||
uv = READUV(*u_ptr++,*v_ptr++);
|
uv = READUV(*u_ptr++,*v_ptr++);
|
||||||
y1 = uv + READY(y_ptr[y_span]);
|
y1 = uv + READY(y_ptr[y_span]);
|
||||||
y0 = uv + READY(*y_ptr++);
|
y0 = uv + READY(*y_ptr++);
|
||||||
FIXUP(y1);
|
FIXUP(y1);
|
||||||
FIXUP(y0);
|
FIXUP(y0);
|
||||||
STORE(y1, dst_ptr[dst_span]);
|
STORE(y1, dst_ptr_1span);
|
||||||
STORE(y0, *dst_ptr++);
|
STORE(y0, dst_ptr);
|
||||||
y1 = uv + READY(y_ptr[y_span]);
|
y1 = uv + READY(y_ptr[y_span]);
|
||||||
y0 = uv + READY(*y_ptr++);
|
y0 = uv + READY(*y_ptr++);
|
||||||
FIXUP(y1);
|
FIXUP(y1);
|
||||||
FIXUP(y0);
|
FIXUP(y0);
|
||||||
STORE(y1, dst_ptr[dst_span]);
|
STORE(y1, dst_ptr_1span);
|
||||||
STORE(y0, *dst_ptr++);
|
STORE(y0, dst_ptr);
|
||||||
height += (2<<16);
|
height += (2<<16);
|
||||||
}
|
}
|
||||||
if ((height>>16) == 0)
|
if ((height>>16) == 0)
|
||||||
{
|
{
|
||||||
/* Trailing column pair */
|
/* Trailing column pair */
|
||||||
uint32_t uv, y0, y1;
|
uint32_t uv, y0, y1;
|
||||||
|
uint8_t * dst_ptr_1span = dst_ptr + dst_span;
|
||||||
|
|
||||||
uv = READUV(*u_ptr,*v_ptr);
|
uv = READUV(*u_ptr,*v_ptr);
|
||||||
y1 = uv + READY(y_ptr[y_span]);
|
y1 = uv + READY(y_ptr[y_span]);
|
||||||
y0 = uv + READY(*y_ptr++);
|
y0 = uv + READY(*y_ptr++);
|
||||||
FIXUP(y1);
|
FIXUP(y1);
|
||||||
FIXUP(y0);
|
FIXUP(y0);
|
||||||
STORE(y0, dst_ptr[dst_span]);
|
STORE(y0, dst_ptr_1span);
|
||||||
STORE(y1, *dst_ptr++);
|
STORE(y1, dst_ptr);
|
||||||
}
|
}
|
||||||
dst_ptr += dst_span*2-width;
|
dst_ptr += (dst_span * 2) - (width * 4);
|
||||||
y_ptr += y_span*2-width;
|
y_ptr += y_span*2-width;
|
||||||
u_ptr += uv_span-(width>>1);
|
u_ptr += uv_span-(width>>1);
|
||||||
v_ptr += uv_span-(width>>1);
|
v_ptr += uv_span-(width>>1);
|
||||||
|
@ -1011,8 +993,8 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
|
||||||
y0 = uv + READY(*y_ptr++);
|
y0 = uv + READY(*y_ptr++);
|
||||||
FIXUP(y1);
|
FIXUP(y1);
|
||||||
FIXUP(y0);
|
FIXUP(y0);
|
||||||
STORE(y1, *dst_ptr++);
|
STORE(y1, dst_ptr);
|
||||||
STORE(y0, *dst_ptr++);
|
STORE(y0, dst_ptr);
|
||||||
height += (2<<16);
|
height += (2<<16);
|
||||||
}
|
}
|
||||||
if ((height>>16) == 0)
|
if ((height>>16) == 0)
|
||||||
|
@ -1023,42 +1005,11 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
|
||||||
uv = READUV(*u_ptr++,*v_ptr++);
|
uv = READUV(*u_ptr++,*v_ptr++);
|
||||||
y0 = uv + READY(*y_ptr++);
|
y0 = uv + READY(*y_ptr++);
|
||||||
FIXUP(y0);
|
FIXUP(y0);
|
||||||
STORE(y0, *dst_ptr++);
|
STORE(y0, dst_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef FLAGS
|
|
||||||
#undef READUV
|
|
||||||
#undef READY
|
|
||||||
#undef FIXUP
|
|
||||||
#undef STORE
|
|
||||||
|
|
||||||
#define FLAGS 0x40080100
|
|
||||||
#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
|
|
||||||
#define READY(Y) tables[Y]
|
|
||||||
#define FIXUP(Y) \
|
|
||||||
do { \
|
|
||||||
int tmp = (Y) & FLAGS; \
|
|
||||||
if (tmp != 0) \
|
|
||||||
{ \
|
|
||||||
tmp -= tmp>>8; \
|
|
||||||
(Y) |= tmp; \
|
|
||||||
tmp = FLAGS & ~(Y>>1); \
|
|
||||||
(Y) += tmp>>8; \
|
|
||||||
} \
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
#define STORE(Y,DSTPTR) \
|
|
||||||
do { \
|
|
||||||
*(DSTPTR)++ = (Y); \
|
|
||||||
*(DSTPTR)++ = (Y)>>22; \
|
|
||||||
*(DSTPTR)++ = (Y)>>11; \
|
|
||||||
*(DSTPTR)++ = 255; \
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
static void yuv444_2_rgb8888(uint8_t *dst_ptr,
|
static void yuv444_2_rgb8888(uint8_t *dst_ptr,
|
||||||
const uint8_t *y_ptr,
|
const uint8_t *y_ptr,
|
||||||
const uint8_t *u_ptr,
|
const uint8_t *u_ptr,
|
||||||
|
@ -1067,8 +1018,7 @@ static void yuv444_2_rgb8888(uint8_t *dst_ptr,
|
||||||
int32_t height,
|
int32_t height,
|
||||||
int32_t y_span,
|
int32_t y_span,
|
||||||
int32_t uv_span,
|
int32_t uv_span,
|
||||||
int32_t dst_span,
|
int32_t dst_span)
|
||||||
int32_t dither)
|
|
||||||
{
|
{
|
||||||
height -= 1;
|
height -= 1;
|
||||||
while (height > 0)
|
while (height > 0)
|
||||||
|
@ -1143,4 +1093,11 @@ static void yuv444_2_rgb8888(uint8_t *dst_ptr,
|
||||||
height -= 1;
|
height -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef FLAGS
|
||||||
|
#undef READUV
|
||||||
|
#undef READY
|
||||||
|
#undef FIXUP
|
||||||
|
#undef STORE
|
||||||
|
|
||||||
#endif // YUV2RGB_H
|
#endif // YUV2RGB_H
|
||||||
|
|
Loading…
Reference in a new issue