xref: /aosp_15_r20/external/webrtc/pc/video_track.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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