Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start/Stop receiving stream method for VideoTrack #25

Merged
merged 8 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/media_stream_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ const char* const MediaStreamTrackInterface::kVideoKind =
const char* const MediaStreamTrackInterface::kAudioKind =
cricket::kMediaTypeAudio;

bool VideoTrackInterface::should_receive() const {
return true;
}

VideoTrackInterface::ContentHint VideoTrackInterface::content_hint() const {
return ContentHint::kNone;
}
Expand Down
2 changes: 2 additions & 0 deletions api/media_stream_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ class RTC_EXPORT VideoTrackInterface

virtual VideoTrackSourceInterface* GetSource() const = 0;

virtual void set_should_receive(bool should_receive) {}
virtual bool should_receive() const;
virtual ContentHint content_hint() const;
virtual void set_content_hint(ContentHint hint) {}

Expand Down
3 changes: 3 additions & 0 deletions media/base/media_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,9 @@ class VideoMediaChannel : public MediaChannel, public Delayable {
virtual void GenerateKeyFrame(uint32_t ssrc) = 0;

virtual std::vector<webrtc::RtpSource> GetSources(uint32_t ssrc) const = 0;

virtual void StartReceive(uint32_t ssrc) {}
virtual void StopReceive(uint32_t ssrc) {}
};

// Info about data received in DataMediaChannel. For use in
Expand Down
29 changes: 29 additions & 0 deletions media/engine/webrtc_video_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,24 @@ void WebRtcVideoChannel::RequestEncoderSwitch(
<< format.ToString() << " not negotiated.";
}

void WebRtcVideoChannel::StartReceive(uint32_t ssrc) {
RTC_DCHECK_RUN_ON(&thread_checker_);
WebRtcVideoReceiveStream* stream = FindReceiveStream(ssrc);
if(!stream) {
return;
}
stream->StartStream();
}

void WebRtcVideoChannel::StopReceive(uint32_t ssrc) {
RTC_DCHECK_RUN_ON(&thread_checker_);
WebRtcVideoReceiveStream* stream = FindReceiveStream(ssrc);
if(!stream) {
return;
}
stream->StopStream();
}

bool WebRtcVideoChannel::ApplyChangedParams(
const ChangedSendParameters& changed_params) {
RTC_DCHECK_RUN_ON(&thread_checker_);
Expand Down Expand Up @@ -3017,6 +3035,17 @@ void WebRtcVideoChannel::WebRtcVideoReceiveStream::SetRecvParameters(
}
}

void WebRtcVideoChannel::WebRtcVideoReceiveStream::StartStream(){
if (stream_) {
stream_->Start();
}
}
void WebRtcVideoChannel::WebRtcVideoReceiveStream::StopStream(){
if (stream_) {
stream_->Stop();
}
}

void WebRtcVideoChannel::WebRtcVideoReceiveStream::RecreateWebRtcVideoStream() {
absl::optional<int> base_minimum_playout_delay_ms;
absl::optional<webrtc::VideoReceiveStream::RecordingState> recording_state;
Expand Down
6 changes: 5 additions & 1 deletion media/engine/webrtc_video_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ class WebRtcVideoChannel : public VideoMediaChannel,
uint32_t ssrc,
rtc::scoped_refptr<webrtc::FrameTransformerInterface> frame_transformer)
override;

void StartReceive(uint32_t ssrc) override;
void StopReceive(uint32_t ssrc) override;
private:
class WebRtcVideoReceiveStream;

Expand Down Expand Up @@ -479,6 +480,9 @@ class WebRtcVideoChannel : public VideoMediaChannel,
void SetDepacketizerToDecoderFrameTransformer(
rtc::scoped_refptr<webrtc::FrameTransformerInterface>
frame_transformer);

void StartStream();
void StopStream();

private:
void RecreateWebRtcVideoStream();
Expand Down
7 changes: 7 additions & 0 deletions modules/video_coding/frame_buffer2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,13 @@ void FrameBuffer::SetProtectionMode(VCMVideoProtection mode) {
protection_mode_ = mode;
}

