| OLD | NEW | 
|     1 /* |     1 /* | 
|     2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |     2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 
|     3  * |     3  * | 
|     4  *  Use of this source code is governed by a BSD-style license |     4  *  Use of this source code is governed by a BSD-style license | 
|     5  *  that can be found in the LICENSE file in the root of the source |     5  *  that can be found in the LICENSE file in the root of the source | 
|     6  *  tree. An additional intellectual property rights grant can be found |     6  *  tree. An additional intellectual property rights grant can be found | 
|     7  *  in the file PATENTS.  All contributing project authors may |     7  *  in the file PATENTS.  All contributing project authors may | 
|     8  *  be found in the AUTHORS file in the root of the source tree. |     8  *  be found in the AUTHORS file in the root of the source tree. | 
|     9  */ |     9  */ | 
|    10  |    10  | 
|    11 #include <limits> |    11 #include <limits> | 
|    12 #include <utility> |    12 #include <utility> | 
|    13  |    13  | 
|    14 #include "webrtc/api/video/i420_buffer.h" |    14 #include "webrtc/api/video/i420_buffer.h" | 
|    15 #include "webrtc/base/logging.h" |    15 #include "webrtc/base/logging.h" | 
 |    16 #include "webrtc/media/base/videoadapter.h" | 
|    16 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h" |    17 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h" | 
|    17 #include "webrtc/system_wrappers/include/metrics_default.h" |    18 #include "webrtc/system_wrappers/include/metrics_default.h" | 
|    18 #include "webrtc/system_wrappers/include/sleep.h" |    19 #include "webrtc/system_wrappers/include/sleep.h" | 
|    19 #include "webrtc/test/encoder_settings.h" |    20 #include "webrtc/test/encoder_settings.h" | 
|    20 #include "webrtc/test/fake_encoder.h" |    21 #include "webrtc/test/fake_encoder.h" | 
|    21 #include "webrtc/test/frame_generator.h" |    22 #include "webrtc/test/frame_generator.h" | 
|    22 #include "webrtc/test/gmock.h" |    23 #include "webrtc/test/gmock.h" | 
|    23 #include "webrtc/test/gtest.h" |    24 #include "webrtc/test/gtest.h" | 
|    24 #include "webrtc/video/send_statistics_proxy.h" |    25 #include "webrtc/video/send_statistics_proxy.h" | 
|    25 #include "webrtc/video/vie_encoder.h" |    26 #include "webrtc/video/vie_encoder.h" | 
|    26  |    27  | 
|    27 namespace { |    28 namespace { | 
|    28 #if defined(WEBRTC_ANDROID) |    29 #if defined(WEBRTC_ANDROID) | 
|    29 // TODO(kthelgason): Lower this limit when better testing |    30 // TODO(kthelgason): Lower this limit when better testing | 
|    30 // on MediaCodec and fallback implementations are in place. |    31 // on MediaCodec and fallback implementations are in place. | 
|    31 const int kMinPixelsPerFrame = 320 * 180; |    32 const int kMinPixelsPerFrame = 320 * 180; | 
|    32 #else |    33 #else | 
|    33 const int kMinPixelsPerFrame = 120 * 90; |    34 const int kMinPixelsPerFrame = 120 * 90; | 
|    34 #endif |    35 #endif | 
|    35 } |    36 } | 
|    36  |    37  | 
|    37 namespace webrtc { |    38 namespace webrtc { | 
|    38  |    39  | 
|    39 using DegredationPreference = VideoSendStream::DegradationPreference; |    40 using DegredationPreference = VideoSendStream::DegradationPreference; | 
|    40 using ScaleReason = ScalingObserverInterface::ScaleReason; |    41 using ScaleReason = AdaptationObserverInterface::AdaptReason; | 
|    41 using ::testing::_; |    42 using ::testing::_; | 
|    42 using ::testing::Return; |    43 using ::testing::Return; | 
|    43  |    44  | 
|    44 namespace { |    45 namespace { | 
|    45 const size_t kMaxPayloadLength = 1440; |    46 const size_t kMaxPayloadLength = 1440; | 
|    46 const int kTargetBitrateBps = 100000; |    47 const int kTargetBitrateBps = 100000; | 
|    47  |    48  | 
|    48 class TestBuffer : public webrtc::I420Buffer { |    49 class TestBuffer : public webrtc::I420Buffer { | 
|    49  public: |    50  public: | 
|    50   TestBuffer(rtc::Event* event, int width, int height) |    51   TestBuffer(rtc::Event* event, int width, int height) | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|    62 class ViEEncoderUnderTest : public ViEEncoder { |    63 class ViEEncoderUnderTest : public ViEEncoder { | 
|    63  public: |    64  public: | 
|    64   ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy, |    65   ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy, | 
|    65                       const VideoSendStream::Config::EncoderSettings& settings) |    66                       const VideoSendStream::Config::EncoderSettings& settings) | 
|    66       : ViEEncoder(1 /* number_of_cores */, |    67       : ViEEncoder(1 /* number_of_cores */, | 
|    67                    stats_proxy, |    68                    stats_proxy, | 
|    68                    settings, |    69                    settings, | 
|    69                    nullptr /* pre_encode_callback */, |    70                    nullptr /* pre_encode_callback */, | 
|    70                    nullptr /* encoder_timing */) {} |    71                    nullptr /* encoder_timing */) {} | 
|    71  |    72  | 
|    72   void PostTaskAndWait(bool down, ScaleReason reason) { |    73   void PostTaskAndWait(bool down, AdaptReason reason) { | 
|    73     rtc::Event event(false, false); |    74     rtc::Event event(false, false); | 
|    74     encoder_queue()->PostTask([this, &event, reason, down] { |    75     encoder_queue()->PostTask([this, &event, reason, down] { | 
|    75       down ? ScaleDown(reason) : ScaleUp(reason); |    76       down ? AdaptDown(reason) : AdaptUp(reason); | 
|    76       event.Set(); |    77       event.Set(); | 
|    77     }); |    78     }); | 
|    78     RTC_DCHECK(event.Wait(5000)); |    79     RTC_DCHECK(event.Wait(5000)); | 
|    79   } |    80   } | 
|    80  |    81  | 
|    81   void TriggerCpuOveruse() { PostTaskAndWait(true, ScaleReason::kCpu); } |    82   void TriggerCpuOveruse() { PostTaskAndWait(true, AdaptReason::kCpu); } | 
|    82  |    83  | 
|    83   void TriggerCpuNormalUsage() { PostTaskAndWait(false, ScaleReason::kCpu); } |    84   void TriggerCpuNormalUsage() { PostTaskAndWait(false, AdaptReason::kCpu); } | 
|    84  |    85  | 
|    85   void TriggerQualityLow() { PostTaskAndWait(true, ScaleReason::kQuality); } |    86   void TriggerQualityLow() { PostTaskAndWait(true, AdaptReason::kQuality); } | 
|    86  |    87  | 
|    87   void TriggerQualityHigh() { PostTaskAndWait(false, ScaleReason::kQuality); } |    88   void TriggerQualityHigh() { PostTaskAndWait(false, AdaptReason::kQuality); } | 
|    88 }; |    89 }; | 
|    89  |    90  | 
|    90 class VideoStreamFactory |    91 class VideoStreamFactory | 
|    91     : public VideoEncoderConfig::VideoStreamFactoryInterface { |    92     : public VideoEncoderConfig::VideoStreamFactoryInterface { | 
|    92  public: |    93  public: | 
|    93   explicit VideoStreamFactory(size_t num_temporal_layers) |    94   explicit VideoStreamFactory(size_t num_temporal_layers) | 
|    94       : num_temporal_layers_(num_temporal_layers) { |    95       : num_temporal_layers_(num_temporal_layers) { | 
|    95     EXPECT_GT(num_temporal_layers, 0u); |    96     EXPECT_GT(num_temporal_layers, 0u); | 
|    96   } |    97   } | 
|    97  |    98  | 
|    98  private: |    99  private: | 
|    99   std::vector<VideoStream> CreateEncoderStreams( |   100   std::vector<VideoStream> CreateEncoderStreams( | 
|   100       int width, |   101       int width, | 
|   101       int height, |   102       int height, | 
|   102       const VideoEncoderConfig& encoder_config) override { |   103       const VideoEncoderConfig& encoder_config) override { | 
|   103     std::vector<VideoStream> streams = |   104     std::vector<VideoStream> streams = | 
|   104         test::CreateVideoStreams(width, height, encoder_config); |   105         test::CreateVideoStreams(width, height, encoder_config); | 
|   105     for (VideoStream& stream : streams) { |   106     for (VideoStream& stream : streams) { | 
|   106       stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1); |   107       stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1); | 
|   107     } |   108     } | 
|   108     return streams; |   109     return streams; | 
|   109   } |   110   } | 
|   110   const size_t num_temporal_layers_; |   111   const size_t num_temporal_layers_; | 
|   111 }; |   112 }; | 
|   112  |   113  | 
 |   114 class AdaptingFrameForwarder : public test::FrameForwarder { | 
 |   115  public: | 
 |   116   AdaptingFrameForwarder() : adaptation_enabled_(false) {} | 
 |   117   virtual ~AdaptingFrameForwarder() {} | 
 |   118  | 
 |   119   void set_adaptation_enabled(bool enabled) { | 
 |   120     rtc::CritScope cs(&crit_); | 
 |   121     adaptation_enabled_ = enabled; | 
 |   122   } | 
 |   123  | 
 |   124   bool adaption_enabled() { | 
 |   125     rtc::CritScope cs(&crit_); | 
 |   126     return adaptation_enabled_; | 
 |   127   } | 
 |   128  | 
 |   129   void IncomingCapturedFrame(const VideoFrame& video_frame) override { | 
 |   130     int cropped_width = 0; | 
 |   131     int cropped_height = 0; | 
 |   132     int out_width = 0; | 
 |   133     int out_height = 0; | 
 |   134     if (adaption_enabled() && | 
 |   135         adapter_.AdaptFrameResolution(video_frame.width(), video_frame.height(), | 
 |   136                                       video_frame.timestamp_us() * 1000, | 
 |   137                                       &cropped_width, &cropped_height, | 
 |   138                                       &out_width, &out_height)) { | 
 |   139       VideoFrame adapted_frame( | 
 |   140           new rtc::RefCountedObject<TestBuffer>(nullptr, out_width, out_height), | 
 |   141           99, 99, kVideoRotation_0); | 
 |   142       adapted_frame.set_ntp_time_ms(video_frame.ntp_time_ms()); | 
 |   143       test::FrameForwarder::IncomingCapturedFrame(adapted_frame); | 
 |   144     } else { | 
 |   145       test::FrameForwarder::IncomingCapturedFrame(video_frame); | 
 |   146     } | 
 |   147   } | 
 |   148  | 
 |   149   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink, | 
 |   150                        const rtc::VideoSinkWants& wants) override { | 
 |   151     rtc::CritScope cs(&crit_); | 
 |   152     adapter_.OnResolutionRequest(wants.max_pixel_count, | 
 |   153                                  wants.max_pixel_count_step_up); | 
 |   154     test::FrameForwarder::AddOrUpdateSink(sink, wants); | 
 |   155   } | 
 |   156  | 
 |   157   cricket::VideoAdapter adapter_; | 
 |   158   bool adaptation_enabled_ GUARDED_BY(crit_); | 
 |   159 }; | 
|   113 }  // namespace |   160 }  // namespace | 
|   114  |   161  | 
|   115 class ViEEncoderTest : public ::testing::Test { |   162 class ViEEncoderTest : public ::testing::Test { | 
|   116  public: |   163  public: | 
|   117   static const int kDefaultTimeoutMs = 30 * 1000; |   164   static const int kDefaultTimeoutMs = 30 * 1000; | 
|   118  |   165  | 
|   119   ViEEncoderTest() |   166   ViEEncoderTest() | 
|   120       : video_send_config_(VideoSendStream::Config(nullptr)), |   167       : video_send_config_(VideoSendStream::Config(nullptr)), | 
|   121         codec_width_(320), |   168         codec_width_(320), | 
|   122         codec_height_(240), |   169         codec_height_(240), | 
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   251   class TestSink : public ViEEncoder::EncoderSink { |   298   class TestSink : public ViEEncoder::EncoderSink { | 
|   252    public: |   299    public: | 
|   253     explicit TestSink(TestEncoder* test_encoder) |   300     explicit TestSink(TestEncoder* test_encoder) | 
|   254         : test_encoder_(test_encoder), encoded_frame_event_(false, false) {} |   301         : test_encoder_(test_encoder), encoded_frame_event_(false, false) {} | 
|   255  |   302  | 
|   256     void WaitForEncodedFrame(int64_t expected_ntp_time) { |   303     void WaitForEncodedFrame(int64_t expected_ntp_time) { | 
|   257       uint32_t timestamp = 0; |   304       uint32_t timestamp = 0; | 
|   258       EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs)); |   305       EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs)); | 
|   259       { |   306       { | 
|   260         rtc::CritScope lock(&crit_); |   307         rtc::CritScope lock(&crit_); | 
|   261         timestamp = timestamp_; |   308         timestamp = last_timestamp_; | 
|   262       } |   309       } | 
|   263       test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp); |   310       test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp); | 
|   264     } |   311     } | 
|   265  |   312  | 
 |   313     void WaitForEncodedFrame(uint32_t expected_width, | 
 |   314                              uint32_t expected_height) { | 
 |   315       uint32_t width = 0; | 
 |   316       uint32_t height = 0; | 
 |   317       EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs)); | 
 |   318       { | 
 |   319         rtc::CritScope lock(&crit_); | 
 |   320         width = last_width_; | 
 |   321         height = last_height_; | 
 |   322       } | 
 |   323       EXPECT_EQ(expected_height, height); | 
 |   324       EXPECT_EQ(expected_width, width); | 
 |   325     } | 
 |   326  | 
