Remove TemporalLayersFactory and associated classes
As the rate allocation has been moved into entirely into SimulcastRateAllocator, and the listeners are thus no longer needed, this class doesn't fill any other purpose than to determine if ScreenshareLayers or TemporalLayers should be created for a given simulcast stream. This can however be done just from looking at the VideoCodec instance, so changing this into a static factory method. Due to dependencies from upstream projects, keep the class name and field in VideoCodec around for now. Bug: webrtc:9012 Change-Id: I028fe6b2a19e0d16b35956cc2df01dcf5bfa7979 Reviewed-on: https://webrtc-review.googlesource.com/63264 Commit-Queue: Erik Språng <sprang@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22529}
This commit is contained in:
@ -37,18 +37,6 @@ namespace {
|
||||
const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000;
|
||||
const int kMaxBufferedInputFrames = 10;
|
||||
|
||||
std::unique_ptr<VideoBitrateAllocator> CreateBitrateAllocator(
|
||||
TestConfig* config) {
|
||||
std::unique_ptr<TemporalLayersFactory> tl_factory;
|
||||
if (config->codec_settings.codecType == VideoCodecType::kVideoCodecVP8) {
|
||||
tl_factory.reset(new TemporalLayersFactory());
|
||||
config->codec_settings.VP8()->tl_factory = tl_factory.get();
|
||||
}
|
||||
return std::unique_ptr<VideoBitrateAllocator>(
|
||||
VideoCodecInitializer::CreateBitrateAllocator(config->codec_settings,
|
||||
std::move(tl_factory)));
|
||||
}
|
||||
|
||||
size_t GetMaxNaluSizeBytes(const EncodedImage& encoded_frame,
|
||||
const TestConfig& config) {
|
||||
if (config.codec_settings.codecType != kVideoCodecH264)
|
||||
@ -179,7 +167,8 @@ VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder,
|
||||
stats_(stats),
|
||||
encoder_(encoder),
|
||||
decoders_(decoders),
|
||||
bitrate_allocator_(CreateBitrateAllocator(&config_)),
|
||||
bitrate_allocator_(VideoCodecInitializer::CreateBitrateAllocator(
|
||||
config_.codec_settings)),
|
||||
framerate_fps_(0),
|
||||
encode_callback_(this),
|
||||
decode_callback_(this),
|
||||
|
||||
@ -284,18 +284,6 @@ std::vector<TemporalLayers::FrameConfig> GetTemporalPattern(size_t num_layers) {
|
||||
return {TemporalLayers::FrameConfig(
|
||||
TemporalLayers::kNone, TemporalLayers::kNone, TemporalLayers::kNone)};
|
||||
}
|
||||
|
||||
// Temporary fix for forced SW fallback.
|
||||
// For VP8 SW codec, |TemporalLayers| is created and reported to
|
||||
// SimulcastRateAllocator::OnTemporalLayersCreated but not for VP8 HW.
|
||||
// Causes an issue when going from forced SW -> HW as |TemporalLayers| is not
|
||||
// deregistred when deleted by SW codec (tl factory might not exist, owned by
|
||||
// SimulcastRateAllocator).
|
||||
bool ExcludeOnTemporalLayersCreated(int num_temporal_layers) {
|
||||
return webrtc::field_trial::IsEnabled(
|
||||
"WebRTC-VP8-Forced-Fallback-Encoder-v2") &&
|
||||
num_temporal_layers == 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers,
|
||||
@ -399,30 +387,6 @@ void DefaultTemporalLayers::PopulateCodecSpecific(
|
||||
}
|
||||
}
|
||||
|
||||
TemporalLayers* TemporalLayersFactory::Create(
|
||||
int simulcast_id,
|
||||
int temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const {
|
||||
TemporalLayers* tl =
|
||||
new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx);
|
||||
if (listener_ && !ExcludeOnTemporalLayersCreated(temporal_layers))
|
||||
listener_->OnTemporalLayersCreated(simulcast_id, tl);
|
||||
return tl;
|
||||
}
|
||||
|
||||
std::unique_ptr<TemporalLayersChecker> TemporalLayersFactory::CreateChecker(
|
||||
int /*simulcast_id*/,
|
||||
int temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const {
|
||||
TemporalLayersChecker* tlc =
|
||||
new DefaultTemporalLayersChecker(temporal_layers, initial_tl0_pic_idx);
|
||||
return std::unique_ptr<TemporalLayersChecker>(tlc);
|
||||
}
|
||||
|
||||
void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) {
|
||||
listener_ = listener;
|
||||
}
|
||||
|
||||
// Returns list of temporal dependencies for each frame in the temporal pattern.
|
||||
// Values are lists of indecies in the pattern.
|
||||
std::vector<std::set<uint8_t>> GetTemporalDependencies(
|
||||
|
||||
@ -63,7 +63,7 @@ std::vector<uint32_t> GetTemporalLayerRates(int target_bitrate_kbps,
|
||||
codec.simulcastStream[0].maxBitrate = target_bitrate_kbps;
|
||||
codec.simulcastStream[0].numberOfTemporalLayers = num_temporal_layers;
|
||||
codec.simulcastStream[0].active = true;
|
||||
SimulcastRateAllocator allocator(codec, nullptr);
|
||||
SimulcastRateAllocator allocator(codec);
|
||||
return allocator.GetAllocation(target_bitrate_kbps, framerate_fps)
|
||||
.GetTemporalLayerAllocation(0);
|
||||
}
|
||||
|
||||
@ -344,24 +344,12 @@ void LibvpxVp8Encoder::SetStreamState(bool send_stream, int stream_idx) {
|
||||
void LibvpxVp8Encoder::SetupTemporalLayers(int num_streams,
|
||||
int num_temporal_layers,
|
||||
const VideoCodec& codec) {
|
||||
RTC_DCHECK(codec.VP8().tl_factory != nullptr);
|
||||
const TemporalLayersFactory* tl_factory = codec.VP8().tl_factory;
|
||||
RTC_DCHECK(temporal_layers_.empty());
|
||||
if (num_streams == 1) {
|
||||
for (int i = 0; i < num_streams; ++i) {
|
||||
temporal_layers_.emplace_back(
|
||||
tl_factory->Create(0, num_temporal_layers, tl0_pic_idx_[0]));
|
||||
TemporalLayers::CreateTemporalLayers(codec, i, tl0_pic_idx_[i]));
|
||||
temporal_layers_checkers_.emplace_back(
|
||||
tl_factory->CreateChecker(0, num_temporal_layers, tl0_pic_idx_[0]));
|
||||
} else {
|
||||
for (int i = 0; i < num_streams; ++i) {
|
||||
RTC_CHECK_GT(num_temporal_layers, 0);
|
||||
int layers = std::max(static_cast<uint8_t>(1),
|
||||
codec.simulcastStream[i].numberOfTemporalLayers);
|
||||
temporal_layers_.emplace_back(
|
||||
tl_factory->Create(i, layers, tl0_pic_idx_[i]));
|
||||
temporal_layers_checkers_.emplace_back(
|
||||
tl_factory->CreateChecker(i, layers, tl0_pic_idx_[i]));
|
||||
}
|
||||
TemporalLayers::CreateTemporalLayersChecker(codec, i, tl0_pic_idx_[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,7 +529,7 @@ int LibvpxVp8Encoder::InitEncode(const VideoCodec* inst,
|
||||
// Note the order we use is different from webm, we have lowest resolution
|
||||
// at position 0 and they have highest resolution at position 0.
|
||||
int stream_idx = encoders_.size() - 1;
|
||||
SimulcastRateAllocator init_allocator(codec_, nullptr);
|
||||
SimulcastRateAllocator init_allocator(codec_);
|
||||
BitrateAllocation allocation = init_allocator.GetAllocation(
|
||||
inst->startBitrate * 1000, inst->maxFramerate);
|
||||
std::vector<uint32_t> stream_bitrates;
|
||||
|
||||
@ -37,40 +37,6 @@ constexpr int ScreenshareLayers::kMaxNumTemporalLayers;
|
||||
// been exceeded. This prevents needless keyframe requests.
|
||||
const int ScreenshareLayers::kMaxFrameIntervalMs = 2750;
|
||||
|
||||
webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create(
|
||||
int simulcast_id,
|
||||
int num_temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const {
|
||||
webrtc::TemporalLayers* tl;
|
||||
if (simulcast_id == 0) {
|
||||
tl = new webrtc::ScreenshareLayers(num_temporal_layers, rand(),
|
||||
webrtc::Clock::GetRealTimeClock());
|
||||
} else {
|
||||
TemporalLayersFactory rt_tl_factory;
|
||||
tl = rt_tl_factory.Create(simulcast_id, num_temporal_layers, rand());
|
||||
}
|
||||
if (listener_)
|
||||
listener_->OnTemporalLayersCreated(simulcast_id, tl);
|
||||
return tl;
|
||||
}
|
||||
|
||||
std::unique_ptr<webrtc::TemporalLayersChecker>
|
||||
ScreenshareTemporalLayersFactory::CreateChecker(
|
||||
int simulcast_id,
|
||||
int temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const {
|
||||
webrtc::TemporalLayersChecker* tlc;
|
||||
if (simulcast_id == 0) {
|
||||
tlc =
|
||||
new webrtc::TemporalLayersChecker(temporal_layers, initial_tl0_pic_idx);
|
||||
} else {
|
||||
TemporalLayersFactory rt_tl_factory;
|
||||
return rt_tl_factory.CreateChecker(simulcast_id, temporal_layers,
|
||||
initial_tl0_pic_idx);
|
||||
}
|
||||
return std::unique_ptr<webrtc::TemporalLayersChecker>(tlc);
|
||||
}
|
||||
|
||||
ScreenshareLayers::ScreenshareLayers(int num_temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx,
|
||||
Clock* clock)
|
||||
|
||||
@ -20,20 +20,8 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
SimulcastRateAllocator::SimulcastRateAllocator(
|
||||
const VideoCodec& codec,
|
||||
std::unique_ptr<TemporalLayersFactory> tl_factory)
|
||||
: codec_(codec), tl_factory_(std::move(tl_factory)) {
|
||||
if (tl_factory_.get())
|
||||
tl_factory_->SetListener(this);
|
||||
}
|
||||
|
||||
void SimulcastRateAllocator::OnTemporalLayersCreated(int simulcast_id,
|
||||
TemporalLayers* layers) {
|
||||
RTC_DCHECK(temporal_layers_.find(simulcast_id) == temporal_layers_.end());
|
||||
RTC_DCHECK(layers);
|
||||
temporal_layers_[simulcast_id] = layers;
|
||||
}
|
||||
SimulcastRateAllocator::SimulcastRateAllocator(const VideoCodec& codec)
|
||||
: codec_(codec) {}
|
||||
|
||||
BitrateAllocation SimulcastRateAllocator::GetAllocation(
|
||||
uint32_t total_bitrate_bps,
|
||||
@ -241,12 +229,7 @@ SimulcastRateAllocator::ScreenshareTemporalLayerAllocation(
|
||||
}
|
||||
|
||||
uint32_t SimulcastRateAllocator::GetPreferredBitrateBps(uint32_t framerate) {
|
||||
// Create a temporary instance without temporal layers, as they may be
|
||||
// stateful, and updating the bitrate to max here can cause side effects.
|
||||
SimulcastRateAllocator temp_allocator(codec_, nullptr);
|
||||
BitrateAllocation allocation =
|
||||
temp_allocator.GetAllocation(codec_.maxBitrate * 1000, framerate);
|
||||
return allocation.get_sum_bps();
|
||||
return GetAllocation(codec_.maxBitrate * 1000, framerate).get_sum_bps();
|
||||
}
|
||||
|
||||
const VideoCodec& webrtc::SimulcastRateAllocator::GetCodec() const {
|
||||
|
||||
@ -24,15 +24,9 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class SimulcastRateAllocator : public VideoBitrateAllocator,
|
||||
public TemporalLayersListener {
|
||||
class SimulcastRateAllocator : public VideoBitrateAllocator {
|
||||
public:
|
||||
explicit SimulcastRateAllocator(
|
||||
const VideoCodec& codec,
|
||||
std::unique_ptr<TemporalLayersFactory> tl_factory);
|
||||
|
||||
void OnTemporalLayersCreated(int simulcast_id,
|
||||
TemporalLayers* layers) override;
|
||||
explicit SimulcastRateAllocator(const VideoCodec& codec);
|
||||
|
||||
BitrateAllocation GetAllocation(uint32_t total_bitrate_bps,
|
||||
uint32_t framerate) override;
|
||||
@ -58,8 +52,6 @@ class SimulcastRateAllocator : public VideoBitrateAllocator,
|
||||
int NumTemporalStreams(size_t simulcast_id) const;
|
||||
|
||||
const VideoCodec codec_;
|
||||
std::map<uint32_t, TemporalLayers*> temporal_layers_;
|
||||
std::unique_ptr<TemporalLayersFactory> tl_factory_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(SimulcastRateAllocator);
|
||||
};
|
||||
|
||||
@ -271,10 +271,7 @@ class TestVp8Simulcast : public ::testing::Test {
|
||||
}
|
||||
|
||||
void SetUpRateAllocator() {
|
||||
TemporalLayersFactory* tl_factory = new TemporalLayersFactory();
|
||||
rate_allocator_.reset(new SimulcastRateAllocator(
|
||||
settings_, std::unique_ptr<TemporalLayersFactory>(tl_factory)));
|
||||
settings_.VP8()->tl_factory = tl_factory;
|
||||
rate_allocator_.reset(new SimulcastRateAllocator(settings_));
|
||||
}
|
||||
|
||||
void SetRates(uint32_t bitrate_kbps, uint32_t fps) {
|
||||
|
||||
@ -15,13 +15,65 @@
|
||||
#include <vector>
|
||||
|
||||
#include "modules/include/module_common_types.h"
|
||||
#include "modules/video_coding/codecs/vp8/default_temporal_layers.h"
|
||||
#include "modules/video_coding/codecs/vp8/include/vp8_common_types.h"
|
||||
#include "modules/video_coding/codecs/vp8/screenshare_layers.h"
|
||||
#include "modules/video_coding/include/video_codec_interface.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "system_wrappers/include/clock.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
uint8_t NumTemporalLayers(const VideoCodec& codec, int spatial_id) {
|
||||
uint8_t num_temporal_layers =
|
||||
std::max<uint8_t>(1, codec.VP8().numberOfTemporalLayers);
|
||||
if (codec.numberOfSimulcastStreams > 0) {
|
||||
RTC_DCHECK_LT(spatial_id, codec.numberOfSimulcastStreams);
|
||||
num_temporal_layers =
|
||||
std::max(num_temporal_layers,
|
||||
codec.simulcastStream[spatial_id].numberOfTemporalLayers);
|
||||
}
|
||||
return num_temporal_layers;
|
||||
}
|
||||
|
||||
bool IsConferenceModeScreenshare(const VideoCodec& codec) {
|
||||
if (codec.mode != kScreensharing) {
|
||||
return false;
|
||||
}
|
||||
return NumTemporalLayers(codec, 0) == 2;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<TemporalLayers> TemporalLayers::CreateTemporalLayers(
|
||||
const VideoCodec& codec,
|
||||
size_t spatial_id,
|
||||
uint8_t initial_tl0_pic_idx) {
|
||||
if (IsConferenceModeScreenshare(codec) && spatial_id == 0) {
|
||||
// Conference mode temporal layering for screen content in base stream.
|
||||
return rtc::MakeUnique<ScreenshareLayers>(2, initial_tl0_pic_idx,
|
||||
Clock::GetRealTimeClock());
|
||||
}
|
||||
|
||||
return rtc::MakeUnique<DefaultTemporalLayers>(
|
||||
NumTemporalLayers(codec, spatial_id), initial_tl0_pic_idx);
|
||||
}
|
||||
|
||||
std::unique_ptr<TemporalLayersChecker>
|
||||
TemporalLayers::CreateTemporalLayersChecker(const VideoCodec& codec,
|
||||
size_t spatial_id,
|
||||
uint8_t initial_tl0_pic_idx) {
|
||||
if (IsConferenceModeScreenshare(codec) && spatial_id == 0) {
|
||||
// Conference mode temporal layering for screen content in base stream,
|
||||
// use generic checker.
|
||||
return rtc::MakeUnique<TemporalLayersChecker>(2, initial_tl0_pic_idx);
|
||||
}
|
||||
|
||||
return rtc::MakeUnique<DefaultTemporalLayersChecker>(
|
||||
NumTemporalLayers(codec, spatial_id), initial_tl0_pic_idx);
|
||||
}
|
||||
|
||||
TemporalLayersChecker::TemporalLayersChecker(int num_temporal_layers,
|
||||
uint8_t /*initial_tl0_pic_idx*/)
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "typedefs.h" // NOLINT(build/include)
|
||||
|
||||
#define VP8_TS_MAX_PERIODICITY 16
|
||||
@ -35,6 +36,7 @@ struct Vp8EncoderConfig {
|
||||
unsigned int rc_max_quantizer;
|
||||
};
|
||||
|
||||
class TemporalLayersChecker;
|
||||
class TemporalLayers {
|
||||
public:
|
||||
enum BufferFlags {
|
||||
@ -95,6 +97,15 @@ class TemporalLayers {
|
||||
bool freeze_entropy);
|
||||
};
|
||||
|
||||
static std::unique_ptr<TemporalLayers> CreateTemporalLayers(
|
||||
const VideoCodec& codec,
|
||||
size_t spatial_id,
|
||||
uint8_t initial_tl0_pic_idx);
|
||||
static std::unique_ptr<TemporalLayersChecker> CreateTemporalLayersChecker(
|
||||
const VideoCodec& codec,
|
||||
size_t spatial_id,
|
||||
uint8_t initial_tl0_pic_idx);
|
||||
|
||||
// Factory for TemporalLayer strategy. Default behavior is a fixed pattern
|
||||
// of temporal layers. See default_temporal_layers.cc
|
||||
virtual ~TemporalLayers() {}
|
||||
@ -124,57 +135,14 @@ class TemporalLayers {
|
||||
virtual uint8_t Tl0PicIdx() const = 0;
|
||||
};
|
||||
|
||||
class TemporalLayersListener;
|
||||
class TemporalLayersChecker;
|
||||
|
||||
// TODO(webrtc:9012): Remove TemporalLayersFactory type and field once all
|
||||
// upstream usage is gone.
|
||||
class TemporalLayersFactory {
|
||||
public:
|
||||
TemporalLayersFactory() : listener_(nullptr) {}
|
||||
virtual ~TemporalLayersFactory() {}
|
||||
virtual TemporalLayers* Create(int simulcast_id,
|
||||
int temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const;
|
||||
|
||||
// Creates helper class which performs online checks of a correctness of
|
||||
// temporal layers dependencies returned by TemporalLayers class created in
|
||||
// the same factory.
|
||||
virtual std::unique_ptr<TemporalLayersChecker> CreateChecker(
|
||||
int simulcast_id,
|
||||
int temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const;
|
||||
|
||||
void SetListener(TemporalLayersListener* listener);
|
||||
|
||||
protected:
|
||||
TemporalLayersListener* listener_;
|
||||
TemporalLayersFactory() = default;
|
||||
virtual ~TemporalLayersFactory() = default;
|
||||
};
|
||||
|
||||
class ScreenshareTemporalLayersFactory : public webrtc::TemporalLayersFactory {
|
||||
public:
|
||||
ScreenshareTemporalLayersFactory() {}
|
||||
virtual ~ScreenshareTemporalLayersFactory() {}
|
||||
|
||||
webrtc::TemporalLayers* Create(int simulcast_id,
|
||||
int num_temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const override;
|
||||
|
||||
// Creates helper class which performs online checks of a correctness of
|
||||
// temporal layers dependencies returned by TemporalLayers class created in
|
||||
// the same factory.
|
||||
std::unique_ptr<webrtc::TemporalLayersChecker> CreateChecker(
|
||||
int simulcast_id,
|
||||
int temporal_layers,
|
||||
uint8_t initial_tl0_pic_idx) const override;
|
||||
};
|
||||
|
||||
class TemporalLayersListener {
|
||||
public:
|
||||
TemporalLayersListener() {}
|
||||
virtual ~TemporalLayersListener() {}
|
||||
|
||||
virtual void OnTemporalLayersCreated(int simulcast_id,
|
||||
TemporalLayers* layers) = 0;
|
||||
};
|
||||
|
||||
// Used only inside RTC_DCHECK(). It checks correctness of temporal layers
|
||||
// dependencies and sync bits. The only method of this class is called after
|
||||
|
||||
@ -60,7 +60,6 @@ class TestVp8Impl : public VideoCodecUnitTest {
|
||||
codec_settings.VP8()->frameDroppingOn = false;
|
||||
codec_settings.VP8()->automaticResizeOn = false;
|
||||
codec_settings.VP8()->complexity = kComplexityNormal;
|
||||
codec_settings.VP8()->tl_factory = &tl_factory_;
|
||||
return codec_settings;
|
||||
}
|
||||
|
||||
@ -120,8 +119,6 @@ class TestVp8Impl : public VideoCodecUnitTest {
|
||||
ASSERT_TRUE(vp8::GetQp(encoded_frame._buffer, encoded_frame._length, &qp));
|
||||
EXPECT_EQ(encoded_frame.qp_, qp) << "Encoder QP != parsed bitstream QP.";
|
||||
}
|
||||
|
||||
TemporalLayersFactory tl_factory_;
|
||||
};
|
||||
|
||||
TEST_F(TestVp8Impl, SetRateAllocation) {
|
||||
|
||||
Reference in New Issue
Block a user