Я практикую OpenCL, преобразовав rgb в NV12. Я получил сообщение об ошибке сравнения, как показано ниже:
"[Ошибка] не удалось сравнить плоскость Y при x (0) y (1) output_cpu (18) output_cl (16) "
Я использую простой 16x16 RGB-буфер с R=1, G=2, B=3
, как показано ниже:
123 123 123 123 123 ....
123 123 123.............
Может кто-нибудь помочь объяснить причину это ошибка сравнения?
Вот мой тестовый код преобразования процессора
int rgb, r, g, b, y, u, v;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
// src is int rgb buffer
rgb = src[i * width + j];
r = rgb & 0xFF;
g = (rgb >> 8) & 0xFF;
b = (rgb >> 16) & 0xFF;
y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; y = y > 255 ? 255 : (y < 0 ? 0 : y);
u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; u = u > 255 ? 255 : (u < 0 ? 0 : u);
v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128; v = v > 255 ? 255 : (v < 0 ? 0 : v);
// dst is unsigned char YUV buffer
dst[i * width + j] = (unsigned char)y;
}
}
Вот преобразование версии CL
__kernel void rgb_2_nv12(__global unsigned int* src, __global char* dst, uint w, uint h)
{
int x = get_global_id(0);
y = get_global_id(1);
int RGB, R, G, B, Y, U, V;
unsigned int pos;
pos = y * w + x;
half_w = w >> 1;
// src is same int rgb buffer
RGB = src[y * w + x];
R = RGB & 0xff;
G = (RGB >> 8) & 0xff;
B = (RGB >> 16) & 0xff;
Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
Y = Y > 255 ? 255 : (Y < 0 ? 0 : Y);
U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
U = U > 255 ? 255 : (U < 0 ? 0 : U);
V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
V = V > 255 ? 255 : (V < 0 ? 0 : V);
// dst is unsigned char YUV buffer
dst[pos] = (unsigned char)Y;
Вот мои настройки CL:
cl_mem cl_buf_src = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, rgb_size, input_int, &err); // rgb_size = 16x16, unsigned it input_int[rgb_size]
cl_mem cl_buf_dst = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, yuv_size, output_cl, &err); // yuv_size = 1.5 * rgb_size, unsigned char output_cl[yuv_size]
clSetKernelArg(kernel_rgb_2_nv12, 0, sizeof(cl_mem), (void*)&cl_buf_src); // int
clSetKernelArg(kernel_rgb_2_nv12, 1, sizeof(cl_mem), (void*)&cl_buf_dst);
clSetKernelArg(kernel_rgb_2_nv12, 2, sizeof(cl_uint), &w); // 16
clSetKernelArg(kernel_rgb_2_nv12, 3, sizeof(cl_uint), &h); // 16
size_t globalWorkSize[2] = { w, h };
clEnqueueNDRangeKernel(queue, kernel_rgb_2_nv12, 2, NULL, globalWorkSize, NULL, 0, NULL, NULL);