Calculate video padding for vp9 in the same way as for vp8
Bug: webrtc:11476 Change-Id: I8d7b5aac91868e10061605cc5043226ee916cc09 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/172722 Reviewed-by: Evan Shrubsole <eshr@google.com> Reviewed-by: Niels Moller <nisse@webrtc.org> Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30982}
This commit is contained in:
parent
15a95175d4
commit
93be66cdaa
@ -44,6 +44,7 @@ class VideoStreamEncoderInterface : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
public:
|
||||
virtual void OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream> streams,
|
||||
bool is_svc,
|
||||
VideoEncoderConfig::ContentType content_type,
|
||||
int min_transmit_bitrate_bps) = 0;
|
||||
};
|
||||
|
||||
@ -58,12 +58,16 @@ bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
|
||||
|
||||
// Calculate max padding bitrate for a multi layer codec.
|
||||
int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams,
|
||||
bool is_svc,
|
||||
VideoEncoderConfig::ContentType content_type,
|
||||
int min_transmit_bitrate_bps,
|
||||
bool pad_to_min_bitrate,
|
||||
bool alr_probing) {
|
||||
int pad_up_to_bitrate_bps = 0;
|
||||
|
||||
RTC_DCHECK(!is_svc || streams.size() <= 1) << "Only one stream is allowed in "
|
||||
"SVC mode.";
|
||||
|
||||
// Filter out only the active streams;
|
||||
std::vector<VideoStream> active_streams;
|
||||
for (const VideoStream& stream : streams) {
|
||||
@ -71,7 +75,13 @@ int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams,
|
||||
active_streams.emplace_back(stream);
|
||||
}
|
||||
|
||||
if (active_streams.size() > 1) {
|
||||
if (active_streams.size() > 1 || (!active_streams.empty() && is_svc)) {
|
||||
// Simulcast or SVC is used.
|
||||
// if SVC is used, stream bitrates should already encode svc bitrates:
|
||||
// min_bitrate = min bitrate of a lowest svc layer.
|
||||
// target_bitrate = sum of target bitrates of lower layers + min bitrate
|
||||
// of the last one (as used in the calculations below).
|
||||
// max_bitrate = sum of all active layers' max_bitrate.
|
||||
if (alr_probing) {
|
||||
// With alr probing, just pad to the min bitrate of the lowest stream,
|
||||
// probing will handle the rest of the rampup.
|
||||
@ -471,22 +481,23 @@ MediaStreamAllocationConfig VideoSendStreamImpl::GetAllocationConfig() const {
|
||||
|
||||
void VideoSendStreamImpl::OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream> streams,
|
||||
bool is_svc,
|
||||
VideoEncoderConfig::ContentType content_type,
|
||||
int min_transmit_bitrate_bps) {
|
||||
if (!worker_queue_->IsCurrent()) {
|
||||
rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
|
||||
worker_queue_->PostTask([send_stream, streams, content_type,
|
||||
worker_queue_->PostTask([send_stream, streams, is_svc, content_type,
|
||||
min_transmit_bitrate_bps]() mutable {
|
||||
if (send_stream) {
|
||||
send_stream->OnEncoderConfigurationChanged(
|
||||
std::move(streams), content_type, min_transmit_bitrate_bps);
|
||||
std::move(streams), is_svc, content_type, min_transmit_bitrate_bps);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
|
||||
TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
|
||||
RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
|
||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||
|
||||
const VideoCodecType codec_type =
|
||||
@ -516,14 +527,9 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
|
||||
encoder_max_bitrate_bps_);
|
||||
|
||||
// TODO(bugs.webrtc.org/10266): Query the VideoBitrateAllocator instead.
|
||||
if (codec_type == kVideoCodecVP9) {
|
||||
max_padding_bitrate_ = has_alr_probing_ ? streams[0].min_bitrate_bps
|
||||
: streams[0].target_bitrate_bps;
|
||||
} else {
|
||||
max_padding_bitrate_ = CalculateMaxPadBitrateBps(
|
||||
streams, content_type, min_transmit_bitrate_bps,
|
||||
config_->suspend_below_min_bitrate, has_alr_probing_);
|
||||
}
|
||||
max_padding_bitrate_ = CalculateMaxPadBitrateBps(
|
||||
streams, is_svc, content_type, min_transmit_bitrate_bps,
|
||||
config_->suspend_below_min_bitrate, has_alr_probing_);
|
||||
|
||||
// Clear stats for disabled layers.
|
||||
for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
|
||||
|
||||
@ -116,6 +116,7 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
|
||||
|
||||
void OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream> streams,
|
||||
bool is_svc,
|
||||
VideoEncoderConfig::ContentType content_type,
|
||||
int min_transmit_bitrate_bps) override;
|
||||
|
||||
|
||||
@ -241,7 +241,7 @@ TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChange) {
|
||||
|
||||
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
|
||||
->OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream>{qvga_stream, vga_stream},
|
||||
std::vector<VideoStream>{qvga_stream, vga_stream}, false,
|
||||
VideoEncoderConfig::ContentType::kRealtimeVideo,
|
||||
min_transmit_bitrate_bps);
|
||||
vss_impl->Stop();
|
||||
@ -309,7 +309,7 @@ TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChangeWithAlr) {
|
||||
|
||||
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
|
||||
->OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream>{low_stream, high_stream},
|
||||
std::vector<VideoStream>{low_stream, high_stream}, false,
|
||||
VideoEncoderConfig::ContentType::kScreen,
|
||||
min_transmit_bitrate_bps);
|
||||
vss_impl->Stop();
|
||||
@ -371,7 +371,7 @@ TEST_F(VideoSendStreamImplTest,
|
||||
|
||||
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
|
||||
->OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream>{low_stream, high_stream},
|
||||
std::vector<VideoStream>{low_stream, high_stream}, false,
|
||||
VideoEncoderConfig::ContentType::kRealtimeVideo,
|
||||
/*min_transmit_bitrate_bps=*/0);
|
||||
vss_impl->Stop();
|
||||
@ -690,7 +690,7 @@ TEST_F(VideoSendStreamImplTest, CallsVideoStreamEncoderOnBitrateUpdate) {
|
||||
|
||||
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
|
||||
->OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream>{qvga_stream},
|
||||
std::vector<VideoStream>{qvga_stream}, false,
|
||||
VideoEncoderConfig::ContentType::kRealtimeVideo,
|
||||
min_transmit_bitrate_bps);
|
||||
|
||||
@ -816,7 +816,7 @@ TEST_F(VideoSendStreamImplTest, DisablesPaddingOnPausedEncoder) {
|
||||
// Reconfigure e.g. due to a fake frame.
|
||||
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
|
||||
->OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream>{qvga_stream},
|
||||
std::vector<VideoStream>{qvga_stream}, false,
|
||||
VideoEncoderConfig::ContentType::kRealtimeVideo,
|
||||
min_transmit_bitrate_bps);
|
||||
// Still no padding because no actual frames were passed, only
|
||||
@ -893,5 +893,112 @@ TEST_F(VideoSendStreamImplTest, KeepAliveOnDroppedFrame) {
|
||||
ASSERT_TRUE(done.Wait(5000));
|
||||
}
|
||||
|
||||
TEST_F(VideoSendStreamImplTest, ConfiguresBitratesForSvcWithAlr) {
|
||||
test_queue_.SendTask(
|
||||
[this] {
|
||||
const bool kSuspend = false;
|
||||
config_.suspend_below_min_bitrate = kSuspend;
|
||||
config_.rtp.extensions.emplace_back(
|
||||
RtpExtension::kTransportSequenceNumberUri, 1);
|
||||
config_.periodic_alr_bandwidth_probing = true;
|
||||
auto vss_impl = CreateVideoSendStreamImpl(
|
||||
kDefaultInitialBitrateBps, kDefaultBitratePriority,
|
||||
VideoEncoderConfig::ContentType::kScreen);
|
||||
vss_impl->Start();
|
||||
|
||||
// Svc
|
||||
VideoStream stream;
|
||||
stream.width = 1920;
|
||||
stream.height = 1080;
|
||||
stream.max_framerate = 30;
|
||||
stream.min_bitrate_bps = 60000;
|
||||
stream.target_bitrate_bps = 6000000;
|
||||
stream.max_bitrate_bps = 1250000;
|
||||
stream.num_temporal_layers = 2;
|
||||
stream.max_qp = 56;
|
||||
stream.bitrate_priority = 1;
|
||||
|
||||
int min_transmit_bitrate_bps = 400000;
|
||||
|
||||
config_.rtp.ssrcs.emplace_back(1);
|
||||
config_.rtp.ssrcs.emplace_back(2);
|
||||
|
||||
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
|
||||
.WillRepeatedly(Invoke([&](BitrateAllocatorObserver*,
|
||||
MediaStreamAllocationConfig config) {
|
||||
EXPECT_EQ(config.min_bitrate_bps,
|
||||
static_cast<uint32_t>(stream.min_bitrate_bps));
|
||||
EXPECT_EQ(config.max_bitrate_bps,
|
||||
static_cast<uint32_t>(stream.max_bitrate_bps));
|
||||
if (config.pad_up_bitrate_bps != 0) {
|
||||
EXPECT_EQ(config.pad_up_bitrate_bps,
|
||||
static_cast<uint32_t>(min_transmit_bitrate_bps));
|
||||
}
|
||||
EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
|
||||
}));
|
||||
|
||||
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
|
||||
->OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream>{stream}, true,
|
||||
VideoEncoderConfig::ContentType::kScreen,
|
||||
min_transmit_bitrate_bps);
|
||||
vss_impl->Stop();
|
||||
},
|
||||
RTC_FROM_HERE);
|
||||
}
|
||||
|
||||
TEST_F(VideoSendStreamImplTest, ConfiguresBitratesForSvcNoAlr) {
|
||||
test_queue_.SendTask(
|
||||
[this] {
|
||||
const bool kSuspend = false;
|
||||
config_.suspend_below_min_bitrate = kSuspend;
|
||||
config_.rtp.extensions.emplace_back(
|
||||
RtpExtension::kTransportSequenceNumberUri, 1);
|
||||
config_.periodic_alr_bandwidth_probing = false;
|
||||
auto vss_impl = CreateVideoSendStreamImpl(
|
||||
kDefaultInitialBitrateBps, kDefaultBitratePriority,
|
||||
VideoEncoderConfig::ContentType::kScreen);
|
||||
vss_impl->Start();
|
||||
|
||||
// Svc
|
||||
VideoStream stream;
|
||||
stream.width = 1920;
|
||||
stream.height = 1080;
|
||||
stream.max_framerate = 30;
|
||||
stream.min_bitrate_bps = 60000;
|
||||
stream.target_bitrate_bps = 6000000;
|
||||
stream.max_bitrate_bps = 1250000;
|
||||
stream.num_temporal_layers = 2;
|
||||
stream.max_qp = 56;
|
||||
stream.bitrate_priority = 1;
|
||||
|
||||
int min_transmit_bitrate_bps = 400000;
|
||||
|
||||
config_.rtp.ssrcs.emplace_back(1);
|
||||
config_.rtp.ssrcs.emplace_back(2);
|
||||
|
||||
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
|
||||
.WillRepeatedly(Invoke([&](BitrateAllocatorObserver*,
|
||||
MediaStreamAllocationConfig config) {
|
||||
EXPECT_EQ(config.min_bitrate_bps,
|
||||
static_cast<uint32_t>(stream.min_bitrate_bps));
|
||||
EXPECT_EQ(config.max_bitrate_bps,
|
||||
static_cast<uint32_t>(stream.max_bitrate_bps));
|
||||
if (config.pad_up_bitrate_bps != 0) {
|
||||
EXPECT_EQ(config.pad_up_bitrate_bps,
|
||||
static_cast<uint32_t>(stream.target_bitrate_bps));
|
||||
}
|
||||
EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
|
||||
}));
|
||||
|
||||
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
|
||||
->OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream>{stream}, true,
|
||||
VideoEncoderConfig::ContentType::kScreen,
|
||||
min_transmit_bitrate_bps);
|
||||
vss_impl->Stop();
|
||||
},
|
||||
RTC_FROM_HERE);
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
|
||||
@ -516,18 +516,6 @@ void VideoStreamEncoder::ReconfigureEncoder() {
|
||||
RTC_LOG(LS_ERROR) << "Failed to create encoder configuration.";
|
||||
}
|
||||
|
||||
// Set min_bitrate_bps, max_bitrate_bps, and max padding bit rate for VP9.
|
||||
if (encoder_config_.codec_type == kVideoCodecVP9) {
|
||||
// Lower max bitrate to the level codec actually can produce.
|
||||
streams[0].max_bitrate_bps =
|
||||
std::min(streams[0].max_bitrate_bps,
|
||||
SvcRateAllocator::GetMaxBitrate(codec).bps<int>());
|
||||
streams[0].min_bitrate_bps = codec.spatialLayers[0].minBitrate * 1000;
|
||||
// target_bitrate_bps specifies the maximum padding bitrate.
|
||||
streams[0].target_bitrate_bps =
|
||||
SvcRateAllocator::GetPaddingBitrate(codec).bps<int>();
|
||||
}
|
||||
|
||||
char log_stream_buf[4 * 1024];
|
||||
rtc::SimpleStringBuilder log_stream(log_stream_buf);
|
||||
log_stream << "ReconfigureEncoder:\n";
|
||||
@ -717,8 +705,26 @@ void VideoStreamEncoder::ReconfigureEncoder() {
|
||||
|
||||
pending_encoder_reconfiguration_ = false;
|
||||
|
||||
bool is_svc = false;
|
||||
// Set min_bitrate_bps, max_bitrate_bps, and max padding bit rate for VP9
|
||||
// and leave only one stream containing all necessary information.
|
||||
if (encoder_config_.codec_type == kVideoCodecVP9) {
|
||||
// Lower max bitrate to the level codec actually can produce.
|
||||
streams[0].max_bitrate_bps =
|
||||
std::min(streams[0].max_bitrate_bps,
|
||||
SvcRateAllocator::GetMaxBitrate(codec).bps<int>());
|
||||
streams[0].min_bitrate_bps = codec.spatialLayers[0].minBitrate * 1000;
|
||||
// target_bitrate_bps specifies the maximum padding bitrate.
|
||||
streams[0].target_bitrate_bps =
|
||||
SvcRateAllocator::GetPaddingBitrate(codec).bps<int>();
|
||||
streams[0].width = streams.back().width;
|
||||
streams[0].height = streams.back().height;
|
||||
is_svc = codec.VP9()->numberOfSpatialLayers > 1;
|
||||
streams.resize(1);
|
||||
}
|
||||
|
||||
sink_->OnEncoderConfigurationChanged(
|
||||
std::move(streams), encoder_config_.content_type,
|
||||
std::move(streams), is_svc, encoder_config_.content_type,
|
||||
encoder_config_.min_transmit_bitrate_bps);
|
||||
|
||||
resource_adaptation_processor_->ConfigureQualityScaler(info);
|
||||
|
||||
@ -1141,6 +1141,7 @@ class VideoStreamEncoderTest : public ::testing::Test {
|
||||
|
||||
void OnEncoderConfigurationChanged(
|
||||
std::vector<VideoStream> streams,
|
||||
bool is_svc,
|
||||
VideoEncoderConfig::ContentType content_type,
|
||||
int min_transmit_bitrate_bps) override {
|
||||
rtc::CritScope lock(&crit_);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user