|   266     void SetExpectNoFrames() { |   327     void SetExpectNoFrames() { | 
|   267       rtc::CritScope lock(&crit_); |   328       rtc::CritScope lock(&crit_); | 
|   268       expect_frames_ = false; |   329       expect_frames_ = false; | 
|   269     } |   330     } | 
|   270  |   331  | 
|   271     int number_of_reconfigurations() { |   332     int number_of_reconfigurations() { | 
|   272       rtc::CritScope lock(&crit_); |   333       rtc::CritScope lock(&crit_); | 
|   273       return number_of_reconfigurations_; |   334       return number_of_reconfigurations_; | 
|   274     } |   335     } | 
|   275  |   336  | 
|   276     int last_min_transmit_bitrate() { |   337     int last_min_transmit_bitrate() { | 
|   277       rtc::CritScope lock(&crit_); |   338       rtc::CritScope lock(&crit_); | 
|   278       return min_transmit_bitrate_bps_; |   339       return min_transmit_bitrate_bps_; | 
|   279     } |   340     } | 
|   280  |   341  | 
|   281    private: |   342    private: | 
|   282     Result OnEncodedImage( |   343     Result OnEncodedImage( | 
|   283         const EncodedImage& encoded_image, |   344         const EncodedImage& encoded_image, | 
|   284         const CodecSpecificInfo* codec_specific_info, |   345         const CodecSpecificInfo* codec_specific_info, | 
|   285         const RTPFragmentationHeader* fragmentation) override { |   346         const RTPFragmentationHeader* fragmentation) override { | 
|   286       rtc::CritScope lock(&crit_); |   347       rtc::CritScope lock(&crit_); | 
|   287       EXPECT_TRUE(expect_frames_); |   348       EXPECT_TRUE(expect_frames_); | 
|   288       timestamp_ = encoded_image._timeStamp; |   349       last_timestamp_ = encoded_image._timeStamp; | 
 |   350       last_width_ = encoded_image._encodedWidth; | 
 |   351       last_height_ = encoded_image._encodedHeight; | 
|   289       encoded_frame_event_.Set(); |   352       encoded_frame_event_.Set(); | 
|   290       return Result(Result::OK, timestamp_); |   353       return Result(Result::OK, last_timestamp_); | 
|   291     } |   354     } | 
|   292  |   355  | 
|   293     void OnEncoderConfigurationChanged(std::vector<VideoStream> streams, |   356     void OnEncoderConfigurationChanged(std::vector<VideoStream> streams, | 
|   294                                        int min_transmit_bitrate_bps) override { |   357                                        int min_transmit_bitrate_bps) override { | 
|   295       rtc::CriticalSection crit_; |   358       rtc::CriticalSection crit_; | 
|   296       ++number_of_reconfigurations_; |   359       ++number_of_reconfigurations_; | 
|   297       min_transmit_bitrate_bps_ = min_transmit_bitrate_bps; |   360       min_transmit_bitrate_bps_ = min_transmit_bitrate_bps; | 
|   298     } |   361     } | 
|   299  |   362  | 
|   300     rtc::CriticalSection crit_; |   363     rtc::CriticalSection crit_; | 
|   301     TestEncoder* test_encoder_; |   364     TestEncoder* test_encoder_; | 
|   302     rtc::Event encoded_frame_event_; |   365     rtc::Event encoded_frame_event_; | 
|   303     uint32_t timestamp_ = 0; |   366     uint32_t last_timestamp_ = 0; | 
 |   367     uint32_t last_height_ = 0; | 
 |   368     uint32_t last_width_ = 0; | 
