Skip to content

Start/Stop receiving stream method for VideoTrack #11

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

Merged
merged 1 commit into from
Sep 20, 2023
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
2 changes: 2 additions & 0 deletions media/base/media_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,8 @@ class VideoMediaReceiveChannelInterface : public MediaReceiveChannelInterface {
bool nack_enabled,
webrtc::RtcpMode rtcp_mode,
absl::optional<int> rtx_time) = 0;
virtual void StartReceive(uint32_t ssrc) {}
virtual void StopReceive(uint32_t ssrc) {}
};

} // namespace cricket
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 @@ -928,6 +928,24 @@ void WebRtcVideoChannel::RequestEncoderSwitch(
}
}

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 @@ -3182,6 +3200,17 @@ void WebRtcVideoChannel::WebRtcVideoReceiveStream::SetRecvParameters(
}
}

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

void WebRtcVideoChannel::WebRtcVideoReceiveStream::RecreateReceiveStream() {
RTC_DCHECK(stream_);
absl::optional<int> base_minimum_playout_delay_ms;
Expand Down
5 changes: 5 additions & 0 deletions media/engine/webrtc_video_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ class WebRtcVideoChannel : public VideoMediaChannel,
webrtc::RtcpMode rtcp_mode,
absl::optional<int> rtx_time) override;

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

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

void StartStream();
void StopStream();

