1 /* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 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 11 #ifndef API_VIDEO_CODECS_VIDEO_ENCODER_H_ 12 #define API_VIDEO_CODECS_VIDEO_ENCODER_H_ 13 14 #include <limits> 15 #include <memory> 16 #include <string> 17 #include <vector> 18 19 #include "absl/container/inlined_vector.h" 20 #include "absl/types/optional.h" 21 #include "api/fec_controller_override.h" 22 #include "api/units/data_rate.h" 23 #include "api/video/encoded_image.h" 24 #include "api/video/video_bitrate_allocation.h" 25 #include "api/video/video_codec_constants.h" 26 #include "api/video/video_frame.h" 27 #include "api/video_codecs/video_codec.h" 28 #include "rtc_base/checks.h" 29 #include "rtc_base/system/rtc_export.h" 30 31 namespace webrtc { 32 33 class RTPFragmentationHeader; 34 // TODO(pbos): Expose these through a public (root) header or change these APIs. 35 struct CodecSpecificInfo; 36 37 constexpr int kDefaultMinPixelsPerFrame = 320 * 180; 38 39 class EncodedImageCallback { 40 public: ~EncodedImageCallback()41 virtual ~EncodedImageCallback() {} 42 43 struct Result { 44 enum Error { 45 OK, 46 47 // Failed to send the packet. 48 ERROR_SEND_FAILED, 49 }; 50 ResultResult51 explicit Result(Error error) : error(error) {} ResultResult52 Result(Error error, uint32_t frame_id) : error(error), frame_id(frame_id) {} 53 54 Error error; 55 56 // Frame ID assigned to the frame. The frame ID should be the same as the ID 57 // seen by the receiver for this frame. RTP timestamp of the frame is used 58 // as frame ID when RTP is used to send video. Must be used only when 59 // error=OK. 60 uint32_t frame_id = 0; 61 62 // Tells the encoder that the next frame is should be dropped. 63 bool drop_next_frame = false; 64 }; 65 66 // Used to signal the encoder about reason a frame is dropped. 67 // kDroppedByMediaOptimizations - dropped by MediaOptimizations (for rate 68 // limiting purposes). 69 // kDroppedByEncoder - dropped by encoder's internal rate limiter. 70 enum class DropReason : uint8_t { 71 kDroppedByMediaOptimizations, 72 kDroppedByEncoder 73 }; 74 75 // Callback function which is called when an image has been encoded. 76 virtual Result OnEncodedImage( 77 const EncodedImage& encoded_image, 78 const CodecSpecificInfo* codec_specific_info, 79 const RTPFragmentationHeader* fragmentation) = 0; 80 OnDroppedFrame(DropReason reason)81 virtual void OnDroppedFrame(DropReason reason) {} 82 }; 83 84 class RTC_EXPORT VideoEncoder { 85 public: 86 struct QpThresholds { QpThresholdsQpThresholds87 QpThresholds(int l, int h) : low(l), high(h) {} QpThresholdsQpThresholds88 QpThresholds() : low(-1), high(-1) {} 89 int low; 90 int high; 91 }; 92 93 // Quality scaling is enabled if thresholds are provided. 94 struct RTC_EXPORT ScalingSettings { 95 private: 96 // Private magic type for kOff, implicitly convertible to 97 // ScalingSettings. 98 struct KOff {}; 99 100 public: 101 // TODO(nisse): Would be nicer if kOff were a constant ScalingSettings 102 // rather than a magic value. However, absl::optional is not trivially copy 103 // constructible, and hence a constant ScalingSettings needs a static 104 // initializer, which is strongly discouraged in Chrome. We can hopefully 105 // fix this when we switch to absl::optional or std::optional. 106 static constexpr KOff kOff = {}; 107 108 ScalingSettings(int low, int high); 109 ScalingSettings(int low, int high, int min_pixels); 110 ScalingSettings(const ScalingSettings&); 111 ScalingSettings(KOff); // NOLINT(runtime/explicit) 112 ~ScalingSettings(); 113 114 absl::optional<QpThresholds> thresholds; 115 116 // We will never ask for a resolution lower than this. 117 // TODO(kthelgason): Lower this limit when better testing 118 // on MediaCodec and fallback implementations are in place. 119 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206 120 int min_pixels_per_frame = kDefaultMinPixelsPerFrame; 121 122 private: 123 // Private constructor; to get an object without thresholds, use 124 // the magic constant ScalingSettings::kOff. 125 ScalingSettings(); 126 }; 127 128 // Bitrate limits for resolution. 129 struct ResolutionBitrateLimits { ResolutionBitrateLimitsResolutionBitrateLimits130 ResolutionBitrateLimits(int frame_size_pixels, 131 int min_start_bitrate_bps, 132 int min_bitrate_bps, 133 int max_bitrate_bps) 134 : frame_size_pixels(frame_size_pixels), 135 min_start_bitrate_bps(min_start_bitrate_bps), 136 min_bitrate_bps(min_bitrate_bps), 137 max_bitrate_bps(max_bitrate_bps) {} 138 // Size of video frame, in pixels, the bitrate thresholds are intended for. 139 int frame_size_pixels = 0; 140 // Recommended minimum bitrate to start encoding. 141 int min_start_bitrate_bps = 0; 142 // Recommended minimum bitrate. 143 int min_bitrate_bps = 0; 144 // Recommended maximum bitrate. 145 int max_bitrate_bps = 0; 146 147 bool operator==(const ResolutionBitrateLimits& rhs) const; 148 bool operator!=(const ResolutionBitrateLimits& rhs) const { 149 return !(*this == rhs); 150 } 151 }; 152 153 // Struct containing metadata about the encoder implementing this interface. 154 struct RTC_EXPORT EncoderInfo { 155 static constexpr uint8_t kMaxFramerateFraction = 156 std::numeric_limits<uint8_t>::max(); 157 158 EncoderInfo(); 159 EncoderInfo(const EncoderInfo&); 160 161 ~EncoderInfo(); 162 163 std::string ToString() const; 164 bool operator==(const EncoderInfo& rhs) const; 165 bool operator!=(const EncoderInfo& rhs) const { return !(*this == rhs); } 166 167 // Any encoder implementation wishing to use the WebRTC provided 168 // quality scaler must populate this field. 169 ScalingSettings scaling_settings; 170 171 // The width and height of the incoming video frames should be divisible 172 // by |requested_resolution_alignment|. If they are not, the encoder may 173 // drop the incoming frame. 174 // For example: With I420, this value would be a multiple of 2. 175 // Note that this field is unrelated to any horizontal or vertical stride 176 // requirements the encoder has on the incoming video frame buffers. 177 int requested_resolution_alignment; 178 179 // If true, encoder supports working with a native handle (e.g. texture 180 // handle for hw codecs) rather than requiring a raw I420 buffer. 181 bool supports_native_handle; 182 183 // The name of this particular encoder implementation, e.g. "libvpx". 184 std::string implementation_name; 185 186 // If this field is true, the encoder rate controller must perform 187 // well even in difficult situations, and produce close to the specified 188 // target bitrate seen over a reasonable time window, drop frames if 189 // necessary in order to keep the rate correct, and react quickly to 190 // changing bitrate targets. If this method returns true, we disable the 191 // frame dropper in the media optimization module and rely entirely on the 192 // encoder to produce media at a bitrate that closely matches the target. 193 // Any overshooting may result in delay buildup. If this method returns 194 // false (default behavior), the media opt frame dropper will drop input 195 // frames if it suspect encoder misbehavior. Misbehavior is common, 196 // especially in hardware codecs. Disable media opt at your own risk. 197 bool has_trusted_rate_controller; 198 199 // If this field is true, the encoder uses hardware support and different 200 // thresholds will be used in CPU adaptation. 201 bool is_hardware_accelerated; 202 203 // If this field is true, the encoder uses internal camera sources, meaning 204 // that it does not require/expect frames to be delivered via 205 // webrtc::VideoEncoder::Encode. 206 // Internal source encoders are deprecated and support for them will be 207 // phased out. 208 bool has_internal_source; 209 210 // For each spatial layer (simulcast stream or SVC layer), represented as an 211 // element in |fps_allocation| a vector indicates how many temporal layers 212 // the encoder is using for that spatial layer. 213 // For each spatial/temporal layer pair, the frame rate fraction is given as 214 // an 8bit unsigned integer where 0 = 0% and 255 = 100%. 215 // 216 // If the vector is empty for a given spatial layer, it indicates that frame 217 // rates are not defined and we can't count on any specific frame rate to be 218 // generated. Likely this indicates Vp8TemporalLayersType::kBitrateDynamic. 219 // 220 // The encoder may update this on a per-frame basis in response to both 221 // internal and external signals. 222 // 223 // Spatial layers are treated independently, but temporal layers are 224 // cumulative. For instance, if: 225 // fps_allocation[0][0] = kFullFramerate / 2; 226 // fps_allocation[0][1] = kFullFramerate; 227 // Then half of the frames are in the base layer and half is in TL1, but 228 // since TL1 is assumed to depend on the base layer, the frame rate is 229 // indicated as the full 100% for the top layer. 230 // 231 // Defaults to a single spatial layer containing a single temporal layer 232 // with a 100% frame rate fraction. 233 absl::InlinedVector<uint8_t, kMaxTemporalStreams> 234 fps_allocation[kMaxSpatialLayers]; 235 236 // Recommended bitrate limits for different resolutions. 237 std::vector<ResolutionBitrateLimits> resolution_bitrate_limits; 238 239 // Obtains the limits from |resolution_bitrate_limits| that best matches the 240 // |frame_size_pixels|. 241 absl::optional<ResolutionBitrateLimits> 242 GetEncoderBitrateLimitsForResolution(int frame_size_pixels) const; 243 244 // If true, this encoder has internal support for generating simulcast 245 // streams. Otherwise, an adapter class will be needed. 246 // Even if true, the config provided to InitEncode() might not be supported, 247 // in such case the encoder should return 248 // WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED. 249 bool supports_simulcast; 250 }; 251 252 struct RTC_EXPORT RateControlParameters { 253 RateControlParameters(); 254 RateControlParameters(const VideoBitrateAllocation& bitrate, 255 double framerate_fps); 256 RateControlParameters(const VideoBitrateAllocation& bitrate, 257 double framerate_fps, 258 DataRate bandwidth_allocation); 259 virtual ~RateControlParameters(); 260 261 // Target bitrate, per spatial/temporal layer. 262 // A target bitrate of 0bps indicates a layer should not be encoded at all. 263 VideoBitrateAllocation bitrate; 264 // Target framerate, in fps. A value <= 0.0 is invalid and should be 265 // interpreted as framerate target not available. In this case the encoder 266 // should fall back to the max framerate specified in |codec_settings| of 267 // the last InitEncode() call. 268 double framerate_fps; 269 // The network bandwidth available for video. This is at least 270 // |bitrate.get_sum_bps()|, but may be higher if the application is not 271 // network constrained. 272 DataRate bandwidth_allocation; 273 274 bool operator==(const RateControlParameters& rhs) const; 275 bool operator!=(const RateControlParameters& rhs) const; 276 }; 277 278 struct LossNotification { 279 // The timestamp of the last decodable frame *prior* to the last received. 280 // (The last received - described below - might itself be decodable or not.) 281 uint32_t timestamp_of_last_decodable; 282 // The timestamp of the last received frame. 283 uint32_t timestamp_of_last_received; 284 // Describes whether the dependencies of the last received frame were 285 // all decodable. 286 // |false| if some dependencies were undecodable, |true| if all dependencies 287 // were decodable, and |nullopt| if the dependencies are unknown. 288 absl::optional<bool> dependencies_of_last_received_decodable; 289 // Describes whether the received frame was decodable. 290 // |false| if some dependency was undecodable or if some packet belonging 291 // to the last received frame was missed. 292 // |true| if all dependencies were decodable and all packets belonging 293 // to the last received frame were received. 294 // |nullopt| if no packet belonging to the last frame was missed, but the 295 // last packet in the frame was not yet received. 296 absl::optional<bool> last_received_decodable; 297 }; 298 299 // Negotiated capabilities which the VideoEncoder may expect the other 300 // side to use. 301 struct Capabilities { CapabilitiesCapabilities302 explicit Capabilities(bool loss_notification) 303 : loss_notification(loss_notification) {} 304 bool loss_notification; 305 }; 306 307 struct Settings { SettingsSettings308 Settings(const Capabilities& capabilities, 309 int number_of_cores, 310 size_t max_payload_size) 311 : capabilities(capabilities), 312 number_of_cores(number_of_cores), 313 max_payload_size(max_payload_size) {} 314 315 Capabilities capabilities; 316 int number_of_cores; 317 size_t max_payload_size; 318 }; 319 320 static VideoCodecVP8 GetDefaultVp8Settings(); 321 static VideoCodecVP9 GetDefaultVp9Settings(); 322 static VideoCodecH264 GetDefaultH264Settings(); 323 ~VideoEncoder()324 virtual ~VideoEncoder() {} 325 326 // Set a FecControllerOverride, through which the encoder may override 327 // decisions made by FecController. 328 // TODO(bugs.webrtc.org/10769): Update downstream, then make pure-virtual. 329 virtual void SetFecControllerOverride( 330 FecControllerOverride* fec_controller_override); 331 332 // Initialize the encoder with the information from the codecSettings 333 // 334 // Input: 335 // - codec_settings : Codec settings 336 // - settings : Settings affecting the encoding itself. 337 // Input for deprecated version: 338 // - number_of_cores : Number of cores available for the encoder 339 // - max_payload_size : The maximum size each payload is allowed 340 // to have. Usually MTU - overhead. 341 // 342 // Return value : Set bit rate if OK 343 // <0 - Errors: 344 // WEBRTC_VIDEO_CODEC_ERR_PARAMETER 345 // WEBRTC_VIDEO_CODEC_ERR_SIZE 346 // WEBRTC_VIDEO_CODEC_MEMORY 347 // WEBRTC_VIDEO_CODEC_ERROR 348 // TODO(bugs.webrtc.org/10720): After updating downstream projects and posting 349 // an announcement to discuss-webrtc, remove the three-parameters variant 350 // and make the two-parameters variant pure-virtual. 351 /* RTC_DEPRECATED */ virtual int32_t InitEncode( 352 const VideoCodec* codec_settings, 353 int32_t number_of_cores, 354 size_t max_payload_size); 355 virtual int InitEncode(const VideoCodec* codec_settings, 356 const VideoEncoder::Settings& settings); 357 358 // Register an encode complete callback object. 359 // 360 // Input: 361 // - callback : Callback object which handles encoded images. 362 // 363 // Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. 364 virtual int32_t RegisterEncodeCompleteCallback( 365 EncodedImageCallback* callback) = 0; 366 367 // Free encoder memory. 368 // Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. 369 virtual int32_t Release() = 0; 370 371 // Encode an I420 image (as a part of a video stream). The encoded image 372 // will be returned to the user through the encode complete callback. 373 // 374 // Input: 375 // - frame : Image to be encoded 376 // - frame_types : Frame type to be generated by the encoder. 377 // 378 // Return value : WEBRTC_VIDEO_CODEC_OK if OK 379 // <0 - Errors: 380 // WEBRTC_VIDEO_CODEC_ERR_PARAMETER 381 // WEBRTC_VIDEO_CODEC_MEMORY 382 // WEBRTC_VIDEO_CODEC_ERROR 383 virtual int32_t Encode(const VideoFrame& frame, 384 const std::vector<VideoFrameType>* frame_types) = 0; 385 386 // Sets rate control parameters: bitrate, framerate, etc. These settings are 387 // instantaneous (i.e. not moving averages) and should apply from now until 388 // the next call to SetRates(). 389 virtual void SetRates(const RateControlParameters& parameters) = 0; 390 391 // Inform the encoder when the packet loss rate changes. 392 // 393 // Input: - packet_loss_rate : The packet loss rate (0.0 to 1.0). 394 virtual void OnPacketLossRateUpdate(float packet_loss_rate); 395 396 // Inform the encoder when the round trip time changes. 397 // 398 // Input: - rtt_ms : The new RTT, in milliseconds. 399 virtual void OnRttUpdate(int64_t rtt_ms); 400 401 // Called when a loss notification is received. 402 virtual void OnLossNotification(const LossNotification& loss_notification); 403 404 // Returns meta-data about the encoder, such as implementation name. 405 // The output of this method may change during runtime. For instance if a 406 // hardware encoder fails, it may fall back to doing software encoding using 407 // an implementation with different characteristics. 408 virtual EncoderInfo GetEncoderInfo() const; 409 }; 410 } // namespace webrtc 411 #endif // API_VIDEO_CODECS_VIDEO_ENCODER_H_ 412