blob: a0fa2df74594f38f0603b4153b1b67ff57d64943 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
stefan@webrtc.org07b45a52012-02-02 08:37:48 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
mflodmancc3d4422017-08-03 08:27:51 -070011#ifndef WEBRTC_VIDEO_VIDEO_STREAM_ENCODER_H_
12#define WEBRTC_VIDEO_VIDEO_STREAM_ENCODER_H_
niklase@google.com470e71d2011-07-07 08:21:25 +000013
sprangc5d62e22017-04-02 23:53:04 -070014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
perkj376b1922016-05-02 11:35:24 -070016#include <string>
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000017#include <vector>
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +000018
nisseaf916892017-01-10 07:44:26 -080019#include "webrtc/api/video/video_rotation.h"
ilnikd60d06a2017-04-05 03:02:20 -070020#include "webrtc/api/video_codecs/video_encoder.h"
ossuf515ab82016-12-07 04:52:58 -080021#include "webrtc/call/call.h"
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000022#include "webrtc/common_types.h"
Erik Språng08127a92016-11-16 16:41:30 +010023#include "webrtc/common_video/include/video_bitrate_allocator.h"
nissed30a1112016-04-18 05:15:22 -070024#include "webrtc/media/base/videosinkinterface.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010025#include "webrtc/modules/video_coding/include/video_coding_defines.h"
kthelgason876222f2016-11-29 01:44:11 -080026#include "webrtc/modules/video_coding/utility/quality_scaler.h"
Peter Boströmcd5c25c2016-04-21 16:48:08 +020027#include "webrtc/modules/video_coding/video_coding_impl.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020028#include "webrtc/rtc_base/criticalsection.h"
29#include "webrtc/rtc_base/event.h"
30#include "webrtc/rtc_base/sequenced_task_checker.h"
31#include "webrtc/rtc_base/task_queue.h"
perkj26091b12016-09-01 01:17:40 -070032#include "webrtc/system_wrappers/include/atomic32.h"
ossuf515ab82016-12-07 04:52:58 -080033#include "webrtc/typedefs.h"
perkj26091b12016-09-01 01:17:40 -070034#include "webrtc/video/overuse_frame_detector.h"
mbonadei52127002017-08-28 06:46:48 -070035#include "webrtc/call/video_send_stream.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000036
37namespace webrtc {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000038
niklase@google.com470e71d2011-07-07 08:21:25 +000039class ProcessThread;
pbos@webrtc.org273a4142014-12-01 15:23:21 +000040class SendStatisticsProxy;
sprang1a646ee2016-12-01 06:34:11 -080041class VideoBitrateAllocationObserver;
niklase@google.com470e71d2011-07-07 08:21:25 +000042
mflodmancc3d4422017-08-03 08:27:51 -070043// VideoStreamEncoder represent a video encoder that accepts raw video frames as
44// input and produces an encoded bit stream.
perkjbc75d972016-05-02 06:31:25 -070045// Usage:
perkj26091b12016-09-01 01:17:40 -070046// Instantiate.
perkja49cbd32016-09-16 07:53:41 -070047// Call SetSink.
48// Call SetSource.
perkj26091b12016-09-01 01:17:40 -070049// Call ConfigureEncoder with the codec settings.
perkj26091b12016-09-01 01:17:40 -070050// Call Stop() when done.
mflodmancc3d4422017-08-03 08:27:51 -070051class VideoStreamEncoder : public rtc::VideoSinkInterface<VideoFrame>,
52 public EncodedImageCallback,
53 public VCMSendStatisticsCallback,
54 public AdaptationObserverInterface {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000055 public:
Per512ecb32016-09-23 15:52:06 +020056 // Interface for receiving encoded video frames and notifications about
57 // configuration changes.
58 class EncoderSink : public EncodedImageCallback {
59 public:
60 virtual void OnEncoderConfigurationChanged(
61 std::vector<VideoStream> streams,
62 int min_transmit_bitrate_bps) = 0;
63 };
64
asapersson09f05612017-05-15 23:40:18 -070065 // Number of resolution and framerate reductions (-1: disabled).
66 struct AdaptCounts {
67 int resolution = 0;
68 int fps = 0;
69 };
70
kthelgason876222f2016-11-29 01:44:11 -080071 // Downscale resolution at most 2 times for CPU reasons.
sprangc5d62e22017-04-02 23:53:04 -070072 static const int kMaxCpuResolutionDowngrades = 2;
73 // Downscale framerate at most 4 times.
74 static const int kMaxCpuFramerateDowngrades = 4;
perkj803d97f2016-11-01 11:45:46 -070075
mflodmancc3d4422017-08-03 08:27:51 -070076 VideoStreamEncoder(uint32_t number_of_cores,
77 SendStatisticsProxy* stats_proxy,
78 const VideoSendStream::Config::EncoderSettings& settings,
79 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback,
80 EncodedFrameObserver* encoder_timing,
81 std::unique_ptr<OveruseFrameDetector> overuse_detector);
82 ~VideoStreamEncoder();
perkj26091b12016-09-01 01:17:40 -070083 // RegisterProcessThread register |module_process_thread| with those objects
84 // that use it. Registration has to happen on the thread where
85 // |module_process_thread| was created (libjingle's worker thread).
86 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue.
87 void RegisterProcessThread(ProcessThread* module_process_thread);
88 void DeRegisterProcessThread();
niklase@google.com470e71d2011-07-07 08:21:25 +000089
perkj803d97f2016-11-01 11:45:46 -070090 // Sets the source that will provide I420 video frames.
91 // |degradation_preference| control whether or not resolution or frame rate
92 // may be reduced.
93 void SetSource(
94 rtc::VideoSourceInterface<VideoFrame>* source,
95 const VideoSendStream::DegradationPreference& degradation_preference);
96
97 // Sets the |sink| that gets the encoded frames. |rotation_applied| means
98 // that the source must support rotation. Only set |rotation_applied| if the
99 // remote side does not support the rotation extension.
100 void SetSink(EncoderSink* sink, bool rotation_applied);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000101
perkj26091b12016-09-01 01:17:40 -0700102 // TODO(perkj): Can we remove VideoCodec.startBitrate ?
103 void SetStartBitrate(int start_bitrate_bps);
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000104
sprang1a646ee2016-12-01 06:34:11 -0800105 void SetBitrateObserver(VideoBitrateAllocationObserver* bitrate_observer);
106
Per512ecb32016-09-23 15:52:06 +0200107 void ConfigureEncoder(VideoEncoderConfig config,
asapersson5f7226f2016-11-25 04:37:00 -0800108 size_t max_data_payload_length,
109 bool nack_enabled);
niklase@google.com470e71d2011-07-07 08:21:25 +0000110
perkj26091b12016-09-01 01:17:40 -0700111 // Permanently stop encoding. After this method has returned, it is
112 // guaranteed that no encoded frames will be delivered to the sink.
113 void Stop();
114
Peter Boström233bfd22016-01-18 20:23:40 +0100115 void SendKeyFrame();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000116
Peter Boström0013dcc2016-02-19 20:42:19 +0100117 // virtual to test EncoderStateFeedback with mocks.
perkj600246e2016-05-04 11:26:51 -0700118 virtual void OnReceivedIntraFrameRequest(size_t stream_index);
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +0000119
mflodman86aabb22016-03-11 15:44:32 +0100120 void OnBitrateUpdated(uint32_t bitrate_bps,
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000121 uint8_t fraction_lost,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000122 int64_t round_trip_time_ms);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000123
perkj803d97f2016-11-01 11:45:46 -0700124 protected:
kthelgason876222f2016-11-29 01:44:11 -0800125 // Used for testing. For example the |ScalingObserverInterface| methods must
126 // be called on |encoder_queue_|.
perkj803d97f2016-11-01 11:45:46 -0700127 rtc::TaskQueue* encoder_queue() { return &encoder_queue_; }
128
kthelgason876222f2016-11-29 01:44:11 -0800129 // webrtc::ScalingObserverInterface implementation.
perkj803d97f2016-11-01 11:45:46 -0700130 // These methods are protected for easier testing.
sprangb1ca0732017-02-01 08:38:12 -0800131 void AdaptUp(AdaptReason reason) override;
132 void AdaptDown(AdaptReason reason) override;
sprangfda496a2017-06-15 04:21:07 -0700133 static CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time);
perkj803d97f2016-11-01 11:45:46 -0700134
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000135 private:
Pera48ddb72016-09-29 11:48:50 +0200136 class ConfigureEncoderTask;
perkj26091b12016-09-01 01:17:40 -0700137 class EncodeTask;
perkja49cbd32016-09-16 07:53:41 -0700138 class VideoSourceProxy;
perkj26091b12016-09-01 01:17:40 -0700139
kthelgason93f16d72017-01-16 06:15:23 -0800140 class VideoFrameInfo {
141 public:
perkjfa10b552016-10-02 23:45:26 -0700142 VideoFrameInfo(int width,
143 int height,
perkjfa10b552016-10-02 23:45:26 -0700144 bool is_texture)
145 : width(width),
146 height(height),
perkjfa10b552016-10-02 23:45:26 -0700147 is_texture(is_texture) {}
148 int width;
149 int height;
perkjfa10b552016-10-02 23:45:26 -0700150 bool is_texture;
kthelgason93f16d72017-01-16 06:15:23 -0800151 int pixel_count() const { return width * height; }
perkjfa10b552016-10-02 23:45:26 -0700152 };
153
Pera48ddb72016-09-29 11:48:50 +0200154 void ConfigureEncoderOnTaskQueue(VideoEncoderConfig config,
asapersson5f7226f2016-11-25 04:37:00 -0800155 size_t max_data_payload_length,
156 bool nack_enabled);
perkjfa10b552016-10-02 23:45:26 -0700157 void ReconfigureEncoder();
perkj26091b12016-09-01 01:17:40 -0700158
kthelgason2bc68642017-02-07 07:02:22 -0800159 void ConfigureQualityScaler();
160
perkja49cbd32016-09-16 07:53:41 -0700161 // Implements VideoSinkInterface.
162 void OnFrame(const VideoFrame& video_frame) override;
163
perkj26091b12016-09-01 01:17:40 -0700164 // Implements VideoSendStatisticsCallback.
165 void SendStatistics(uint32_t bit_rate,
166 uint32_t frame_rate) override;
167
perkjd52063f2016-09-07 06:32:18 -0700168 void EncodeVideoFrame(const VideoFrame& frame,
169 int64_t time_when_posted_in_ms);
perkj26091b12016-09-01 01:17:40 -0700170
171 // Implements EncodedImageCallback.
172 EncodedImageCallback::Result OnEncodedImage(
173 const EncodedImage& encoded_image,
174 const CodecSpecificInfo* codec_specific_info,
175 const RTPFragmentationHeader* fragmentation) override;
176
kthelgason876222f2016-11-29 01:44:11 -0800177 void OnDroppedFrame() override;
178
perkj26091b12016-09-01 01:17:40 -0700179 bool EncoderPaused() const;
180 void TraceFrameDropStart();
181 void TraceFrameDropEnd();
182
asapersson09f05612017-05-15 23:40:18 -0700183 // Class holding adaptation information.
184 class AdaptCounter final {
185 public:
186 AdaptCounter();
187 ~AdaptCounter();
188
189 // Get number of adaptation downscales for |reason|.
190 AdaptCounts Counts(int reason) const;
191
192 std::string ToString() const;
193
asaperssonf7e294d2017-06-13 23:25:22 -0700194 void IncrementFramerate(int reason);
195 void IncrementResolution(int reason);
196 void DecrementFramerate(int reason);
197 void DecrementResolution(int reason);
198 void DecrementFramerate(int reason, int cur_fps);
asapersson09f05612017-05-15 23:40:18 -0700199
200 // Gets the total number of downgrades (for all adapt reasons).
201 int FramerateCount() const;
202 int ResolutionCount() const;
asapersson09f05612017-05-15 23:40:18 -0700203
204 // Gets the total number of downgrades for |reason|.
205 int FramerateCount(int reason) const;
206 int ResolutionCount(int reason) const;
207 int TotalCount(int reason) const;
208
209 private:
210 std::string ToString(const std::vector<int>& counters) const;
211 int Count(const std::vector<int>& counters) const;
asaperssonf7e294d2017-06-13 23:25:22 -0700212 void MoveCount(std::vector<int>* counters, int from_reason);
asapersson09f05612017-05-15 23:40:18 -0700213
214 // Degradation counters holding number of framerate/resolution reductions
215 // per adapt reason.
216 std::vector<int> fps_counters_;
217 std::vector<int> resolution_counters_;
218 };
219
danilchapa37de392017-09-09 04:17:22 -0700220 AdaptCounter& GetAdaptCounter() RTC_RUN_ON(&encoder_queue_);
221 const AdaptCounter& GetConstAdaptCounter() RTC_RUN_ON(&encoder_queue_);
222 void UpdateAdaptationStats(AdaptReason reason) RTC_RUN_ON(&encoder_queue_);
223 AdaptCounts GetActiveCounts(AdaptReason reason) RTC_RUN_ON(&encoder_queue_);
sprangc5d62e22017-04-02 23:53:04 -0700224
perkj26091b12016-09-01 01:17:40 -0700225 rtc::Event shutdown_event_;
stefan@webrtc.orgbfacda62013-03-27 16:36:01 +0000226
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000227 const uint32_t number_of_cores_;
kthelgason2bc68642017-02-07 07:02:22 -0800228 // Counts how many frames we've dropped in the initial rampup phase.
229 int initial_rampup_;
perkja49cbd32016-09-16 07:53:41 -0700230
231 const std::unique_ptr<VideoSourceProxy> source_proxy_;
Per512ecb32016-09-23 15:52:06 +0200232 EncoderSink* sink_;
perkj26091b12016-09-01 01:17:40 -0700233 const VideoSendStream::Config::EncoderSettings settings_;
Pera48ddb72016-09-29 11:48:50 +0200234 const VideoCodecType codec_type_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000235
danilchapa37de392017-09-09 04:17:22 -0700236 vcm::VideoSender video_sender_ RTC_ACCESS_ON(&encoder_queue_);
sprangfda496a2017-06-15 04:21:07 -0700237 std::unique_ptr<OveruseFrameDetector> overuse_detector_
danilchapa37de392017-09-09 04:17:22 -0700238 RTC_ACCESS_ON(&encoder_queue_);
239 std::unique_ptr<QualityScaler> quality_scaler_ RTC_ACCESS_ON(&encoder_queue_);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000240
Peter Boström7083e112015-09-22 16:28:51 +0200241 SendStatisticsProxy* const stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700242 rtc::VideoSinkInterface<VideoFrame>* const pre_encode_callback_;
Peter Boström7083e112015-09-22 16:28:51 +0200243 ProcessThread* module_process_thread_;
perkj26091b12016-09-01 01:17:40 -0700244 rtc::ThreadChecker module_process_thread_checker_;
perkja49cbd32016-09-16 07:53:41 -0700245 // |thread_checker_| checks that public methods that are related to lifetime
mflodmancc3d4422017-08-03 08:27:51 -0700246 // of VideoStreamEncoder are called on the same thread.
perkja49cbd32016-09-16 07:53:41 -0700247 rtc::ThreadChecker thread_checker_;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000248
danilchapa37de392017-09-09 04:17:22 -0700249 VideoEncoderConfig encoder_config_ RTC_ACCESS_ON(&encoder_queue_);
Erik Språng08127a92016-11-16 16:41:30 +0100250 std::unique_ptr<VideoBitrateAllocator> rate_allocator_
danilchapa37de392017-09-09 04:17:22 -0700251 RTC_ACCESS_ON(&encoder_queue_);
sprangfda496a2017-06-15 04:21:07 -0700252 // The maximum frame rate of the current codec configuration, as determined
253 // at the last ReconfigureEncoder() call.
danilchapa37de392017-09-09 04:17:22 -0700254 int max_framerate_ RTC_ACCESS_ON(&encoder_queue_);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000255
perkjfa10b552016-10-02 23:45:26 -0700256 // Set when ConfigureEncoder has been called in order to lazy reconfigure the
257 // encoder on the next frame.
danilchapa37de392017-09-09 04:17:22 -0700258 bool pending_encoder_reconfiguration_ RTC_ACCESS_ON(&encoder_queue_);
259 rtc::Optional<VideoFrameInfo> last_frame_info_ RTC_ACCESS_ON(&encoder_queue_);
260 int crop_width_ RTC_ACCESS_ON(&encoder_queue_);
261 int crop_height_ RTC_ACCESS_ON(&encoder_queue_);
262 uint32_t encoder_start_bitrate_bps_ RTC_ACCESS_ON(&encoder_queue_);
263 size_t max_data_payload_length_ RTC_ACCESS_ON(&encoder_queue_);
264 bool nack_enabled_ RTC_ACCESS_ON(&encoder_queue_);
265 uint32_t last_observed_bitrate_bps_ RTC_ACCESS_ON(&encoder_queue_);
266 bool encoder_paused_and_dropped_frame_ RTC_ACCESS_ON(&encoder_queue_);
perkj26091b12016-09-01 01:17:40 -0700267 Clock* const clock_;
asapersson09f05612017-05-15 23:40:18 -0700268 // Counters used for deciding if the video resolution or framerate is
269 // currently restricted, and if so, why, on a per degradation preference
270 // basis.
sprangc5d62e22017-04-02 23:53:04 -0700271 // TODO(sprang): Replace this with a state holding a relative overuse measure
272 // instead, that can be translated into suitable down-scale or fps limit.
asapersson09f05612017-05-15 23:40:18 -0700273 std::map<const VideoSendStream::DegradationPreference, AdaptCounter>
danilchapa37de392017-09-09 04:17:22 -0700274 adapt_counters_ RTC_ACCESS_ON(&encoder_queue_);
asapersson09f05612017-05-15 23:40:18 -0700275 // Set depending on degradation preferences.
sprangb1ca0732017-02-01 08:38:12 -0800276 VideoSendStream::DegradationPreference degradation_preference_
danilchapa37de392017-09-09 04:17:22 -0700277 RTC_ACCESS_ON(&encoder_queue_);
perkj803d97f2016-11-01 11:45:46 -0700278
sprang84a37592017-02-10 07:04:27 -0800279 struct AdaptationRequest {
280 // The pixel count produced by the source at the time of the adaptation.
281 int input_pixel_count_;
sprangc5d62e22017-04-02 23:53:04 -0700282 // Framerate received from the source at the time of the adaptation.
283 int framerate_fps_;
sprang84a37592017-02-10 07:04:27 -0800284 // Indicates if request was to adapt up or down.
285 enum class Mode { kAdaptUp, kAdaptDown } mode_;
286 };
287 // Stores a snapshot of the last adaptation request triggered by an AdaptUp
288 // or AdaptDown signal.
289 rtc::Optional<AdaptationRequest> last_adaptation_request_
danilchapa37de392017-09-09 04:17:22 -0700290 RTC_ACCESS_ON(&encoder_queue_);
perkj803d97f2016-11-01 11:45:46 -0700291
292 rtc::RaceChecker incoming_frame_race_checker_
danilchapa37de392017-09-09 04:17:22 -0700293 RTC_GUARDED_BY(incoming_frame_race_checker_);
perkj26091b12016-09-01 01:17:40 -0700294 Atomic32 posted_frames_waiting_for_encode_;
295 // Used to make sure incoming time stamp is increasing for every frame.
danilchapa37de392017-09-09 04:17:22 -0700296 int64_t last_captured_timestamp_ RTC_GUARDED_BY(incoming_frame_race_checker_);
perkj26091b12016-09-01 01:17:40 -0700297 // Delta used for translating between NTP and internal timestamps.
danilchapa37de392017-09-09 04:17:22 -0700298 const int64_t delta_ntp_internal_ms_
299 RTC_GUARDED_BY(incoming_frame_race_checker_);
perkj26091b12016-09-01 01:17:40 -0700300
danilchapa37de392017-09-09 04:17:22 -0700301 int64_t last_frame_log_ms_ RTC_GUARDED_BY(incoming_frame_race_checker_);
302 int captured_frame_count_ RTC_ACCESS_ON(&encoder_queue_);
303 int dropped_frame_count_ RTC_ACCESS_ON(&encoder_queue_);
asapersson6ffb67d2016-09-12 00:10:45 -0700304
danilchapa37de392017-09-09 04:17:22 -0700305 VideoBitrateAllocationObserver* bitrate_observer_
306 RTC_ACCESS_ON(&encoder_queue_);
307 rtc::Optional<int64_t> last_parameters_update_ms_
308 RTC_ACCESS_ON(&encoder_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800309
perkj26091b12016-09-01 01:17:40 -0700310 // All public methods are proxied to |encoder_queue_|. It must must be
311 // destroyed first to make sure no tasks are run that use other members.
312 rtc::TaskQueue encoder_queue_;
perkja49cbd32016-09-16 07:53:41 -0700313
mflodmancc3d4422017-08-03 08:27:51 -0700314 RTC_DISALLOW_COPY_AND_ASSIGN(VideoStreamEncoder);
niklase@google.com470e71d2011-07-07 08:21:25 +0000315};
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000316
317} // namespace webrtc
318
mflodmancc3d4422017-08-03 08:27:51 -0700319#endif // WEBRTC_VIDEO_VIDEO_STREAM_ENCODER_H_