mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2025-12-07 01:06:46 +08:00
scale with conversion using 2 steps with unittest
a prototype function to implement the yuv to rgb with conversion and scale. replace with 1 step function in future version, using same API. R=harryjin@google.com BUG=libyuv:471 Review URL: https://codereview.chromium.org/1421553016 .
This commit is contained in:
parent
6100f50f13
commit
60adcbaf32
@ -1,6 +1,6 @@
|
|||||||
Name: libyuv
|
Name: libyuv
|
||||||
URL: http://code.google.com/p/libyuv/
|
URL: http://code.google.com/p/libyuv/
|
||||||
Version: 1536
|
Version: 1537
|
||||||
License: BSD
|
License: BSD
|
||||||
License File: LICENSE
|
License File: LICENSE
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,6 @@ int ARGBScaleClip(const uint8* src_argb, int src_stride_argb,
|
|||||||
int clip_x, int clip_y, int clip_width, int clip_height,
|
int clip_x, int clip_y, int clip_width, int clip_height,
|
||||||
enum FilterMode filtering);
|
enum FilterMode filtering);
|
||||||
|
|
||||||
// TODO(fbarchard): Implement this.
|
|
||||||
// Scale with YUV conversion to ARGB and clipping.
|
// Scale with YUV conversion to ARGB and clipping.
|
||||||
LIBYUV_API
|
LIBYUV_API
|
||||||
int YUVToARGBScaleClip(const uint8* src_y, int src_stride_y,
|
int YUVToARGBScaleClip(const uint8* src_y, int src_stride_y,
|
||||||
|
|||||||
@ -11,6 +11,6 @@
|
|||||||
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
|
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
|
||||||
#define INCLUDE_LIBYUV_VERSION_H_
|
#define INCLUDE_LIBYUV_VERSION_H_
|
||||||
|
|
||||||
#define LIBYUV_VERSION 1536
|
#define LIBYUV_VERSION 1537
|
||||||
|
|
||||||
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
|
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
|
||||||
|
|||||||
@ -847,6 +847,37 @@ int ARGBScale(const uint8* src_argb, int src_stride_argb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scale with YUV conversion to ARGB and clipping.
|
||||||
|
LIBYUV_API
|
||||||
|
int YUVToARGBScaleClip(const uint8* src_y, int src_stride_y,
|
||||||
|
const uint8* src_u, int src_stride_u,
|
||||||
|
const uint8* src_v, int src_stride_v,
|
||||||
|
uint32 src_fourcc,
|
||||||
|
int src_width, int src_height,
|
||||||
|
uint8* dst_argb, int dst_stride_argb,
|
||||||
|
uint32 dst_fourcc,
|
||||||
|
int dst_width, int dst_height,
|
||||||
|
int clip_x, int clip_y, int clip_width, int clip_height,
|
||||||
|
enum FilterMode filtering) {
|
||||||
|
|
||||||
|
uint8* argb_buffer = (uint8*)malloc(src_width * src_height * 4);
|
||||||
|
int r;
|
||||||
|
I420ToARGB(src_y, src_stride_y,
|
||||||
|
src_u, src_stride_u,
|
||||||
|
src_v, src_stride_v,
|
||||||
|
argb_buffer, src_width * 4,
|
||||||
|
src_width, src_height);
|
||||||
|
|
||||||
|
r = ARGBScaleClip(argb_buffer, src_width * 4,
|
||||||
|
src_width, src_height,
|
||||||
|
dst_argb, dst_stride_argb,
|
||||||
|
dst_width, dst_height,
|
||||||
|
clip_x, clip_y, clip_width, clip_height,
|
||||||
|
filtering);
|
||||||
|
free(argb_buffer);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
} // namespace libyuv
|
} // namespace libyuv
|
||||||
|
|||||||
@ -12,8 +12,10 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "libyuv/cpu_id.h"
|
#include "libyuv/cpu_id.h"
|
||||||
|
#include "libyuv/convert.h"
|
||||||
#include "libyuv/scale_argb.h"
|
#include "libyuv/scale_argb.h"
|
||||||
#include "libyuv/row.h"
|
#include "libyuv/row.h"
|
||||||
|
#include "libyuv/video_common.h"
|
||||||
#include "../unit_test/unit_test.h"
|
#include "../unit_test/unit_test.h"
|
||||||
|
|
||||||
namespace libyuv {
|
namespace libyuv {
|
||||||
@ -299,4 +301,156 @@ TEST_SCALETO(ARGBScale, 1280, 720)
|
|||||||
#undef TEST_SCALETO1
|
#undef TEST_SCALETO1
|
||||||
#undef TEST_SCALETO
|
#undef TEST_SCALETO
|
||||||
|
|
||||||
|
// Scale with YUV conversion to ARGB and clipping.
|
||||||
|
LIBYUV_API
|
||||||
|
int YUVToARGBScaleReference2(const uint8* src_y, int src_stride_y,
|
||||||
|
const uint8* src_u, int src_stride_u,
|
||||||
|
const uint8* src_v, int src_stride_v,
|
||||||
|
uint32 src_fourcc,
|
||||||
|
int src_width, int src_height,
|
||||||
|
uint8* dst_argb, int dst_stride_argb,
|
||||||
|
uint32 dst_fourcc,
|
||||||
|
int dst_width, int dst_height,
|
||||||
|
int clip_x, int clip_y,
|
||||||
|
int clip_width, int clip_height,
|
||||||
|
enum FilterMode filtering) {
|
||||||
|
|
||||||
|
uint8* argb_buffer = (uint8*)malloc(src_width * src_height * 4);
|
||||||
|
int r;
|
||||||
|
I420ToARGB(src_y, src_stride_y,
|
||||||
|
src_u, src_stride_u,
|
||||||
|
src_v, src_stride_v,
|
||||||
|
argb_buffer, src_width * 4,
|
||||||
|
src_width, src_height);
|
||||||
|
|
||||||
|
r = ARGBScaleClip(argb_buffer, src_width * 4,
|
||||||
|
src_width, src_height,
|
||||||
|
dst_argb, dst_stride_argb,
|
||||||
|
dst_width, dst_height,
|
||||||
|
clip_x, clip_y, clip_width, clip_height,
|
||||||
|
filtering);
|
||||||
|
free(argb_buffer);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillRamp(uint8* buf, int width, int height, int v, int dx, int dy) {
|
||||||
|
int rv = v;
|
||||||
|
for (int y = 0; y < height; ++y) {
|
||||||
|
for (int x = 0; x < width; ++x) {
|
||||||
|
*buf++ = v;
|
||||||
|
v += dx;
|
||||||
|
if (v < 0 || v > 255) {
|
||||||
|
dx = -dx;
|
||||||
|
v += dx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v = rv + dy;
|
||||||
|
if (v < 0 || v > 255) {
|
||||||
|
dy = -dy;
|
||||||
|
v += dy;
|
||||||
|
}
|
||||||
|
rv = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
|
||||||
|
static int YUVToARGBTestFilter(int src_width, int src_height,
|
||||||
|
int dst_width, int dst_height,
|
||||||
|
FilterMode f, int benchmark_iterations,
|
||||||
|
int disable_cpu_flags, int benchmark_cpu_info) {
|
||||||
|
int64 src_y_plane_size = Abs(src_width) * Abs(src_height);
|
||||||
|
int64 src_uv_plane_size = ((Abs(src_width) + 1) / 2) *
|
||||||
|
((Abs(src_height) + 1) / 2);
|
||||||
|
int src_stride_y = Abs(src_width);
|
||||||
|
int src_stride_uv = (Abs(src_width) + 1) / 2;
|
||||||
|
|
||||||
|
align_buffer_page_end(src_y, src_y_plane_size);
|
||||||
|
align_buffer_page_end(src_u, src_uv_plane_size);
|
||||||
|
align_buffer_page_end(src_v, src_uv_plane_size);
|
||||||
|
|
||||||
|
int64 dst_argb_plane_size = (dst_width) * (dst_height) * 4LL;
|
||||||
|
int dst_stride_argb = (dst_width) * 4;
|
||||||
|
align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
|
||||||
|
align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
|
||||||
|
if (!dst_argb_c || !dst_argb_opt || !src_y || !src_u || !src_v) {
|
||||||
|
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Fill YUV image with continuous ramp, which is less sensitive to
|
||||||
|
// subsampling and filtering differences for test purposes.
|
||||||
|
FillRamp(src_y, Abs(src_width), Abs(src_height), 128, 1, 1);
|
||||||
|
FillRamp(src_u, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 3, 1, 1);
|
||||||
|
FillRamp(src_v, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 4, 1, 1);
|
||||||
|
memset(dst_argb_c, 2, dst_argb_plane_size);
|
||||||
|
memset(dst_argb_opt, 3, dst_argb_plane_size);
|
||||||
|
|
||||||
|
YUVToARGBScaleReference2(src_y, src_stride_y,
|
||||||
|
src_u, src_stride_uv,
|
||||||
|
src_v, src_stride_uv,
|
||||||
|
libyuv::FOURCC_I420,
|
||||||
|
src_width, src_height,
|
||||||
|
dst_argb_c, dst_stride_argb,
|
||||||
|
libyuv::FOURCC_I420,
|
||||||
|
dst_width, dst_height,
|
||||||
|
0, 0, dst_width, dst_height,
|
||||||
|
f);
|
||||||
|
|
||||||
|
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||||
|
YUVToARGBScaleClip(src_y, src_stride_y,
|
||||||
|
src_u, src_stride_uv,
|
||||||
|
src_v, src_stride_uv,
|
||||||
|
libyuv::FOURCC_I420,
|
||||||
|
src_width, src_height,
|
||||||
|
dst_argb_opt, dst_stride_argb,
|
||||||
|
libyuv::FOURCC_I420,
|
||||||
|
dst_width, dst_height,
|
||||||
|
0, 0, dst_width, dst_height,
|
||||||
|
f);
|
||||||
|
}
|
||||||
|
int max_diff = 0;
|
||||||
|
for (int i = 0; i < dst_height; ++i) {
|
||||||
|
for (int j = 0; j < dst_width * 4; ++j) {
|
||||||
|
int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
|
||||||
|
dst_argb_opt[(i * dst_stride_argb) + j]);
|
||||||
|
if (abs_diff > max_diff) {
|
||||||
|
printf("error %d at %d,%d c %d opt %d",
|
||||||
|
abs_diff,
|
||||||
|
j, i,
|
||||||
|
dst_argb_c[(i * dst_stride_argb) + j],
|
||||||
|
dst_argb_opt[(i * dst_stride_argb) + j]);
|
||||||
|
EXPECT_LE(abs_diff, 40);
|
||||||
|
max_diff = abs_diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_aligned_buffer_page_end(dst_argb_c);
|
||||||
|
free_aligned_buffer_page_end(dst_argb_opt);
|
||||||
|
free_aligned_buffer_page_end(src_y);
|
||||||
|
free_aligned_buffer_page_end(src_u);
|
||||||
|
free_aligned_buffer_page_end(src_v);
|
||||||
|
return max_diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LibYUVScaleTest, YUVToRGBScaleUp) {
|
||||||
|
int diff = YUVToARGBTestFilter(benchmark_width_, benchmark_height_,
|
||||||
|
benchmark_width_ * 3 / 2,
|
||||||
|
benchmark_height_ * 3 / 2,
|
||||||
|
libyuv::kFilterBilinear,
|
||||||
|
benchmark_iterations_,
|
||||||
|
disable_cpu_flags_, benchmark_cpu_info_);
|
||||||
|
EXPECT_LE(diff, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LibYUVScaleTest, YUVToRGBScaleDown) {
|
||||||
|
int diff = YUVToARGBTestFilter(benchmark_width_ * 3 / 2,
|
||||||
|
benchmark_height_ * 3 / 2,
|
||||||
|
benchmark_width_, benchmark_height_,
|
||||||
|
libyuv::kFilterBilinear,
|
||||||
|
benchmark_iterations_,
|
||||||
|
disable_cpu_flags_, benchmark_cpu_info_);
|
||||||
|
EXPECT_LE(diff, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace libyuv
|
} // namespace libyuv
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user