OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2013 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 #include <string> |
| 12 #include "third_party/googletest/src/include/gtest/gtest.h" |
| 13 #include "test/codec_factory.h" |
| 14 #include "test/decode_test_driver.h" |
| 15 #include "test/i420_video_source.h" |
| 16 #include "vpx/svc_context.h" |
| 17 #include "vpx/vp8cx.h" |
| 18 #include "vpx/vpx_encoder.h" |
| 19 |
| 20 namespace { |
| 21 |
| 22 using libvpx_test::CodecFactory; |
| 23 using libvpx_test::Decoder; |
| 24 using libvpx_test::VP9CodecFactory; |
| 25 |
| 26 class SvcTest : public ::testing::Test { |
| 27 protected: |
| 28 static const uint32_t kWidth = 352; |
| 29 static const uint32_t kHeight = 288; |
| 30 |
| 31 SvcTest() |
| 32 : codec_iface_(0), |
| 33 test_file_name_("hantro_collage_w352h288.yuv"), |
| 34 codec_initialized_(false), |
| 35 decoder_(0) { |
| 36 memset(&svc_, 0, sizeof(svc_)); |
| 37 memset(&codec_, 0, sizeof(codec_)); |
| 38 memset(&codec_enc_, 0, sizeof(codec_enc_)); |
| 39 } |
| 40 |
| 41 virtual ~SvcTest() {} |
| 42 |
| 43 virtual void SetUp() { |
| 44 svc_.encoding_mode = INTER_LAYER_PREDICTION_IP; |
| 45 svc_.log_level = SVC_LOG_DEBUG; |
| 46 svc_.log_print = 0; |
| 47 |
| 48 codec_iface_ = vpx_codec_vp9_cx(); |
| 49 const vpx_codec_err_t res = |
| 50 vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0); |
| 51 EXPECT_EQ(VPX_CODEC_OK, res); |
| 52 |
| 53 codec_enc_.g_w = kWidth; |
| 54 codec_enc_.g_h = kHeight; |
| 55 codec_enc_.g_timebase.num = 1; |
| 56 codec_enc_.g_timebase.den = 60; |
| 57 codec_enc_.kf_min_dist = 100; |
| 58 codec_enc_.kf_max_dist = 100; |
| 59 |
| 60 vpx_codec_dec_cfg_t dec_cfg = {0}; |
| 61 VP9CodecFactory codec_factory; |
| 62 decoder_ = codec_factory.CreateDecoder(dec_cfg, 0); |
| 63 } |
| 64 |
| 65 virtual void TearDown() { |
| 66 vpx_svc_release(&svc_); |
| 67 delete(decoder_); |
| 68 if (codec_initialized_) vpx_codec_destroy(&codec_); |
| 69 } |
| 70 |
| 71 SvcContext svc_; |
| 72 vpx_codec_ctx_t codec_; |
| 73 struct vpx_codec_enc_cfg codec_enc_; |
| 74 vpx_codec_iface_t *codec_iface_; |
| 75 std::string test_file_name_; |
| 76 bool codec_initialized_; |
| 77 Decoder *decoder_; |
| 78 }; |
| 79 |
| 80 TEST_F(SvcTest, SvcInit) { |
| 81 // test missing parameters |
| 82 vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_); |
| 83 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 84 res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_); |
| 85 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 86 res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_); |
| 87 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 88 |
| 89 res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL); |
| 90 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 91 |
| 92 svc_.spatial_layers = 6; // too many layers |
| 93 res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_); |
| 94 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 95 |
| 96 svc_.spatial_layers = 0; // use default layers |
| 97 res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_); |
| 98 EXPECT_EQ(VPX_CODEC_OK, res); |
| 99 codec_initialized_ = true; |
| 100 EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers); |
| 101 } |
| 102 |
| 103 TEST_F(SvcTest, InitTwoLayers) { |
| 104 svc_.spatial_layers = 2; |
| 105 vpx_svc_set_scale_factors(&svc_, "4/16,16*16"); // invalid scale values |
| 106 vpx_codec_err_t res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_); |
| 107 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 108 |
| 109 vpx_svc_set_scale_factors(&svc_, "4/16,16/16"); // valid scale values |
| 110 res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_); |
| 111 EXPECT_EQ(VPX_CODEC_OK, res); |
| 112 codec_initialized_ = true; |
| 113 } |
| 114 |
| 115 TEST_F(SvcTest, InvalidOptions) { |
| 116 vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL); |
| 117 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 118 |
| 119 res = vpx_svc_set_options(&svc_, "not-an-option=1"); |
| 120 EXPECT_EQ(VPX_CODEC_OK, res); |
| 121 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 122 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 123 } |
| 124 |
| 125 TEST_F(SvcTest, SetLayersOption) { |
| 126 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "layers=3"); |
| 127 EXPECT_EQ(VPX_CODEC_OK, res); |
| 128 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 129 EXPECT_EQ(VPX_CODEC_OK, res); |
| 130 codec_initialized_ = true; |
| 131 EXPECT_EQ(3, svc_.spatial_layers); |
| 132 } |
| 133 |
| 134 TEST_F(SvcTest, SetEncodingMode) { |
| 135 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "encoding-mode=alt-ip"); |
| 136 EXPECT_EQ(VPX_CODEC_OK, res); |
| 137 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 138 EXPECT_EQ(VPX_CODEC_OK, res); |
| 139 codec_initialized_ = true; |
| 140 EXPECT_EQ(ALT_INTER_LAYER_PREDICTION_IP, svc_.encoding_mode); |
| 141 } |
| 142 |
| 143 TEST_F(SvcTest, SetMultipleOptions) { |
| 144 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "layers=2 encoding-mode=ip"); |
| 145 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 146 EXPECT_EQ(VPX_CODEC_OK, res); |
| 147 codec_initialized_ = true; |
| 148 EXPECT_EQ(2, svc_.spatial_layers); |
| 149 EXPECT_EQ(INTER_LAYER_PREDICTION_IP, svc_.encoding_mode); |
| 150 } |
| 151 |
| 152 TEST_F(SvcTest, SetScaleFactorsOption) { |
| 153 svc_.spatial_layers = 2; |
| 154 vpx_codec_err_t res = |
| 155 vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors"); |
| 156 EXPECT_EQ(VPX_CODEC_OK, res); |
| 157 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 158 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 159 |
| 160 res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3"); |
| 161 EXPECT_EQ(VPX_CODEC_OK, res); |
| 162 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 163 EXPECT_EQ(VPX_CODEC_OK, res); |
| 164 codec_initialized_ = true; |
| 165 } |
| 166 |
| 167 TEST_F(SvcTest, SetQuantizersOption) { |
| 168 svc_.spatial_layers = 2; |
| 169 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "quantizers=not-quantizers"); |
| 170 EXPECT_EQ(VPX_CODEC_OK, res); |
| 171 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 172 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 173 |
| 174 vpx_svc_set_options(&svc_, "quantizers=40,45"); |
| 175 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 176 EXPECT_EQ(VPX_CODEC_OK, res); |
| 177 codec_initialized_ = true; |
| 178 } |
| 179 |
| 180 TEST_F(SvcTest, SetQuantizers) { |
| 181 vpx_codec_err_t res = vpx_svc_set_quantizers(NULL, "40,30"); |
| 182 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 183 |
| 184 res = vpx_svc_set_quantizers(&svc_, NULL); |
| 185 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 186 |
| 187 svc_.spatial_layers = 2; |
| 188 res = vpx_svc_set_quantizers(&svc_, "40"); |
| 189 EXPECT_EQ(VPX_CODEC_OK, res); |
| 190 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 191 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 192 |
| 193 res = vpx_svc_set_quantizers(&svc_, "40,30"); |
| 194 EXPECT_EQ(VPX_CODEC_OK, res); |
| 195 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 196 EXPECT_EQ(VPX_CODEC_OK, res); |
| 197 codec_initialized_ = true; |
| 198 } |
| 199 |
| 200 TEST_F(SvcTest, SetScaleFactors) { |
| 201 vpx_codec_err_t res = vpx_svc_set_scale_factors(NULL, "4/16,16/16"); |
| 202 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 203 |
| 204 res = vpx_svc_set_scale_factors(&svc_, NULL); |
| 205 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 206 |
| 207 svc_.spatial_layers = 2; |
| 208 res = vpx_svc_set_scale_factors(&svc_, "4/16"); |
| 209 EXPECT_EQ(VPX_CODEC_OK, res); |
| 210 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 211 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 212 |
| 213 res = vpx_svc_set_scale_factors(&svc_, "4/16,16/16"); |
| 214 EXPECT_EQ(VPX_CODEC_OK, res); |
| 215 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 216 EXPECT_EQ(VPX_CODEC_OK, res); |
| 217 codec_initialized_ = true; |
| 218 } |
| 219 |
| 220 // Test that decoder can handle an SVC frame as the first frame in a sequence. |
| 221 TEST_F(SvcTest, FirstFrameHasLayers) { |
| 222 svc_.spatial_layers = 2; |
| 223 vpx_svc_set_scale_factors(&svc_, "4/16,16/16"); |
| 224 vpx_svc_set_quantizers(&svc_, "40,30"); |
| 225 |
| 226 vpx_codec_err_t res = |
| 227 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 228 EXPECT_EQ(VPX_CODEC_OK, res); |
| 229 codec_initialized_ = true; |
| 230 |
| 231 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight, |
| 232 codec_enc_.g_timebase.den, |
| 233 codec_enc_.g_timebase.num, 0, 30); |
| 234 video.Begin(); |
| 235 |
| 236 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(), |
| 237 video.duration(), VPX_DL_REALTIME); |
| 238 EXPECT_EQ(VPX_CODEC_OK, res); |
| 239 |
| 240 const vpx_codec_err_t res_dec = decoder_->DecodeFrame( |
| 241 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), |
| 242 vpx_svc_get_frame_size(&svc_)); |
| 243 |
| 244 // this test fails with a decoder error |
| 245 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError(); |
| 246 } |
| 247 |
| 248 TEST_F(SvcTest, EncodeThreeFrames) { |
| 249 svc_.spatial_layers = 2; |
| 250 vpx_svc_set_scale_factors(&svc_, "4/16,16/16"); |
| 251 vpx_svc_set_quantizers(&svc_, "40,30"); |
| 252 |
| 253 vpx_codec_err_t res = |
| 254 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 255 ASSERT_EQ(VPX_CODEC_OK, res); |
| 256 codec_initialized_ = true; |
| 257 |
| 258 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight, |
| 259 codec_enc_.g_timebase.den, |
| 260 codec_enc_.g_timebase.num, 0, 30); |
| 261 // FRAME 0 |
| 262 video.Begin(); |
| 263 // This frame is a keyframe. |
| 264 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(), |
| 265 video.duration(), VPX_DL_REALTIME); |
| 266 ASSERT_EQ(VPX_CODEC_OK, res); |
| 267 EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_)); |
| 268 |
| 269 vpx_codec_err_t res_dec = decoder_->DecodeFrame( |
| 270 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), |
| 271 vpx_svc_get_frame_size(&svc_)); |
| 272 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError(); |
| 273 |
| 274 // FRAME 1 |
| 275 video.Next(); |
| 276 // This is a P-frame. |
| 277 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(), |
| 278 video.duration(), VPX_DL_REALTIME); |
| 279 ASSERT_EQ(VPX_CODEC_OK, res); |
| 280 EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_)); |
| 281 |
| 282 res_dec = decoder_->DecodeFrame( |
| 283 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), |
| 284 vpx_svc_get_frame_size(&svc_)); |
| 285 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError(); |
| 286 |
| 287 // FRAME 2 |
| 288 video.Next(); |
| 289 // This is a P-frame. |
| 290 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(), |
| 291 video.duration(), VPX_DL_REALTIME); |
| 292 ASSERT_EQ(VPX_CODEC_OK, res); |
| 293 EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_)); |
| 294 |
| 295 res_dec = decoder_->DecodeFrame( |
| 296 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), |
| 297 vpx_svc_get_frame_size(&svc_)); |
| 298 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError(); |
| 299 } |
| 300 |
| 301 TEST_F(SvcTest, GetLayerResolution) { |
| 302 svc_.spatial_layers = 2; |
| 303 vpx_svc_set_scale_factors(&svc_, "4/16,8/16"); |
| 304 vpx_svc_set_quantizers(&svc_, "40,30"); |
| 305 |
| 306 vpx_codec_err_t res = |
| 307 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); |
| 308 EXPECT_EQ(VPX_CODEC_OK, res); |
| 309 codec_initialized_ = true; |
| 310 |
| 311 // ensure that requested layer is a valid layer |
| 312 uint32_t layer_width, layer_height; |
| 313 res = vpx_svc_get_layer_resolution(&svc_, svc_.spatial_layers, |
| 314 &layer_width, &layer_height); |
| 315 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 316 |
| 317 res = vpx_svc_get_layer_resolution(NULL, 0, &layer_width, &layer_height); |
| 318 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 319 |
| 320 res = vpx_svc_get_layer_resolution(&svc_, 0, NULL, &layer_height); |
| 321 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 322 |
| 323 res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, NULL); |
| 324 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); |
| 325 |
| 326 res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, &layer_height); |
| 327 EXPECT_EQ(VPX_CODEC_OK, res); |
| 328 EXPECT_EQ(kWidth * 4 / 16, layer_width); |
| 329 EXPECT_EQ(kHeight * 4 / 16, layer_height); |
| 330 |
| 331 res = vpx_svc_get_layer_resolution(&svc_, 1, &layer_width, &layer_height); |
| 332 EXPECT_EQ(VPX_CODEC_OK, res); |
| 333 EXPECT_EQ(kWidth * 8 / 16, layer_width); |
| 334 EXPECT_EQ(kHeight * 8 / 16, layer_height); |
| 335 } |
| 336 |
| 337 } // namespace |
OLD | NEW |