|   304     bool expect_frames_ = true; |   369     bool expect_frames_ = true; | 
|   305     int number_of_reconfigurations_ = 0; |   370     int number_of_reconfigurations_ = 0; | 
|   306     int min_transmit_bitrate_bps_ = 0; |   371     int min_transmit_bitrate_bps_ = 0; | 
|   307   }; |   372   }; | 
|   308  |   373  | 
|   309   VideoSendStream::Config video_send_config_; |   374   VideoSendStream::Config video_send_config_; | 
|   310   VideoEncoderConfig video_encoder_config_; |   375   VideoEncoderConfig video_encoder_config_; | 
|   311   int codec_width_; |   376   int codec_width_; | 
|   312   int codec_height_; |   377   int codec_height_; | 
|   313   TestEncoder fake_encoder_; |   378   TestEncoder fake_encoder_; | 
|   314   std::unique_ptr<SendStatisticsProxy> stats_proxy_; |   379   std::unique_ptr<SendStatisticsProxy> stats_proxy_; | 
|   315   TestSink sink_; |   380   TestSink sink_; | 
|   316   test::FrameForwarder video_source_; |   381   AdaptingFrameForwarder video_source_; | 
|   317   std::unique_ptr<ViEEncoderUnderTest> vie_encoder_; |   382   std::unique_ptr<ViEEncoderUnderTest> vie_encoder_; | 
|   318 }; |   383 }; | 
|   319  |   384  | 
|   320 TEST_F(ViEEncoderTest, EncodeOneFrame) { |   385 TEST_F(ViEEncoderTest, EncodeOneFrame) { | 
|   321   vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |   386   vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 
|   322   rtc::Event frame_destroyed_event(false, false); |   387   rtc::Event frame_destroyed_event(false, false); | 
|   323   video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); |   388   video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); | 
|   324   sink_.WaitForEncodedFrame(1); |   389   sink_.WaitForEncodedFrame(1); | 
|   325   EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs)); |   390   EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs)); | 
|   326   vie_encoder_->Stop(); |   391   vie_encoder_->Stop(); | 
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1022   SleepMs(kProcessIntervalMs + 1000 / kDefaultFps); |  1087   SleepMs(kProcessIntervalMs + 1000 / kDefaultFps); | 
|  1023   EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate)) |  1088   EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate)) | 
|  1024       .Times(1); |  1089       .Times(1); | 
|  1025   video_source_.IncomingCapturedFrame(CreateFrame( |  1090   video_source_.IncomingCapturedFrame(CreateFrame( | 
|  1026       kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_)); |  1091       kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_)); | 
|  1027   sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs); |  1092   sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs); | 
|  1028  |  1093  | 
|  1029   vie_encoder_->Stop(); |  1094   vie_encoder_->Stop(); | 
|  1030 } |  1095 } | 
|  1031  |  1096  | 
 |  1097 // TODO(sprang): Extend this with fps throttling and any "balanced" extensions. | 
 |  1098 TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) { | 
 |  1099   vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 
 |  1100  | 
 |  1101   const int kFrameWidth = 1280; | 
 |  1102   const int kFrameHeight = 720; | 
 |  1103   // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as | 
 |  1104   // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan(). | 
 |  1105   video_source_.set_adaptation_enabled(true); | 
 |  1106  | 
 |  1107   video_source_.IncomingCapturedFrame( | 
 |  1108       CreateFrame(1, kFrameWidth, kFrameHeight)); | 
 |  1109   sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight); | 
 |  1110  | 
 |  1111   // Trigger CPU overuse, downscale by 3/4. | 
 |  1112   vie_encoder_->TriggerCpuOveruse(); | 
 |  1113   video_source_.IncomingCapturedFrame( | 
 |  1114       CreateFrame(2, kFrameWidth, kFrameHeight)); | 
 |  1115   sink_.WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4); | 
 |  1116  | 
 |  1117   // Trigger CPU normal use, return to original resoluton; | 
 |  1118   vie_encoder_->TriggerCpuNormalUsage(); | 
 |  1119   video_source_.IncomingCapturedFrame( | 
 |  1120       CreateFrame(3, kFrameWidth, kFrameHeight)); | 
 |  1121   sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight); | 
 |  1122  | 
 |  1123   vie_encoder_->Stop(); | 
 |  1124 } | 
 |  1125  | 
|  1032 }  // namespace webrtc |  1126 }  // namespace webrtc | 
| OLD | NEW |