blob: f71740e84807116f6c4c0889ac3dceb35beba717 [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 Aloncde8ab22019-03-20 11:56:20 +010014#include <memory>
Elad Alonde3360e2019-03-06 21:14:54 +010015#include <vector>
16
Elad Alon6c371ca2019-04-04 12:28:51 +020017#include "absl/types/optional.h"
Elad Aloncde8ab22019-03-20 11:56:20 +010018#include "api/video_codecs/video_codec.h"
Elad Alon6c371ca2019-04-04 12:28:51 +020019#include "api/video_codecs/video_encoder.h"
Elad Alonde3360e2019-03-06 21:14:54 +010020#include "api/video_codecs/vp8_frame_config.h"
21
22namespace webrtc {
23
24// Some notes on the prerequisites of the TemporalLayers interface.
25// * Vp8FrameBufferController is not thread safe, synchronization is the
26// caller's responsibility.
27// * The encoder is assumed to encode all frames in order, and callbacks to
Elad Alon979c4422019-04-17 12:53:08 +020028// PopulateCodecSpecific() / OnEncodeDone() must happen in the same order.
Elad Alonde3360e2019-03-06 21:14:54 +010029//
30// This means that in the case of pipelining encoders, it is OK to have a chain
31// of calls such as this:
Elad Alon162a0392019-04-23 15:33:59 +020032// - NextFrameConfig(timestampA)
33// - NextFrameConfig(timestampB)
Elad Alonde3360e2019-03-06 21:14:54 +010034// - PopulateCodecSpecific(timestampA, ...)
Elad Alon162a0392019-04-23 15:33:59 +020035// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010036// - OnEncodeDone(timestampA, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020037// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010038// - OnEncodeDone(timestampB, 0, ...)
39// - OnEncodeDone(timestampC, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020040// Note that NextFrameConfig() for a new frame can happen before
Elad Alon979c4422019-04-17 12:53:08 +020041// OnEncodeDone() for a previous one, but calls themselves must be both
Elad Alonde3360e2019-03-06 21:14:54 +010042// synchronized (e.g. run on a task queue) and in order (per type).
Elad Alon979c4422019-04-17 12:53:08 +020043//
44// TODO(eladalon): Revise comment (referring to PopulateCodecSpecific in this
45// context is not very meaningful).
Elad Alonde3360e2019-03-06 21:14:54 +010046
47struct CodecSpecificInfo;
48
Elad Alon3d622d62019-05-09 22:31:08 +020049// TODO(eladalon): This configuration is temporal-layers specific; refactor.
Elad Alonde3360e2019-03-06 21:14:54 +010050struct Vp8EncoderConfig {
Elad Alon3d622d62019-05-09 22:31:08 +020051 static constexpr size_t kMaxPeriodicity = 16;
52 static constexpr size_t kMaxLayers = 5;
Elad Alonde3360e2019-03-06 21:14:54 +010053
Elad Alon3d622d62019-05-09 22:31:08 +020054 // Number of active temporal layers. Set to 0 if not used.
55 uint32_t ts_number_layers;
56 // Arrays of length |ts_number_layers|, indicating (cumulative) target bitrate
57 // and rate decimator (e.g. 4 if every 4th frame is in the given layer) for
58 // each active temporal layer, starting with temporal id 0.
59 uint32_t ts_target_bitrate[kMaxLayers];
60 uint32_t ts_rate_decimator[kMaxLayers];
Elad Alonde3360e2019-03-06 21:14:54 +010061
Elad Alon3d622d62019-05-09 22:31:08 +020062 // The periodicity of the temporal pattern. Set to 0 if not used.
63 uint32_t ts_periodicity;
64 // Array of length |ts_periodicity| indicating the sequence of temporal id's
65 // to assign to incoming frames.
66 uint32_t ts_layer_id[kMaxPeriodicity];
Elad Alonde3360e2019-03-06 21:14:54 +010067
68 // Target bitrate, in bps.
Elad Alon3d622d62019-05-09 22:31:08 +020069 uint32_t rc_target_bitrate;
Elad Alonde3360e2019-03-06 21:14:54 +010070
Elad Alon3d622d62019-05-09 22:31:08 +020071 // Clamp QP to min/max. Use 0 to disable clamping.
72 uint32_t rc_min_quantizer;
73 uint32_t rc_max_quantizer;
Elad Alon544dece2019-04-25 14:24:36 +020074
Elad Alon3d622d62019-05-09 22:31:08 +020075 // If has_value(), override error resilience to value().
76 absl::optional<uint32_t> error_resilient;
Elad Alonde3360e2019-03-06 21:14:54 +010077};
78
79// This interface defines a way of delegating the logic of buffer management.
Elad Aloncde8ab22019-03-20 11:56:20 +010080// Multiple streams may be controlled by a single controller, demuxing between
81// them using stream_index.
Elad Alonde3360e2019-03-06 21:14:54 +010082class Vp8FrameBufferController {
83 public:
84 virtual ~Vp8FrameBufferController() = default;
85
Elad Aloncde8ab22019-03-20 11:56:20 +010086 // Number of streamed controlled by |this|.
87 virtual size_t StreamCount() const = 0;
88
Elad Alonde3360e2019-03-06 21:14:54 +010089 // If this method returns true, the encoder is free to drop frames for
90 // instance in an effort to uphold encoding bitrate.
91 // If this return false, the encoder must not drop any frames unless:
92 // 1. Requested to do so via Vp8FrameConfig.drop_frame
93 // 2. The frame to be encoded is requested to be a keyframe
Elad Alon6cdbf3f2019-05-08 10:02:46 +020094 // 3. The encoder detected a large overshoot and decided to drop and then
Elad Alonde3360e2019-03-06 21:14:54 +010095 // re-encode the image at a low bitrate. In this case the encoder should
Elad Alon1f28c282019-05-07 21:31:21 +020096 // call OnFrameDropped() once to indicate drop, and then call
Elad Alonde3360e2019-03-06 21:14:54 +010097 // OnEncodeDone() again when the frame has actually been encoded.
Elad Aloncde8ab22019-03-20 11:56:20 +010098 virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0;
Elad Alonde3360e2019-03-06 21:14:54 +010099
Elad Alon979c4422019-04-17 12:53:08 +0200100 // New target bitrate for a stream (each entry in
101 // |bitrates_bps| is for another temporal layer).
Elad Aloncde8ab22019-03-20 11:56:20 +0100102 virtual void OnRatesUpdated(size_t stream_index,
103 const std::vector<uint32_t>& bitrates_bps,
Elad Alonde3360e2019-03-06 21:14:54 +0100104 int framerate_fps) = 0;
105
Elad Alon3d622d62019-05-09 22:31:08 +0200106 // Called by the encoder before encoding a frame. |cfg| contains the current
107 // configuration. If the encoder wishes any part of that to be changed before
108 // the encode step, |cfg| should be changed and then return true. If false is
109 // returned, the encoder will proceed without updating the configuration.
110 virtual bool UpdateConfiguration(size_t stream_index,
111 Vp8EncoderConfig* cfg) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100112
Elad Alon979c4422019-04-17 12:53:08 +0200113 // Returns the recommended VP8 encode flags needed.
Elad Alonde3360e2019-03-06 21:14:54 +0100114 // The timestamp may be used as both a time and a unique identifier, and so
115 // the caller must make sure no two frames use the same timestamp.
116 // The timestamp uses a 90kHz RTP clock.
117 // After calling this method, first call the actual encoder with the provided
118 // frame configuration, and then OnEncodeDone() below.
Elad Alon979c4422019-04-17 12:53:08 +0200119 virtual Vp8FrameConfig NextFrameConfig(size_t stream_index,
120 uint32_t rtp_timestamp) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100121
122 // Called after the encode step is done. |rtp_timestamp| must match the
Elad Alon162a0392019-04-23 15:33:59 +0200123 // parameter use in the NextFrameConfig() call.
Elad Alonde3360e2019-03-06 21:14:54 +0100124 // |is_keyframe| must be true iff the encoder decided to encode this frame as
125 // a keyframe.
Elad Alon979c4422019-04-17 12:53:08 +0200126 // If |info| is not null, the encoder may update |info| with codec specific
127 // data such as temporal id. |qp| should indicate the frame-level QP this
128 // frame was encoded at. If the encoder does not support extracting this, |qp|
129 // should be set to 0.
Elad Aloncde8ab22019-03-20 11:56:20 +0100130 virtual void OnEncodeDone(size_t stream_index,
131 uint32_t rtp_timestamp,
Elad Alonde3360e2019-03-06 21:14:54 +0100132 size_t size_bytes,
133 bool is_keyframe,
134 int qp,
135 CodecSpecificInfo* info) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100136
Elad Alon6796ec22019-04-15 10:07:50 +0200137 // Called when a frame is dropped by the encoder.
138 virtual void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) = 0;
139
Elad Aloncde8ab22019-03-20 11:56:20 +0100140 // Called by the encoder when the packet loss rate changes.
141 // |packet_loss_rate| runs between 0.0 (no loss) and 1.0 (everything lost).
142 virtual void OnPacketLossRateUpdate(float packet_loss_rate) = 0;
143
144 // Called by the encoder when the round trip time changes.
145 virtual void OnRttUpdate(int64_t rtt_ms) = 0;
Elad Alon6c371ca2019-04-04 12:28:51 +0200146
147 // Called when a loss notification is received.
148 virtual void OnLossNotification(
Elad Alon123ee9b2019-04-17 12:48:06 +0200149 const VideoEncoder::LossNotification& loss_notification) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100150};
151
152// Interface for a factory of Vp8FrameBufferController instances.
153class Vp8FrameBufferControllerFactory {
154 public:
155 virtual ~Vp8FrameBufferControllerFactory() = default;
156
157 virtual std::unique_ptr<Vp8FrameBufferController> Create(
158 const VideoCodec& codec) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100159};
160
161} // namespace webrtc
162
163#endif // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_