| Index: webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc
|
| deleted file mode 100644
|
| index b8ece616813836fa637933ad156c6782bf43bb56..0000000000000000000000000000000000000000
|
| --- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc
|
| +++ /dev/null
|
| @@ -1,799 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2014 The WebRTC 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 <array>
|
| -#include <memory>
|
| -#include <vector>
|
| -
|
| -#include "webrtc/common_video/include/video_frame_buffer.h"
|
| -#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h"
|
| -#include "webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h"
|
| -#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
| -#include "webrtc/test/gmock.h"
|
| -
|
| -namespace webrtc {
|
| -namespace testing {
|
| -
|
| -class TestSimulcastEncoderAdapter : public TestVp8Simulcast {
|
| - public:
|
| - TestSimulcastEncoderAdapter()
|
| - : TestVp8Simulcast(new SimulcastEncoderAdapter(new Vp8EncoderFactory()),
|
| - VP8Decoder::Create()) {}
|
| -
|
| - protected:
|
| - class Vp8EncoderFactory : public VideoEncoderFactory {
|
| - public:
|
| - VideoEncoder* Create() override { return VP8Encoder::Create(); }
|
| -
|
| - void Destroy(VideoEncoder* encoder) override { delete encoder; }
|
| -
|
| - virtual ~Vp8EncoderFactory() {}
|
| - };
|
| -
|
| - virtual void SetUp() { TestVp8Simulcast::SetUp(); }
|
| - virtual void TearDown() { TestVp8Simulcast::TearDown(); }
|
| -};
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestKeyFrameRequestsOnAllStreams) {
|
| - TestVp8Simulcast::TestKeyFrameRequestsOnAllStreams();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestPaddingAllStreams) {
|
| - TestVp8Simulcast::TestPaddingAllStreams();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestPaddingTwoStreams) {
|
| - TestVp8Simulcast::TestPaddingTwoStreams();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestPaddingTwoStreamsOneMaxedOut) {
|
| - TestVp8Simulcast::TestPaddingTwoStreamsOneMaxedOut();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestPaddingOneStream) {
|
| - TestVp8Simulcast::TestPaddingOneStream();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestPaddingOneStreamTwoMaxedOut) {
|
| - TestVp8Simulcast::TestPaddingOneStreamTwoMaxedOut();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestSendAllStreams) {
|
| - TestVp8Simulcast::TestSendAllStreams();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestDisablingStreams) {
|
| - TestVp8Simulcast::TestDisablingStreams();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestSwitchingToOneStream) {
|
| - TestVp8Simulcast::TestSwitchingToOneStream();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestSwitchingToOneOddStream) {
|
| - TestVp8Simulcast::TestSwitchingToOneOddStream();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestStrideEncodeDecode) {
|
| - TestVp8Simulcast::TestStrideEncodeDecode();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestSaptioTemporalLayers333PatternEncoder) {
|
| - TestVp8Simulcast::TestSaptioTemporalLayers333PatternEncoder();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapter, TestSpatioTemporalLayers321PatternEncoder) {
|
| - TestVp8Simulcast::TestSpatioTemporalLayers321PatternEncoder();
|
| -}
|
| -
|
| -class MockVideoEncoder : public VideoEncoder {
|
| - public:
|
| - // TODO(nisse): Valid overrides commented out, because the gmock
|
| - // methods don't use any override declarations, and we want to avoid
|
| - // warnings from -Winconsistent-missing-override. See
|
| - // http://crbug.com/428099.
|
| - int32_t InitEncode(const VideoCodec* codecSettings,
|
| - int32_t numberOfCores,
|
| - size_t maxPayloadSize) /* override */ {
|
| - codec_ = *codecSettings;
|
| - return init_encode_return_value_;
|
| - }
|
| -
|
| - MOCK_METHOD3(
|
| - Encode,
|
| - int32_t(const VideoFrame& inputImage,
|
| - const CodecSpecificInfo* codecSpecificInfo,
|
| - const std::vector<FrameType>* frame_types) /* override */);
|
| -
|
| - int32_t RegisterEncodeCompleteCallback(
|
| - EncodedImageCallback* callback) /* override */ {
|
| - callback_ = callback;
|
| - return 0;
|
| - }
|
| -
|
| - MOCK_METHOD0(Release, int32_t());
|
| -
|
| - int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation,
|
| - uint32_t framerate) {
|
| - last_set_bitrate_ = bitrate_allocation;
|
| - return 0;
|
| - }
|
| -
|
| - MOCK_METHOD2(SetChannelParameters, int32_t(uint32_t packetLoss, int64_t rtt));
|
| -
|
| - bool SupportsNativeHandle() const /* override */ {
|
| - return supports_native_handle_;
|
| - }
|
| -
|
| - virtual ~MockVideoEncoder() {}
|
| -
|
| - const VideoCodec& codec() const { return codec_; }
|
| -
|
| - void SendEncodedImage(int width, int height) {
|
| - // Sends a fake image of the given width/height.
|
| - EncodedImage image;
|
| - image._encodedWidth = width;
|
| - image._encodedHeight = height;
|
| - CodecSpecificInfo codec_specific_info;
|
| - memset(&codec_specific_info, 0, sizeof(codec_specific_info));
|
| - callback_->OnEncodedImage(image, &codec_specific_info, nullptr);
|
| - }
|
| -
|
| - void set_supports_native_handle(bool enabled) {
|
| - supports_native_handle_ = enabled;
|
| - }
|
| -
|
| - void set_init_encode_return_value(int32_t value) {
|
| - init_encode_return_value_ = value;
|
| - }
|
| -
|
| - BitrateAllocation last_set_bitrate() const { return last_set_bitrate_; }
|
| -
|
| - MOCK_CONST_METHOD0(ImplementationName, const char*());
|
| -
|
| - private:
|
| - bool supports_native_handle_ = false;
|
| - int32_t init_encode_return_value_ = 0;
|
| - BitrateAllocation last_set_bitrate_;
|
| -
|
| - VideoCodec codec_;
|
| - EncodedImageCallback* callback_;
|
| -};
|
| -
|
| -class MockVideoEncoderFactory : public VideoEncoderFactory {
|
| - public:
|
| - VideoEncoder* Create() override {
|
| - MockVideoEncoder* encoder = new
|
| - ::testing::NiceMock<MockVideoEncoder>();
|
| - encoder->set_init_encode_return_value(init_encode_return_value_);
|
| - const char* encoder_name = encoder_names_.empty()
|
| - ? "codec_implementation_name"
|
| - : encoder_names_[encoders_.size()];
|
| - ON_CALL(*encoder, ImplementationName()).WillByDefault(Return(encoder_name));
|
| - encoders_.push_back(encoder);
|
| - return encoder;
|
| - }
|
| -
|
| - void Destroy(VideoEncoder* encoder) override {
|
| - for (size_t i = 0; i < encoders_.size(); ++i) {
|
| - if (encoders_[i] == encoder) {
|
| - encoders_.erase(encoders_.begin() + i);
|
| - break;
|
| - }
|
| - }
|
| - delete encoder;
|
| - }
|
| -
|
| - virtual ~MockVideoEncoderFactory() {}
|
| -
|
| - const std::vector<MockVideoEncoder*>& encoders() const { return encoders_; }
|
| - void SetEncoderNames(const std::vector<const char*>& encoder_names) {
|
| - encoder_names_ = encoder_names;
|
| - }
|
| - void set_init_encode_return_value(int32_t value) {
|
| - init_encode_return_value_ = value;
|
| - }
|
| -
|
| - private:
|
| - int32_t init_encode_return_value_ = 0;
|
| - std::vector<MockVideoEncoder*> encoders_;
|
| - std::vector<const char*> encoder_names_;
|
| -};
|
| -
|
| -class TestSimulcastEncoderAdapterFakeHelper {
|
| - public:
|
| - TestSimulcastEncoderAdapterFakeHelper()
|
| - : factory_(new MockVideoEncoderFactory()) {}
|
| -
|
| - // Can only be called once as the SimulcastEncoderAdapter will take the
|
| - // ownership of |factory_|.
|
| - VP8Encoder* CreateMockEncoderAdapter() {
|
| - return new SimulcastEncoderAdapter(factory_);
|
| - }
|
| -
|
| - void ExpectCallSetChannelParameters(uint32_t packetLoss, int64_t rtt) {
|
| - EXPECT_TRUE(!factory_->encoders().empty());
|
| - for (size_t i = 0; i < factory_->encoders().size(); ++i) {
|
| - EXPECT_CALL(*factory_->encoders()[i],
|
| - SetChannelParameters(packetLoss, rtt))
|
| - .Times(1);
|
| - }
|
| - }
|
| -
|
| - MockVideoEncoderFactory* factory() { return factory_; }
|
| -
|
| - private:
|
| - MockVideoEncoderFactory* factory_;
|
| -};
|
| -
|
| -static const int kTestTemporalLayerProfile[3] = {3, 2, 1};
|
| -
|
| -class TestSimulcastEncoderAdapterFake : public ::testing::Test,
|
| - public EncodedImageCallback {
|
| - public:
|
| - TestSimulcastEncoderAdapterFake()
|
| - : helper_(new TestSimulcastEncoderAdapterFakeHelper()),
|
| - adapter_(helper_->CreateMockEncoderAdapter()),
|
| - last_encoded_image_width_(-1),
|
| - last_encoded_image_height_(-1),
|
| - last_encoded_image_simulcast_index_(-1) {}
|
| - virtual ~TestSimulcastEncoderAdapterFake() {
|
| - if (adapter_) {
|
| - adapter_->Release();
|
| - }
|
| - }
|
| -
|
| - Result OnEncodedImage(const EncodedImage& encoded_image,
|
| - const CodecSpecificInfo* codec_specific_info,
|
| - const RTPFragmentationHeader* fragmentation) override {
|
| - last_encoded_image_width_ = encoded_image._encodedWidth;
|
| - last_encoded_image_height_ = encoded_image._encodedHeight;
|
| - if (codec_specific_info) {
|
| - last_encoded_image_simulcast_index_ =
|
| - codec_specific_info->codecSpecific.VP8.simulcastIdx;
|
| - }
|
| - return Result(Result::OK, encoded_image._timeStamp);
|
| - }
|
| -
|
| - bool GetLastEncodedImageInfo(int* out_width,
|
| - int* out_height,
|
| - int* out_simulcast_index) {
|
| - if (last_encoded_image_width_ == -1) {
|
| - return false;
|
| - }
|
| - *out_width = last_encoded_image_width_;
|
| - *out_height = last_encoded_image_height_;
|
| - *out_simulcast_index = last_encoded_image_simulcast_index_;
|
| - return true;
|
| - }
|
| -
|
| - void SetupCodec() {
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - rate_allocator_.reset(new SimulcastRateAllocator(codec_, nullptr));
|
| - tl_factory_.SetListener(rate_allocator_.get());
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - adapter_->RegisterEncodeCompleteCallback(this);
|
| - }
|
| -
|
| - void VerifyCodec(const VideoCodec& ref, int stream_index) {
|
| - const VideoCodec& target =
|
| - helper_->factory()->encoders()[stream_index]->codec();
|
| - EXPECT_EQ(ref.codecType, target.codecType);
|
| - EXPECT_EQ(0, strcmp(ref.plName, target.plName));
|
| - EXPECT_EQ(ref.plType, target.plType);
|
| - EXPECT_EQ(ref.width, target.width);
|
| - EXPECT_EQ(ref.height, target.height);
|
| - EXPECT_EQ(ref.startBitrate, target.startBitrate);
|
| - EXPECT_EQ(ref.maxBitrate, target.maxBitrate);
|
| - EXPECT_EQ(ref.minBitrate, target.minBitrate);
|
| - EXPECT_EQ(ref.maxFramerate, target.maxFramerate);
|
| - EXPECT_EQ(ref.VP8().pictureLossIndicationOn,
|
| - target.VP8().pictureLossIndicationOn);
|
| - EXPECT_EQ(ref.VP8().complexity, target.VP8().complexity);
|
| - EXPECT_EQ(ref.VP8().resilience, target.VP8().resilience);
|
| - EXPECT_EQ(ref.VP8().numberOfTemporalLayers,
|
| - target.VP8().numberOfTemporalLayers);
|
| - EXPECT_EQ(ref.VP8().denoisingOn, target.VP8().denoisingOn);
|
| - EXPECT_EQ(ref.VP8().errorConcealmentOn, target.VP8().errorConcealmentOn);
|
| - EXPECT_EQ(ref.VP8().automaticResizeOn, target.VP8().automaticResizeOn);
|
| - EXPECT_EQ(ref.VP8().frameDroppingOn, target.VP8().frameDroppingOn);
|
| - EXPECT_EQ(ref.VP8().keyFrameInterval, target.VP8().keyFrameInterval);
|
| - EXPECT_EQ(ref.qpMax, target.qpMax);
|
| - EXPECT_EQ(0, target.numberOfSimulcastStreams);
|
| - EXPECT_EQ(ref.mode, target.mode);
|
| -
|
| - // No need to compare simulcastStream as numberOfSimulcastStreams should
|
| - // always be 0.
|
| - }
|
| -
|
| - void InitRefCodec(int stream_index, VideoCodec* ref_codec) {
|
| - *ref_codec = codec_;
|
| - ref_codec->VP8()->numberOfTemporalLayers =
|
| - kTestTemporalLayerProfile[stream_index];
|
| - ref_codec->VP8()->tl_factory = &tl_factory_;
|
| - ref_codec->width = codec_.simulcastStream[stream_index].width;
|
| - ref_codec->height = codec_.simulcastStream[stream_index].height;
|
| - ref_codec->maxBitrate = codec_.simulcastStream[stream_index].maxBitrate;
|
| - ref_codec->minBitrate = codec_.simulcastStream[stream_index].minBitrate;
|
| - ref_codec->qpMax = codec_.simulcastStream[stream_index].qpMax;
|
| - }
|
| -
|
| - void VerifyCodecSettings() {
|
| - EXPECT_EQ(3u, helper_->factory()->encoders().size());
|
| - VideoCodec ref_codec;
|
| -
|
| - // stream 0, the lowest resolution stream.
|
| - InitRefCodec(0, &ref_codec);
|
| - ref_codec.qpMax = 45;
|
| - ref_codec.VP8()->complexity = webrtc::kComplexityHigher;
|
| - ref_codec.VP8()->denoisingOn = false;
|
| - ref_codec.startBitrate = 100; // Should equal to the target bitrate.
|
| - VerifyCodec(ref_codec, 0);
|
| -
|
| - // stream 1
|
| - InitRefCodec(1, &ref_codec);
|
| - ref_codec.VP8()->denoisingOn = false;
|
| - // The start bitrate (300kbit) minus what we have for the lower layers
|
| - // (100kbit).
|
| - ref_codec.startBitrate = 200;
|
| - VerifyCodec(ref_codec, 1);
|
| -
|
| - // stream 2, the biggest resolution stream.
|
| - InitRefCodec(2, &ref_codec);
|
| - // We don't have enough bits to send this, so the adapter should have
|
| - // configured it to use the min bitrate for this layer (600kbit) but turn
|
| - // off sending.
|
| - ref_codec.startBitrate = 600;
|
| - VerifyCodec(ref_codec, 2);
|
| - }
|
| -
|
| - protected:
|
| - std::unique_ptr<TestSimulcastEncoderAdapterFakeHelper> helper_;
|
| - std::unique_ptr<VP8Encoder> adapter_;
|
| - VideoCodec codec_;
|
| - int last_encoded_image_width_;
|
| - int last_encoded_image_height_;
|
| - int last_encoded_image_simulcast_index_;
|
| - TemporalLayersFactory tl_factory_;
|
| - std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
|
| -};
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, InitEncode) {
|
| - SetupCodec();
|
| - VerifyCodecSettings();
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, ReleaseWithoutInitEncode) {
|
| - EXPECT_EQ(0, adapter_->Release());
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, Reinit) {
|
| - SetupCodec();
|
| - EXPECT_EQ(0, adapter_->Release());
|
| -
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, SetChannelParameters) {
|
| - SetupCodec();
|
| - const uint32_t packetLoss = 5;
|
| - const int64_t rtt = 30;
|
| - helper_->ExpectCallSetChannelParameters(packetLoss, rtt);
|
| - adapter_->SetChannelParameters(packetLoss, rtt);
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, EncodedCallbackForDifferentEncoders) {
|
| - SetupCodec();
|
| -
|
| - // Set bitrates so that we send all layers.
|
| - adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
|
| -
|
| - // At this point, the simulcast encoder adapter should have 3 streams: HD,
|
| - // quarter HD, and quarter quarter HD. We're going to mostly ignore the exact
|
| - // resolutions, to test that the adapter forwards on the correct resolution
|
| - // and simulcast index values, going only off the encoder that generates the
|
| - // image.
|
| - std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
|
| - ASSERT_EQ(3u, encoders.size());
|
| - encoders[0]->SendEncodedImage(1152, 704);
|
| - int width;
|
| - int height;
|
| - int simulcast_index;
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(1152, width);
|
| - EXPECT_EQ(704, height);
|
| - EXPECT_EQ(0, simulcast_index);
|
| -
|
| - encoders[1]->SendEncodedImage(300, 620);
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(300, width);
|
| - EXPECT_EQ(620, height);
|
| - EXPECT_EQ(1, simulcast_index);
|
| -
|
| - encoders[2]->SendEncodedImage(120, 240);
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(120, width);
|
| - EXPECT_EQ(240, height);
|
| - EXPECT_EQ(2, simulcast_index);
|
| -}
|
| -
|
| -// This test verifies that the underlying encoders are reused, when the adapter
|
| -// is reinited with different number of simulcast streams. It further checks
|
| -// that the allocated encoders are reused in the same order as before, starting
|
| -// with the lowest stream.
|
| -TEST_F(TestSimulcastEncoderAdapterFake, ReusesEncodersInOrder) {
|
| - // Set up common settings for three streams.
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - rate_allocator_.reset(new SimulcastRateAllocator(codec_, nullptr));
|
| - tl_factory_.SetListener(rate_allocator_.get());
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - adapter_->RegisterEncodeCompleteCallback(this);
|
| -
|
| - // Input data.
|
| - rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
|
| - VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
|
| - std::vector<FrameType> frame_types;
|
| -
|
| - // Encode with three streams.
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - VerifyCodecSettings();
|
| - std::vector<MockVideoEncoder*> original_encoders =
|
| - helper_->factory()->encoders();
|
| - ASSERT_EQ(3u, original_encoders.size());
|
| - EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*original_encoders[2], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - frame_types.resize(3, kVideoFrameKey);
|
| - EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
|
| - EXPECT_CALL(*original_encoders[0], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*original_encoders[1], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*original_encoders[2], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_EQ(0, adapter_->Release());
|
| -
|
| - // Encode with two streams.
|
| - codec_.width /= 2;
|
| - codec_.height /= 2;
|
| - codec_.numberOfSimulcastStreams = 2;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - std::vector<MockVideoEncoder*> new_encoders = helper_->factory()->encoders();
|
| - ASSERT_EQ(2u, new_encoders.size());
|
| - ASSERT_EQ(original_encoders[0], new_encoders[0]);
|
| - EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - ASSERT_EQ(original_encoders[1], new_encoders[1]);
|
| - EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - frame_types.resize(2, kVideoFrameKey);
|
| - EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
|
| - EXPECT_CALL(*original_encoders[0], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*original_encoders[1], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_EQ(0, adapter_->Release());
|
| -
|
| - // Encode with single stream.
|
| - codec_.width /= 2;
|
| - codec_.height /= 2;
|
| - codec_.numberOfSimulcastStreams = 1;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - new_encoders = helper_->factory()->encoders();
|
| - ASSERT_EQ(1u, new_encoders.size());
|
| - ASSERT_EQ(original_encoders[0], new_encoders[0]);
|
| - EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - frame_types.resize(1, kVideoFrameKey);
|
| - EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
|
| - EXPECT_CALL(*original_encoders[0], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_EQ(0, adapter_->Release());
|
| -
|
| - // Encode with three streams, again.
|
| - codec_.width *= 4;
|
| - codec_.height *= 4;
|
| - codec_.numberOfSimulcastStreams = 3;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - new_encoders = helper_->factory()->encoders();
|
| - ASSERT_EQ(3u, new_encoders.size());
|
| - // The first encoder is reused.
|
| - ASSERT_EQ(original_encoders[0], new_encoders[0]);
|
| - EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - // The second and third encoders are new.
|
| - EXPECT_CALL(*new_encoders[1], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*new_encoders[2], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - frame_types.resize(3, kVideoFrameKey);
|
| - EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
|
| - EXPECT_CALL(*original_encoders[0], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*new_encoders[1], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_CALL(*new_encoders[2], Release())
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
| - EXPECT_EQ(0, adapter_->Release());
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, DoesNotLeakEncoders) {
|
| - SetupCodec();
|
| - VerifyCodecSettings();
|
| -
|
| - EXPECT_EQ(3u, helper_->factory()->encoders().size());
|
| -
|
| - // The adapter should destroy all encoders it has allocated. Since
|
| - // |helper_->factory()| is owned by |adapter_|, however, we need to rely on
|
| - // lsan to find leaks here.
|
| - EXPECT_EQ(0, adapter_->Release());
|
| - adapter_.reset();
|
| -}
|
| -
|
| -// This test verifies that an adapter reinit with the same codec settings as
|
| -// before does not change the underlying encoder codec settings.
|
| -TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderEncoderSettings) {
|
| - SetupCodec();
|
| - VerifyCodecSettings();
|
| -
|
| - // Capture current codec settings.
|
| - std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
|
| - ASSERT_EQ(3u, encoders.size());
|
| - std::array<VideoCodec, 3> codecs_before;
|
| - for (int i = 0; i < 3; ++i) {
|
| - codecs_before[i] = encoders[i]->codec();
|
| - }
|
| -
|
| - // Reinitialize and verify that the new codec settings are the same.
|
| - EXPECT_EQ(0, adapter_->Release());
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - for (int i = 0; i < 3; ++i) {
|
| - const VideoCodec& codec_before = codecs_before[i];
|
| - const VideoCodec& codec_after = encoders[i]->codec();
|
| -
|
| - // webrtc::VideoCodec does not implement operator==.
|
| - EXPECT_EQ(codec_before.codecType, codec_after.codecType);
|
| - EXPECT_EQ(codec_before.plType, codec_after.plType);
|
| - EXPECT_EQ(codec_before.width, codec_after.width);
|
| - EXPECT_EQ(codec_before.height, codec_after.height);
|
| - EXPECT_EQ(codec_before.startBitrate, codec_after.startBitrate);
|
| - EXPECT_EQ(codec_before.maxBitrate, codec_after.maxBitrate);
|
| - EXPECT_EQ(codec_before.minBitrate, codec_after.minBitrate);
|
| - EXPECT_EQ(codec_before.targetBitrate, codec_after.targetBitrate);
|
| - EXPECT_EQ(codec_before.maxFramerate, codec_after.maxFramerate);
|
| - EXPECT_EQ(codec_before.qpMax, codec_after.qpMax);
|
| - EXPECT_EQ(codec_before.numberOfSimulcastStreams,
|
| - codec_after.numberOfSimulcastStreams);
|
| - EXPECT_EQ(codec_before.mode, codec_after.mode);
|
| - EXPECT_EQ(codec_before.expect_encode_from_texture,
|
| - codec_after.expect_encode_from_texture);
|
| - }
|
| -}
|
| -
|
| -// This test is similar to the one above, except that it tests the simulcastIdx
|
| -// from the CodecSpecificInfo that is connected to an encoded frame. The
|
| -// PayloadRouter demuxes the incoming encoded frames on different RTP modules
|
| -// using the simulcastIdx, so it's important that there is no corresponding
|
| -// encoder reordering in between adapter reinits as this would lead to PictureID
|
| -// discontinuities.
|
| -TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderFrameSimulcastIdx) {
|
| - SetupCodec();
|
| - adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
|
| - VerifyCodecSettings();
|
| -
|
| - // Send frames on all streams.
|
| - std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
|
| - ASSERT_EQ(3u, encoders.size());
|
| - encoders[0]->SendEncodedImage(1152, 704);
|
| - int width;
|
| - int height;
|
| - int simulcast_index;
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(0, simulcast_index);
|
| -
|
| - encoders[1]->SendEncodedImage(300, 620);
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(1, simulcast_index);
|
| -
|
| - encoders[2]->SendEncodedImage(120, 240);
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(2, simulcast_index);
|
| -
|
| - // Reinitialize.
|
| - EXPECT_EQ(0, adapter_->Release());
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
|
| -
|
| - // Verify that the same encoder sends out frames on the same simulcast index.
|
| - encoders[0]->SendEncodedImage(1152, 704);
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(0, simulcast_index);
|
| -
|
| - encoders[1]->SendEncodedImage(300, 620);
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(1, simulcast_index);
|
| -
|
| - encoders[2]->SendEncodedImage(120, 240);
|
| - EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
|
| - EXPECT_EQ(2, simulcast_index);
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, SupportsNativeHandleForSingleStreams) {
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - codec_.numberOfSimulcastStreams = 1;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - adapter_->RegisterEncodeCompleteCallback(this);
|
| - ASSERT_EQ(1u, helper_->factory()->encoders().size());
|
| - helper_->factory()->encoders()[0]->set_supports_native_handle(true);
|
| - EXPECT_TRUE(adapter_->SupportsNativeHandle());
|
| - helper_->factory()->encoders()[0]->set_supports_native_handle(false);
|
| - EXPECT_FALSE(adapter_->SupportsNativeHandle());
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, SetRatesUnderMinBitrate) {
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - codec_.minBitrate = 50;
|
| - codec_.numberOfSimulcastStreams = 1;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - rate_allocator_.reset(new SimulcastRateAllocator(codec_, nullptr));
|
| -
|
| - // Above min should be respected.
|
| - BitrateAllocation target_bitrate =
|
| - rate_allocator_->GetAllocation(codec_.minBitrate * 1000, 30);
|
| - adapter_->SetRateAllocation(target_bitrate, 30);
|
| - EXPECT_EQ(target_bitrate,
|
| - helper_->factory()->encoders()[0]->last_set_bitrate());
|
| -
|
| - // Below min but non-zero should be replaced with the min bitrate.
|
| - BitrateAllocation too_low_bitrate =
|
| - rate_allocator_->GetAllocation((codec_.minBitrate - 1) * 1000, 30);
|
| - adapter_->SetRateAllocation(too_low_bitrate, 30);
|
| - EXPECT_EQ(target_bitrate,
|
| - helper_->factory()->encoders()[0]->last_set_bitrate());
|
| -
|
| - // Zero should be passed on as is, since it means "pause".
|
| - adapter_->SetRateAllocation(BitrateAllocation(), 30);
|
| - EXPECT_EQ(BitrateAllocation(),
|
| - helper_->factory()->encoders()[0]->last_set_bitrate());
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, SupportsImplementationName) {
|
| - EXPECT_STREQ("SimulcastEncoderAdapter", adapter_->ImplementationName());
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - std::vector<const char*> encoder_names;
|
| - encoder_names.push_back("codec1");
|
| - encoder_names.push_back("codec2");
|
| - encoder_names.push_back("codec3");
|
| - helper_->factory()->SetEncoderNames(encoder_names);
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - EXPECT_STREQ("SimulcastEncoderAdapter (codec1, codec2, codec3)",
|
| - adapter_->ImplementationName());
|
| -
|
| - // Single streams should not expose "SimulcastEncoderAdapter" in name.
|
| - EXPECT_EQ(0, adapter_->Release());
|
| - codec_.numberOfSimulcastStreams = 1;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - adapter_->RegisterEncodeCompleteCallback(this);
|
| - ASSERT_EQ(1u, helper_->factory()->encoders().size());
|
| - EXPECT_STREQ("codec1", adapter_->ImplementationName());
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake,
|
| - SupportsNativeHandleForMultipleStreams) {
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - codec_.numberOfSimulcastStreams = 3;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - adapter_->RegisterEncodeCompleteCallback(this);
|
| - ASSERT_EQ(3u, helper_->factory()->encoders().size());
|
| - for (MockVideoEncoder* encoder : helper_->factory()->encoders())
|
| - encoder->set_supports_native_handle(true);
|
| - // If one encoder doesn't support it, then overall support is disabled.
|
| - helper_->factory()->encoders()[0]->set_supports_native_handle(false);
|
| - EXPECT_FALSE(adapter_->SupportsNativeHandle());
|
| - // Once all do, then the adapter claims support.
|
| - helper_->factory()->encoders()[0]->set_supports_native_handle(true);
|
| - EXPECT_TRUE(adapter_->SupportsNativeHandle());
|
| -}
|
| -
|
| -// TODO(nisse): Reuse definition in webrtc/test/fake_texture_handle.h.
|
| -class FakeNativeBuffer : public VideoFrameBuffer {
|
| - public:
|
| - FakeNativeBuffer(int width, int height) : width_(width), height_(height) {}
|
| -
|
| - Type type() const override { return Type::kNative; }
|
| - int width() const override { return width_; }
|
| - int height() const override { return height_; }
|
| -
|
| - rtc::scoped_refptr<I420BufferInterface> ToI420() override {
|
| - RTC_NOTREACHED();
|
| - return nullptr;
|
| - }
|
| -
|
| - private:
|
| - const int width_;
|
| - const int height_;
|
| -};
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake,
|
| - NativeHandleForwardingForMultipleStreams) {
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - codec_.numberOfSimulcastStreams = 3;
|
| - // High start bitrate, so all streams are enabled.
|
| - codec_.startBitrate = 3000;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - adapter_->RegisterEncodeCompleteCallback(this);
|
| - ASSERT_EQ(3u, helper_->factory()->encoders().size());
|
| - for (MockVideoEncoder* encoder : helper_->factory()->encoders())
|
| - encoder->set_supports_native_handle(true);
|
| - EXPECT_TRUE(adapter_->SupportsNativeHandle());
|
| -
|
| - rtc::scoped_refptr<VideoFrameBuffer> buffer(
|
| - new rtc::RefCountedObject<FakeNativeBuffer>(1280, 720));
|
| - VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
|
| - // Expect calls with the given video frame verbatim, since it's a texture
|
| - // frame and can't otherwise be modified/resized.
|
| - for (MockVideoEncoder* encoder : helper_->factory()->encoders())
|
| - EXPECT_CALL(*encoder, Encode(::testing::Ref(input_frame), _, _)).Times(1);
|
| - std::vector<FrameType> frame_types(3, kVideoFrameKey);
|
| - EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, TestFailureReturnCodesFromEncodeCalls) {
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - codec_.numberOfSimulcastStreams = 3;
|
| - EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
|
| - adapter_->RegisterEncodeCompleteCallback(this);
|
| - ASSERT_EQ(3u, helper_->factory()->encoders().size());
|
| - // Tell the 2nd encoder to request software fallback.
|
| - EXPECT_CALL(*helper_->factory()->encoders()[1], Encode(_, _, _))
|
| - .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE));
|
| -
|
| - // Send a fake frame and assert the return is software fallback.
|
| - rtc::scoped_refptr<I420Buffer> input_buffer =
|
| - I420Buffer::Create(kDefaultWidth, kDefaultHeight);
|
| - input_buffer->InitializeData();
|
| - VideoFrame input_frame(input_buffer, 0, 0, webrtc::kVideoRotation_0);
|
| - std::vector<FrameType> frame_types(3, kVideoFrameKey);
|
| - EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
|
| - adapter_->Encode(input_frame, nullptr, &frame_types));
|
| -}
|
| -
|
| -TEST_F(TestSimulcastEncoderAdapterFake, TestInitFailureCleansUpEncoders) {
|
| - TestVp8Simulcast::DefaultSettings(
|
| - &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
|
| - codec_.VP8()->tl_factory = &tl_factory_;
|
| - codec_.numberOfSimulcastStreams = 3;
|
| - helper_->factory()->set_init_encode_return_value(
|
| - WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
|
| - EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
|
| - adapter_->InitEncode(&codec_, 1, 1200));
|
| - EXPECT_TRUE(helper_->factory()->encoders().empty());
|
| -}
|
| -
|
| -} // namespace testing
|
| -} // namespace webrtc
|
|
|