blob: 9513be8230ed7e5a3d6f8acdc474f8a66424c52b [file] [log] [blame]
nisse6f5a6c32016-09-22 01:25:59 -07001/*
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 "webrtc/media/base/adaptedvideotracksource.h"
12
nisseaf916892017-01-10 07:44:26 -080013#include "webrtc/api/video/i420_buffer.h"
14
nisse6f5a6c32016-09-22 01:25:59 -070015namespace rtc {
16
17AdaptedVideoTrackSource::AdaptedVideoTrackSource() {
18 thread_checker_.DetachFromThread();
19}
20
kthelgasonc8474172016-12-08 08:04:51 -080021AdaptedVideoTrackSource::AdaptedVideoTrackSource(int required_alignment)
22 : video_adapter_(required_alignment) {
23 thread_checker_.DetachFromThread();
24}
25
nisse6f5a6c32016-09-22 01:25:59 -070026bool AdaptedVideoTrackSource::GetStats(Stats* stats) {
27 rtc::CritScope lock(&stats_crit_);
28
29 if (!stats_) {
30 return false;
31 }
32
33 *stats = *stats_;
34 return true;
35}
36
nisseacd935b2016-11-11 03:55:13 -080037void AdaptedVideoTrackSource::OnFrame(const webrtc::VideoFrame& frame) {
nisse6f5a6c32016-09-22 01:25:59 -070038 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer(
39 frame.video_frame_buffer());
40 /* Note that this is a "best effort" approach to
41 wants.rotation_applied; apply_rotation_ can change from false to
42 true between the check of apply_rotation() and the call to
43 broadcaster_.OnFrame(), in which case we generate a frame with
44 pending rotation despite some sink with wants.rotation_applied ==
45 true was just added. The VideoBroadcaster enforces
46 synchronization for us in this case, by not passing the frame on
47 to sinks which don't want it. */
magjed3f075492017-06-01 10:02:26 -070048 if (apply_rotation() && frame.rotation() != webrtc::kVideoRotation_0 &&
49 buffer->type() == webrtc::VideoFrameBuffer::Type::kI420) {
nisse6f5a6c32016-09-22 01:25:59 -070050 /* Apply pending rotation. */
nisseacd935b2016-11-11 03:55:13 -080051 broadcaster_.OnFrame(webrtc::VideoFrame(
magjed3f075492017-06-01 10:02:26 -070052 webrtc::I420Buffer::Rotate(*buffer->GetI420(), frame.rotation()),
nisse6f5a6c32016-09-22 01:25:59 -070053 webrtc::kVideoRotation_0, frame.timestamp_us()));
54 } else {
55 broadcaster_.OnFrame(frame);
56 }
57}
58
59void AdaptedVideoTrackSource::AddOrUpdateSink(
nisseacd935b2016-11-11 03:55:13 -080060 rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
nisse6f5a6c32016-09-22 01:25:59 -070061 const rtc::VideoSinkWants& wants) {
62 RTC_DCHECK(thread_checker_.CalledOnValidThread());
63
64 broadcaster_.AddOrUpdateSink(sink, wants);
65 OnSinkWantsChanged(broadcaster_.wants());
66}
67
68void AdaptedVideoTrackSource::RemoveSink(
nisseacd935b2016-11-11 03:55:13 -080069 rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
nisse6f5a6c32016-09-22 01:25:59 -070070 RTC_DCHECK(thread_checker_.CalledOnValidThread());
71
72 broadcaster_.RemoveSink(sink);
73 OnSinkWantsChanged(broadcaster_.wants());
74}
75
76bool AdaptedVideoTrackSource::apply_rotation() {
77 return broadcaster_.wants().rotation_applied;
78}
79
80void AdaptedVideoTrackSource::OnSinkWantsChanged(
81 const rtc::VideoSinkWants& wants) {
82 RTC_DCHECK(thread_checker_.CalledOnValidThread());
sprangc5d62e22017-04-02 23:53:04 -070083 video_adapter_.OnResolutionFramerateRequest(
84 wants.target_pixel_count, wants.max_pixel_count, wants.max_framerate_fps);
nisse6f5a6c32016-09-22 01:25:59 -070085}
86
87bool AdaptedVideoTrackSource::AdaptFrame(int width,
88 int height,
89 int64_t time_us,
90 int* out_width,
91 int* out_height,
92 int* crop_width,
93 int* crop_height,
94 int* crop_x,
95 int* crop_y) {
96 {
97 rtc::CritScope lock(&stats_crit_);
98 stats_ = rtc::Optional<Stats>({width, height});
99 }
100
101 if (!broadcaster_.frame_wanted()) {
102 return false;
103 }
104
105 if (!video_adapter_.AdaptFrameResolution(
106 width, height, time_us * rtc::kNumNanosecsPerMicrosec,
107 crop_width, crop_height, out_width, out_height)) {
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