1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_VIDEO_VIDEO_SOURCE_INTERFACE_H_
#define API_VIDEO_VIDEO_SOURCE_INTERFACE_H_
#include <limits>
#include <vector>
#include "absl/types/optional.h"
#include "api/video/video_sink_interface.h"
#include "rtc_base/system/rtc_export.h"
namespace rtc {
// VideoSinkWants is used for notifying the source of properties a video frame
// should have when it is delivered to a certain sink.
struct RTC_EXPORT VideoSinkWants {
struct FrameSize {
FrameSize(int width, int height) : width(width), height(height) {}
FrameSize(const FrameSize&) = default;
~FrameSize() = default;
int width;
int height;
};
VideoSinkWants();
VideoSinkWants(const VideoSinkWants&);
~VideoSinkWants();
// Tells the source whether the sink wants frames with rotation applied.
// By default, any rotation must be applied by the sink.
bool rotation_applied = false;
// Tells the source that the sink only wants black frames.
bool black_frames = false;
// Tells the source the maximum number of pixels the sink wants.
int max_pixel_count = std::numeric_limits<int>::max();
// Tells the source the desired number of pixels the sinks wants. This will
// typically be used when stepping the resolution up again when conditions
// have improved after an earlier downgrade. The source should select the
// closest resolution to this pixel count, but if max_pixel_count is set, it
// still sets the absolute upper bound.
absl::optional<int> target_pixel_count;
// Tells the source the maximum framerate the sink wants.
int max_framerate_fps = std::numeric_limits<int>::max();
// Tells the source that the sink wants width and height of the video frames
// to be divisible by `resolution_alignment`.
// For example: With I420, this value would be a multiple of 2.
// Note that this field is unrelated to any horizontal or vertical stride
// requirements the encoder has on the incoming video frame buffers.
int resolution_alignment = 1;
// The resolutions that sink is configured to consume. If the sink is an
// encoder this is what the encoder is configured to encode. In singlecast we
// only encode one resolution, but in simulcast and SVC this can mean multiple
// resolutions per frame.
//
// The sink is always configured to consume a subset of the
// webrtc::VideoFrame's resolution. In the case of encoding, we usually encode
// at webrtc::VideoFrame's resolution but this may not always be the case due
// to scaleResolutionDownBy or turning off simulcast or SVC layers.
//
// For example, we may capture at 720p and due to adaptation (e.g. applying
// `max_pixel_count` constraints) create webrtc::VideoFrames of size 480p, but
// if we do scaleResolutionDownBy:2 then the only resolution we end up
// encoding is 240p. In this case we still need to provide webrtc::VideoFrames
// of size 480p but we can optimize internal buffers for 240p, avoiding
// downsampling to 480p if possible.
//
// Note that the `resolutions` can change while frames are in flight and
// should only be used as a hint when constructing the webrtc::VideoFrame.
std::vector<FrameSize> resolutions;
// This is the resolution requested by the user using RtpEncodingParameters.
absl::optional<FrameSize> requested_resolution;
// `is_active` : Is this VideoSinkWants from an encoder that is encoding any
// layer. IF YES, it will affect how the VideoAdapter will choose to
// prioritize the OnOutputFormatRequest vs. requested_resolution. IF NO,
// VideoAdapter consider this VideoSinkWants as a passive listener (e.g a
// VideoRenderer or a VideoEncoder that is not currently actively encoding).
bool is_active = false;
// This sub-struct contains information computed by VideoBroadcaster
// that aggregates several VideoSinkWants (and sends them to
// AdaptedVideoTrackSource).
struct Aggregates {
// `active_without_requested_resolution` is set by VideoBroadcaster
// when aggregating sink wants if there exists any sink (encoder) that is
// active but has not set the `requested_resolution`, i.e is relying on
// OnOutputFormatRequest to handle encode resolution.
bool any_active_without_requested_resolution = false;
};
absl::optional<Aggregates> aggregates;
};
inline bool operator==(const VideoSinkWants::FrameSize& a,
const VideoSinkWants::FrameSize& b) {
return a.width == b.width && a.height == b.height;
}
inline bool operator!=(const VideoSinkWants::FrameSize& a,
const VideoSinkWants::FrameSize& b) {
return !(a == b);
}
template <typename VideoFrameT>
class VideoSourceInterface {
public:
virtual ~VideoSourceInterface() = default;
virtual void AddOrUpdateSink(VideoSinkInterface<VideoFrameT>* sink,
const VideoSinkWants& wants) = 0;
// RemoveSink must guarantee that at the time the method returns,
// there is no current and no future calls to VideoSinkInterface::OnFrame.
virtual void RemoveSink(VideoSinkInterface<VideoFrameT>* sink) = 0;
// Request underlying source to capture a new frame.
// TODO(crbug/1255737): make pure virtual once downstream projects adapt.
virtual void RequestRefreshFrame() {}
};
} // namespace rtc
#endif // API_VIDEO_VIDEO_SOURCE_INTERFACE_H_
|