xref: /aosp_15_r20/external/webrtc/media/base/video_adapter.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2010 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 MEDIA_BASE_VIDEO_ADAPTER_H_
12 #define MEDIA_BASE_VIDEO_ADAPTER_H_
13 
14 #include <stdint.h>
15 
16 #include <string>
17 #include <utility>
18 
19 #include "absl/types/optional.h"
20 #include "api/video/video_source_interface.h"
21 #include "common_video/framerate_controller.h"
22 #include "media/base/video_common.h"
23 #include "rtc_base/synchronization/mutex.h"
24 #include "rtc_base/system/rtc_export.h"
25 #include "rtc_base/thread_annotations.h"
26 
27 namespace cricket {
28 
29 // VideoAdapter adapts an input video frame to an output frame based on the
30 // specified input and output formats. The adaptation includes dropping frames
31 // to reduce frame rate and scaling frames.
32 // VideoAdapter is thread safe.
33 class RTC_EXPORT VideoAdapter {
34  public:
35   VideoAdapter();
36   // The source requests output frames whose width and height are divisible
37   // by `source_resolution_alignment`.
38   explicit VideoAdapter(int source_resolution_alignment);
39   virtual ~VideoAdapter();
40 
41   VideoAdapter(const VideoAdapter&) = delete;
42   VideoAdapter& operator=(const VideoAdapter&) = delete;
43 
44   // Return the adapted resolution and cropping parameters given the
45   // input resolution. The input frame should first be cropped, then
46   // scaled to the final output resolution. Returns true if the frame
47   // should be adapted, and false if it should be dropped.
48   bool AdaptFrameResolution(int in_width,
49                             int in_height,
50                             int64_t in_timestamp_ns,
51                             int* cropped_width,
52                             int* cropped_height,
53                             int* out_width,
54                             int* out_height) RTC_LOCKS_EXCLUDED(mutex_);
55 
56   // DEPRECATED. Please use OnOutputFormatRequest below.
57   // TODO(asapersson): Remove this once it is no longer used.
58   // Requests the output frame size and frame interval from
59   // `AdaptFrameResolution` to not be larger than `format`. Also, the input
60   // frame size will be cropped to match the requested aspect ratio. The
61   // requested aspect ratio is orientation agnostic and will be adjusted to
62   // maintain the input orientation, so it doesn't matter if e.g. 1280x720 or
63   // 720x1280 is requested.
64   // Note: Should be called from the source only.
65   void OnOutputFormatRequest(const absl::optional<VideoFormat>& format)
66       RTC_LOCKS_EXCLUDED(mutex_);
67 
68   // Requests output frame size and frame interval from `AdaptFrameResolution`.
69   // `target_aspect_ratio`: The input frame size will be cropped to match the
70   // requested aspect ratio. The aspect ratio is orientation agnostic and will
71   // be adjusted to maintain the input orientation (i.e. it doesn't matter if
72   // e.g. <1280,720> or <720,1280> is requested).
73   // `max_pixel_count`: The maximum output frame size.
74   // `max_fps`: The maximum output framerate.
75   // Note: Should be called from the source only.
76   void OnOutputFormatRequest(
77       const absl::optional<std::pair<int, int>>& target_aspect_ratio,
78       const absl::optional<int>& max_pixel_count,
79       const absl::optional<int>& max_fps) RTC_LOCKS_EXCLUDED(mutex_);
80 
81   // Same as above, but allows setting two different target aspect ratios
82   // depending on incoming frame orientation. This gives more fine-grained
83   // control and can e.g. be used to force landscape video to be cropped to
84   // portrait video.
85   void OnOutputFormatRequest(
86       const absl::optional<std::pair<int, int>>& target_landscape_aspect_ratio,
87       const absl::optional<int>& max_landscape_pixel_count,
88       const absl::optional<std::pair<int, int>>& target_portrait_aspect_ratio,
89       const absl::optional<int>& max_portrait_pixel_count,
90       const absl::optional<int>& max_fps) RTC_LOCKS_EXCLUDED(mutex_);
91 
92   // Requests the output frame size from `AdaptFrameResolution` to have as close
93   // as possible to `sink_wants.target_pixel_count` pixels (if set)
94   // but no more than `sink_wants.max_pixel_count`.
95   // `sink_wants.max_framerate_fps` is essentially analogous to
96   // `sink_wants.max_pixel_count`, but for framerate rather than resolution.
97   // Set `sink_wants.max_pixel_count` and/or `sink_wants.max_framerate_fps` to
98   // std::numeric_limit<int>::max() if no upper limit is desired.
99   // The sink resolution alignment requirement is given by
100   // `sink_wants.resolution_alignment`.
101   // Note: Should be called from the sink only.
102   void OnSinkWants(const rtc::VideoSinkWants& sink_wants)
103       RTC_LOCKS_EXCLUDED(mutex_);
104 
105   // Returns maximum image area, which shouldn't impose any adaptations.
106   // Can return `numeric_limits<int>::max()` if no limit is set.
107   int GetTargetPixels() const;
108 
109   // Returns current frame-rate limit.
110   // Can return `numeric_limits<float>::infinity()` if no limit is set.
111   float GetMaxFramerate() const;
112 
113  private:
114   // Determine if frame should be dropped based on input fps and requested fps.
115   bool DropFrame(int64_t in_timestamp_ns) RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
116 
117   int frames_in_ RTC_GUARDED_BY(mutex_);      // Number of input frames.
118   int frames_out_ RTC_GUARDED_BY(mutex_);     // Number of output frames.
119   int frames_scaled_ RTC_GUARDED_BY(mutex_);  // Number of frames scaled.
120   int adaption_changes_
121       RTC_GUARDED_BY(mutex_);  // Number of changes in scale factor.
122   int previous_width_ RTC_GUARDED_BY(mutex_);  // Previous adapter output width.
123   int previous_height_
124       RTC_GUARDED_BY(mutex_);  // Previous adapter output height.
125   const bool variable_start_scale_factor_;
126 
127   // The fixed source resolution alignment requirement.
128   const int source_resolution_alignment_;
129   // The currently applied resolution alignment, as given by the requirements:
130   //  - the fixed `source_resolution_alignment_`; and
131   //  - the latest `sink_wants.resolution_alignment`.
132   int resolution_alignment_ RTC_GUARDED_BY(mutex_);
133 
134   // Max number of pixels/fps requested via calls to OnOutputFormatRequest,
135   // OnResolutionFramerateRequest respectively.
136   // The adapted output format is the minimum of these.
137   struct OutputFormatRequest {
138     absl::optional<std::pair<int, int>> target_landscape_aspect_ratio;
139     absl::optional<int> max_landscape_pixel_count;
140     absl::optional<std::pair<int, int>> target_portrait_aspect_ratio;
141     absl::optional<int> max_portrait_pixel_count;
142     absl::optional<int> max_fps;
143 
144     // For logging.
145     std::string ToString() const;
146   };
147 
148   OutputFormatRequest output_format_request_ RTC_GUARDED_BY(mutex_);
149   int resolution_request_target_pixel_count_ RTC_GUARDED_BY(mutex_);
150   int resolution_request_max_pixel_count_ RTC_GUARDED_BY(mutex_);
151   int max_framerate_request_ RTC_GUARDED_BY(mutex_);
152 
153   // Stashed OutputFormatRequest that is used to save value of
154   // OnOutputFormatRequest in case all active encoders are using
155   // requested_resolution. I.e when all active encoders are using
156   // requested_resolution, the call to OnOutputFormatRequest is ignored
157   // and the value from requested_resolution is used instead (to scale/crop
158   // frame). This allows for an application to only use
159   // RtpEncodingParameters::request_resolution and get the same behavior as if
160   // it had used VideoAdapter::OnOutputFormatRequest.
161   absl::optional<OutputFormatRequest> stashed_output_format_request_
162       RTC_GUARDED_BY(mutex_);
163 
164   webrtc::FramerateController framerate_controller_ RTC_GUARDED_BY(mutex_);
165 
166   // The critical section to protect the above variables.
167   mutable webrtc::Mutex mutex_;
168 };
169 
170 }  // namespace cricket
171 
172 #endif  // MEDIA_BASE_VIDEO_ADAPTER_H_
173