blob: e9eed087d2f9b7abb802893a234bb9ca504b22d4 [file] [log] [blame]
/*
* Copyright (c) 2020, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <stdbool.h>
#include <cstring>
#include "av1/encoder/interintra_ml_data_collect.h"
#include "test/util.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace {
// Testing infrastructure for the L-shape copy function. In all test
// cases, the source buffer has 256 elements with src_[i] == i.
// If the high-bitdepth version of it is requested, then src16_[i] == (i << 4).
// A high-bitdepth but 8-bit version can be requested with LowbdSrc16,
// which encodes lowbd_src16_[i] == i.
class InterIntraMLDataCollectTest : public ::testing::Test {
protected:
void SetUp() override {
for (int i = 0; i < 256; ++i) {
src_[i] = i;
lowbd_src16_[i] = i;
src16_[i] = i << 4;
}
}
// Get a reference to the buffer, offset so the border is grabbed at a
// negative offset.
const uint8_t *Src(int border) const {
return src_ + border + SrcStride() * border;
}
const uint8_t *Src16(int border) const {
return CONVERT_TO_BYTEPTR(src16_ + border + SrcStride() * border);
}
const uint8_t *LowbdSrc16(int border) const {
return CONVERT_TO_BYTEPTR(lowbd_src16_ + border + SrcStride() * border);
}
int SrcStride() const { return 16; }
private:
uint8_t src_[256];
uint16_t src16_[256];
uint16_t lowbd_src16_[256];
};
// 4x8 block with a 1 pixel border.
TEST_F(InterIntraMLDataCollectTest, ComputeLShape4x8) {
const int border = 1;
const int width = 4;
const int height = 8;
uint8_t dst[13];
// Low-bitdepth test.
int bitdepth = 8;
bool is_src_hbd = false;
av1_interintra_ml_data_collect_copy_intrapred_lshape(
dst, Src(border), SrcStride(), width, height, border, bitdepth,
is_src_hbd);
ASSERT_EQ(SrcStride(), 16);
/* clang-format off */
uint8_t expected[13] = { 0, 1, 2, 3, 4,
16,
32,
48,
64,
80,
96,
112,
128 };
/* clang-format on */
ASSERT_EQ(0, memcmp(expected, dst, 13));
// Same results expected if the pipeline is high bit-depth but the
// actual data is 8-bit.
memset(dst, 0, 13);
ASSERT_NE(0, memcmp(expected, dst, 13));
is_src_hbd = true;
av1_interintra_ml_data_collect_copy_intrapred_lshape(
dst, LowbdSrc16(border), SrcStride(), width, height, border, bitdepth,
is_src_hbd);
ASSERT_EQ(0, memcmp(expected, dst, 13));
// High-bitdepth test.
uint16_t expected16[13];
for (int i = 0; i < 13; ++i) {
expected16[i] = expected[i] << 4;
}
bitdepth = 12;
is_src_hbd = true;
uint8_t dst16[26];
av1_interintra_ml_data_collect_copy_intrapred_lshape(
dst16, Src16(border), SrcStride(), width, height, border, bitdepth,
is_src_hbd);
ASSERT_EQ(0, memcmp(expected16, dst16, 26));
}
// 4x4 block with a 4 pixel border, low bitdepth.
TEST_F(InterIntraMLDataCollectTest, ComputeLShape4x4) {
const int border = 4;
const int width = 4;
const int height = 4;
uint8_t dst[48];
int bitdepth = 8;
bool is_src_hbd = false;
av1_interintra_ml_data_collect_copy_intrapred_lshape(
dst, Src(border), SrcStride(), width, height, border, bitdepth,
is_src_hbd);
ASSERT_EQ(SrcStride(), 16);
/* clang-format off */
uint8_t expected[48] = { 0, 1, 2, 3, 4, 5, 6, 7,
16, 17, 18, 19, 20, 21, 22, 23,
32, 33, 34, 35, 36, 37, 38, 39,
48, 49, 50, 51, 52, 53, 54, 55,
64, 65, 66, 67,
80, 81, 82, 83,
96, 97, 98, 99,
112, 113, 114, 115 };
/* clang-format on */
ASSERT_EQ(0, memcmp(expected, dst, 48));
// Same results expected if the pipeline is high bit-depth but the
// actual data is 8-bit.
memset(dst, 0, 48);
ASSERT_NE(0, memcmp(expected, dst, 48));
is_src_hbd = true;
av1_interintra_ml_data_collect_copy_intrapred_lshape(
dst, LowbdSrc16(border), SrcStride(), width, height, border, bitdepth,
is_src_hbd);
ASSERT_EQ(0, memcmp(expected, dst, 48));
// High-bitdepth test.
uint16_t expected16[48];
for (int i = 0; i < 48; ++i) {
expected16[i] = expected[i] << 4;
}
bitdepth = 12;
is_src_hbd = true;
uint8_t dst16[96];
av1_interintra_ml_data_collect_copy_intrapred_lshape(
dst16, Src16(border), SrcStride(), width, height, border, bitdepth,
is_src_hbd);
ASSERT_EQ(0, memcmp(expected16, dst16, 96));
}
TEST_F(InterIntraMLDataCollectTest, SerializeLowbd) {
/* clang-format off */
uint8_t source_image[] = { 16, 17, 18, 19,
20, 21, 22, 23,
24, 25, 26, 27,
28, 29, 30, 31 };
uint8_t intrapred_lshape[] = { 91, 92, 93, 94, 95,
96,
97,
98,
99 };
uint8_t interpred[] = { 35, 36, 37, 38, 39,
40, 41, 42, 43, 44,
45, 46, 47, 48, 49,
50, 51, 52, 53, 54,
55, 56, 57, 58, 59 };
uint8_t predictor[] = { 60, 61, 62, 63,
64, 65, 66, 67,
68, 69, 70, 71,
72, 73, 74, 75 };
uint8_t expected[91] = { 4 /* width */,
4 /* height */,
2 /* plane */,
8 /* bitdepth */,
1 /* border */,
43, 2, 0, 0, /* x */
26, 0, 0, 0, /* y */
7, 0, 0, 0, /* frame_order_hint */
57, 48, 0, 0, /* lambda */
13 /* base_q */,
/* source_image */
16, 17, 18, 19,
20, 21, 22, 23,
24, 25, 26, 27,
28, 29, 30, 31,
/* intrapred_lshape */
91, 92, 93, 94, 95,
96,
97,
98,
99,
1 /* prediction type */,
/* predictor */
60, 61, 62, 63,
64, 65, 66, 67,
68, 69, 70, 71,
72, 73, 74, 75,
25 /* ref_q */,
/* interpred */
35, 36, 37, 38, 39,
40, 41, 42, 43, 44,
45, 46, 47, 48, 49,
50, 51, 52, 53, 54,
55, 56, 57, 58, 59,
12 /* interintra bias */};
/* clang-format on */
IIMLPlaneInfo info = { .width = 4,
.height = 4,
.plane = 2,
.bitdepth = 8,
.border = 1,
.x = 555,
.y = 26,
.frame_order_hint = 7,
.lambda = 12345,
.base_q = 13,
.source_image = source_image,
.intrapred_lshape = intrapred_lshape,
.prediction_type = 1,
.predictor = predictor,
.ref_q = 25,
.interpred = interpred,
.interintra_bias = 12 };
uint8_t *buf;
size_t buf_size;
av1_interintra_ml_data_collect_serialize(&info, &buf, &buf_size);
ASSERT_EQ(91U, buf_size);
ASSERT_EQ(0, memcmp(expected, buf, buf_size));
free(buf);
}
TEST_F(InterIntraMLDataCollectTest, SerializeHighbd) {
/* clang-format off */
uint16_t source_image[] = { 160, 170,
200, 210,
240, 250,
280, 290 };
uint16_t intrapred_lshape[] = { 91, 92, 930,
960,
970,
980,
99 };
uint16_t interpred[] = { 35, 36, 37,
40, 41, 42,
45, 46, 470,
50, 51, 520,
55, 56, 57 };
uint16_t predictor[] = { 300, 310,
320, 330,
340, 350,
360, 370 };
uint8_t expected[101] = { 2 /* width */,
4 /* height */,
0 /* plane */,
10 /* bitdepth */,
1 /* border */,
43, 2, 0, 0, /* x */
26, 0, 0, 0, /* y */
7, 0, 0, 0, /* frame_order_hint */
57, 48, 0, 0, /* lambda */
13 /* base_q */,
/* source_image */
160, 0, 170, 0,
200, 0, 210, 0,
240, 0, 250, 0,
24, 1, 34, 1,
/* intrapred_lshape */
91, 0, 92, 0, 162, 3,
192, 3,
202, 3,
212, 3,
99, 0,
2 /* prediction type */,
/* predictor */
44, 1, 54, 1,
64, 1, 74, 1,
84, 1, 94, 1,
104, 1, 114, 1,
25 /* ref_q */,
/* interpred */
35, 0, 36, 0, 37, 0,
40, 0, 41, 0, 42, 0,
45, 0, 46, 0, 214, 1,
50, 0, 51, 0, 8, 2,
55, 0, 56, 0, 57, 0,
0 /* interintra-bias */};
/* clang-format on */
IIMLPlaneInfo info = { .width = 2,
.height = 4,
.plane = 0,
.bitdepth = 10,
.border = 1,
.x = 555,
.y = 26,
.frame_order_hint = 7,
.lambda = 12345,
.base_q = 13,
.source_image =
reinterpret_cast<uint8_t *>(source_image),
.intrapred_lshape =
reinterpret_cast<uint8_t *>(intrapred_lshape),
.prediction_type = 2,
.predictor = reinterpret_cast<uint8_t *>(predictor),
.ref_q = 25,
.interpred = reinterpret_cast<uint8_t *>(interpred),
.interintra_bias = 0 };
uint8_t *buf;
size_t buf_size;
av1_interintra_ml_data_collect_serialize(&info, &buf, &buf_size);
ASSERT_EQ(101U, buf_size);
ASSERT_EQ(0, memcmp(expected, buf, buf_size));
free(buf);
}
} // namespace