123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h"
- #include <memory>
- #include <numeric>
- #include <tuple>
- #include <va/va.h>
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/cxx17_backports.h"
- #include "base/logging.h"
- #include "base/memory/raw_ptr.h"
- #include "base/numerics/safe_conversions.h"
- #include "media/filters/vp9_parser.h"
- #include "media/gpu/gpu_video_encode_accelerator_helpers.h"
- #include "media/gpu/vaapi/vaapi_common.h"
- #include "media/gpu/vaapi/vaapi_wrapper.h"
- #include "media/gpu/video_rate_control.h"
- #include "media/gpu/vp9_svc_layers.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/libvpx/source/libvpx/vp9/common/vp9_blockd.h"
- #include "third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h"
- using ::testing::_;
- using ::testing::InSequence;
- using ::testing::Invoke;
- using ::testing::Return;
- namespace media {
- namespace {
- constexpr size_t kDefaultMaxNumRefFrames = kVp9NumRefsPerFrame;
- constexpr int kSpatialLayersResolutionScaleDenom[][3] = {
- {1, 0, 0}, // For one spatial layer.
- {2, 1, 0}, // For two spatial layers.
- {4, 2, 1}, // For three spatial layers.
- };
- constexpr uint8_t kTemporalLayerPattern[][4] = {
- {0, 0, 0, 0},
- {0, 1, 0, 1},
- {0, 2, 1, 2},
- };
- VaapiVideoEncoderDelegate::Config kDefaultVaapiVideoEncoderDelegateConfig{
- .max_num_ref_frames = kDefaultMaxNumRefFrames};
- VideoEncodeAccelerator::Config kDefaultVideoEncodeAcceleratorConfig(
- PIXEL_FORMAT_I420,
- gfx::Size(1280, 720),
- VP9PROFILE_PROFILE0,
- Bitrate::ConstantBitrate(14000000u)
- /* = maximum bitrate in bits per second for level 3.1 */,
- VideoEncodeAccelerator::kDefaultFramerate,
- absl::nullopt /* gop_length */,
- absl::nullopt /* h264 output level*/,
- false /* is_constrained_h264 */,
- VideoEncodeAccelerator::Config::StorageType::kShmem);
- constexpr std::array<bool, kVp9NumRefsPerFrame> kRefFramesUsedForKeyFrame = {
- false, false, false};
- constexpr std::array<bool, kVp9NumRefsPerFrame> kRefFramesUsedForInterFrame = {
- true, true, true};
- constexpr std::array<bool, kVp9NumRefsPerFrame>
- kRefFramesUsedForInterFrameInTemporalLayer = {true, false, false};
- void GetTemporalLayer(bool keyframe,
- int frame_num,
- size_t num_spatial_layers,
- size_t num_temporal_layers,
- std::array<bool, kVp9NumRefsPerFrame>* ref_frames_used,
- uint8_t* temporal_layer_id) {
- switch (num_temporal_layers) {
- case 1:
- *temporal_layer_id = 0;
- if (num_spatial_layers > 1) {
- // K-SVC stream.
- *ref_frames_used = keyframe
- ? kRefFramesUsedForKeyFrame
- : kRefFramesUsedForInterFrameInTemporalLayer;
- } else {
- // Simple stream.
- *ref_frames_used =
- keyframe ? kRefFramesUsedForKeyFrame : kRefFramesUsedForInterFrame;
- }
- break;
- case 2:
- if (keyframe) {
- *temporal_layer_id = 0;
- *ref_frames_used = kRefFramesUsedForKeyFrame;
- return;
- }
- {
- *temporal_layer_id = kTemporalLayerPattern[1][frame_num % 4];
- *ref_frames_used = kRefFramesUsedForInterFrameInTemporalLayer;
- }
- break;
- case 3:
- if (keyframe) {
- *temporal_layer_id = 0u;
- *ref_frames_used = kRefFramesUsedForKeyFrame;
- return;
- }
- {
- *temporal_layer_id = kTemporalLayerPattern[2][frame_num % 4];
- *ref_frames_used = kRefFramesUsedForInterFrameInTemporalLayer;
- }
- break;
- }
- }
- VideoBitrateAllocation CreateBitrateAllocationWithActiveLayers(
- const VideoBitrateAllocation& bitrate_allocation,
- const std::vector<size_t>& active_layers) {
- VideoBitrateAllocation new_bitrate_allocation;
- for (size_t si : active_layers) {
- for (size_t ti = 0; ti < VideoBitrateAllocation::kMaxTemporalLayers; ++ti) {
- const uint32_t bps = bitrate_allocation.GetBitrateBps(si, ti);
- new_bitrate_allocation.SetBitrate(si, ti, bps);
- }
- }
- return new_bitrate_allocation;
- }
- VideoBitrateAllocation AdaptBitrateAllocation(
- const VideoBitrateAllocation& bitrate_allocation) {
- VideoBitrateAllocation new_bitrate_allocation;
- size_t new_si = 0;
- for (size_t si = 0; si < VideoBitrateAllocation::kMaxSpatialLayers; ++si) {
- int sum = 0;
- for (size_t ti = 0; ti < VideoBitrateAllocation::kMaxTemporalLayers; ++ti)
- sum += bitrate_allocation.GetBitrateBps(si, ti);
- if (sum == 0) {
- // The spatial layer is disabled.
- continue;
- }
- for (size_t ti = 0; ti < VideoBitrateAllocation::kMaxTemporalLayers; ++ti) {
- const uint32_t bps = bitrate_allocation.GetBitrateBps(si, ti);
- new_bitrate_allocation.SetBitrate(new_si, ti, bps);
- }
- new_si++;
- }
- return new_bitrate_allocation;
- }
- std::vector<gfx::Size> GetDefaultSpatialLayerResolutions(
- size_t num_spatial_layers) {
- constexpr gfx::Size& kDefaultSize =
- kDefaultVideoEncodeAcceleratorConfig.input_visible_size;
- std::vector<gfx::Size> spatial_layer_resolutions(num_spatial_layers);
- for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
- const int denom =
- kSpatialLayersResolutionScaleDenom[num_spatial_layers - 1][sid];
- spatial_layer_resolutions[sid] =
- gfx::Size(kDefaultSize.width() / denom, kDefaultSize.height() / denom);
- }
- return spatial_layer_resolutions;
- }
- MATCHER_P4(MatchRtcConfigWithRates,
- bitrate_allocation,
- framerate,
- num_temporal_layers,
- spatial_layer_resolutions,
- "") {
- if (arg.target_bandwidth < 0)
- return false;
- if (static_cast<uint32_t>(arg.target_bandwidth) !=
- bitrate_allocation.GetSumBps() / 1000) {
- return false;
- }
- if (arg.framerate != static_cast<double>(framerate))
- return false;
- const size_t num_spatial_layers = spatial_layer_resolutions.size();
- for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
- int bitrate_sum = 0;
- for (size_t tid = 0; tid < num_temporal_layers; ++tid) {
- size_t idx = sid * num_temporal_layers + tid;
- bitrate_sum += bitrate_allocation.GetBitrateBps(sid, tid);
- if (arg.layer_target_bitrate[idx] != bitrate_sum / 1000)
- return false;
- if (arg.ts_rate_decimator[tid] != (1 << (num_temporal_layers - tid - 1)))
- return false;
- }
- if (arg.scaling_factor_num[sid] != 1 ||
- arg.scaling_factor_den[sid] !=
- kSpatialLayersResolutionScaleDenom[num_spatial_layers - 1][sid]) {
- return false;
- }
- }
- const gfx::Size& size = spatial_layer_resolutions.back();
- return arg.width == size.width() && arg.height == size.height() &&
- base::checked_cast<size_t>(arg.ss_number_layers) ==
- num_spatial_layers &&
- base::checked_cast<size_t>(arg.ts_number_layers) ==
- num_temporal_layers;
- }
- MATCHER_P3(MatchFrameParam,
- frame_type,
- temporal_layer_id,
- spatial_layer_id,
- "") {
- return arg.frame_type == frame_type &&
- arg.temporal_layer_id == temporal_layer_id &&
- arg.spatial_layer_id == spatial_layer_id;
- }
- MATCHER_P2(MatchVABufferDescriptor, va_buffer_type, va_buffer_size, "") {
- return arg.type == va_buffer_type && arg.size == va_buffer_size &&
- arg.data != nullptr;
- }
- class MockVaapiWrapper : public VaapiWrapper {
- public:
- MockVaapiWrapper() : VaapiWrapper(kEncodeConstantQuantizationParameter) {}
- MOCK_METHOD1(SubmitBuffer_Locked, bool(const VABufferDescriptor&));
- protected:
- ~MockVaapiWrapper() override = default;
- };
- class MockVP9RateControl
- : public VideoRateControl<libvpx::VP9RateControlRtcConfig,
- libvpx::VP9RateControlRTC,
- libvpx::VP9FrameParamsQpRTC> {
- public:
- MockVP9RateControl() = default;
- ~MockVP9RateControl() override = default;
- MOCK_METHOD1(UpdateRateControl, void(const libvpx::VP9RateControlRtcConfig&));
- MOCK_CONST_METHOD0(GetQP, int());
- MOCK_CONST_METHOD0(GetLoopfilterLevel, int());
- MOCK_METHOD1(ComputeQP, void(const libvpx::VP9FrameParamsQpRTC&));
- MOCK_METHOD1(PostEncodeUpdate, void(uint64_t));
- };
- } // namespace
- struct VP9VaapiVideoEncoderDelegateTestParam;
- class VP9VaapiVideoEncoderDelegateTest
- : public ::testing::TestWithParam<VP9VaapiVideoEncoderDelegateTestParam> {
- public:
- VP9VaapiVideoEncoderDelegateTest() = default;
- ~VP9VaapiVideoEncoderDelegateTest() override = default;
- void SetUp() override;
- MOCK_METHOD0(OnError, void());
- protected:
- void ResetEncoder();
- void InitializeVP9VaapiVideoEncoderDelegate(size_t num_spatial_layers,
- size_t num_temporal_layers);
- void EncodeConstantQuantizationParameterSequence(
- bool is_keyframe,
- const gfx::Size& layer_size,
- absl::optional<std::array<bool, kVp9NumRefsPerFrame>>
- expected_ref_frames_used,
- uint8_t expected_temporal_layer_id,
- uint8_t expected_spatial_layer_id);
- void UpdateRatesTest(size_t num_spatial_layers, size_t num_temporal_layers);
- void UpdateRatesAndEncode(
- const VideoBitrateAllocation& bitrate_allocation,
- uint32_t framerate,
- bool valid_rates_request,
- bool is_key_pic,
- const std::vector<gfx::Size>& expected_spatial_layer_resolutions,
- size_t expected_temporal_layers,
- size_t expected_temporal_layer_id);
- private:
- std::unique_ptr<VaapiVideoEncoderDelegate::EncodeJob> CreateEncodeJob(
- bool keyframe,
- const scoped_refptr<VASurface>& va_surface,
- const scoped_refptr<VP9Picture>& picture);
- std::unique_ptr<VP9VaapiVideoEncoderDelegate> encoder_;
- scoped_refptr<MockVaapiWrapper> mock_vaapi_wrapper_;
- raw_ptr<MockVP9RateControl> mock_rate_ctrl_ = nullptr;
- };
- void VP9VaapiVideoEncoderDelegateTest::ResetEncoder() {
- encoder_ = std::make_unique<VP9VaapiVideoEncoderDelegate>(
- mock_vaapi_wrapper_,
- base::BindRepeating(&VP9VaapiVideoEncoderDelegateTest::OnError,
- base::Unretained(this)));
- }
- void VP9VaapiVideoEncoderDelegateTest::SetUp() {
- mock_vaapi_wrapper_ = base::MakeRefCounted<MockVaapiWrapper>();
- ASSERT_TRUE(mock_vaapi_wrapper_);
- ResetEncoder();
- EXPECT_CALL(*this, OnError()).Times(0);
- }
- std::unique_ptr<VaapiVideoEncoderDelegate::EncodeJob>
- VP9VaapiVideoEncoderDelegateTest::CreateEncodeJob(
- bool keyframe,
- const scoped_refptr<VASurface>& va_surface,
- const scoped_refptr<VP9Picture>& picture) {
- constexpr VABufferID kDummyVABufferID = 12;
- auto scoped_va_buffer = ScopedVABuffer::CreateForTesting(
- kDummyVABufferID, VAEncCodedBufferType,
- kDefaultVideoEncodeAcceleratorConfig.input_visible_size.GetArea());
- // TODO(b/229358029): Set a valid timestamp and check the timestamp in
- // metadata.
- constexpr base::TimeDelta timestamp;
- return std::make_unique<VaapiVideoEncoderDelegate::EncodeJob>(
- keyframe, timestamp, va_surface->id(), picture,
- std::move(scoped_va_buffer));
- }
- void VP9VaapiVideoEncoderDelegateTest::InitializeVP9VaapiVideoEncoderDelegate(
- size_t num_spatial_layers,
- size_t num_temporal_layers) {
- auto config = kDefaultVideoEncodeAcceleratorConfig;
- auto ave_config = kDefaultVaapiVideoEncoderDelegateConfig;
- auto rate_ctrl = std::make_unique<MockVP9RateControl>();
- mock_rate_ctrl_ = rate_ctrl.get();
- encoder_->set_rate_ctrl_for_testing(std::move(rate_ctrl));
- auto initial_bitrate_allocation = AllocateDefaultBitrateForTesting(
- num_spatial_layers, num_temporal_layers,
- kDefaultVideoEncodeAcceleratorConfig.bitrate);
- std::vector<gfx::Size> svc_layer_size =
- GetDefaultSpatialLayerResolutions(num_spatial_layers);
- if (num_spatial_layers > 1u || num_temporal_layers > 1u) {
- DCHECK_GT(num_spatial_layers, 0u);
- for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
- uint32_t sl_bitrate = 0;
- for (size_t tid = 0; tid < num_temporal_layers; ++tid)
- sl_bitrate += initial_bitrate_allocation.GetBitrateBps(sid, tid);
- VideoEncodeAccelerator::Config::SpatialLayer spatial_layer;
- spatial_layer.width = svc_layer_size[sid].width();
- spatial_layer.height = svc_layer_size[sid].height();
- spatial_layer.bitrate_bps = sl_bitrate;
- spatial_layer.framerate = *config.initial_framerate;
- spatial_layer.num_of_temporal_layers = num_temporal_layers;
- spatial_layer.max_qp = 30u;
- config.spatial_layers.push_back(spatial_layer);
- }
- }
- EXPECT_CALL(*mock_rate_ctrl_,
- UpdateRateControl(MatchRtcConfigWithRates(
- AllocateDefaultBitrateForTesting(
- num_spatial_layers, num_temporal_layers, config.bitrate),
- VideoEncodeAccelerator::kDefaultFramerate,
- num_temporal_layers, svc_layer_size)))
- .Times(1)
- .WillOnce(Return());
- EXPECT_TRUE(encoder_->Initialize(config, ave_config));
- EXPECT_EQ(num_temporal_layers > 1u || num_spatial_layers > 1u,
- !!encoder_->svc_layers_);
- EXPECT_EQ(encoder_->GetSVCLayerResolutions(), svc_layer_size);
- }
- void VP9VaapiVideoEncoderDelegateTest::
- EncodeConstantQuantizationParameterSequence(
- bool is_keyframe,
- const gfx::Size& layer_size,
- absl::optional<std::array<bool, kVp9NumRefsPerFrame>>
- expected_ref_frames_used,
- uint8_t expected_temporal_layer_id,
- uint8_t expected_spatial_layer_id) {
- InSequence seq;
- constexpr VASurfaceID kDummyVASurfaceID = 123;
- auto va_surface = base::MakeRefCounted<VASurface>(
- kDummyVASurfaceID, layer_size, VA_RT_FORMAT_YUV420, base::DoNothing());
- scoped_refptr<VP9Picture> picture = new VaapiVP9Picture(va_surface);
- auto encode_job = CreateEncodeJob(is_keyframe, va_surface, picture);
- FRAME_TYPE libvpx_frame_type =
- is_keyframe ? FRAME_TYPE::KEY_FRAME : FRAME_TYPE::INTER_FRAME;
- EXPECT_CALL(
- *mock_rate_ctrl_,
- ComputeQP(MatchFrameParam(libvpx_frame_type, expected_temporal_layer_id,
- expected_spatial_layer_id)))
- .WillOnce(Return());
- constexpr int kDefaultQP = 34;
- constexpr int kDefaultLoopFilterLevel = 8;
- EXPECT_CALL(*mock_rate_ctrl_, GetQP()).WillOnce(Return(kDefaultQP));
- EXPECT_CALL(*mock_rate_ctrl_, GetLoopfilterLevel())
- .WillOnce(Return(kDefaultLoopFilterLevel));
- EXPECT_CALL(*mock_vaapi_wrapper_,
- SubmitBuffer_Locked(MatchVABufferDescriptor(
- VAEncSequenceParameterBufferType,
- sizeof(VAEncSequenceParameterBufferVP9))))
- .WillOnce(Return(true));
- EXPECT_CALL(*mock_vaapi_wrapper_,
- SubmitBuffer_Locked(MatchVABufferDescriptor(
- VAEncPictureParameterBufferType,
- sizeof(VAEncPictureParameterBufferVP9))))
- .WillOnce(Return(true));
- EXPECT_TRUE(encoder_->PrepareEncodeJob(*encode_job.get()));
- // TODO(hiroh): Test for encoder_->reference_frames_.
- constexpr size_t kDefaultEncodedFrameSize = 123456;
- // For BitrateControlUpdate sequence.
- EXPECT_CALL(*mock_rate_ctrl_, PostEncodeUpdate(kDefaultEncodedFrameSize))
- .WillOnce(Return());
- encoder_->BitrateControlUpdate(kDefaultEncodedFrameSize);
- }
- void VP9VaapiVideoEncoderDelegateTest::UpdateRatesAndEncode(
- const VideoBitrateAllocation& bitrate_allocation,
- uint32_t framerate,
- bool valid_rates_request,
- bool is_key_pic,
- const std::vector<gfx::Size>& expected_spatial_layer_resolutions,
- size_t expected_temporal_layers,
- size_t expected_temporal_layer_id) {
- ASSERT_TRUE(encoder_->current_params_.bitrate_allocation !=
- bitrate_allocation ||
- encoder_->current_params_.framerate != framerate);
- // Since the request is pended, this is always successful and no call happens
- // to VP9SVCLayers and RateControl.
- EXPECT_TRUE(encoder_->UpdateRates(bitrate_allocation, framerate));
- EXPECT_TRUE(encoder_->pending_update_rates_.has_value());
- // The pending update rates request is applied in GetSVCLayerResolutions().
- if (!valid_rates_request) {
- EXPECT_TRUE(encoder_->GetSVCLayerResolutions().empty());
- return;
- }
- // VideoBitrateAllocation is adapted if some spatial layers are deactivated.
- const VideoBitrateAllocation adapted_bitrate_allocation =
- AdaptBitrateAllocation(bitrate_allocation);
- EXPECT_CALL(*mock_rate_ctrl_, UpdateRateControl(MatchRtcConfigWithRates(
- adapted_bitrate_allocation, framerate,
- expected_temporal_layers,
- expected_spatial_layer_resolutions)))
- .Times(1)
- .WillOnce(Return());
- EXPECT_EQ(encoder_->GetSVCLayerResolutions(),
- expected_spatial_layer_resolutions);
- EXPECT_FALSE(encoder_->pending_update_rates_.has_value());
- EXPECT_EQ(encoder_->current_params_.bitrate_allocation,
- adapted_bitrate_allocation);
- EXPECT_EQ(encoder_->current_params_.framerate, framerate);
- const size_t num_spatial_layers = expected_spatial_layer_resolutions.size();
- for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
- const gfx::Size& layer_size = expected_spatial_layer_resolutions[sid];
- const bool is_keyframe = is_key_pic && sid == 0;
- EncodeConstantQuantizationParameterSequence(
- is_keyframe, layer_size,
- /*expected_ref_frames_used=*/{}, expected_temporal_layer_id, sid);
- }
- }
- void VP9VaapiVideoEncoderDelegateTest::UpdateRatesTest(
- size_t num_spatial_layers,
- size_t num_temporal_layers) {
- ASSERT_TRUE(num_temporal_layers <= VP9SVCLayers::kMaxSupportedTemporalLayers);
- ASSERT_TRUE(num_spatial_layers <= VP9SVCLayers::kMaxSupportedTemporalLayers);
- const auto spatial_layer_resolutions =
- GetDefaultSpatialLayerResolutions(num_spatial_layers);
- auto update_rates_and_encode = [this, num_spatial_layers, num_temporal_layers,
- &spatial_layer_resolutions](
- bool is_key_pic,
- uint8_t expected_temporal_layer_id,
- uint32_t bitrate, uint32_t framerate) {
- auto bitrate_allocation = AllocateDefaultBitrateForTesting(
- num_spatial_layers, num_temporal_layers,
- media::Bitrate::ConstantBitrate(bitrate));
- UpdateRatesAndEncode(bitrate_allocation, framerate,
- /*valid_rates_request=*/true, is_key_pic,
- spatial_layer_resolutions, num_temporal_layers,
- expected_temporal_layer_id);
- };
- const uint32_t kBitrate =
- kDefaultVideoEncodeAcceleratorConfig.bitrate.target_bps();
- const uint32_t kFramerate =
- *kDefaultVideoEncodeAcceleratorConfig.initial_framerate;
- const uint8_t* expected_temporal_ids =
- kTemporalLayerPattern[num_temporal_layers - 1];
- // Call UpdateRates before Encode.
- update_rates_and_encode(true, expected_temporal_ids[0], kBitrate / 2,
- kFramerate);
- // Bitrate change only.
- update_rates_and_encode(false, expected_temporal_ids[1], kBitrate,
- kFramerate);
- // Framerate change only.
- update_rates_and_encode(false, expected_temporal_ids[2], kBitrate,
- kFramerate + 2);
- // Bitrate + Frame changes.
- update_rates_and_encode(false, expected_temporal_ids[3], kBitrate * 3 / 4,
- kFramerate - 5);
- }
- struct VP9VaapiVideoEncoderDelegateTestParam {
- size_t num_spatial_layers;
- size_t num_temporal_layers;
- } kTestCasesForVP9VaapiVideoEncoderDelegateTest[] = {
- {1u, 1u}, {1u, 2u}, {1u, 3u}, {2u, 1u}, {2u, 2u},
- {2u, 3u}, {3u, 1u}, {3u, 2u}, {3u, 3u},
- };
- TEST_P(VP9VaapiVideoEncoderDelegateTest, Initialize) {
- InitializeVP9VaapiVideoEncoderDelegate(GetParam().num_spatial_layers,
- GetParam().num_temporal_layers);
- }
- TEST_P(VP9VaapiVideoEncoderDelegateTest, EncodeWithSoftwareBitrateControl) {
- const size_t num_spatial_layers = GetParam().num_spatial_layers;
- const size_t num_temporal_layers = GetParam().num_temporal_layers;
- InitializeVP9VaapiVideoEncoderDelegate(num_spatial_layers,
- num_temporal_layers);
- const std::vector<gfx::Size> layer_sizes =
- GetDefaultSpatialLayerResolutions(num_spatial_layers);
- constexpr size_t kEncodeFrames = 20;
- for (size_t frame_num = 0; frame_num < kEncodeFrames; ++frame_num) {
- for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
- const bool is_keyframe = (frame_num == 0 && sid == 0);
- std::array<bool, kVp9NumRefsPerFrame> ref_frames_used;
- uint8_t temporal_layer_id;
- GetTemporalLayer(is_keyframe, frame_num, num_spatial_layers,
- num_temporal_layers, &ref_frames_used,
- &temporal_layer_id);
- EncodeConstantQuantizationParameterSequence(is_keyframe, layer_sizes[sid],
- ref_frames_used,
- temporal_layer_id, sid);
- }
- }
- }
- TEST_P(VP9VaapiVideoEncoderDelegateTest,
- ForceKeyFrameWithSoftwareBitrateControl) {
- const size_t num_spatial_layers = GetParam().num_spatial_layers;
- const size_t num_temporal_layers = GetParam().num_temporal_layers;
- InitializeVP9VaapiVideoEncoderDelegate(num_spatial_layers,
- num_temporal_layers);
- constexpr size_t kNumKeyFrames = 3;
- constexpr size_t kKeyFrameInterval = 20;
- const std::vector<gfx::Size> layer_sizes =
- GetDefaultSpatialLayerResolutions(num_spatial_layers);
- for (size_t j = 0; j < kNumKeyFrames; ++j) {
- for (size_t i = 0; i < kKeyFrameInterval; ++i) {
- for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
- const bool keyframe = (i == 0 && sid == 0);
- std::array<bool, kVp9NumRefsPerFrame> ref_frames_used;
- uint8_t temporal_layer_id;
- GetTemporalLayer(keyframe, i, num_spatial_layers, num_temporal_layers,
- &ref_frames_used, &temporal_layer_id);
- EncodeConstantQuantizationParameterSequence(keyframe, layer_sizes[sid],
- ref_frames_used,
- temporal_layer_id, sid);
- }
- }
- }
- }
- TEST_P(VP9VaapiVideoEncoderDelegateTest, UpdateRates) {
- const size_t num_spatial_layers = GetParam().num_spatial_layers;
- const size_t num_temporal_layers = GetParam().num_temporal_layers;
- InitializeVP9VaapiVideoEncoderDelegate(num_spatial_layers,
- num_temporal_layers);
- UpdateRatesTest(num_spatial_layers, num_temporal_layers);
- }
- TEST_P(VP9VaapiVideoEncoderDelegateTest, DeactivateActivateSpatialLayers) {
- const size_t num_spatial_layers = GetParam().num_spatial_layers;
- const size_t num_temporal_layers = GetParam().num_temporal_layers;
- if (num_spatial_layers == 1)
- GTEST_SKIP() << "Skip a single spatial layer";
- InitializeVP9VaapiVideoEncoderDelegate(num_spatial_layers,
- num_temporal_layers);
- const std::vector<std::vector<size_t>> kActivateExercise[2] = {
- {
- // Two spatial layers.
- {0}, // Deactivate the top layer.
- {0, 1}, // Activate the top layer.
- {1}, // Deactivate the bottom layer.
- {0, 1}, // Activate the bottom layer.
- },
- {
- // Three spatial layers.
- {0, 1}, // Deactivate the top layer.
- {1}, // Deactivate the bottom layer.
- {0}, // Activate the bottom layer and deactivate the top two layers.
- {1,
- 2}, // Activate the top two layers and deactivate the bottom layer.
- {0, 1, 2}, // Activate the bottom layer.
- {2}, // Deactivate the bottom two layers.
- {0, 1, 2}, // Activate the bottom two layers.
- },
- };
- const VideoBitrateAllocation kDefaultBitrateAllocation =
- AllocateDefaultBitrateForTesting(
- num_spatial_layers, num_temporal_layers,
- kDefaultVideoEncodeAcceleratorConfig.bitrate);
- const std::vector<gfx::Size> kDefaultSpatialLayers =
- GetDefaultSpatialLayerResolutions(num_spatial_layers);
- const uint32_t kFramerate =
- *kDefaultVideoEncodeAcceleratorConfig.initial_framerate;
- for (auto& active_layers : kActivateExercise[num_spatial_layers - 2]) {
- const VideoBitrateAllocation bitrate_allocation =
- CreateBitrateAllocationWithActiveLayers(kDefaultBitrateAllocation,
- active_layers);
- std::vector<gfx::Size> spatial_layer_resolutions;
- for (size_t active_sid : active_layers)
- spatial_layer_resolutions.emplace_back(kDefaultSpatialLayers[active_sid]);
- // Always is_key_pic=true and temporal_layer_id=0 because the active spatial
- // layers are changed.
- UpdateRatesAndEncode(bitrate_allocation, kFramerate,
- /*valid_rates_request=*/true,
- /*is_key_pic=*/true, spatial_layer_resolutions,
- num_temporal_layers,
- /*expected_temporal_layer_id=*/0u);
- }
- }
- TEST_P(VP9VaapiVideoEncoderDelegateTest, FailsWithInvalidSpatialLayers) {
- const size_t num_spatial_layers = GetParam().num_spatial_layers;
- const size_t num_temporal_layers = GetParam().num_temporal_layers;
- const VideoBitrateAllocation kDefaultBitrateAllocation =
- AllocateDefaultBitrateForTesting(
- num_spatial_layers, num_temporal_layers,
- kDefaultVideoEncodeAcceleratorConfig.bitrate);
- std::vector<VideoBitrateAllocation> invalid_bitrate_allocations;
- constexpr uint32_t kBitrate = 1234u;
- auto bitrate_allocation = kDefaultBitrateAllocation;
- // Activate one more top spatial layer.
- ASSERT_LE(num_spatial_layers + 1, VideoBitrateAllocation::kMaxSpatialLayers);
- bitrate_allocation.SetBitrate(num_spatial_layers, /*temporal_index=*/0,
- kBitrate);
- invalid_bitrate_allocations.push_back(bitrate_allocation);
- // Deactivate a middle spatial layer.
- if (num_spatial_layers == 3) {
- bitrate_allocation = kDefaultBitrateAllocation;
- for (size_t ti = 0; ti < VideoBitrateAllocation::kMaxTemporalLayers; ++ti)
- bitrate_allocation.SetBitrate(1, ti, 0u);
- invalid_bitrate_allocations.push_back(bitrate_allocation);
- }
- // Increase the number of temporal layers.
- bitrate_allocation = kDefaultBitrateAllocation;
- ASSERT_LE(num_temporal_layers + 1,
- VideoBitrateAllocation::kMaxTemporalLayers);
- for (size_t si = 0; si < num_spatial_layers; ++si)
- bitrate_allocation.SetBitrate(si, num_temporal_layers, kBitrate);
- invalid_bitrate_allocations.push_back(bitrate_allocation);
- // Decrease the number of temporal layers.
- if (num_temporal_layers > 1) {
- bitrate_allocation = kDefaultBitrateAllocation;
- for (size_t si = 0; si < num_spatial_layers; ++si)
- bitrate_allocation.SetBitrate(si, num_temporal_layers - 1, 0u);
- invalid_bitrate_allocations.push_back(bitrate_allocation);
- }
- // Set 0 in the bottom temporal layer.
- if (num_temporal_layers > 1) {
- bitrate_allocation = kDefaultBitrateAllocation;
- bitrate_allocation.SetBitrate(/*spatial_index=*/0, /*temporal_index=*/0,
- 0u);
- invalid_bitrate_allocations.push_back(bitrate_allocation);
- }
- // Set 0 in the middle temporal layer
- if (num_temporal_layers == 3) {
- bitrate_allocation = kDefaultBitrateAllocation;
- bitrate_allocation.SetBitrate(/*spatial_index=*/0, /*temporal_index=*/1,
- 0u);
- invalid_bitrate_allocations.push_back(bitrate_allocation);
- }
- const uint32_t kFramerate =
- *kDefaultVideoEncodeAcceleratorConfig.initial_framerate;
- for (const auto& invalid_allocation : invalid_bitrate_allocations) {
- InitializeVP9VaapiVideoEncoderDelegate(num_spatial_layers,
- num_temporal_layers);
- // The values of expected_spatial_layer_resolutions, is_key_pic,
- // expected_temporal_layers and expected_temporal_layer_id are meaningless
- // because UpdateRatesAndEncode will returns before checking them due to the
- // invalid VideoBitrateAllocation request.
- UpdateRatesAndEncode(invalid_allocation, kFramerate,
- /*valid_rates_request=*/false,
- /*is_key_pic=*/true,
- /*expected_spatial_layer_resolutions=*/{},
- /*expected_temporal_layers=*/0u,
- /*expected_temporal_layer_id=*/0u);
- ResetEncoder();
- }
- }
- INSTANTIATE_TEST_SUITE_P(
- ,
- VP9VaapiVideoEncoderDelegateTest,
- ::testing::ValuesIn(kTestCasesForVP9VaapiVideoEncoderDelegateTest));
- } // namespace media
|