From f4dedb0ffca5b6d358d28071b5a376be27b44efb Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 24 Jan 2024 11:47:26 +0100 Subject: [PATCH] video_codec: planar<->packed YUV use unsigned char This requires less conversions from/to (char *). \+ vcap/testcard: handle unsuppoted subsampling --- src/video_capture/testcard.c | 22 ++++++++++---- src/video_codec.c | 58 +++++++++++++++++++++--------------- src/video_codec.h | 15 ++++++---- src/video_frame.c | 18 +++++------ 4 files changed, 69 insertions(+), 44 deletions(-) diff --git a/src/video_capture/testcard.c b/src/video_capture/testcard.c index 2a3429a3b..2995c5159 100644 --- a/src/video_capture/testcard.c +++ b/src/video_capture/testcard.c @@ -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; } diff --git a/src/video_codec.c b/src/video_codec.c index daeda00fe..bd6f264ca 100644 --- a/src/video_codec.c +++ b/src/video_codec.c @@ -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; diff --git a/src/video_codec.h b/src/video_codec.h index c9370ef9c..0be8dc77b 100644 --- a/src/video_codec.h +++ b/src/video_codec.h @@ -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 } diff --git a/src/video_frame.c b/src/video_frame.c index a9a5485bb..f107b1b72 100644 --- a/src/video_frame.c +++ b/src/video_frame.c @@ -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);