Enable VP8 configuration via scalability mode

Bug: webrtc:13959
Change-Id: I16054506ca4086767323443fb9b1e623224e234d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/258791
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36884}
This commit is contained in:
Niels Möller
2022-05-13 13:34:37 +02:00
committed by WebRTC LUCI CQ
parent fb9ae767aa
commit 059548919b
7 changed files with 189 additions and 19 deletions

View File

@ -285,6 +285,7 @@ rtc_library("video_coding") {
":timing",
":video_codec_interface",
":video_coding_utility",
":webrtc_vp8_scalability",
":webrtc_vp9_helpers",
"..:module_api",
"..:module_api_public",
@ -346,6 +347,7 @@ rtc_library("video_coding") {
"../rtp_rtcp:rtp_rtcp_format",
"../rtp_rtcp:rtp_video_header",
"codecs/av1:av1_svc_config",
"svc:scalability_mode_util",
]
absl_deps = [
"//third_party/abseil-cpp/absl/base:core_headers",
@ -656,6 +658,7 @@ rtc_library("webrtc_vp8") {
":video_codec_interface",
":video_coding_utility",
":webrtc_libvpx_interface",
":webrtc_vp8_scalability",
":webrtc_vp8_temporal_layers",
"../../api:fec_controller_api",
"../../api:scoped_refptr",
@ -676,6 +679,7 @@ rtc_library("webrtc_vp8") {
"../../rtc_base/experiments:rate_control_settings",
"../../system_wrappers:field_trial",
"../../system_wrappers:metrics",
"svc:scalability_mode_util",
"//third_party/libyuv",
]
absl_deps = [

View File

@ -29,7 +29,9 @@
#include "api/video_codecs/vp8_temporal_layers_factory.h"
#include "modules/video_coding/codecs/interface/common_constants.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "modules/video_coding/codecs/vp8/vp8_scalability.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "modules/video_coding/svc/scalability_mode_util.h"
#include "modules/video_coding/utility/simulcast_rate_allocator.h"
#include "modules/video_coding/utility/simulcast_utility.h"
#include "rtc_base/checks.h"
@ -444,6 +446,13 @@ int LibvpxVp8Encoder::InitEncode(const VideoCodec* inst,
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}
if (absl::optional<ScalabilityMode> scalability_mode =
inst->GetScalabilityMode();
scalability_mode.has_value() &&
!VP8SupportsScalabilityMode(*scalability_mode)) {
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}
num_active_streams_ = 0;
for (int i = 0; i < inst->numberOfSimulcastStreams; ++i) {
if (inst->simulcastStream[i].active) {

View File

@ -139,4 +139,47 @@ absl::string_view ScalabilityModeToString(ScalabilityMode scalability_mode) {
RTC_CHECK_NOTREACHED();
}
int ScalabilityModeToNumTemporalLayers(ScalabilityMode scalability_mode) {
switch (scalability_mode) {
case ScalabilityMode::kL1T1:
return 1;
case ScalabilityMode::kL1T2:
case ScalabilityMode::kL1T2h:
return 2;
case ScalabilityMode::kL1T3:
case ScalabilityMode::kL1T3h:
return 3;
case ScalabilityMode::kL2T1:
case ScalabilityMode::kL2T1h:
case ScalabilityMode::kL2T1_KEY:
return 1;
case ScalabilityMode::kL2T2:
case ScalabilityMode::kL2T2h:
case ScalabilityMode::kL2T2_KEY:
case ScalabilityMode::kL2T2_KEY_SHIFT:
return 2;
case ScalabilityMode::kL2T3:
case ScalabilityMode::kL2T3h:
case ScalabilityMode::kL2T3_KEY:
return 3;
case ScalabilityMode::kL3T1:
case ScalabilityMode::kL3T1h:
case ScalabilityMode::kL3T1_KEY:
return 1;
case ScalabilityMode::kL3T2:
case ScalabilityMode::kL3T2h:
case ScalabilityMode::kL3T2_KEY:
return 2;
case ScalabilityMode::kL3T3:
case ScalabilityMode::kL3T3h:
case ScalabilityMode::kL3T3_KEY:
return 3;
case ScalabilityMode::kS2T1:
return 1;
case ScalabilityMode::kS3T3:
return 3;
}
RTC_CHECK_NOTREACHED();
}
} // namespace webrtc

View File

@ -22,6 +22,8 @@ absl::optional<ScalabilityMode> ScalabilityModeFromString(
absl::string_view ScalabilityModeToString(ScalabilityMode scalability_mode);
int ScalabilityModeToNumTemporalLayers(ScalabilityMode scalability_mode);
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_SVC_SCALABILITY_MODE_UTIL_H_

View File

@ -21,8 +21,10 @@
#include "api/video/video_bitrate_allocation.h"
#include "api/video_codecs/video_encoder.h"
#include "modules/video_coding/codecs/av1/av1_svc_config.h"
#include "modules/video_coding/codecs/vp8/vp8_scalability.h"
#include "modules/video_coding/codecs/vp9/svc_config.h"
#include "modules/video_coding/include/video_coding_defines.h"
#include "modules/video_coding/svc/scalability_mode_util.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/logging.h"
@ -114,8 +116,14 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
sim_stream->qpMax = streams[i].max_qp;
int num_temporal_layers =
streams[i].scalability_mode.has_value()
? ScalabilityModeToNumTemporalLayers(*streams[i].scalability_mode)
: streams[i].num_temporal_layers.value_or(1);
sim_stream->numberOfTemporalLayers =
static_cast<unsigned char>(streams[i].num_temporal_layers.value_or(1));
static_cast<unsigned char>(num_temporal_layers);
sim_stream->active = streams[i].active;
video_codec.width =
@ -130,9 +138,16 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
static_cast<unsigned int>(streams[i].max_qp));
max_framerate = std::max(max_framerate, streams[i].max_framerate);
// TODO(bugs.webrtc.org/11607): Since scalability mode is a top-level
// setting on VideoCodec, setting it makes sense only if it is the same for
// all simulcast streams.
if (streams[0].scalability_mode != streams[i].scalability_mode) {
RTC_LOG(LS_WARNING) << "Inconsistent scalability modes configured.";
scalability_mode.reset();
// For VP8, top-level scalability mode doesn't matter, since configuration
// is based on the per-simulcast stream configuration of temporal layers.
if (video_codec.codecType != kVideoCodecVP8) {
RTC_LOG(LS_WARNING) << "Inconsistent scalability modes configured.";
}
}
}
@ -167,9 +182,26 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
*video_codec.VP8() = VideoEncoder::GetDefaultVp8Settings();
}
video_codec.VP8()->numberOfTemporalLayers = static_cast<unsigned char>(
streams.back().num_temporal_layers.value_or(
video_codec.VP8()->numberOfTemporalLayers));
// Validate specified scalability modes. If some layer has an unsupported
// mode, store it as the top-level scalability mode, which will make
// InitEncode fail with an appropriate error.
for (const auto& stream : streams) {
if (stream.scalability_mode.has_value() &&
!VP8SupportsScalabilityMode(*stream.scalability_mode)) {
RTC_LOG(LS_WARNING)
<< "Invalid scalability mode for VP8: "
<< ScalabilityModeToString(*stream.scalability_mode);
video_codec.SetScalabilityMode(*stream.scalability_mode);
break;
}
}
video_codec.VP8()->numberOfTemporalLayers =
streams.back().scalability_mode.has_value()
? ScalabilityModeToNumTemporalLayers(
*streams.back().scalability_mode)
: streams.back().num_temporal_layers.value_or(
video_codec.VP8()->numberOfTemporalLayers);
RTC_DCHECK_GE(video_codec.VP8()->numberOfTemporalLayers, 1);
RTC_DCHECK_LE(video_codec.VP8()->numberOfTemporalLayers,
kMaxTemporalStreams);