xref: /aosp_15_r20/external/webrtc/media/base/adapted_video_track_source.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2016 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 #include "media/base/adapted_video_track_source.h"
12 
13 #include "api/scoped_refptr.h"
14 #include "api/video/i420_buffer.h"
15 #include "api/video/video_frame_buffer.h"
16 #include "api/video/video_rotation.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/time_utils.h"
19 
20 namespace rtc {
21 
22 AdaptedVideoTrackSource::AdaptedVideoTrackSource() = default;
23 
AdaptedVideoTrackSource(int required_alignment)24 AdaptedVideoTrackSource::AdaptedVideoTrackSource(int required_alignment)
25     : video_adapter_(required_alignment) {}
26 
27 AdaptedVideoTrackSource::~AdaptedVideoTrackSource() = default;
28 
GetStats(Stats * stats)29 bool AdaptedVideoTrackSource::GetStats(Stats* stats) {
30   webrtc::MutexLock lock(&stats_mutex_);
31 
32   if (!stats_) {
33     return false;
34   }
35 
36   *stats = *stats_;
37   return true;
38 }
39 
OnFrame(const webrtc::VideoFrame & frame)40 void AdaptedVideoTrackSource::OnFrame(const webrtc::VideoFrame& frame) {
41   rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer(
42       frame.video_frame_buffer());
43   /* Note that this is a "best effort" approach to
44      wants.rotation_applied; apply_rotation_ can change from false to
45      true between the check of apply_rotation() and the call to
46      broadcaster_.OnFrame(), in which case we generate a frame with
47      pending rotation despite some sink with wants.rotation_applied ==
48      true was just added. The VideoBroadcaster enforces
49      synchronization for us in this case, by not passing the frame on
50      to sinks which don't want it. */
51   if (apply_rotation() && frame.rotation() != webrtc::kVideoRotation_0 &&
52       buffer->type() == webrtc::VideoFrameBuffer::Type::kI420) {
53     /* Apply pending rotation. */
54     webrtc::VideoFrame rotated_frame(frame);
55     rotated_frame.set_video_frame_buffer(
56         webrtc::I420Buffer::Rotate(*buffer->GetI420(), frame.rotation()));
57     rotated_frame.set_rotation(webrtc::kVideoRotation_0);
58     broadcaster_.OnFrame(rotated_frame);
59   } else {
60     broadcaster_.OnFrame(frame);
61   }
62 }
63 
OnFrameDropped()64 void AdaptedVideoTrackSource::OnFrameDropped() {
65   broadcaster_.OnDiscardedFrame();
66 }
67 
AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame> * sink,const rtc::VideoSinkWants & wants)68 void AdaptedVideoTrackSource::AddOrUpdateSink(
69     rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
70     const rtc::VideoSinkWants& wants) {
71   broadcaster_.AddOrUpdateSink(sink, wants);
72   OnSinkWantsChanged(broadcaster_.wants());
73 }
74 
RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame> * sink)75 void AdaptedVideoTrackSource::RemoveSink(
76     rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
77   broadcaster_.RemoveSink(sink);
78   OnSinkWantsChanged(broadcaster_.wants());
79 }
80 
apply_rotation()81 bool AdaptedVideoTrackSource::apply_rotation() {
82   return broadcaster_.wants().rotation_applied;
83 }
84 
OnSinkWantsChanged(const rtc::VideoSinkWants & wants)85 void AdaptedVideoTrackSource::OnSinkWantsChanged(
86     const rtc::VideoSinkWants& wants) {
87   video_adapter_.OnSinkWants(wants);
88 }
89 
AdaptFrame(int width,int height,int64_t time_us,int * out_width,int * out_height,int * crop_width,int * crop_height,int * crop_x,int * crop_y)90 bool AdaptedVideoTrackSource::AdaptFrame(int width,
91                                          int height,
92                                          int64_t time_us,
93                                          int* out_width,
94                                          int* out_height,
95                                          int* crop_width,
96                                          int* crop_height,
97                                          int* crop_x,
98                                          int* crop_y) {
99   {
100     webrtc::MutexLock lock(&stats_mutex_);
101     stats_ = Stats{width, height};
102   }
103 
104   if (!broadcaster_.frame_wanted()) {
105     return false;
106   }
107 
108   if (!video_adapter_.AdaptFrameResolution(
109           width, height, time_us * rtc::kNumNanosecsPerMicrosec, crop_width,
110           crop_height, out_width, out_height)) {
111     broadcaster_.OnDiscardedFrame();
112     // VideoAdapter dropped the frame.
113     return false;
114   }
115 
116   *crop_x = (width - *crop_width) / 2;
117   *crop_y = (height - *crop_height) / 2;
118   return true;
119 }
120 
ProcessConstraints(const webrtc::VideoTrackSourceConstraints & constraints)121 void AdaptedVideoTrackSource::ProcessConstraints(
122     const webrtc::VideoTrackSourceConstraints& constraints) {
123   broadcaster_.ProcessConstraints(constraints);
124 }
125 
126 }  // namespace rtc
127