1 /* 2 * Copyright (c) 2016 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 "third_party/googletest/src/include/gtest/gtest.h" 12 13 #include "./vpx_config.h" 14 #include "vpx/vp8cx.h" 15 #include "vpx/vpx_encoder.h" 16 17 namespace { 18 19 #define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0])) 20 21 TEST(EncodeAPI, InvalidParams) { 22 static const vpx_codec_iface_t *kCodecs[] = { 23 #if CONFIG_VP8_ENCODER 24 &vpx_codec_vp8_cx_algo, 25 #endif 26 #if CONFIG_VP9_ENCODER 27 &vpx_codec_vp9_cx_algo, 28 #endif 29 }; 30 uint8_t buf[1] = { 0 }; 31 vpx_image_t img; 32 vpx_codec_ctx_t enc; 33 vpx_codec_enc_cfg_t cfg; 34 35 EXPECT_EQ(&img, vpx_img_wrap(&img, VPX_IMG_FMT_I420, 1, 1, 1, buf)); 36 37 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_enc_init(NULL, NULL, NULL, 0)); 38 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_enc_init(&enc, NULL, NULL, 0)); 39 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, NULL, 0, 0, 0, 0)); 40 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, &img, 0, 0, 0, 0)); 41 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL)); 42 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, 43 vpx_codec_enc_config_default(NULL, NULL, 0)); 44 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, 45 vpx_codec_enc_config_default(NULL, &cfg, 0)); 46 EXPECT_TRUE(vpx_codec_error(NULL) != NULL); 47 48 for (int i = 0; i < NELEMENTS(kCodecs); ++i) { 49 SCOPED_TRACE(vpx_codec_iface_name(kCodecs[i])); 50 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, 51 vpx_codec_enc_init(NULL, kCodecs[i], NULL, 0)); 52 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, 53 vpx_codec_enc_init(&enc, kCodecs[i], NULL, 0)); 54 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, 55 vpx_codec_enc_config_default(kCodecs[i], &cfg, 1)); 56 57 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(kCodecs[i], &cfg, 0)); 58 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, kCodecs[i], &cfg, 0)); 59 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, NULL, 0, 0, 0, 0)); 60 61 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc)); 62 } 63 } 64 65 TEST(EncodeAPI, HighBitDepthCapability) { 66 // VP8 should not claim VP9 HBD as a capability. 67 #if CONFIG_VP8_ENCODER 68 const vpx_codec_caps_t vp8_caps = vpx_codec_get_caps(&vpx_codec_vp8_cx_algo); 69 EXPECT_EQ(vp8_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0); 70 #endif 71 72 #if CONFIG_VP9_ENCODER 73 const vpx_codec_caps_t vp9_caps = vpx_codec_get_caps(&vpx_codec_vp9_cx_algo); 74 #if CONFIG_VP9_HIGHBITDEPTH 75 EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, VPX_CODEC_CAP_HIGHBITDEPTH); 76 #else 77 EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0); 78 #endif 79 #endif 80 } 81 82 #if CONFIG_VP8_ENCODER 83 TEST(EncodeAPI, ImageSizeSetting) { 84 const int width = 711; 85 const int height = 360; 86 const int bps = 12; 87 vpx_image_t img; 88 vpx_codec_ctx_t enc; 89 vpx_codec_enc_cfg_t cfg; 90 uint8_t *img_buf = reinterpret_cast<uint8_t *>( 91 calloc(width * height * bps / 8, sizeof(*img_buf))); 92 vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &cfg, 0); 93 94 cfg.g_w = width; 95 cfg.g_h = height; 96 97 vpx_img_wrap(&img, VPX_IMG_FMT_I420, width, height, 1, img_buf); 98 99 vpx_codec_enc_init(&enc, vpx_codec_vp8_cx(), &cfg, 0); 100 101 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, &img, 0, 1, 0, 0)); 102 103 free(img_buf); 104 105 vpx_codec_destroy(&enc); 106 } 107 #endif 108 109 // Set up 2 spatial streams with 2 temporal layers per stream, and generate 110 // invalid configuration by setting the temporal layer rate allocation 111 // (ts_target_bitrate[]) to 0 for both layers. This should fail independent of 112 // CONFIG_MULTI_RES_ENCODING. 113 TEST(EncodeAPI, MultiResEncode) { 114 static const vpx_codec_iface_t *kCodecs[] = { 115 #if CONFIG_VP8_ENCODER 116 &vpx_codec_vp8_cx_algo, 117 #endif 118 #if CONFIG_VP9_ENCODER 119 &vpx_codec_vp9_cx_algo, 120 #endif 121 }; 122 const int width = 1280; 123 const int height = 720; 124 const int width_down = width / 2; 125 const int height_down = height / 2; 126 const int target_bitrate = 1000; 127 const int framerate = 30; 128 129 for (int c = 0; c < NELEMENTS(kCodecs); ++c) { 130 const vpx_codec_iface_t *const iface = kCodecs[c]; 131 vpx_codec_ctx_t enc[2]; 132 vpx_codec_enc_cfg_t cfg[2]; 133 vpx_rational_t dsf[2] = { { 2, 1 }, { 2, 1 } }; 134 135 memset(enc, 0, sizeof(enc)); 136 137 for (int i = 0; i < 2; i++) { 138 vpx_codec_enc_config_default(iface, &cfg[i], 0); 139 } 140 141 /* Highest-resolution encoder settings */ 142 cfg[0].g_w = width; 143 cfg[0].g_h = height; 144 cfg[0].rc_dropframe_thresh = 0; 145 cfg[0].rc_end_usage = VPX_CBR; 146 cfg[0].rc_resize_allowed = 0; 147 cfg[0].rc_min_quantizer = 2; 148 cfg[0].rc_max_quantizer = 56; 149 cfg[0].rc_undershoot_pct = 100; 150 cfg[0].rc_overshoot_pct = 15; 151 cfg[0].rc_buf_initial_sz = 500; 152 cfg[0].rc_buf_optimal_sz = 600; 153 cfg[0].rc_buf_sz = 1000; 154 cfg[0].g_error_resilient = 1; /* Enable error resilient mode */ 155 cfg[0].g_lag_in_frames = 0; 156 157 cfg[0].kf_mode = VPX_KF_AUTO; 158 cfg[0].kf_min_dist = 3000; 159 cfg[0].kf_max_dist = 3000; 160 161 cfg[0].rc_target_bitrate = target_bitrate; /* Set target bitrate */ 162 cfg[0].g_timebase.num = 1; /* Set fps */ 163 cfg[0].g_timebase.den = framerate; 164 165 memcpy(&cfg[1], &cfg[0], sizeof(cfg[0])); 166 cfg[1].rc_target_bitrate = 500; 167 cfg[1].g_w = width_down; 168 cfg[1].g_h = height_down; 169 170 for (int i = 0; i < 2; i++) { 171 cfg[i].ts_number_layers = 2; 172 cfg[i].ts_periodicity = 2; 173 cfg[i].ts_rate_decimator[0] = 2; 174 cfg[i].ts_rate_decimator[1] = 1; 175 cfg[i].ts_layer_id[0] = 0; 176 cfg[i].ts_layer_id[1] = 1; 177 // Invalid parameters. 178 cfg[i].ts_target_bitrate[0] = 0; 179 cfg[i].ts_target_bitrate[1] = 0; 180 } 181 182 // VP9 should report incapable, VP8 invalid for all configurations. 183 const char kVP9Name[] = "WebM Project VP9"; 184 const bool is_vp9 = strncmp(kVP9Name, vpx_codec_iface_name(iface), 185 sizeof(kVP9Name) - 1) == 0; 186 EXPECT_EQ(is_vp9 ? VPX_CODEC_INCAPABLE : VPX_CODEC_INVALID_PARAM, 187 vpx_codec_enc_init_multi(&enc[0], iface, &cfg[0], 2, 0, &dsf[0])); 188 189 for (int i = 0; i < 2; i++) { 190 vpx_codec_destroy(&enc[i]); 191 } 192 } 193 } 194 195 } // namespace 196