void FrameBuffer::Start() {
TRACE_EVENT0("webrtc", "FrameBuffer::Stop");
MutexLock lock(&mutex_);
if (!stopped_)
return;
stopped_ = false;
}
void FrameBuffer::Stop() {
TRACE_EVENT0("webrtc", "FrameBuffer::Stop");
MutexLock lock(&mutex_);
Expand Down
2 changes: 2 additions & 0 deletions modules/video_coding/frame_buffer2.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class FrameBuffer {
// Stop the frame buffer, causing any sleeping thread in NextFrame to
// return immediately.
void Stop();
// Unstop the frame buffer, re-allowing new frames to be inserted and read.
void Start();

// Updates the RTT for jitter buffer estimation.
void UpdateRtt(int64_t rtt_ms);
Expand Down
10 changes: 6 additions & 4 deletions pc/media_stream_track_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,18 @@ PROXY_PRIMARY_THREAD_DESTRUCTOR()
BYPASS_PROXY_CONSTMETHOD0(std::string, kind)
BYPASS_PROXY_CONSTMETHOD0(std::string, id)
PROXY_SECONDARY_CONSTMETHOD0(TrackState, state)
PROXY_SECONDARY_CONSTMETHOD0(bool, enabled)
PROXY_SECONDARY_METHOD1(bool, set_enabled, bool)
PROXY_SECONDARY_CONSTMETHOD0(ContentHint, content_hint)
PROXY_SECONDARY_METHOD1(void, set_content_hint, ContentHint)
PROXY_CONSTMETHOD0(bool, enabled)
PROXY_METHOD1(bool, set_enabled, bool)
PROXY_CONSTMETHOD0(ContentHint, content_hint)
PROXY_METHOD1(void, set_content_hint, ContentHint)
PROXY_SECONDARY_METHOD2(void,
AddOrUpdateSink,
rtc::VideoSinkInterface<VideoFrame>*,
const rtc::VideoSinkWants&)
PROXY_SECONDARY_METHOD1(void, RemoveSink, rtc::VideoSinkInterface<VideoFrame>*)
BYPASS_PROXY_CONSTMETHOD0(VideoTrackSourceInterface*, GetSource)
PROXY_CONSTMETHOD0(bool, should_receive)
PROXY_METHOD1(void, set_should_receive, bool)

PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
Expand Down
7 changes: 5 additions & 2 deletions pc/rtp_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -584,10 +584,13 @@ VideoRtpSender::~VideoRtpSender() {
}

void VideoRtpSender::OnChanged() {
// Running on the signaling thread.
TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
RTC_DCHECK(!stopped_);
if (cached_track_content_hint_ != video_track()->content_hint()) {
cached_track_content_hint_ = video_track()->content_hint();

auto content_hint = video_track()->content_hint();
if (cached_track_content_hint_ != content_hint) {
cached_track_content_hint_ = content_hint;
if (can_send_track()) {
SetSend();
}
Expand Down
43 changes: 41 additions & 2 deletions pc/video_rtp_receiver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "rtc_base/checks.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/task_utils/to_queued_task.h"

namespace webrtc {

Expand All @@ -46,9 +47,12 @@ VideoRtpReceiver::VideoRtpReceiver(
worker_thread,
source_),
worker_thread))),
attachment_id_(GenerateUniqueId()) {
cached_track_should_receive_(track_->should_receive()),
attachment_id_(GenerateUniqueId()),
worker_thread_safety_(PendingTaskSafetyFlag::CreateDetachedInactive()) {
RTC_DCHECK(worker_thread_);
SetStreams(streams);
track_->RegisterObserver(this);
RTC_DCHECK_EQ(source_->state(), MediaSourceInterface::kLive);
}

Expand Down Expand Up @@ -137,6 +141,39 @@ void VideoRtpReceiver::StopAndEndTrack() {
track_->internal()->set_ended();
}

void VideoRtpReceiver::OnChanged() {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
if (cached_track_should_receive_ != track_->should_receive()) {
cached_track_should_receive_ = track_->should_receive();
worker_thread_->PostTask(ToQueuedTask(
worker_thread_safety_,
[this, receive = cached_track_should_receive_]() {
RTC_DCHECK_RUN_ON(worker_thread_);
if(receive) {
StartMediaChannel();
} else {
StopMediaChannel();
}
}));
}
}

void VideoRtpReceiver::StartMediaChannel() {
RTC_DCHECK_RUN_ON(worker_thread_);
if (!media_channel_) {
return;
}
media_channel_->StartReceive(ssrc_.value_or(0));
OnGenerateKeyFrame();
}
void VideoRtpReceiver::StopMediaChannel() {
RTC_DCHECK_RUN_ON(worker_thread_);
if (!media_channel_) {
return;
}
media_channel_->StopReceive(ssrc_.value_or(0));
}

void VideoRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);

Expand Down Expand Up @@ -235,6 +272,7 @@ void VideoRtpReceiver::set_transport(
void VideoRtpReceiver::SetStreams(
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);

// Remove remote track from any streams that are going away.
for (const auto& existing_stream : streams_) {
bool removed = true;
Expand Down Expand Up @@ -301,13 +339,14 @@ void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
void VideoRtpReceiver::SetMediaChannel_w(cricket::MediaChannel* media_channel) {
if (media_channel == media_channel_)
return;

bool encoded_sink_enabled = saved_encoded_sink_enabled_;
if (encoded_sink_enabled && media_channel_) {
// Turn off the old sink, if any.
SetEncodedSinkEnabled(false);
}

media_channel ? worker_thread_safety_->SetAlive()
: worker_thread_safety_->SetNotAlive();
media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);

if (media_channel_) {
Expand Down
11 changes: 10 additions & 1 deletion pc/video_rtp_receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@

namespace webrtc {

class VideoRtpReceiver : public RtpReceiverInternal {
class VideoRtpReceiver : public RtpReceiverInternal,
public ObserverInterface {
public:
// An SSRC of 0 will create a receiver that will match the first SSRC it
// sees. Must be called on signaling thread.
Expand All @@ -61,6 +62,9 @@ class VideoRtpReceiver : public RtpReceiverInternal {

rtc::scoped_refptr<VideoTrackInterface> video_track() const { return track_; }

// ObserverInterface implementation
void OnChanged() override;

// RtpReceiverInterface implementation
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
return track_;
Expand Down Expand Up @@ -111,6 +115,8 @@ class VideoRtpReceiver : public RtpReceiverInternal {
std::vector<RtpSource> GetSources() const override;

private:
void StartMediaChannel();
void StopMediaChannel();
void RestartMediaChannel(absl::optional<uint32_t> ssrc);
void SetSink(rtc::VideoSinkInterface<VideoFrame>* sink)
RTC_RUN_ON(worker_thread_);
Expand Down Expand Up @@ -165,6 +171,8 @@ class VideoRtpReceiver : public RtpReceiverInternal {
RTC_GUARDED_BY(&signaling_thread_checker_) = nullptr;
bool received_first_packet_ RTC_GUARDED_BY(&signaling_thread_checker_) =
false;

bool cached_track_should_receive_ RTC_GUARDED_BY(&signaling_thread_checker_);
const int attachment_id_;
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_
RTC_GUARDED_BY(worker_thread_);
Expand All @@ -180,6 +188,7 @@ class VideoRtpReceiver : public RtpReceiverInternal {
// or switched.
bool saved_generate_keyframe_ RTC_GUARDED_BY(worker_thread_) = false;
bool saved_encoded_sink_enabled_ RTC_GUARDED_BY(worker_thread_) = false;
const rtc::scoped_refptr<PendingTaskSafetyFlag> worker_thread_safety_;
};

} // namespace webrtc
Expand Down
60 changes: 40 additions & 20 deletions pc/video_track.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "rtc_base/checks.h"
#include "rtc_base/location.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/logging.h"

namespace webrtc {

Expand Down Expand Up @@ -53,7 +54,7 @@ void VideoTrack::AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
RTC_DCHECK_RUN_ON(worker_thread_);
VideoSourceBaseGuarded::AddOrUpdateSink(sink, wants);
rtc::VideoSinkWants modified_wants = wants;
modified_wants.black_frames = !enabled();
modified_wants.black_frames = !enabled_w_;
video_source_->AddOrUpdateSink(sink, modified_wants);
}

Expand All @@ -68,31 +69,56 @@ VideoTrackSourceInterface* VideoTrack::GetSource() const {
return video_source_.get();
}

void VideoTrack::set_should_receive(bool receive) {
RTC_DCHECK_RUN_ON(&signaling_thread_);
if (should_receive_ == receive)
return;
should_receive_ = receive;
Notifier<VideoTrackInterface>::FireOnChanged();
}

bool VideoTrack::should_receive() const {
RTC_DCHECK_RUN_ON(&signaling_thread_);
return should_receive_;
}

VideoTrackInterface::ContentHint VideoTrack::content_hint() const {
RTC_DCHECK_RUN_ON(worker_thread_);
RTC_DCHECK_RUN_ON(&signaling_thread_);
return content_hint_;
}

void VideoTrack::set_content_hint(ContentHint hint) {
RTC_DCHECK_RUN_ON(worker_thread_);
RTC_DCHECK_RUN_ON(&signaling_thread_);
if (content_hint_ == hint)
return;
content_hint_ = hint;
Notifier<VideoTrackInterface>::FireOnChanged();
}

bool VideoTrack::set_enabled(bool enable) {
RTC_DCHECK_RUN_ON(worker_thread_);
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);
}
return MediaStreamTrack<VideoTrackInterface>::set_enabled(enable);
RTC_DCHECK_RUN_ON(&signaling_thread_);

bool ret = MediaStreamTrack<VideoTrackInterface>::set_enabled(enable);

worker_thread_->Invoke<void>(RTC_FROM_HERE, [&]() {
RTC_DCHECK_RUN_ON(worker_thread_);
enabled_w_ = enable;
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);
}
});

return ret;
}

bool VideoTrack::enabled() const {
RTC_DCHECK_RUN_ON(worker_thread_);
if (worker_thread_->IsCurrent()) {
RTC_DCHECK_RUN_ON(worker_thread_);
return enabled_w_;
}
RTC_DCHECK_RUN_ON(&signaling_thread_);
return MediaStreamTrack<VideoTrackInterface>::enabled();
}

Expand All @@ -103,15 +129,9 @@ MediaStreamTrackInterface::TrackState VideoTrack::state() const {

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);
});
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
MediaSourceInterface::SourceState state = video_source_->state();
set_state(state == MediaSourceInterface::kEnded ? kEnded : kLive);
}

rtc::scoped_refptr<VideoTrack> VideoTrack::Create(
Expand Down
Loading