Skip to content

Commit

Permalink
Start/Stop receiving stream method for VideoTrack (#25)
Browse files Browse the repository at this point in the history
* Initial implementation of start/stop receive

* move set_state call to signalling thread as well.

https://source.chromium.org/chromium/_/webrtc/src.git/+/dfd69c22100e1d2e83295f33d06fa9916caa5c53

* separate should_receive from enabled for now

* ios hooks

* Fix ios compile errors

* code cleanup

* clean up

* reuse frame buffers instead
  • Loading branch information
davidliu authored May 10, 2022
1 parent a4b0722 commit 415fbe5
Show file tree
Hide file tree
Showing 18 changed files with 207 additions and 31 deletions.
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

0 comments on commit 415fbe5

Please sign in to comment.