From b2528b0be934de1918e20c85fc170d809eeb49ab Mon Sep 17 00:00:00 2001 From: Sergio Garcia Murillo Date: Mon, 23 Jan 2023 11:13:48 +0100 Subject: [PATCH] Add support for odd width and height in I410ToI420 Bug: libyuv:950 Change-Id: Ic9a094463af875aefd927023f730b5f35f8551de Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4154630 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- include/libyuv/scale_row.h | 15 +++++++ source/scale.cc | 45 ++++++++++++-------- source/scale_common.cc | 85 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 124 insertions(+), 21 deletions(-) diff --git a/include/libyuv/scale_row.h b/include/libyuv/scale_row.h index 356da19dd..7996ea05d 100644 --- a/include/libyuv/scale_row.h +++ b/include/libyuv/scale_row.h @@ -275,6 +275,11 @@ void ScaleRowDown2_16To8_C(const uint16_t* src_ptr, uint8_t* dst, int dst_width, int scale); +void ScaleRowDown2_16To8_Odd_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width, + int scale); void ScaleRowDown2Linear_C(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst, @@ -288,6 +293,11 @@ void ScaleRowDown2Linear_16To8_C(const uint16_t* src_ptr, uint8_t* dst, int dst_width, int scale); +void ScaleRowDown2Linear_16To8_Odd_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width, + int scale); void ScaleRowDown2Box_C(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst, @@ -305,6 +315,11 @@ void ScaleRowDown2Box_16To8_C(const uint16_t* src_ptr, uint8_t* dst, int dst_width, int scale); +void ScaleRowDown2Box_16To8_Odd_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width, + int scale); void ScaleRowDown4_C(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst, diff --git a/source/scale.cc b/source/scale.cc index 8c4536e20..65a4685fc 100644 --- a/source/scale.cc +++ b/source/scale.cc @@ -211,13 +211,17 @@ void ScalePlaneDown2_16To8(int src_width, int y; void (*ScaleRowDown2)(const uint16_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, int dst_width, int scale) = - filtering == kFilterNone - ? ScaleRowDown2_16To8_C - : (filtering == kFilterLinear ? ScaleRowDown2Linear_16To8_C - : ScaleRowDown2Box_16To8_C); + (src_width & 1) + ? (filtering == kFilterNone + ? ScaleRowDown2_16To8_Odd_C + : (filtering == kFilterLinear ? ScaleRowDown2Linear_16To8_Odd_C + : ScaleRowDown2Box_16To8_Odd_C)) + : (filtering == kFilterNone + ? ScaleRowDown2_16To8_C + : (filtering == kFilterLinear ? ScaleRowDown2Linear_16To8_C + : ScaleRowDown2Box_16To8_C)); int row_stride = src_stride * 2; - (void)src_width; - (void)src_height; + (void)dst_height; if (!filtering) { src_ptr += src_stride; // Point to odd rows. src_stride = 0; @@ -226,12 +230,17 @@ void ScalePlaneDown2_16To8(int src_width, if (filtering == kFilterLinear) { src_stride = 0; } - // TODO(fbarchard): Loop through source height to allow odd height. - for (y = 0; y < dst_height; ++y) { + for (y = 0; y < src_height / 2; ++y) { ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width, scale); src_ptr += row_stride; dst_ptr += dst_stride; } + if (src_height & 1) { + if (!filtering) { + src_ptr -= src_stride; // Point to last row. + } + ScaleRowDown2(src_ptr, 0, dst_ptr, dst_width, scale); + } } // Scale plane, 1/4 @@ -1056,10 +1065,10 @@ void ScalePlaneBilinearDown(int src_width, const int max_y = (src_height - 1) << 16; int j; - void (*ScaleFilterCols)(uint8_t* dst_ptr, const uint8_t* src_ptr, + void (*ScaleFilterCols)(uint8_t * dst_ptr, const uint8_t* src_ptr, int dst_width, int x, int dx) = (src_width >= 32768) ? ScaleFilterCols64_C : ScaleFilterCols_C; - void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr, + void (*InterpolateRow)(uint8_t * dst_ptr, const uint8_t* src_ptr, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, @@ -1179,10 +1188,10 @@ void ScalePlaneBilinearDown_16(int src_width, const int max_y = (src_height - 1) << 16; int j; - void (*ScaleFilterCols)(uint16_t* dst_ptr, const uint16_t* src_ptr, + void (*ScaleFilterCols)(uint16_t * dst_ptr, const uint16_t* src_ptr, int dst_width, int x, int dx) = (src_width >= 32768) ? ScaleFilterCols64_16_C : ScaleFilterCols_16_C; - void (*InterpolateRow)(uint16_t* dst_ptr, const uint16_t* src_ptr, + void (*InterpolateRow)(uint16_t * dst_ptr, const uint16_t* src_ptr, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_16_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, @@ -1267,10 +1276,10 @@ void ScalePlaneBilinearUp(int src_width, int dx = 0; int dy = 0; const int max_y = (src_height - 1) << 16; - void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr, + void (*InterpolateRow)(uint8_t * dst_ptr, const uint8_t* src_ptr, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_C; - void (*ScaleFilterCols)(uint8_t* dst_ptr, const uint8_t* src_ptr, + void (*ScaleFilterCols)(uint8_t * dst_ptr, const uint8_t* src_ptr, int dst_width, int x, int dx) = filtering ? ScaleFilterCols_C : ScaleCols_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, @@ -1735,10 +1744,10 @@ void ScalePlaneBilinearUp_16(int src_width, int dx = 0; int dy = 0; const int max_y = (src_height - 1) << 16; - void (*InterpolateRow)(uint16_t* dst_ptr, const uint16_t* src_ptr, + void (*InterpolateRow)(uint16_t * dst_ptr, const uint16_t* src_ptr, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_16_C; - void (*ScaleFilterCols)(uint16_t* dst_ptr, const uint16_t* src_ptr, + void (*ScaleFilterCols)(uint16_t * dst_ptr, const uint16_t* src_ptr, int dst_width, int x, int dx) = filtering ? ScaleFilterCols_16_C : ScaleCols_16_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, @@ -1863,7 +1872,7 @@ static void ScalePlaneSimple(int src_width, const uint8_t* src_ptr, uint8_t* dst_ptr) { int i; - void (*ScaleCols)(uint8_t* dst_ptr, const uint8_t* src_ptr, int dst_width, + void (*ScaleCols)(uint8_t * dst_ptr, const uint8_t* src_ptr, int dst_width, int x, int dx) = ScaleCols_C; // Initial source x/y coordinate and step values as 16.16 fixed point. int x = 0; @@ -1900,7 +1909,7 @@ static void ScalePlaneSimple_16(int src_width, const uint16_t* src_ptr, uint16_t* dst_ptr) { int i; - void (*ScaleCols)(uint16_t* dst_ptr, const uint16_t* src_ptr, int dst_width, + void (*ScaleCols)(uint16_t * dst_ptr, const uint16_t* src_ptr, int dst_width, int x, int dx) = ScaleCols_16_C; // Initial source x/y coordinate and step values as 16.16 fixed point. int x = 0; diff --git a/source/scale_common.cc b/source/scale_common.cc index 55749a2e2..f18324034 100644 --- a/source/scale_common.cc +++ b/source/scale_common.cc @@ -101,6 +101,30 @@ void ScaleRowDown2_16To8_C(const uint16_t* src_ptr, } } +void ScaleRowDown2_16To8_Odd_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width, + int scale) { + int x; + (void)src_stride; + assert(scale >= 256); + assert(scale <= 32768); + dst_width -= 1; + for (x = 0; x < dst_width - 1; x += 2) { + dst[0] = STATIC_CAST(uint8_t, C16TO8(src_ptr[1], scale)); + dst[1] = STATIC_CAST(uint8_t, C16TO8(src_ptr[3], scale)); + dst += 2; + src_ptr += 4; + } + if (dst_width & 1) { + dst[0] = STATIC_CAST(uint8_t, C16TO8(src_ptr[1], scale)); + dst += 1; + src_ptr += 2; + } + dst[0] = STATIC_CAST(uint8_t, C16TO8(src_ptr[0], scale)); +} + void ScaleRowDown2Linear_C(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst, @@ -158,6 +182,31 @@ void ScaleRowDown2Linear_16To8_C(const uint16_t* src_ptr, } } +void ScaleRowDown2Linear_16To8_Odd_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width, + int scale) { + const uint16_t* s = src_ptr; + int x; + (void)src_stride; + assert(scale >= 256); + assert(scale <= 32768); + dst_width -= 1; + for (x = 0; x < dst_width - 1; x += 2) { + dst[0] = STATIC_CAST(uint8_t, C16TO8((s[0] + s[1] + 1) >> 1, scale)); + dst[1] = STATIC_CAST(uint8_t, C16TO8((s[2] + s[3] + 1) >> 1, scale)); + dst += 2; + s += 4; + } + if (dst_width & 1) { + dst[0] = STATIC_CAST(uint8_t, C16TO8((s[0] + s[1] + 1) >> 1, scale)); + dst += 1; + s += 2; + } + dst[0] = STATIC_CAST(uint8_t, C16TO8(s[0], scale)); +} + void ScaleRowDown2Box_C(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst, @@ -245,6 +294,36 @@ void ScaleRowDown2Box_16To8_C(const uint16_t* src_ptr, } } +void ScaleRowDown2Box_16To8_Odd_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width, + int scale) { + const uint16_t* s = src_ptr; + const uint16_t* t = src_ptr + src_stride; + int x; + assert(scale >= 256); + assert(scale <= 32768); + dst_width -= 1; + for (x = 0; x < dst_width - 1; x += 2) { + dst[0] = STATIC_CAST(uint8_t, + C16TO8((s[0] + s[1] + t[0] + t[1] + 2) >> 2, scale)); + dst[1] = STATIC_CAST(uint8_t, + C16TO8((s[2] + s[3] + t[2] + t[3] + 2) >> 2, scale)); + dst += 2; + s += 4; + t += 4; + } + if (dst_width & 1) { + dst[0] = STATIC_CAST(uint8_t, + C16TO8((s[0] + s[1] + t[0] + t[1] + 2) >> 2, scale)); + dst += 1; + s += 2; + t += 2; + } + dst[0] = STATIC_CAST(uint8_t, C16TO8((s[0] + t[0] + 1) >> 1, scale)); +} + void ScaleRowDown4_C(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst, @@ -1554,7 +1633,7 @@ void ScalePlaneVertical(int src_height, enum FilterMode filtering) { // TODO(fbarchard): Allow higher bpp. int dst_width_bytes = dst_width * bpp; - void (*InterpolateRow)(uint8_t* dst_argb, const uint8_t* src_argb, + void (*InterpolateRow)(uint8_t * dst_argb, const uint8_t* src_argb, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_C; const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0; @@ -1633,7 +1712,7 @@ void ScalePlaneVertical_16(int src_height, enum FilterMode filtering) { // TODO(fbarchard): Allow higher wpp. int dst_width_words = dst_width * wpp; - void (*InterpolateRow)(uint16_t* dst_argb, const uint16_t* src_argb, + void (*InterpolateRow)(uint16_t * dst_argb, const uint16_t* src_argb, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_16_C; const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0; @@ -1712,7 +1791,7 @@ void ScalePlaneVertical_16To8(int src_height, // TODO(fbarchard): Allow higher wpp. int dst_width_words = dst_width * wpp; // TODO(https://crbug.com/libyuv/931): Add NEON 32 bit and AVX2 versions. - void (*InterpolateRow_16To8)(uint8_t* dst_argb, const uint16_t* src_argb, + void (*InterpolateRow_16To8)(uint8_t * dst_argb, const uint16_t* src_argb, ptrdiff_t src_stride, int scale, int dst_width, int source_y_fraction) = InterpolateRow_16To8_C; const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;