|  | /* | 
|  | *  Copyright (c) 2015 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 <stdio.h> | 
|  |  | 
|  | #include <map> | 
|  |  | 
|  | #include "gflags/gflags.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | #include "webrtc/test/field_trial.h" | 
|  | #include "webrtc/test/frame_generator.h" | 
|  | #include "webrtc/test/frame_generator_capturer.h" | 
|  | #include "webrtc/test/run_test.h" | 
|  | #include "webrtc/test/testsupport/fileutils.h" | 
|  | #include "webrtc/typedefs.h" | 
|  | #include "webrtc/video/loopback.h" | 
|  | #include "webrtc/video/video_send_stream.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace flags { | 
|  |  | 
|  | // Fixed for prerecorded screenshare content. | 
|  | size_t Width() { | 
|  | return 1850; | 
|  | } | 
|  | size_t Height() { | 
|  | return 1110; | 
|  | } | 
|  |  | 
|  | DEFINE_int32(fps, 5, "Frames per second."); | 
|  | int Fps() { | 
|  | return static_cast<int>(FLAGS_fps); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(min_bitrate, 50, "Minimum video bitrate."); | 
|  | size_t MinBitrate() { | 
|  | return static_cast<size_t>(FLAGS_min_bitrate); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(tl0_bitrate, 200, "Temporal layer 0 target bitrate."); | 
|  | size_t StartBitrate() { | 
|  | return static_cast<size_t>(FLAGS_tl0_bitrate); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(tl1_bitrate, 2000, "Temporal layer 1 target bitrate."); | 
|  | size_t MaxBitrate() { | 
|  | return static_cast<size_t>(FLAGS_tl1_bitrate); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(min_transmit_bitrate, 400, "Min transmit bitrate incl. padding."); | 
|  | int MinTransmitBitrate() { | 
|  | return FLAGS_min_transmit_bitrate; | 
|  | } | 
|  |  | 
|  | DEFINE_string(codec, "VP8", "Video codec to use."); | 
|  | std::string Codec() { | 
|  | return static_cast<std::string>(FLAGS_codec); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(loss_percent, 0, "Percentage of packets randomly lost."); | 
|  | int LossPercent() { | 
|  | return static_cast<int>(FLAGS_loss_percent); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(link_capacity, | 
|  | 0, | 
|  | "Capacity (kbps) of the fake link. 0 means infinite."); | 
|  | int LinkCapacity() { | 
|  | return static_cast<int>(FLAGS_link_capacity); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(queue_size, 0, "Size of the bottleneck link queue in packets."); | 
|  | int QueueSize() { | 
|  | return static_cast<int>(FLAGS_queue_size); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(avg_propagation_delay_ms, | 
|  | 0, | 
|  | "Average link propagation delay in ms."); | 
|  | int AvgPropagationDelayMs() { | 
|  | return static_cast<int>(FLAGS_avg_propagation_delay_ms); | 
|  | } | 
|  |  | 
|  | DEFINE_int32(std_propagation_delay_ms, | 
|  | 0, | 
|  | "Link propagation delay standard deviation in ms."); | 
|  | int StdPropagationDelayMs() { | 
|  | return static_cast<int>(FLAGS_std_propagation_delay_ms); | 
|  | } | 
|  |  | 
|  | DEFINE_bool(logs, false, "print logs to stderr"); | 
|  |  | 
|  | DEFINE_string( | 
|  | force_fieldtrials, | 
|  | "", | 
|  | "Field trials control experimental feature code which can be forced. " | 
|  | "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" | 
|  | " will assign the group Enable to field trial WebRTC-FooFeature. Multiple " | 
|  | "trials are separated by \"/\""); | 
|  | }  // namespace flags | 
|  |  | 
|  | class ScreenshareLoopback : public test::Loopback { | 
|  | public: | 
|  | explicit ScreenshareLoopback(const Config& config) : Loopback(config) { | 
|  | vp8_settings_ = VideoEncoder::GetDefaultVp8Settings(); | 
|  | vp8_settings_.denoisingOn = false; | 
|  | vp8_settings_.frameDroppingOn = false; | 
|  | vp8_settings_.numberOfTemporalLayers = 2; | 
|  | } | 
|  | virtual ~ScreenshareLoopback() {} | 
|  |  | 
|  | protected: | 
|  | VideoEncoderConfig CreateEncoderConfig() override { | 
|  | VideoEncoderConfig encoder_config(test::Loopback::CreateEncoderConfig()); | 
|  | VideoStream* stream = &encoder_config.streams[0]; | 
|  | encoder_config.content_type = VideoEncoderConfig::ContentType::kScreen; | 
|  | encoder_config.min_transmit_bitrate_bps = flags::MinTransmitBitrate(); | 
|  | encoder_config.encoder_specific_settings = &vp8_settings_; | 
|  | stream->temporal_layer_thresholds_bps.clear(); | 
|  | stream->target_bitrate_bps = | 
|  | static_cast<int>(config_.start_bitrate_kbps) * 1000; | 
|  | stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps); | 
|  | return encoder_config; | 
|  | } | 
|  |  | 
|  | test::VideoCapturer* CreateCapturer(VideoSendStream* send_stream) override { | 
|  | std::vector<std::string> slides; | 
|  | slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv")); | 
|  | slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv")); | 
|  | slides.push_back(test::ResourcePath("photo_1850_1110", "yuv")); | 
|  | slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv")); | 
|  |  | 
|  | test::FrameGenerator* frame_generator = | 
|  | test::FrameGenerator::CreateFromYuvFile( | 
|  | slides, flags::Width(), flags::Height(), 10 * flags::Fps()); | 
|  | test::FrameGeneratorCapturer* capturer(new test::FrameGeneratorCapturer( | 
|  | clock_, send_stream->Input(), frame_generator, flags::Fps())); | 
|  | EXPECT_TRUE(capturer->Init()); | 
|  | return capturer; | 
|  | } | 
|  |  | 
|  | VideoCodecVP8 vp8_settings_; | 
|  | }; | 
|  |  | 
|  | void Loopback() { | 
|  | test::Loopback::Config config{flags::Width(), | 
|  | flags::Height(), | 
|  | flags::Fps(), | 
|  | flags::MinBitrate(), | 
|  | flags::StartBitrate(), | 
|  | flags::MaxBitrate(), | 
|  | flags::MinTransmitBitrate(), | 
|  | flags::Codec(), | 
|  | 0,  // Default number of temporal layers. | 
|  | flags::LossPercent(), | 
|  | flags::LinkCapacity(), | 
|  | flags::QueueSize(), | 
|  | flags::AvgPropagationDelayMs(), | 
|  | flags::StdPropagationDelayMs(), | 
|  | flags::FLAGS_logs}; | 
|  | ScreenshareLoopback loopback(config); | 
|  | loopback.Run(); | 
|  | } | 
|  | }  // namespace webrtc | 
|  |  | 
|  | int main(int argc, char* argv[]) { | 
|  | ::testing::InitGoogleTest(&argc, argv); | 
|  | google::ParseCommandLineFlags(&argc, &argv, true); | 
|  | webrtc::test::InitFieldTrialsFromString( | 
|  | webrtc::flags::FLAGS_force_fieldtrials); | 
|  | webrtc::test::RunTest(webrtc::Loopback); | 
|  | return 0; | 
|  | } |