|  | /* | 
|  | *  Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  |  | 
|  | #include <math.h> | 
|  | #include <stddef.h> | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  | #include <sys/types.h> | 
|  |  | 
|  | #include "third_party/googletest/src/include/gtest/gtest.h" | 
|  | #include "vpx/vpx_integer.h" | 
|  | #include "vpx_mem/vpx_mem.h" | 
|  | extern "C" { | 
|  | #include "vp8/encoder/onyx_int.h" | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | TEST(Vp8RoiMapTest, ParameterCheck) { | 
|  | int delta_q[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 }; | 
|  | int delta_lf[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 }; | 
|  | unsigned int threshold[MAX_MB_SEGMENTS] = { 0, 100, 200, 300 }; | 
|  |  | 
|  | const int internalq_trans[] = { | 
|  | 0,   1,  2,  3,  4,  5,  7,  8, | 
|  | 9,  10, 12, 13, 15, 17, 18, 19, | 
|  | 20,  21, 23, 24, 25, 26, 27, 28, | 
|  | 29,  30, 31, 33, 35, 37, 39, 41, | 
|  | 43,  45, 47, 49, 51, 53, 55, 57, | 
|  | 59,  61, 64, 67, 70, 73, 76, 79, | 
|  | 82,  85, 88, 91, 94, 97, 100, 103, | 
|  | 106, 109, 112, 115, 118, 121, 124, 127, | 
|  | }; | 
|  |  | 
|  | // Initialize elements of cpi with valid defaults. | 
|  | VP8_COMP cpi; | 
|  | cpi.mb.e_mbd.mb_segement_abs_delta = SEGMENT_DELTADATA; | 
|  | cpi.cyclic_refresh_mode_enabled = 0; | 
|  | cpi.mb.e_mbd.segmentation_enabled = 0; | 
|  | cpi.mb.e_mbd.update_mb_segmentation_map = 0; | 
|  | cpi.mb.e_mbd.update_mb_segmentation_data = 0; | 
|  | cpi.common.mb_rows = 240 >> 4; | 
|  | cpi.common.mb_cols = 320 >> 4; | 
|  | const int mbs = (cpi.common.mb_rows * cpi.common.mb_cols); | 
|  | vpx_memset(cpi.segment_feature_data, 0, sizeof(cpi.segment_feature_data)); | 
|  |  | 
|  | // Segment map | 
|  | cpi.segmentation_map = reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1)); | 
|  |  | 
|  | // Allocate memory for the source memory map. | 
|  | unsigned char *roi_map = | 
|  | reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1)); | 
|  | vpx_memset(&roi_map[mbs >> 2], 1, (mbs >> 2)); | 
|  | vpx_memset(&roi_map[mbs >> 1], 2, (mbs >> 2)); | 
|  | vpx_memset(&roi_map[mbs -(mbs >> 2)], 3, (mbs >> 2)); | 
|  |  | 
|  | // Do a test call with valid parameters. | 
|  | int roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, | 
|  | cpi.common.mb_cols, delta_q, delta_lf, | 
|  | threshold); | 
|  | EXPECT_EQ(0, roi_retval) | 
|  | << "vp8_set_roimap roi failed with default test parameters"; | 
|  |  | 
|  | // Check that the values in the cpi structure get set as expected. | 
|  | if (roi_retval == 0) { | 
|  | // Check that the segment map got set. | 
|  | const int mapcompare = memcmp(roi_map, cpi.segmentation_map, mbs); | 
|  | EXPECT_EQ(0, mapcompare) << "segment map error"; | 
|  |  | 
|  | // Check the q deltas (note the need to translate into | 
|  | // the interanl range of 0-127. | 
|  | for (int i = 0; i < MAX_MB_SEGMENTS; ++i) { | 
|  | const int transq = internalq_trans[abs(delta_q[i])]; | 
|  | if (abs(cpi.segment_feature_data[MB_LVL_ALT_Q][i]) != transq) { | 
|  | EXPECT_EQ(transq, cpi.segment_feature_data[MB_LVL_ALT_Q][i]) | 
|  | << "segment delta_q  error"; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Check the loop filter deltas | 
|  | for (int i = 0; i < MAX_MB_SEGMENTS; ++i) { | 
|  | if (cpi.segment_feature_data[MB_LVL_ALT_LF][i] != delta_lf[i]) { | 
|  | EXPECT_EQ(delta_lf[i], cpi.segment_feature_data[MB_LVL_ALT_LF][i]) | 
|  | << "segment delta_lf error"; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Check the breakout thresholds | 
|  | for (int i = 0; i < MAX_MB_SEGMENTS; ++i) { | 
|  | unsigned int breakout = | 
|  | static_cast<unsigned int>(cpi.segment_encode_breakout[i]); | 
|  |  | 
|  | if (threshold[i] != breakout) { | 
|  | EXPECT_EQ(threshold[i], breakout) | 
|  | << "breakout threshold error"; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Segmentation, and segmentation update flages should be set. | 
|  | EXPECT_EQ(1, cpi.mb.e_mbd.segmentation_enabled) | 
|  | << "segmentation_enabled error"; | 
|  | EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_map) | 
|  | << "update_mb_segmentation_map error"; | 
|  | EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_data) | 
|  | << "update_mb_segmentation_data error"; | 
|  |  | 
|  |  | 
|  | // Try a range of delta q and lf parameters (some legal, some not) | 
|  | for (int i = 0; i < 1000; ++i) { | 
|  | int rand_deltas[4]; | 
|  | int deltas_valid; | 
|  | rand_deltas[0] = (rand() % 160) - 80; | 
|  | rand_deltas[1] = (rand() % 160) - 80; | 
|  | rand_deltas[2] = (rand() % 160) - 80; | 
|  | rand_deltas[3] = (rand() % 160) - 80; | 
|  |  | 
|  | deltas_valid = ((abs(rand_deltas[0]) <= 63) && | 
|  | (abs(rand_deltas[1]) <= 63) && | 
|  | (abs(rand_deltas[2]) <= 63) && | 
|  | (abs(rand_deltas[3]) <= 63)) ? 0 : -1; | 
|  |  | 
|  | // Test with random delta q values. | 
|  | roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, | 
|  | cpi.common.mb_cols, rand_deltas, | 
|  | delta_lf, threshold); | 
|  | EXPECT_EQ(deltas_valid, roi_retval) << "dq range check error"; | 
|  |  | 
|  | // One delta_q error shown at a time | 
|  | if (deltas_valid != roi_retval) | 
|  | break; | 
|  |  | 
|  | // Test with random loop filter values. | 
|  | roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, | 
|  | cpi.common.mb_cols, delta_q, | 
|  | rand_deltas, threshold); | 
|  | EXPECT_EQ(deltas_valid, roi_retval) << "dlf range check error"; | 
|  |  | 
|  | // One delta loop filter error shown at a time | 
|  | if (deltas_valid != roi_retval) | 
|  | break; | 
|  | } | 
|  |  | 
|  | // Test that we report and error if cyclic refresh is enabled. | 
|  | cpi.cyclic_refresh_mode_enabled = 1; | 
|  | roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, | 
|  | cpi.common.mb_cols, delta_q, | 
|  | delta_lf, threshold); | 
|  | EXPECT_EQ(-1, roi_retval) << "cyclic refresh check error"; | 
|  | cpi.cyclic_refresh_mode_enabled = 0; | 
|  |  | 
|  | // Test invalid number of rows or colums. | 
|  | roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows + 1, | 
|  | cpi.common.mb_cols, delta_q, | 
|  | delta_lf, threshold); | 
|  | EXPECT_EQ(-1, roi_retval) << "MB rows bounds check error"; | 
|  |  | 
|  | roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, | 
|  | cpi.common.mb_cols - 1, delta_q, | 
|  | delta_lf, threshold); | 
|  | EXPECT_EQ(-1, roi_retval) << "MB cols bounds check error"; | 
|  | } | 
|  |  | 
|  | // Free allocated memory | 
|  | if (cpi.segmentation_map) | 
|  | vpx_free(cpi.segmentation_map); | 
|  | if (roi_map) | 
|  | vpx_free(roi_map); | 
|  | }; | 
|  |  | 
|  | }  // namespace |