1/* 2 * Copyright (c) 2015 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#include <algorithm> 11#include "third_party/googletest/src/include/gtest/gtest.h" 12#include "test/codec_factory.h" 13#include "test/encode_test_driver.h" 14#include "test/util.h" 15#include "test/y4m_video_source.h" 16 17namespace { 18 19// Check if any pixel in a 16x16 macroblock varies between frames. 20int CheckMb(const vpx_image_t ¤t, const vpx_image_t &previous, int mb_r, 21 int mb_c) { 22 for (int plane = 0; plane < 3; plane++) { 23 int r = 16 * mb_r; 24 int c0 = 16 * mb_c; 25 int r_top = std::min(r + 16, static_cast<int>(current.d_h)); 26 int c_top = std::min(c0 + 16, static_cast<int>(current.d_w)); 27 r = std::max(r, 0); 28 c0 = std::max(c0, 0); 29 if (plane > 0 && current.x_chroma_shift) { 30 c_top = (c_top + 1) >> 1; 31 c0 >>= 1; 32 } 33 if (plane > 0 && current.y_chroma_shift) { 34 r_top = (r_top + 1) >> 1; 35 r >>= 1; 36 } 37 for (; r < r_top; ++r) { 38 for (int c = c0; c < c_top; ++c) { 39 if (current.planes[plane][current.stride[plane] * r + c] != 40 previous.planes[plane][previous.stride[plane] * r + c]) { 41 return 1; 42 } 43 } 44 } 45 } 46 return 0; 47} 48 49void GenerateMap(int mb_rows, int mb_cols, const vpx_image_t ¤t, 50 const vpx_image_t &previous, uint8_t *map) { 51 for (int mb_r = 0; mb_r < mb_rows; ++mb_r) { 52 for (int mb_c = 0; mb_c < mb_cols; ++mb_c) { 53 map[mb_r * mb_cols + mb_c] = CheckMb(current, previous, mb_r, mb_c); 54 } 55 } 56} 57 58const int kAqModeCyclicRefresh = 3; 59 60class ActiveMapRefreshTest 61 : public ::libvpx_test::EncoderTest, 62 public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { 63 protected: 64 ActiveMapRefreshTest() : EncoderTest(GET_PARAM(0)) {} 65 virtual ~ActiveMapRefreshTest() {} 66 67 virtual void SetUp() { 68 InitializeConfig(); 69 SetMode(GET_PARAM(1)); 70 cpu_used_ = GET_PARAM(2); 71 } 72 73 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, 74 ::libvpx_test::Encoder *encoder) { 75 ::libvpx_test::Y4mVideoSource *y4m_video = 76 static_cast<libvpx_test::Y4mVideoSource *>(video); 77 if (video->frame() == 1) { 78 encoder->Control(VP8E_SET_CPUUSED, cpu_used_); 79 encoder->Control(VP9E_SET_AQ_MODE, kAqModeCyclicRefresh); 80 } else if (video->frame() >= 2 && video->img()) { 81 vpx_image_t *current = video->img(); 82 vpx_image_t *previous = y4m_holder_->img(); 83 ASSERT_TRUE(previous != NULL); 84 vpx_active_map_t map = vpx_active_map_t(); 85 const int width = static_cast<int>(current->d_w); 86 const int height = static_cast<int>(current->d_h); 87 const int mb_width = (width + 15) / 16; 88 const int mb_height = (height + 15) / 16; 89 uint8_t *active_map = new uint8_t[mb_width * mb_height]; 90 GenerateMap(mb_height, mb_width, *current, *previous, active_map); 91 map.cols = mb_width; 92 map.rows = mb_height; 93 map.active_map = active_map; 94 encoder->Control(VP8E_SET_ACTIVEMAP, &map); 95 delete[] active_map; 96 } 97 if (video->img()) { 98 y4m_video->SwapBuffers(y4m_holder_); 99 } 100 } 101 102 int cpu_used_; 103 ::libvpx_test::Y4mVideoSource *y4m_holder_; 104}; 105 106TEST_P(ActiveMapRefreshTest, Test) { 107 cfg_.g_lag_in_frames = 0; 108 cfg_.g_profile = 1; 109 cfg_.rc_target_bitrate = 600; 110 cfg_.rc_resize_allowed = 0; 111 cfg_.rc_min_quantizer = 8; 112 cfg_.rc_max_quantizer = 30; 113 cfg_.g_pass = VPX_RC_ONE_PASS; 114 cfg_.rc_end_usage = VPX_CBR; 115 cfg_.kf_max_dist = 90000; 116 117 ::libvpx_test::Y4mVideoSource video("desktop_credits.y4m", 0, 30); 118 ::libvpx_test::Y4mVideoSource video_holder("desktop_credits.y4m", 0, 30); 119 video_holder.Begin(); 120 y4m_holder_ = &video_holder; 121 122 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 123} 124 125VP9_INSTANTIATE_TEST_CASE(ActiveMapRefreshTest, 126 ::testing::Values(::libvpx_test::kRealTime), 127 ::testing::Range(5, 6)); 128} // namespace 129