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}
This commit is contained in:

committed by
Commit Bot

parent
7ddd46386a
commit
c22a3a6a7d
@ -162,6 +162,8 @@ rtc_static_library("rtc_audio_video") {
|
|||||||
"engine/videodecodersoftwarefallbackwrapper.h",
|
"engine/videodecodersoftwarefallbackwrapper.h",
|
||||||
"engine/videoencodersoftwarefallbackwrapper.cc",
|
"engine/videoencodersoftwarefallbackwrapper.cc",
|
||||||
"engine/videoencodersoftwarefallbackwrapper.h",
|
"engine/videoencodersoftwarefallbackwrapper.h",
|
||||||
|
"engine/vp8_encoder_simulcast_proxy.cc",
|
||||||
|
"engine/vp8_encoder_simulcast_proxy.h",
|
||||||
"engine/webrtcmediaengine.cc",
|
"engine/webrtcmediaengine.cc",
|
||||||
"engine/webrtcmediaengine.h",
|
"engine/webrtcmediaengine.h",
|
||||||
"engine/webrtcvideocapturer.cc",
|
"engine/webrtcvideocapturer.cc",
|
||||||
@ -460,6 +462,7 @@ if (rtc_include_tests) {
|
|||||||
"engine/simulcast_unittest.cc",
|
"engine/simulcast_unittest.cc",
|
||||||
"engine/videodecodersoftwarefallbackwrapper_unittest.cc",
|
"engine/videodecodersoftwarefallbackwrapper_unittest.cc",
|
||||||
"engine/videoencodersoftwarefallbackwrapper_unittest.cc",
|
"engine/videoencodersoftwarefallbackwrapper_unittest.cc",
|
||||||
|
"engine/vp8_encoder_simulcast_proxy_unittest.cc",
|
||||||
"engine/webrtcmediaengine_unittest.cc",
|
"engine/webrtcmediaengine_unittest.cc",
|
||||||
"engine/webrtcvideocapturer_unittest.cc",
|
"engine/webrtcvideocapturer_unittest.cc",
|
||||||
"engine/webrtcvideoencoderfactory_unittest.cc",
|
"engine/webrtcvideoencoderfactory_unittest.cc",
|
||||||
@ -541,6 +544,7 @@ if (rtc_include_tests) {
|
|||||||
"../system_wrappers:metrics_default",
|
"../system_wrappers:metrics_default",
|
||||||
"../test:audio_codec_mocks",
|
"../test:audio_codec_mocks",
|
||||||
"../test:test_support",
|
"../test:test_support",
|
||||||
|
"../test:video_test_common",
|
||||||
"../voice_engine:voice_engine",
|
"../voice_engine:voice_engine",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
85
media/engine/vp8_encoder_simulcast_proxy.cc
Normal file
85
media/engine/vp8_encoder_simulcast_proxy.cc
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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 "media/engine/scopedvideoencoder.h"
|
||||||
|
#include "media/engine/simulcast_encoder_adapter.h"
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
VP8EncoderSimulcastProxy::VP8EncoderSimulcastProxy(
|
||||||
|
cricket::WebRtcVideoEncoderFactory* factory)
|
||||||
|
: factory_(factory), callback_(nullptr) {
|
||||||
|
encoder_ = CreateScopedVideoEncoder(factory_, cricket::VideoCodec("VP8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
VP8EncoderSimulcastProxy::~VP8EncoderSimulcastProxy() {}
|
||||||
|
|
||||||
|
int VP8EncoderSimulcastProxy::Release() {
|
||||||
|
return encoder_->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
int VP8EncoderSimulcastProxy::InitEncode(const VideoCodec* inst,
|
||||||
|
int number_of_cores,
|
||||||
|
size_t max_payload_size) {
|
||||||
|
int ret = encoder_->InitEncode(inst, number_of_cores, max_payload_size);
|
||||||
|
if (ret == WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED) {
|
||||||
|
encoder_.reset(new SimulcastEncoderAdapter(factory_));
|
||||||
|
if (callback_) {
|
||||||
|
encoder_->RegisterEncodeCompleteCallback(callback_);
|
||||||
|
}
|
||||||
|
ret = encoder_->InitEncode(inst, number_of_cores, max_payload_size);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int VP8EncoderSimulcastProxy::Encode(
|
||||||
|
const VideoFrame& input_image,
|
||||||
|
const CodecSpecificInfo* codec_specific_info,
|
||||||
|
const std::vector<FrameType>* frame_types) {
|
||||||
|
return encoder_->Encode(input_image, codec_specific_info, frame_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VP8EncoderSimulcastProxy::RegisterEncodeCompleteCallback(
|
||||||
|
EncodedImageCallback* callback) {
|
||||||
|
callback_ = callback;
|
||||||
|
return encoder_->RegisterEncodeCompleteCallback(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VP8EncoderSimulcastProxy::SetChannelParameters(uint32_t packet_loss,
|
||||||
|
int64_t rtt) {
|
||||||
|
return encoder_->SetChannelParameters(packet_loss, rtt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VP8EncoderSimulcastProxy::SetRateAllocation(
|
||||||
|
const BitrateAllocation& bitrate,
|
||||||
|
uint32_t new_framerate) {
|
||||||
|
return encoder_->SetRateAllocation(bitrate, new_framerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoEncoder::ScalingSettings VP8EncoderSimulcastProxy::GetScalingSettings()
|
||||||
|
const {
|
||||||
|
return encoder_->GetScalingSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t VP8EncoderSimulcastProxy::SetPeriodicKeyFrames(bool enable) {
|
||||||
|
return encoder_->SetPeriodicKeyFrames(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VP8EncoderSimulcastProxy::SupportsNativeHandle() const {
|
||||||
|
return encoder_->SupportsNativeHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* VP8EncoderSimulcastProxy::ImplementationName() const {
|
||||||
|
return encoder_->ImplementationName();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
58
media/engine/vp8_encoder_simulcast_proxy.h
Normal file
58
media/engine/vp8_encoder_simulcast_proxy.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEDIA_ENGINE_VP8_ENCODER_SIMULCAST_PROXY_H_
|
||||||
|
#define MEDIA_ENGINE_VP8_ENCODER_SIMULCAST_PROXY_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "media/engine/webrtcvideoencoderfactory.h"
|
||||||
|
#include "modules/video_coding/codecs/vp8/include/vp8.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// This class provides fallback to SimulcastEncoderAdapter if default VP8Encoder
|
||||||
|
// doesn't support simulcast for provided settings.
|
||||||
|
class VP8EncoderSimulcastProxy : public VP8Encoder {
|
||||||
|
public:
|
||||||
|
explicit VP8EncoderSimulcastProxy(
|
||||||
|
cricket::WebRtcVideoEncoderFactory* factory);
|
||||||
|
virtual ~VP8EncoderSimulcastProxy();
|
||||||
|
|
||||||
|
// Implements VideoEncoder.
|
||||||
|
int Release() override;
|
||||||
|
int InitEncode(const VideoCodec* inst,
|
||||||
|
int number_of_cores,
|
||||||
|
size_t max_payload_size) override;
|
||||||
|
int Encode(const VideoFrame& input_image,
|
||||||
|
const CodecSpecificInfo* codec_specific_info,
|
||||||
|
const std::vector<FrameType>* frame_types) override;
|
||||||
|
int RegisterEncodeCompleteCallback(EncodedImageCallback* callback) override;
|
||||||
|
int SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
|
||||||
|
int SetRateAllocation(const BitrateAllocation& bitrate,
|
||||||
|
uint32_t new_framerate) override;
|
||||||
|
|
||||||
|
VideoEncoder::ScalingSettings GetScalingSettings() const override;
|
||||||
|
|
||||||
|
int32_t SetPeriodicKeyFrames(bool enable) override;
|
||||||
|
bool SupportsNativeHandle() const override;
|
||||||
|
const char* ImplementationName() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
cricket::WebRtcVideoEncoderFactory* const factory_;
|
||||||
|
std::unique_ptr<VideoEncoder> encoder_;
|
||||||
|
EncodedImageCallback* callback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MEDIA_ENGINE_VP8_ENCODER_SIMULCAST_PROXY_H_
|
152
media/engine/vp8_encoder_simulcast_proxy_unittest.cc
Normal file
152
media/engine/vp8_encoder_simulcast_proxy_unittest.cc
Normal file
@ -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
|
@ -42,6 +42,7 @@
|
|||||||
#include "rtc_base/timeutils.h"
|
#include "rtc_base/timeutils.h"
|
||||||
#include "rtc_base/trace_event.h"
|
#include "rtc_base/trace_event.h"
|
||||||
#include "system_wrappers/include/field_trial.h"
|
#include "system_wrappers/include/field_trial.h"
|
||||||
|
#include "vp8_encoder_simulcast_proxy.h"
|
||||||
|
|
||||||
using DegradationPreference = webrtc::VideoSendStream::DegradationPreference;
|
using DegradationPreference = webrtc::VideoSendStream::DegradationPreference;
|
||||||
|
|
||||||
@ -67,8 +68,7 @@ class EncoderFactoryAdapter {
|
|||||||
virtual ~EncoderFactoryAdapter() {}
|
virtual ~EncoderFactoryAdapter() {}
|
||||||
|
|
||||||
virtual AllocatedEncoder CreateVideoEncoder(
|
virtual AllocatedEncoder CreateVideoEncoder(
|
||||||
const VideoCodec& codec,
|
const VideoCodec& codec) const = 0;
|
||||||
bool is_conference_mode_screenshare) const = 0;
|
|
||||||
|
|
||||||
virtual std::vector<VideoCodec> GetSupportedCodecs() const = 0;
|
virtual std::vector<VideoCodec> GetSupportedCodecs() const = 0;
|
||||||
};
|
};
|
||||||
@ -99,9 +99,7 @@ class CricketEncoderFactoryAdapter : public EncoderFactoryAdapter {
|
|||||||
external_encoder_factory_(std::move(external_encoder_factory)) {}
|
external_encoder_factory_(std::move(external_encoder_factory)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AllocatedEncoder CreateVideoEncoder(
|
AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec) const override;
|
||||||
const VideoCodec& codec,
|
|
||||||
bool is_conference_mode_screenshare) const override;
|
|
||||||
|
|
||||||
std::vector<VideoCodec> GetSupportedCodecs() const override;
|
std::vector<VideoCodec> GetSupportedCodecs() const override;
|
||||||
|
|
||||||
@ -134,9 +132,7 @@ class WebRtcEncoderFactoryAdapter : public EncoderFactoryAdapter {
|
|||||||
: encoder_factory_(std::move(encoder_factory)) {}
|
: encoder_factory_(std::move(encoder_factory)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AllocatedEncoder CreateVideoEncoder(
|
AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec) const override {
|
||||||
const VideoCodec& codec,
|
|
||||||
bool is_conference_mode_screenshare) const override {
|
|
||||||
if (!encoder_factory_)
|
if (!encoder_factory_)
|
||||||
return AllocatedEncoder();
|
return AllocatedEncoder();
|
||||||
const webrtc::SdpVideoFormat format(codec.name, codec.params);
|
const webrtc::SdpVideoFormat format(codec.name, codec.params);
|
||||||
@ -1688,8 +1684,7 @@ WebRtcVideoChannel::WebRtcVideoSendStream::GetSsrcs() const {
|
|||||||
|
|
||||||
EncoderFactoryAdapter::AllocatedEncoder
|
EncoderFactoryAdapter::AllocatedEncoder
|
||||||
CricketEncoderFactoryAdapter::CreateVideoEncoder(
|
CricketEncoderFactoryAdapter::CreateVideoEncoder(
|
||||||
const VideoCodec& codec,
|
const VideoCodec& codec) const {
|
||||||
bool is_conference_mode_screenshare) const {
|
|
||||||
// Try creating external encoder.
|
// Try creating external encoder.
|
||||||
if (external_encoder_factory_ != nullptr &&
|
if (external_encoder_factory_ != nullptr &&
|
||||||
FindMatchingCodec(external_encoder_factory_->supported_codecs(), codec)) {
|
FindMatchingCodec(external_encoder_factory_->supported_codecs(), codec)) {
|
||||||
@ -1719,12 +1714,10 @@ CricketEncoderFactoryAdapter::CreateVideoEncoder(
|
|||||||
// Try creating internal encoder.
|
// Try creating internal encoder.
|
||||||
std::unique_ptr<webrtc::VideoEncoder> internal_encoder;
|
std::unique_ptr<webrtc::VideoEncoder> internal_encoder;
|
||||||
if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(), codec)) {
|
if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(), codec)) {
|
||||||
if (CodecNamesEq(codec.name.c_str(), kVp8CodecName) &&
|
if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) {
|
||||||
is_conference_mode_screenshare && UseSimulcastScreenshare()) {
|
|
||||||
// TODO(sprang): Remove this adapter once libvpx supports simulcast with
|
|
||||||
// same-resolution substreams.
|
|
||||||
internal_encoder = std::unique_ptr<webrtc::VideoEncoder>(
|
internal_encoder = std::unique_ptr<webrtc::VideoEncoder>(
|
||||||
new webrtc::SimulcastEncoderAdapter(internal_encoder_factory_.get()));
|
new webrtc::VP8EncoderSimulcastProxy(
|
||||||
|
internal_encoder_factory_.get()));
|
||||||
} else {
|
} else {
|
||||||
internal_encoder = std::unique_ptr<webrtc::VideoEncoder>(
|
internal_encoder = std::unique_ptr<webrtc::VideoEncoder>(
|
||||||
internal_encoder_factory_->CreateVideoEncoder(codec));
|
internal_encoder_factory_->CreateVideoEncoder(codec));
|
||||||
@ -1753,13 +1746,8 @@ void WebRtcVideoChannel::WebRtcVideoSendStream::SetCodec(
|
|||||||
std::unique_ptr<webrtc::VideoEncoder> new_encoder;
|
std::unique_ptr<webrtc::VideoEncoder> new_encoder;
|
||||||
if (force_encoder_allocation || !allocated_encoder_ ||
|
if (force_encoder_allocation || !allocated_encoder_ ||
|
||||||
allocated_codec_ != codec_settings.codec) {
|
allocated_codec_ != codec_settings.codec) {
|
||||||
const bool is_conference_mode_screenshare =
|
|
||||||
parameters_.encoder_config.content_type ==
|
|
||||||
webrtc::VideoEncoderConfig::ContentType::kScreen &&
|
|
||||||
parameters_.conference_mode;
|
|
||||||
EncoderFactoryAdapter::AllocatedEncoder new_allocated_encoder =
|
EncoderFactoryAdapter::AllocatedEncoder new_allocated_encoder =
|
||||||
encoder_factory_->CreateVideoEncoder(codec_settings.codec,
|
encoder_factory_->CreateVideoEncoder(codec_settings.codec);
|
||||||
is_conference_mode_screenshare);
|
|
||||||
new_encoder = std::unique_ptr<webrtc::VideoEncoder>(
|
new_encoder = std::unique_ptr<webrtc::VideoEncoder>(
|
||||||
std::move(new_allocated_encoder.encoder));
|
std::move(new_allocated_encoder.encoder));
|
||||||
parameters_.config.encoder_settings.encoder = new_encoder.get();
|
parameters_.config.encoder_settings.encoder = new_encoder.get();
|
||||||
|
@ -67,10 +67,6 @@ TEST_F(TestVp8Impl, TestSaptioTemporalLayers333PatternEncoder) {
|
|||||||
TestVp8Simulcast::TestSaptioTemporalLayers333PatternEncoder();
|
TestVp8Simulcast::TestSaptioTemporalLayers333PatternEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestVp8Impl, TestSpatioTemporalLayers321PatternEncoder) {
|
|
||||||
TestVp8Simulcast::TestSpatioTemporalLayers321PatternEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TestVp8Impl, TestStrideEncodeDecode) {
|
TEST_F(TestVp8Impl, TestStrideEncodeDecode) {
|
||||||
TestVp8Simulcast::TestStrideEncodeDecode();
|
TestVp8Simulcast::TestStrideEncodeDecode();
|
||||||
}
|
}
|
||||||
|
@ -286,6 +286,64 @@ TEST_F(TestVp8Impl, DecodedQpEqualsEncodedQp) {
|
|||||||
EXPECT_EQ(encoded_cb_.encoded_frame_.qp_, *decoded_cb_.qp_);
|
EXPECT_EQ(encoded_cb_.encoded_frame_.qp_, *decoded_cb_.qp_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TestVp8Impl, ChecksSimulcastSettings) {
|
||||||
|
codec_settings_.numberOfSimulcastStreams = 2;
|
||||||
|
// Reslutions are not scaled by 2, temporal layers do not match.
|
||||||
|
codec_settings_.simulcastStream[0] = {kWidth, kHeight, 2, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[1] = {kWidth, kHeight, 3, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
|
||||||
|
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||||
|
codec_settings_.numberOfSimulcastStreams = 3;
|
||||||
|
// Reslutions are not scaled by 2.
|
||||||
|
codec_settings_.simulcastStream[0] = {kWidth / 2, kHeight / 2, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[1] = {kWidth / 2, kHeight / 2, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[2] = {kWidth, kHeight, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
|
||||||
|
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||||
|
// Reslutions are not scaled by 2.
|
||||||
|
codec_settings_.simulcastStream[0] = {kWidth, kHeight, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[1] = {kWidth, kHeight, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[2] = {kWidth, kHeight, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
|
||||||
|
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||||
|
// Temporal layers do not match.
|
||||||
|
codec_settings_.simulcastStream[0] = {kWidth / 4, kHeight / 4, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[1] = {kWidth / 2, kHeight / 2, 2, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[2] = {kWidth, kHeight, 3, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
|
||||||
|
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||||
|
// Resolutions do not match codec config.
|
||||||
|
codec_settings_.simulcastStream[0] = {
|
||||||
|
kWidth / 4 + 1, kHeight / 4 + 1, 1, 4000, 3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[1] = {
|
||||||
|
kWidth / 2 + 2, kHeight / 2 + 2, 1, 4000, 3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[2] = {kWidth + 4, kHeight + 4, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
|
||||||
|
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||||
|
// Everything fine: scaling by 2, top resolution matches video, temporal
|
||||||
|
// settings are the same for all layers.
|
||||||
|
codec_settings_.simulcastStream[0] = {kWidth / 4, kHeight / 4, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[1] = {kWidth / 2, kHeight / 2, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
codec_settings_.simulcastStream[2] = {kWidth, kHeight, 1, 4000,
|
||||||
|
3000, 2000, 80};
|
||||||
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||||
|
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(WEBRTC_ANDROID)
|
#if defined(WEBRTC_ANDROID)
|
||||||
#define MAYBE_AlignedStrideEncodeDecode DISABLED_AlignedStrideEncodeDecode
|
#define MAYBE_AlignedStrideEncodeDecode DISABLED_AlignedStrideEncodeDecode
|
||||||
#else
|
#else
|
||||||
|
@ -100,6 +100,21 @@ bool ValidSimulcastResolutions(const VideoCodec& codec, int num_streams) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 1; i < num_streams; ++i) {
|
||||||
|
if (codec.simulcastStream[i].width !=
|
||||||
|
codec.simulcastStream[i - 1].width * 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValidSimulcastTemporalLayers(const VideoCodec& codec, int num_streams) {
|
||||||
|
for (int i = 0; i < num_streams - 1; ++i) {
|
||||||
|
if (codec.simulcastStream[i].numberOfTemporalLayers !=
|
||||||
|
codec.simulcastStream[i + 1].numberOfTemporalLayers)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,8 +410,10 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst,
|
|||||||
int number_of_streams = NumberOfStreams(*inst);
|
int number_of_streams = NumberOfStreams(*inst);
|
||||||
bool doing_simulcast = (number_of_streams > 1);
|
bool doing_simulcast = (number_of_streams > 1);
|
||||||
|
|
||||||
if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) {
|
if (doing_simulcast &&
|
||||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
(!ValidSimulcastResolutions(*inst, number_of_streams) ||
|
||||||
|
!ValidSimulcastTemporalLayers(*inst, number_of_streams))) {
|
||||||
|
return WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_temporal_layers =
|
int num_temporal_layers =
|
||||||
|
@ -28,5 +28,6 @@
|
|||||||
#define WEBRTC_VIDEO_CODEC_ERR_REQUEST_SLI -12
|
#define WEBRTC_VIDEO_CODEC_ERR_REQUEST_SLI -12
|
||||||
#define WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE -13
|
#define WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE -13
|
||||||
#define WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT -14
|
#define WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT -14
|
||||||
|
#define WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED -15
|
||||||
|
|
||||||
#endif // MODULES_VIDEO_CODING_INCLUDE_VIDEO_ERROR_CODES_H_
|
#endif // MODULES_VIDEO_CODING_INCLUDE_VIDEO_ERROR_CODES_H_
|
||||||
|
Reference in New Issue
Block a user