Revert "Move FakeCodec to separate target and behave like real encoder."
This reverts commit 223eba5f72b5228847eeebaaef1c4305a29e8b3d. Reason for revert: Breaks perf tests and downstream projects. Original change's description: > Move FakeCodec to separate target and behave like real encoder. > > Add FakeVp8Encoder, change FakeEncoder to use BitrateAllocator for simulcast. > Change call_test to use VP8 payload name for simulcast tests. > > Bug: none > Change-Id: I5a34c52e66bbd6c05859729ed14ae87ac26b5969 > Reviewed-on: https://webrtc-review.googlesource.com/91861 > Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org> > Reviewed-by: Sebastian Jansson <srte@webrtc.org> > Reviewed-by: Erik Språng <sprang@webrtc.org> > Reviewed-by: Per Kjellander <perkj@webrtc.org> > Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#24359} TBR=mbonadei@webrtc.org,ilnik@webrtc.org,sprang@webrtc.org,srte@webrtc.org,perkj@webrtc.org Change-Id: I602acecb3f340cc8d737ca074bf52496593419c8 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: none Reviewed-on: https://webrtc-review.googlesource.com/95181 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24365}
This commit is contained in:

committed by
Commit Bot

parent
ac50c6a204
commit
7d13a6e5b9
@ -347,13 +347,11 @@ if (rtc_include_tests) {
|
||||
"../system_wrappers",
|
||||
"../test:audio_codec_mocks",
|
||||
"../test:direct_transport",
|
||||
"../test:fake_video_codecs",
|
||||
"../test:field_trial",
|
||||
"../test:test_common",
|
||||
"../test:test_support",
|
||||
"../test:video_test_common",
|
||||
"../video:video",
|
||||
"//testing/gmock",
|
||||
"//testing/gtest",
|
||||
"//third_party/abseil-cpp/absl/memory",
|
||||
]
|
||||
@ -392,7 +390,6 @@ if (rtc_include_tests) {
|
||||
"../system_wrappers:metrics_default",
|
||||
"../system_wrappers:runtime_enabled_features_default",
|
||||
"../test:direct_transport",
|
||||
"../test:fake_video_codecs",
|
||||
"../test:field_trial",
|
||||
"../test:fileutils",
|
||||
"../test:perf_test",
|
||||
|
@ -357,9 +357,6 @@ void RtpVideoSender::OnBitrateAllocationUpdated(
|
||||
// inactive.
|
||||
if (layer_bitrates[i]) {
|
||||
rtp_modules_[i]->SetVideoBitrateAllocation(*layer_bitrates[i]);
|
||||
} else {
|
||||
// Signal a 0 bitrate on a simulcast stream.
|
||||
rtp_modules_[i]->SetVideoBitrateAllocation(VideoBitrateAllocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
DefaultVideoBitrateAllocator::DefaultVideoBitrateAllocator(
|
||||
@ -29,23 +27,14 @@ VideoBitrateAllocation DefaultVideoBitrateAllocator::GetAllocation(
|
||||
if (total_bitrate_bps == 0 || !codec_.active)
|
||||
return allocation;
|
||||
|
||||
uint32_t allocated_bitrate_bps = total_bitrate_bps;
|
||||
allocated_bitrate_bps =
|
||||
std::max(allocated_bitrate_bps, codec_.minBitrate * 1000);
|
||||
if (codec_.maxBitrate > 0) {
|
||||
allocated_bitrate_bps =
|
||||
std::min(allocated_bitrate_bps, codec_.maxBitrate * 1000);
|
||||
if (total_bitrate_bps < codec_.minBitrate * 1000) {
|
||||
allocation.SetBitrate(0, 0, codec_.minBitrate * 1000);
|
||||
} else if (codec_.maxBitrate > 0 &&
|
||||
total_bitrate_bps > codec_.maxBitrate * 1000) {
|
||||
allocation.SetBitrate(0, 0, codec_.maxBitrate * 1000);
|
||||
} else {
|
||||
allocation.SetBitrate(0, 0, total_bitrate_bps);
|
||||
}
|
||||
size_t num_simulcast_streams =
|
||||
std::max<size_t>(1, codec_.numberOfSimulcastStreams);
|
||||
// The bitrate is split between all the streams in proportion of powers of 2
|
||||
// e.g. 1:2, 1:2:4, etc.
|
||||
for (size_t i = 0; i < num_simulcast_streams; i++) {
|
||||
allocation.SetBitrate(
|
||||
i, 0,
|
||||
allocated_bitrate_bps * (1 << i) / ((1 << num_simulcast_streams) - 1));
|
||||
}
|
||||
|
||||
return allocation;
|
||||
}
|
||||
|
||||
|
@ -299,32 +299,23 @@ if (rtc_include_tests) {
|
||||
rtc_test("test_support_unittests") {
|
||||
deps = [
|
||||
":direct_transport",
|
||||
":fake_video_codecs",
|
||||
":fileutils",
|
||||
":fileutils_unittests",
|
||||
":perf_test",
|
||||
":rtp_test_utils",
|
||||
":test_common",
|
||||
":test_main",
|
||||
":test_support",
|
||||
":test_support_test_artifacts",
|
||||
":video_test_common",
|
||||
":video_test_support",
|
||||
"../api:create_simulcast_test_fixture_api",
|
||||
"../api:simulcast_test_fixture_api",
|
||||
"../api/video:video_frame_i420",
|
||||
"../modules/rtp_rtcp:rtp_rtcp",
|
||||
"../modules/video_capture",
|
||||
"../modules/video_coding:simulcast_test_fixture_impl",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../test:single_threaded_task_queue",
|
||||
"//testing/gmock",
|
||||
"//testing/gtest",
|
||||
"//third_party/abseil-cpp/absl/memory",
|
||||
]
|
||||
sources = [
|
||||
"direct_transport_unittest.cc",
|
||||
"fake_vp8_encoder_unittest.cc",
|
||||
"frame_generator_unittest.cc",
|
||||
"rtp_file_reader_unittest.cc",
|
||||
"rtp_file_writer_unittest.cc",
|
||||
@ -351,7 +342,6 @@ if (rtc_include_tests) {
|
||||
if (is_ios) {
|
||||
deps += [ ":test_support_unittests_bundle_data" ]
|
||||
}
|
||||
|
||||
if (!is_android && !build_with_chromium) {
|
||||
# This is needed in order to avoid:
|
||||
# undefined symbol: webrtc::videocapturemodule::VideoCaptureImpl::Create
|
||||
@ -498,46 +488,13 @@ rtc_source_set("single_threaded_task_queue") {
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("fake_video_codecs") {
|
||||
testonly = true
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"configurable_frame_size_encoder.cc",
|
||||
"configurable_frame_size_encoder.h",
|
||||
"fake_decoder.cc",
|
||||
"fake_decoder.h",
|
||||
"fake_encoder.cc",
|
||||
"fake_encoder.h",
|
||||
"fake_vp8_encoder.cc",
|
||||
"fake_vp8_encoder.h",
|
||||
]
|
||||
if (!build_with_chromium && is_clang) {
|
||||
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
||||
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
deps = [
|
||||
"..:webrtc_common",
|
||||
"../api/video:video_frame_i420",
|
||||
"../api/video_codecs:video_codecs_api",
|
||||
"../common_video:common_video",
|
||||
"../modules/video_coding:video_codec_interface",
|
||||
"../modules/video_coding:video_coding_utility",
|
||||
"../modules/video_coding:webrtc_h264",
|
||||
"../modules/video_coding:webrtc_vp8",
|
||||
"../modules/video_coding:webrtc_vp9",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:rtc_task_queue",
|
||||
"../rtc_base:sequenced_task_checker",
|
||||
"../system_wrappers",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("test_common") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"call_test.cc",
|
||||
"call_test.h",
|
||||
"configurable_frame_size_encoder.cc",
|
||||
"configurable_frame_size_encoder.h",
|
||||
"constants.cc",
|
||||
"constants.h",
|
||||
"drifting_clock.cc",
|
||||
@ -545,6 +502,10 @@ rtc_source_set("test_common") {
|
||||
"encoder_proxy_factory.h",
|
||||
"encoder_settings.cc",
|
||||
"encoder_settings.h",
|
||||
"fake_decoder.cc",
|
||||
"fake_decoder.h",
|
||||
"fake_encoder.cc",
|
||||
"fake_encoder.h",
|
||||
"fake_videorenderer.h",
|
||||
"function_video_decoder_factory.h",
|
||||
"function_video_encoder_factory.h",
|
||||
@ -573,17 +534,18 @@ rtc_source_set("test_common") {
|
||||
|
||||
deps = [
|
||||
":direct_transport",
|
||||
":fake_video_codecs",
|
||||
":fileutils",
|
||||
":rtp_test_utils",
|
||||
":test_support",
|
||||
":video_test_common",
|
||||
"..:webrtc_common",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:simulated_network_api",
|
||||
"../api:transport_api",
|
||||
"../api/audio_codecs:builtin_audio_decoder_factory",
|
||||
"../api/audio_codecs:builtin_audio_encoder_factory",
|
||||
"../api/video:video_frame",
|
||||
"../api/video:video_frame_i420",
|
||||
"../api/video_codecs:video_codecs_api",
|
||||
"../audio",
|
||||
"../call",
|
||||
@ -593,6 +555,7 @@ rtc_source_set("test_common") {
|
||||
"../call:simulated_network",
|
||||
"../call:simulated_packet_receiver",
|
||||
"../call:video_stream_api",
|
||||
"../common_video",
|
||||
"../logging:rtc_event_log_api",
|
||||
"../logging:rtc_event_log_impl_base",
|
||||
"../media:rtc_internal_video_codecs",
|
||||
@ -606,6 +569,7 @@ rtc_source_set("test_common") {
|
||||
"../modules/rtp_rtcp",
|
||||
"../modules/rtp_rtcp:mock_rtp_rtcp",
|
||||
"../modules/rtp_rtcp:rtp_rtcp_format",
|
||||
"../modules/video_coding:video_codec_interface",
|
||||
"../modules/video_coding:video_coding_utility",
|
||||
"../modules/video_coding:webrtc_h264",
|
||||
"../modules/video_coding:webrtc_multiplex",
|
||||
@ -613,6 +577,8 @@ rtc_source_set("test_common") {
|
||||
"../modules/video_coding:webrtc_vp9",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:rtc_task_queue",
|
||||
"../rtc_base:sequenced_task_checker",
|
||||
"../rtc_base/experiments:congestion_controller_experiment",
|
||||
"../system_wrappers",
|
||||
"../system_wrappers:field_trial_api",
|
||||
|
@ -43,14 +43,9 @@ CallTest::CallTest()
|
||||
audio_send_stream_(nullptr),
|
||||
bbr_network_controller_factory_(new BbrNetworkControllerFactory()),
|
||||
fake_encoder_factory_([this]() {
|
||||
std::unique_ptr<FakeEncoder> fake_encoder;
|
||||
if (video_encoder_configs_[0].codec_type == kVideoCodecVP8) {
|
||||
fake_encoder = absl::make_unique<FakeVP8Encoder>(clock_);
|
||||
} else {
|
||||
fake_encoder = absl::make_unique<FakeEncoder>(clock_);
|
||||
}
|
||||
fake_encoder->SetMaxBitrate(fake_encoder_max_bitrate_);
|
||||
return fake_encoder;
|
||||
auto encoder = absl::make_unique<test::FakeEncoder>(clock_);
|
||||
encoder->SetMaxBitrate(fake_encoder_max_bitrate_);
|
||||
return encoder;
|
||||
}),
|
||||
num_video_streams_(1),
|
||||
num_audio_streams_(0),
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "test/encoder_settings.h"
|
||||
#include "test/fake_decoder.h"
|
||||
#include "test/fake_videorenderer.h"
|
||||
#include "test/fake_vp8_encoder.h"
|
||||
#include "test/frame_generator_capturer.h"
|
||||
#include "test/function_video_encoder_factory.h"
|
||||
#include "test/rtp_rtcp_observer.h"
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "common_video/include/video_frame.h"
|
||||
#include "modules/video_coding/include/video_codec_interface.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
@ -22,7 +22,7 @@ namespace test {
|
||||
class ConfigurableFrameSizeEncoder : public VideoEncoder {
|
||||
public:
|
||||
explicit ConfigurableFrameSizeEncoder(size_t max_frame_size);
|
||||
~ConfigurableFrameSizeEncoder() override;
|
||||
virtual ~ConfigurableFrameSizeEncoder();
|
||||
|
||||
int32_t InitEncode(const VideoCodec* codec_settings,
|
||||
int32_t number_of_cores,
|
||||
|
@ -12,17 +12,16 @@
|
||||
|
||||
#include "api/video/i420_buffer.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
#include "test/call_test.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
namespace {
|
||||
const int kDefaultWidth = 320;
|
||||
const int kDefaultHeight = 180;
|
||||
} // namespace
|
||||
|
||||
FakeDecoder::FakeDecoder()
|
||||
: callback_(NULL), width_(kDefaultWidth), height_(kDefaultHeight) {}
|
||||
: callback_(NULL),
|
||||
width_(CallTest::kDefaultWidth),
|
||||
height_(CallTest::kDefaultHeight) {}
|
||||
|
||||
int32_t FakeDecoder::InitDecode(const VideoCodec* config,
|
||||
int32_t number_of_cores) {
|
||||
@ -76,7 +75,7 @@ int32_t FakeH264Decoder::Decode(const EncodedImage& input,
|
||||
i += sizeof(kStartCode) + 1; // Skip start code and NAL header.
|
||||
}
|
||||
if (input._buffer[i] != value) {
|
||||
RTC_CHECK_EQ(value, input._buffer[i])
|
||||
EXPECT_EQ(value, input._buffer[i])
|
||||
<< "Bitstream mismatch between sender and receiver.";
|
||||
return -1;
|
||||
}
|
||||
|
@ -16,10 +16,10 @@
|
||||
#include <memory>
|
||||
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/video_coding/codecs/vp8/temporal_layers.h"
|
||||
#include "modules/video_coding/include/video_codec_interface.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "system_wrappers/include/sleep.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
@ -37,9 +37,6 @@ FakeEncoder::FakeEncoder(Clock* clock)
|
||||
for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
|
||||
encoded_buffer_[i] = static_cast<uint8_t>(i);
|
||||
}
|
||||
for (bool& used : used_layers_) {
|
||||
used = false;
|
||||
}
|
||||
}
|
||||
|
||||
void FakeEncoder::SetMaxBitrate(int max_kbps) {
|
||||
@ -56,7 +53,6 @@ int32_t FakeEncoder::InitEncode(const VideoCodec* config,
|
||||
target_bitrate_.SetBitrate(0, 0, config_.startBitrate * 1000);
|
||||
configured_input_framerate_ = config_.maxFramerate;
|
||||
pending_keyframe_ = true;
|
||||
last_frame_info_ = FrameInfo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -67,7 +63,9 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
||||
unsigned char num_simulcast_streams;
|
||||
SimulcastStream simulcast_streams[kMaxSimulcastStreams];
|
||||
EncodedImageCallback* callback;
|
||||
VideoBitrateAllocation target_bitrate;
|
||||
uint32_t target_bitrate_sum_kbps;
|
||||
int max_target_bitrate_kbps;
|
||||
size_t num_encoded_bytes;
|
||||
int framerate;
|
||||
VideoCodecMode mode;
|
||||
bool keyframe;
|
||||
@ -79,7 +77,9 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
||||
simulcast_streams[i] = config_.simulcastStream[i];
|
||||
}
|
||||
callback = callback_;
|
||||
target_bitrate = target_bitrate_;
|
||||
target_bitrate_sum_kbps = target_bitrate_.get_sum_kbps();
|
||||
max_target_bitrate_kbps = max_target_bitrate_kbps_;
|
||||
num_encoded_bytes = sizeof(encoded_buffer_);
|
||||
mode = config_.mode;
|
||||
if (configured_input_framerate_ > 0) {
|
||||
framerate = configured_input_framerate_;
|
||||
@ -90,28 +90,63 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
||||
pending_keyframe_ = false;
|
||||
}
|
||||
|
||||
FrameInfo frame_info =
|
||||
NextFrame(frame_types, keyframe, num_simulcast_streams, target_bitrate,
|
||||
simulcast_streams, framerate);
|
||||
for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
|
||||
if (frame_info.layers[i].size == 0) {
|
||||
// Drop this temporal layer.
|
||||
continue;
|
||||
for (FrameType frame_type : *frame_types) {
|
||||
if (frame_type == kVideoFrameKey) {
|
||||
keyframe = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RTC_DCHECK_GT(max_framerate, 0);
|
||||
|
||||
size_t bitrate =
|
||||
std::max(target_bitrate_sum_kbps, simulcast_streams[0].minBitrate);
|
||||
if (max_target_bitrate_kbps > 0)
|
||||
bitrate = std::min(bitrate, static_cast<size_t>(max_target_bitrate_kbps));
|
||||
|
||||
size_t bits_available = bitrate * 1000 / framerate;
|
||||
|
||||
RTC_DCHECK_GT(num_simulcast_streams, 0);
|
||||
for (unsigned char i = 0; i < num_simulcast_streams; ++i) {
|
||||
CodecSpecificInfo specifics;
|
||||
memset(&specifics, 0, sizeof(specifics));
|
||||
specifics.codecType = kVideoCodecGeneric;
|
||||
specifics.codecSpecific.generic.simulcast_idx = i;
|
||||
std::unique_ptr<uint8_t[]> encoded_buffer(
|
||||
new uint8_t[frame_info.layers[i].size]);
|
||||
memcpy(encoded_buffer.get(), encoded_buffer_, frame_info.layers[i].size);
|
||||
EncodedImage encoded(encoded_buffer.get(), frame_info.layers[i].size,
|
||||
sizeof(encoded_buffer_));
|
||||
encoded._timeStamp = input_image.timestamp();
|
||||
size_t min_stream_bits = static_cast<size_t>(
|
||||
(simulcast_streams[i].minBitrate * 1000) / framerate);
|
||||
size_t max_stream_bits = static_cast<size_t>(
|
||||
(simulcast_streams[i].maxBitrate * 1000) / framerate);
|
||||
size_t stream_bits =
|
||||
(bits_available > max_stream_bits) ? max_stream_bits : bits_available;
|
||||
size_t stream_bytes = (stream_bits + 7) / 8;
|
||||
if (keyframe) {
|
||||
// The first frame is a key frame and should be larger.
|
||||
// Store the overshoot bytes and distribute them over the coming frames,
|
||||
// so that we on average meet the bitrate target.
|
||||
debt_bytes_ += (kKeyframeSizeFactor - 1) * stream_bytes;
|
||||
stream_bytes *= kKeyframeSizeFactor;
|
||||
} else {
|
||||
if (debt_bytes_ > 0) {
|
||||
// Pay at most half of the frame size for old debts.
|
||||
size_t payment_size = std::min(stream_bytes / 2, debt_bytes_);
|
||||
debt_bytes_ -= payment_size;
|
||||
stream_bytes -= payment_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (stream_bytes > num_encoded_bytes)
|
||||
stream_bytes = num_encoded_bytes;
|
||||
|
||||
// Always encode something on the first frame.
|
||||
if (min_stream_bits > bits_available && i > 0)
|
||||
continue;
|
||||
|
||||
std::unique_ptr<uint8_t[]> encoded_buffer(new uint8_t[num_encoded_bytes]);
|
||||
memcpy(encoded_buffer.get(), encoded_buffer_, num_encoded_bytes);
|
||||
EncodedImage encoded(encoded_buffer.get(), stream_bytes, num_encoded_bytes);
|
||||
encoded.SetTimestamp(input_image.timestamp());
|
||||
encoded.capture_time_ms_ = input_image.render_time_ms();
|
||||
encoded._frameType =
|
||||
frame_info.keyframe ? kVideoFrameKey : kVideoFrameDelta;
|
||||
encoded._frameType = (*frame_types)[i];
|
||||
encoded._encodedWidth = simulcast_streams[i].width;
|
||||
encoded._encodedHeight = simulcast_streams[i].height;
|
||||
encoded.rotation_ = input_image.rotation();
|
||||
@ -119,77 +154,17 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
||||
? VideoContentType::SCREENSHARE
|
||||
: VideoContentType::UNSPECIFIED;
|
||||
specifics.codec_name = ImplementationName();
|
||||
specifics.codecSpecific.generic.simulcast_idx = i;
|
||||
RTC_DCHECK(callback);
|
||||
if (callback->OnEncodedImage(encoded, &specifics, nullptr).error !=
|
||||
EncodedImageCallback::Result::OK) {
|
||||
return -1;
|
||||
}
|
||||
bits_available -= std::min(encoded._length * 8, bits_available);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FakeEncoder::FrameInfo FakeEncoder::NextFrame(
|
||||
const std::vector<FrameType>* frame_types,
|
||||
bool keyframe,
|
||||
uint8_t num_simulcast_streams,
|
||||
const VideoBitrateAllocation& target_bitrate,
|
||||
SimulcastStream simulcast_streams[kMaxSimulcastStreams],
|
||||
int framerate) {
|
||||
FrameInfo frame_info;
|
||||
frame_info.keyframe = keyframe;
|
||||
|
||||
if (frame_types) {
|
||||
for (FrameType frame_type : *frame_types) {
|
||||
if (frame_type == kVideoFrameKey) {
|
||||
frame_info.keyframe = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < num_simulcast_streams; ++i) {
|
||||
if (target_bitrate.GetBitrate(i, 0) > 0) {
|
||||
int temporal_id = last_frame_info_.layers.size() > i
|
||||
? ++last_frame_info_.layers[i].temporal_id %
|
||||
simulcast_streams[i].numberOfTemporalLayers
|
||||
: 0;
|
||||
frame_info.layers.emplace_back(0, temporal_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (last_frame_info_.layers.size() < frame_info.layers.size()) {
|
||||
// A new keyframe is needed since a new layer will be added.
|
||||
frame_info.keyframe = true;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
|
||||
FrameInfo::SpatialLayer& layer_info = frame_info.layers[i];
|
||||
if (frame_info.keyframe) {
|
||||
layer_info.temporal_id = 0;
|
||||
size_t avg_frame_size =
|
||||
(target_bitrate.GetBitrate(i, 0) + 7) / (8 * framerate);
|
||||
|
||||
// The first frame is a key frame and should be larger.
|
||||
// Store the overshoot bytes and distribute them over the coming frames,
|
||||
// so that we on average meet the bitrate target.
|
||||
debt_bytes_ += (kKeyframeSizeFactor - 1) * avg_frame_size;
|
||||
layer_info.size = kKeyframeSizeFactor * avg_frame_size;
|
||||
} else {
|
||||
size_t avg_frame_size =
|
||||
(target_bitrate.GetBitrate(i, layer_info.temporal_id) + 7) /
|
||||
(8 * framerate);
|
||||
layer_info.size = avg_frame_size;
|
||||
if (debt_bytes_ > 0) {
|
||||
// Pay at most half of the frame size for old debts.
|
||||
size_t payment_size = std::min(avg_frame_size / 2, debt_bytes_);
|
||||
debt_bytes_ -= payment_size;
|
||||
layer_info.size -= payment_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
last_frame_info_ = frame_info;
|
||||
return frame_info;
|
||||
}
|
||||
|
||||
int32_t FakeEncoder::RegisterEncodeCompleteCallback(
|
||||
EncodedImageCallback* callback) {
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
|
@ -50,30 +50,7 @@ class FakeEncoder : public VideoEncoder {
|
||||
static const char* kImplementationName;
|
||||
|
||||
protected:
|
||||
struct FrameInfo {
|
||||
bool keyframe;
|
||||
struct SpatialLayer {
|
||||
SpatialLayer() = default;
|
||||
SpatialLayer(int size, int temporal_id)
|
||||
: size(size), temporal_id(temporal_id) {}
|
||||
// Size of a current frame in the layer.
|
||||
int size = 0;
|
||||
// Temporal index of a current frame in the layer.
|
||||
int temporal_id = 0;
|
||||
};
|
||||
std::vector<SpatialLayer> layers;
|
||||
};
|
||||
|
||||
FrameInfo NextFrame(const std::vector<FrameType>* frame_types,
|
||||
bool keyframe,
|
||||
uint8_t num_simulcast_streams,
|
||||
const VideoBitrateAllocation& target_bitrate,
|
||||
SimulcastStream simulcast_streams[kMaxSimulcastStreams],
|
||||
int framerate);
|
||||
|
||||
FrameInfo last_frame_info_;
|
||||
Clock* const clock_;
|
||||
|
||||
VideoCodec config_ RTC_GUARDED_BY(crit_sect_);
|
||||
EncodedImageCallback* callback_ RTC_GUARDED_BY(crit_sect_);
|
||||
VideoBitrateAllocation target_bitrate_ RTC_GUARDED_BY(crit_sect_);
|
||||
@ -83,7 +60,6 @@ class FakeEncoder : public VideoEncoder {
|
||||
rtc::CriticalSection crit_sect_;
|
||||
|
||||
uint8_t encoded_buffer_[100000];
|
||||
bool used_layers_[kMaxSimulcastStreams];
|
||||
|
||||
// Current byte debt to be payed over a number of frames.
|
||||
// The debt is acquired by keyframes overshooting the bitrate target.
|
||||
|
@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "test/fake_vp8_encoder.h"
|
||||
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/video_coding/codecs/vp8/temporal_layers.h"
|
||||
#include "modules/video_coding/include/video_codec_interface.h"
|
||||
#include "modules/video_coding/include/video_error_codes.h"
|
||||
#include "modules/video_coding/utility/simulcast_utility.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/random.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace test {
|
||||
|
||||
FakeVP8Encoder::FakeVP8Encoder(Clock* clock)
|
||||
: FakeEncoder(clock), callback_(nullptr) {
|
||||
FakeEncoder::RegisterEncodeCompleteCallback(this);
|
||||
sequence_checker_.Detach();
|
||||
}
|
||||
|
||||
int32_t FakeVP8Encoder::RegisterEncodeCompleteCallback(
|
||||
EncodedImageCallback* callback) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
||||
callback_ = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t FakeVP8Encoder::InitEncode(const VideoCodec* config,
|
||||
int32_t number_of_cores,
|
||||
size_t max_payload_size) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
||||
auto result =
|
||||
FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
|
||||
if (result != WEBRTC_VIDEO_CODEC_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int number_of_streams = SimulcastUtility::NumberOfSimulcastStreams(*config);
|
||||
bool doing_simulcast = number_of_streams > 1;
|
||||
|
||||
int num_temporal_layers =
|
||||
doing_simulcast ? config->simulcastStream[0].numberOfTemporalLayers
|
||||
: config->VP8().numberOfTemporalLayers;
|
||||
RTC_DCHECK_GT(num_temporal_layers, 0);
|
||||
|
||||
SetupTemporalLayers(number_of_streams, num_temporal_layers, *config);
|
||||
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
int32_t FakeVP8Encoder::Release() {
|
||||
auto result = FakeEncoder::Release();
|
||||
sequence_checker_.Detach();
|
||||
return result;
|
||||
}
|
||||
|
||||
void FakeVP8Encoder::SetupTemporalLayers(int num_streams,
|
||||
int num_temporal_layers,
|
||||
const VideoCodec& codec) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
||||
|
||||
temporal_layers_.clear();
|
||||
for (int i = 0; i < num_streams; ++i) {
|
||||
temporal_layers_.emplace_back(
|
||||
TemporalLayers::CreateTemporalLayers(codec, i));
|
||||
}
|
||||
}
|
||||
|
||||
void FakeVP8Encoder::PopulateCodecSpecific(
|
||||
CodecSpecificInfo* codec_specific,
|
||||
const TemporalLayers::FrameConfig& tl_config,
|
||||
FrameType frame_type,
|
||||
int stream_idx,
|
||||
uint32_t timestamp) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
||||
codec_specific->codecType = kVideoCodecVP8;
|
||||
codec_specific->codec_name = ImplementationName();
|
||||
CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8);
|
||||
vp8Info->simulcastIdx = stream_idx;
|
||||
vp8Info->keyIdx = kNoKeyIdx;
|
||||
vp8Info->nonReference = false;
|
||||
temporal_layers_[stream_idx]->PopulateCodecSpecific(
|
||||
frame_type == kVideoFrameKey, tl_config, vp8Info, timestamp);
|
||||
}
|
||||
|
||||
EncodedImageCallback::Result FakeVP8Encoder::OnEncodedImage(
|
||||
const EncodedImage& encoded_image,
|
||||
const CodecSpecificInfo* codec_specific_info,
|
||||
const RTPFragmentationHeader* fragments) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
||||
uint8_t stream_idx = codec_specific_info->codecSpecific.generic.simulcast_idx;
|
||||
CodecSpecificInfo overrided_specific_info;
|
||||
TemporalLayers::FrameConfig tl_config =
|
||||
temporal_layers_[stream_idx]->UpdateLayerConfig(encoded_image._timeStamp);
|
||||
PopulateCodecSpecific(&overrided_specific_info, tl_config,
|
||||
encoded_image._frameType, stream_idx,
|
||||
encoded_image._timeStamp);
|
||||
temporal_layers_[stream_idx]->FrameEncoded(encoded_image._timeStamp,
|
||||
encoded_image._length, -1);
|
||||
|
||||
return callback_->OnEncodedImage(encoded_image, &overrided_specific_info,
|
||||
fragments);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef TEST_FAKE_VP8_ENCODER_H_
|
||||
#define TEST_FAKE_VP8_ENCODER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/video_coding/codecs/vp8/temporal_layers.h"
|
||||
#include "test/fake_encoder.h"
|
||||
|
||||
#include "rtc_base/criticalsection.h"
|
||||
#include "rtc_base/sequenced_task_checker.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class FakeVP8Encoder : public FakeEncoder, public EncodedImageCallback {
|
||||
public:
|
||||
explicit FakeVP8Encoder(Clock* clock);
|
||||
virtual ~FakeVP8Encoder() = default;
|
||||
|
||||
int32_t RegisterEncodeCompleteCallback(
|
||||
EncodedImageCallback* callback) override;
|
||||
|
||||
int32_t InitEncode(const VideoCodec* config,
|
||||
int32_t number_of_cores,
|
||||
size_t max_payload_size) override;
|
||||
|
||||
int32_t Release() override;
|
||||
|
||||
const char* ImplementationName() const override { return "FakeVp8Encoder"; }
|
||||
|
||||
Result OnEncodedImage(const EncodedImage& encodedImage,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
const RTPFragmentationHeader* fragments) override;
|
||||
|
||||
private:
|
||||
void SetupTemporalLayers(int num_streams,
|
||||
int num_temporal_layers,
|
||||
const VideoCodec& codec);
|
||||
void PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
|
||||
const TemporalLayers::FrameConfig& tl_config,
|
||||
FrameType frame_type,
|
||||
int stream_idx,
|
||||
uint32_t timestamp);
|
||||
|
||||
rtc::SequencedTaskChecker sequence_checker_;
|
||||
EncodedImageCallback* callback_ RTC_GUARDED_BY(sequence_checker_);
|
||||
|
||||
std::vector<std::unique_ptr<TemporalLayers>> temporal_layers_
|
||||
RTC_GUARDED_BY(sequence_checker_);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // TEST_FAKE_VP8_ENCODER_H_
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "api/test/create_simulcast_test_fixture.h"
|
||||
#include "api/test/simulcast_test_fixture.h"
|
||||
#include "modules/video_coding/utility/simulcast_test_fixture_impl.h"
|
||||
#include "test/fake_decoder.h"
|
||||
#include "test/fake_vp8_encoder.h"
|
||||
#include "test/function_video_decoder_factory.h"
|
||||
#include "test/function_video_encoder_factory.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<SimulcastTestFixture> CreateSpecificSimulcastTestFixture() {
|
||||
std::unique_ptr<VideoEncoderFactory> encoder_factory =
|
||||
absl::make_unique<FunctionVideoEncoderFactory>([]() {
|
||||
return absl::make_unique<FakeVP8Encoder>(Clock::GetRealTimeClock());
|
||||
});
|
||||
std::unique_ptr<VideoDecoderFactory> decoder_factory =
|
||||
absl::make_unique<FunctionVideoDecoderFactory>(
|
||||
[]() { return absl::make_unique<FakeDecoder>(); });
|
||||
return CreateSimulcastTestFixture(std::move(encoder_factory),
|
||||
std::move(decoder_factory),
|
||||
SdpVideoFormat("VP8"));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(TestFakeVp8Codec, TestKeyFrameRequestsOnAllStreams) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestKeyFrameRequestsOnAllStreams();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestPaddingAllStreams) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestPaddingAllStreams();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestPaddingTwoStreams) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestPaddingTwoStreams();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestPaddingTwoStreamsOneMaxedOut) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestPaddingTwoStreamsOneMaxedOut();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestPaddingOneStream) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestPaddingOneStream();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestPaddingOneStreamTwoMaxedOut) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestPaddingOneStreamTwoMaxedOut();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestSendAllStreams) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestSendAllStreams();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestDisablingStreams) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestDisablingStreams();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestSwitchingToOneStream) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestSwitchingToOneStream();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestSwitchingToOneOddStream) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestSwitchingToOneOddStream();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestSwitchingToOneSmallStream) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestSwitchingToOneSmallStream();
|
||||
}
|
||||
|
||||
TEST(TestFakeVp8Codec, TestSpatioTemporalLayers333PatternEncoder) {
|
||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
||||
fixture->TestSpatioTemporalLayers333PatternEncoder();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
@ -361,7 +361,6 @@ if (rtc_include_tests) {
|
||||
"../system_wrappers",
|
||||
"../system_wrappers:metrics_default",
|
||||
"../system_wrappers:runtime_enabled_features_default",
|
||||
"../test:fake_video_codecs",
|
||||
"../test:field_trial",
|
||||
"../test:rtp_test_utils",
|
||||
"../test:run_test",
|
||||
@ -473,7 +472,6 @@ if (rtc_include_tests) {
|
||||
"../system_wrappers:metrics_api",
|
||||
"../system_wrappers:metrics_default",
|
||||
"../test:direct_transport",
|
||||
"../test:fake_video_codecs",
|
||||
"../test:field_trial",
|
||||
"../test:fileutils",
|
||||
"../test:perf_test",
|
||||
|
@ -30,12 +30,7 @@ class RtcpXrObserver : public test::EndToEndTest {
|
||||
sent_rtcp_rrtr_(0),
|
||||
sent_rtcp_target_bitrate_(false),
|
||||
sent_zero_rtcp_target_bitrate_(false),
|
||||
sent_rtcp_dlrr_(0),
|
||||
send_transport_(nullptr) {
|
||||
forward_transport_config_.link_capacity_kbps = 500;
|
||||
forward_transport_config_.queue_delay_ms = 0;
|
||||
forward_transport_config_.loss_percent = 0;
|
||||
}
|
||||
sent_rtcp_dlrr_(0) {}
|
||||
|
||||
private:
|
||||
// Receive stream should send RR packets (and RRTR packets if enabled).
|
||||
@ -61,14 +56,6 @@ class RtcpXrObserver : public test::EndToEndTest {
|
||||
test::RtcpPacketParser parser;
|
||||
EXPECT_TRUE(parser.Parse(packet, length));
|
||||
|
||||
if (parser.sender_ssrc() == test::CallTest::kVideoSendSsrcs[1] &&
|
||||
enable_zero_target_bitrate_) {
|
||||
// Reduce bandwidth restriction to disable second stream after it was
|
||||
// enabled for some time.
|
||||
forward_transport_config_.link_capacity_kbps = 200;
|
||||
send_transport_->SetConfig(forward_transport_config_);
|
||||
}
|
||||
|
||||
sent_rtcp_sr_ += parser.sender_report()->num_packets();
|
||||
EXPECT_LE(parser.xr()->num_packets(), 1);
|
||||
if (parser.xr()->num_packets() > 0) {
|
||||
@ -77,12 +64,8 @@ class RtcpXrObserver : public test::EndToEndTest {
|
||||
++sent_rtcp_dlrr_;
|
||||
if (parser.xr()->target_bitrate()) {
|
||||
sent_rtcp_target_bitrate_ = true;
|
||||
auto target_bitrates =
|
||||
parser.xr()->target_bitrate()->GetTargetBitrates();
|
||||
if (target_bitrates.empty()) {
|
||||
sent_zero_rtcp_target_bitrate_ = true;
|
||||
}
|
||||
for (const rtcp::TargetBitrate::BitrateItem& item : target_bitrates) {
|
||||
for (const rtcp::TargetBitrate::BitrateItem& item :
|
||||
parser.xr()->target_bitrate()->GetTargetBitrates()) {
|
||||
if (item.target_bitrate_kbps == 0) {
|
||||
sent_zero_rtcp_target_bitrate_ = true;
|
||||
break;
|
||||
@ -115,20 +98,39 @@ class RtcpXrObserver : public test::EndToEndTest {
|
||||
return enable_zero_target_bitrate_ ? 2 : 1;
|
||||
}
|
||||
|
||||
test::PacketTransport* CreateSendTransport(
|
||||
test::SingleThreadedTaskQueueForTesting* task_queue,
|
||||
Call* sender_call) {
|
||||
send_transport_ = new test::PacketTransport(
|
||||
task_queue, sender_call, this, test::PacketTransport::kSender,
|
||||
test::CallTest::payload_type_map_, forward_transport_config_);
|
||||
return send_transport_;
|
||||
// This test uses VideoStream settings different from the the default one
|
||||
// implemented in DefaultVideoStreamFactory, so it implements its own
|
||||
// VideoEncoderConfig::VideoStreamFactoryInterface which is created
|
||||
// in ModifyVideoConfigs.
|
||||
class ZeroTargetVideoStreamFactory
|
||||
: public VideoEncoderConfig::VideoStreamFactoryInterface {
|
||||
public:
|
||||
ZeroTargetVideoStreamFactory() {}
|
||||
|
||||
private:
|
||||
std::vector<VideoStream> CreateEncoderStreams(
|
||||
int width,
|
||||
int height,
|
||||
const VideoEncoderConfig& encoder_config) override {
|
||||
std::vector<VideoStream> streams =
|
||||
test::CreateVideoStreams(width, height, encoder_config);
|
||||
// Set one of the streams' target bitrates to zero to test that a
|
||||
// bitrate of 0 can be signalled.
|
||||
streams[encoder_config.number_of_streams - 1].min_bitrate_bps = 0;
|
||||
streams[encoder_config.number_of_streams - 1].target_bitrate_bps = 0;
|
||||
streams[encoder_config.number_of_streams - 1].max_bitrate_bps = 0;
|
||||
return streams;
|
||||
}
|
||||
};
|
||||
|
||||
void ModifyVideoConfigs(
|
||||
VideoSendStream::Config* send_config,
|
||||
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||
VideoEncoderConfig* encoder_config) override {
|
||||
if (enable_zero_target_bitrate_) {
|
||||
encoder_config->video_stream_factory =
|
||||
new rtc::RefCountedObject<ZeroTargetVideoStreamFactory>();
|
||||
|
||||
// Configure VP8 to be able to use simulcast.
|
||||
send_config->rtp.payload_name = "VP8";
|
||||
encoder_config->codec_type = kVideoCodecVP8;
|
||||
@ -164,8 +166,6 @@ class RtcpXrObserver : public test::EndToEndTest {
|
||||
bool sent_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
|
||||
bool sent_zero_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
|
||||
int sent_rtcp_dlrr_;
|
||||
DefaultNetworkSimulationConfig forward_transport_config_;
|
||||
test::PacketTransport* send_transport_;
|
||||
};
|
||||
|
||||
TEST_F(ExtendedReportsEndToEndTest,
|
||||
|
Reference in New Issue
Block a user