2014-11-01 06:10:48 +00:00
|
|
|
/*
|
2020-12-09 20:58:21 +01:00
|
|
|
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
|
2014-11-01 06:10:48 +00:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2022-12-06 10:09:10 +00:00
|
|
|
#include <memory>
|
2018-11-19 09:52:37 +01:00
|
|
|
#ifdef RTC_ENABLE_VP9
|
|
|
|
|
|
2018-05-28 12:26:36 +02:00
|
|
|
#include <algorithm>
|
2018-05-31 16:00:24 +02:00
|
|
|
#include <limits>
|
2022-12-06 10:09:10 +00:00
|
|
|
#include <tuple>
|
2019-09-25 09:10:33 +00:00
|
|
|
#include <utility>
|
2014-11-01 06:10:48 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
#include "absl/algorithm/container.h"
|
Use absl::make_unique and absl::WrapUnique directly
Instead of going through our wrappers in ptr_util.h.
This CL was generated by the following script:
git grep -l ptr_util | xargs perl -pi -e 's,#include "rtc_base/ptr_util.h",#include "absl/memory/memory.h",'
git grep -l MakeUnique | xargs perl -pi -e 's,\b(rtc::)?MakeUnique\b,absl::make_unique,g'
git grep -l WrapUnique | xargs perl -pi -e 's,\b(rtc::)?WrapUnique\b,absl::WrapUnique,g'
git checkout -- rtc_base/ptr_util{.h,_unittest.cc}
git cl format
Followed by manually adding dependencies on
//third_party/abseil-cpp/absl/memory until `gn check` stopped
complaining.
Bug: webrtc:9473
Change-Id: I89ccd363f070479b8c431eb2c3d404a46eaacc1c
Reviewed-on: https://webrtc-review.googlesource.com/86600
Commit-Queue: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23850}
2018-07-05 11:40:33 +02:00
|
|
|
#include "absl/memory/memory.h"
|
2020-10-01 19:13:13 +02:00
|
|
|
#include "absl/strings/match.h"
|
2022-12-06 10:09:10 +00:00
|
|
|
#include "absl/types/optional.h"
|
2018-07-16 10:01:49 -07:00
|
|
|
#include "api/video/color_space.h"
|
2018-07-13 17:10:00 -07:00
|
|
|
#include "api/video/i010_buffer.h"
|
2022-12-06 10:09:10 +00:00
|
|
|
#include "api/video_codecs/scalability_mode.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "common_video/include/video_frame_buffer.h"
|
|
|
|
|
#include "common_video/libyuv/include/webrtc_libyuv.h"
|
2018-05-18 17:31:19 +02:00
|
|
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
2022-12-06 10:09:10 +00:00
|
|
|
#include "modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h"
|
2020-10-15 17:26:46 +02:00
|
|
|
#include "modules/video_coding/svc/create_scalability_structure.h"
|
2022-04-29 11:03:13 +02:00
|
|
|
#include "modules/video_coding/svc/scalability_mode_util.h"
|
2020-10-15 17:26:46 +02:00
|
|
|
#include "modules/video_coding/svc/scalable_video_controller.h"
|
|
|
|
|
#include "modules/video_coding/svc/scalable_video_controller_no_layering.h"
|
2021-07-27 12:48:50 +02:00
|
|
|
#include "modules/video_coding/svc/svc_rate_allocator.h"
|
Reland "VP9 decoder: Sets thread count based on resolution, reinit on change."
This is a reland of d5925756980f6e82a55f57532c8d855e954459fb
Patchset 2 is a reland of
https://webrtc-review.googlesource.com/c/src/+/177012
Patchset 3 is a fix for a potential crash when InitDecode()is called from
VideoStreamDecoderImpl::GetDecoder(), where the decoder_settings
parameter is a but surprisingly set to nullptr.
Original change's description:
> VP9 decoder: Sets thread count based on resolution, reinit on change.
>
> Previously, number of decoder threads for VP9 were always set to 8 but
> with a cap at number of cores. This was done since we "can't know" the
> resolution that will be used.
>
> With this change, we now intialize the number of threads based on
> resolution given in InitDecode(). If a resolution change happens in
> flight, it requires a keyframe. We therefore parse the header from
> any key frame and if it has a new resolution, we re-initialize the
> decoder.
>
> The number of threads used is based on pixel count. We set one thread
> as target for 1280x720, and scale up lineraly from there. The 8-thread
> cap is gone, but still limit it core count.
>
> This means for instance: 1 <= 720p, 2 for 1080p, 4 for 1440p, 9 for 4K.
>
> Bug: webrtc:11551
> Change-Id: I14c169a6c651c50bd1b870c4b22bc4495c8448fd
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174460
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#31507}
Bug: webrtc:11551
Change-Id: I2b4b146d0b8319f07ce1660202d6aa4b374eb015
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/177246
Reviewed-by: Johannes Kron <kron@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31527}
2020-06-15 16:52:13 +02:00
|
|
|
#include "modules/video_coding/utility/vp9_uncompressed_header_parser.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/checks.h"
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
#include "rtc_base/experiments/field_trial_list.h"
|
2020-10-01 19:13:13 +02:00
|
|
|
#include "rtc_base/experiments/field_trial_parser.h"
|
2019-01-23 12:48:13 +01:00
|
|
|
#include "rtc_base/experiments/rate_control_settings.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/logging.h"
|
2020-10-15 17:26:46 +02:00
|
|
|
#include "rtc_base/strings/string_builder.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "rtc_base/time_utils.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/trace_event.h"
|
2020-09-29 10:37:32 +02:00
|
|
|
#include "third_party/libyuv/include/libyuv/convert.h"
|
2014-11-01 06:10:48 +00:00
|
|
|
#include "vpx/vp8cx.h"
|
|
|
|
|
#include "vpx/vpx_encoder.h"
|
|
|
|
|
|
2023-10-06 13:18:41 +02:00
|
|
|
#if (defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)) && \
|
|
|
|
|
(defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS))
|
|
|
|
|
#define MOBILE_ARM
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-11-01 06:10:48 +00:00
|
|
|
namespace webrtc {
|
|
|
|
|
|
2018-05-18 17:31:19 +02:00
|
|
|
namespace {
|
2018-10-01 17:13:50 +02:00
|
|
|
// Maps from gof_idx to encoder internal reference frame buffer index. These
|
|
|
|
|
// maps work for 1,2 and 3 temporal layers with GOF length of 1,2 and 4 frames.
|
|
|
|
|
uint8_t kRefBufIdx[4] = {0, 0, 0, 1};
|
|
|
|
|
uint8_t kUpdBufIdx[4] = {0, 0, 1, 0};
|
|
|
|
|
|
2019-03-06 16:04:32 +01:00
|
|
|
// Maximum allowed PID difference for differnet per-layer frame-rate case.
|
2019-09-06 13:12:52 +02:00
|
|
|
const int kMaxAllowedPidDiff = 30;
|
2018-12-04 15:54:52 +01:00
|
|
|
|
2020-06-18 19:16:53 +02:00
|
|
|
// TODO(ilink): Tune these thresholds further.
|
|
|
|
|
// Selected using ConverenceMotion_1280_720_50.yuv clip.
|
|
|
|
|
// No toggling observed on any link capacity from 100-2000kbps.
|
|
|
|
|
// HD was reached consistently when link capacity was 1500kbps.
|
|
|
|
|
// Set resolutions are a bit more conservative than svc_config.cc sets, e.g.
|
|
|
|
|
// for 300kbps resolution converged to 270p instead of 360p.
|
|
|
|
|
constexpr int kLowVp9QpThreshold = 149;
|
|
|
|
|
constexpr int kHighVp9QpThreshold = 205;
|
|
|
|
|
|
2019-09-25 09:10:33 +00:00
|
|
|
std::pair<size_t, size_t> GetActiveLayers(
|
|
|
|
|
const VideoBitrateAllocation& allocation) {
|
2018-12-04 15:54:52 +01:00
|
|
|
for (size_t sl_idx = 0; sl_idx < kMaxSpatialLayers; ++sl_idx) {
|
2019-09-25 09:10:33 +00:00
|
|
|
if (allocation.GetSpatialLayerSum(sl_idx) > 0) {
|
|
|
|
|
size_t last_layer = sl_idx + 1;
|
|
|
|
|
while (last_layer < kMaxSpatialLayers &&
|
|
|
|
|
allocation.GetSpatialLayerSum(last_layer) > 0) {
|
|
|
|
|
++last_layer;
|
|
|
|
|
}
|
|
|
|
|
return std::make_pair(sl_idx, last_layer);
|
2018-12-04 15:54:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-09-25 09:10:33 +00:00
|
|
|
return {0, 0};
|
2018-12-04 15:54:52 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-06 10:09:10 +00:00
|
|
|
using Vp9ScalabilityStructure =
|
|
|
|
|
std::tuple<std::unique_ptr<ScalableVideoController>, ScalabilityMode>;
|
|
|
|
|
absl::optional<Vp9ScalabilityStructure> CreateVp9ScalabilityStructure(
|
2020-10-15 17:26:46 +02:00
|
|
|
const VideoCodec& codec) {
|
|
|
|
|
int num_spatial_layers = codec.VP9().numberOfSpatialLayers;
|
|
|
|
|
int num_temporal_layers =
|
|
|
|
|
std::max(1, int{codec.VP9().numberOfTemporalLayers});
|
|
|
|
|
if (num_spatial_layers == 1 && num_temporal_layers == 1) {
|
2022-12-06 10:09:10 +00:00
|
|
|
return absl::make_optional<Vp9ScalabilityStructure>(
|
|
|
|
|
std::make_unique<ScalableVideoControllerNoLayering>(),
|
|
|
|
|
ScalabilityMode::kL1T1);
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char name[20];
|
|
|
|
|
rtc::SimpleStringBuilder ss(name);
|
2020-10-20 13:06:59 +02:00
|
|
|
if (codec.mode == VideoCodecMode::kScreensharing) {
|
|
|
|
|
// TODO(bugs.webrtc.org/11999): Compose names of the structures when they
|
|
|
|
|
// are implemented.
|
2022-12-06 10:09:10 +00:00
|
|
|
return absl::nullopt;
|
2020-10-20 13:06:59 +02:00
|
|
|
} else if (codec.VP9().interLayerPred == InterLayerPredMode::kOn ||
|
|
|
|
|
num_spatial_layers == 1) {
|
|
|
|
|
ss << "L" << num_spatial_layers << "T" << num_temporal_layers;
|
|
|
|
|
} else if (codec.VP9().interLayerPred == InterLayerPredMode::kOnKeyPic) {
|
|
|
|
|
ss << "L" << num_spatial_layers << "T" << num_temporal_layers << "_KEY";
|
|
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK_EQ(codec.VP9().interLayerPred, InterLayerPredMode::kOff);
|
|
|
|
|
ss << "S" << num_spatial_layers << "T" << num_temporal_layers;
|
|
|
|
|
}
|
2020-10-15 17:26:46 +02:00
|
|
|
|
|
|
|
|
// Check spatial ratio.
|
|
|
|
|
if (num_spatial_layers > 1 && codec.spatialLayers[0].targetBitrate > 0) {
|
|
|
|
|
if (codec.width != codec.spatialLayers[num_spatial_layers - 1].width ||
|
|
|
|
|
codec.height != codec.spatialLayers[num_spatial_layers - 1].height) {
|
|
|
|
|
RTC_LOG(LS_WARNING)
|
|
|
|
|
<< "Top layer resolution expected to match overall resolution";
|
2022-12-06 10:09:10 +00:00
|
|
|
return absl::nullopt;
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
// Check if the ratio is one of the supported.
|
|
|
|
|
int numerator;
|
|
|
|
|
int denominator;
|
|
|
|
|
if (codec.spatialLayers[1].width == 2 * codec.spatialLayers[0].width) {
|
|
|
|
|
numerator = 1;
|
|
|
|
|
denominator = 2;
|
|
|
|
|
// no suffix for 1:2 ratio.
|
|
|
|
|
} else if (2 * codec.spatialLayers[1].width ==
|
|
|
|
|
3 * codec.spatialLayers[0].width) {
|
|
|
|
|
numerator = 2;
|
|
|
|
|
denominator = 3;
|
|
|
|
|
ss << "h";
|
|
|
|
|
} else {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Unsupported scalability ratio "
|
|
|
|
|
<< codec.spatialLayers[0].width << ":"
|
|
|
|
|
<< codec.spatialLayers[1].width;
|
2022-12-06 10:09:10 +00:00
|
|
|
return absl::nullopt;
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
// Validate ratio is consistent for all spatial layer transitions.
|
|
|
|
|
for (int sid = 1; sid < num_spatial_layers; ++sid) {
|
|
|
|
|
if (codec.spatialLayers[sid].width * numerator !=
|
|
|
|
|
codec.spatialLayers[sid - 1].width * denominator ||
|
|
|
|
|
codec.spatialLayers[sid].height * numerator !=
|
|
|
|
|
codec.spatialLayers[sid - 1].height * denominator) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Inconsistent scalability ratio " << numerator
|
|
|
|
|
<< ":" << denominator;
|
2022-12-06 10:09:10 +00:00
|
|
|
return absl::nullopt;
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-29 11:03:13 +02:00
|
|
|
absl::optional<ScalabilityMode> scalability_mode =
|
|
|
|
|
ScalabilityModeFromString(name);
|
|
|
|
|
if (!scalability_mode.has_value()) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Invalid scalability mode " << name;
|
2022-12-06 10:09:10 +00:00
|
|
|
return absl::nullopt;
|
2022-04-29 11:03:13 +02:00
|
|
|
}
|
|
|
|
|
auto scalability_structure_controller =
|
|
|
|
|
CreateScalabilityStructure(*scalability_mode);
|
2020-10-15 17:26:46 +02:00
|
|
|
if (scalability_structure_controller == nullptr) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Unsupported scalability structure " << name;
|
|
|
|
|
} else {
|
|
|
|
|
RTC_LOG(LS_INFO) << "Created scalability structure " << name;
|
|
|
|
|
}
|
2022-12-06 10:09:10 +00:00
|
|
|
return absl::make_optional<Vp9ScalabilityStructure>(
|
|
|
|
|
std::move(scalability_structure_controller), *scalability_mode);
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpx_svc_ref_frame_config_t Vp9References(
|
|
|
|
|
rtc::ArrayView<const ScalableVideoController::LayerFrameConfig> layers) {
|
|
|
|
|
vpx_svc_ref_frame_config_t ref_config = {};
|
|
|
|
|
for (const ScalableVideoController::LayerFrameConfig& layer_frame : layers) {
|
|
|
|
|
const auto& buffers = layer_frame.Buffers();
|
|
|
|
|
RTC_DCHECK_LE(buffers.size(), 3);
|
|
|
|
|
int sid = layer_frame.SpatialId();
|
|
|
|
|
if (!buffers.empty()) {
|
|
|
|
|
ref_config.lst_fb_idx[sid] = buffers[0].id;
|
|
|
|
|
ref_config.reference_last[sid] = buffers[0].referenced;
|
|
|
|
|
if (buffers[0].updated) {
|
|
|
|
|
ref_config.update_buffer_slot[sid] |= (1 << buffers[0].id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (buffers.size() > 1) {
|
|
|
|
|
ref_config.gld_fb_idx[sid] = buffers[1].id;
|
|
|
|
|
ref_config.reference_golden[sid] = buffers[1].referenced;
|
|
|
|
|
if (buffers[1].updated) {
|
|
|
|
|
ref_config.update_buffer_slot[sid] |= (1 << buffers[1].id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (buffers.size() > 2) {
|
|
|
|
|
ref_config.alt_fb_idx[sid] = buffers[2].id;
|
|
|
|
|
ref_config.reference_alt_ref[sid] = buffers[2].referenced;
|
|
|
|
|
if (buffers[2].updated) {
|
|
|
|
|
ref_config.update_buffer_slot[sid] |= (1 << buffers[2].id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// TODO(bugs.webrtc.org/11999): Fill ref_config.duration
|
|
|
|
|
return ref_config;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-30 14:06:13 +02:00
|
|
|
bool AllowDenoising() {
|
2023-10-06 13:18:41 +02:00
|
|
|
#ifdef MOBILE_ARM
|
|
|
|
|
// Keep the denoiser disabled on mobile ARM devices. It increases encode time
|
|
|
|
|
// by up to 16%.
|
2022-03-30 14:06:13 +02:00
|
|
|
return false;
|
2023-10-06 13:18:41 +02:00
|
|
|
#else
|
|
|
|
|
return true;
|
2022-03-30 14:06:13 +02:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 17:50:43 -07:00
|
|
|
} // namespace
|
2015-07-07 14:40:38 -07:00
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::EncoderOutputCodedPacketCallback(vpx_codec_cx_pkt* pkt,
|
|
|
|
|
void* user_data) {
|
|
|
|
|
LibvpxVp9Encoder* enc = static_cast<LibvpxVp9Encoder*>(user_data);
|
2015-07-31 06:10:09 -07:00
|
|
|
enc->GetEncodedLayerFrame(pkt);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
LibvpxVp9Encoder::LibvpxVp9Encoder(const cricket::VideoCodec& codec,
|
|
|
|
|
std::unique_ptr<LibvpxInterface> interface,
|
2022-03-29 11:04:48 +02:00
|
|
|
const FieldTrialsView& trials)
|
2020-12-09 20:58:21 +01:00
|
|
|
: libvpx_(std::move(interface)),
|
|
|
|
|
encoded_image_(),
|
2017-08-17 08:12:10 -07:00
|
|
|
encoded_complete_callback_(nullptr),
|
2018-06-28 10:59:02 -07:00
|
|
|
profile_(
|
|
|
|
|
ParseSdpForVP9Profile(codec.params).value_or(VP9Profile::kProfile0)),
|
2014-11-01 06:10:48 +00:00
|
|
|
inited_(false),
|
|
|
|
|
timestamp_(0),
|
|
|
|
|
rc_max_intra_target_(0),
|
2017-08-17 08:12:10 -07:00
|
|
|
encoder_(nullptr),
|
|
|
|
|
config_(nullptr),
|
|
|
|
|
raw_(nullptr),
|
|
|
|
|
input_image_(nullptr),
|
2018-05-03 14:14:09 +02:00
|
|
|
force_key_frame_(true),
|
2018-04-26 11:03:49 +02:00
|
|
|
pics_since_key_(0),
|
2015-07-31 06:10:09 -07:00
|
|
|
num_temporal_layers_(0),
|
Reland of Work on flexible mode and screen sharing. (patchset #1 id:1 of https://codereview.webrtc.org/1438543002/ )
Reason for revert:
Failed test not related to this CL (test fails on
master at an earlier date), re-landing original CL..
(This time from my @webrtc account.)
Original issue's description:
> Revert of Work on flexible mode and screen sharing. (patchset #28 id:520001 of https://codereview.webrtc.org/1328113004/ )
>
> Reason for revert:
> Seems to break VideoSendStreamTest.ReconfigureBitratesSetsEncoderBitratesCorrectly on Linux Memcheck buildbot.
>
> Original issue's description:
> > Work on flexible mode and screen sharing.
> >
> > Implement VP8 style screensharing but with spatial layers.
> > Implement flexible mode.
> >
> > Files from other patches:
> > generic_encoder.cc
> > layer_filtering_transport.cc
> >
> > BUG=webrtc:4914
> >
> > Committed: https://crrev.com/77ccfb4d16c148e61a316746bb5d9705e8b39f4a
> > Cr-Commit-Position: refs/heads/master@{#10572}
>
> TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,philipel@webrtc.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:4914
>
> Committed: https://crrev.com/0be8f1d347bdb171462df89c2a4c69b3f3eb7519
> Cr-Commit-Position: refs/heads/master@{#10578}
TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,terelius@webrtc.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:4914
Review URL: https://codereview.webrtc.org/1431283002
Cr-Commit-Position: refs/heads/master@{#10581}
2015-11-10 07:17:23 -08:00
|
|
|
num_spatial_layers_(0),
|
2018-10-01 17:13:50 +02:00
|
|
|
num_active_spatial_layers_(0),
|
2019-09-25 09:10:33 +00:00
|
|
|
first_active_layer_(0),
|
2020-10-01 19:13:13 +02:00
|
|
|
layer_deactivation_requires_key_frame_(absl::StartsWith(
|
|
|
|
|
trials.Lookup("WebRTC-Vp9IssueKeyFrameOnLayerDeactivation"),
|
|
|
|
|
"Enabled")),
|
2018-05-28 12:26:36 +02:00
|
|
|
is_svc_(false),
|
2018-04-26 11:03:49 +02:00
|
|
|
inter_layer_pred_(InterLayerPredMode::kOn),
|
2018-12-04 15:54:52 +01:00
|
|
|
external_ref_control_(false), // Set in InitEncode because of tests.
|
2020-10-01 19:13:13 +02:00
|
|
|
trusted_rate_controller_(
|
|
|
|
|
RateControlSettings::ParseFromKeyValueConfig(&trials)
|
|
|
|
|
.LibvpxVp9TrustedRateController()),
|
2018-11-23 13:59:24 +01:00
|
|
|
first_frame_in_picture_(true),
|
2018-12-04 15:54:52 +01:00
|
|
|
ss_info_needed_(false),
|
2019-09-25 09:10:33 +00:00
|
|
|
force_all_active_layers_(false),
|
2019-03-06 16:04:32 +01:00
|
|
|
is_flexible_mode_(false),
|
2020-10-01 19:13:13 +02:00
|
|
|
variable_framerate_experiment_(ParseVariableFramerateConfig(trials)),
|
2019-03-06 16:04:32 +01:00
|
|
|
variable_framerate_controller_(
|
|
|
|
|
variable_framerate_experiment_.framerate_limit),
|
2020-10-01 19:13:13 +02:00
|
|
|
quality_scaler_experiment_(ParseQualityScalerConfig(trials)),
|
|
|
|
|
external_ref_ctrl_(
|
|
|
|
|
!absl::StartsWith(trials.Lookup("WebRTC-Vp9ExternalRefCtrl"),
|
|
|
|
|
"Disabled")),
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
performance_flags_(ParsePerformanceFlagsFromTrials(trials)),
|
2020-02-21 10:47:10 -08:00
|
|
|
num_steady_state_frames_(0),
|
|
|
|
|
config_changed_(true) {
|
2019-03-01 13:53:55 +01:00
|
|
|
codec_ = {};
|
2017-01-26 13:23:44 -08:00
|
|
|
memset(&svc_params_, 0, sizeof(vpx_svc_extra_cfg_t));
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
LibvpxVp9Encoder::~LibvpxVp9Encoder() {
|
2014-11-01 06:10:48 +00:00
|
|
|
Release();
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::SetFecControllerOverride(FecControllerOverride*) {
|
2019-06-28 15:19:43 +02:00
|
|
|
// Ignored.
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
int LibvpxVp9Encoder::Release() {
|
2018-03-02 13:11:04 +01:00
|
|
|
int ret_val = WEBRTC_VIDEO_CODEC_OK;
|
|
|
|
|
|
2017-08-17 08:12:10 -07:00
|
|
|
if (encoder_ != nullptr) {
|
2018-03-02 14:44:10 +01:00
|
|
|
if (inited_) {
|
2020-12-13 14:50:59 +01:00
|
|
|
if (libvpx_->codec_destroy(encoder_)) {
|
2018-03-02 14:44:10 +01:00
|
|
|
ret_val = WEBRTC_VIDEO_CODEC_MEMORY;
|
|
|
|
|
}
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
delete encoder_;
|
2017-08-17 08:12:10 -07:00
|
|
|
encoder_ = nullptr;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2017-08-17 08:12:10 -07:00
|
|
|
if (config_ != nullptr) {
|
2014-11-01 06:10:48 +00:00
|
|
|
delete config_;
|
2017-08-17 08:12:10 -07:00
|
|
|
config_ = nullptr;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2017-08-17 08:12:10 -07:00
|
|
|
if (raw_ != nullptr) {
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->img_free(raw_);
|
2017-08-17 08:12:10 -07:00
|
|
|
raw_ = nullptr;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
inited_ = false;
|
2018-03-02 13:11:04 +01:00
|
|
|
return ret_val;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
bool LibvpxVp9Encoder::ExplicitlyConfiguredSpatialLayers() const {
|
2015-11-02 07:23:20 -08:00
|
|
|
// We check target_bitrate_bps of the 0th layer to see if the spatial layers
|
|
|
|
|
// (i.e. bitrates) were explicitly configured.
|
2018-09-11 11:40:25 +02:00
|
|
|
return codec_.spatialLayers[0].targetBitrate > 0;
|
2015-11-02 07:23:20 -08:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
bool LibvpxVp9Encoder::SetSvcRates(
|
2018-04-23 12:32:22 +02:00
|
|
|
const VideoBitrateAllocation& bitrate_allocation) {
|
2019-09-25 09:10:33 +00:00
|
|
|
std::pair<size_t, size_t> current_layers =
|
|
|
|
|
GetActiveLayers(current_bitrate_allocation_);
|
|
|
|
|
std::pair<size_t, size_t> new_layers = GetActiveLayers(bitrate_allocation);
|
|
|
|
|
|
|
|
|
|
const bool layer_activation_requires_key_frame =
|
|
|
|
|
inter_layer_pred_ == InterLayerPredMode::kOff ||
|
|
|
|
|
inter_layer_pred_ == InterLayerPredMode::kOnKeyPic;
|
|
|
|
|
const bool lower_layers_enabled = new_layers.first < current_layers.first;
|
|
|
|
|
const bool higher_layers_enabled = new_layers.second > current_layers.second;
|
|
|
|
|
const bool disabled_layers = new_layers.first > current_layers.first ||
|
|
|
|
|
new_layers.second < current_layers.second;
|
|
|
|
|
|
|
|
|
|
if (lower_layers_enabled ||
|
|
|
|
|
(higher_layers_enabled && layer_activation_requires_key_frame) ||
|
|
|
|
|
(disabled_layers && layer_deactivation_requires_key_frame_)) {
|
|
|
|
|
force_key_frame_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (current_layers != new_layers) {
|
|
|
|
|
ss_info_needed_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-28 19:32:37 +02:00
|
|
|
config_->rc_target_bitrate = bitrate_allocation.get_sum_kbps();
|
|
|
|
|
|
2015-11-02 07:23:20 -08:00
|
|
|
if (ExplicitlyConfiguredSpatialLayers()) {
|
2018-03-28 19:32:37 +02:00
|
|
|
for (size_t sl_idx = 0; sl_idx < num_spatial_layers_; ++sl_idx) {
|
2018-10-03 18:04:57 +02:00
|
|
|
const bool was_layer_active = (config_->ss_target_bitrate[sl_idx] > 0);
|
2018-03-28 19:32:37 +02:00
|
|
|
config_->ss_target_bitrate[sl_idx] =
|
|
|
|
|
bitrate_allocation.GetSpatialLayerSum(sl_idx) / 1000;
|
|
|
|
|
|
|
|
|
|
for (size_t tl_idx = 0; tl_idx < num_temporal_layers_; ++tl_idx) {
|
|
|
|
|
config_->layer_target_bitrate[sl_idx * num_temporal_layers_ + tl_idx] =
|
|
|
|
|
bitrate_allocation.GetTemporalLayerSum(sl_idx, tl_idx) / 1000;
|
|
|
|
|
}
|
2018-05-03 14:14:09 +02:00
|
|
|
|
2018-10-03 18:04:57 +02:00
|
|
|
if (!was_layer_active) {
|
2018-09-05 21:07:17 +02:00
|
|
|
// Reset frame rate controller if layer is resumed after pause.
|
|
|
|
|
framerate_controller_[sl_idx].Reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
framerate_controller_[sl_idx].SetTargetRate(
|
2019-05-24 11:51:31 +02:00
|
|
|
codec_.spatialLayers[sl_idx].maxFramerate);
|
2015-11-02 07:23:20 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
float rate_ratio[VPX_MAX_LAYERS] = {0};
|
|
|
|
|
float total = 0;
|
2018-08-20 09:28:45 +02:00
|
|
|
for (int i = 0; i < num_spatial_layers_; ++i) {
|
2017-01-26 13:23:44 -08:00
|
|
|
if (svc_params_.scaling_factor_num[i] <= 0 ||
|
|
|
|
|
svc_params_.scaling_factor_den[i] <= 0) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "Scaling factors not specified!";
|
2015-11-02 07:23:20 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2017-01-26 13:23:44 -08:00
|
|
|
rate_ratio[i] = static_cast<float>(svc_params_.scaling_factor_num[i]) /
|
|
|
|
|
svc_params_.scaling_factor_den[i];
|
2015-11-02 07:23:20 -08:00
|
|
|
total += rate_ratio[i];
|
|
|
|
|
}
|
2015-10-08 05:13:32 -07:00
|
|
|
|
2018-08-20 09:28:45 +02:00
|
|
|
for (int i = 0; i < num_spatial_layers_; ++i) {
|
2018-06-26 13:41:16 +02:00
|
|
|
RTC_CHECK_GT(total, 0);
|
2015-11-02 07:23:20 -08:00
|
|
|
config_->ss_target_bitrate[i] = static_cast<unsigned int>(
|
|
|
|
|
config_->rc_target_bitrate * rate_ratio[i] / total);
|
|
|
|
|
if (num_temporal_layers_ == 1) {
|
|
|
|
|
config_->layer_target_bitrate[i] = config_->ss_target_bitrate[i];
|
|
|
|
|
} else if (num_temporal_layers_ == 2) {
|
|
|
|
|
config_->layer_target_bitrate[i * num_temporal_layers_] =
|
|
|
|
|
config_->ss_target_bitrate[i] * 2 / 3;
|
|
|
|
|
config_->layer_target_bitrate[i * num_temporal_layers_ + 1] =
|
|
|
|
|
config_->ss_target_bitrate[i];
|
|
|
|
|
} else if (num_temporal_layers_ == 3) {
|
|
|
|
|
config_->layer_target_bitrate[i * num_temporal_layers_] =
|
|
|
|
|
config_->ss_target_bitrate[i] / 2;
|
|
|
|
|
config_->layer_target_bitrate[i * num_temporal_layers_ + 1] =
|
|
|
|
|
config_->layer_target_bitrate[i * num_temporal_layers_] +
|
|
|
|
|
(config_->ss_target_bitrate[i] / 4);
|
|
|
|
|
config_->layer_target_bitrate[i * num_temporal_layers_ + 2] =
|
|
|
|
|
config_->ss_target_bitrate[i];
|
|
|
|
|
} else {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "Unsupported number of temporal layers: "
|
|
|
|
|
<< num_temporal_layers_;
|
2015-11-02 07:23:20 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2018-09-05 21:07:17 +02:00
|
|
|
|
|
|
|
|
framerate_controller_[i].SetTargetRate(codec_.maxFramerate);
|
2015-07-31 06:10:09 -07:00
|
|
|
}
|
|
|
|
|
}
|
2018-08-20 09:28:45 +02:00
|
|
|
|
|
|
|
|
num_active_spatial_layers_ = 0;
|
2019-09-25 09:10:33 +00:00
|
|
|
first_active_layer_ = 0;
|
|
|
|
|
bool seen_active_layer = false;
|
|
|
|
|
bool expect_no_more_active_layers = false;
|
2018-08-20 09:28:45 +02:00
|
|
|
for (int i = 0; i < num_spatial_layers_; ++i) {
|
|
|
|
|
if (config_->ss_target_bitrate[i] > 0) {
|
2019-09-25 09:10:33 +00:00
|
|
|
RTC_DCHECK(!expect_no_more_active_layers) << "Only middle layer is "
|
|
|
|
|
"deactivated.";
|
|
|
|
|
if (!seen_active_layer) {
|
|
|
|
|
first_active_layer_ = i;
|
|
|
|
|
}
|
|
|
|
|
num_active_spatial_layers_ = i + 1;
|
|
|
|
|
seen_active_layer = true;
|
|
|
|
|
} else {
|
|
|
|
|
expect_no_more_active_layers = seen_active_layer;
|
2018-08-20 09:28:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-30 14:06:13 +02:00
|
|
|
if (seen_active_layer && performance_flags_.use_per_layer_speed) {
|
|
|
|
|
bool denoiser_on =
|
2022-03-31 16:11:15 +02:00
|
|
|
AllowDenoising() && codec_.VP9()->denoisingOn &&
|
2022-03-30 14:06:13 +02:00
|
|
|
performance_flags_by_spatial_index_[num_active_spatial_layers_ - 1]
|
2022-03-31 16:11:15 +02:00
|
|
|
.allow_denoising;
|
2022-03-30 14:06:13 +02:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY,
|
|
|
|
|
denoiser_on ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-25 09:10:33 +00:00
|
|
|
if (higher_layers_enabled && !force_key_frame_) {
|
|
|
|
|
// Prohibit drop of all layers for the next frame, so newly enabled
|
|
|
|
|
// layer would have a valid spatial reference.
|
|
|
|
|
for (size_t i = 0; i < num_spatial_layers_; ++i) {
|
|
|
|
|
svc_drop_frame_.framedrop_thresh[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
force_all_active_layers_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-15 17:26:46 +02:00
|
|
|
if (svc_controller_) {
|
|
|
|
|
for (int sid = 0; sid < num_spatial_layers_; ++sid) {
|
2021-09-10 12:05:08 +02:00
|
|
|
// Bitrates in `layer_target_bitrate` are accumulated for each temporal
|
|
|
|
|
// layer but in `VideoBitrateAllocation` they should be separated.
|
|
|
|
|
int previous_bitrate_kbps = 0;
|
2020-10-15 17:26:46 +02:00
|
|
|
for (int tid = 0; tid < num_temporal_layers_; ++tid) {
|
2021-09-10 12:05:08 +02:00
|
|
|
int accumulated_bitrate_kbps =
|
|
|
|
|
config_->layer_target_bitrate[sid * num_temporal_layers_ + tid];
|
|
|
|
|
int single_layer_bitrate_kbps =
|
|
|
|
|
accumulated_bitrate_kbps - previous_bitrate_kbps;
|
|
|
|
|
RTC_DCHECK_GE(single_layer_bitrate_kbps, 0);
|
2021-09-10 12:30:09 +02:00
|
|
|
current_bitrate_allocation_.SetBitrate(
|
2021-09-10 12:05:08 +02:00
|
|
|
sid, tid, single_layer_bitrate_kbps * 1'000);
|
|
|
|
|
previous_bitrate_kbps = accumulated_bitrate_kbps;
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
2021-09-10 12:30:09 +02:00
|
|
|
svc_controller_->OnRatesUpdated(current_bitrate_allocation_);
|
|
|
|
|
} else {
|
|
|
|
|
current_bitrate_allocation_ = bitrate_allocation;
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
2020-02-21 10:47:10 -08:00
|
|
|
config_changed_ = true;
|
2015-07-31 06:10:09 -07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-10 12:30:09 +02:00
|
|
|
void LibvpxVp9Encoder::DisableSpatialLayer(int sid) {
|
|
|
|
|
RTC_DCHECK_LT(sid, num_spatial_layers_);
|
|
|
|
|
if (config_->ss_target_bitrate[sid] == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
config_->ss_target_bitrate[sid] = 0;
|
|
|
|
|
for (int tid = 0; tid < num_temporal_layers_; ++tid) {
|
|
|
|
|
config_->layer_target_bitrate[sid * num_temporal_layers_ + tid] = 0;
|
|
|
|
|
}
|
|
|
|
|
config_changed_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LibvpxVp9Encoder::EnableSpatialLayer(int sid) {
|
|
|
|
|
RTC_DCHECK_LT(sid, num_spatial_layers_);
|
|
|
|
|
if (config_->ss_target_bitrate[sid] > 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (int tid = 0; tid < num_temporal_layers_; ++tid) {
|
|
|
|
|
config_->layer_target_bitrate[sid * num_temporal_layers_ + tid] =
|
2022-06-30 15:42:51 +02:00
|
|
|
current_bitrate_allocation_.GetTemporalLayerSum(sid, tid) / 1000;
|
2021-09-10 12:30:09 +02:00
|
|
|
}
|
|
|
|
|
config_->ss_target_bitrate[sid] =
|
|
|
|
|
current_bitrate_allocation_.GetSpatialLayerSum(sid) / 1000;
|
|
|
|
|
RTC_DCHECK_GT(config_->ss_target_bitrate[sid], 0);
|
|
|
|
|
config_changed_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LibvpxVp9Encoder::SetActiveSpatialLayers() {
|
|
|
|
|
// Svc controller may decide to skip a frame at certain spatial layer even
|
|
|
|
|
// when bitrate for it is non-zero, however libvpx uses configured bitrate as
|
|
|
|
|
// a signal which layers should be produced.
|
|
|
|
|
RTC_DCHECK(svc_controller_);
|
|
|
|
|
RTC_DCHECK(!layer_frames_.empty());
|
|
|
|
|
RTC_DCHECK(absl::c_is_sorted(
|
|
|
|
|
layer_frames_, [](const ScalableVideoController::LayerFrameConfig& lhs,
|
|
|
|
|
const ScalableVideoController::LayerFrameConfig& rhs) {
|
|
|
|
|
return lhs.SpatialId() < rhs.SpatialId();
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
auto frame_it = layer_frames_.begin();
|
|
|
|
|
for (int sid = 0; sid < num_spatial_layers_; ++sid) {
|
|
|
|
|
if (frame_it != layer_frames_.end() && frame_it->SpatialId() == sid) {
|
|
|
|
|
EnableSpatialLayer(sid);
|
|
|
|
|
++frame_it;
|
|
|
|
|
} else {
|
|
|
|
|
DisableSpatialLayer(sid);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::SetRates(const RateControlParameters& parameters) {
|
2014-11-01 06:10:48 +00:00
|
|
|
if (!inited_) {
|
2022-05-16 22:37:34 +02:00
|
|
|
RTC_LOG(LS_WARNING) << "SetRates() called while uninitialized.";
|
2019-04-12 13:59:09 +02:00
|
|
|
return;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
if (encoder_->err) {
|
2019-04-12 13:59:09 +02:00
|
|
|
RTC_LOG(LS_WARNING) << "Encoder in error state: " << encoder_->err;
|
|
|
|
|
return;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2019-04-12 13:59:09 +02:00
|
|
|
if (parameters.framerate_fps < 1.0) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Unsupported framerate: "
|
|
|
|
|
<< parameters.framerate_fps;
|
|
|
|
|
return;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2016-11-16 16:41:30 +01:00
|
|
|
|
2019-04-12 13:59:09 +02:00
|
|
|
codec_.maxFramerate = static_cast<uint32_t>(parameters.framerate_fps + 0.5);
|
2019-09-25 09:10:33 +00:00
|
|
|
|
|
|
|
|
bool res = SetSvcRates(parameters.bitrate);
|
|
|
|
|
RTC_DCHECK(res) << "Failed to set new bitrate allocation";
|
2020-02-21 10:47:10 -08:00
|
|
|
config_changed_ = true;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
2019-06-11 14:57:57 +02:00
|
|
|
// TODO(eladalon): s/inst/codec_settings/g.
|
2020-12-09 20:58:21 +01:00
|
|
|
int LibvpxVp9Encoder::InitEncode(const VideoCodec* inst,
|
|
|
|
|
const Settings& settings) {
|
2017-08-17 08:12:10 -07:00
|
|
|
if (inst == nullptr) {
|
2014-11-01 06:10:48 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (inst->maxFramerate < 1) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
// Allow zero to represent an unspecified maxBitRate
|
|
|
|
|
if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (inst->width < 1 || inst->height < 1) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
2019-06-11 14:57:57 +02:00
|
|
|
if (settings.number_of_cores < 1) {
|
2014-11-01 06:10:48 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
2016-10-25 09:05:06 -07:00
|
|
|
if (inst->VP9().numberOfTemporalLayers > 3) {
|
2015-07-31 06:10:09 -07:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
2017-02-15 02:23:28 -08:00
|
|
|
// libvpx probably does not support more than 3 spatial layers.
|
|
|
|
|
if (inst->VP9().numberOfSpatialLayers > 3) {
|
2015-07-31 06:10:09 -07:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
Reland of Work on flexible mode and screen sharing. (patchset #1 id:1 of https://codereview.webrtc.org/1438543002/ )
Reason for revert:
Failed test not related to this CL (test fails on
master at an earlier date), re-landing original CL..
(This time from my @webrtc account.)
Original issue's description:
> Revert of Work on flexible mode and screen sharing. (patchset #28 id:520001 of https://codereview.webrtc.org/1328113004/ )
>
> Reason for revert:
> Seems to break VideoSendStreamTest.ReconfigureBitratesSetsEncoderBitratesCorrectly on Linux Memcheck buildbot.
>
> Original issue's description:
> > Work on flexible mode and screen sharing.
> >
> > Implement VP8 style screensharing but with spatial layers.
> > Implement flexible mode.
> >
> > Files from other patches:
> > generic_encoder.cc
> > layer_filtering_transport.cc
> >
> > BUG=webrtc:4914
> >
> > Committed: https://crrev.com/77ccfb4d16c148e61a316746bb5d9705e8b39f4a
> > Cr-Commit-Position: refs/heads/master@{#10572}
>
> TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,philipel@webrtc.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:4914
>
> Committed: https://crrev.com/0be8f1d347bdb171462df89c2a4c69b3f3eb7519
> Cr-Commit-Position: refs/heads/master@{#10578}
TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,terelius@webrtc.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:4914
Review URL: https://codereview.webrtc.org/1431283002
Cr-Commit-Position: refs/heads/master@{#10581}
2015-11-10 07:17:23 -08:00
|
|
|
|
2020-10-01 17:16:22 +02:00
|
|
|
absl::optional<vpx_img_fmt_t> previous_img_fmt =
|
|
|
|
|
raw_ ? absl::make_optional<vpx_img_fmt_t>(raw_->fmt) : absl::nullopt;
|
|
|
|
|
|
2016-01-26 01:05:20 -08:00
|
|
|
int ret_val = Release();
|
|
|
|
|
if (ret_val < 0) {
|
|
|
|
|
return ret_val;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2017-08-17 08:12:10 -07:00
|
|
|
if (encoder_ == nullptr) {
|
2014-11-01 06:10:48 +00:00
|
|
|
encoder_ = new vpx_codec_ctx_t;
|
2021-09-21 09:54:44 +02:00
|
|
|
memset(encoder_, 0, sizeof(*encoder_));
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2017-08-17 08:12:10 -07:00
|
|
|
if (config_ == nullptr) {
|
2014-11-01 06:10:48 +00:00
|
|
|
config_ = new vpx_codec_enc_cfg_t;
|
2021-09-21 09:54:44 +02:00
|
|
|
memset(config_, 0, sizeof(*config_));
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
timestamp_ = 0;
|
|
|
|
|
if (&codec_ != inst) {
|
|
|
|
|
codec_ = *inst;
|
|
|
|
|
}
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
memset(&svc_params_, 0, sizeof(vpx_svc_extra_cfg_t));
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2018-09-28 14:56:39 +02:00
|
|
|
force_key_frame_ = true;
|
|
|
|
|
pics_since_key_ = 0;
|
|
|
|
|
|
2022-12-06 10:09:10 +00:00
|
|
|
scalability_mode_ = inst->GetScalabilityMode();
|
|
|
|
|
if (scalability_mode_.has_value()) {
|
2022-05-16 22:37:34 +02:00
|
|
|
// Use settings from `ScalabilityMode` identifier.
|
|
|
|
|
RTC_LOG(LS_INFO) << "Create scalability structure "
|
2022-12-06 10:09:10 +00:00
|
|
|
<< ScalabilityModeToString(*scalability_mode_);
|
|
|
|
|
svc_controller_ = CreateScalabilityStructure(*scalability_mode_);
|
2022-05-16 22:37:34 +02:00
|
|
|
if (!svc_controller_) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Failed to create scalability structure.";
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
ScalableVideoController::StreamLayersConfig info =
|
|
|
|
|
svc_controller_->StreamConfig();
|
|
|
|
|
num_spatial_layers_ = info.num_spatial_layers;
|
|
|
|
|
num_temporal_layers_ = info.num_temporal_layers;
|
2022-12-06 10:09:10 +00:00
|
|
|
inter_layer_pred_ = ScalabilityModeToInterLayerPredMode(*scalability_mode_);
|
2022-05-16 22:37:34 +02:00
|
|
|
} else {
|
|
|
|
|
num_spatial_layers_ = inst->VP9().numberOfSpatialLayers;
|
|
|
|
|
RTC_DCHECK_GT(num_spatial_layers_, 0);
|
|
|
|
|
num_temporal_layers_ = inst->VP9().numberOfTemporalLayers;
|
|
|
|
|
if (num_temporal_layers_ == 0) {
|
|
|
|
|
num_temporal_layers_ = 1;
|
|
|
|
|
}
|
|
|
|
|
inter_layer_pred_ = inst->VP9().interLayerPred;
|
2022-12-06 10:09:10 +00:00
|
|
|
auto vp9_scalability = CreateVp9ScalabilityStructure(*inst);
|
|
|
|
|
if (vp9_scalability.has_value()) {
|
|
|
|
|
std::tie(svc_controller_, scalability_mode_) =
|
|
|
|
|
std::move(vp9_scalability.value());
|
|
|
|
|
} else {
|
|
|
|
|
svc_controller_ = nullptr;
|
|
|
|
|
scalability_mode_ = absl::nullopt;
|
|
|
|
|
}
|
2018-09-10 10:39:35 +00:00
|
|
|
}
|
2018-09-05 21:07:17 +02:00
|
|
|
|
2021-08-16 09:33:13 +02:00
|
|
|
framerate_controller_ = std::vector<FramerateControllerDeprecated>(
|
|
|
|
|
num_spatial_layers_, FramerateControllerDeprecated(codec_.maxFramerate));
|
2018-09-05 21:07:17 +02:00
|
|
|
|
2018-05-28 12:26:36 +02:00
|
|
|
is_svc_ = (num_spatial_layers_ > 1 || num_temporal_layers_ > 1);
|
|
|
|
|
|
2014-11-01 06:10:48 +00:00
|
|
|
// Populate encoder configuration with default values.
|
2020-12-13 14:50:59 +01:00
|
|
|
if (libvpx_->codec_enc_config_default(vpx_codec_vp9_cx(), config_, 0)) {
|
2014-11-01 06:10:48 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|
|
|
}
|
2018-07-13 17:10:00 -07:00
|
|
|
|
|
|
|
|
vpx_img_fmt img_fmt = VPX_IMG_FMT_NONE;
|
|
|
|
|
unsigned int bits_for_storage = 8;
|
|
|
|
|
switch (profile_) {
|
|
|
|
|
case VP9Profile::kProfile0:
|
2020-10-01 17:16:22 +02:00
|
|
|
img_fmt = previous_img_fmt.value_or(VPX_IMG_FMT_I420);
|
2018-07-13 17:10:00 -07:00
|
|
|
bits_for_storage = 8;
|
|
|
|
|
config_->g_bit_depth = VPX_BITS_8;
|
|
|
|
|
config_->g_profile = 0;
|
|
|
|
|
config_->g_input_bit_depth = 8;
|
|
|
|
|
break;
|
2020-06-11 13:41:06 +02:00
|
|
|
case VP9Profile::kProfile1:
|
|
|
|
|
// Encoding of profile 1 is not implemented. It would require extended
|
|
|
|
|
// support for I444, I422, and I440 buffers.
|
2021-11-15 16:57:07 +01:00
|
|
|
RTC_DCHECK_NOTREACHED();
|
2020-06-11 13:41:06 +02:00
|
|
|
break;
|
2018-07-13 17:10:00 -07:00
|
|
|
case VP9Profile::kProfile2:
|
|
|
|
|
img_fmt = VPX_IMG_FMT_I42016;
|
|
|
|
|
bits_for_storage = 16;
|
|
|
|
|
config_->g_bit_depth = VPX_BITS_10;
|
|
|
|
|
config_->g_profile = 2;
|
|
|
|
|
config_->g_input_bit_depth = 10;
|
|
|
|
|
break;
|
2022-06-22 14:42:48 +02:00
|
|
|
case VP9Profile::kProfile3:
|
|
|
|
|
// Encoding of profile 3 is not implemented.
|
|
|
|
|
RTC_DCHECK_NOTREACHED();
|
|
|
|
|
break;
|
2018-07-13 17:10:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Creating a wrapper to the image - setting image data to nullptr. Actual
|
|
|
|
|
// pointer will be set in encode. Setting align to 1, as it is meaningless
|
|
|
|
|
// (actual memory is not allocated).
|
2020-12-13 14:50:59 +01:00
|
|
|
raw_ = libvpx_->img_wrap(nullptr, img_fmt, codec_.width, codec_.height, 1,
|
|
|
|
|
nullptr);
|
2018-07-13 17:10:00 -07:00
|
|
|
raw_->bit_depth = bits_for_storage;
|
|
|
|
|
|
2014-11-01 06:10:48 +00:00
|
|
|
config_->g_w = codec_.width;
|
|
|
|
|
config_->g_h = codec_.height;
|
|
|
|
|
config_->rc_target_bitrate = inst->startBitrate; // in kbit/s
|
2018-05-28 12:26:36 +02:00
|
|
|
config_->g_error_resilient = is_svc_ ? VPX_ERROR_RESILIENT_DEFAULT : 0;
|
2014-11-01 06:10:48 +00:00
|
|
|
// Setting the time base of the codec.
|
|
|
|
|
config_->g_timebase.num = 1;
|
|
|
|
|
config_->g_timebase.den = 90000;
|
|
|
|
|
config_->g_lag_in_frames = 0; // 0- no frame lagging
|
|
|
|
|
config_->g_threads = 1;
|
|
|
|
|
// Rate control settings.
|
2022-05-12 16:16:39 +02:00
|
|
|
config_->rc_dropframe_thresh = inst->GetFrameDropEnabled() ? 30 : 0;
|
2014-11-01 06:10:48 +00:00
|
|
|
config_->rc_end_usage = VPX_CBR;
|
|
|
|
|
config_->g_pass = VPX_RC_ONE_PASS;
|
2019-02-14 14:44:22 +01:00
|
|
|
config_->rc_min_quantizer =
|
|
|
|
|
codec_.mode == VideoCodecMode::kScreensharing ? 8 : 2;
|
2015-01-27 23:08:24 +00:00
|
|
|
config_->rc_max_quantizer = 52;
|
2014-11-01 06:10:48 +00:00
|
|
|
config_->rc_undershoot_pct = 50;
|
|
|
|
|
config_->rc_overshoot_pct = 50;
|
|
|
|
|
config_->rc_buf_initial_sz = 500;
|
|
|
|
|
config_->rc_buf_optimal_sz = 600;
|
|
|
|
|
config_->rc_buf_sz = 1000;
|
|
|
|
|
// Set the maximum target size of any key-frame.
|
|
|
|
|
rc_max_intra_target_ = MaxIntraTarget(config_->rc_buf_optimal_sz);
|
2019-01-18 11:56:48 +01:00
|
|
|
// Key-frame interval is enforced manually by this wrapper.
|
|
|
|
|
config_->kf_mode = VPX_KF_DISABLED;
|
|
|
|
|
// TODO(webm:1592): work-around for libvpx issue, as it can still
|
|
|
|
|
// put some key-frames at will even in VPX_KF_DISABLED kf_mode.
|
|
|
|
|
config_->kf_max_dist = inst->VP9().keyFrameInterval;
|
|
|
|
|
config_->kf_min_dist = config_->kf_max_dist;
|
2020-06-18 19:16:53 +02:00
|
|
|
if (quality_scaler_experiment_.enabled) {
|
|
|
|
|
// In that experiment webrtc wide quality scaler is used instead of libvpx
|
|
|
|
|
// internal scaler.
|
|
|
|
|
config_->rc_resize_allowed = 0;
|
|
|
|
|
} else {
|
|
|
|
|
config_->rc_resize_allowed = inst->VP9().automaticResizeOn ? 1 : 0;
|
|
|
|
|
}
|
2015-01-26 15:21:36 +00:00
|
|
|
// Determine number of threads based on the image size and #cores.
|
2015-12-21 03:04:49 -08:00
|
|
|
config_->g_threads =
|
2019-06-11 14:57:57 +02:00
|
|
|
NumberOfThreads(config_->g_w, config_->g_h, settings.number_of_cores);
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2016-10-25 09:05:06 -07:00
|
|
|
is_flexible_mode_ = inst->VP9().flexibleMode;
|
2018-05-17 16:46:43 +02:00
|
|
|
|
2019-05-24 11:51:31 +02:00
|
|
|
if (num_spatial_layers_ > 1 &&
|
|
|
|
|
codec_.mode == VideoCodecMode::kScreensharing && !is_flexible_mode_) {
|
|
|
|
|
RTC_LOG(LS_ERROR) << "Flexible mode is required for screenshare with "
|
|
|
|
|
"several spatial layers";
|
2018-12-04 15:54:52 +01:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// External reference control is required for different frame rate on spatial
|
|
|
|
|
// layers because libvpx generates rtp incompatible references in this case.
|
2020-10-01 19:13:13 +02:00
|
|
|
external_ref_control_ = external_ref_ctrl_ ||
|
|
|
|
|
(num_spatial_layers_ > 1 &&
|
|
|
|
|
codec_.mode == VideoCodecMode::kScreensharing) ||
|
|
|
|
|
inter_layer_pred_ == InterLayerPredMode::kOn;
|
2018-12-04 15:54:52 +01:00
|
|
|
|
2018-05-17 16:46:43 +02:00
|
|
|
if (num_temporal_layers_ == 1) {
|
2015-07-31 06:10:09 -07:00
|
|
|
gof_.SetGofInfoVP9(kTemporalStructureMode1);
|
|
|
|
|
config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING;
|
|
|
|
|
config_->ts_number_layers = 1;
|
|
|
|
|
config_->ts_rate_decimator[0] = 1;
|
|
|
|
|
config_->ts_periodicity = 1;
|
|
|
|
|
config_->ts_layer_id[0] = 0;
|
|
|
|
|
} else if (num_temporal_layers_ == 2) {
|
|
|
|
|
gof_.SetGofInfoVP9(kTemporalStructureMode2);
|
|
|
|
|
config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_0101;
|
|
|
|
|
config_->ts_number_layers = 2;
|
|
|
|
|
config_->ts_rate_decimator[0] = 2;
|
|
|
|
|
config_->ts_rate_decimator[1] = 1;
|
|
|
|
|
config_->ts_periodicity = 2;
|
|
|
|
|
config_->ts_layer_id[0] = 0;
|
|
|
|
|
config_->ts_layer_id[1] = 1;
|
|
|
|
|
} else if (num_temporal_layers_ == 3) {
|
|
|
|
|
gof_.SetGofInfoVP9(kTemporalStructureMode3);
|
|
|
|
|
config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_0212;
|
|
|
|
|
config_->ts_number_layers = 3;
|
|
|
|
|
config_->ts_rate_decimator[0] = 4;
|
|
|
|
|
config_->ts_rate_decimator[1] = 2;
|
|
|
|
|
config_->ts_rate_decimator[2] = 1;
|
|
|
|
|
config_->ts_periodicity = 4;
|
|
|
|
|
config_->ts_layer_id[0] = 0;
|
|
|
|
|
config_->ts_layer_id[1] = 2;
|
|
|
|
|
config_->ts_layer_id[2] = 1;
|
|
|
|
|
config_->ts_layer_id[3] = 2;
|
|
|
|
|
} else {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
if (external_ref_control_) {
|
|
|
|
|
config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
|
2019-05-24 11:51:31 +02:00
|
|
|
if (num_temporal_layers_ > 1 && num_spatial_layers_ > 1 &&
|
|
|
|
|
codec_.mode == VideoCodecMode::kScreensharing) {
|
2018-12-04 15:54:52 +01:00
|
|
|
// External reference control for several temporal layers with different
|
|
|
|
|
// frame rates on spatial layers is not implemented yet.
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-28 09:58:58 +02:00
|
|
|
ref_buf_ = {};
|
2018-05-28 12:26:36 +02:00
|
|
|
|
2014-11-01 06:10:48 +00:00
|
|
|
return InitAndSetControlSettings(inst);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
int LibvpxVp9Encoder::NumberOfThreads(int width,
|
|
|
|
|
int height,
|
|
|
|
|
int number_of_cores) {
|
2015-01-26 15:21:36 +00:00
|
|
|
// Keep the number of encoder threads equal to the possible number of column
|
|
|
|
|
// tiles, which is (1, 2, 4, 8). See comments below for VP9E_SET_TILE_COLUMNS.
|
|
|
|
|
if (width * height >= 1280 * 720 && number_of_cores > 4) {
|
|
|
|
|
return 4;
|
2017-07-12 16:11:09 -07:00
|
|
|
} else if (width * height >= 640 * 360 && number_of_cores > 2) {
|
2015-01-26 15:21:36 +00:00
|
|
|
return 2;
|
|
|
|
|
} else {
|
2023-10-06 13:18:41 +02:00
|
|
|
// Use 2 threads for low res on mobile ARM.
|
|
|
|
|
#ifdef MOBILE_ARM
|
2017-12-05 10:44:35 -08:00
|
|
|
if (width * height >= 320 * 180 && number_of_cores > 2) {
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2015-01-26 15:21:36 +00:00
|
|
|
// 1 thread less than VGA.
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
|
2015-12-04 10:58:08 +01:00
|
|
|
// Set QP-min/max per spatial and temporal layer.
|
|
|
|
|
int tot_num_layers = num_spatial_layers_ * num_temporal_layers_;
|
|
|
|
|
for (int i = 0; i < tot_num_layers; ++i) {
|
2017-01-26 13:23:44 -08:00
|
|
|
svc_params_.max_quantizers[i] = config_->rc_max_quantizer;
|
|
|
|
|
svc_params_.min_quantizers[i] = config_->rc_min_quantizer;
|
2015-12-04 10:58:08 +01:00
|
|
|
}
|
2015-07-31 06:10:09 -07:00
|
|
|
config_->ss_number_layers = num_spatial_layers_;
|
2020-10-15 17:26:46 +02:00
|
|
|
if (svc_controller_) {
|
|
|
|
|
auto stream_config = svc_controller_->StreamConfig();
|
|
|
|
|
for (int i = 0; i < stream_config.num_spatial_layers; ++i) {
|
|
|
|
|
svc_params_.scaling_factor_num[i] = stream_config.scaling_factor_num[i];
|
|
|
|
|
svc_params_.scaling_factor_den[i] = stream_config.scaling_factor_den[i];
|
|
|
|
|
}
|
|
|
|
|
} else if (ExplicitlyConfiguredSpatialLayers()) {
|
2015-11-02 07:23:20 -08:00
|
|
|
for (int i = 0; i < num_spatial_layers_; ++i) {
|
|
|
|
|
const auto& layer = codec_.spatialLayers[i];
|
2018-06-26 13:41:16 +02:00
|
|
|
RTC_CHECK_GT(layer.width, 0);
|
2018-03-02 12:28:00 +01:00
|
|
|
const int scale_factor = codec_.width / layer.width;
|
|
|
|
|
RTC_DCHECK_GT(scale_factor, 0);
|
|
|
|
|
|
|
|
|
|
// Ensure scaler factor is integer.
|
|
|
|
|
if (scale_factor * layer.width != codec_.width) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure scale factor is the same in both dimensions.
|
|
|
|
|
if (scale_factor * layer.height != codec_.height) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure scale factor is power of two.
|
|
|
|
|
const bool is_pow_of_two = (scale_factor & (scale_factor - 1)) == 0;
|
|
|
|
|
if (!is_pow_of_two) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
svc_params_.scaling_factor_num[i] = 1;
|
|
|
|
|
svc_params_.scaling_factor_den[i] = scale_factor;
|
2018-09-05 21:07:17 +02:00
|
|
|
|
|
|
|
|
RTC_DCHECK_GT(codec_.spatialLayers[i].maxFramerate, 0);
|
|
|
|
|
RTC_DCHECK_LE(codec_.spatialLayers[i].maxFramerate, codec_.maxFramerate);
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
// Frame rate of high spatial layer is supposed to be equal or higher
|
|
|
|
|
// than frame rate of low spatial layer.
|
|
|
|
|
RTC_DCHECK_GE(codec_.spatialLayers[i].maxFramerate,
|
|
|
|
|
codec_.spatialLayers[i - 1].maxFramerate);
|
|
|
|
|
}
|
2015-11-02 07:23:20 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
int scaling_factor_num = 256;
|
|
|
|
|
for (int i = num_spatial_layers_ - 1; i >= 0; --i) {
|
|
|
|
|
// 1:2 scaling in each dimension.
|
2017-01-26 13:23:44 -08:00
|
|
|
svc_params_.scaling_factor_num[i] = scaling_factor_num;
|
|
|
|
|
svc_params_.scaling_factor_den[i] = 256;
|
2015-11-02 07:23:20 -08:00
|
|
|
}
|
2015-07-31 06:10:09 -07:00
|
|
|
}
|
|
|
|
|
|
2022-03-30 14:06:13 +02:00
|
|
|
UpdatePerformanceFlags();
|
|
|
|
|
RTC_DCHECK_EQ(performance_flags_by_spatial_index_.size(),
|
|
|
|
|
static_cast<size_t>(num_spatial_layers_));
|
|
|
|
|
|
2018-03-28 19:32:37 +02:00
|
|
|
SvcRateAllocator init_allocator(codec_);
|
2019-08-02 15:16:28 +02:00
|
|
|
current_bitrate_allocation_ =
|
|
|
|
|
init_allocator.Allocate(VideoBitrateAllocationParameters(
|
|
|
|
|
inst->startBitrate * 1000, inst->maxFramerate));
|
2018-12-04 15:54:52 +01:00
|
|
|
if (!SetSvcRates(current_bitrate_allocation_)) {
|
2015-07-31 06:10:09 -07:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-13 14:50:59 +01:00
|
|
|
const vpx_codec_err_t rv = libvpx_->codec_enc_init(
|
2018-07-13 17:10:00 -07:00
|
|
|
encoder_, vpx_codec_vp9_cx(), config_,
|
|
|
|
|
config_->g_bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH);
|
|
|
|
|
if (rv != VPX_CODEC_OK) {
|
2020-12-13 14:50:59 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "Init error: " << libvpx_->codec_err_to_string(rv);
|
2014-11-01 06:10:48 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
|
|
|
|
}
|
2020-10-01 19:13:13 +02:00
|
|
|
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
if (performance_flags_.use_per_layer_speed) {
|
|
|
|
|
for (int si = 0; si < num_spatial_layers_; ++si) {
|
|
|
|
|
svc_params_.speed_per_layer[si] =
|
|
|
|
|
performance_flags_by_spatial_index_[si].base_layer_speed;
|
|
|
|
|
svc_params_.loopfilter_ctrl[si] =
|
|
|
|
|
performance_flags_by_spatial_index_[si].deblock_mode;
|
Revert "Adds experimental libvpx VP9 speed settings."
This reverts commit 6e7167456b5eba36c7985d6a74f1d191958d4e0f.
Reason for revert: Unexpected perf change
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "min_pixel_count:0|129600,base_layer_speed:5|8,high_layer_speed:7|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
TBR=sprang@webrtc.org,ssilkin@webrtc.org,mhoro@webrtc.org
Change-Id: If910963441ac1a0e002aac7066791c7cc7764a1a
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:11551
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196344
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32762}
2020-12-03 16:05:49 +00:00
|
|
|
}
|
2022-03-30 14:06:13 +02:00
|
|
|
bool denoiser_on =
|
2022-03-31 16:11:15 +02:00
|
|
|
AllowDenoising() && inst->VP9().denoisingOn &&
|
2022-03-30 14:06:13 +02:00
|
|
|
performance_flags_by_spatial_index_[num_spatial_layers_ - 1]
|
2022-03-31 16:11:15 +02:00
|
|
|
.allow_denoising;
|
2022-03-30 14:06:13 +02:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY,
|
|
|
|
|
denoiser_on ? 1 : 0);
|
2020-10-01 19:13:13 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
|
|
|
|
rc_max_intra_target_);
|
|
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_AQ_MODE,
|
|
|
|
|
inst->VP9().adaptiveQpMode ? 3 : 0);
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_FRAME_PARALLEL_DECODING, 0);
|
|
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_GF_TEMPORAL_REF, 0);
|
2018-04-26 11:03:49 +02:00
|
|
|
|
2018-05-28 12:26:36 +02:00
|
|
|
if (is_svc_) {
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC, 1);
|
|
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
|
2015-07-31 06:10:09 -07:00
|
|
|
}
|
2021-01-20 22:12:33 +01:00
|
|
|
if (!is_svc_ || !performance_flags_.use_per_layer_speed) {
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
encoder_, VP8E_SET_CPUUSED,
|
|
|
|
|
performance_flags_by_spatial_index_.rbegin()->base_layer_speed);
|
|
|
|
|
}
|
2018-04-26 11:03:49 +02:00
|
|
|
|
|
|
|
|
if (num_spatial_layers_ > 1) {
|
|
|
|
|
switch (inter_layer_pred_) {
|
|
|
|
|
case InterLayerPredMode::kOn:
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 0);
|
2018-04-26 11:03:49 +02:00
|
|
|
break;
|
|
|
|
|
case InterLayerPredMode::kOff:
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 1);
|
2018-04-26 11:03:49 +02:00
|
|
|
break;
|
|
|
|
|
case InterLayerPredMode::kOnKeyPic:
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 2);
|
2018-04-26 11:03:49 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
2021-11-15 16:57:07 +01:00
|
|
|
RTC_DCHECK_NOTREACHED();
|
2018-04-26 11:03:49 +02:00
|
|
|
}
|
2018-05-17 16:46:43 +02:00
|
|
|
|
2019-05-24 16:50:00 +02:00
|
|
|
memset(&svc_drop_frame_, 0, sizeof(svc_drop_frame_));
|
2019-09-09 10:16:18 +02:00
|
|
|
const bool reverse_constrained_drop_mode =
|
|
|
|
|
inter_layer_pred_ == InterLayerPredMode::kOn &&
|
|
|
|
|
codec_.mode == VideoCodecMode::kScreensharing &&
|
|
|
|
|
num_spatial_layers_ > 1;
|
|
|
|
|
if (reverse_constrained_drop_mode) {
|
|
|
|
|
// Screenshare dropping mode: drop a layer only together with all lower
|
|
|
|
|
// layers. This ensures that drops on lower layers won't reduce frame-rate
|
|
|
|
|
// for higher layers and reference structure is RTP-compatible.
|
|
|
|
|
svc_drop_frame_.framedrop_mode = CONSTRAINED_FROM_ABOVE_DROP;
|
2019-05-24 16:50:00 +02:00
|
|
|
svc_drop_frame_.max_consec_drop = 5;
|
2019-09-09 10:16:18 +02:00
|
|
|
for (size_t i = 0; i < num_spatial_layers_; ++i) {
|
|
|
|
|
svc_drop_frame_.framedrop_thresh[i] = config_->rc_dropframe_thresh;
|
2019-05-24 16:50:00 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Configure encoder to drop entire superframe whenever it needs to drop
|
|
|
|
|
// a layer. This mode is preferred over per-layer dropping which causes
|
|
|
|
|
// quality flickering and is not compatible with RTP non-flexible mode.
|
2023-05-05 16:18:10 +02:00
|
|
|
svc_drop_frame_.framedrop_mode = FULL_SUPERFRAME_DROP;
|
2019-05-24 16:50:00 +02:00
|
|
|
svc_drop_frame_.max_consec_drop = std::numeric_limits<int>::max();
|
|
|
|
|
for (size_t i = 0; i < num_spatial_layers_; ++i) {
|
|
|
|
|
svc_drop_frame_.framedrop_thresh[i] = config_->rc_dropframe_thresh;
|
|
|
|
|
}
|
2018-05-17 16:46:43 +02:00
|
|
|
}
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
|
|
|
|
|
&svc_drop_frame_);
|
2018-04-26 11:03:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-31 06:10:09 -07:00
|
|
|
// Register callback for getting each spatial layer.
|
|
|
|
|
vpx_codec_priv_output_cx_pkt_cb_pair_t cbp = {
|
2020-12-09 20:58:21 +01:00
|
|
|
LibvpxVp9Encoder::EncoderOutputCodedPacketCallback,
|
2015-12-21 03:04:49 -08:00
|
|
|
reinterpret_cast<void*>(this)};
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK,
|
|
|
|
|
reinterpret_cast<void*>(&cbp));
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2015-01-26 15:21:36 +00:00
|
|
|
// Control function to set the number of column tiles in encoding a frame, in
|
|
|
|
|
// log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns.
|
|
|
|
|
// The number tile columns will be capped by the encoder based on image size
|
|
|
|
|
// (minimum width of tile column is 256 pixels, maximum is 4096).
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_TILE_COLUMNS,
|
|
|
|
|
static_cast<int>((config_->g_threads >> 1)));
|
2017-03-28 23:56:08 -07:00
|
|
|
|
|
|
|
|
// Turn on row-based multithreading.
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_ROW_MT, 1);
|
2017-06-05 13:43:49 -07:00
|
|
|
|
2022-03-30 14:06:13 +02:00
|
|
|
if (AllowDenoising() && !performance_flags_.use_per_layer_speed) {
|
|
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY,
|
|
|
|
|
inst->VP9().denoisingOn ? 1 : 0);
|
|
|
|
|
}
|
2017-06-05 13:43:49 -07:00
|
|
|
|
2018-06-13 11:52:16 +02:00
|
|
|
if (codec_.mode == VideoCodecMode::kScreensharing) {
|
2015-09-04 06:13:23 -07:00
|
|
|
// Adjust internal parameters to screen content.
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_TUNE_CONTENT, 1);
|
2015-09-04 06:13:23 -07:00
|
|
|
}
|
2015-09-16 14:05:00 -07:00
|
|
|
// Enable encoder skip of static/low content blocks.
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP8E_SET_STATIC_THRESHOLD, 1);
|
2014-11-01 06:10:48 +00:00
|
|
|
inited_ = true;
|
2020-02-21 10:47:10 -08:00
|
|
|
config_changed_ = true;
|
2014-11-01 06:10:48 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
uint32_t LibvpxVp9Encoder::MaxIntraTarget(uint32_t optimal_buffer_size) {
|
2014-11-01 06:10:48 +00:00
|
|
|
// Set max to the optimal buffer level (normalized by target BR),
|
|
|
|
|
// and scaled by a scale_par.
|
|
|
|
|
// Max target size = scale_par * optimal_buffer_size * targetBR[Kbps].
|
|
|
|
|
// This value is presented in percentage of perFrameBw:
|
|
|
|
|
// perFrameBw = targetBR[Kbps] * 1000 / framerate.
|
|
|
|
|
// The target in % is as follows:
|
|
|
|
|
float scale_par = 0.5;
|
|
|
|
|
uint32_t target_pct =
|
|
|
|
|
optimal_buffer_size * scale_par * codec_.maxFramerate / 10;
|
|
|
|
|
// Don't go below 3 times the per frame bandwidth.
|
|
|
|
|
const uint32_t min_intra_size = 300;
|
2015-12-21 03:04:49 -08:00
|
|
|
return (target_pct < min_intra_size) ? min_intra_size : target_pct;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
|
|
|
|
|
const std::vector<VideoFrameType>* frame_types) {
|
2014-11-01 06:10:48 +00:00
|
|
|
if (!inited_) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
|
|
|
|
}
|
2017-08-17 08:12:10 -07:00
|
|
|
if (encoded_complete_callback_ == nullptr) {
|
2014-11-01 06:10:48 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
|
|
|
|
}
|
2019-02-04 16:40:19 +01:00
|
|
|
if (num_active_spatial_layers_ == 0) {
|
|
|
|
|
// All spatial layers are disabled, return without encoding anything.
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
|
|
|
|
}
|
2018-05-03 14:14:09 +02:00
|
|
|
|
2014-11-01 06:10:48 +00:00
|
|
|
// We only support one stream at the moment.
|
2018-05-03 14:14:09 +02:00
|
|
|
if (frame_types && !frame_types->empty()) {
|
2019-03-21 15:43:58 +01:00
|
|
|
if ((*frame_types)[0] == VideoFrameType::kVideoFrameKey) {
|
2018-05-03 14:14:09 +02:00
|
|
|
force_key_frame_ = true;
|
|
|
|
|
}
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2018-05-18 17:31:19 +02:00
|
|
|
|
2019-01-18 11:56:48 +01:00
|
|
|
if (pics_since_key_ + 1 ==
|
|
|
|
|
static_cast<size_t>(codec_.VP9()->keyFrameInterval)) {
|
|
|
|
|
force_key_frame_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-15 17:26:46 +02:00
|
|
|
if (svc_controller_) {
|
|
|
|
|
layer_frames_ = svc_controller_->NextFrameConfig(force_key_frame_);
|
|
|
|
|
if (layer_frames_.empty()) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|
|
|
}
|
2022-08-03 16:27:27 +02:00
|
|
|
if (layer_frames_.front().IsKeyframe()) {
|
|
|
|
|
force_key_frame_ = true;
|
|
|
|
|
}
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
vpx_svc_layer_id_t layer_id = {0};
|
|
|
|
|
if (!force_key_frame_) {
|
2018-11-29 15:09:31 +00:00
|
|
|
const size_t gof_idx = (pics_since_key_ + 1) % gof_.num_frames_in_gof;
|
|
|
|
|
layer_id.temporal_layer_id = gof_.temporal_idx[gof_idx];
|
2018-09-05 21:07:17 +02:00
|
|
|
|
2022-01-19 14:17:14 +01:00
|
|
|
if (codec_.mode == VideoCodecMode::kScreensharing) {
|
2018-12-04 15:54:52 +01:00
|
|
|
const uint32_t frame_timestamp_ms =
|
|
|
|
|
1000 * input_image.timestamp() / kVideoPayloadTypeFrequency;
|
2018-09-05 21:07:17 +02:00
|
|
|
|
2019-03-06 16:04:32 +01:00
|
|
|
// To ensure that several rate-limiters with different limits don't
|
|
|
|
|
// interfere, they must be queried in order of increasing limit.
|
|
|
|
|
|
|
|
|
|
bool use_steady_state_limiter =
|
|
|
|
|
variable_framerate_experiment_.enabled &&
|
|
|
|
|
input_image.update_rect().IsEmpty() &&
|
|
|
|
|
num_steady_state_frames_ >=
|
|
|
|
|
variable_framerate_experiment_.frames_before_steady_state;
|
|
|
|
|
|
2019-09-25 09:10:33 +00:00
|
|
|
// Need to check all frame limiters, even if lower layers are disabled,
|
|
|
|
|
// because variable frame-rate limiter should be checked after the first
|
|
|
|
|
// layer. It's easier to overwrite active layers after, then check all
|
|
|
|
|
// cases.
|
2018-12-04 15:54:52 +01:00
|
|
|
for (uint8_t sl_idx = 0; sl_idx < num_active_spatial_layers_; ++sl_idx) {
|
2019-03-06 16:04:32 +01:00
|
|
|
const float layer_fps =
|
|
|
|
|
framerate_controller_[layer_id.spatial_layer_id].GetTargetRate();
|
|
|
|
|
// Use steady state rate-limiter at the correct place.
|
|
|
|
|
if (use_steady_state_limiter &&
|
|
|
|
|
layer_fps > variable_framerate_experiment_.framerate_limit - 1e-9) {
|
|
|
|
|
if (variable_framerate_controller_.DropFrame(frame_timestamp_ms)) {
|
|
|
|
|
layer_id.spatial_layer_id = num_active_spatial_layers_;
|
|
|
|
|
}
|
|
|
|
|
// Break always: if rate limiter triggered frame drop, no need to
|
|
|
|
|
// continue; otherwise, the rate is less than the next limiters.
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-12-04 15:54:52 +01:00
|
|
|
if (framerate_controller_[sl_idx].DropFrame(frame_timestamp_ms)) {
|
|
|
|
|
++layer_id.spatial_layer_id;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-09-05 21:07:17 +02:00
|
|
|
}
|
2019-03-06 16:04:32 +01:00
|
|
|
|
|
|
|
|
if (use_steady_state_limiter &&
|
|
|
|
|
layer_id.spatial_layer_id < num_active_spatial_layers_) {
|
|
|
|
|
variable_framerate_controller_.AddFrame(frame_timestamp_ms);
|
|
|
|
|
}
|
2018-11-29 15:09:31 +00:00
|
|
|
}
|
2018-09-05 21:07:17 +02:00
|
|
|
|
2019-09-25 09:10:33 +00:00
|
|
|
if (force_all_active_layers_) {
|
|
|
|
|
layer_id.spatial_layer_id = first_active_layer_;
|
|
|
|
|
force_all_active_layers_ = false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-29 15:09:31 +00:00
|
|
|
RTC_DCHECK_LE(layer_id.spatial_layer_id, num_active_spatial_layers_);
|
|
|
|
|
if (layer_id.spatial_layer_id >= num_active_spatial_layers_) {
|
|
|
|
|
// Drop entire picture.
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2018-05-18 17:31:19 +02:00
|
|
|
}
|
2018-12-04 15:54:52 +01:00
|
|
|
}
|
2018-11-29 15:09:31 +00:00
|
|
|
|
2020-02-21 12:05:28 +01:00
|
|
|
// Need to set temporal layer id on ALL layers, even disabled ones.
|
|
|
|
|
// Otherwise libvpx might produce frames on a disabled layer:
|
|
|
|
|
// http://crbug.com/1051476
|
|
|
|
|
for (int sl_idx = 0; sl_idx < num_spatial_layers_; ++sl_idx) {
|
2018-12-04 15:54:52 +01:00
|
|
|
layer_id.temporal_layer_id_per_spatial[sl_idx] = layer_id.temporal_layer_id;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-25 09:10:33 +00:00
|
|
|
if (layer_id.spatial_layer_id < first_active_layer_) {
|
|
|
|
|
layer_id.spatial_layer_id = first_active_layer_;
|
2019-09-25 09:06:50 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-15 17:26:46 +02:00
|
|
|
if (svc_controller_) {
|
|
|
|
|
layer_id.spatial_layer_id = layer_frames_.front().SpatialId();
|
|
|
|
|
layer_id.temporal_layer_id = layer_frames_.front().TemporalId();
|
|
|
|
|
for (const auto& layer : layer_frames_) {
|
|
|
|
|
layer_id.temporal_layer_id_per_spatial[layer.SpatialId()] =
|
|
|
|
|
layer.TemporalId();
|
|
|
|
|
}
|
2021-09-10 12:30:09 +02:00
|
|
|
SetActiveSpatialLayers();
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
|
|
|
|
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
if (is_svc_ && performance_flags_.use_per_layer_speed) {
|
|
|
|
|
// Update speed settings that might depend on temporal index.
|
|
|
|
|
bool speed_updated = false;
|
|
|
|
|
for (int sl_idx = 0; sl_idx < num_spatial_layers_; ++sl_idx) {
|
|
|
|
|
const int target_speed =
|
|
|
|
|
layer_id.temporal_layer_id_per_spatial[sl_idx] == 0
|
|
|
|
|
? performance_flags_by_spatial_index_[sl_idx].base_layer_speed
|
|
|
|
|
: performance_flags_by_spatial_index_[sl_idx].high_layer_speed;
|
|
|
|
|
if (svc_params_.speed_per_layer[sl_idx] != target_speed) {
|
|
|
|
|
svc_params_.speed_per_layer[sl_idx] = target_speed;
|
|
|
|
|
speed_updated = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (speed_updated) {
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_LAYER_ID, &layer_id);
|
2019-09-25 09:10:33 +00:00
|
|
|
|
2019-05-24 16:50:00 +02:00
|
|
|
if (num_spatial_layers_ > 1) {
|
|
|
|
|
// Update frame dropping settings as they may change on per-frame basis.
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
|
|
|
|
|
&svc_drop_frame_);
|
2019-05-24 16:50:00 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-21 10:47:10 -08:00
|
|
|
if (config_changed_) {
|
2020-12-13 14:50:59 +01:00
|
|
|
if (libvpx_->codec_enc_config_set(encoder_, config_)) {
|
2020-02-21 10:47:10 -08:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|
|
|
}
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
|
|
|
|
|
if (!performance_flags_.use_per_layer_speed) {
|
|
|
|
|
// Not setting individual speeds per layer, find the highest active
|
|
|
|
|
// resolution instead and base the speed on that.
|
|
|
|
|
for (int i = num_spatial_layers_ - 1; i >= 0; --i) {
|
|
|
|
|
if (config_->ss_target_bitrate[i] > 0) {
|
|
|
|
|
int width = (svc_params_.scaling_factor_num[i] * config_->g_w) /
|
|
|
|
|
svc_params_.scaling_factor_den[i];
|
|
|
|
|
int height = (svc_params_.scaling_factor_num[i] * config_->g_h) /
|
|
|
|
|
svc_params_.scaling_factor_den[i];
|
|
|
|
|
int speed =
|
|
|
|
|
std::prev(performance_flags_.settings_by_resolution.lower_bound(
|
|
|
|
|
width * height))
|
|
|
|
|
->second.base_layer_speed;
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP8E_SET_CPUUSED, speed);
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-21 10:47:10 -08:00
|
|
|
config_changed_ = false;
|
2018-05-18 17:31:19 +02:00
|
|
|
}
|
|
|
|
|
|
2016-11-28 15:58:53 -08:00
|
|
|
RTC_DCHECK_EQ(input_image.width(), raw_->d_w);
|
|
|
|
|
RTC_DCHECK_EQ(input_image.height(), raw_->d_h);
|
2015-07-31 06:10:09 -07:00
|
|
|
|
|
|
|
|
// Set input image for use in the callback.
|
|
|
|
|
// This was necessary since you need some information from input_image.
|
|
|
|
|
// You can save only the necessary information (such as timestamp) instead of
|
|
|
|
|
// doing this.
|
|
|
|
|
input_image_ = &input_image;
|
|
|
|
|
|
2021-08-09 13:02:57 +02:00
|
|
|
// In case we need to map the buffer, `mapped_buffer` is used to keep it alive
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
// through reference counting until after encoding has finished.
|
|
|
|
|
rtc::scoped_refptr<const VideoFrameBuffer> mapped_buffer;
|
2019-05-03 11:39:26 +02:00
|
|
|
const I010BufferInterface* i010_buffer;
|
|
|
|
|
rtc::scoped_refptr<const I010BufferInterface> i010_copy;
|
2018-07-13 17:10:00 -07:00
|
|
|
switch (profile_) {
|
|
|
|
|
case VP9Profile::kProfile0: {
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
mapped_buffer =
|
|
|
|
|
PrepareBufferForProfile0(input_image.video_frame_buffer());
|
|
|
|
|
if (!mapped_buffer) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
2020-09-28 12:04:11 +02:00
|
|
|
}
|
2018-07-13 17:10:00 -07:00
|
|
|
break;
|
|
|
|
|
}
|
2020-06-11 13:41:06 +02:00
|
|
|
case VP9Profile::kProfile1: {
|
2021-11-15 16:57:07 +01:00
|
|
|
RTC_DCHECK_NOTREACHED();
|
2020-06-11 13:41:06 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2018-07-13 17:10:00 -07:00
|
|
|
case VP9Profile::kProfile2: {
|
|
|
|
|
// We can inject kI010 frames directly for encode. All other formats
|
|
|
|
|
// should be converted to it.
|
|
|
|
|
switch (input_image.video_frame_buffer()->type()) {
|
|
|
|
|
case VideoFrameBuffer::Type::kI010: {
|
|
|
|
|
i010_buffer = input_image.video_frame_buffer()->GetI010();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default: {
|
2021-06-21 13:47:44 +02:00
|
|
|
auto i420_buffer = input_image.video_frame_buffer()->ToI420();
|
|
|
|
|
if (!i420_buffer) {
|
|
|
|
|
RTC_LOG(LS_ERROR) << "Failed to convert "
|
|
|
|
|
<< VideoFrameBufferTypeToString(
|
|
|
|
|
input_image.video_frame_buffer()->type())
|
|
|
|
|
<< " image to I420. Can't encode frame.";
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|
|
|
}
|
|
|
|
|
i010_copy = I010Buffer::Copy(*i420_buffer);
|
2019-05-03 11:39:26 +02:00
|
|
|
i010_buffer = i010_copy.get();
|
2018-07-13 17:10:00 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
raw_->planes[VPX_PLANE_Y] = const_cast<uint8_t*>(
|
|
|
|
|
reinterpret_cast<const uint8_t*>(i010_buffer->DataY()));
|
|
|
|
|
raw_->planes[VPX_PLANE_U] = const_cast<uint8_t*>(
|
|
|
|
|
reinterpret_cast<const uint8_t*>(i010_buffer->DataU()));
|
|
|
|
|
raw_->planes[VPX_PLANE_V] = const_cast<uint8_t*>(
|
|
|
|
|
reinterpret_cast<const uint8_t*>(i010_buffer->DataV()));
|
|
|
|
|
raw_->stride[VPX_PLANE_Y] = i010_buffer->StrideY() * 2;
|
|
|
|
|
raw_->stride[VPX_PLANE_U] = i010_buffer->StrideU() * 2;
|
|
|
|
|
raw_->stride[VPX_PLANE_V] = i010_buffer->StrideV() * 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-06-22 14:42:48 +02:00
|
|
|
case VP9Profile::kProfile3: {
|
|
|
|
|
RTC_DCHECK_NOTREACHED();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-07-13 17:10:00 -07:00
|
|
|
}
|
2014-11-01 06:10:48 +00:00
|
|
|
|
Reland of Work on flexible mode and screen sharing. (patchset #1 id:1 of https://codereview.webrtc.org/1438543002/ )
Reason for revert:
Failed test not related to this CL (test fails on
master at an earlier date), re-landing original CL..
(This time from my @webrtc account.)
Original issue's description:
> Revert of Work on flexible mode and screen sharing. (patchset #28 id:520001 of https://codereview.webrtc.org/1328113004/ )
>
> Reason for revert:
> Seems to break VideoSendStreamTest.ReconfigureBitratesSetsEncoderBitratesCorrectly on Linux Memcheck buildbot.
>
> Original issue's description:
> > Work on flexible mode and screen sharing.
> >
> > Implement VP8 style screensharing but with spatial layers.
> > Implement flexible mode.
> >
> > Files from other patches:
> > generic_encoder.cc
> > layer_filtering_transport.cc
> >
> > BUG=webrtc:4914
> >
> > Committed: https://crrev.com/77ccfb4d16c148e61a316746bb5d9705e8b39f4a
> > Cr-Commit-Position: refs/heads/master@{#10572}
>
> TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,philipel@webrtc.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:4914
>
> Committed: https://crrev.com/0be8f1d347bdb171462df89c2a4c69b3f3eb7519
> Cr-Commit-Position: refs/heads/master@{#10578}
TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,terelius@webrtc.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:4914
Review URL: https://codereview.webrtc.org/1431283002
Cr-Commit-Position: refs/heads/master@{#10581}
2015-11-10 07:17:23 -08:00
|
|
|
vpx_enc_frame_flags_t flags = 0;
|
2018-05-03 14:14:09 +02:00
|
|
|
if (force_key_frame_) {
|
2014-11-01 06:10:48 +00:00
|
|
|
flags = VPX_EFLAG_FORCE_KF;
|
|
|
|
|
}
|
Reland of Work on flexible mode and screen sharing. (patchset #1 id:1 of https://codereview.webrtc.org/1438543002/ )
Reason for revert:
Failed test not related to this CL (test fails on
master at an earlier date), re-landing original CL..
(This time from my @webrtc account.)
Original issue's description:
> Revert of Work on flexible mode and screen sharing. (patchset #28 id:520001 of https://codereview.webrtc.org/1328113004/ )
>
> Reason for revert:
> Seems to break VideoSendStreamTest.ReconfigureBitratesSetsEncoderBitratesCorrectly on Linux Memcheck buildbot.
>
> Original issue's description:
> > Work on flexible mode and screen sharing.
> >
> > Implement VP8 style screensharing but with spatial layers.
> > Implement flexible mode.
> >
> > Files from other patches:
> > generic_encoder.cc
> > layer_filtering_transport.cc
> >
> > BUG=webrtc:4914
> >
> > Committed: https://crrev.com/77ccfb4d16c148e61a316746bb5d9705e8b39f4a
> > Cr-Commit-Position: refs/heads/master@{#10572}
>
> TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,philipel@webrtc.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:4914
>
> Committed: https://crrev.com/0be8f1d347bdb171462df89c2a4c69b3f3eb7519
> Cr-Commit-Position: refs/heads/master@{#10578}
TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,terelius@webrtc.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:4914
Review URL: https://codereview.webrtc.org/1431283002
Cr-Commit-Position: refs/heads/master@{#10581}
2015-11-10 07:17:23 -08:00
|
|
|
|
2020-10-15 17:26:46 +02:00
|
|
|
if (svc_controller_) {
|
|
|
|
|
vpx_svc_ref_frame_config_t ref_config = Vp9References(layer_frames_);
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_REF_FRAME_CONFIG,
|
|
|
|
|
&ref_config);
|
2020-10-15 17:26:46 +02:00
|
|
|
} else if (external_ref_control_) {
|
2018-12-04 15:54:52 +01:00
|
|
|
vpx_svc_ref_frame_config_t ref_config =
|
|
|
|
|
SetReferences(force_key_frame_, layer_id.spatial_layer_id);
|
2018-10-02 10:28:10 +02:00
|
|
|
|
|
|
|
|
if (VideoCodecMode::kScreensharing == codec_.mode) {
|
|
|
|
|
for (uint8_t sl_idx = 0; sl_idx < num_active_spatial_layers_; ++sl_idx) {
|
|
|
|
|
ref_config.duration[sl_idx] = static_cast<int64_t>(
|
2019-05-24 11:51:31 +02:00
|
|
|
90000 / (std::min(static_cast<float>(codec_.maxFramerate),
|
|
|
|
|
framerate_controller_[sl_idx].GetTargetRate())));
|
2018-10-02 10:28:10 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_SET_SVC_REF_FRAME_CONFIG,
|
|
|
|
|
&ref_config);
|
2018-10-01 17:13:50 +02:00
|
|
|
}
|
|
|
|
|
|
2018-11-23 13:59:24 +01:00
|
|
|
first_frame_in_picture_ = true;
|
|
|
|
|
|
2018-09-05 21:07:17 +02:00
|
|
|
// TODO(ssilkin): Frame duration should be specified per spatial layer
|
|
|
|
|
// since their frame rate can be different. For now calculate frame duration
|
|
|
|
|
// based on target frame rate of the highest spatial layer, which frame rate
|
|
|
|
|
// is supposed to be equal or higher than frame rate of low spatial layers.
|
|
|
|
|
// Also, timestamp should represent actual time passed since previous frame
|
|
|
|
|
// (not 'expected' time). Then rate controller can drain buffer more
|
|
|
|
|
// accurately.
|
|
|
|
|
RTC_DCHECK_GE(framerate_controller_.size(), num_active_spatial_layers_);
|
2018-09-17 09:37:37 +02:00
|
|
|
float target_framerate_fps =
|
|
|
|
|
(codec_.mode == VideoCodecMode::kScreensharing)
|
2019-05-24 11:51:31 +02:00
|
|
|
? std::min(static_cast<float>(codec_.maxFramerate),
|
|
|
|
|
framerate_controller_[num_active_spatial_layers_ - 1]
|
|
|
|
|
.GetTargetRate())
|
2018-09-17 09:37:37 +02:00
|
|
|
: codec_.maxFramerate;
|
|
|
|
|
uint32_t duration = static_cast<uint32_t>(90000 / target_framerate_fps);
|
2020-12-13 14:50:59 +01:00
|
|
|
const vpx_codec_err_t rv = libvpx_->codec_encode(
|
|
|
|
|
encoder_, raw_, timestamp_, duration, flags, VPX_DL_REALTIME);
|
2018-07-13 17:10:00 -07:00
|
|
|
if (rv != VPX_CODEC_OK) {
|
2020-12-13 14:50:59 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "Encoding error: " << libvpx_->codec_err_to_string(rv)
|
2018-07-13 17:10:00 -07:00
|
|
|
<< "\n"
|
2020-01-14 12:11:31 +01:00
|
|
|
"Details: "
|
2020-12-13 14:50:59 +01:00
|
|
|
<< libvpx_->codec_error(encoder_) << "\n"
|
|
|
|
|
<< libvpx_->codec_error_detail(encoder_);
|
2014-11-01 06:10:48 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|
|
|
}
|
|
|
|
|
timestamp_ += duration;
|
2015-07-31 06:10:09 -07:00
|
|
|
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-03 12:33:17 +01:00
|
|
|
bool LibvpxVp9Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
|
2020-12-09 20:58:21 +01:00
|
|
|
absl::optional<int>* spatial_idx,
|
2022-04-25 17:28:00 +02:00
|
|
|
absl::optional<int>* temporal_idx,
|
2022-01-19 14:17:14 +01:00
|
|
|
const vpx_codec_cx_pkt& pkt) {
|
2017-08-17 08:12:10 -07:00
|
|
|
RTC_CHECK(codec_specific != nullptr);
|
2014-11-01 06:10:48 +00:00
|
|
|
codec_specific->codecType = kVideoCodecVP9;
|
2015-12-21 03:04:49 -08:00
|
|
|
CodecSpecificInfoVP9* vp9_info = &(codec_specific->codecSpecific.VP9);
|
2018-04-09 13:11:59 +02:00
|
|
|
|
2018-11-23 13:59:24 +01:00
|
|
|
vp9_info->first_frame_in_picture = first_frame_in_picture_;
|
2018-08-23 16:37:27 +02:00
|
|
|
vp9_info->flexible_mode = is_flexible_mode_;
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
if (pkt.data.frame.flags & VPX_FRAME_IS_KEY) {
|
|
|
|
|
pics_since_key_ = 0;
|
|
|
|
|
} else if (first_frame_in_picture_) {
|
|
|
|
|
++pics_since_key_;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-31 06:10:09 -07:00
|
|
|
vpx_svc_layer_id_t layer_id = {0};
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2019-01-18 11:56:48 +01:00
|
|
|
// Can't have keyframe with non-zero temporal layer.
|
|
|
|
|
RTC_DCHECK(pics_since_key_ != 0 || layer_id.temporal_layer_id == 0);
|
|
|
|
|
|
2017-08-17 08:12:10 -07:00
|
|
|
RTC_CHECK_GT(num_temporal_layers_, 0);
|
2018-06-21 11:07:21 -05:00
|
|
|
RTC_CHECK_GT(num_active_spatial_layers_, 0);
|
2015-07-31 06:10:09 -07:00
|
|
|
if (num_temporal_layers_ == 1) {
|
2017-08-17 08:12:10 -07:00
|
|
|
RTC_CHECK_EQ(layer_id.temporal_layer_id, 0);
|
2015-07-31 06:10:09 -07:00
|
|
|
vp9_info->temporal_idx = kNoTemporalIdx;
|
2022-04-25 17:28:00 +02:00
|
|
|
*temporal_idx = absl::nullopt;
|
2015-07-31 06:10:09 -07:00
|
|
|
} else {
|
|
|
|
|
vp9_info->temporal_idx = layer_id.temporal_layer_id;
|
2022-04-25 17:28:00 +02:00
|
|
|
*temporal_idx = layer_id.temporal_layer_id;
|
2015-07-31 06:10:09 -07:00
|
|
|
}
|
2018-06-21 11:07:21 -05:00
|
|
|
if (num_active_spatial_layers_ == 1) {
|
2017-08-17 08:12:10 -07:00
|
|
|
RTC_CHECK_EQ(layer_id.spatial_layer_id, 0);
|
2018-08-27 15:33:42 +02:00
|
|
|
*spatial_idx = absl::nullopt;
|
2015-07-31 06:10:09 -07:00
|
|
|
} else {
|
2018-08-27 15:33:42 +02:00
|
|
|
*spatial_idx = layer_id.spatial_layer_id;
|
2015-07-31 06:10:09 -07:00
|
|
|
}
|
|
|
|
|
|
2018-04-26 11:03:49 +02:00
|
|
|
const bool is_key_pic = (pics_since_key_ == 0);
|
|
|
|
|
const bool is_inter_layer_pred_allowed =
|
|
|
|
|
(inter_layer_pred_ == InterLayerPredMode::kOn ||
|
|
|
|
|
(inter_layer_pred_ == InterLayerPredMode::kOnKeyPic && is_key_pic));
|
|
|
|
|
|
|
|
|
|
// Always set inter_layer_predicted to true on high layer frame if inter-layer
|
|
|
|
|
// prediction (ILP) is allowed even if encoder didn't actually use it.
|
|
|
|
|
// Setting inter_layer_predicted to false would allow receiver to decode high
|
|
|
|
|
// layer frame without decoding low layer frame. If that would happen (e.g.
|
|
|
|
|
// if low layer frame is lost) then receiver won't be able to decode next high
|
|
|
|
|
// layer frame which uses ILP.
|
|
|
|
|
vp9_info->inter_layer_predicted =
|
2018-11-23 13:59:24 +01:00
|
|
|
first_frame_in_picture_ ? false : is_inter_layer_pred_allowed;
|
2018-04-26 11:03:49 +02:00
|
|
|
|
2018-09-26 13:28:50 +02:00
|
|
|
// Mark all low spatial layer frames as references (not just frames of
|
|
|
|
|
// active low spatial layers) if inter-layer prediction is enabled since
|
|
|
|
|
// these frames are indirect references of high spatial layer, which can
|
|
|
|
|
// later be enabled without key frame.
|
2018-04-26 11:03:49 +02:00
|
|
|
vp9_info->non_ref_for_inter_layer_pred =
|
2018-09-26 13:28:50 +02:00
|
|
|
!is_inter_layer_pred_allowed ||
|
|
|
|
|
layer_id.spatial_layer_id + 1 == num_spatial_layers_;
|
2015-11-11 05:30:48 -08:00
|
|
|
|
2015-09-08 02:40:29 -07:00
|
|
|
// Always populate this, so that the packetizer can properly set the marker
|
|
|
|
|
// bit.
|
2018-06-21 11:07:21 -05:00
|
|
|
vp9_info->num_spatial_layers = num_active_spatial_layers_;
|
2020-02-04 10:06:33 +00:00
|
|
|
vp9_info->first_active_layer = first_active_layer_;
|
Reland of Work on flexible mode and screen sharing. (patchset #1 id:1 of https://codereview.webrtc.org/1438543002/ )
Reason for revert:
Failed test not related to this CL (test fails on
master at an earlier date), re-landing original CL..
(This time from my @webrtc account.)
Original issue's description:
> Revert of Work on flexible mode and screen sharing. (patchset #28 id:520001 of https://codereview.webrtc.org/1328113004/ )
>
> Reason for revert:
> Seems to break VideoSendStreamTest.ReconfigureBitratesSetsEncoderBitratesCorrectly on Linux Memcheck buildbot.
>
> Original issue's description:
> > Work on flexible mode and screen sharing.
> >
> > Implement VP8 style screensharing but with spatial layers.
> > Implement flexible mode.
> >
> > Files from other patches:
> > generic_encoder.cc
> > layer_filtering_transport.cc
> >
> > BUG=webrtc:4914
> >
> > Committed: https://crrev.com/77ccfb4d16c148e61a316746bb5d9705e8b39f4a
> > Cr-Commit-Position: refs/heads/master@{#10572}
>
> TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,philipel@webrtc.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:4914
>
> Committed: https://crrev.com/0be8f1d347bdb171462df89c2a4c69b3f3eb7519
> Cr-Commit-Position: refs/heads/master@{#10578}
TBR=sprang@webrtc.org,stefan@webrtc.org,philipel@google.com,asapersson@webrtc.org,mflodman@webrtc.org,terelius@webrtc.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:4914
Review URL: https://codereview.webrtc.org/1431283002
Cr-Commit-Position: refs/heads/master@{#10581}
2015-11-10 07:17:23 -08:00
|
|
|
|
2018-05-28 12:26:36 +02:00
|
|
|
vp9_info->num_ref_pics = 0;
|
2019-01-18 11:56:48 +01:00
|
|
|
FillReferenceIndices(pkt, pics_since_key_, vp9_info->inter_layer_predicted,
|
|
|
|
|
vp9_info);
|
2018-05-28 12:26:36 +02:00
|
|
|
if (vp9_info->flexible_mode) {
|
|
|
|
|
vp9_info->gof_idx = kNoGofIdx;
|
2022-01-19 14:17:14 +01:00
|
|
|
if (!svc_controller_) {
|
|
|
|
|
if (num_temporal_layers_ == 1) {
|
|
|
|
|
vp9_info->temporal_up_switch = true;
|
|
|
|
|
} else {
|
|
|
|
|
// In flexible mode with > 1 temporal layer but no SVC controller we
|
|
|
|
|
// can't techincally determine if a frame is an upswitch point, use
|
|
|
|
|
// gof-based data as proxy for now.
|
|
|
|
|
// TODO(sprang): Remove once SVC controller is the only choice.
|
|
|
|
|
vp9_info->gof_idx =
|
|
|
|
|
static_cast<uint8_t>(pics_since_key_ % gof_.num_frames_in_gof);
|
|
|
|
|
vp9_info->temporal_up_switch =
|
|
|
|
|
gof_.temporal_up_switch[vp9_info->gof_idx];
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-28 12:26:36 +02:00
|
|
|
} else {
|
|
|
|
|
vp9_info->gof_idx =
|
|
|
|
|
static_cast<uint8_t>(pics_since_key_ % gof_.num_frames_in_gof);
|
|
|
|
|
vp9_info->temporal_up_switch = gof_.temporal_up_switch[vp9_info->gof_idx];
|
2019-01-18 11:56:48 +01:00
|
|
|
RTC_DCHECK(vp9_info->num_ref_pics == gof_.num_ref_pics[vp9_info->gof_idx] ||
|
|
|
|
|
vp9_info->num_ref_pics == 0);
|
2018-05-28 12:26:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vp9_info->inter_pic_predicted = (!is_key_pic && vp9_info->num_ref_pics > 0);
|
|
|
|
|
|
2019-04-23 10:09:28 +02:00
|
|
|
// Write SS on key frame of independently coded spatial layers and on base
|
|
|
|
|
// temporal/spatial layer frame if number of layers changed without issuing
|
|
|
|
|
// of key picture (inter-layer prediction is enabled).
|
|
|
|
|
const bool is_key_frame = is_key_pic && !vp9_info->inter_layer_predicted;
|
|
|
|
|
if (is_key_frame || (ss_info_needed_ && layer_id.temporal_layer_id == 0 &&
|
2019-09-25 09:10:33 +00:00
|
|
|
layer_id.spatial_layer_id == first_active_layer_)) {
|
2019-04-23 10:09:28 +02:00
|
|
|
vp9_info->ss_data_available = true;
|
2015-07-31 06:10:09 -07:00
|
|
|
vp9_info->spatial_layer_resolution_present = true;
|
2019-09-25 09:10:33 +00:00
|
|
|
// Signal disabled layers.
|
|
|
|
|
for (size_t i = 0; i < first_active_layer_; ++i) {
|
|
|
|
|
vp9_info->width[i] = 0;
|
|
|
|
|
vp9_info->height[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = first_active_layer_; i < num_active_spatial_layers_; ++i) {
|
2017-01-26 13:23:44 -08:00
|
|
|
vp9_info->width[i] = codec_.width * svc_params_.scaling_factor_num[i] /
|
|
|
|
|
svc_params_.scaling_factor_den[i];
|
2015-07-31 06:10:09 -07:00
|
|
|
vp9_info->height[i] = codec_.height * svc_params_.scaling_factor_num[i] /
|
2017-01-26 13:23:44 -08:00
|
|
|
svc_params_.scaling_factor_den[i];
|
2015-07-31 06:10:09 -07:00
|
|
|
}
|
2018-08-23 16:37:27 +02:00
|
|
|
if (vp9_info->flexible_mode) {
|
|
|
|
|
vp9_info->gof.num_frames_in_gof = 0;
|
|
|
|
|
} else {
|
2015-07-31 06:10:09 -07:00
|
|
|
vp9_info->gof.CopyGofInfoVP9(gof_);
|
|
|
|
|
}
|
2019-04-23 10:09:28 +02:00
|
|
|
|
|
|
|
|
ss_info_needed_ = false;
|
|
|
|
|
} else {
|
|
|
|
|
vp9_info->ss_data_available = false;
|
2015-07-31 06:10:09 -07:00
|
|
|
}
|
2018-11-23 13:59:24 +01:00
|
|
|
|
|
|
|
|
first_frame_in_picture_ = false;
|
2020-10-15 17:26:46 +02:00
|
|
|
|
|
|
|
|
// Populate codec-agnostic section in the codec specific structure.
|
|
|
|
|
if (svc_controller_) {
|
|
|
|
|
auto it = absl::c_find_if(
|
|
|
|
|
layer_frames_,
|
|
|
|
|
[&](const ScalableVideoController::LayerFrameConfig& config) {
|
2021-02-03 12:33:17 +01:00
|
|
|
return config.SpatialId() == layer_id.spatial_layer_id;
|
2020-10-15 17:26:46 +02:00
|
|
|
});
|
2021-02-03 12:33:17 +01:00
|
|
|
if (it == layer_frames_.end()) {
|
|
|
|
|
RTC_LOG(LS_ERROR) << "Encoder produced a frame for layer S"
|
|
|
|
|
<< layer_id.spatial_layer_id << "T"
|
|
|
|
|
<< layer_id.temporal_layer_id
|
|
|
|
|
<< " that wasn't requested.";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-10-15 17:26:46 +02:00
|
|
|
codec_specific->generic_frame_info = svc_controller_->OnEncodeDone(*it);
|
|
|
|
|
if (is_key_frame) {
|
|
|
|
|
codec_specific->template_structure =
|
|
|
|
|
svc_controller_->DependencyStructure();
|
|
|
|
|
auto& resolutions = codec_specific->template_structure->resolutions;
|
|
|
|
|
resolutions.resize(num_spatial_layers_);
|
|
|
|
|
for (int sid = 0; sid < num_spatial_layers_; ++sid) {
|
|
|
|
|
resolutions[sid] = RenderResolution(
|
|
|
|
|
/*width=*/codec_.width * svc_params_.scaling_factor_num[sid] /
|
|
|
|
|
svc_params_.scaling_factor_den[sid],
|
|
|
|
|
/*height=*/codec_.height * svc_params_.scaling_factor_num[sid] /
|
|
|
|
|
svc_params_.scaling_factor_den[sid]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-19 14:17:14 +01:00
|
|
|
if (is_flexible_mode_) {
|
|
|
|
|
// Populate data for legacy temporal-upswitch state.
|
|
|
|
|
// We can switch up to a higher temporal layer only if all temporal layers
|
|
|
|
|
// higher than this (within the current spatial layer) are switch points.
|
|
|
|
|
vp9_info->temporal_up_switch = true;
|
|
|
|
|
for (int i = layer_id.temporal_layer_id + 1; i < num_temporal_layers_;
|
|
|
|
|
++i) {
|
|
|
|
|
// Assumes decode targets are always ordered first by spatial then by
|
|
|
|
|
// temporal id.
|
|
|
|
|
size_t dti_index =
|
|
|
|
|
(layer_id.spatial_layer_id * num_temporal_layers_) + i;
|
|
|
|
|
vp9_info->temporal_up_switch &=
|
|
|
|
|
(codec_specific->generic_frame_info
|
|
|
|
|
->decode_target_indications[dti_index] ==
|
|
|
|
|
DecodeTargetIndication::kSwitch);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-15 17:26:46 +02:00
|
|
|
}
|
2022-12-06 10:09:10 +00:00
|
|
|
codec_specific->scalability_mode = scalability_mode_;
|
2021-02-03 12:33:17 +01:00
|
|
|
return true;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::FillReferenceIndices(const vpx_codec_cx_pkt& pkt,
|
|
|
|
|
const size_t pic_num,
|
|
|
|
|
const bool inter_layer_predicted,
|
|
|
|
|
CodecSpecificInfoVP9* vp9_info) {
|
2018-05-28 12:26:36 +02:00
|
|
|
vpx_svc_layer_id_t layer_id = {0};
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
|
2018-05-28 12:26:36 +02:00
|
|
|
|
2018-08-21 12:30:33 +02:00
|
|
|
const bool is_key_frame =
|
|
|
|
|
(pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
|
2018-05-28 12:26:36 +02:00
|
|
|
|
|
|
|
|
std::vector<RefFrameBuffer> ref_buf_list;
|
|
|
|
|
|
2018-08-21 12:30:33 +02:00
|
|
|
if (is_svc_) {
|
|
|
|
|
vpx_svc_ref_frame_config_t enc_layer_conf = {{0}};
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_GET_SVC_REF_FRAME_CONFIG,
|
|
|
|
|
&enc_layer_conf);
|
2022-09-08 16:33:34 +02:00
|
|
|
char ref_buf_flags[] = "00000000";
|
|
|
|
|
// There should be one character per buffer + 1 termination '\0'.
|
|
|
|
|
static_assert(sizeof(ref_buf_flags) == kNumVp9Buffers + 1);
|
2018-08-21 12:30:33 +02:00
|
|
|
|
|
|
|
|
if (enc_layer_conf.reference_last[layer_id.spatial_layer_id]) {
|
|
|
|
|
const size_t fb_idx =
|
|
|
|
|
enc_layer_conf.lst_fb_idx[layer_id.spatial_layer_id];
|
2022-07-28 09:58:58 +02:00
|
|
|
RTC_DCHECK_LT(fb_idx, ref_buf_.size());
|
2018-08-27 14:54:20 +02:00
|
|
|
if (std::find(ref_buf_list.begin(), ref_buf_list.end(),
|
2022-07-28 09:58:58 +02:00
|
|
|
ref_buf_[fb_idx]) == ref_buf_list.end()) {
|
|
|
|
|
ref_buf_list.push_back(ref_buf_[fb_idx]);
|
2022-09-08 16:33:34 +02:00
|
|
|
ref_buf_flags[fb_idx] = '1';
|
2018-08-27 14:54:20 +02:00
|
|
|
}
|
2018-08-21 12:30:33 +02:00
|
|
|
}
|
2018-05-28 12:26:36 +02:00
|
|
|
|
2018-08-21 12:30:33 +02:00
|
|
|
if (enc_layer_conf.reference_alt_ref[layer_id.spatial_layer_id]) {
|
|
|
|
|
const size_t fb_idx =
|
|
|
|
|
enc_layer_conf.alt_fb_idx[layer_id.spatial_layer_id];
|
2022-07-28 09:58:58 +02:00
|
|
|
RTC_DCHECK_LT(fb_idx, ref_buf_.size());
|
2018-08-27 14:54:20 +02:00
|
|
|
if (std::find(ref_buf_list.begin(), ref_buf_list.end(),
|
2022-07-28 09:58:58 +02:00
|
|
|
ref_buf_[fb_idx]) == ref_buf_list.end()) {
|
|
|
|
|
ref_buf_list.push_back(ref_buf_[fb_idx]);
|
2022-09-08 16:33:34 +02:00
|
|
|
ref_buf_flags[fb_idx] = '1';
|
2018-08-27 14:54:20 +02:00
|
|
|
}
|
2018-08-21 12:30:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (enc_layer_conf.reference_golden[layer_id.spatial_layer_id]) {
|
|
|
|
|
const size_t fb_idx =
|
|
|
|
|
enc_layer_conf.gld_fb_idx[layer_id.spatial_layer_id];
|
2022-07-28 09:58:58 +02:00
|
|
|
RTC_DCHECK_LT(fb_idx, ref_buf_.size());
|
2018-08-27 14:54:20 +02:00
|
|
|
if (std::find(ref_buf_list.begin(), ref_buf_list.end(),
|
2022-07-28 09:58:58 +02:00
|
|
|
ref_buf_[fb_idx]) == ref_buf_list.end()) {
|
|
|
|
|
ref_buf_list.push_back(ref_buf_[fb_idx]);
|
2022-09-08 16:33:34 +02:00
|
|
|
ref_buf_flags[fb_idx] = '1';
|
2018-08-27 14:54:20 +02:00
|
|
|
}
|
2018-08-21 12:30:33 +02:00
|
|
|
}
|
2019-03-21 10:08:40 +01:00
|
|
|
|
|
|
|
|
RTC_LOG(LS_VERBOSE) << "Frame " << pic_num << " sl "
|
|
|
|
|
<< layer_id.spatial_layer_id << " tl "
|
|
|
|
|
<< layer_id.temporal_layer_id << " refered buffers "
|
2022-09-08 16:33:34 +02:00
|
|
|
<< ref_buf_flags;
|
2019-03-21 10:08:40 +01:00
|
|
|
|
2018-08-21 12:30:33 +02:00
|
|
|
} else if (!is_key_frame) {
|
|
|
|
|
RTC_DCHECK_EQ(num_spatial_layers_, 1);
|
|
|
|
|
RTC_DCHECK_EQ(num_temporal_layers_, 1);
|
|
|
|
|
// In non-SVC mode encoder doesn't provide reference list. Assume each frame
|
|
|
|
|
// refers previous one, which is stored in buffer 0.
|
2022-07-28 09:58:58 +02:00
|
|
|
ref_buf_list.push_back(ref_buf_[0]);
|
2018-05-28 12:26:36 +02:00
|
|
|
}
|
|
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
std::vector<size_t> ref_pid_list;
|
|
|
|
|
|
2018-05-28 12:26:36 +02:00
|
|
|
vp9_info->num_ref_pics = 0;
|
|
|
|
|
for (const RefFrameBuffer& ref_buf : ref_buf_list) {
|
|
|
|
|
RTC_DCHECK_LE(ref_buf.pic_num, pic_num);
|
|
|
|
|
if (ref_buf.pic_num < pic_num) {
|
|
|
|
|
if (inter_layer_pred_ != InterLayerPredMode::kOn) {
|
|
|
|
|
// RTP spec limits temporal prediction to the same spatial layer.
|
|
|
|
|
// It is safe to ignore this requirement if inter-layer prediction is
|
|
|
|
|
// enabled for all frames when all base frames are relayed to receiver.
|
|
|
|
|
RTC_DCHECK_EQ(ref_buf.spatial_layer_id, layer_id.spatial_layer_id);
|
2019-05-24 11:51:31 +02:00
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK_LE(ref_buf.spatial_layer_id, layer_id.spatial_layer_id);
|
2018-05-28 12:26:36 +02:00
|
|
|
}
|
|
|
|
|
RTC_DCHECK_LE(ref_buf.temporal_layer_id, layer_id.temporal_layer_id);
|
|
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
// Encoder may reference several spatial layers on the same previous
|
|
|
|
|
// frame in case if some spatial layers are skipped on the current frame.
|
|
|
|
|
// We shouldn't put duplicate references as it may break some old
|
|
|
|
|
// clients and isn't RTP compatible.
|
|
|
|
|
if (std::find(ref_pid_list.begin(), ref_pid_list.end(),
|
|
|
|
|
ref_buf.pic_num) != ref_pid_list.end()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
ref_pid_list.push_back(ref_buf.pic_num);
|
|
|
|
|
|
2018-05-28 12:26:36 +02:00
|
|
|
const size_t p_diff = pic_num - ref_buf.pic_num;
|
|
|
|
|
RTC_DCHECK_LE(p_diff, 127UL);
|
|
|
|
|
|
|
|
|
|
vp9_info->p_diff[vp9_info->num_ref_pics] = static_cast<uint8_t>(p_diff);
|
|
|
|
|
++vp9_info->num_ref_pics;
|
|
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK(inter_layer_predicted);
|
|
|
|
|
// RTP spec only allows to use previous spatial layer for inter-layer
|
|
|
|
|
// prediction.
|
|
|
|
|
RTC_DCHECK_EQ(ref_buf.spatial_layer_id + 1, layer_id.spatial_layer_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::UpdateReferenceBuffers(const vpx_codec_cx_pkt& pkt,
|
|
|
|
|
const size_t pic_num) {
|
2018-05-28 12:26:36 +02:00
|
|
|
vpx_svc_layer_id_t layer_id = {0};
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
|
2018-05-28 12:26:36 +02:00
|
|
|
|
2022-07-28 09:58:58 +02:00
|
|
|
RefFrameBuffer frame_buf = {.pic_num = pic_num,
|
|
|
|
|
.spatial_layer_id = layer_id.spatial_layer_id,
|
|
|
|
|
.temporal_layer_id = layer_id.temporal_layer_id};
|
2018-05-28 12:26:36 +02:00
|
|
|
|
2019-03-21 10:08:40 +01:00
|
|
|
if (is_svc_) {
|
2018-08-21 12:30:33 +02:00
|
|
|
vpx_svc_ref_frame_config_t enc_layer_conf = {{0}};
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_GET_SVC_REF_FRAME_CONFIG,
|
|
|
|
|
&enc_layer_conf);
|
2019-03-21 10:08:40 +01:00
|
|
|
const int update_buffer_slot =
|
|
|
|
|
enc_layer_conf.update_buffer_slot[layer_id.spatial_layer_id];
|
2018-08-21 12:30:33 +02:00
|
|
|
|
2022-07-28 09:58:58 +02:00
|
|
|
for (size_t i = 0; i < ref_buf_.size(); ++i) {
|
2019-03-21 10:08:40 +01:00
|
|
|
if (update_buffer_slot & (1 << i)) {
|
2018-12-04 15:54:52 +01:00
|
|
|
ref_buf_[i] = frame_buf;
|
|
|
|
|
}
|
2018-05-28 12:26:36 +02:00
|
|
|
}
|
2019-03-21 10:08:40 +01:00
|
|
|
|
|
|
|
|
RTC_LOG(LS_VERBOSE) << "Frame " << pic_num << " sl "
|
|
|
|
|
<< layer_id.spatial_layer_id << " tl "
|
|
|
|
|
<< layer_id.temporal_layer_id << " updated buffers "
|
|
|
|
|
<< (update_buffer_slot & (1 << 0) ? 1 : 0)
|
|
|
|
|
<< (update_buffer_slot & (1 << 1) ? 1 : 0)
|
|
|
|
|
<< (update_buffer_slot & (1 << 2) ? 1 : 0)
|
|
|
|
|
<< (update_buffer_slot & (1 << 3) ? 1 : 0)
|
|
|
|
|
<< (update_buffer_slot & (1 << 4) ? 1 : 0)
|
|
|
|
|
<< (update_buffer_slot & (1 << 5) ? 1 : 0)
|
|
|
|
|
<< (update_buffer_slot & (1 << 6) ? 1 : 0)
|
|
|
|
|
<< (update_buffer_slot & (1 << 7) ? 1 : 0);
|
2018-08-21 12:30:33 +02:00
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK_EQ(num_spatial_layers_, 1);
|
|
|
|
|
RTC_DCHECK_EQ(num_temporal_layers_, 1);
|
|
|
|
|
// In non-svc mode encoder doesn't provide reference list. Assume each frame
|
|
|
|
|
// is reference and stored in buffer 0.
|
|
|
|
|
ref_buf_[0] = frame_buf;
|
2018-05-28 12:26:36 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
vpx_svc_ref_frame_config_t LibvpxVp9Encoder::SetReferences(
|
2018-12-04 15:54:52 +01:00
|
|
|
bool is_key_pic,
|
2022-07-28 09:58:58 +02:00
|
|
|
int first_active_spatial_layer_id) {
|
2018-10-01 17:13:50 +02:00
|
|
|
// kRefBufIdx, kUpdBufIdx need to be updated to support longer GOFs.
|
|
|
|
|
RTC_DCHECK_LE(gof_.num_frames_in_gof, 4);
|
|
|
|
|
|
|
|
|
|
vpx_svc_ref_frame_config_t ref_config;
|
|
|
|
|
memset(&ref_config, 0, sizeof(ref_config));
|
|
|
|
|
|
|
|
|
|
const size_t num_temporal_refs = std::max(1, num_temporal_layers_ - 1);
|
|
|
|
|
const bool is_inter_layer_pred_allowed =
|
|
|
|
|
inter_layer_pred_ == InterLayerPredMode::kOn ||
|
|
|
|
|
(inter_layer_pred_ == InterLayerPredMode::kOnKeyPic && is_key_pic);
|
|
|
|
|
absl::optional<int> last_updated_buf_idx;
|
|
|
|
|
|
|
|
|
|
// Put temporal reference to LAST and spatial reference to GOLDEN. Update
|
|
|
|
|
// frame buffer (i.e. store encoded frame) if current frame is a temporal
|
|
|
|
|
// reference (i.e. it belongs to a low temporal layer) or it is a spatial
|
|
|
|
|
// reference. In later case, always store spatial reference in the last
|
|
|
|
|
// reference frame buffer.
|
|
|
|
|
// For the case of 3 temporal and 3 spatial layers we need 6 frame buffers
|
|
|
|
|
// for temporal references plus 1 buffer for spatial reference. 7 buffers
|
|
|
|
|
// in total.
|
|
|
|
|
|
2022-07-28 09:58:58 +02:00
|
|
|
for (int sl_idx = first_active_spatial_layer_id;
|
2018-12-04 15:54:52 +01:00
|
|
|
sl_idx < num_active_spatial_layers_; ++sl_idx) {
|
|
|
|
|
const size_t curr_pic_num = is_key_pic ? 0 : pics_since_key_ + 1;
|
|
|
|
|
const size_t gof_idx = curr_pic_num % gof_.num_frames_in_gof;
|
2018-10-01 17:13:50 +02:00
|
|
|
|
|
|
|
|
if (!is_key_pic) {
|
|
|
|
|
// Set up temporal reference.
|
|
|
|
|
const int buf_idx = sl_idx * num_temporal_refs + kRefBufIdx[gof_idx];
|
|
|
|
|
|
|
|
|
|
// Last reference frame buffer is reserved for spatial reference. It is
|
|
|
|
|
// not supposed to be used for temporal prediction.
|
|
|
|
|
RTC_DCHECK_LT(buf_idx, kNumVp9Buffers - 1);
|
|
|
|
|
|
2019-09-06 13:12:52 +02:00
|
|
|
const int pid_diff = curr_pic_num - ref_buf_[buf_idx].pic_num;
|
2018-12-04 15:54:52 +01:00
|
|
|
// Incorrect spatial layer may be in the buffer due to a key-frame.
|
|
|
|
|
const bool same_spatial_layer =
|
|
|
|
|
ref_buf_[buf_idx].spatial_layer_id == sl_idx;
|
|
|
|
|
bool correct_pid = false;
|
2019-05-24 11:51:31 +02:00
|
|
|
if (is_flexible_mode_) {
|
2019-09-06 13:12:52 +02:00
|
|
|
correct_pid = pid_diff > 0 && pid_diff < kMaxAllowedPidDiff;
|
2018-12-04 15:54:52 +01:00
|
|
|
} else {
|
|
|
|
|
// Below code assumes single temporal referecence.
|
|
|
|
|
RTC_DCHECK_EQ(gof_.num_ref_pics[gof_idx], 1);
|
|
|
|
|
correct_pid = pid_diff == gof_.pid_diff[gof_idx][0];
|
|
|
|
|
}
|
2018-10-01 17:13:50 +02:00
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
if (same_spatial_layer && correct_pid) {
|
2018-10-01 17:13:50 +02:00
|
|
|
ref_config.lst_fb_idx[sl_idx] = buf_idx;
|
|
|
|
|
ref_config.reference_last[sl_idx] = 1;
|
|
|
|
|
} else {
|
|
|
|
|
// This reference doesn't match with one specified by GOF. This can
|
|
|
|
|
// only happen if spatial layer is enabled dynamically without key
|
|
|
|
|
// frame. Spatial prediction is supposed to be enabled in this case.
|
2018-12-04 15:54:52 +01:00
|
|
|
RTC_DCHECK(is_inter_layer_pred_allowed &&
|
|
|
|
|
sl_idx > first_active_spatial_layer_id);
|
2018-10-01 17:13:50 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
if (is_inter_layer_pred_allowed && sl_idx > first_active_spatial_layer_id) {
|
2018-10-01 17:13:50 +02:00
|
|
|
// Set up spatial reference.
|
|
|
|
|
RTC_DCHECK(last_updated_buf_idx);
|
|
|
|
|
ref_config.gld_fb_idx[sl_idx] = *last_updated_buf_idx;
|
|
|
|
|
ref_config.reference_golden[sl_idx] = 1;
|
|
|
|
|
} else {
|
2018-12-04 15:54:52 +01:00
|
|
|
RTC_DCHECK(ref_config.reference_last[sl_idx] != 0 ||
|
|
|
|
|
sl_idx == first_active_spatial_layer_id ||
|
2018-10-01 17:13:50 +02:00
|
|
|
inter_layer_pred_ == InterLayerPredMode::kOff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
last_updated_buf_idx.reset();
|
|
|
|
|
|
2018-12-04 15:54:52 +01:00
|
|
|
if (gof_.temporal_idx[gof_idx] < num_temporal_layers_ - 1 ||
|
|
|
|
|
num_temporal_layers_ == 1) {
|
2018-10-01 17:13:50 +02:00
|
|
|
last_updated_buf_idx = sl_idx * num_temporal_refs + kUpdBufIdx[gof_idx];
|
|
|
|
|
|
|
|
|
|
// Ensure last frame buffer is not used for temporal prediction (it is
|
|
|
|
|
// reserved for spatial reference).
|
|
|
|
|
RTC_DCHECK_LT(*last_updated_buf_idx, kNumVp9Buffers - 1);
|
|
|
|
|
} else if (is_inter_layer_pred_allowed) {
|
|
|
|
|
last_updated_buf_idx = kNumVp9Buffers - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (last_updated_buf_idx) {
|
|
|
|
|
ref_config.update_buffer_slot[sl_idx] = 1 << *last_updated_buf_idx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ref_config;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-03 12:33:17 +01:00
|
|
|
void LibvpxVp9Encoder::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
|
2016-01-26 01:05:20 -08:00
|
|
|
RTC_DCHECK_EQ(pkt->kind, VPX_CODEC_CX_FRAME_PKT);
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2018-04-04 11:45:41 +02:00
|
|
|
if (pkt->data.frame.sz == 0) {
|
|
|
|
|
// Ignore dropped frame.
|
2021-02-03 12:33:17 +01:00
|
|
|
return;
|
2018-04-04 11:45:41 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-09 13:11:59 +02:00
|
|
|
vpx_svc_layer_id_t layer_id = {0};
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
|
2018-04-09 13:11:59 +02:00
|
|
|
|
2019-06-18 15:56:56 +02:00
|
|
|
encoded_image_.SetEncodedData(EncodedImageBuffer::Create(
|
|
|
|
|
static_cast<const uint8_t*>(pkt->data.frame.buf), pkt->data.frame.sz));
|
2016-01-21 01:11:35 -08:00
|
|
|
|
2022-01-18 19:20:40 +01:00
|
|
|
codec_specific_ = {};
|
|
|
|
|
absl::optional<int> spatial_index;
|
2022-04-25 17:28:00 +02:00
|
|
|
absl::optional<int> temporal_index;
|
|
|
|
|
if (!PopulateCodecSpecific(&codec_specific_, &spatial_index, &temporal_index,
|
|
|
|
|
*pkt)) {
|
2022-01-18 19:20:40 +01:00
|
|
|
// Drop the frame.
|
|
|
|
|
encoded_image_.set_size(0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
encoded_image_.SetSpatialIndex(spatial_index);
|
2022-04-25 17:28:00 +02:00
|
|
|
encoded_image_.SetTemporalIndex(temporal_index);
|
2022-01-18 19:20:40 +01:00
|
|
|
|
2018-05-03 14:14:09 +02:00
|
|
|
const bool is_key_frame =
|
2022-01-18 19:20:40 +01:00
|
|
|
((pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false) &&
|
|
|
|
|
!codec_specific_.codecSpecific.VP9.inter_layer_predicted;
|
|
|
|
|
|
2018-05-03 14:14:09 +02:00
|
|
|
// Ensure encoder issued key frame on request.
|
|
|
|
|
RTC_DCHECK(is_key_frame || !force_key_frame_);
|
|
|
|
|
|
2015-07-31 06:10:09 -07:00
|
|
|
// Check if encoded frame is a key frame.
|
2019-03-21 15:43:58 +01:00
|
|
|
encoded_image_._frameType = VideoFrameType::kVideoFrameDelta;
|
2018-05-03 14:14:09 +02:00
|
|
|
if (is_key_frame) {
|
2019-03-21 15:43:58 +01:00
|
|
|
encoded_image_._frameType = VideoFrameType::kVideoFrameKey;
|
2018-05-03 14:14:09 +02:00
|
|
|
force_key_frame_ = false;
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
2016-01-26 01:05:20 -08:00
|
|
|
|
2019-01-18 11:56:48 +01:00
|
|
|
UpdateReferenceBuffers(*pkt, pics_since_key_);
|
2018-05-28 12:26:36 +02:00
|
|
|
|
2019-01-15 08:50:01 +01:00
|
|
|
TRACE_COUNTER1("webrtc", "EncodedFrameSize", encoded_image_.size());
|
2023-09-18 15:48:49 +02:00
|
|
|
encoded_image_.SetRtpTimestamp(input_image_->timestamp());
|
2023-02-22 14:46:23 +01:00
|
|
|
encoded_image_.SetCaptureTimeIdentifier(
|
|
|
|
|
input_image_->capture_time_identifier());
|
2022-07-20 15:30:10 +08:00
|
|
|
encoded_image_.SetColorSpace(input_image_->color_space());
|
2018-04-04 11:45:41 +02:00
|
|
|
encoded_image_._encodedHeight =
|
|
|
|
|
pkt->data.frame.height[layer_id.spatial_layer_id];
|
|
|
|
|
encoded_image_._encodedWidth =
|
|
|
|
|
pkt->data.frame.width[layer_id.spatial_layer_id];
|
|
|
|
|
int qp = -1;
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->codec_control(encoder_, VP8E_GET_LAST_QUANTIZER, &qp);
|
2018-04-04 11:45:41 +02:00
|
|
|
encoded_image_.qp_ = qp;
|
2015-07-31 06:10:09 -07:00
|
|
|
|
2023-05-05 16:18:10 +02:00
|
|
|
const bool end_of_picture = encoded_image_.SpatialIndex().value_or(0) + 1 ==
|
|
|
|
|
num_active_spatial_layers_;
|
|
|
|
|
DeliverBufferedFrame(end_of_picture);
|
2018-04-04 11:45:41 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::DeliverBufferedFrame(bool end_of_picture) {
|
2019-01-15 08:50:01 +01:00
|
|
|
if (encoded_image_.size() > 0) {
|
2019-05-24 16:50:00 +02:00
|
|
|
if (num_spatial_layers_ > 1) {
|
|
|
|
|
// Restore frame dropping settings, as dropping may be temporary forbidden
|
|
|
|
|
// due to dynamically enabled layers.
|
2019-09-09 10:16:18 +02:00
|
|
|
for (size_t i = 0; i < num_spatial_layers_; ++i) {
|
|
|
|
|
svc_drop_frame_.framedrop_thresh[i] = config_->rc_dropframe_thresh;
|
2019-05-24 16:50:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-11 12:42:56 +01:00
|
|
|
codec_specific_.end_of_picture = end_of_picture;
|
2018-04-04 11:45:41 +02:00
|
|
|
|
2020-08-12 17:30:36 +02:00
|
|
|
encoded_complete_callback_->OnEncodedImage(encoded_image_,
|
|
|
|
|
&codec_specific_);
|
2018-05-18 17:31:19 +02:00
|
|
|
|
2018-09-05 21:07:17 +02:00
|
|
|
if (codec_.mode == VideoCodecMode::kScreensharing) {
|
|
|
|
|
const uint8_t spatial_idx = encoded_image_.SpatialIndex().value_or(0);
|
|
|
|
|
const uint32_t frame_timestamp_ms =
|
2023-09-18 15:48:49 +02:00
|
|
|
1000 * encoded_image_.RtpTimestamp() / kVideoPayloadTypeFrequency;
|
2018-09-05 21:07:17 +02:00
|
|
|
framerate_controller_[spatial_idx].AddFrame(frame_timestamp_ms);
|
2019-03-06 16:04:32 +01:00
|
|
|
|
|
|
|
|
const size_t steady_state_size = SteadyStateSize(
|
|
|
|
|
spatial_idx, codec_specific_.codecSpecific.VP9.temporal_idx);
|
|
|
|
|
|
|
|
|
|
// Only frames on spatial layers, which may be limited in a steady state
|
|
|
|
|
// are considered for steady state detection.
|
|
|
|
|
if (framerate_controller_[spatial_idx].GetTargetRate() >
|
|
|
|
|
variable_framerate_experiment_.framerate_limit + 1e-9) {
|
|
|
|
|
if (encoded_image_.qp_ <=
|
|
|
|
|
variable_framerate_experiment_.steady_state_qp &&
|
|
|
|
|
encoded_image_.size() <= steady_state_size) {
|
|
|
|
|
++num_steady_state_frames_;
|
|
|
|
|
} else {
|
|
|
|
|
num_steady_state_frames_ = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-18 17:31:19 +02:00
|
|
|
}
|
2019-03-06 16:04:32 +01:00
|
|
|
encoded_image_.set_size(0);
|
2014-11-01 06:10:48 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
int LibvpxVp9Encoder::RegisterEncodeCompleteCallback(
|
2014-11-01 06:10:48 +00:00
|
|
|
EncodedImageCallback* callback) {
|
|
|
|
|
encoded_complete_callback_ = callback;
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
VideoEncoder::EncoderInfo LibvpxVp9Encoder::GetEncoderInfo() const {
|
2018-11-07 16:54:15 +01:00
|
|
|
EncoderInfo info;
|
|
|
|
|
info.supports_native_handle = false;
|
|
|
|
|
info.implementation_name = "libvpx";
|
2020-10-09 16:09:11 +02:00
|
|
|
if (quality_scaler_experiment_.enabled && inited_ &&
|
|
|
|
|
codec_.VP9().automaticResizeOn) {
|
2020-06-18 19:16:53 +02:00
|
|
|
info.scaling_settings = VideoEncoder::ScalingSettings(
|
|
|
|
|
quality_scaler_experiment_.low_qp, quality_scaler_experiment_.high_qp);
|
|
|
|
|
} else {
|
|
|
|
|
info.scaling_settings = VideoEncoder::ScalingSettings::kOff;
|
|
|
|
|
}
|
2018-11-08 16:56:43 +01:00
|
|
|
info.has_trusted_rate_controller = trusted_rate_controller_;
|
2018-11-30 13:12:21 +01:00
|
|
|
info.is_hardware_accelerated = false;
|
2020-03-24 16:53:59 +01:00
|
|
|
if (inited_) {
|
|
|
|
|
// Find the max configured fps of any active spatial layer.
|
|
|
|
|
float max_fps = 0.0;
|
|
|
|
|
for (size_t si = 0; si < num_spatial_layers_; ++si) {
|
|
|
|
|
if (codec_.spatialLayers[si].active &&
|
|
|
|
|
codec_.spatialLayers[si].maxFramerate > max_fps) {
|
|
|
|
|
max_fps = codec_.spatialLayers[si].maxFramerate;
|
|
|
|
|
}
|
2019-01-17 15:27:50 +01:00
|
|
|
}
|
2020-03-24 16:53:59 +01:00
|
|
|
|
|
|
|
|
for (size_t si = 0; si < num_spatial_layers_; ++si) {
|
|
|
|
|
info.fps_allocation[si].clear();
|
|
|
|
|
if (!codec_.spatialLayers[si].active) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This spatial layer may already use a fraction of the total frame rate.
|
|
|
|
|
const float sl_fps_fraction =
|
|
|
|
|
codec_.spatialLayers[si].maxFramerate / max_fps;
|
|
|
|
|
for (size_t ti = 0; ti < num_temporal_layers_; ++ti) {
|
|
|
|
|
const uint32_t decimator =
|
|
|
|
|
num_temporal_layers_ <= 1 ? 1 : config_->ts_rate_decimator[ti];
|
|
|
|
|
RTC_DCHECK_GT(decimator, 0);
|
|
|
|
|
info.fps_allocation[si].push_back(
|
|
|
|
|
rtc::saturated_cast<uint8_t>(EncoderInfo::kMaxFramerateFraction *
|
|
|
|
|
(sl_fps_fraction / decimator)));
|
|
|
|
|
}
|
2019-01-17 15:27:50 +01:00
|
|
|
}
|
2020-10-08 14:56:45 +02:00
|
|
|
if (profile_ == VP9Profile::kProfile0) {
|
|
|
|
|
info.preferred_pixel_formats = {VideoFrameBuffer::Type::kI420,
|
|
|
|
|
VideoFrameBuffer::Type::kNV12};
|
|
|
|
|
}
|
2019-01-17 15:27:50 +01:00
|
|
|
}
|
2021-02-01 09:20:05 +01:00
|
|
|
if (!encoder_info_override_.resolution_bitrate_limits().empty()) {
|
|
|
|
|
info.resolution_bitrate_limits =
|
|
|
|
|
encoder_info_override_.resolution_bitrate_limits();
|
|
|
|
|
}
|
2018-11-07 16:54:15 +01:00
|
|
|
return info;
|
2015-12-18 16:01:11 +01:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
size_t LibvpxVp9Encoder::SteadyStateSize(int sid, int tid) {
|
2019-03-06 16:04:32 +01:00
|
|
|
const size_t bitrate_bps = current_bitrate_allocation_.GetBitrate(
|
|
|
|
|
sid, tid == kNoTemporalIdx ? 0 : tid);
|
|
|
|
|
const float fps = (codec_.mode == VideoCodecMode::kScreensharing)
|
2019-05-24 11:51:31 +02:00
|
|
|
? std::min(static_cast<float>(codec_.maxFramerate),
|
|
|
|
|
framerate_controller_[sid].GetTargetRate())
|
2019-03-06 16:04:32 +01:00
|
|
|
: codec_.maxFramerate;
|
|
|
|
|
return static_cast<size_t>(
|
|
|
|
|
bitrate_bps / (8 * fps) *
|
|
|
|
|
(100 -
|
|
|
|
|
variable_framerate_experiment_.steady_state_undershoot_percentage) /
|
|
|
|
|
100 +
|
|
|
|
|
0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// static
|
2020-12-09 20:58:21 +01:00
|
|
|
LibvpxVp9Encoder::VariableFramerateExperiment
|
2022-03-29 11:04:48 +02:00
|
|
|
LibvpxVp9Encoder::ParseVariableFramerateConfig(const FieldTrialsView& trials) {
|
2019-03-06 16:04:32 +01:00
|
|
|
FieldTrialFlag enabled = FieldTrialFlag("Enabled");
|
|
|
|
|
FieldTrialParameter<double> framerate_limit("min_fps", 5.0);
|
|
|
|
|
FieldTrialParameter<int> qp("min_qp", 32);
|
|
|
|
|
FieldTrialParameter<int> undershoot_percentage("undershoot", 30);
|
|
|
|
|
FieldTrialParameter<int> frames_before_steady_state(
|
|
|
|
|
"frames_before_steady_state", 5);
|
|
|
|
|
ParseFieldTrial({&enabled, &framerate_limit, &qp, &undershoot_percentage,
|
|
|
|
|
&frames_before_steady_state},
|
2020-10-01 19:13:13 +02:00
|
|
|
trials.Lookup("WebRTC-VP9VariableFramerateScreenshare"));
|
2019-03-06 16:04:32 +01:00
|
|
|
VariableFramerateExperiment config;
|
|
|
|
|
config.enabled = enabled.Get();
|
|
|
|
|
config.framerate_limit = framerate_limit.Get();
|
|
|
|
|
config.steady_state_qp = qp.Get();
|
|
|
|
|
config.steady_state_undershoot_percentage = undershoot_percentage.Get();
|
|
|
|
|
config.frames_before_steady_state = frames_before_steady_state.Get();
|
|
|
|
|
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-18 19:16:53 +02:00
|
|
|
// static
|
2020-12-09 20:58:21 +01:00
|
|
|
LibvpxVp9Encoder::QualityScalerExperiment
|
2022-03-29 11:04:48 +02:00
|
|
|
LibvpxVp9Encoder::ParseQualityScalerConfig(const FieldTrialsView& trials) {
|
2020-06-18 19:16:53 +02:00
|
|
|
FieldTrialFlag disabled = FieldTrialFlag("Disabled");
|
|
|
|
|
FieldTrialParameter<int> low_qp("low_qp", kLowVp9QpThreshold);
|
|
|
|
|
FieldTrialParameter<int> high_qp("hihg_qp", kHighVp9QpThreshold);
|
|
|
|
|
ParseFieldTrial({&disabled, &low_qp, &high_qp},
|
2020-10-01 19:13:13 +02:00
|
|
|
trials.Lookup("WebRTC-VP9QualityScaler"));
|
2020-06-18 19:16:53 +02:00
|
|
|
QualityScalerExperiment config;
|
|
|
|
|
config.enabled = !disabled.Get();
|
|
|
|
|
RTC_LOG(LS_INFO) << "Webrtc quality scaler for vp9 is "
|
|
|
|
|
<< (config.enabled ? "enabled." : "disabled");
|
|
|
|
|
config.low_qp = low_qp.Get();
|
|
|
|
|
config.high_qp = high_qp.Get();
|
|
|
|
|
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::UpdatePerformanceFlags() {
|
2022-04-06 16:44:30 +02:00
|
|
|
flat_map<int, PerformanceFlags::ParameterSet> params_by_resolution;
|
|
|
|
|
if (codec_.GetVideoEncoderComplexity() ==
|
|
|
|
|
VideoCodecComplexity::kComplexityLow) {
|
|
|
|
|
// For low tier devices, always use speed 9. Only disable upper
|
|
|
|
|
// layer deblocking below QCIF.
|
|
|
|
|
params_by_resolution[0] = {.base_layer_speed = 9,
|
|
|
|
|
.high_layer_speed = 9,
|
|
|
|
|
.deblock_mode = 1,
|
|
|
|
|
.allow_denoising = true};
|
|
|
|
|
params_by_resolution[352 * 288] = {.base_layer_speed = 9,
|
|
|
|
|
.high_layer_speed = 9,
|
|
|
|
|
.deblock_mode = 0,
|
|
|
|
|
.allow_denoising = true};
|
|
|
|
|
} else {
|
|
|
|
|
params_by_resolution = performance_flags_.settings_by_resolution;
|
|
|
|
|
}
|
|
|
|
|
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
const auto find_speed = [&](int min_pixel_count) {
|
2022-04-06 16:44:30 +02:00
|
|
|
RTC_DCHECK(!params_by_resolution.empty());
|
|
|
|
|
auto it = params_by_resolution.upper_bound(min_pixel_count);
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
return std::prev(it)->second;
|
|
|
|
|
};
|
|
|
|
|
performance_flags_by_spatial_index_.clear();
|
2022-04-06 16:44:30 +02:00
|
|
|
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
if (is_svc_) {
|
|
|
|
|
for (int si = 0; si < num_spatial_layers_; ++si) {
|
|
|
|
|
performance_flags_by_spatial_index_.push_back(find_speed(
|
|
|
|
|
codec_.spatialLayers[si].width * codec_.spatialLayers[si].height));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
performance_flags_by_spatial_index_.push_back(
|
|
|
|
|
find_speed(codec_.width * codec_.height));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-01 19:13:13 +02:00
|
|
|
// static
|
2020-12-09 20:58:21 +01:00
|
|
|
LibvpxVp9Encoder::PerformanceFlags
|
|
|
|
|
LibvpxVp9Encoder::ParsePerformanceFlagsFromTrials(
|
2022-03-29 11:04:48 +02:00
|
|
|
const FieldTrialsView& trials) {
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
struct Params : public PerformanceFlags::ParameterSet {
|
|
|
|
|
int min_pixel_count = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
FieldTrialStructList<Params> trials_list(
|
|
|
|
|
{FieldTrialStructMember("min_pixel_count",
|
|
|
|
|
[](Params* p) { return &p->min_pixel_count; }),
|
|
|
|
|
FieldTrialStructMember("high_layer_speed",
|
|
|
|
|
[](Params* p) { return &p->high_layer_speed; }),
|
|
|
|
|
FieldTrialStructMember("base_layer_speed",
|
|
|
|
|
[](Params* p) { return &p->base_layer_speed; }),
|
|
|
|
|
FieldTrialStructMember("deblock_mode",
|
2022-03-30 14:06:13 +02:00
|
|
|
[](Params* p) { return &p->deblock_mode; }),
|
|
|
|
|
FieldTrialStructMember("denoiser",
|
2022-03-31 16:11:15 +02:00
|
|
|
[](Params* p) { return &p->allow_denoising; })},
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
{});
|
|
|
|
|
|
|
|
|
|
FieldTrialFlag per_layer_speed("use_per_layer_speed");
|
|
|
|
|
|
|
|
|
|
ParseFieldTrial({&trials_list, &per_layer_speed},
|
|
|
|
|
trials.Lookup("WebRTC-VP9-PerformanceFlags"));
|
|
|
|
|
|
|
|
|
|
PerformanceFlags flags;
|
|
|
|
|
flags.use_per_layer_speed = per_layer_speed.Get();
|
|
|
|
|
|
|
|
|
|
constexpr int kMinSpeed = 1;
|
|
|
|
|
constexpr int kMaxSpeed = 9;
|
|
|
|
|
for (auto& f : trials_list.Get()) {
|
|
|
|
|
if (f.base_layer_speed < kMinSpeed || f.base_layer_speed > kMaxSpeed ||
|
|
|
|
|
f.high_layer_speed < kMinSpeed || f.high_layer_speed > kMaxSpeed ||
|
|
|
|
|
f.deblock_mode < 0 || f.deblock_mode > 2) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Ignoring invalid performance flags: "
|
|
|
|
|
<< "min_pixel_count = " << f.min_pixel_count
|
|
|
|
|
<< ", high_layer_speed = " << f.high_layer_speed
|
|
|
|
|
<< ", base_layer_speed = " << f.base_layer_speed
|
|
|
|
|
<< ", deblock_mode = " << f.deblock_mode;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
flags.settings_by_resolution[f.min_pixel_count] = f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags.settings_by_resolution.empty()) {
|
|
|
|
|
return GetDefaultPerformanceFlags();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// static
|
2020-12-09 20:58:21 +01:00
|
|
|
LibvpxVp9Encoder::PerformanceFlags
|
|
|
|
|
LibvpxVp9Encoder::GetDefaultPerformanceFlags() {
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
PerformanceFlags flags;
|
2021-08-06 09:02:29 -05:00
|
|
|
flags.use_per_layer_speed = true;
|
2023-10-06 13:18:41 +02:00
|
|
|
#ifdef MOBILE_ARM
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
// Speed 8 on all layers for all resolutions.
|
2022-04-06 16:44:30 +02:00
|
|
|
flags.settings_by_resolution[0] = {.base_layer_speed = 8,
|
|
|
|
|
.high_layer_speed = 8,
|
|
|
|
|
.deblock_mode = 0,
|
|
|
|
|
.allow_denoising = true};
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
#else
|
2022-04-06 16:44:30 +02:00
|
|
|
|
2021-08-06 09:02:29 -05:00
|
|
|
// For smaller resolutions, use lower speed setting for the temporal base
|
|
|
|
|
// layer (get some coding gain at the cost of increased encoding complexity).
|
|
|
|
|
// Set encoder Speed 5 for TL0, encoder Speed 8 for upper temporal layers, and
|
|
|
|
|
// disable deblocking for upper-most temporal layers.
|
2022-04-06 16:44:30 +02:00
|
|
|
flags.settings_by_resolution[0] = {.base_layer_speed = 5,
|
|
|
|
|
.high_layer_speed = 8,
|
|
|
|
|
.deblock_mode = 1,
|
|
|
|
|
.allow_denoising = true};
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
|
|
|
|
|
// Use speed 7 for QCIF and above.
|
2021-08-06 09:02:29 -05:00
|
|
|
// Set encoder Speed 7 for TL0, encoder Speed 8 for upper temporal layers, and
|
|
|
|
|
// enable deblocking for all temporal layers.
|
2022-04-06 16:44:30 +02:00
|
|
|
flags.settings_by_resolution[352 * 288] = {.base_layer_speed = 7,
|
|
|
|
|
.high_layer_speed = 8,
|
|
|
|
|
.deblock_mode = 0,
|
|
|
|
|
.allow_denoising = true};
|
2022-03-30 14:06:13 +02:00
|
|
|
|
|
|
|
|
// For very high resolution (1080p and up), turn the speed all the way up
|
|
|
|
|
// since this is very CPU intensive. Also disable denoising to save CPU, at
|
|
|
|
|
// these resolutions denoising appear less effective and hopefully you also
|
|
|
|
|
// have a less noisy video source at this point.
|
2022-04-06 16:44:30 +02:00
|
|
|
flags.settings_by_resolution[1920 * 1080] = {.base_layer_speed = 9,
|
|
|
|
|
.high_layer_speed = 9,
|
|
|
|
|
.deblock_mode = 0,
|
|
|
|
|
.allow_denoising = false};
|
|
|
|
|
|
Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e7167456b5eba36c7985d6a74f1d191958d4e0f
Patch set 1 is the original.
Later patch sets fix a parsing bug, and adds a new flag which enables
or disabled the ability to set separate per spatial layer speed
(use_per_layer_speed).
Original change's description:
> Adds experimental libvpx VP9 speed settings.
>
> Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to
> configure the libvpx VP9 encoder with a list of flags to affect the
> quality vs speed tradeoff. This CL adds support for:
>
> * Speed (effort), for the temporal base layer frames
> * Speed for higher (non-base) layer frames
> * De-blocking (as part of the loopfilter) enabled for:
> 0 = all frames
> 1 = all but frames from the highest temporal layer
> 2 = no frames
>
> Each entry in the list has a threshold in min number of pixels needed
> for settings in the entry to apply.
>
> Example: Two spatial layers (180p, 360p) with three temporal
> layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to:
> "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|8,deblock_mode:1|2"
> This translates to:
> S0:
> - TL0: Speed 5, deblocked
> - TL1: Speed 8, deblocked
> - TL2: Speed 8, not deblocked
> S1:
> - TL0: Speed 7, not deblocked
> - TL1: Speed 8, not deblocked
> - TL2: Speed 8, not deblocked
>
> Bug: webrtc:11551
> Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461
> Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32749}
Bug: webrtc:11551
Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345
Reviewed-by: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32780}
2020-12-04 14:04:10 +01:00
|
|
|
#endif
|
|
|
|
|
return flags;
|
2020-10-01 19:13:13 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-09 20:58:21 +01:00
|
|
|
void LibvpxVp9Encoder::MaybeRewrapRawWithFormat(const vpx_img_fmt fmt) {
|
2020-09-28 12:04:11 +02:00
|
|
|
if (!raw_) {
|
2020-12-13 14:50:59 +01:00
|
|
|
raw_ = libvpx_->img_wrap(nullptr, fmt, codec_.width, codec_.height, 1,
|
|
|
|
|
nullptr);
|
2020-09-28 12:04:11 +02:00
|
|
|
} else if (raw_->fmt != fmt) {
|
2021-11-04 12:01:23 +00:00
|
|
|
RTC_LOG(LS_INFO) << "Switching VP9 encoder pixel format to "
|
|
|
|
|
<< (fmt == VPX_IMG_FMT_NV12 ? "NV12" : "I420");
|
2020-12-13 14:50:59 +01:00
|
|
|
libvpx_->img_free(raw_);
|
|
|
|
|
raw_ = libvpx_->img_wrap(nullptr, fmt, codec_.width, codec_.height, 1,
|
|
|
|
|
nullptr);
|
2020-09-28 12:04:11 +02:00
|
|
|
}
|
|
|
|
|
// else no-op since the image is already in the right format.
|
|
|
|
|
}
|
|
|
|
|
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
rtc::scoped_refptr<VideoFrameBuffer> LibvpxVp9Encoder::PrepareBufferForProfile0(
|
|
|
|
|
rtc::scoped_refptr<VideoFrameBuffer> buffer) {
|
|
|
|
|
absl::InlinedVector<VideoFrameBuffer::Type, kMaxPreferredPixelFormats>
|
|
|
|
|
supported_formats = {VideoFrameBuffer::Type::kI420,
|
|
|
|
|
VideoFrameBuffer::Type::kNV12};
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<VideoFrameBuffer> mapped_buffer;
|
|
|
|
|
if (buffer->type() != VideoFrameBuffer::Type::kNative) {
|
2021-08-09 13:02:57 +02:00
|
|
|
// `buffer` is already mapped.
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
mapped_buffer = buffer;
|
|
|
|
|
} else {
|
|
|
|
|
// Attempt to map to one of the supported formats.
|
|
|
|
|
mapped_buffer = buffer->GetMappedFrameBuffer(supported_formats);
|
|
|
|
|
}
|
|
|
|
|
if (!mapped_buffer ||
|
|
|
|
|
(absl::c_find(supported_formats, mapped_buffer->type()) ==
|
|
|
|
|
supported_formats.end() &&
|
|
|
|
|
mapped_buffer->type() != VideoFrameBuffer::Type::kI420A)) {
|
|
|
|
|
// Unknown pixel format or unable to map, convert to I420 and prepare that
|
|
|
|
|
// buffer instead to ensure Scale() is safe to use.
|
2021-03-23 09:18:28 +01:00
|
|
|
auto converted_buffer = buffer->ToI420();
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
if (!converted_buffer) {
|
|
|
|
|
RTC_LOG(LS_ERROR) << "Failed to convert "
|
|
|
|
|
<< VideoFrameBufferTypeToString(buffer->type())
|
|
|
|
|
<< " image to I420. Can't encode frame.";
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2021-07-27 21:27:46 +09:00
|
|
|
RTC_CHECK(converted_buffer->type() == VideoFrameBuffer::Type::kI420 ||
|
|
|
|
|
converted_buffer->type() == VideoFrameBuffer::Type::kI420A);
|
|
|
|
|
|
2021-08-09 13:02:57 +02:00
|
|
|
// Because `buffer` had to be converted, use `converted_buffer` instead.
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
buffer = mapped_buffer = converted_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-09 13:02:57 +02:00
|
|
|
// Prepare `raw_` from `mapped_buffer`.
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
switch (mapped_buffer->type()) {
|
|
|
|
|
case VideoFrameBuffer::Type::kI420:
|
|
|
|
|
case VideoFrameBuffer::Type::kI420A: {
|
|
|
|
|
MaybeRewrapRawWithFormat(VPX_IMG_FMT_I420);
|
|
|
|
|
const I420BufferInterface* i420_buffer = mapped_buffer->GetI420();
|
|
|
|
|
RTC_DCHECK(i420_buffer);
|
|
|
|
|
raw_->planes[VPX_PLANE_Y] = const_cast<uint8_t*>(i420_buffer->DataY());
|
|
|
|
|
raw_->planes[VPX_PLANE_U] = const_cast<uint8_t*>(i420_buffer->DataU());
|
|
|
|
|
raw_->planes[VPX_PLANE_V] = const_cast<uint8_t*>(i420_buffer->DataV());
|
|
|
|
|
raw_->stride[VPX_PLANE_Y] = i420_buffer->StrideY();
|
|
|
|
|
raw_->stride[VPX_PLANE_U] = i420_buffer->StrideU();
|
|
|
|
|
raw_->stride[VPX_PLANE_V] = i420_buffer->StrideV();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case VideoFrameBuffer::Type::kNV12: {
|
|
|
|
|
MaybeRewrapRawWithFormat(VPX_IMG_FMT_NV12);
|
|
|
|
|
const NV12BufferInterface* nv12_buffer = mapped_buffer->GetNV12();
|
|
|
|
|
RTC_DCHECK(nv12_buffer);
|
|
|
|
|
raw_->planes[VPX_PLANE_Y] = const_cast<uint8_t*>(nv12_buffer->DataY());
|
|
|
|
|
raw_->planes[VPX_PLANE_U] = const_cast<uint8_t*>(nv12_buffer->DataUV());
|
|
|
|
|
raw_->planes[VPX_PLANE_V] = raw_->planes[VPX_PLANE_U] + 1;
|
|
|
|
|
raw_->stride[VPX_PLANE_Y] = nv12_buffer->StrideY();
|
|
|
|
|
raw_->stride[VPX_PLANE_U] = nv12_buffer->StrideUV();
|
|
|
|
|
raw_->stride[VPX_PLANE_V] = nv12_buffer->StrideUV();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
2021-11-15 16:57:07 +01:00
|
|
|
RTC_DCHECK_NOTREACHED();
|
Support native scaling of VideoFrameBuffers in LibvpxVp9Encoder.
This CL is part of Optimized Scaling efforts. In Chromium, the native
frame buffer is getting an optimized CropAndScale() implementation. To
support HW accelerated scaling, returning pre-scaled images and skipping
unnecessary intermediate downscales, WebRTC needs to 1) use CropAndScale
instead of libyuv::XXXXScale and 2) only map buffers it actually intends
to encode.
- To achieve this, WebRTC encoders are updated to map kNative video
buffers so that in a follow-up CL VideoStreamEncoder can stop mapping
intermediate buffer sizes.
In this CL LibvpxVp9Encoder is updated to map kNative buffers of pixel
formats it supports and convert ToI420() if the kNative buffer is
something else. A fake native buffer that keeps track of which
resolutions were mapped, MappableNativeBuffer, is added.
Because VP9 is currently an SVC encoder and not a simulcast encoder, it
does not need to invoke CropAndScale.
This CL also fixes MultiplexEncoderAdapter, but because it simply
forwards frames it only cares about the pixel format when
|supports_augmented_data_| is true so this is the only time we map it.
Because this encoder is not used with kNative in practise, we don't care
to make this path optimal.
Bug: webrtc:12469, chromium:1157072
Change-Id: I74edf85b18eccd0d250776bbade7a6444478efce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212580
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#33526}
2021-03-22 12:24:30 +01:00
|
|
|
}
|
|
|
|
|
return mapped_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-01 06:10:48 +00:00
|
|
|
} // namespace webrtc
|
2018-11-19 09:52:37 +01:00
|
|
|
|
|
|
|
|
#endif // RTC_ENABLE_VP9
|