Use non-proxied source object in VideoTrack.

Use the internal representation of the video source object from the
track. Before there were implicit thread hops due to use of the proxy.

Also, override AudioTrack's enabled methods to enforce thread
expectations.

Bug: webrtc:13540
Change-Id: I4bc7aca96d6fc24f31ade45e47f52599f1cc2f97
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/250180
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35911}
This commit is contained in:
Tommi 2022-02-04 16:44:37 +01:00 committed by WebRTC LUCI CQ
parent bab128555a
commit 3eb29c1235
7 changed files with 52 additions and 30 deletions

View File

@ -868,6 +868,7 @@ rtc_library("video_track") {
"../api:sequence_checker",
"../api/video:video_frame",
"../media:rtc_media_base",
"../pc:rtc_pc_base",
"../rtc_base",
"../rtc_base:checks",
"../rtc_base:refcount",

View File

@ -42,6 +42,16 @@ std::string AudioTrack::kind() const {
return kAudioKind;
}
bool AudioTrack::set_enabled(bool enable) {
RTC_DCHECK_RUN_ON(&thread_checker_);
return MediaStreamTrack<AudioTrackInterface>::set_enabled(enable);
}
bool AudioTrack::enabled() const {
RTC_DCHECK_RUN_ON(&thread_checker_);
return MediaStreamTrack<AudioTrackInterface>::enabled();
}
AudioSourceInterface* AudioTrack::GetSource() const {
// Callable from any thread.
return audio_source_.get();

View File

@ -41,6 +41,11 @@ class AudioTrack : public MediaStreamTrack<AudioTrackInterface>,
// MediaStreamTrack implementation.
std::string kind() const override;
// NOTE: `set_enabled` and `enabled` are overridden only to ensure threading
// expectations consistent with what's declared in media_stream_track_proxy.h.
bool set_enabled(bool enable) override;
bool enabled() const override;
// AudioTrackInterface implementation.
AudioSourceInterface* GetSource() const override;

View File

@ -29,12 +29,12 @@ BYPASS_PROXY_CONSTMETHOD0(std::string, kind)
BYPASS_PROXY_CONSTMETHOD0(std::string, id)
PROXY_CONSTMETHOD0(TrackState, state)
PROXY_CONSTMETHOD0(bool, enabled)
PROXY_METHOD1(bool, set_enabled, bool)
BYPASS_PROXY_CONSTMETHOD0(AudioSourceInterface*, GetSource)
PROXY_METHOD1(void, AddSink, AudioTrackSinkInterface*)
PROXY_METHOD1(void, RemoveSink, AudioTrackSinkInterface*)
PROXY_METHOD1(bool, GetSignalLevel, int*)
PROXY_METHOD0(rtc::scoped_refptr<AudioProcessorInterface>, GetAudioProcessor)
PROXY_METHOD1(bool, set_enabled, bool)
PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
END_PROXY_MAP(AudioTrack)
@ -43,7 +43,7 @@ BEGIN_PROXY_MAP(VideoTrack)
PROXY_PRIMARY_THREAD_DESTRUCTOR()
BYPASS_PROXY_CONSTMETHOD0(std::string, kind)
BYPASS_PROXY_CONSTMETHOD0(std::string, id)
PROXY_SECONDARY_CONSTMETHOD0(TrackState, state)
PROXY_CONSTMETHOD0(TrackState, state)
PROXY_SECONDARY_CONSTMETHOD0(bool, enabled)
PROXY_SECONDARY_METHOD1(bool, set_enabled, bool)
PROXY_SECONDARY_CONSTMETHOD0(ContentHint, content_hint)

View File

@ -41,11 +41,7 @@ VideoRtpReceiver::VideoRtpReceiver(
track_(VideoTrackProxyWithInternal<VideoTrack>::Create(
rtc::Thread::Current(),
worker_thread,
VideoTrack::Create(receiver_id,
CreateVideoTrackSourceProxy(rtc::Thread::Current(),
worker_thread,
source_),
worker_thread))),
VideoTrack::Create(receiver_id, source_, worker_thread))),
attachment_id_(GenerateUniqueId()) {
RTC_DCHECK(worker_thread_);
SetStreams(streams);

View File

@ -22,12 +22,14 @@
namespace webrtc {
VideoTrack::VideoTrack(const std::string& label,
VideoTrackSourceInterface* video_source,
rtc::Thread* worker_thread)
VideoTrack::VideoTrack(
const std::string& label,
rtc::scoped_refptr<
VideoTrackSourceProxyWithInternal<VideoTrackSourceInterface>> source,
rtc::Thread* worker_thread)
: MediaStreamTrack<VideoTrackInterface>(label),
worker_thread_(worker_thread),
video_source_(video_source),
video_source_(std::move(source)),
content_hint_(ContentHint::kNone) {
RTC_DCHECK_RUN_ON(&signaling_thread_);
// Detach the thread checker for VideoSourceBaseGuarded since we'll make calls
@ -54,18 +56,18 @@ void VideoTrack::AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
VideoSourceBaseGuarded::AddOrUpdateSink(sink, wants);
rtc::VideoSinkWants modified_wants = wants;
modified_wants.black_frames = !enabled();
video_source_->AddOrUpdateSink(sink, modified_wants);
video_source_->internal()->AddOrUpdateSink(sink, modified_wants);
}
void VideoTrack::RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
RTC_DCHECK_RUN_ON(worker_thread_);
VideoSourceBaseGuarded::RemoveSink(sink);
video_source_->RemoveSink(sink);
video_source_->internal()->RemoveSink(sink);
}
void VideoTrack::RequestRefreshFrame() {
RTC_DCHECK_RUN_ON(worker_thread_);
video_source_->RequestRefreshFrame();
video_source_->internal()->RequestRefreshFrame();
}
VideoTrackSourceInterface* VideoTrack::GetSource() const {
@ -88,10 +90,11 @@ void VideoTrack::set_content_hint(ContentHint hint) {
bool VideoTrack::set_enabled(bool enable) {
RTC_DCHECK_RUN_ON(worker_thread_);
auto* source = video_source_->internal();
for (auto& sink_pair : sink_pairs()) {
rtc::VideoSinkWants modified_wants = sink_pair.wants;
modified_wants.black_frames = !enable;
video_source_->AddOrUpdateSink(sink_pair.sink, modified_wants);
source->AddOrUpdateSink(sink_pair.sink, modified_wants);
}
return MediaStreamTrack<VideoTrackInterface>::set_enabled(enable);
}
@ -102,28 +105,29 @@ bool VideoTrack::enabled() const {
}
MediaStreamTrackInterface::TrackState VideoTrack::state() const {
RTC_DCHECK_RUN_ON(worker_thread_);
RTC_DCHECK_RUN_ON(&signaling_thread_);
return MediaStreamTrack<VideoTrackInterface>::state();
}
void VideoTrack::OnChanged() {
RTC_DCHECK_RUN_ON(&signaling_thread_);
worker_thread_->Invoke<void>(
RTC_FROM_HERE, [this, state = video_source_->state()]() {
// TODO(tommi): Calling set_state() this way isn't ideal since we're
// currently blocking the signaling thread and set_state() may
// internally fire notifications via `FireOnChanged()` which may further
// amplify the blocking effect on the signaling thread.
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
set_state(state == MediaSourceInterface::kEnded ? kEnded : kLive);
});
auto* source = video_source_->internal();
auto state = source->state();
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
set_state(state == MediaSourceInterface::kEnded ? kEnded : kLive);
}
rtc::scoped_refptr<VideoTrack> VideoTrack::Create(
const std::string& id,
VideoTrackSourceInterface* source,
rtc::Thread* worker_thread) {
return rtc::make_ref_counted<VideoTrack>(id, source, worker_thread);
rtc::scoped_refptr<
VideoTrackSourceProxyWithInternal<VideoTrackSourceInterface>>
source_proxy = VideoTrackSourceProxy::Create(rtc::Thread::Current(),
worker_thread, source);
return rtc::make_ref_counted<VideoTrack>(id, std::move(source_proxy),
worker_thread);
}
} // namespace webrtc

View File

@ -21,6 +21,7 @@
#include "api/video/video_sink_interface.h"
#include "api/video/video_source_interface.h"
#include "media/base/video_source_base.h"
#include "pc/video_track_source_proxy.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h"
@ -49,9 +50,11 @@ class VideoTrack : public MediaStreamTrack<VideoTrackInterface>,
std::string kind() const override;
protected:
VideoTrack(const std::string& id,
VideoTrackSourceInterface* video_source,
rtc::Thread* worker_thread);
VideoTrack(
const std::string& id,
rtc::scoped_refptr<
VideoTrackSourceProxyWithInternal<VideoTrackSourceInterface>> source,
rtc::Thread* worker_thread);
~VideoTrack();
private:
@ -60,7 +63,10 @@ class VideoTrack : public MediaStreamTrack<VideoTrackInterface>,
RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker signaling_thread_;
rtc::Thread* const worker_thread_;
const rtc::scoped_refptr<VideoTrackSourceInterface> video_source_;
const rtc::scoped_refptr<
VideoTrackSourceProxyWithInternal<VideoTrackSourceInterface>>
video_source_;
ContentHint content_hint_ RTC_GUARDED_BY(worker_thread_);
};