mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-20 17:40:12 +00:00
video_codec: planar<->packed YUV use unsigned char
This requires less conversions from/to (char *). \+ vcap/testcard: handle unsuppoted subsampling
This commit is contained in:
@@ -357,16 +357,26 @@ static size_t testcard_load_from_file_y4m(const char *filename, struct video_des
|
||||
desc->height = info.height;
|
||||
desc->color_spec = info.bitdepth == 8 ? UYVY : Y416;
|
||||
size_t data_len = vc_get_datalen(desc->width, desc->height, desc->color_spec);
|
||||
*in_file_contents = (char *) malloc(data_len);
|
||||
unsigned char *converted = malloc(data_len);
|
||||
if (info.bitdepth == 8) {
|
||||
if (info.subsampling == Y4M_SUBS_422) {
|
||||
i422_8_to_uyvy(desc->width, desc->height, (char *) data, *in_file_contents);
|
||||
} else {
|
||||
i444_8_to_uyvy(desc->width, desc->height, (char *) data, *in_file_contents);
|
||||
switch (info.subsampling) {
|
||||
case Y4M_SUBS_422:
|
||||
i422_8_to_uyvy(desc->width, desc->height, data,
|
||||
converted);
|
||||
break;
|
||||
case Y4M_SUBS_444:
|
||||
i444_8_to_uyvy(desc->width, desc->height, data,
|
||||
converted);
|
||||
break;
|
||||
default:
|
||||
MSG(ERROR, "Wrong Y4M subsampling: %d", info.subsampling);
|
||||
free(converted);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
i444_16_to_y416(desc->width, desc->height, (char *) data, *in_file_contents, info.bitdepth);
|
||||
i444_16_to_y416(desc->width, desc->height, data, converted, info.bitdepth);
|
||||
}
|
||||
*in_file_contents = (char *) converted;
|
||||
free(data);
|
||||
return data_len;
|
||||
}
|
||||
|
||||
@@ -936,43 +936,49 @@ bool codec_is_420(codec_t pix_fmt)
|
||||
pixfmt_plane_info[pix_fmt].plane_info[5] == 2;
|
||||
}
|
||||
|
||||
void uyvy_to_i422(int width, int height, const char *in, char *out)
|
||||
void
|
||||
uyvy_to_i422(int width, int height, const unsigned char *in, unsigned char *out)
|
||||
{
|
||||
char *out_y = out;
|
||||
char *out_cb = out + width * height;
|
||||
char *out_cr = out + width * height + ((width + 1) / 2) * height;
|
||||
unsigned char *out_y = out;
|
||||
unsigned char *out_cb = out + width * height;
|
||||
unsigned char *out_cr =
|
||||
out + width * height + ((width + 1) / 2) * height;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width / 2; ++x) {
|
||||
*out_cb++ = *in++;
|
||||
*out_y++ = *in++;
|
||||
*out_y++ = *in++;
|
||||
*out_cr++ = *in++;
|
||||
*out_y++ = *in++;
|
||||
*out_y++ = *in++;
|
||||
}
|
||||
if (width % 2 == 1) {
|
||||
*out_cb++ = *in++;
|
||||
*out_y++ = *in++;
|
||||
*out_y++ = *in++;
|
||||
*out_cr++ = *in++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void y416_to_i444(int width, int height, const char *in, char *out, int depth)
|
||||
void
|
||||
y416_to_i444(int width, int height, const unsigned char *in, unsigned char *out,
|
||||
int depth)
|
||||
{
|
||||
const uint16_t *inp = (const uint16_t *)(const void *) in;
|
||||
uint16_t *out_y = (uint16_t *)(void *) out;
|
||||
uint16_t *out_cb = (uint16_t *)(void *) out + width * height;
|
||||
uint16_t *out_cr = (uint16_t *)(void *) out + 2 * width * height;
|
||||
const uint16_t *inp = (const uint16_t *) (const void *) in;
|
||||
uint16_t *out_y = (uint16_t *) (void *) out;
|
||||
uint16_t *out_cb = (uint16_t *) (void *) out + width * height;
|
||||
uint16_t *out_cr = (uint16_t *) (void *) out + 2 * width * height;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
*out_cb++ = *inp++ >> (16 - depth);
|
||||
*out_y++ = *inp++ >> (16 - depth);
|
||||
*out_y++ = *inp++ >> (16 - depth);
|
||||
*out_cr++ = *inp++ >> (16 - depth);
|
||||
inp++; // alpha
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i444_16_to_y416(int width, int height, const char *in, char *out, int in_depth)
|
||||
void
|
||||
i444_16_to_y416(int width, int height, const unsigned char *in,
|
||||
unsigned char *out, int in_depth)
|
||||
{
|
||||
const uint16_t *in_y = (const uint16_t *)(const void *) in;
|
||||
const uint16_t *in_cb = (const uint16_t *)(const void *) in + width * height;
|
||||
@@ -988,12 +994,14 @@ void i444_16_to_y416(int width, int height, const char *in, char *out, int in_de
|
||||
}
|
||||
}
|
||||
|
||||
void i422_8_to_uyvy(int width, int height, const char *in, char *out)
|
||||
void
|
||||
i422_8_to_uyvy(int width, int height, const unsigned char *in,
|
||||
unsigned char *out)
|
||||
{
|
||||
const char *in_y = in;
|
||||
const char *in_cb = in + width * height;
|
||||
const char *in_cr = in_cb + (((width + 1) / 2) * height);
|
||||
char *outp = out;
|
||||
const unsigned char *in_y = in;
|
||||
const unsigned char *in_cb = in + width * height;
|
||||
const unsigned char *in_cr = in_cb + (((width + 1) / 2) * height);
|
||||
unsigned char *outp = out;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < (width + 1) / 2; ++x) {
|
||||
*outp++ = *in_cb++;
|
||||
@@ -1004,12 +1012,14 @@ void i422_8_to_uyvy(int width, int height, const char *in, char *out)
|
||||
}
|
||||
}
|
||||
|
||||
void i444_8_to_uyvy(int width, int height, const char *in, char *out)
|
||||
void
|
||||
i444_8_to_uyvy(int width, int height, const unsigned char *in,
|
||||
unsigned char *out)
|
||||
{
|
||||
const char *in_y = in;
|
||||
const char *in_cb = in + width * height;
|
||||
const char *in_cr = in_cb + width * height;
|
||||
char *outp = out;
|
||||
const unsigned char *in_y = in;
|
||||
const unsigned char *in_cb = in + width * height;
|
||||
const unsigned char *in_cr = in_cb + width * height;
|
||||
unsigned char *outp = out;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < (width + 1) / 2; ++x) {
|
||||
*outp++ = *in_cb;
|
||||
|
||||
@@ -106,11 +106,16 @@ bool vc_deinterlace_ex(codec_t codec, unsigned char *src, size_t src_linesize, u
|
||||
bool clear_video_buffer(unsigned char *data, size_t linesize, size_t pitch, size_t height, codec_t color_spec);
|
||||
|
||||
// conversions from/to planar formats
|
||||
void uyvy_to_i422(int width, int height, const char *in, char *out);
|
||||
void y416_to_i444(int width, int height, const char *in, char *out, int depth);
|
||||
void i444_16_to_y416(int width, int height, const char *in, char *out, int in_depth);
|
||||
void i422_8_to_uyvy(int width, int height, const char *in, char *out);
|
||||
void i444_8_to_uyvy(int width, int height, const char *in, char *out);
|
||||
void uyvy_to_i422(int width, int height, const unsigned char *in,
|
||||
unsigned char *out);
|
||||
void y416_to_i444(int width, int height, const unsigned char *in,
|
||||
unsigned char *out, int depth);
|
||||
void i444_16_to_y416(int width, int height, const unsigned char *in,
|
||||
unsigned char *out, int in_depth);
|
||||
void i422_8_to_uyvy(int width, int height, const unsigned char *in,
|
||||
unsigned char *out);
|
||||
void i444_8_to_uyvy(int width, int height, const unsigned char *in,
|
||||
unsigned char *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -492,32 +492,32 @@ static bool save_video_frame_as_y4m(struct video_frame *frame, const char *name)
|
||||
{
|
||||
struct tile *tile = &frame->tiles[0];
|
||||
if (get_bits_per_component(frame->color_spec) <= 8 && (frame->color_spec == UYVY || get_decoder_from_to(frame->color_spec, UYVY))) {
|
||||
char *uyvy = tile->data;
|
||||
char *tmp_data_uyvy = NULL;
|
||||
unsigned char *uyvy = (unsigned char *) tile->data;
|
||||
unsigned char *tmp_data_uyvy = NULL;
|
||||
if (frame->color_spec != UYVY) {
|
||||
decoder_t dec = get_decoder_from_to(frame->color_spec, UYVY);
|
||||
int len = vc_get_datalen(tile->width, tile->height, UYVY);
|
||||
uyvy = tmp_data_uyvy = malloc(len);
|
||||
dec ((unsigned char *) uyvy, (const unsigned char *) tile->data, len, 0, 0, 0);
|
||||
dec (uyvy, (const unsigned char *) tile->data, len, 0, 0, 0);
|
||||
}
|
||||
char *i422 = malloc(tile->width * tile->height + 2 * ((tile->width + 1) / 2) * tile->height);
|
||||
unsigned char *i422 = malloc(tile->width * tile->height + 2 * ((tile->width + 1) / 2) * tile->height);
|
||||
uyvy_to_i422(tile->width, tile->height, uyvy, i422);
|
||||
|
||||
struct y4m_metadata info = { .width = tile->width, .height = tile->height, .bitdepth = 8, .subsampling = Y4M_SUBS_422, .limited = true };
|
||||
bool ret = y4m_write(name, &info, (unsigned char *) i422);
|
||||
bool ret = y4m_write(name, &info, i422);
|
||||
free(tmp_data_uyvy);
|
||||
free(i422);
|
||||
return ret;
|
||||
} else if (get_decoder_from_to(frame->color_spec, Y416)) {
|
||||
char *y416 = tile->data;
|
||||
char *tmp_data_y416 = NULL;
|
||||
unsigned char *y416 = (unsigned char *) tile->data;
|
||||
unsigned char *tmp_data_y416 = NULL;
|
||||
if (frame->color_spec != Y416) {
|
||||
decoder_t dec = get_decoder_from_to(frame->color_spec, Y416);
|
||||
int len = vc_get_datalen(tile->width, tile->height, Y416);
|
||||
y416 = tmp_data_y416 = malloc(len);
|
||||
dec ((unsigned char *) y416, (const unsigned char *) tile->data, len, 0, 0, 0);
|
||||
dec (y416, (const unsigned char *) tile->data, len, 0, 0, 0);
|
||||
}
|
||||
char *i444 = malloc(tile->width * tile->height * 6);
|
||||
unsigned char *i444 = malloc(tile->width * tile->height * 6);
|
||||
int depth = get_bits_per_component(frame->color_spec);
|
||||
y416_to_i444(tile->width, tile->height, y416, i444, depth);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user