Refactor VP8 encoder creation logic
Now decision between using SimulcastEncoderAdapter and using VP8 encoder
is postponed before codec is initialized for VP8 internal codecs. This is done
be new VP8EncoderProxy class. New error code for codec initialization is used
to signal that simulcast parameters are not supported.
Bug: webrtc:7925
Change-Id: I3a82c21bf5dfaaa7fa25350986830523f02c39d8
Reviewed-on: https://webrtc-review.googlesource.com/13980
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20419}
diff --git a/media/engine/vp8_encoder_simulcast_proxy_unittest.cc b/media/engine/vp8_encoder_simulcast_proxy_unittest.cc
new file mode 100644
index 0000000..0b26bb8
--- /dev/null
+++ b/media/engine/vp8_encoder_simulcast_proxy_unittest.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017 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 "media/engine/vp8_encoder_simulcast_proxy.h"
+
+#include <string>
+
+#include "media/engine/webrtcvideoencoderfactory.h"
+#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/include/video_codec_interface.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/video_codec_settings.h"
+
+namespace webrtc {
+namespace testing {
+
+using ::testing::Return;
+using ::testing::_;
+using ::testing::NiceMock;
+
+class MockEncoder : 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.
+ MockEncoder() {}
+ virtual ~MockEncoder() {}
+
+ MOCK_METHOD3(InitEncode,
+ int32_t(const VideoCodec* codec_settings,
+ int32_t number_of_cores,
+ size_t max_payload_size));
+
+ MOCK_METHOD1(RegisterEncodeCompleteCallback, int32_t(EncodedImageCallback*));
+
+ MOCK_METHOD0(Release, int32_t());
+
+ MOCK_METHOD3(
+ Encode,
+ int32_t(const VideoFrame& inputImage,
+ const CodecSpecificInfo* codecSpecificInfo,
+ const std::vector<FrameType>* frame_types) /* override */);
+
+ MOCK_METHOD2(SetChannelParameters, int32_t(uint32_t packetLoss, int64_t rtt));
+
+ MOCK_CONST_METHOD0(ImplementationName, const char*());
+};
+
+class MockWebRtcVideoEncoderFactory
+ : public cricket::WebRtcVideoEncoderFactory {
+ public:
+ MockWebRtcVideoEncoderFactory() {}
+ virtual ~MockWebRtcVideoEncoderFactory() {}
+
+ MOCK_METHOD1(CreateVideoEncoder,
+ webrtc::VideoEncoder*(const cricket::VideoCodec& codec));
+
+ MOCK_CONST_METHOD0(supported_codecs, std::vector<cricket::VideoCodec>&());
+
+ MOCK_METHOD1(DestroyVideoEncoder, void(webrtc::VideoEncoder*));
+};
+
+TEST(VP8EncoderSimulcastProxy, ChoosesCorrectImplementation) {
+ const std::string kImplementationName = "Fake";
+ const std::string kSimulcastAdaptedImplementationName =
+ "SimulcastEncoderAdapter (Fake, Fake, Fake)";
+ VideoCodec codec_settings;
+ webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings);
+ TemporalLayersFactory tl_factory;
+ codec_settings.VP8()->tl_factory = &tl_factory;
+ codec_settings.simulcastStream[0] = {
+ test::kTestWidth, test::kTestHeight, 2, 2000, 1000, 1000, 56};
+ codec_settings.simulcastStream[1] = {
+ test::kTestWidth, test::kTestHeight, 2, 3000, 1000, 1000, 56};
+ codec_settings.simulcastStream[2] = {
+ test::kTestWidth, test::kTestHeight, 2, 5000, 1000, 1000, 56};
+ codec_settings.numberOfSimulcastStreams = 3;
+
+ NiceMock<MockEncoder> mock_encoder;
+ NiceMock<MockWebRtcVideoEncoderFactory> simulcast_factory;
+
+ EXPECT_CALL(mock_encoder, InitEncode(_, _, _))
+ .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
+ EXPECT_CALL(mock_encoder, ImplementationName())
+ .WillRepeatedly(Return(kImplementationName.c_str()));
+
+ EXPECT_CALL(simulcast_factory, CreateVideoEncoder(_))
+ .Times(1)
+ .WillOnce(Return(&mock_encoder));
+
+ VP8EncoderSimulcastProxy simulcast_enabled_proxy(&simulcast_factory);
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
+ simulcast_enabled_proxy.InitEncode(&codec_settings, 4, 1200));
+ EXPECT_EQ(kImplementationName, simulcast_enabled_proxy.ImplementationName());
+
+ NiceMock<MockEncoder> mock_encoder1;
+ NiceMock<MockEncoder> mock_encoder2;
+ NiceMock<MockEncoder> mock_encoder3;
+ NiceMock<MockEncoder> mock_encoder4;
+ NiceMock<MockWebRtcVideoEncoderFactory> nonsimulcast_factory;
+
+ EXPECT_CALL(mock_encoder1, InitEncode(_, _, _))
+ .WillOnce(
+ Return(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED));
+ EXPECT_CALL(mock_encoder1, ImplementationName())
+ .WillRepeatedly(Return(kImplementationName.c_str()));
+
+ EXPECT_CALL(mock_encoder2, InitEncode(_, _, _))
+ .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
+ EXPECT_CALL(mock_encoder2, ImplementationName())
+ .WillRepeatedly(Return(kImplementationName.c_str()));
+
+ EXPECT_CALL(mock_encoder3, InitEncode(_, _, _))
+ .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
+ EXPECT_CALL(mock_encoder3, ImplementationName())
+ .WillRepeatedly(Return(kImplementationName.c_str()));
+
+ EXPECT_CALL(mock_encoder4, InitEncode(_, _, _))
+ .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
+ EXPECT_CALL(mock_encoder4, ImplementationName())
+ .WillRepeatedly(Return(kImplementationName.c_str()));
+
+ EXPECT_CALL(nonsimulcast_factory, CreateVideoEncoder(_))
+ .Times(4)
+ .WillOnce(Return(&mock_encoder1))
+ .WillOnce(Return(&mock_encoder2))
+ .WillOnce(Return(&mock_encoder3))
+ .WillOnce(Return(&mock_encoder4));
+
+ VP8EncoderSimulcastProxy simulcast_disabled_proxy(&nonsimulcast_factory);
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
+ simulcast_disabled_proxy.InitEncode(&codec_settings, 4, 1200));
+ EXPECT_EQ(kSimulcastAdaptedImplementationName,
+ simulcast_disabled_proxy.ImplementationName());
+
+ // Cleanup.
+ simulcast_enabled_proxy.Release();
+ simulcast_disabled_proxy.Release();
+}
+
+} // namespace testing
+} // namespace webrtc