• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame> * sink,const rtc::VideoSinkWants & wants)64 void AdaptedVideoTrackSource::AddOrUpdateSink(
65     rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
66     const rtc::VideoSinkWants& wants) {
67   broadcaster_.AddOrUpdateSink(sink, wants);
68   OnSinkWantsChanged(broadcaster_.wants());
69 }
70 
RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame> * sink)71 void AdaptedVideoTrackSource::RemoveSink(
72     rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
73   broadcaster_.RemoveSink(sink);
74   OnSinkWantsChanged(broadcaster_.wants());
75 }
76 
apply_rotation()77 bool AdaptedVideoTrackSource::apply_rotation() {
78   return broadcaster_.wants().rotation_applied;
79 }
80 
OnSinkWantsChanged(const rtc::VideoSinkWants & wants)81 void AdaptedVideoTrackSource::OnSinkWantsChanged(
82     const rtc::VideoSinkWants& wants) {
83   video_adapter_.OnSinkWants(wants);
84 }
85 
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)86 bool AdaptedVideoTrackSource::AdaptFrame(int width,
87                                          int height,
88                                          int64_t time_us,
89                                          int* out_width,
90                                          int* out_height,
91                                          int* crop_width,
92                                          int* crop_height,
93                                          int* crop_x,
94                                          int* crop_y) {
95   {
96     webrtc::MutexLock lock(&stats_mutex_);
97     stats_ = Stats{width, height};
98   }
99 
100   if (!broadcaster_.frame_wanted()) {
101     return false;
102   }
103 
104   if (!video_adapter_.AdaptFrameResolution(
105           width, height, time_us * rtc::kNumNanosecsPerMicrosec, crop_width,
106           crop_height, out_width, out_height)) {
107     broadcaster_.OnDiscardedFrame();
108     // VideoAdapter dropped the frame.
109     return false;
110   }
111 
112   *crop_x = (width - *crop_width) / 2;
113   *crop_y = (height - *crop_height) / 2;
114   return true;
115 }
116 
117 }  // namespace rtc
118