1 /*
2 * Copyright 2011 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 "pc/video_track.h"
12
13 #include <utility>
14 #include <vector>
15
16 #include "api/notifier.h"
17 #include "api/sequence_checker.h"
18 #include "rtc_base/checks.h"
19
20 namespace webrtc {
21
VideoTrack(absl::string_view label,rtc::scoped_refptr<VideoTrackSourceProxyWithInternal<VideoTrackSourceInterface>> source,rtc::Thread * worker_thread)22 VideoTrack::VideoTrack(
23 absl::string_view label,
24 rtc::scoped_refptr<
25 VideoTrackSourceProxyWithInternal<VideoTrackSourceInterface>> source,
26 rtc::Thread* worker_thread)
27 : MediaStreamTrack<VideoTrackInterface>(label),
28 worker_thread_(worker_thread),
29 video_source_(std::move(source)),
30 content_hint_(ContentHint::kNone) {
31 RTC_DCHECK_RUN_ON(&signaling_thread_);
32 // Detach the thread checker for VideoSourceBaseGuarded since we'll make calls
33 // to VideoSourceBaseGuarded on the worker thread, but we're currently on the
34 // signaling thread.
35 source_sequence_.Detach();
36 video_source_->RegisterObserver(this);
37 }
38
~VideoTrack()39 VideoTrack::~VideoTrack() {
40 RTC_DCHECK_RUN_ON(&signaling_thread_);
41 video_source_->UnregisterObserver(this);
42 }
43
kind() const44 std::string VideoTrack::kind() const {
45 return kVideoKind;
46 }
47
48 // AddOrUpdateSink and RemoveSink should be called on the worker
49 // thread.
AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame> * sink,const rtc::VideoSinkWants & wants)50 void VideoTrack::AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
51 const rtc::VideoSinkWants& wants) {
52 RTC_DCHECK_RUN_ON(worker_thread_);
53 VideoSourceBaseGuarded::AddOrUpdateSink(sink, wants);
54 rtc::VideoSinkWants modified_wants = wants;
55 modified_wants.black_frames = !enabled_w_;
56 video_source_->internal()->AddOrUpdateSink(sink, modified_wants);
57 }
58
RemoveSink(rtc::VideoSinkInterface<VideoFrame> * sink)59 void VideoTrack::RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
60 RTC_DCHECK_RUN_ON(worker_thread_);
61 VideoSourceBaseGuarded::RemoveSink(sink);
62 video_source_->internal()->RemoveSink(sink);
63 }
64
RequestRefreshFrame()65 void VideoTrack::RequestRefreshFrame() {
66 RTC_DCHECK_RUN_ON(worker_thread_);
67 video_source_->internal()->RequestRefreshFrame();
68 }
69
GetSource() const70 VideoTrackSourceInterface* VideoTrack::GetSource() const {
71 // Callable from any thread.
72 return video_source_.get();
73 }
74
GetSourceInternal() const75 VideoTrackSourceInterface* VideoTrack::GetSourceInternal() const {
76 return video_source_->internal();
77 }
78
content_hint() const79 VideoTrackInterface::ContentHint VideoTrack::content_hint() const {
80 RTC_DCHECK_RUN_ON(&signaling_thread_);
81 return content_hint_;
82 }
83
set_content_hint(ContentHint hint)84 void VideoTrack::set_content_hint(ContentHint hint) {
85 RTC_DCHECK_RUN_ON(&signaling_thread_);
86 if (content_hint_ == hint)
87 return;
88 content_hint_ = hint;
89 Notifier<VideoTrackInterface>::FireOnChanged();
90 }
91
set_enabled(bool enable)92 bool VideoTrack::set_enabled(bool enable) {
93 RTC_DCHECK_RUN_ON(&signaling_thread_);
94
95 bool ret = MediaStreamTrack<VideoTrackInterface>::set_enabled(enable);
96
97 worker_thread_->BlockingCall([&]() {
98 RTC_DCHECK_RUN_ON(worker_thread_);
99 enabled_w_ = enable;
100 for (auto& sink_pair : sink_pairs()) {
101 rtc::VideoSinkWants modified_wants = sink_pair.wants;
102 modified_wants.black_frames = !enable;
103 video_source_->AddOrUpdateSink(sink_pair.sink, modified_wants);
104 }
105 });
106
107 return ret;
108 }
109
enabled() const110 bool VideoTrack::enabled() const {
111 if (worker_thread_->IsCurrent()) {
112 RTC_DCHECK_RUN_ON(worker_thread_);
113 return enabled_w_;
114 }
115 RTC_DCHECK_RUN_ON(&signaling_thread_);
116 return MediaStreamTrack<VideoTrackInterface>::enabled();
117 }
118
state() const119 MediaStreamTrackInterface::TrackState VideoTrack::state() const {
120 RTC_DCHECK_RUN_ON(worker_thread_);
121 return MediaStreamTrack<VideoTrackInterface>::state();
122 }
123
OnChanged()124 void VideoTrack::OnChanged() {
125 RTC_DCHECK_RUN_ON(&signaling_thread_);
126 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
127 MediaSourceInterface::SourceState state = video_source_->state();
128 set_state(state == MediaSourceInterface::kEnded ? kEnded : kLive);
129 }
130
Create(absl::string_view id,rtc::scoped_refptr<VideoTrackSourceInterface> source,rtc::Thread * worker_thread)131 rtc::scoped_refptr<VideoTrack> VideoTrack::Create(
132 absl::string_view id,
133 rtc::scoped_refptr<VideoTrackSourceInterface> source,
134 rtc::Thread* worker_thread) {
135 rtc::scoped_refptr<
136 VideoTrackSourceProxyWithInternal<VideoTrackSourceInterface>>
137 source_proxy = VideoTrackSourceProxy::Create(
138 rtc::Thread::Current(), worker_thread, std::move(source));
139
140 return rtc::make_ref_counted<VideoTrack>(id, std::move(source_proxy),
141 worker_thread);
142 }
143
144 } // namespace webrtc
145