Add streams() to RtpReceiverInterface and implementations.

This makes the receiver know about its associated set of streams, the
equivalent of the [[AssociatedRemoteMediaStreams]] slot in the spec,
https://w3c.github.io/webrtc-pc/#dfn-x%5B%5Bassociatedremotemediastreams%5D%5D

This does not change layers below peerconnection.cc. The streams are set
upon the receiver's construction and is not modified for the duration of
its lifetime.

When we support modifying the associated set of streams of a receiver
the receiver needs to know about it. The receiver's streams() should be
used in all places where a receiver's streams need to be known.

Bug: webrtc:8473
Change-Id: I31202973aed98e61fa9b6a78b52e815227b6c17d
Reviewed-on: https://webrtc-review.googlesource.com/22922
Reviewed-by: Peter Thatcher <pthatcher@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20825}
This commit is contained in:
Henrik Boström
2017-11-21 13:41:51 +01:00
committed by Commit Bot
parent dd41194ca4
commit 9e6fd2bd47
8 changed files with 89 additions and 44 deletions

View File

@ -94,6 +94,14 @@ class RtpReceiverObserverInterface {
class RtpReceiverInterface : public rtc::RefCountInterface { class RtpReceiverInterface : public rtc::RefCountInterface {
public: public:
virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0; virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
// The list of streams that |track| is associated with. This is the same as
// the [[AssociatedRemoteMediaStreams]] internal slot in the spec.
// https://w3c.github.io/webrtc-pc/#dfn-x%5B%5Bassociatedremotemediastreams%5D%5D
// TODO(hbos): Make pure virtual as soon as Chromium's mock implements this.
virtual std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
const {
return std::vector<rtc::scoped_refptr<MediaStreamInterface>>();
}
// Audio or video receiver? // Audio or video receiver?
virtual cricket::MediaType media_type() const = 0; virtual cricket::MediaType media_type() const = 0;
@ -130,6 +138,8 @@ class RtpReceiverInterface : public rtc::RefCountInterface {
BEGIN_SIGNALING_PROXY_MAP(RtpReceiver) BEGIN_SIGNALING_PROXY_MAP(RtpReceiver)
PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track) PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<MediaStreamInterface>>,
streams)
PROXY_CONSTMETHOD0(cricket::MediaType, media_type) PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
PROXY_CONSTMETHOD0(std::string, id) PROXY_CONSTMETHOD0(std::string, id)
PROXY_CONSTMETHOD0(RtpParameters, GetParameters); PROXY_CONSTMETHOD0(RtpParameters, GetParameters);

View File

@ -152,13 +152,14 @@ void OrtcRtpReceiverAdapter::MaybeRecreateInternalReceiver() {
switch (kind_) { switch (kind_) {
case cricket::MEDIA_TYPE_AUDIO: case cricket::MEDIA_TYPE_AUDIO:
internal_receiver_ = internal_receiver_ =
new AudioRtpReceiver(rtc::CreateRandomUuid(), ssrc, new AudioRtpReceiver(rtc::CreateRandomUuid(), {}, ssrc,
rtp_transport_controller_->voice_channel()); rtp_transport_controller_->voice_channel());
break; break;
case cricket::MEDIA_TYPE_VIDEO: case cricket::MEDIA_TYPE_VIDEO:
internal_receiver_ = new VideoRtpReceiver( internal_receiver_ =
rtc::CreateRandomUuid(), rtp_transport_controller_->worker_thread(), new VideoRtpReceiver(rtc::CreateRandomUuid(), {},
ssrc, rtp_transport_controller_->video_channel()); rtp_transport_controller_->worker_thread(), ssrc,
rtp_transport_controller_->video_channel());
break; break;
case cricket::MEDIA_TYPE_DATA: case cricket::MEDIA_TYPE_DATA:
RTC_NOTREACHED(); RTC_NOTREACHED();

View File

@ -2079,33 +2079,34 @@ void PeerConnection::OnMessage(rtc::Message* msg) {
void PeerConnection::CreateAudioReceiver( void PeerConnection::CreateAudioReceiver(
MediaStreamInterface* stream, MediaStreamInterface* stream,
const RtpSenderInfo& remote_sender_info) { const RtpSenderInfo& remote_sender_info) {
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>> rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
signaling_thread(), signaling_thread(),
new AudioRtpReceiver(remote_sender_info.sender_id, new AudioRtpReceiver(remote_sender_info.sender_id, streams,
remote_sender_info.first_ssrc, voice_channel())); remote_sender_info.first_ssrc, voice_channel()));
stream->AddTrack( stream->AddTrack(
static_cast<AudioTrackInterface*>(receiver->internal()->track().get())); static_cast<AudioTrackInterface*>(receiver->internal()->track().get()));
GetAudioTransceiver()->internal()->AddReceiver(receiver); GetAudioTransceiver()->internal()->AddReceiver(receiver);
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams; observer_->OnAddTrack(receiver, std::move(streams));
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
observer_->OnAddTrack(receiver, streams);
} }
void PeerConnection::CreateVideoReceiver( void PeerConnection::CreateVideoReceiver(
MediaStreamInterface* stream, MediaStreamInterface* stream,
const RtpSenderInfo& remote_sender_info) { const RtpSenderInfo& remote_sender_info) {
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>> rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
signaling_thread(), signaling_thread(),
new VideoRtpReceiver(remote_sender_info.sender_id, worker_thread(), new VideoRtpReceiver(remote_sender_info.sender_id, streams,
remote_sender_info.first_ssrc, video_channel())); worker_thread(), remote_sender_info.first_ssrc,
video_channel()));
stream->AddTrack( stream->AddTrack(
static_cast<VideoTrackInterface*>(receiver->internal()->track().get())); static_cast<VideoTrackInterface*>(receiver->internal()->track().get()));
GetVideoTransceiver()->internal()->AddReceiver(receiver); GetVideoTransceiver()->internal()->AddReceiver(receiver);
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams; observer_->OnAddTrack(receiver, std::move(streams));
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
observer_->OnAddTrack(receiver, streams);
} }
// TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote

View File

@ -72,10 +72,10 @@ TEST_F(PeerConnectionRtpTest, AddTrackWithoutStreamFiresOnAddTrack) {
ASSERT_EQ(1u, callee->observer()->add_track_events_.size()); ASSERT_EQ(1u, callee->observer()->add_track_events_.size());
// TODO(deadbeef): When no stream is handled correctly we would expect // TODO(deadbeef): When no stream is handled correctly we would expect
// |add_track_events_[0].streams| to be empty. https://crbug.com/webrtc/7933 // |add_track_events_[0].streams| to be empty. https://crbug.com/webrtc/7933
ASSERT_EQ(1u, callee->observer()->add_track_events_[0].streams.size()); auto& add_track_event = callee->observer()->add_track_events_[0];
EXPECT_TRUE( ASSERT_EQ(1u, add_track_event.streams.size());
callee->observer()->add_track_events_[0].streams[0]->FindAudioTrack( EXPECT_TRUE(add_track_event.streams[0]->FindAudioTrack("audio_track"));
"audio_track")); EXPECT_EQ(add_track_event.streams, add_track_event.receiver->streams());
} }
TEST_F(PeerConnectionRtpTest, AddTrackWithStreamFiresOnAddTrack) { TEST_F(PeerConnectionRtpTest, AddTrackWithStreamFiresOnAddTrack) {
@ -89,12 +89,11 @@ TEST_F(PeerConnectionRtpTest, AddTrackWithStreamFiresOnAddTrack) {
ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
ASSERT_EQ(1u, callee->observer()->add_track_events_.size()); ASSERT_EQ(1u, callee->observer()->add_track_events_.size());
ASSERT_EQ(1u, callee->observer()->add_track_events_[0].streams.size()); auto& add_track_event = callee->observer()->add_track_events_[0];
EXPECT_EQ("audio_stream", ASSERT_EQ(1u, add_track_event.streams.size());
callee->observer()->add_track_events_[0].streams[0]->label()); EXPECT_EQ("audio_stream", add_track_event.streams[0]->label());
EXPECT_TRUE( EXPECT_TRUE(add_track_event.streams[0]->FindAudioTrack("audio_track"));
callee->observer()->add_track_events_[0].streams[0]->FindAudioTrack( EXPECT_EQ(add_track_event.streams, add_track_event.receiver->streams());
"audio_track"));
} }
TEST_F(PeerConnectionRtpTest, RemoveTrackWithoutStreamFiresOnRemoveTrack) { TEST_F(PeerConnectionRtpTest, RemoveTrackWithoutStreamFiresOnRemoveTrack) {

View File

@ -10,6 +10,7 @@
#include "pc/rtpreceiver.h" #include "pc/rtpreceiver.h"
#include <utility>
#include <vector> #include <vector>
#include "api/mediastreamtrackproxy.h" #include "api/mediastreamtrackproxy.h"
@ -20,9 +21,11 @@
namespace webrtc { namespace webrtc {
AudioRtpReceiver::AudioRtpReceiver(const std::string& track_id, AudioRtpReceiver::AudioRtpReceiver(
uint32_t ssrc, const std::string& track_id,
cricket::VoiceChannel* channel) std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
uint32_t ssrc,
cricket::VoiceChannel* channel)
: id_(track_id), : id_(track_id),
ssrc_(ssrc), ssrc_(ssrc),
channel_(channel), channel_(channel),
@ -30,6 +33,7 @@ AudioRtpReceiver::AudioRtpReceiver(const std::string& track_id,
rtc::Thread::Current(), rtc::Thread::Current(),
AudioTrack::Create(track_id, AudioTrack::Create(track_id,
RemoteAudioSource::Create(ssrc, channel)))), RemoteAudioSource::Create(ssrc, channel)))),
streams_(std::move(streams)),
cached_track_enabled_(track_->enabled()) { cached_track_enabled_(track_->enabled()) {
RTC_DCHECK(track_->GetSource()->remote()); RTC_DCHECK(track_->GetSource()->remote());
track_->RegisterObserver(this); track_->RegisterObserver(this);
@ -144,10 +148,12 @@ void AudioRtpReceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) {
received_first_packet_ = true; received_first_packet_ = true;
} }
VideoRtpReceiver::VideoRtpReceiver(const std::string& track_id, VideoRtpReceiver::VideoRtpReceiver(
rtc::Thread* worker_thread, const std::string& track_id,
uint32_t ssrc, std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
cricket::VideoChannel* channel) rtc::Thread* worker_thread,
uint32_t ssrc,
cricket::VideoChannel* channel)
: id_(track_id), : id_(track_id),
ssrc_(ssrc), ssrc_(ssrc),
channel_(channel), channel_(channel),
@ -161,7 +167,8 @@ VideoRtpReceiver::VideoRtpReceiver(const std::string& track_id,
VideoTrackSourceProxy::Create(rtc::Thread::Current(), VideoTrackSourceProxy::Create(rtc::Thread::Current(),
worker_thread, worker_thread,
source_), source_),
worker_thread))) { worker_thread))),
streams_(std::move(streams)) {
source_->SetState(MediaSourceInterface::kLive); source_->SetState(MediaSourceInterface::kLive);
if (!channel_) { if (!channel_) {
RTC_LOG(LS_ERROR) RTC_LOG(LS_ERROR)

View File

@ -49,9 +49,11 @@ class AudioRtpReceiver : public ObserverInterface,
// sees. // sees.
// TODO(deadbeef): Use rtc::Optional, or have another constructor that // TODO(deadbeef): Use rtc::Optional, or have another constructor that
// doesn't take an SSRC, and make this one DCHECK(ssrc != 0). // doesn't take an SSRC, and make this one DCHECK(ssrc != 0).
AudioRtpReceiver(const std::string& track_id, AudioRtpReceiver(
uint32_t ssrc, const std::string& track_id,
cricket::VoiceChannel* channel); std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
uint32_t ssrc,
cricket::VoiceChannel* channel);
virtual ~AudioRtpReceiver(); virtual ~AudioRtpReceiver();
@ -69,6 +71,10 @@ class AudioRtpReceiver : public ObserverInterface,
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override { rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
return track_.get(); return track_.get();
} }
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
const override {
return streams_;
}
cricket::MediaType media_type() const override { cricket::MediaType media_type() const override {
return cricket::MEDIA_TYPE_AUDIO; return cricket::MEDIA_TYPE_AUDIO;
@ -99,6 +105,7 @@ class AudioRtpReceiver : public ObserverInterface,
const uint32_t ssrc_; const uint32_t ssrc_;
cricket::VoiceChannel* channel_; cricket::VoiceChannel* channel_;
const rtc::scoped_refptr<AudioTrackInterface> track_; const rtc::scoped_refptr<AudioTrackInterface> track_;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
bool cached_track_enabled_; bool cached_track_enabled_;
double cached_volume_ = 1; double cached_volume_ = 1;
bool stopped_ = false; bool stopped_ = false;
@ -111,10 +118,12 @@ class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal>,
public: public:
// An SSRC of 0 will create a receiver that will match the first SSRC it // An SSRC of 0 will create a receiver that will match the first SSRC it
// sees. // sees.
VideoRtpReceiver(const std::string& track_id, VideoRtpReceiver(
rtc::Thread* worker_thread, const std::string& track_id,
uint32_t ssrc, std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
cricket::VideoChannel* channel); rtc::Thread* worker_thread,
uint32_t ssrc,
cricket::VideoChannel* channel);
virtual ~VideoRtpReceiver(); virtual ~VideoRtpReceiver();
@ -126,6 +135,10 @@ class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal>,
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override { rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
return track_.get(); return track_.get();
} }
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
const override {
return streams_;
}
cricket::MediaType media_type() const override { cricket::MediaType media_type() const override {
return cricket::MEDIA_TYPE_VIDEO; return cricket::MEDIA_TYPE_VIDEO;
@ -160,6 +173,7 @@ class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal>,
// the VideoRtpReceiver is stopped. // the VideoRtpReceiver is stopped.
rtc::scoped_refptr<VideoTrackSource> source_; rtc::scoped_refptr<VideoTrackSource> source_;
rtc::scoped_refptr<VideoTrackInterface> track_; rtc::scoped_refptr<VideoTrackInterface> track_;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
bool stopped_ = false; bool stopped_ = false;
RtpReceiverObserverInterface* observer_ = nullptr; RtpReceiverObserverInterface* observer_ = nullptr;
bool received_first_packet_ = false; bool received_first_packet_ = false;

View File

@ -165,16 +165,19 @@ class RtpSenderReceiverTest : public testing::Test,
VerifyVideoChannelNoInput(); VerifyVideoChannelNoInput();
} }
void CreateAudioRtpReceiver() { void CreateAudioRtpReceiver(
audio_rtp_receiver_ = std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams = {}) {
new AudioRtpReceiver(kAudioTrackId, kAudioSsrc, voice_channel_); audio_rtp_receiver_ = new AudioRtpReceiver(
kAudioTrackId, std::move(streams), kAudioSsrc, voice_channel_);
audio_track_ = audio_rtp_receiver_->audio_track(); audio_track_ = audio_rtp_receiver_->audio_track();
VerifyVoiceChannelOutput(); VerifyVoiceChannelOutput();
} }
void CreateVideoRtpReceiver() { void CreateVideoRtpReceiver(
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams = {}) {
video_rtp_receiver_ = new VideoRtpReceiver( video_rtp_receiver_ = new VideoRtpReceiver(
kVideoTrackId, rtc::Thread::Current(), kVideoSsrc, video_channel_); kVideoTrackId, std::move(streams), rtc::Thread::Current(), kVideoSsrc,
video_channel_);
video_track_ = video_rtp_receiver_->video_track(); video_track_ = video_rtp_receiver_->video_track();
VerifyVideoChannelOutput(); VerifyVideoChannelOutput();
} }
@ -292,6 +295,16 @@ TEST_F(RtpSenderReceiverTest, AddAndDestroyVideoRtpReceiver) {
DestroyVideoRtpReceiver(); DestroyVideoRtpReceiver();
} }
TEST_F(RtpSenderReceiverTest, AddAndDestroyAudioRtpReceiverWithStreams) {
CreateAudioRtpReceiver({local_stream_});
DestroyAudioRtpReceiver();
}
TEST_F(RtpSenderReceiverTest, AddAndDestroyVideoRtpReceiverWithStreams) {
CreateVideoRtpReceiver({local_stream_});
DestroyVideoRtpReceiver();
}
// Test that the AudioRtpSender applies options from the local audio source. // Test that the AudioRtpSender applies options from the local audio source.
TEST_F(RtpSenderReceiverTest, LocalAudioSourceOptionsApplied) { TEST_F(RtpSenderReceiverTest, LocalAudioSourceOptionsApplied) {
cricket::AudioOptions options; cricket::AudioOptions options;

View File

@ -64,7 +64,7 @@ JNI_FUNCTION_DECLARATION(jstring,
} }
JNI_FUNCTION_DECLARATION(void, MediaStream_free, JNIEnv*, jclass, jlong j_p) { JNI_FUNCTION_DECLARATION(void, MediaStream_free, JNIEnv*, jclass, jlong j_p) {
CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p)); reinterpret_cast<MediaStreamInterface*>(j_p)->Release();
} }
} // namespace jni } // namespace jni