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 <utility>
17 
18 #include "absl/types/optional.h"
19 #include "api/video/video_source_interface.h"
20 #include "media/base/video_common.h"
21 #include "rtc_base/constructor_magic.h"
22 #include "rtc_base/synchronization/mutex.h"
23 #include "rtc_base/thread_annotations.h"
24 
25 namespace cricket {
26 
27 // VideoAdapter adapts an input video frame to an output frame based on the
28 // specified input and output formats. The adaptation includes dropping frames
29 // to reduce frame rate and scaling frames.
30 // VideoAdapter is thread safe.
31 class VideoAdapter {
32  public:
33   VideoAdapter();
34   // The source requests output frames whose width and height are divisible
35   // by |source_resolution_alignment|.
36   explicit VideoAdapter(int source_resolution_alignment);
37   virtual ~VideoAdapter();
38 
39   // Return the adapted resolution and cropping parameters given the
40   // input resolution. The input frame should first be cropped, then
41   // scaled to the final output resolution. Returns true if the frame
42   // should be adapted, and false if it should be dropped.
43   bool AdaptFrameResolution(int in_width,
44                             int in_height,
45                             int64_t in_timestamp_ns,
46                             int* cropped_width,
47                             int* cropped_height,
48                             int* out_width,
49                             int* out_height) RTC_LOCKS_EXCLUDED(mutex_);
50 
51   // DEPRECATED. Please use OnOutputFormatRequest below.
52   // TODO(asapersson): Remove this once it is no longer used.
53   // Requests the output frame size and frame interval from
54   // |AdaptFrameResolution| to not be larger than |format|. Also, the input
55   // frame size will be cropped to match the requested aspect ratio. The
56   // requested aspect ratio is orientation agnostic and will be adjusted to
57   // maintain the input orientation, so it doesn't matter if e.g. 1280x720 or
58   // 720x1280 is requested.
59   // Note: Should be called from the source only.
60   void OnOutputFormatRequest(const absl::optional<VideoFormat>& format)
61       RTC_LOCKS_EXCLUDED(mutex_);
62 
63   // Requests output frame size and frame interval from |AdaptFrameResolution|.
64   // |target_aspect_ratio|: The input frame size will be cropped to match the
65   // requested aspect ratio. The aspect ratio is orientation agnostic and will
66   // be adjusted to maintain the input orientation (i.e. it doesn't matter if
67   // e.g. <1280,720> or <720,1280> is requested).
68   // |max_pixel_count|: The maximum output frame size.
69   // |max_fps|: The maximum output framerate.
70   // Note: Should be called from the source only.
71   void OnOutputFormatRequest(
72       const absl::optional<std::pair<int, int>>& target_aspect_ratio,
73       const absl::optional<int>& max_pixel_count,
74       const absl::optional<int>& max_fps) RTC_LOCKS_EXCLUDED(mutex_);
75 
76   // Same as above, but allows setting two different target aspect ratios
77   // depending on incoming frame orientation. This gives more fine-grained
78   // control and can e.g. be used to force landscape video to be cropped to
79   // portrait video.
80   void OnOutputFormatRequest(
81       const absl::optional<std::pair<int, int>>& target_landscape_aspect_ratio,
82       const absl::optional<int>& max_landscape_pixel_count,
83       const absl::optional<std::pair<int, int>>& target_portrait_aspect_ratio,
84       const absl::optional<int>& max_portrait_pixel_count,
85       const absl::optional<int>& max_fps) RTC_LOCKS_EXCLUDED(mutex_);
86 
87   // Requests the output frame size from |AdaptFrameResolution| to have as close
88   // as possible to |sink_wants.target_pixel_count| pixels (if set)
89   // but no more than |sink_wants.max_pixel_count|.
90   // |sink_wants.max_framerate_fps| is essentially analogous to
91   // |sink_wants.max_pixel_count|, but for framerate rather than resolution.
92   // Set |sink_wants.max_pixel_count| and/or |sink_wants.max_framerate_fps| to
93   // std::numeric_limit<int>::max() if no upper limit is desired.
94   // The sink resolution alignment requirement is given by
95   // |sink_wants.resolution_alignment|.
96   // Note: Should be called from the sink only.
97   void OnSinkWants(const rtc::VideoSinkWants& sink_wants)
98       RTC_LOCKS_EXCLUDED(mutex_);
99 
100  private:
101   // Determine if frame should be dropped based on input fps and requested fps.
102   bool KeepFrame(int64_t in_timestamp_ns) RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
103 
104   int frames_in_ RTC_GUARDED_BY(mutex_);      // Number of input frames.
105   int frames_out_ RTC_GUARDED_BY(mutex_);     // Number of output frames.
106   int frames_scaled_ RTC_GUARDED_BY(mutex_);  // Number of frames scaled.
107   int adaption_changes_
108       RTC_GUARDED_BY(mutex_);  // Number of changes in scale factor.
109   int previous_width_ RTC_GUARDED_BY(mutex_);  // Previous adapter output width.
110   int previous_height_
111       RTC_GUARDED_BY(mutex_);  // Previous adapter output height.
112   const bool variable_start_scale_factor_;
113 
114   // The fixed source resolution alignment requirement.
115   const int source_resolution_alignment_;
116   // The currently applied resolution alignment, as given by the requirements:
117   //  - the fixed |source_resolution_alignment_|; and
118   //  - the latest |sink_wants.resolution_alignment|.
119   int resolution_alignment_ RTC_GUARDED_BY(mutex_);
120 
121   // The target timestamp for the next frame based on requested format.
122   absl::optional<int64_t> next_frame_timestamp_ns_ RTC_GUARDED_BY(mutex_);
123 
124   // Max number of pixels/fps requested via calls to OnOutputFormatRequest,
125   // OnResolutionFramerateRequest respectively.
126   // The adapted output format is the minimum of these.
127   absl::optional<std::pair<int, int>> target_landscape_aspect_ratio_
128       RTC_GUARDED_BY(mutex_);
129   absl::optional<int> max_landscape_pixel_count_ RTC_GUARDED_BY(mutex_);
130   absl::optional<std::pair<int, int>> target_portrait_aspect_ratio_
131       RTC_GUARDED_BY(mutex_);
132   absl::optional<int> max_portrait_pixel_count_ RTC_GUARDED_BY(mutex_);
133   absl::optional<int> max_fps_ RTC_GUARDED_BY(mutex_);
134   int resolution_request_target_pixel_count_ RTC_GUARDED_BY(mutex_);
135   int resolution_request_max_pixel_count_ RTC_GUARDED_BY(mutex_);
136   int max_framerate_request_ RTC_GUARDED_BY(mutex_);
137 
138   // The critical section to protect the above variables.
139   webrtc::Mutex mutex_;
140 
141   RTC_DISALLOW_COPY_AND_ASSIGN(VideoAdapter);
142 };
143 
144 }  // namespace cricket
145 
146 #endif  // MEDIA_BASE_VIDEO_ADAPTER_H_
147