mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-21 19:40:24 +00:00
Libavcodec: added support for 12-bit RGB
This commit is contained in:
@@ -135,6 +135,7 @@ static void v210_to_p010le(AVFrame *out_frame, unsigned char *in_data, int width
|
||||
static void rgb_to_bgr0(AVFrame *out_frame, unsigned char *in_data, int width, int height);
|
||||
static void rgb_to_gbrp(AVFrame *out_frame, unsigned char *in_data, int width, int height);
|
||||
static void r10k_to_gbrp10le(AVFrame *out_frame, unsigned char *in_data, int width, int height);
|
||||
static void r12l_to_gbrp12le(AVFrame *out_frame, unsigned char *in_data, int width, int height);
|
||||
|
||||
typedef void (*pixfmt_callback_t)(AVFrame *out_frame, unsigned char *in_data, int width, int height);
|
||||
static pixfmt_callback_t select_pixfmt_callback(AVPixelFormat fmt, codec_t src);
|
||||
@@ -779,6 +780,7 @@ static const struct {
|
||||
{ RGB, AV_PIX_FMT_BGR0, rgb_to_bgr0 },
|
||||
{ RGB, AV_PIX_FMT_GBRP, rgb_to_gbrp },
|
||||
{ R10k, AV_PIX_FMT_GBRP10LE, r10k_to_gbrp10le },
|
||||
{ R12L, AV_PIX_FMT_GBRP12LE, r12l_to_gbrp12le },
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1507,6 +1509,86 @@ static void r10k_to_gbrp10le(AVFrame *out_frame, unsigned char *in_data, int wid
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define BYTE_SWAP(x) (3 - x)
|
||||
#else
|
||||
#define BYTE_SWAP(x) x
|
||||
#endif
|
||||
|
||||
static void r12l_to_gbrp12le(AVFrame *out_frame, unsigned char *in_data, int width, int height)
|
||||
{
|
||||
int src_linesize = vc_get_linesize(width, R12L);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
unsigned char *src = in_data + y * src_linesize;
|
||||
uint16_t *dst_b = (uint16_t *) (out_frame->data[0] + out_frame->linesize[0] * y);
|
||||
uint16_t *dst_g = (uint16_t *) (out_frame->data[1] + out_frame->linesize[1] * y);
|
||||
uint16_t *dst_r = (uint16_t *) (out_frame->data[2] + out_frame->linesize[2] * y);
|
||||
for (int x = 0; x < width; x += 8) {
|
||||
uint16_t tmp;
|
||||
tmp = src[BYTE_SWAP(0)];
|
||||
tmp |= (src[BYTE_SWAP(1)] & 0xf) << 8;
|
||||
*dst_r++ = tmp; // r0
|
||||
*dst_g++ = src[BYTE_SWAP(2)] << 4 | src[BYTE_SWAP(1)] >> 4; // g0
|
||||
tmp = src[BYTE_SWAP(3)];
|
||||
src += 4;
|
||||
tmp |= (src[BYTE_SWAP(0)] & 0xf) << 8;
|
||||
*dst_b++ = tmp; // b0
|
||||
*dst_r++ = src[BYTE_SWAP(1)] << 4 | src[BYTE_SWAP(0)] >> 4; // r1
|
||||
tmp = src[BYTE_SWAP(2)];
|
||||
tmp |= (src[BYTE_SWAP(3)] & 0xf) << 8;
|
||||
*dst_g++ = tmp; // g1
|
||||
tmp = src[BYTE_SWAP(3)] >> 4;
|
||||
src += 4;
|
||||
*dst_b++ = src[BYTE_SWAP(0)] << 4 | tmp; // b1
|
||||
tmp = src[BYTE_SWAP(1)];
|
||||
tmp |= (src[BYTE_SWAP(2)] & 0xf) << 8;
|
||||
*dst_r++ = tmp; // r2
|
||||
*dst_g++ = src[BYTE_SWAP(3)] << 4 | src[BYTE_SWAP(2)] >> 4; // g2
|
||||
src += 4;
|
||||
tmp = src[BYTE_SWAP(0)];
|
||||
tmp |= (src[BYTE_SWAP(1)] & 0xf) << 8;
|
||||
*dst_b++ = tmp; // b2
|
||||
*dst_r++ = src[BYTE_SWAP(2)] << 4 | src[BYTE_SWAP(1)] >> 4; // r3
|
||||
tmp = src[BYTE_SWAP(3)];
|
||||
src += 4;
|
||||
tmp |= (src[BYTE_SWAP(0)] & 0xf) << 8;
|
||||
*dst_g++ = tmp; // g3
|
||||
*dst_b++ = src[BYTE_SWAP(1)] << 4 | src[BYTE_SWAP(0)] >> 4; // b3
|
||||
tmp = src[BYTE_SWAP(2)];
|
||||
tmp |= (src[BYTE_SWAP(3)] & 0xf) << 8;
|
||||
*dst_r++ = tmp; // r4
|
||||
tmp = src[BYTE_SWAP(3)] >> 4;
|
||||
src += 4;
|
||||
*dst_g++ = src[BYTE_SWAP(0)] << 4 | tmp; // g4
|
||||
tmp = src[BYTE_SWAP(1)];
|
||||
tmp |= (src[BYTE_SWAP(2)] & 0xf) << 8;
|
||||
*dst_b++ = tmp; // b4
|
||||
*dst_r++ = src[BYTE_SWAP(3)] << 4 | src[BYTE_SWAP(2)] >> 4; // r5
|
||||
src += 4;
|
||||
tmp = src[BYTE_SWAP(0)];
|
||||
tmp |= (src[BYTE_SWAP(1)] & 0xf) << 8;
|
||||
*dst_g++ = tmp; // g5
|
||||
*dst_b++ = src[BYTE_SWAP(2)] << 4 | src[BYTE_SWAP(1)] >> 4; // b5
|
||||
tmp = src[BYTE_SWAP(3)];
|
||||
src += 4;
|
||||
tmp |= (src[BYTE_SWAP(0)] & 0xf) << 8;
|
||||
*dst_r++ = tmp; // r6
|
||||
*dst_g++ = src[BYTE_SWAP(1)] << 4 | src[BYTE_SWAP(0)] >> 4; // g6
|
||||
tmp = src[BYTE_SWAP(2)];
|
||||
tmp |= (src[BYTE_SWAP(3)] & 0xf) << 8;
|
||||
*dst_b++ = tmp; // b6
|
||||
tmp = src[BYTE_SWAP(3)] >> 4;
|
||||
src += 4;
|
||||
*dst_r++ = src[BYTE_SWAP(0)] << 4 | tmp; // r7
|
||||
tmp = src[BYTE_SWAP(1)];
|
||||
tmp |= (src[BYTE_SWAP(2)] & 0xf) << 8;
|
||||
*dst_g++ = tmp; // g7
|
||||
*dst_b++ = src[BYTE_SWAP(3)] << 4 | src[BYTE_SWAP(2)] >> 4; // b7
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pixfmt_callback_t select_pixfmt_callback(AVPixelFormat fmt, codec_t src) {
|
||||
// no conversion needed
|
||||
if (ug_to_av_pixfmt_map.find(src) != ug_to_av_pixfmt_map.end()
|
||||
|
||||
@@ -513,6 +513,109 @@ static void gbrp10le_to_rgb(char *dst_buffer, AVFrame *frame,
|
||||
}
|
||||
}
|
||||
}
|
||||
static void gbrp10le_to_rgba(char *dst_buffer, AVFrame *frame,
|
||||
int width, int height, int pitch, int rgb_shift[static restrict 3])
|
||||
{
|
||||
for (int y = 0; y < height; ++y) {
|
||||
uint16_t *src_b = (uint16_t *) (frame->data[0] + frame->linesize[0] * y);
|
||||
uint16_t *src_g = (uint16_t *) (frame->data[1] + frame->linesize[1] * y);
|
||||
uint16_t *src_r = (uint16_t *) (frame->data[2] + frame->linesize[2] * y);
|
||||
uint32_t *dst = (uint32_t *) (dst_buffer + y * pitch);
|
||||
for (int x = 0; x < width; ++x) {
|
||||
*dst++ = (*src_r++ >> 2) << rgb_shift[0] | (*src_g++ >> 2) << rgb_shift[1] |
|
||||
(*src_b++ >> 2) << rgb_shift[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define BYTE_SWAP(x) (3 - x)
|
||||
#else
|
||||
#define BYTE_SWAP(x) x
|
||||
#endif
|
||||
|
||||
static void gbrp12le_to_r12l(char *dst_buffer, AVFrame *frame,
|
||||
int width, int height, int pitch, int rgb_shift[static restrict 3])
|
||||
{
|
||||
UNUSED(rgb_shift);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
uint16_t *src_b = (uint16_t *) (frame->data[0] + frame->linesize[0] * y);
|
||||
uint16_t *src_g = (uint16_t *) (frame->data[1] + frame->linesize[1] * y);
|
||||
uint16_t *src_r = (uint16_t *) (frame->data[2] + frame->linesize[2] * y);
|
||||
unsigned char *dst = (unsigned char *) dst_buffer + y * pitch;
|
||||
for (int x = 0; x < width; x += 8) {
|
||||
dst[BYTE_SWAP(0)] = *src_r & 0xff;
|
||||
dst[BYTE_SWAP(1)] = (*src_g & 0xf) << 4 | *src_r++ >> 8;
|
||||
dst[BYTE_SWAP(2)] = *src_g++ >> 4;
|
||||
dst[BYTE_SWAP(3)] = *src_b & 0xff;
|
||||
dst[4 + BYTE_SWAP(0)] = (*src_r & 0xf) << 4 | *src_b++ >> 8;
|
||||
dst[4 + BYTE_SWAP(1)] = *src_r++ >> 4;
|
||||
dst[4 + BYTE_SWAP(2)] = *src_g & 0xff;
|
||||
dst[4 + BYTE_SWAP(3)] = (*src_b & 0xf) << 4 | *src_g++ >> 8;
|
||||
dst[8 + BYTE_SWAP(0)] = *src_b++ >> 4;
|
||||
dst[8 + BYTE_SWAP(1)] = *src_r & 0xff;
|
||||
dst[8 + BYTE_SWAP(2)] = (*src_g & 0xf) << 4 | *src_r++ >> 8;
|
||||
dst[8 + BYTE_SWAP(3)] = *src_g++ >> 4;
|
||||
dst[12 + BYTE_SWAP(0)] = *src_b & 0xff;
|
||||
dst[12 + BYTE_SWAP(1)] = (*src_r & 0xf) << 4 | *src_b++ >> 8;
|
||||
dst[12 + BYTE_SWAP(2)] = *src_r++ >> 4;
|
||||
dst[12 + BYTE_SWAP(3)] = *src_g & 0xff;
|
||||
dst[16 + BYTE_SWAP(0)] = (*src_b & 0xf) << 4 | *src_g++ >> 8;
|
||||
dst[16 + BYTE_SWAP(1)] = *src_b++ >> 4;
|
||||
dst[16 + BYTE_SWAP(2)] = *src_r & 0xff;
|
||||
dst[16 + BYTE_SWAP(3)] = (*src_g & 0xf) << 4 | *src_r++ >> 8;
|
||||
dst[20 + BYTE_SWAP(0)] = *src_g++ >> 4;
|
||||
dst[20 + BYTE_SWAP(1)] = *src_b & 0xff;
|
||||
dst[20 + BYTE_SWAP(2)] = (*src_r & 0xf) << 4 | *src_b++ >> 8;
|
||||
dst[20 + BYTE_SWAP(3)] = *src_r++ >> 4;;
|
||||
dst[24 + BYTE_SWAP(0)] = *src_g & 0xff;
|
||||
dst[24 + BYTE_SWAP(1)] = (*src_b & 0xf) << 4 | *src_g++ >> 8;
|
||||
dst[24 + BYTE_SWAP(2)] = *src_b++ >> 4;
|
||||
dst[24 + BYTE_SWAP(3)] = *src_r & 0xff;
|
||||
dst[28 + BYTE_SWAP(0)] = (*src_g & 0xf) << 4 | *src_r++ >> 8;
|
||||
dst[28 + BYTE_SWAP(1)] = *src_g++ >> 4;
|
||||
dst[28 + BYTE_SWAP(2)] = *src_b & 0xff;
|
||||
dst[28 + BYTE_SWAP(3)] = (*src_r & 0xf) << 4 | *src_b++ >> 8;
|
||||
dst[32 + BYTE_SWAP(0)] = *src_r++ >> 4;
|
||||
dst[32 + BYTE_SWAP(1)] = *src_g & 0xff;
|
||||
dst[32 + BYTE_SWAP(2)] = (*src_b & 0xf) << 4 | *src_g++ >> 8;
|
||||
dst[32 + BYTE_SWAP(3)] = *src_b++ >> 4;
|
||||
dst += 36;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gbrp12le_to_rgb(char *dst_buffer, AVFrame *frame,
|
||||
int width, int height, int pitch, int rgb_shift[static restrict 3])
|
||||
{
|
||||
UNUSED(rgb_shift);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
uint16_t *src_b = (uint16_t *) (frame->data[0] + frame->linesize[0] * y);
|
||||
uint16_t *src_g = (uint16_t *) (frame->data[1] + frame->linesize[1] * y);
|
||||
uint16_t *src_r = (uint16_t *) (frame->data[2] + frame->linesize[2] * y);
|
||||
unsigned char *dst = (unsigned char *) dst_buffer + y * pitch;
|
||||
for (int x = 0; x < width; ++x) {
|
||||
*dst++ = *src_r++ >> 4;
|
||||
*dst++ = *src_g++ >> 4;
|
||||
*dst++ = *src_b++ >> 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gbrp12le_to_rgba(char *dst_buffer, AVFrame *frame,
|
||||
int width, int height, int pitch, int rgb_shift[static restrict 3])
|
||||
{
|
||||
for (int y = 0; y < height; ++y) {
|
||||
uint16_t *src_b = (uint16_t *) (frame->data[0] + frame->linesize[0] * y);
|
||||
uint16_t *src_g = (uint16_t *) (frame->data[1] + frame->linesize[1] * y);
|
||||
uint16_t *src_r = (uint16_t *) (frame->data[2] + frame->linesize[2] * y);
|
||||
uint32_t *dst = (uint32_t *) (dst_buffer + y * pitch);
|
||||
for (int x = 0; x < width; ++x) {
|
||||
*dst++ = (*src_r++ >> 4) << rgb_shift[0] | (*src_g++ >> 4) << rgb_shift[1] |
|
||||
(*src_b++ >> 4) << rgb_shift[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void yuv420p_to_yuv422(char *dst_buffer, AVFrame *in_frame,
|
||||
int width, int height, int pitch, int rgb_shift[static restrict 3])
|
||||
@@ -1243,6 +1346,10 @@ static const struct {
|
||||
{AV_PIX_FMT_RGB24, RGB, rgb24_to_rgb, true},
|
||||
{AV_PIX_FMT_GBRP10LE, R10k, gbrp10le_to_r10k, true},
|
||||
{AV_PIX_FMT_GBRP10LE, RGB, gbrp10le_to_rgb, false},
|
||||
{AV_PIX_FMT_GBRP10LE, RGBA, gbrp10le_to_rgba, false},
|
||||
{AV_PIX_FMT_GBRP12LE, R12L, gbrp12le_to_r12l, true},
|
||||
{AV_PIX_FMT_GBRP12LE, RGB, gbrp12le_to_rgb, false},
|
||||
{AV_PIX_FMT_GBRP12LE, RGBA, gbrp12le_to_rgba, false},
|
||||
#ifdef HWACC_VDPAU
|
||||
// HW acceleration
|
||||
{AV_PIX_FMT_VDPAU, HW_VDPAU, av_vdpau_to_ug_vdpau, false},
|
||||
@@ -1597,8 +1704,12 @@ static const struct decode_from_to dec_template[] = {
|
||||
{ VIDEO_CODEC_NONE, VIDEO_CODEC_NONE, VIDEO_CODEC_NONE, 80 }, // for probe
|
||||
{ VIDEO_CODEC_NONE, RGB, RGB, 500 },
|
||||
{ VIDEO_CODEC_NONE, RGB, RGBA, 500 },
|
||||
{ VIDEO_CODEC_NONE, R10k, RGB, 500 },
|
||||
{ VIDEO_CODEC_NONE, R10k, R10k, 500 },
|
||||
{ VIDEO_CODEC_NONE, R10k, RGB, 500 },
|
||||
{ VIDEO_CODEC_NONE, R10k, RGBA, 500 },
|
||||
{ VIDEO_CODEC_NONE, R12L, R12L, 500 },
|
||||
{ VIDEO_CODEC_NONE, R12L, RGB, 500 },
|
||||
{ VIDEO_CODEC_NONE, R12L, RGBA, 500 },
|
||||
//{ VIDEO_CODEC_NONE, UYVY, RGB, 500 }, // there are conversions but don't enable now
|
||||
{ VIDEO_CODEC_NONE, UYVY, UYVY, 500 },
|
||||
{ VIDEO_CODEC_NONE, v210, v210, 500 },
|
||||
|
||||
Reference in New Issue
Block a user