void SetLocalSsrc(uint32_t local_ssrc);
void UpdateRtxSsrc(uint32_t ssrc);
Expand Down
2 changes: 2 additions & 0 deletions pc/media_stream_track_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ PROXY_SECONDARY_METHOD2(void,
PROXY_SECONDARY_METHOD1(void, RemoveSink, rtc::VideoSinkInterface<VideoFrame>*)
PROXY_SECONDARY_METHOD0(void, RequestRefreshFrame)
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
39 changes: 38 additions & 1 deletion pc/video_rtp_receiver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ VideoRtpReceiver::VideoRtpReceiver(
rtc::Thread::Current(),
worker_thread,
VideoTrack::Create(receiver_id, 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::kInitializing);
}

Expand Down Expand Up @@ -116,6 +119,39 @@ void VideoRtpReceiver::Stop() {
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(
[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(signaled_ssrc_.value_or(0));
OnGenerateKeyFrame();
}

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

void VideoRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
MediaSourceInterface::SourceState state = source_->state();
Expand Down Expand Up @@ -211,6 +247,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
11 changes: 10 additions & 1 deletion pc/video_rtp_receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,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 @@ -60,6 +61,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 @@ -115,6 +119,8 @@ class VideoRtpReceiver : public RtpReceiverInternal {
cricket::MediaReceiveChannelInterface* media_channel);

private:
void StartMediaChannel();
void StopMediaChannel();
void RestartMediaChannel(absl::optional<uint32_t> ssrc)
RTC_RUN_ON(&signaling_thread_checker_);
void RestartMediaChannel_w(absl::optional<uint32_t> ssrc,
Expand Down Expand Up @@ -162,6 +168,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 @@ -177,6 +185,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
13 changes: 13 additions & 0 deletions pc/video_track.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ VideoTrackSourceInterface* VideoTrack::GetSourceInternal() const {
return video_source_->internal();
}

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(&signaling_thread_);
return content_hint_;
Expand Down
4 changes: 4 additions & 0 deletions pc/video_track.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class VideoTrack : public MediaStreamTrack<VideoTrackInterface>,
void RequestRefreshFrame() override;
VideoTrackSourceInterface* GetSource() const override;

void set_should_receive(bool should_receive) override;
bool should_receive() const override;

ContentHint content_hint() const override;
void set_content_hint(ContentHint hint) override;
bool set_enabled(bool enable) override;
Expand Down Expand Up @@ -81,6 +84,7 @@ class VideoTrack : public MediaStreamTrack<VideoTrackInterface>,
// be queried without blocking on the worker thread by callers that don't
// use an api proxy to call the `enabled()` method.
bool enabled_w_ RTC_GUARDED_BY(worker_thread_) = true;
bool should_receive_ RTC_GUARDED_BY(signaling_thread_) = true;
};

} // namespace webrtc
Expand Down
14 changes: 7 additions & 7 deletions sdk/android/api/org/webrtc/PeerConnectionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,13 @@ public static class Options {
// Keep in sync with webrtc/rtc_base/network.h!
//
// These bit fields are defined for `networkIgnoreMask` below.
static final int ADAPTER_TYPE_UNKNOWN = 0;
static final int ADAPTER_TYPE_ETHERNET = 1 << 0;
static final int ADAPTER_TYPE_WIFI = 1 << 1;
static final int ADAPTER_TYPE_CELLULAR = 1 << 2;
static final int ADAPTER_TYPE_VPN = 1 << 3;
static final int ADAPTER_TYPE_LOOPBACK = 1 << 4;
static final int ADAPTER_TYPE_ANY = 1 << 5;
public static final int ADAPTER_TYPE_UNKNOWN = 0;
public static final int ADAPTER_TYPE_ETHERNET = 1 << 0;
public static final int ADAPTER_TYPE_WIFI = 1 << 1;
public static final int ADAPTER_TYPE_CELLULAR = 1 << 2;
public static final int ADAPTER_TYPE_VPN = 1 << 3;
public static final int ADAPTER_TYPE_LOOPBACK = 1 << 4;
public static final int ADAPTER_TYPE_ANY = 1 << 5;

public int networkIgnoreMask;
public boolean disableEncryption;
Expand Down
20 changes: 20 additions & 0 deletions sdk/android/api/org/webrtc/VideoTrack.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,24 @@ public void removeSink(VideoSink sink) {
}
}

/**
* For a remote video track, starts/stops receiving the video stream.
*
* If this is a local video track, this is a no-op.
*/
public void setShouldReceive(boolean shouldReceive){
nativeSetShouldReceive(getNativeMediaStreamTrack(), shouldReceive);
}

/**
* The current receive status for a remote video track.
*
* This has no meaning for a local video track.
*/
public boolean shouldReceive(){
return nativeGetShouldReceive(getNativeMediaStreamTrack());
}

@Override
public void dispose() {
for (long nativeSink : sinks.values()) {
Expand All @@ -73,4 +91,6 @@ long getNativeVideoTrack() {
private static native void nativeRemoveSink(long track, long nativeSink);
private static native long nativeWrapSink(VideoSink sink);
private static native void nativeFreeSink(long sink);
private static native void nativeSetShouldReceive(long track, boolean shouldReceive);
private static native boolean nativeGetShouldReceive(long track);
}
11 changes: 11 additions & 0 deletions sdk/android/src/jni/video_track.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,16 @@ static void JNI_VideoTrack_FreeSink(JNIEnv* jni, jlong j_native_sink) {
delete reinterpret_cast<rtc::VideoSinkInterface<VideoFrame>*>(j_native_sink);
}

static void JNI_VideoTrack_SetShouldReceive(JNIEnv* jni,
jlong j_native_track,
jboolean should_receive) {
reinterpret_cast<VideoTrackInterface*>(j_native_track)->set_should_receive(should_receive);
}

static jboolean JNI_VideoTrack_GetShouldReceive(JNIEnv* jni,
jlong j_native_track) {
return reinterpret_cast<VideoTrackInterface*>(j_native_track)->should_receive();
}

} // namespace jni
} // namespace webrtc
3 changes: 3 additions & 0 deletions sdk/objc/api/peerconnection/RTCVideoTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ RTC_OBJC_EXPORT
/** The video source for this video track. */
@property(nonatomic, readonly) RTC_OBJC_TYPE(RTCVideoSource) *source;

/** The receive state, if this is a remote video track. */
@property(nonatomic, assign) BOOL shouldReceive;

- (instancetype)init NS_UNAVAILABLE;

/** Register a renderer that will render all frames received on this track. */
Expand Down
8 changes: 8 additions & 0 deletions sdk/objc/api/peerconnection/RTCVideoTrack.mm
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ - (void)dealloc {
return _source;
}

- (BOOL)shouldReceive {
return self.nativeVideoTrack->should_receive();
}

- (void)setShouldReceive:(BOOL)shouldReceive {
self.nativeVideoTrack->set_should_receive(shouldReceive);
}

- (void)addRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
if (!_workerThread->IsCurrent()) {
_workerThread->BlockingCall([renderer, self] { [self addRenderer:renderer]; });
Expand Down