blob: 01715853808cc22cbd2085fcc1a58afeea14f8ce [file] [log] [blame]
/*
* Copyright (c) 2012-2017 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "test_engine/test.h"
#include <VX/vx.h>
#include <VX/vxu.h>
TESTCASE(ChannelCombine, CT_VXContext, ct_setup_vx_context, 0)
TEST(ChannelCombine, testNodeCreation)
{
vx_context context = context_->vx_context_;
vx_image src1_image = 0, src2_image = 0, src3_image = 0, dst_image = 0;
vx_graph graph = 0;
vx_node node = 0;
ASSERT_VX_OBJECT(src1_image = vxCreateImage(context, 128, 128, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(src2_image = vxCreateImage(context, 128, 128, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(src3_image = vxCreateImage(context, 128, 128, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(dst_image = vxCreateImage(context, 128, 128, VX_DF_IMAGE_RGB), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH);
ASSERT_VX_OBJECT(node = vxChannelCombineNode(graph, src1_image, src2_image, src3_image, NULL, dst_image), VX_TYPE_NODE);
VX_CALL(vxVerifyGraph(graph));
VX_CALL(vxReleaseNode(&node));
VX_CALL(vxReleaseGraph(&graph));
VX_CALL(vxReleaseImage(&dst_image));
VX_CALL(vxReleaseImage(&src1_image));
VX_CALL(vxReleaseImage(&src2_image));
VX_CALL(vxReleaseImage(&src3_image));
ASSERT(node == 0);
ASSERT(graph == 0);
ASSERT(dst_image == 0);
ASSERT(src1_image == 0);
ASSERT(src2_image == 0);
ASSERT(src3_image == 0);
}
static CT_Image channel_combine_image_generate_random(int width, int height, vx_df_image format)
{
CT_Image image;
ASSERT_NO_FAILURE_(return 0,
image = ct_allocate_ct_image_random(width, height, format, &CT()->seed_, 0, 256));
return image;
}
static void channel_combine_fill_chanel(CT_Image src, vx_enum channel, CT_Image dst)
{
uint8_t *dst_base = NULL;
int x, y;
int plane, component;
int x_subsampling = ct_image_get_channel_subsampling_x(dst, channel);
int y_subsampling = ct_image_get_channel_subsampling_y(dst, channel);
int xstep = ct_image_get_channel_step_x(dst, channel);
int ystep = ct_image_get_channel_step_y(dst, channel);
int src_width = dst->width / x_subsampling;
int src_height = dst->height / y_subsampling;
// Check that src was subsampled (by spec)
ASSERT_EQ_INT(src_width, src->width);
ASSERT_EQ_INT(src_height, src->height);
ASSERT_NO_FAILURE(plane = ct_image_get_channel_plane(dst, channel));
ASSERT_NO_FAILURE(component = ct_image_get_channel_component(dst, channel));
ASSERT(dst_base = ct_image_get_plane_base(dst, plane));
for (y = 0; y < src_height; y++)
{
for (x = 0; x < src_width; x++)
{
uint8_t *src_data = CT_IMAGE_DATA_PTR_8U(src, x, y);
uint8_t *dst_data = dst_base + (x * xstep) + (y * ystep);
dst_data[component] = *src_data;
}
}
return;
}
static CT_Image channel_combine_create_reference_image(CT_Image src1, CT_Image src2, CT_Image src3, CT_Image src4, vx_df_image format)
{
CT_Image dst = NULL;
ASSERT_(return NULL, src1);
ASSERT_NO_FAILURE_(return NULL, dst = ct_allocate_image(src1->width, src1->height, format));
switch (format)
{
case VX_DF_IMAGE_RGB:
case VX_DF_IMAGE_RGBX:
ASSERT_(return NULL, src1);
ASSERT_(return NULL, src2);
ASSERT_(return NULL, src3);
if (format == VX_DF_IMAGE_RGB)
ASSERT_(return NULL, src4 == NULL);
ASSERT_NO_FAILURE_(return NULL, channel_combine_fill_chanel(src1, VX_CHANNEL_R, dst));
ASSERT_NO_FAILURE_(return NULL, channel_combine_fill_chanel(src2, VX_CHANNEL_G, dst));
ASSERT_NO_FAILURE_(return NULL, channel_combine_fill_chanel(src3, VX_CHANNEL_B, dst));
if (format == VX_DF_IMAGE_RGBX)
ASSERT_NO_FAILURE_(return NULL, channel_combine_fill_chanel(src4, VX_CHANNEL_A, dst));
return dst;
case VX_DF_IMAGE_NV12:
case VX_DF_IMAGE_NV21:
case VX_DF_IMAGE_UYVY:
case VX_DF_IMAGE_YUYV:
case VX_DF_IMAGE_IYUV:
case VX_DF_IMAGE_YUV4:
ASSERT_(return NULL, src1);
ASSERT_(return NULL, src2);
ASSERT_(return NULL, src3);
ASSERT_(return NULL, src4 == NULL);
ASSERT_NO_FAILURE_(return NULL, channel_combine_fill_chanel(src1, VX_CHANNEL_Y, dst));
ASSERT_NO_FAILURE_(return NULL, channel_combine_fill_chanel(src2, VX_CHANNEL_U, dst));
ASSERT_NO_FAILURE_(return NULL, channel_combine_fill_chanel(src3, VX_CHANNEL_V, dst));
return dst;
}
CT_FAIL_(return NULL, "Not supported");
}
static void channel_combine_check(CT_Image src1, CT_Image src2, CT_Image src3, CT_Image src4, CT_Image dst)
{
CT_Image dst_ref = NULL;
ASSERT_NO_FAILURE(dst_ref = channel_combine_create_reference_image(src1, src2, src3, src4, dst->format));
EXPECT_EQ_CTIMAGE(dst_ref, dst);
#if 0
if (CT_HasFailure())
{
#define DUMP_SRC(i) \
if (src##i) \
{ \
printf("=== SRC" #i " ===\n"); \
ct_dump_image_info(src##i); \
}
DUMP_SRC(1) DUMP_SRC(2) DUMP_SRC(3) DUMP_SRC(4)
#undef DUMP_SRC
printf("=== DST ===\n");
ct_dump_image_info(dst);
printf("=== EXPECTED ===\n");
ct_dump_image_info(dst_ref);
}
#endif
}
typedef struct {
const char* testName;
vx_df_image dst_format;
int width, height;
} Arg;
#define ADD_CASE(testArgName, nextmacro, format, ...) \
CT_EXPAND(nextmacro(testArgName "/" #format, __VA_ARGS__, format))
#define ADD_CASES(testArgName, nextmacro, ...) \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_RGB, __VA_ARGS__), \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_RGBX, __VA_ARGS__), \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_NV12, __VA_ARGS__), \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_NV21, __VA_ARGS__), \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_UYVY, __VA_ARGS__), \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_YUYV, __VA_ARGS__), \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_IYUV, __VA_ARGS__), \
ADD_CASE(testArgName, nextmacro, VX_DF_IMAGE_YUV4, __VA_ARGS__), \
#define ADD_SIZE(testArgName, nextmacro, ...) \
CT_EXPAND(nextmacro(testArgName "/sz=16x16", __VA_ARGS__, 16, 16))
#define ChannelCombine_PARAMETERS \
CT_GENERATE_PARAMETERS("randomInput", ADD_CASES, ADD_SIZE, ARG)
TEST_WITH_ARG(ChannelCombine, testGraphProcessing, Arg,
ChannelCombine_PARAMETERS
)
{
vx_context context = context_->vx_context_;
vx_image src_image[4] = {0, 0, 0, 0};
vx_image dst_image = 0;
vx_graph graph = 0;
vx_node node = 0;
int channels = 0, i;
CT_Image src[4] = {NULL, NULL, NULL, NULL};
CT_Image dst = NULL, dst_dummy = NULL;
vx_enum channel_ref;
ASSERT_NO_FAILURE(dst_dummy = ct_allocate_image(4, 4, arg_->dst_format));
ASSERT_NO_FAILURE(channels = ct_get_num_channels(arg_->dst_format));
channel_ref = (arg_->dst_format==VX_DF_IMAGE_RGB)||(arg_->dst_format==VX_DF_IMAGE_RGBX)?VX_CHANNEL_R:VX_CHANNEL_Y;
for (i = 0; i < channels; i++)
{
int w = arg_->width / ct_image_get_channel_subsampling_x(dst_dummy, channel_ref + i);
int h = arg_->height / ct_image_get_channel_subsampling_y(dst_dummy, channel_ref + i);
ASSERT_NO_FAILURE(src[i] = channel_combine_image_generate_random(w, h, VX_DF_IMAGE_U8));
ASSERT_VX_OBJECT(src_image[i] = ct_image_to_vx_image(src[i], context), VX_TYPE_IMAGE);
}
ASSERT_VX_OBJECT(dst_image = vxCreateImage(context, arg_->width, arg_->height, arg_->dst_format), VX_TYPE_IMAGE);
graph = vxCreateGraph(context);
ASSERT_VX_OBJECT(graph, VX_TYPE_GRAPH);
node = vxChannelCombineNode(graph, src_image[0], src_image[1], src_image[2], src_image[3], dst_image);
ASSERT_VX_OBJECT(node, VX_TYPE_NODE);
VX_CALL(vxVerifyGraph(graph));
VX_CALL(vxProcessGraph(graph));
ASSERT_NO_FAILURE(dst = ct_image_from_vx_image(dst_image));
ASSERT_NO_FAILURE(channel_combine_check(src[0], src[1], src[2], src[3], dst));
VX_CALL(vxReleaseNode(&node));
VX_CALL(vxReleaseGraph(&graph));
ASSERT(node == 0);
ASSERT(graph == 0);
VX_CALL(vxReleaseImage(&dst_image));
ASSERT(dst_image == 0);
for (i = 0; i < channels; i++)
{
VX_CALL(vxReleaseImage(&src_image[i]));
ASSERT(src_image[i] == 0);
}
}
TEST_WITH_ARG(ChannelCombine, testImmediateProcessing, Arg,
ChannelCombine_PARAMETERS
)
{
vx_context context = context_->vx_context_;
vx_image src_image[4] = {0, 0, 0, 0};
vx_image dst_image = 0;
int channels = 0, i;
CT_Image src[4] = {NULL, NULL, NULL, NULL};
CT_Image dst = NULL, dst_dummy = NULL;
vx_enum channel_ref;
ASSERT_NO_FAILURE(dst_dummy = ct_allocate_image(4, 4, arg_->dst_format));
ASSERT_NO_FAILURE(channels = ct_get_num_channels(arg_->dst_format));
channel_ref = (arg_->dst_format==VX_DF_IMAGE_RGB)||(arg_->dst_format==VX_DF_IMAGE_RGBX)?VX_CHANNEL_R:VX_CHANNEL_Y;
for (i = 0; i < channels; i++)
{
int w = arg_->width / ct_image_get_channel_subsampling_x(dst_dummy, channel_ref + i);
int h = arg_->height / ct_image_get_channel_subsampling_y(dst_dummy, channel_ref + i);
ASSERT_NO_FAILURE(src[i] = channel_combine_image_generate_random(w, h, VX_DF_IMAGE_U8));
ASSERT_VX_OBJECT(src_image[i] = ct_image_to_vx_image(src[i], context), VX_TYPE_IMAGE);
}
ASSERT_VX_OBJECT(dst_image = vxCreateImage(context, arg_->width, arg_->height, arg_->dst_format), VX_TYPE_IMAGE);
VX_CALL(vxuChannelCombine(context, src_image[0], src_image[1], src_image[2], src_image[3], dst_image));
ASSERT_NO_FAILURE(dst = ct_image_from_vx_image(dst_image));
ASSERT_NO_FAILURE(channel_combine_check(src[0], src[1], src[2], src[3], dst));
VX_CALL(vxReleaseImage(&dst_image));
ASSERT(dst_image == 0);
for (i = 0; i < channels; i++)
{
VX_CALL(vxReleaseImage(&src_image[i]));
ASSERT(src_image[i] == 0);
}
}
TESTCASE_TESTS(ChannelCombine,
testNodeCreation,
testGraphProcessing,
testImmediateProcessing
)