| /* |
| * 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 "./vpx_config.h" |
| #include "third_party/googletest/src/include/gtest/gtest.h" |
| #include "test/codec_factory.h" |
| #include "test/encode_test_driver.h" |
| #include "test/i420_video_source.h" |
| #include "test/svc_test.h" |
| #include "test/util.h" |
| #include "test/y4m_video_source.h" |
| #include "vp9/common/vp9_onyxc_int.h" |
| #include "vpx/vpx_codec.h" |
| #include "vpx_ports/bitops.h" |
| |
| namespace svc_test { |
| namespace { |
| |
| typedef enum { |
| // Inter-layer prediction is on on all frames. |
| INTER_LAYER_PRED_ON, |
| // Inter-layer prediction is off on all frames. |
| INTER_LAYER_PRED_OFF, |
| // Inter-layer prediction is off on non-key frames and non-sync frames. |
| INTER_LAYER_PRED_OFF_NONKEY, |
| // Inter-layer prediction is on on all frames, but constrained such |
| // that any layer S (> 0) can only predict from previous spatial |
| // layer S-1, from the same superframe. |
| INTER_LAYER_PRED_ON_CONSTRAINED |
| } INTER_LAYER_PRED; |
| |
| class DatarateOnePassCbrSvc : public OnePassCbrSvc { |
| public: |
| explicit DatarateOnePassCbrSvc(const ::libvpx_test::CodecFactory *codec) |
| : OnePassCbrSvc(codec) { |
| inter_layer_pred_mode_ = 0; |
| } |
| |
| protected: |
| virtual ~DatarateOnePassCbrSvc() {} |
| |
| virtual void ResetModel() { |
| last_pts_ = 0; |
| duration_ = 0.0; |
| mismatch_psnr_ = 0.0; |
| mismatch_nframes_ = 0; |
| denoiser_on_ = 0; |
| tune_content_ = 0; |
| base_speed_setting_ = 5; |
| spatial_layer_id_ = 0; |
| temporal_layer_id_ = 0; |
| update_pattern_ = 0; |
| memset(bits_in_buffer_model_, 0, sizeof(bits_in_buffer_model_)); |
| memset(bits_total_, 0, sizeof(bits_total_)); |
| memset(layer_target_avg_bandwidth_, 0, sizeof(layer_target_avg_bandwidth_)); |
| dynamic_drop_layer_ = false; |
| single_layer_resize_ = false; |
| change_bitrate_ = false; |
| last_pts_ref_ = 0; |
| middle_bitrate_ = 0; |
| top_bitrate_ = 0; |
| superframe_count_ = -1; |
| key_frame_spacing_ = 9999; |
| num_nonref_frames_ = 0; |
| layer_framedrop_ = 0; |
| force_key_ = 0; |
| force_key_test_ = 0; |
| insert_layer_sync_ = 0; |
| layer_sync_on_base_ = 0; |
| force_intra_only_frame_ = 0; |
| superframe_has_intra_only_ = 0; |
| use_post_encode_drop_ = 0; |
| denoiser_off_on_ = false; |
| denoiser_enable_layers_ = false; |
| num_resize_down_ = 0; |
| num_resize_up_ = 0; |
| for (int i = 0; i < VPX_MAX_LAYERS; i++) { |
| prev_frame_width[i] = 320; |
| prev_frame_height[i] = 240; |
| } |
| } |
| virtual void BeginPassHook(unsigned int /*pass*/) {} |
| |
| // Example pattern for spatial layers and 2 temporal layers used in the |
| // bypass/flexible mode. The pattern corresponds to the pattern |
| // VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in |
| // non-flexible mode, except that we disable inter-layer prediction. |
| void set_frame_flags_bypass_mode( |
| int tl, int num_spatial_layers, int is_key_frame, |
| vpx_svc_ref_frame_config_t *ref_frame_config) { |
| for (int sl = 0; sl < num_spatial_layers; ++sl) |
| ref_frame_config->update_buffer_slot[sl] = 0; |
| |
| for (int sl = 0; sl < num_spatial_layers; ++sl) { |
| if (tl == 0) { |
| ref_frame_config->lst_fb_idx[sl] = sl; |
| if (sl) { |
| if (is_key_frame) { |
| ref_frame_config->lst_fb_idx[sl] = sl - 1; |
| ref_frame_config->gld_fb_idx[sl] = sl; |
| } else { |
| ref_frame_config->gld_fb_idx[sl] = sl - 1; |
| } |
| } else { |
| ref_frame_config->gld_fb_idx[sl] = 0; |
| } |
| ref_frame_config->alt_fb_idx[sl] = 0; |
| } else if (tl == 1) { |
| ref_frame_config->lst_fb_idx[sl] = sl; |
| ref_frame_config->gld_fb_idx[sl] = |
| VPXMIN(REF_FRAMES - 1, num_spatial_layers + sl - 1); |
| ref_frame_config->alt_fb_idx[sl] = |
| VPXMIN(REF_FRAMES - 1, num_spatial_layers + sl); |
| } |
| if (!tl) { |
| if (!sl) { |
| ref_frame_config->reference_last[sl] = 1; |
| ref_frame_config->reference_golden[sl] = 0; |
| ref_frame_config->reference_alt_ref[sl] = 0; |
| ref_frame_config->update_buffer_slot[sl] |= |
| 1 << ref_frame_config->lst_fb_idx[sl]; |
| } else { |
| if (is_key_frame) { |
| ref_frame_config->reference_last[sl] = 1; |
| ref_frame_config->reference_golden[sl] = 0; |
| ref_frame_config->reference_alt_ref[sl] = 0; |
| ref_frame_config->update_buffer_slot[sl] |= |
| 1 << ref_frame_config->gld_fb_idx[sl]; |
| } else { |
| ref_frame_config->reference_last[sl] = 1; |
| ref_frame_config->reference_golden[sl] = 0; |
| ref_frame_config->reference_alt_ref[sl] = 0; |
| ref_frame_config->update_buffer_slot[sl] |= |
| 1 << ref_frame_config->lst_fb_idx[sl]; |
| } |
| } |
| } else if (tl == 1) { |
| if (!sl) { |
| ref_frame_config->reference_last[sl] = 1; |
| ref_frame_config->reference_golden[sl] = 0; |
| ref_frame_config->reference_alt_ref[sl] = 0; |
| ref_frame_config->update_buffer_slot[sl] |= |
| 1 << ref_frame_config->alt_fb_idx[sl]; |
| } else { |
| ref_frame_config->reference_last[sl] = 1; |
| ref_frame_config->reference_golden[sl] = 0; |
| ref_frame_config->reference_alt_ref[sl] = 0; |
| ref_frame_config->update_buffer_slot[sl] |= |
| 1 << ref_frame_config->alt_fb_idx[sl]; |
| } |
| } |
| } |
| } |
| |
| void CheckLayerRateTargeting(int num_spatial_layers, int num_temporal_layers, |
| double thresh_overshoot, |
| double thresh_undershoot) const { |
| for (int sl = 0; sl < num_spatial_layers; ++sl) |
| for (int tl = 0; tl < num_temporal_layers; ++tl) { |
| const int layer = sl * num_temporal_layers + tl; |
| ASSERT_GE(cfg_.layer_target_bitrate[layer], |
| file_datarate_[layer] * thresh_overshoot) |
| << " The datarate for the file exceeds the target by too much!"; |
| ASSERT_LE(cfg_.layer_target_bitrate[layer], |
| file_datarate_[layer] * thresh_undershoot) |
| << " The datarate for the file is lower than the target by too " |
| "much!"; |
| } |
| } |
| |
| virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, |
| ::libvpx_test::Encoder *encoder) { |
| PreEncodeFrameHookSetup(video, encoder); |
| |
| if (video->frame() == 0) { |
| if (force_intra_only_frame_) { |
| // Decoder sets the color_space for Intra-only frames |
| // to BT_601 (see line 1810 in vp9_decodeframe.c). |
| // So set it here in these tess to avoid encoder-decoder |
| // mismatch check on color space setting. |
| encoder->Control(VP9E_SET_COLOR_SPACE, VPX_CS_BT_601); |
| } |
| encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_); |
| encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_); |
| encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED, inter_layer_pred_mode_); |
| |
| if (layer_framedrop_) { |
| vpx_svc_frame_drop_t svc_drop_frame; |
| svc_drop_frame.framedrop_mode = LAYER_DROP; |
| for (int i = 0; i < number_spatial_layers_; i++) |
| svc_drop_frame.framedrop_thresh[i] = 30; |
| svc_drop_frame.max_consec_drop = 30; |
| encoder->Control(VP9E_SET_SVC_FRAME_DROP_LAYER, &svc_drop_frame); |
| } |
| |
| if (use_post_encode_drop_) { |
| encoder->Control(VP9E_SET_POSTENCODE_DROP, use_post_encode_drop_); |
| } |
| } |
| |
| if (denoiser_off_on_) { |
| encoder->Control(VP9E_SET_AQ_MODE, 3); |
| // Set inter_layer_pred to INTER_LAYER_PRED_OFF_NONKEY (K-SVC). |
| encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED, 2); |
| if (!denoiser_enable_layers_) { |
| if (video->frame() == 0) |
| encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 0); |
| else if (video->frame() == 100) |
| encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 1); |
| } else { |
| // Cumulative bitrates for top spatial layers, for |
| // 3 temporal layers. |
| if (video->frame() == 0) { |
| encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 0); |
| // Change layer bitrates to set top spatial layer to 0. |
| // This is for 3 spatial 3 temporal layers. |
| // This will trigger skip encoding/dropping of top spatial layer. |
| cfg_.rc_target_bitrate -= cfg_.layer_target_bitrate[8]; |
| for (int i = 0; i < 3; i++) |
| bitrate_sl3_[i] = cfg_.layer_target_bitrate[i + 6]; |
| cfg_.layer_target_bitrate[6] = 0; |
| cfg_.layer_target_bitrate[7] = 0; |
| cfg_.layer_target_bitrate[8] = 0; |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 100) { |
| // Change layer bitrates to non-zero on top spatial layer. |
| // This will trigger skip encoding of top spatial layer |
| // on key frame (period = 100). |
| for (int i = 0; i < 3; i++) |
| cfg_.layer_target_bitrate[i + 6] = bitrate_sl3_[i]; |
| cfg_.rc_target_bitrate += cfg_.layer_target_bitrate[8]; |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 120) { |
| // Enable denoiser and top spatial layer after key frame (period is |
| // 100). |
| encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 1); |
| } |
| } |
| } |
| |
| if (update_pattern_ && video->frame() >= 100) { |
| vpx_svc_layer_id_t layer_id; |
| if (video->frame() == 100) { |
| cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; |
| encoder->Config(&cfg_); |
| } |
| // Set layer id since the pattern changed. |
| layer_id.spatial_layer_id = 0; |
| layer_id.temporal_layer_id = (video->frame() % 2 != 0); |
| temporal_layer_id_ = layer_id.temporal_layer_id; |
| for (int i = 0; i < number_spatial_layers_; i++) |
| layer_id.temporal_layer_id_per_spatial[i] = temporal_layer_id_; |
| encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id); |
| set_frame_flags_bypass_mode(layer_id.temporal_layer_id, |
| number_spatial_layers_, 0, &ref_frame_config); |
| encoder->Control(VP9E_SET_SVC_REF_FRAME_CONFIG, &ref_frame_config); |
| } |
| |
| if (change_bitrate_ && video->frame() == 200) { |
| duration_ = (last_pts_ + 1) * timebase_; |
| for (int sl = 0; sl < number_spatial_layers_; ++sl) { |
| for (int tl = 0; tl < number_temporal_layers_; ++tl) { |
| const int layer = sl * number_temporal_layers_ + tl; |
| const double file_size_in_kb = bits_total_[layer] / 1000.; |
| file_datarate_[layer] = file_size_in_kb / duration_; |
| } |
| } |
| |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, |
| 0.78, 1.15); |
| |
| memset(file_datarate_, 0, sizeof(file_datarate_)); |
| memset(bits_total_, 0, sizeof(bits_total_)); |
| int64_t bits_in_buffer_model_tmp[VPX_MAX_LAYERS]; |
| last_pts_ref_ = last_pts_; |
| // Set new target bitarate. |
| cfg_.rc_target_bitrate = cfg_.rc_target_bitrate >> 1; |
| // Buffer level should not reset on dynamic bitrate change. |
| memcpy(bits_in_buffer_model_tmp, bits_in_buffer_model_, |
| sizeof(bits_in_buffer_model_)); |
| AssignLayerBitrates(); |
| memcpy(bits_in_buffer_model_, bits_in_buffer_model_tmp, |
| sizeof(bits_in_buffer_model_)); |
| |
| // Change config to update encoder with new bitrate configuration. |
| encoder->Config(&cfg_); |
| } |
| |
| if (dynamic_drop_layer_ && !single_layer_resize_) { |
| if (video->frame() == 0) { |
| // Change layer bitrates to set top layers to 0. This will trigger skip |
| // encoding/dropping of top two spatial layers. |
| cfg_.rc_target_bitrate -= |
| (cfg_.layer_target_bitrate[1] + cfg_.layer_target_bitrate[2]); |
| middle_bitrate_ = cfg_.layer_target_bitrate[1]; |
| top_bitrate_ = cfg_.layer_target_bitrate[2]; |
| cfg_.layer_target_bitrate[1] = 0; |
| cfg_.layer_target_bitrate[2] = 0; |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 50) { |
| // Change layer bitrates to non-zero on two top spatial layers. |
| // This will trigger skip encoding of top two spatial layers. |
| cfg_.layer_target_bitrate[1] = middle_bitrate_; |
| cfg_.layer_target_bitrate[2] = top_bitrate_; |
| cfg_.rc_target_bitrate += |
| cfg_.layer_target_bitrate[2] + cfg_.layer_target_bitrate[1]; |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 100) { |
| // Change layer bitrates to set top layers to 0. This will trigger skip |
| // encoding/dropping of top two spatial layers. |
| cfg_.rc_target_bitrate -= |
| (cfg_.layer_target_bitrate[1] + cfg_.layer_target_bitrate[2]); |
| middle_bitrate_ = cfg_.layer_target_bitrate[1]; |
| top_bitrate_ = cfg_.layer_target_bitrate[2]; |
| cfg_.layer_target_bitrate[1] = 0; |
| cfg_.layer_target_bitrate[2] = 0; |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 150) { |
| // Change layer bitrate on second layer to non-zero to start |
| // encoding it again. |
| cfg_.layer_target_bitrate[1] = middle_bitrate_; |
| cfg_.rc_target_bitrate += cfg_.layer_target_bitrate[1]; |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 200) { |
| // Change layer bitrate on top layer to non-zero to start |
| // encoding it again. |
| cfg_.layer_target_bitrate[2] = top_bitrate_; |
| cfg_.rc_target_bitrate += cfg_.layer_target_bitrate[2]; |
| encoder->Config(&cfg_); |
| } |
| } else if (dynamic_drop_layer_ && single_layer_resize_) { |
| // Change layer bitrates to set top layers to 0. This will trigger skip |
| // encoding/dropping of top spatial layers. |
| if (video->frame() == 2) { |
| cfg_.rc_target_bitrate -= |
| (cfg_.layer_target_bitrate[1] + cfg_.layer_target_bitrate[2]); |
| middle_bitrate_ = cfg_.layer_target_bitrate[1]; |
| top_bitrate_ = cfg_.layer_target_bitrate[2]; |
| cfg_.layer_target_bitrate[1] = 0; |
| cfg_.layer_target_bitrate[2] = 0; |
| // Set spatial layer 0 to a very low bitrate to trigger resize. |
| cfg_.layer_target_bitrate[0] = 30; |
| cfg_.rc_target_bitrate = cfg_.layer_target_bitrate[0]; |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 100) { |
| // Set base spatial layer to very high to go back up to original size. |
| cfg_.layer_target_bitrate[0] = 400; |
| cfg_.rc_target_bitrate = cfg_.layer_target_bitrate[0]; |
| encoder->Config(&cfg_); |
| } |
| } else if (!dynamic_drop_layer_ && single_layer_resize_) { |
| if (video->frame() == 2) { |
| cfg_.layer_target_bitrate[0] = 30; |
| cfg_.layer_target_bitrate[1] = 50; |
| cfg_.rc_target_bitrate = |
| (cfg_.layer_target_bitrate[0] + cfg_.layer_target_bitrate[1]); |
| encoder->Config(&cfg_); |
| } else if (video->frame() == 160) { |
| cfg_.layer_target_bitrate[0] = 1500; |
| cfg_.layer_target_bitrate[1] = 2000; |
| cfg_.rc_target_bitrate = |
| (cfg_.layer_target_bitrate[0] + cfg_.layer_target_bitrate[1]); |
| encoder->Config(&cfg_); |
| } |
| } |
| if (force_key_test_ && force_key_) frame_flags_ = VPX_EFLAG_FORCE_KF; |
| |
| if (insert_layer_sync_) { |
| vpx_svc_spatial_layer_sync_t svc_layer_sync; |
| svc_layer_sync.base_layer_intra_only = 0; |
| for (int i = 0; i < number_spatial_layers_; i++) |
| svc_layer_sync.spatial_layer_sync[i] = 0; |
| if (force_intra_only_frame_) { |
| superframe_has_intra_only_ = 0; |
| if (video->frame() == 0) { |
| svc_layer_sync.base_layer_intra_only = 1; |
| svc_layer_sync.spatial_layer_sync[0] = 1; |
| encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync); |
| superframe_has_intra_only_ = 1; |
| } else if (video->frame() == 100) { |
| svc_layer_sync.base_layer_intra_only = 1; |
| svc_layer_sync.spatial_layer_sync[0] = 1; |
| encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync); |
| superframe_has_intra_only_ = 1; |
| } |
| } else { |
| layer_sync_on_base_ = 0; |
| if (video->frame() == 150) { |
| svc_layer_sync.spatial_layer_sync[1] = 1; |
| encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync); |
| } else if (video->frame() == 240) { |
| svc_layer_sync.spatial_layer_sync[2] = 1; |
| encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync); |
| } else if (video->frame() == 320) { |
| svc_layer_sync.spatial_layer_sync[0] = 1; |
| layer_sync_on_base_ = 1; |
| encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync); |
| } |
| } |
| } |
| |
| const vpx_rational_t tb = video->timebase(); |
| timebase_ = static_cast<double>(tb.num) / tb.den; |
| duration_ = 0; |
| } |
| |
| vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz, |
| uint32_t sizes[8], int *count) { |
| uint8_t marker; |
| marker = *(data + data_sz - 1); |
| *count = 0; |
| if ((marker & 0xe0) == 0xc0) { |
| const uint32_t frames = (marker & 0x7) + 1; |
| const uint32_t mag = ((marker >> 3) & 0x3) + 1; |
| const size_t index_sz = 2 + mag * frames; |
| // This chunk is marked as having a superframe index but doesn't have |
| // enough data for it, thus it's an invalid superframe index. |
| if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME; |
| { |
| const uint8_t marker2 = *(data + data_sz - index_sz); |
| // This chunk is marked as having a superframe index but doesn't have |
| // the matching marker byte at the front of the index therefore it's an |
| // invalid chunk. |
| if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME; |
| } |
| { |
| uint32_t i, j; |
| const uint8_t *x = &data[data_sz - index_sz + 1]; |
| for (i = 0; i < frames; ++i) { |
| uint32_t this_sz = 0; |
| |
| for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8); |
| sizes[i] = this_sz; |
| } |
| *count = frames; |
| } |
| } |
| return VPX_CODEC_OK; |
| } |
| |
| virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { |
| uint32_t sizes[8] = { 0 }; |
| uint32_t sizes_parsed[8] = { 0 }; |
| int count = 0; |
| int num_layers_encoded = 0; |
| last_pts_ = pkt->data.frame.pts; |
| const bool key_frame = |
| (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false; |
| if (key_frame) { |
| // For test that inserts layer sync frames: requesting a layer_sync on |
| // the base layer must force key frame. So if any key frame occurs after |
| // first superframe it must due to layer sync on base spatial layer. |
| if (superframe_count_ > 0 && insert_layer_sync_ && |
| !force_intra_only_frame_) { |
| ASSERT_EQ(layer_sync_on_base_, 1); |
| } |
| temporal_layer_id_ = 0; |
| superframe_count_ = 0; |
| } |
| parse_superframe_index(static_cast<const uint8_t *>(pkt->data.frame.buf), |
| pkt->data.frame.sz, sizes_parsed, &count); |
| // Count may be less than number of spatial layers because of frame drops. |
| if (number_spatial_layers_ > 1) { |
| for (int sl = 0; sl < number_spatial_layers_; ++sl) { |
| if (pkt->data.frame.spatial_layer_encoded[sl]) { |
| sizes[sl] = sizes_parsed[num_layers_encoded]; |
| num_layers_encoded++; |
| } |
| } |
| } |
| // For superframe with Intra-only count will be +1 larger |
| // because of no-show frame. |
| if (force_intra_only_frame_ && superframe_has_intra_only_) |
| ASSERT_EQ(count, num_layers_encoded + 1); |
| else |
| ASSERT_EQ(count, num_layers_encoded); |
| |
| // In the constrained frame drop mode, if a given spatial is dropped all |
| // upper layers must be dropped too. |
| if (!layer_framedrop_) { |
| int num_layers_dropped = 0; |
| for (int sl = 0; sl < number_spatial_layers_; ++sl) { |
| if (!pkt->data.frame.spatial_layer_encoded[sl]) { |
| // Check that all upper layers are dropped. |
| num_layers_dropped++; |
| for (int sl2 = sl + 1; sl2 < number_spatial_layers_; ++sl2) |
| ASSERT_EQ(pkt->data.frame.spatial_layer_encoded[sl2], 0); |
| } |
| } |
| if (num_layers_dropped == number_spatial_layers_ - 1) |
| force_key_ = 1; |
| else |
| force_key_ = 0; |
| } |
| // Keep track of number of non-reference frames, needed for mismatch check. |
| // Non-reference frames are top spatial and temporal layer frames, |
| // for TL > 0. |
| if (temporal_layer_id_ == number_temporal_layers_ - 1 && |
| temporal_layer_id_ > 0 && |
| pkt->data.frame.spatial_layer_encoded[number_spatial_layers_ - 1]) |
| num_nonref_frames_++; |
| for (int sl = 0; sl < number_spatial_layers_; ++sl) { |
| sizes[sl] = sizes[sl] << 3; |
| // Update the total encoded bits per layer. |
| // For temporal layers, update the cumulative encoded bits per layer. |
| for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) { |
| const int layer = sl * number_temporal_layers_ + tl; |
| bits_total_[layer] += static_cast<int64_t>(sizes[sl]); |
| // Update the per-layer buffer level with the encoded frame size. |
| bits_in_buffer_model_[layer] -= static_cast<int64_t>(sizes[sl]); |
| // There should be no buffer underrun, except on the base |
| // temporal layer, since there may be key frames there. |
| // Fo short key frame spacing, buffer can underrun on individual frames. |
| if (!key_frame && tl > 0 && key_frame_spacing_ < 100) { |
| ASSERT_GE(bits_in_buffer_model_[layer], 0) |
| << "Buffer Underrun at frame " << pkt->data.frame.pts; |
| } |
| } |
| |
| if (!single_layer_resize_) { |
| ASSERT_EQ(pkt->data.frame.width[sl], |
| top_sl_width_ * svc_params_.scaling_factor_num[sl] / |
| svc_params_.scaling_factor_den[sl]); |
| |
| ASSERT_EQ(pkt->data.frame.height[sl], |
| top_sl_height_ * svc_params_.scaling_factor_num[sl] / |
| svc_params_.scaling_factor_den[sl]); |
| } else if (superframe_count_ > 0) { |
| if (pkt->data.frame.width[sl] < prev_frame_width[sl] && |
| pkt->data.frame.height[sl] < prev_frame_height[sl]) |
| num_resize_down_ += 1; |
| if (pkt->data.frame.width[sl] > prev_frame_width[sl] && |
| pkt->data.frame.height[sl] > prev_frame_height[sl]) |
| num_resize_up_ += 1; |
| } |
| prev_frame_width[sl] = pkt->data.frame.width[sl]; |
| prev_frame_height[sl] = pkt->data.frame.height[sl]; |
| } |
| } |
| |
| virtual void EndPassHook(void) { |
| if (change_bitrate_) last_pts_ = last_pts_ - last_pts_ref_; |
| duration_ = (last_pts_ + 1) * timebase_; |
| for (int sl = 0; sl < number_spatial_layers_; ++sl) { |
| for (int tl = 0; tl < number_temporal_layers_; ++tl) { |
| const int layer = sl * number_temporal_layers_ + tl; |
| const double file_size_in_kb = bits_total_[layer] / 1000.; |
| file_datarate_[layer] = file_size_in_kb / duration_; |
| } |
| } |
| } |
| |
| virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) { |
| double mismatch_psnr = compute_psnr(img1, img2); |
| mismatch_psnr_ += mismatch_psnr; |
| ++mismatch_nframes_; |
| } |
| |
| unsigned int GetMismatchFrames() { return mismatch_nframes_; } |
| unsigned int GetNonRefFrames() { return num_nonref_frames_; } |
| |
| vpx_codec_pts_t last_pts_; |
| double timebase_; |
| int64_t bits_total_[VPX_MAX_LAYERS]; |
| double duration_; |
| double file_datarate_[VPX_MAX_LAYERS]; |
| size_t bits_in_last_frame_; |
| double mismatch_psnr_; |
| int denoiser_on_; |
| int tune_content_; |
| int spatial_layer_id_; |
| bool dynamic_drop_layer_; |
| bool single_layer_resize_; |
| unsigned int top_sl_width_; |
| unsigned int top_sl_height_; |
| vpx_svc_ref_frame_config_t ref_frame_config; |
| int update_pattern_; |
| bool change_bitrate_; |
| vpx_codec_pts_t last_pts_ref_; |
| int middle_bitrate_; |
| int top_bitrate_; |
| int key_frame_spacing_; |
| int layer_framedrop_; |
| int force_key_; |
| int force_key_test_; |
| int inter_layer_pred_mode_; |
| int insert_layer_sync_; |
| int layer_sync_on_base_; |
| int force_intra_only_frame_; |
| int superframe_has_intra_only_; |
| int use_post_encode_drop_; |
| int bitrate_sl3_[3]; |
| // Denoiser switched on the fly. |
| bool denoiser_off_on_; |
| // Top layer enabled on the fly. |
| bool denoiser_enable_layers_; |
| int num_resize_up_; |
| int num_resize_down_; |
| unsigned int prev_frame_width[VPX_MAX_LAYERS]; |
| unsigned int prev_frame_height[VPX_MAX_LAYERS]; |
| |
| private: |
| virtual void SetConfig(const int num_temporal_layer) { |
| cfg_.rc_end_usage = VPX_CBR; |
| cfg_.g_lag_in_frames = 0; |
| cfg_.g_error_resilient = 1; |
| if (num_temporal_layer == 3) { |
| cfg_.ts_rate_decimator[0] = 4; |
| cfg_.ts_rate_decimator[1] = 2; |
| cfg_.ts_rate_decimator[2] = 1; |
| cfg_.temporal_layering_mode = 3; |
| } else if (num_temporal_layer == 2) { |
| cfg_.ts_rate_decimator[0] = 2; |
| cfg_.ts_rate_decimator[1] = 1; |
| cfg_.temporal_layering_mode = 2; |
| } else if (num_temporal_layer == 1) { |
| cfg_.ts_rate_decimator[0] = 1; |
| cfg_.temporal_layering_mode = 0; |
| } |
| } |
| |
| unsigned int num_nonref_frames_; |
| unsigned int mismatch_nframes_; |
| }; |
| |
| // Params: speed setting. |
| class DatarateOnePassCbrSvcSingleBR |
| : public DatarateOnePassCbrSvc, |
| public ::libvpx_test::CodecTestWithParam<int> { |
| public: |
| DatarateOnePassCbrSvcSingleBR() : DatarateOnePassCbrSvc(GET_PARAM(0)) { |
| memset(&svc_params_, 0, sizeof(svc_params_)); |
| } |
| virtual ~DatarateOnePassCbrSvcSingleBR() {} |
| |
| protected: |
| virtual void SetUp() { |
| InitializeConfig(); |
| SetMode(::libvpx_test::kRealTime); |
| speed_setting_ = GET_PARAM(1); |
| ResetModel(); |
| } |
| }; |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1 |
| // temporal layer, with screen content mode on and same speed setting for all |
| // layers. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL1TLScreenContent1) { |
| SetSvcConfig(2, 1); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 10; |
| cfg_.kf_max_dist = 9999; |
| |
| ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| cfg_.rc_target_bitrate = 500; |
| ResetModel(); |
| tune_content_ = 1; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and |
| // 3 temporal layers, with force key frame after frame drop |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TLForceKey) { |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| cfg_.rc_target_bitrate = 100; |
| ResetModel(); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.25); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and |
| // 2 temporal layers, with a change on the fly from the fixed SVC pattern to one |
| // generate via SVC_SET_REF_FRAME_CONFIG. The new pattern also disables |
| // inter-layer prediction. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL2TLDynamicPatternChange) { |
| SetSvcConfig(3, 2); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| // Change SVC pattern on the fly. |
| update_pattern_ = 1; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| cfg_.rc_target_bitrate = 800; |
| ResetModel(); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC with 3 spatial and 3 temporal |
| // layers, for inter_layer_pred=OffKey (K-SVC) and on the fly switching |
| // of denoiser from off to on (on at frame = 100). Key frame period is set to |
| // 1000 so denoise is enabled on non-key. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, |
| OnePassCbrSvc3SL3TL_DenoiserOffOnFixedLayers) { |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 1000; |
| ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280, |
| 720, 30, 1, 0, 300); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| cfg_.rc_target_bitrate = 1000; |
| ResetModel(); |
| denoiser_off_on_ = true; |
| denoiser_enable_layers_ = false; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| // Don't check rate targeting on two top spatial layer since they will be |
| // skipped for part of the sequence. |
| CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_, |
| 0.78, 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC with 3 spatial and 3 temporal |
| // layers, for inter_layer_pred=OffKey (K-SVC) and on the fly switching |
| // of denoiser from off to on, for dynamic layers. Start at 2 spatial layers |
| // and enable 3rd spatial layer at frame = 100. Use periodic key frame with |
| // period 100 so enabling of spatial layer occurs at key frame. Enable denoiser |
| // at frame > 100, after the key frame sync. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, |
| OnePassCbrSvc3SL3TL_DenoiserOffOnEnableLayers) { |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 0; |
| cfg_.kf_max_dist = 100; |
| ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280, |
| 720, 30, 1, 0, 300); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| cfg_.rc_target_bitrate = 1000; |
| ResetModel(); |
| denoiser_off_on_ = true; |
| denoiser_enable_layers_ = true; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| // Don't check rate targeting on two top spatial layer since they will be |
| // skipped for part of the sequence. |
| CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_, |
| 0.78, 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC with 3 spatial layers and on |
| // the fly switching to 1 and then 2 and back to 3 spatial layers. This switch |
| // is done by setting spatial layer bitrates to 0, and then back to non-zero, |
| // during the sequence. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL_DisableEnableLayers) { |
| SetSvcConfig(3, 1); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.temporal_layering_mode = 0; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| cfg_.rc_target_bitrate = 800; |
| ResetModel(); |
| dynamic_drop_layer_ = true; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| // Don't check rate targeting on two top spatial layer since they will be |
| // skipped for part of the sequence. |
| CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_, |
| 0.78, 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC with 2 spatial layers and on |
| // the fly switching to 1 spatial layer with dynamic resize enabled. |
| // The resizer will resize the single layer down and back up again, as the |
| // bitrate goes back up. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL_SingleLayerResize) { |
| SetSvcConfig(2, 1); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.temporal_layering_mode = 0; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| cfg_.rc_resize_allowed = 1; |
| ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280, |
| 720, 15, 1, 0, 300); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| cfg_.rc_target_bitrate = 800; |
| ResetModel(); |
| dynamic_drop_layer_ = true; |
| single_layer_resize_ = true; |
| base_speed_setting_ = speed_setting_; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| // Expect at least one resize down and at least one resize back up. |
| EXPECT_GE(num_resize_down_, 1); |
| EXPECT_GE(num_resize_up_, 1); |
| // Don't check rate targeting on two top spatial layer since they will be |
| // skipped for part of the sequence. |
| CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_, |
| 0.78, 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // For pass CBR SVC with 1 spatial and 2 temporal layers with dynamic resize |
| // and denoiser enabled. The resizer will resize the single layer down and back |
| // up again, as the bitrate goes back up. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc1SL2TL_DenoiseResize) { |
| SetSvcConfig(1, 2); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.temporal_layering_mode = 2; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| cfg_.rc_resize_allowed = 1; |
| ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280, |
| 720, 12, 1, 0, 300); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| cfg_.rc_target_bitrate = 800; |
| ResetModel(); |
| dynamic_drop_layer_ = false; |
| single_layer_resize_ = true; |
| denoiser_on_ = 1; |
| base_speed_setting_ = speed_setting_; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| // Expect at least one resize down and at least one resize back up. |
| EXPECT_GE(num_resize_down_, 1); |
| EXPECT_GE(num_resize_up_, 1); |
| } |
| |
| // Run SVC encoder for 1 temporal layer, 2 spatial layers, with spatial |
| // downscale 5x5. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL1TL5x5MultipleRuns) { |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.rc_end_usage = VPX_CBR; |
| cfg_.g_lag_in_frames = 0; |
| cfg_.ss_number_layers = 2; |
| cfg_.ts_number_layers = 1; |
| cfg_.ts_rate_decimator[0] = 1; |
| cfg_.g_error_resilient = 1; |
| cfg_.g_threads = 3; |
| cfg_.temporal_layering_mode = 0; |
| svc_params_.scaling_factor_num[0] = 256; |
| svc_params_.scaling_factor_den[0] = 1280; |
| svc_params_.scaling_factor_num[1] = 1280; |
| svc_params_.scaling_factor_den[1] = 1280; |
| cfg_.rc_dropframe_thresh = 10; |
| cfg_.kf_max_dist = 999999; |
| cfg_.kf_min_dist = 0; |
| cfg_.ss_target_bitrate[0] = 300; |
| cfg_.ss_target_bitrate[1] = 1400; |
| cfg_.layer_target_bitrate[0] = 300; |
| cfg_.layer_target_bitrate[1] = 1400; |
| cfg_.rc_target_bitrate = 1700; |
| number_spatial_layers_ = cfg_.ss_number_layers; |
| number_temporal_layers_ = cfg_.ts_number_layers; |
| ResetModel(); |
| layer_target_avg_bandwidth_[0] = cfg_.layer_target_bitrate[0] * 1000 / 30; |
| bits_in_buffer_model_[0] = |
| cfg_.layer_target_bitrate[0] * cfg_.rc_buf_initial_sz; |
| layer_target_avg_bandwidth_[1] = cfg_.layer_target_bitrate[1] * 1000 / 30; |
| bits_in_buffer_model_[1] = |
| cfg_.layer_target_bitrate[1] * cfg_.rc_buf_initial_sz; |
| ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Params: speed setting and index for bitrate array. |
| class DatarateOnePassCbrSvcMultiBR |
| : public DatarateOnePassCbrSvc, |
| public ::libvpx_test::CodecTestWith2Params<int, int> { |
| public: |
| DatarateOnePassCbrSvcMultiBR() : DatarateOnePassCbrSvc(GET_PARAM(0)) { |
| memset(&svc_params_, 0, sizeof(svc_params_)); |
| } |
| virtual ~DatarateOnePassCbrSvcMultiBR() {} |
| |
| protected: |
| virtual void SetUp() { |
| InitializeConfig(); |
| SetMode(::libvpx_test::kRealTime); |
| speed_setting_ = GET_PARAM(1); |
| ResetModel(); |
| } |
| }; |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and |
| // 3 temporal layers. Run CIF clip with 1 thread. |
| TEST_P(DatarateOnePassCbrSvcMultiBR, OnePassCbrSvc2SL3TL) { |
| SetSvcConfig(2, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| const int bitrates[3] = { 200, 400, 600 }; |
| // TODO(marpan): Check that effective_datarate for each layer hits the |
| // layer target_bitrate. |
| cfg_.rc_target_bitrate = bitrates[GET_PARAM(2)]; |
| ResetModel(); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.75, |
| 1.2); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Params: speed setting, layer framedrop control and index for bitrate array. |
| class DatarateOnePassCbrSvcFrameDropMultiBR |
| : public DatarateOnePassCbrSvc, |
| public ::libvpx_test::CodecTestWith3Params<int, int, int> { |
| public: |
| DatarateOnePassCbrSvcFrameDropMultiBR() |
| : DatarateOnePassCbrSvc(GET_PARAM(0)) { |
| memset(&svc_params_, 0, sizeof(svc_params_)); |
| } |
| virtual ~DatarateOnePassCbrSvcFrameDropMultiBR() {} |
| |
| protected: |
| virtual void SetUp() { |
| InitializeConfig(); |
| SetMode(::libvpx_test::kRealTime); |
| speed_setting_ = GET_PARAM(1); |
| ResetModel(); |
| } |
| }; |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and |
| // 3 temporal layers. Run HD clip with 4 threads. |
| TEST_P(DatarateOnePassCbrSvcFrameDropMultiBR, OnePassCbrSvc2SL3TL4Threads) { |
| SetSvcConfig(2, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 4; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| layer_framedrop_ = 0; |
| const int bitrates[3] = { 200, 400, 600 }; |
| cfg_.rc_target_bitrate = bitrates[GET_PARAM(3)]; |
| ResetModel(); |
| layer_framedrop_ = GET_PARAM(2); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.64, |
| 1.45); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and |
| // 3 temporal layers. Run HD clip with 4 threads. |
| TEST_P(DatarateOnePassCbrSvcFrameDropMultiBR, OnePassCbrSvc3SL3TL4Threads) { |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 4; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); |
| top_sl_width_ = 1280; |
| top_sl_height_ = 720; |
| layer_framedrop_ = 0; |
| const int bitrates[3] = { 200, 400, 600 }; |
| cfg_.rc_target_bitrate = bitrates[GET_PARAM(3)]; |
| ResetModel(); |
| layer_framedrop_ = GET_PARAM(2); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.58, |
| 1.2); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Params: speed setting, inter-layer prediction mode. |
| class DatarateOnePassCbrSvcInterLayerPredSingleBR |
| : public DatarateOnePassCbrSvc, |
| public ::libvpx_test::CodecTestWith2Params<int, int> { |
| public: |
| DatarateOnePassCbrSvcInterLayerPredSingleBR() |
| : DatarateOnePassCbrSvc(GET_PARAM(0)) { |
| memset(&svc_params_, 0, sizeof(svc_params_)); |
| } |
| virtual ~DatarateOnePassCbrSvcInterLayerPredSingleBR() {} |
| |
| protected: |
| virtual void SetUp() { |
| InitializeConfig(); |
| SetMode(::libvpx_test::kRealTime); |
| speed_setting_ = GET_PARAM(1); |
| inter_layer_pred_mode_ = GET_PARAM(2); |
| ResetModel(); |
| } |
| }; |
| |
| // Check basic rate targeting with different inter-layer prediction modes for 1 |
| // pass CBR SVC: 3 spatial layers and 3 temporal layers. Run CIF clip with 1 |
| // thread. |
| TEST_P(DatarateOnePassCbrSvcInterLayerPredSingleBR, OnePassCbrSvc3SL3TL) { |
| // Disable test for inter-layer pred off for now since simulcast_mode fails. |
| if (inter_layer_pred_mode_ == INTER_LAYER_PRED_OFF) return; |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.temporal_layering_mode = 3; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| cfg_.rc_target_bitrate = 800; |
| ResetModel(); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check rate targeting with different inter-layer prediction modes for 1 pass |
| // CBR SVC: 3 spatial layers and 3 temporal layers, changing the target bitrate |
| // at the middle of encoding. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TLDynamicBitrateChange) { |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| cfg_.rc_target_bitrate = 800; |
| ResetModel(); |
| change_bitrate_ = true; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| #if CONFIG_VP9_TEMPORAL_DENOISING |
| // Params: speed setting, noise sensitivity, index for bitrate array and inter |
| // layer pred mode. |
| class DatarateOnePassCbrSvcDenoiser |
| : public DatarateOnePassCbrSvc, |
| public ::libvpx_test::CodecTestWith4Params<int, int, int, int> { |
| public: |
| DatarateOnePassCbrSvcDenoiser() : DatarateOnePassCbrSvc(GET_PARAM(0)) { |
| memset(&svc_params_, 0, sizeof(svc_params_)); |
| } |
| virtual ~DatarateOnePassCbrSvcDenoiser() {} |
| |
| protected: |
| virtual void SetUp() { |
| InitializeConfig(); |
| SetMode(::libvpx_test::kRealTime); |
| speed_setting_ = GET_PARAM(1); |
| inter_layer_pred_mode_ = GET_PARAM(3); |
| ResetModel(); |
| } |
| }; |
| |
| // Check basic rate targeting for 1 pass CBR SVC with denoising. |
| // 2 spatial layers and 3 temporal layer. Run HD clip with 2 threads. |
| TEST_P(DatarateOnePassCbrSvcDenoiser, OnePassCbrSvc2SL3TLDenoiserOn) { |
| SetSvcConfig(2, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 2; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| number_spatial_layers_ = cfg_.ss_number_layers; |
| number_temporal_layers_ = cfg_.ts_number_layers; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| const int bitrates[3] = { 600, 800, 1000 }; |
| // TODO(marpan): Check that effective_datarate for each layer hits the |
| // layer target_bitrate. |
| // For SVC, noise_sen = 1 means denoising only the top spatial layer |
| // noise_sen = 2 means denoising the two top spatial layers. |
| cfg_.rc_target_bitrate = bitrates[GET_PARAM(3)]; |
| ResetModel(); |
| denoiser_on_ = GET_PARAM(2); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| #endif |
| |
| // Params: speed setting, key frame dist. |
| class DatarateOnePassCbrSvcSmallKF |
| : public DatarateOnePassCbrSvc, |
| public ::libvpx_test::CodecTestWith2Params<int, int> { |
| public: |
| DatarateOnePassCbrSvcSmallKF() : DatarateOnePassCbrSvc(GET_PARAM(0)) { |
| memset(&svc_params_, 0, sizeof(svc_params_)); |
| } |
| virtual ~DatarateOnePassCbrSvcSmallKF() {} |
| |
| protected: |
| virtual void SetUp() { |
| InitializeConfig(); |
| SetMode(::libvpx_test::kRealTime); |
| speed_setting_ = GET_PARAM(1); |
| ResetModel(); |
| } |
| }; |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3 |
| // temporal layers. Run CIF clip with 1 thread, and few short key frame periods. |
| TEST_P(DatarateOnePassCbrSvcSmallKF, OnePassCbrSvc3SL3TLSmallKf) { |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 10; |
| cfg_.rc_target_bitrate = 800; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| // For this 3 temporal layer case, pattern repeats every 4 frames, so choose |
| // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2). |
| const int kf_dist = GET_PARAM(2); |
| cfg_.kf_max_dist = kf_dist; |
| key_frame_spacing_ = kf_dist; |
| ResetModel(); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| // TODO(jianj): webm:1554 |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.70, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3 |
| // temporal layers. Run CIF clip with 1 thread, and few short key frame periods. |
| TEST_P(DatarateOnePassCbrSvcSmallKF, OnePassCbrSvc2SL3TLSmallKf) { |
| SetSvcConfig(2, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.rc_dropframe_thresh = 10; |
| cfg_.rc_target_bitrate = 400; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| // For this 3 temporal layer case, pattern repeats every 4 frames, so choose |
| // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2). |
| const int kf_dist = GET_PARAM(2) + 32; |
| cfg_.kf_max_dist = kf_dist; |
| key_frame_spacing_ = kf_dist; |
| ResetModel(); |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3 |
| // temporal layers. Run VGA clip with 1 thread, and place layer sync frames: |
| // one at middle layer first, then another one for top layer, and another |
| // insert for base spatial layer (which forces key frame). |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TLSyncFrames) { |
| SetSvcConfig(3, 3); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 1; |
| cfg_.kf_max_dist = 9999; |
| cfg_.rc_dropframe_thresh = 10; |
| cfg_.rc_target_bitrate = 400; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| ResetModel(); |
| insert_layer_sync_ = 1; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78, |
| 1.15); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Run SVC encoder for 3 spatial layers, 1 temporal layer, with |
| // intra-only frame as sync frame on base spatial layer. |
| // Intra_only is inserted at start and in middle of sequence. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL1TLSyncWithIntraOnly) { |
| SetSvcConfig(3, 1); |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 63; |
| cfg_.g_threads = 4; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| cfg_.rc_target_bitrate = 400; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| ResetModel(); |
| insert_layer_sync_ = 1; |
| // Use intra_only frame for sync on base layer. |
| force_intra_only_frame_ = 1; |
| AssignLayerBitrates(); |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.73, |
| 1.2); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Run SVC encoder for 2 quality layers (same resolution different, |
| // bitrates), 1 temporal layer, with screen content mode. |
| TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2QL1TLScreen) { |
| cfg_.rc_buf_initial_sz = 500; |
| cfg_.rc_buf_optimal_sz = 500; |
| cfg_.rc_buf_sz = 1000; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 56; |
| cfg_.rc_end_usage = VPX_CBR; |
| cfg_.g_lag_in_frames = 0; |
| cfg_.ss_number_layers = 2; |
| cfg_.ts_number_layers = 1; |
| cfg_.ts_rate_decimator[0] = 1; |
| cfg_.temporal_layering_mode = 0; |
| cfg_.g_error_resilient = 1; |
| cfg_.g_threads = 2; |
| svc_params_.scaling_factor_num[0] = 1; |
| svc_params_.scaling_factor_den[0] = 1; |
| svc_params_.scaling_factor_num[1] = 1; |
| svc_params_.scaling_factor_den[1] = 1; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| number_spatial_layers_ = cfg_.ss_number_layers; |
| number_temporal_layers_ = cfg_.ts_number_layers; |
| ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, |
| 0, 400); |
| top_sl_width_ = 640; |
| top_sl_height_ = 480; |
| ResetModel(); |
| tune_content_ = 1; |
| // Set the layer bitrates, for 2 spatial layers, 1 temporal. |
| cfg_.rc_target_bitrate = 400; |
| cfg_.ss_target_bitrate[0] = 100; |
| cfg_.ss_target_bitrate[1] = 300; |
| cfg_.layer_target_bitrate[0] = 100; |
| cfg_.layer_target_bitrate[1] = 300; |
| for (int sl = 0; sl < 2; ++sl) { |
| float layer_framerate = 30.0; |
| layer_target_avg_bandwidth_[sl] = static_cast<int>( |
| cfg_.layer_target_bitrate[sl] * 1000.0 / layer_framerate); |
| bits_in_buffer_model_[sl] = |
| cfg_.layer_target_bitrate[sl] * cfg_.rc_buf_initial_sz; |
| } |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.73, |
| 1.25); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| // Params: speed setting. |
| class DatarateOnePassCbrSvcPostencodeDrop |
| : public DatarateOnePassCbrSvc, |
| public ::libvpx_test::CodecTestWithParam<int> { |
| public: |
| DatarateOnePassCbrSvcPostencodeDrop() : DatarateOnePassCbrSvc(GET_PARAM(0)) { |
| memset(&svc_params_, 0, sizeof(svc_params_)); |
| } |
| virtual ~DatarateOnePassCbrSvcPostencodeDrop() {} |
| |
| protected: |
| virtual void SetUp() { |
| InitializeConfig(); |
| SetMode(::libvpx_test::kRealTime); |
| speed_setting_ = GET_PARAM(1); |
| ResetModel(); |
| } |
| }; |
| |
| // Run SVC encoder for 2 quality layers (same resolution different, |
| // bitrates), 1 temporal layer, with screen content mode. |
| TEST_P(DatarateOnePassCbrSvcPostencodeDrop, OnePassCbrSvc2QL1TLScreen) { |
| cfg_.rc_buf_initial_sz = 200; |
| cfg_.rc_buf_optimal_sz = 200; |
| cfg_.rc_buf_sz = 400; |
| cfg_.rc_min_quantizer = 0; |
| cfg_.rc_max_quantizer = 52; |
| cfg_.rc_end_usage = VPX_CBR; |
| cfg_.g_lag_in_frames = 0; |
| cfg_.ss_number_layers = 2; |
| cfg_.ts_number_layers = 1; |
| cfg_.ts_rate_decimator[0] = 1; |
| cfg_.temporal_layering_mode = 0; |
| cfg_.g_error_resilient = 1; |
| cfg_.g_threads = 2; |
| svc_params_.scaling_factor_num[0] = 1; |
| svc_params_.scaling_factor_den[0] = 1; |
| svc_params_.scaling_factor_num[1] = 1; |
| svc_params_.scaling_factor_den[1] = 1; |
| cfg_.rc_dropframe_thresh = 30; |
| cfg_.kf_max_dist = 9999; |
| number_spatial_layers_ = cfg_.ss_number_layers; |
| number_temporal_layers_ = cfg_.ts_number_layers; |
| ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, |
| 30, 1, 0, 300); |
| top_sl_width_ = 352; |
| top_sl_height_ = 288; |
| ResetModel(); |
| base_speed_setting_ = speed_setting_; |
| tune_content_ = 1; |
| use_post_encode_drop_ = 1; |
| // Set the layer bitrates, for 2 spatial layers, 1 temporal. |
| cfg_.rc_target_bitrate = 400; |
| cfg_.ss_target_bitrate[0] = 100; |
| cfg_.ss_target_bitrate[1] = 300; |
| cfg_.layer_target_bitrate[0] = 100; |
| cfg_.layer_target_bitrate[1] = 300; |
| for (int sl = 0; sl < 2; ++sl) { |
| float layer_framerate = 30.0; |
| layer_target_avg_bandwidth_[sl] = static_cast<int>( |
| cfg_.layer_target_bitrate[sl] * 1000.0 / layer_framerate); |
| bits_in_buffer_model_[sl] = |
| cfg_.layer_target_bitrate[sl] * cfg_.rc_buf_initial_sz; |
| } |
| ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.73, |
| 1.25); |
| #if CONFIG_VP9_DECODER |
| // The non-reference frames are expected to be mismatched frames as the |
| // encoder will avoid loopfilter on these frames. |
| EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames()); |
| #endif |
| } |
| |
| VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcSingleBR, |
| ::testing::Range(5, 10)); |
| |
| VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcPostencodeDrop, |
| ::testing::Range(5, 6)); |
| |
| VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcInterLayerPredSingleBR, |
| ::testing::Range(5, 10), ::testing::Range(0, 3)); |
| |
| VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcMultiBR, |
| ::testing::Range(5, 10), ::testing::Range(0, 3)); |
| |
| VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcFrameDropMultiBR, |
| ::testing::Range(5, 10), ::testing::Range(0, 2), |
| ::testing::Range(0, 3)); |
| |
| #if CONFIG_VP9_TEMPORAL_DENOISING |
| VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcDenoiser, |
| ::testing::Range(5, 10), ::testing::Range(1, 3), |
| ::testing::Range(0, 3), ::testing::Range(0, 4)); |
| #endif |
| |
| VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcSmallKF, |
| ::testing::Range(5, 10), ::testing::Range(32, 36)); |
| } // namespace |
| } // namespace svc_test |