blob: 012d870ed619407b1d46455ed8d6bf7cf9cd4008 [file] [log] [blame]
Elad Alonde3360e2019-03-06 21:14:54 +01001/*
2 * Copyright (c) 2019 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_VP8_FRAME_BUFFER_CONTROLLER_H_
12#define API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_
13
Elad Alon4d6795f2019-05-02 23:25:34 +020014#include <array>
Elad Aloncde8ab22019-03-20 11:56:20 +010015#include <memory>
Elad Alonde3360e2019-03-06 21:14:54 +010016#include <vector>
17
Elad Alon6c371ca2019-04-04 12:28:51 +020018#include "absl/types/optional.h"
Elad Aloncde8ab22019-03-20 11:56:20 +010019#include "api/video_codecs/video_codec.h"
Elad Alon6c371ca2019-04-04 12:28:51 +020020#include "api/video_codecs/video_encoder.h"
Elad Alonde3360e2019-03-06 21:14:54 +010021#include "api/video_codecs/vp8_frame_config.h"
22
23namespace webrtc {
24
25// Some notes on the prerequisites of the TemporalLayers interface.
26// * Vp8FrameBufferController is not thread safe, synchronization is the
27// caller's responsibility.
28// * The encoder is assumed to encode all frames in order, and callbacks to
Elad Alon979c4422019-04-17 12:53:08 +020029// PopulateCodecSpecific() / OnEncodeDone() must happen in the same order.
Elad Alonde3360e2019-03-06 21:14:54 +010030//
31// This means that in the case of pipelining encoders, it is OK to have a chain
32// of calls such as this:
Elad Alon162a0392019-04-23 15:33:59 +020033// - NextFrameConfig(timestampA)
34// - NextFrameConfig(timestampB)
Elad Alonde3360e2019-03-06 21:14:54 +010035// - PopulateCodecSpecific(timestampA, ...)
Elad Alon162a0392019-04-23 15:33:59 +020036// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010037// - OnEncodeDone(timestampA, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020038// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010039// - OnEncodeDone(timestampB, 0, ...)
40// - OnEncodeDone(timestampC, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020041// Note that NextFrameConfig() for a new frame can happen before
Elad Alon979c4422019-04-17 12:53:08 +020042// OnEncodeDone() for a previous one, but calls themselves must be both
Elad Alonde3360e2019-03-06 21:14:54 +010043// synchronized (e.g. run on a task queue) and in order (per type).
Elad Alon979c4422019-04-17 12:53:08 +020044//
45// TODO(eladalon): Revise comment (referring to PopulateCodecSpecific in this
46// context is not very meaningful).
Elad Alonde3360e2019-03-06 21:14:54 +010047
48struct CodecSpecificInfo;
49
Elad Alon4d6795f2019-05-02 23:25:34 +020050// Each member represents an override of the VPX configuration if the optional
51// value is set.
Elad Alonde3360e2019-03-06 21:14:54 +010052struct Vp8EncoderConfig {
Elad Alon4d6795f2019-05-02 23:25:34 +020053 struct TemporalLayerConfig {
54 bool operator!=(const TemporalLayerConfig& other) const {
55 return ts_number_layers != other.ts_number_layers ||
56 ts_target_bitrate != other.ts_target_bitrate ||
57 ts_rate_decimator != other.ts_rate_decimator ||
58 ts_periodicity != other.ts_periodicity ||
59 ts_layer_id != other.ts_layer_id;
60 }
Elad Alonde3360e2019-03-06 21:14:54 +010061
Elad Alon4d6795f2019-05-02 23:25:34 +020062 static constexpr size_t kMaxPeriodicity = 16;
63 static constexpr size_t kMaxLayers = 5;
Elad Alonde3360e2019-03-06 21:14:54 +010064
Elad Alon4d6795f2019-05-02 23:25:34 +020065 // Number of active temporal layers. Set to 0 if not used.
66 uint32_t ts_number_layers;
67
68 // Arrays of length |ts_number_layers|, indicating (cumulative) target
69 // bitrate and rate decimator (e.g. 4 if every 4th frame is in the given
70 // layer) for each active temporal layer, starting with temporal id 0.
71 std::array<uint32_t, kMaxLayers> ts_target_bitrate;
72 std::array<uint32_t, kMaxLayers> ts_rate_decimator;
73
74 // The periodicity of the temporal pattern. Set to 0 if not used.
75 uint32_t ts_periodicity;
76
77 // Array of length |ts_periodicity| indicating the sequence of temporal id's
78 // to assign to incoming frames.
79 std::array<uint32_t, kMaxPeriodicity> ts_layer_id;
80 };
81
82 absl::optional<TemporalLayerConfig> temporal_layer_config;
Elad Alonde3360e2019-03-06 21:14:54 +010083
84 // Target bitrate, in bps.
Elad Alon4d6795f2019-05-02 23:25:34 +020085 absl::optional<uint32_t> rc_target_bitrate;
Elad Alonde3360e2019-03-06 21:14:54 +010086
Elad Alon4d6795f2019-05-02 23:25:34 +020087 // Clamp QP to max. Use 0 to disable clamping.
88 absl::optional<uint32_t> rc_max_quantizer;
Elad Alon544dece2019-04-25 14:24:36 +020089
Elad Alon4d6795f2019-05-02 23:25:34 +020090 // Error resilience mode.
91 absl::optional<uint32_t> g_error_resilient;
Elad Alonde3360e2019-03-06 21:14:54 +010092};
93
94// This interface defines a way of delegating the logic of buffer management.
Elad Aloncde8ab22019-03-20 11:56:20 +010095// Multiple streams may be controlled by a single controller, demuxing between
96// them using stream_index.
Elad Alonde3360e2019-03-06 21:14:54 +010097class Vp8FrameBufferController {
98 public:
99 virtual ~Vp8FrameBufferController() = default;
100
Elad Alon4d6795f2019-05-02 23:25:34 +0200101 // Set limits on QP.
102 // The limits are suggestion-only; the controller is allowed to exceed them.
103 virtual void SetQpLimits(size_t stream_index, int min_qp, int max_qp) = 0;
104
Elad Aloncde8ab22019-03-20 11:56:20 +0100105 // Number of streamed controlled by |this|.
106 virtual size_t StreamCount() const = 0;
107
Elad Alonde3360e2019-03-06 21:14:54 +0100108 // If this method returns true, the encoder is free to drop frames for
109 // instance in an effort to uphold encoding bitrate.
110 // If this return false, the encoder must not drop any frames unless:
111 // 1. Requested to do so via Vp8FrameConfig.drop_frame
112 // 2. The frame to be encoded is requested to be a keyframe
113 // 3. The encoded detected a large overshoot and decided to drop and then
114 // re-encode the image at a low bitrate. In this case the encoder should
115 // call OnEncodeDone() once with size = 0 to indicate drop, and then call
116 // OnEncodeDone() again when the frame has actually been encoded.
Elad Aloncde8ab22019-03-20 11:56:20 +0100117 virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100118
Elad Alon979c4422019-04-17 12:53:08 +0200119 // New target bitrate for a stream (each entry in
120 // |bitrates_bps| is for another temporal layer).
Elad Aloncde8ab22019-03-20 11:56:20 +0100121 virtual void OnRatesUpdated(size_t stream_index,
122 const std::vector<uint32_t>& bitrates_bps,
Elad Alonde3360e2019-03-06 21:14:54 +0100123 int framerate_fps) = 0;
124
Elad Alon4d6795f2019-05-02 23:25:34 +0200125 // Called by the encoder before encoding a frame. Returns a set of overrides
126 // the controller wishes to enact in the encoder's configuration.
127 // If a value is not overridden, previous overrides are still in effect.
128 // (It is therefore not possible to go from a specific override to
129 // no-override. Once the controller takes responsibility over a value, it
130 // must maintain responsibility for it.)
131 virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100132
Elad Alon979c4422019-04-17 12:53:08 +0200133 // Returns the recommended VP8 encode flags needed.
Elad Alonde3360e2019-03-06 21:14:54 +0100134 // The timestamp may be used as both a time and a unique identifier, and so
135 // the caller must make sure no two frames use the same timestamp.
136 // The timestamp uses a 90kHz RTP clock.
137 // After calling this method, first call the actual encoder with the provided
138 // frame configuration, and then OnEncodeDone() below.
Elad Alon979c4422019-04-17 12:53:08 +0200139 virtual Vp8FrameConfig NextFrameConfig(size_t stream_index,
140 uint32_t rtp_timestamp) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100141
142 // Called after the encode step is done. |rtp_timestamp| must match the
Elad Alon162a0392019-04-23 15:33:59 +0200143 // parameter use in the NextFrameConfig() call.
Elad Alonde3360e2019-03-06 21:14:54 +0100144 // |is_keyframe| must be true iff the encoder decided to encode this frame as
145 // a keyframe.
Elad Alon979c4422019-04-17 12:53:08 +0200146 // If |info| is not null, the encoder may update |info| with codec specific
147 // data such as temporal id. |qp| should indicate the frame-level QP this
148 // frame was encoded at. If the encoder does not support extracting this, |qp|
149 // should be set to 0.
Elad Aloncde8ab22019-03-20 11:56:20 +0100150 virtual void OnEncodeDone(size_t stream_index,
151 uint32_t rtp_timestamp,
Elad Alonde3360e2019-03-06 21:14:54 +0100152 size_t size_bytes,
153 bool is_keyframe,
154 int qp,
155 CodecSpecificInfo* info) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100156
Elad Alon6796ec22019-04-15 10:07:50 +0200157 // Called when a frame is dropped by the encoder.
158 virtual void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) = 0;
159
Elad Aloncde8ab22019-03-20 11:56:20 +0100160 // Called by the encoder when the packet loss rate changes.
161 // |packet_loss_rate| runs between 0.0 (no loss) and 1.0 (everything lost).
162 virtual void OnPacketLossRateUpdate(float packet_loss_rate) = 0;
163
164 // Called by the encoder when the round trip time changes.
165 virtual void OnRttUpdate(int64_t rtt_ms) = 0;
Elad Alon6c371ca2019-04-04 12:28:51 +0200166
167 // Called when a loss notification is received.
168 virtual void OnLossNotification(
Elad Alon123ee9b2019-04-17 12:48:06 +0200169 const VideoEncoder::LossNotification& loss_notification) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100170};
171
172// Interface for a factory of Vp8FrameBufferController instances.
173class Vp8FrameBufferControllerFactory {
174 public:
175 virtual ~Vp8FrameBufferControllerFactory() = default;
176
177 virtual std::unique_ptr<Vp8FrameBufferController> Create(
178 const VideoCodec& codec) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100179};
180
181} // namespace webrtc
182
183#endif // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_