1/*
2 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12#include <math.h>
13#include <stddef.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <sys/types.h>
18
19#include "third_party/googletest/src/include/gtest/gtest.h"
20#include "test/acm_random.h"
21#include "vp8/encoder/onyx_int.h"
22#include "vpx/vpx_integer.h"
23#include "vpx_mem/vpx_mem.h"
24
25using libvpx_test::ACMRandom;
26
27namespace {
28
29TEST(VP8RoiMapTest, ParameterCheck) {
30  ACMRandom rnd(ACMRandom::DeterministicSeed());
31  int delta_q[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 };
32  int delta_lf[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 };
33  unsigned int threshold[MAX_MB_SEGMENTS] = { 0, 100, 200, 300 };
34
35  const int internalq_trans[] = {
36    0,   1,  2,  3,  4,  5,  7,  8,
37    9,  10, 12, 13, 15, 17, 18, 19,
38    20,  21, 23, 24, 25, 26, 27, 28,
39    29,  30, 31, 33, 35, 37, 39, 41,
40    43,  45, 47, 49, 51, 53, 55, 57,
41    59,  61, 64, 67, 70, 73, 76, 79,
42    82,  85, 88, 91, 94, 97, 100, 103,
43    106, 109, 112, 115, 118, 121, 124, 127,
44  };
45
46  // Initialize elements of cpi with valid defaults.
47  VP8_COMP cpi;
48  cpi.mb.e_mbd.mb_segement_abs_delta = SEGMENT_DELTADATA;
49  cpi.cyclic_refresh_mode_enabled = 0;
50  cpi.mb.e_mbd.segmentation_enabled = 0;
51  cpi.mb.e_mbd.update_mb_segmentation_map = 0;
52  cpi.mb.e_mbd.update_mb_segmentation_data = 0;
53  cpi.common.mb_rows = 240 >> 4;
54  cpi.common.mb_cols = 320 >> 4;
55  const int mbs = (cpi.common.mb_rows * cpi.common.mb_cols);
56  vpx_memset(cpi.segment_feature_data, 0, sizeof(cpi.segment_feature_data));
57
58  // Segment map
59  cpi.segmentation_map = reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1));
60
61  // Allocate memory for the source memory map.
62  unsigned char *roi_map =
63    reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1));
64  vpx_memset(&roi_map[mbs >> 2], 1, (mbs >> 2));
65  vpx_memset(&roi_map[mbs >> 1], 2, (mbs >> 2));
66  vpx_memset(&roi_map[mbs -(mbs >> 2)], 3, (mbs >> 2));
67
68  // Do a test call with valid parameters.
69  int roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
70                                  cpi.common.mb_cols, delta_q, delta_lf,
71                                  threshold);
72  EXPECT_EQ(0, roi_retval)
73        << "vp8_set_roimap roi failed with default test parameters";
74
75  // Check that the values in the cpi structure get set as expected.
76  if (roi_retval == 0) {
77    // Check that the segment map got set.
78    const int mapcompare = memcmp(roi_map, cpi.segmentation_map, mbs);
79    EXPECT_EQ(0, mapcompare) << "segment map error";
80
81    // Check the q deltas (note the need to translate into
82    // the interanl range of 0-127.
83    for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
84      const int transq = internalq_trans[abs(delta_q[i])];
85      if (abs(cpi.segment_feature_data[MB_LVL_ALT_Q][i]) != transq) {
86          EXPECT_EQ(transq, cpi.segment_feature_data[MB_LVL_ALT_Q][i])
87                    << "segment delta_q  error";
88          break;
89      }
90    }
91
92    // Check the loop filter deltas
93    for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
94      if (cpi.segment_feature_data[MB_LVL_ALT_LF][i] != delta_lf[i]) {
95        EXPECT_EQ(delta_lf[i], cpi.segment_feature_data[MB_LVL_ALT_LF][i])
96                  << "segment delta_lf error";
97        break;
98      }
99    }
100
101    // Check the breakout thresholds
102    for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
103      unsigned int breakout =
104        static_cast<unsigned int>(cpi.segment_encode_breakout[i]);
105
106      if (threshold[i] != breakout) {
107        EXPECT_EQ(threshold[i], breakout)
108                  << "breakout threshold error";
109        break;
110      }
111    }
112
113    // Segmentation, and segmentation update flages should be set.
114    EXPECT_EQ(1, cpi.mb.e_mbd.segmentation_enabled)
115              << "segmentation_enabled error";
116    EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_map)
117              << "update_mb_segmentation_map error";
118    EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_data)
119              << "update_mb_segmentation_data error";
120
121
122    // Try a range of delta q and lf parameters (some legal, some not)
123    for (int i = 0; i < 1000; ++i) {
124      int rand_deltas[4];
125      int deltas_valid;
126      rand_deltas[0] = rnd(160) - 80;
127      rand_deltas[1] = rnd(160) - 80;
128      rand_deltas[2] = rnd(160) - 80;
129      rand_deltas[3] = rnd(160) - 80;
130
131      deltas_valid = ((abs(rand_deltas[0]) <= 63) &&
132                      (abs(rand_deltas[1]) <= 63) &&
133                      (abs(rand_deltas[2]) <= 63) &&
134                      (abs(rand_deltas[3]) <= 63)) ? 0 : -1;
135
136      // Test with random delta q values.
137      roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
138                                  cpi.common.mb_cols, rand_deltas,
139                                  delta_lf, threshold);
140      EXPECT_EQ(deltas_valid, roi_retval) << "dq range check error";
141
142      // One delta_q error shown at a time
143      if (deltas_valid != roi_retval)
144        break;
145
146      // Test with random loop filter values.
147      roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
148                                  cpi.common.mb_cols, delta_q,
149                                  rand_deltas, threshold);
150      EXPECT_EQ(deltas_valid, roi_retval) << "dlf range check error";
151
152      // One delta loop filter error shown at a time
153      if (deltas_valid != roi_retval)
154        break;
155    }
156
157    // Test that we report and error if cyclic refresh is enabled.
158    cpi.cyclic_refresh_mode_enabled = 1;
159    roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
160                                cpi.common.mb_cols, delta_q,
161                                delta_lf, threshold);
162    EXPECT_EQ(-1, roi_retval) << "cyclic refresh check error";
163    cpi.cyclic_refresh_mode_enabled = 0;
164
165    // Test invalid number of rows or colums.
166    roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows + 1,
167                                cpi.common.mb_cols, delta_q,
168                                delta_lf, threshold);
169    EXPECT_EQ(-1, roi_retval) << "MB rows bounds check error";
170
171    roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
172                                cpi.common.mb_cols - 1, delta_q,
173                                delta_lf, threshold);
174    EXPECT_EQ(-1, roi_retval) << "MB cols bounds check error";
175  }
176
177  // Free allocated memory
178  if (cpi.segmentation_map)
179    vpx_free(cpi.segmentation_map);
180  if (roi_map)
181    vpx_free(roi_map);
182};
183
184}  // namespace
185