1 /*
2 * Copyright (c) 2017 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 "test/test_video_capturer.h"
12
13 #include <algorithm>
14
15 #include "api/scoped_refptr.h"
16 #include "api/video/i420_buffer.h"
17 #include "api/video/video_frame_buffer.h"
18 #include "api/video/video_rotation.h"
19
20 namespace webrtc {
21 namespace test {
22 TestVideoCapturer::~TestVideoCapturer() = default;
23
OnFrame(const VideoFrame & original_frame)24 void TestVideoCapturer::OnFrame(const VideoFrame& original_frame) {
25 int cropped_width = 0;
26 int cropped_height = 0;
27 int out_width = 0;
28 int out_height = 0;
29
30 VideoFrame frame = MaybePreprocess(original_frame);
31
32 if (!video_adapter_.AdaptFrameResolution(
33 frame.width(), frame.height(), frame.timestamp_us() * 1000,
34 &cropped_width, &cropped_height, &out_width, &out_height)) {
35 // Drop frame in order to respect frame rate constraint.
36 return;
37 }
38
39 if (out_height != frame.height() || out_width != frame.width()) {
40 // Video adapter has requested a down-scale. Allocate a new buffer and
41 // return scaled version.
42 // For simplicity, only scale here without cropping.
43 rtc::scoped_refptr<I420Buffer> scaled_buffer =
44 I420Buffer::Create(out_width, out_height);
45 scaled_buffer->ScaleFrom(*frame.video_frame_buffer()->ToI420());
46 VideoFrame::Builder new_frame_builder =
47 VideoFrame::Builder()
48 .set_video_frame_buffer(scaled_buffer)
49 .set_rotation(kVideoRotation_0)
50 .set_timestamp_us(frame.timestamp_us())
51 .set_id(frame.id());
52 if (frame.has_update_rect()) {
53 VideoFrame::UpdateRect new_rect = frame.update_rect().ScaleWithFrame(
54 frame.width(), frame.height(), 0, 0, frame.width(), frame.height(),
55 out_width, out_height);
56 new_frame_builder.set_update_rect(new_rect);
57 }
58 broadcaster_.OnFrame(new_frame_builder.build());
59
60 } else {
61 // No adaptations needed, just return the frame as is.
62 broadcaster_.OnFrame(frame);
63 }
64 }
65
GetSinkWants()66 rtc::VideoSinkWants TestVideoCapturer::GetSinkWants() {
67 return broadcaster_.wants();
68 }
69
AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame> * sink,const rtc::VideoSinkWants & wants)70 void TestVideoCapturer::AddOrUpdateSink(
71 rtc::VideoSinkInterface<VideoFrame>* sink,
72 const rtc::VideoSinkWants& wants) {
73 broadcaster_.AddOrUpdateSink(sink, wants);
74 UpdateVideoAdapter();
75 }
76
RemoveSink(rtc::VideoSinkInterface<VideoFrame> * sink)77 void TestVideoCapturer::RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
78 broadcaster_.RemoveSink(sink);
79 UpdateVideoAdapter();
80 }
81
UpdateVideoAdapter()82 void TestVideoCapturer::UpdateVideoAdapter() {
83 video_adapter_.OnSinkWants(broadcaster_.wants());
84 }
85
MaybePreprocess(const VideoFrame & frame)86 VideoFrame TestVideoCapturer::MaybePreprocess(const VideoFrame& frame) {
87 MutexLock lock(&lock_);
88 if (preprocessor_ != nullptr) {
89 return preprocessor_->Preprocess(frame);
90 } else {
91 return frame;
92 }
93 }
94
95 } // namespace test
96 } // namespace webrtc
97