Forward the SignalFirstPacketReceived to RtpReceiver.

The RtpReceiverObserverInterface is created.
The SignalFirstPacketReceived will be forwarded from BaseChannel to WebRtcSession.
WebRtcSession will forward SignalFirstAudioPacketReceived and SignalFirstVideoPacketReceived to the RtpReceiverInterface.
The application can listen to the Signal by implementing and registering a RtpReceiverObserver.

Review-Url: https://codereview.webrtc.org/1999853002
Cr-Commit-Position: refs/heads/master@{#13139}
This commit is contained in:
zhihuang 2016-06-14 11:47:14 -07:00 committed by Commit bot
parent 9a38cabf24
commit 184a3fd648
8 changed files with 183 additions and 2 deletions

View File

@ -72,6 +72,9 @@ class AudioProviderInterface {
uint32_t ssrc, uint32_t ssrc,
const RtpParameters& parameters) = 0; const RtpParameters& parameters) = 0;
// Called when the first audio packet is received.
sigslot::signal0<> SignalFirstAudioPacketReceived;
protected: protected:
virtual ~AudioProviderInterface() {} virtual ~AudioProviderInterface() {}
}; };
@ -105,6 +108,9 @@ class VideoProviderInterface {
uint32_t ssrc, uint32_t ssrc,
const RtpParameters& parameters) = 0; const RtpParameters& parameters) = 0;
// Called when the first video packet is received.
sigslot::signal0<> SignalFirstVideoPacketReceived;
protected: protected:
virtual ~VideoProviderInterface() {} virtual ~VideoProviderInterface() {}
}; };

View File

@ -146,6 +146,25 @@ class SignalingMessageReceiver {
virtual ~SignalingMessageReceiver() {} virtual ~SignalingMessageReceiver() {}
}; };
class MockRtpReceiverObserver : public webrtc::RtpReceiverObserverInterface {
public:
MockRtpReceiverObserver(cricket::MediaType media_type)
: expected_media_type_(media_type) {}
void OnFirstPacketReceived(cricket::MediaType media_type) override {
ASSERT_EQ(expected_media_type_, media_type);
first_packet_received_ = true;
}
bool first_packet_received() { return first_packet_received_; }
virtual ~MockRtpReceiverObserver() {}
private:
bool first_packet_received_ = false;
cricket::MediaType expected_media_type_;
};
class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
public SignalingMessageReceiver, public SignalingMessageReceiver,
public ObserverInterface { public ObserverInterface {
@ -780,6 +799,21 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
return pc()->ice_gathering_state(); return pc()->ice_gathering_state();
} }
std::vector<std::unique_ptr<MockRtpReceiverObserver>> const&
rtp_receiver_observers() {
return rtp_receiver_observers_;
}
void SetRtpReceiverObservers() {
rtp_receiver_observers_.clear();
for (auto receiver : pc()->GetReceivers()) {
std::unique_ptr<MockRtpReceiverObserver> observer(
new MockRtpReceiverObserver(receiver->media_type()));
receiver->SetObserver(observer.get());
rtp_receiver_observers_.push_back(std::move(observer));
}
}
private: private:
class DummyDtmfObserver : public DtmfSenderObserverInterface { class DummyDtmfObserver : public DtmfSenderObserverInterface {
public: public:
@ -870,6 +904,8 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
std::unique_ptr<SessionDescriptionInterface> desc( std::unique_ptr<SessionDescriptionInterface> desc(
webrtc::CreateSessionDescription("offer", msg, nullptr)); webrtc::CreateSessionDescription("offer", msg, nullptr));
EXPECT_TRUE(DoSetRemoteDescription(desc.release())); EXPECT_TRUE(DoSetRemoteDescription(desc.release()));
// Set the RtpReceiverObserver after receivers are created.
SetRtpReceiverObservers();
std::unique_ptr<SessionDescriptionInterface> answer; std::unique_ptr<SessionDescriptionInterface> answer;
EXPECT_TRUE(DoCreateAnswer(&answer)); EXPECT_TRUE(DoCreateAnswer(&answer));
std::string sdp; std::string sdp;
@ -886,6 +922,8 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
std::unique_ptr<SessionDescriptionInterface> desc( std::unique_ptr<SessionDescriptionInterface> desc(
webrtc::CreateSessionDescription("answer", msg, nullptr)); webrtc::CreateSessionDescription("answer", msg, nullptr));
EXPECT_TRUE(DoSetRemoteDescription(desc.release())); EXPECT_TRUE(DoSetRemoteDescription(desc.release()));
// Set the RtpReceiverObserver after receivers are created.
SetRtpReceiverObservers();
} }
bool DoCreateOfferAnswer(std::unique_ptr<SessionDescriptionInterface>* desc, bool DoCreateOfferAnswer(std::unique_ptr<SessionDescriptionInterface>* desc,
@ -1026,6 +1064,8 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
rtc::scoped_refptr<DataChannelInterface> data_channel_; rtc::scoped_refptr<DataChannelInterface> data_channel_;
std::unique_ptr<MockDataChannelObserver> data_observer_; std::unique_ptr<MockDataChannelObserver> data_observer_;
std::vector<std::unique_ptr<MockRtpReceiverObserver>> rtp_receiver_observers_;
}; };
class P2PTestConductor : public testing::Test { class P2PTestConductor : public testing::Test {
@ -1314,6 +1354,16 @@ class P2PTestConductor : public testing::Test {
return old; return old;
} }
bool AllObserversReceived(
const std::vector<std::unique_ptr<MockRtpReceiverObserver>>& observers) {
for (auto& observer : observers) {
if (!observer->first_packet_received()) {
return false;
}
}
return true;
}
private: private:
// |ss_| is used by |network_thread_| so it must be destroyed later. // |ss_| is used by |network_thread_| so it must be destroyed later.
std::unique_ptr<rtc::PhysicalSocketServer> pss_; std::unique_ptr<rtc::PhysicalSocketServer> pss_;
@ -1332,6 +1382,33 @@ class P2PTestConductor : public testing::Test {
// https://code.google.com/p/webrtc/issues/detail?id=1205 for details. // https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
#if !defined(THREAD_SANITIZER) #if !defined(THREAD_SANITIZER)
TEST_F(P2PTestConductor, TestRtpReceiverObserverCallbackFunction) {
ASSERT_TRUE(CreateTestClients());
LocalP2PTest();
EXPECT_TRUE_WAIT(
AllObserversReceived(initializing_client()->rtp_receiver_observers()),
kMaxWaitForFramesMs);
EXPECT_TRUE_WAIT(
AllObserversReceived(receiving_client()->rtp_receiver_observers()),
kMaxWaitForFramesMs);
}
// The observers are expected to fire the signal even if they are set after the
// first packet is received.
TEST_F(P2PTestConductor, TestSetRtpReceiverObserverAfterFirstPacketIsReceived) {
ASSERT_TRUE(CreateTestClients());
LocalP2PTest();
// Reset the RtpReceiverObservers.
initializing_client()->SetRtpReceiverObservers();
receiving_client()->SetRtpReceiverObservers();
EXPECT_TRUE_WAIT(
AllObserversReceived(initializing_client()->rtp_receiver_observers()),
kMaxWaitForFramesMs);
EXPECT_TRUE_WAIT(
AllObserversReceived(receiving_client()->rtp_receiver_observers()),
kMaxWaitForFramesMs);
}
// This test sets up a Jsep call between two parties and test Dtmf. // This test sets up a Jsep call between two parties and test Dtmf.
// TODO(holmer): Disabled due to sometimes crashing on buildbots. // TODO(holmer): Disabled due to sometimes crashing on buildbots.
// See issue webrtc/2378. // See issue webrtc/2378.

View File

@ -35,6 +35,8 @@ AudioRtpReceiver::AudioRtpReceiver(MediaStreamInterface* stream,
track_->GetSource()->RegisterAudioObserver(this); track_->GetSource()->RegisterAudioObserver(this);
Reconfigure(); Reconfigure();
stream->AddTrack(track_); stream->AddTrack(track_);
provider_->SignalFirstAudioPacketReceived.connect(
this, &AudioRtpReceiver::OnFirstAudioPacketReceived);
} }
AudioRtpReceiver::~AudioRtpReceiver() { AudioRtpReceiver::~AudioRtpReceiver() {
@ -83,6 +85,22 @@ void AudioRtpReceiver::Reconfigure() {
provider_->SetAudioPlayout(ssrc_, track_->enabled()); provider_->SetAudioPlayout(ssrc_, track_->enabled());
} }
void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
observer_ = observer;
// If received the first packet before setting the observer, call the
// observer.
if (received_first_packet_) {
observer_->OnFirstPacketReceived(media_type());
}
}
void AudioRtpReceiver::OnFirstAudioPacketReceived() {
if (observer_) {
observer_->OnFirstPacketReceived(media_type());
}
received_first_packet_ = true;
}
VideoRtpReceiver::VideoRtpReceiver(MediaStreamInterface* stream, VideoRtpReceiver::VideoRtpReceiver(MediaStreamInterface* stream,
const std::string& track_id, const std::string& track_id,
rtc::Thread* worker_thread, rtc::Thread* worker_thread,
@ -104,6 +122,8 @@ VideoRtpReceiver::VideoRtpReceiver(MediaStreamInterface* stream,
source_->SetState(MediaSourceInterface::kLive); source_->SetState(MediaSourceInterface::kLive);
provider_->SetVideoPlayout(ssrc_, true, &broadcaster_); provider_->SetVideoPlayout(ssrc_, true, &broadcaster_);
stream->AddTrack(track_); stream->AddTrack(track_);
provider_->SignalFirstVideoPacketReceived.connect(
this, &VideoRtpReceiver::OnFirstVideoPacketReceived);
} }
VideoRtpReceiver::~VideoRtpReceiver() { VideoRtpReceiver::~VideoRtpReceiver() {
@ -132,4 +152,20 @@ void VideoRtpReceiver::Stop() {
provider_ = nullptr; provider_ = nullptr;
} }
void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
observer_ = observer;
// If received the first packet before setting the observer, call the
// observer.
if (received_first_packet_) {
observer_->OnFirstPacketReceived(media_type());
}
}
void VideoRtpReceiver::OnFirstVideoPacketReceived() {
if (observer_) {
observer_->OnFirstPacketReceived(media_type());
}
received_first_packet_ = true;
}
} // namespace webrtc } // namespace webrtc

View File

@ -22,6 +22,7 @@
#include "webrtc/api/remoteaudiosource.h" #include "webrtc/api/remoteaudiosource.h"
#include "webrtc/api/videotracksource.h" #include "webrtc/api/videotracksource.h"
#include "webrtc/base/basictypes.h" #include "webrtc/base/basictypes.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/media/base/videobroadcaster.h" #include "webrtc/media/base/videobroadcaster.h"
namespace webrtc { namespace webrtc {
@ -34,7 +35,8 @@ class RtpReceiverInternal : public RtpReceiverInterface {
class AudioRtpReceiver : public ObserverInterface, class AudioRtpReceiver : public ObserverInterface,
public AudioSourceInterface::AudioObserver, public AudioSourceInterface::AudioObserver,
public rtc::RefCountedObject<RtpReceiverInternal> { public rtc::RefCountedObject<RtpReceiverInternal>,
public sigslot::has_slots<> {
public: public:
AudioRtpReceiver(MediaStreamInterface* stream, AudioRtpReceiver(MediaStreamInterface* stream,
const std::string& track_id, const std::string& track_id,
@ -66,17 +68,25 @@ class AudioRtpReceiver : public ObserverInterface,
// RtpReceiverInternal implementation. // RtpReceiverInternal implementation.
void Stop() override; void Stop() override;
void SetObserver(RtpReceiverObserverInterface* observer) override;
cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_AUDIO; }
private: private:
void Reconfigure(); void Reconfigure();
void OnFirstAudioPacketReceived();
const std::string id_; const std::string id_;
const uint32_t ssrc_; const uint32_t ssrc_;
AudioProviderInterface* provider_; // Set to null in Stop(). AudioProviderInterface* provider_; // Set to null in Stop().
const rtc::scoped_refptr<AudioTrackInterface> track_; const rtc::scoped_refptr<AudioTrackInterface> track_;
bool cached_track_enabled_; bool cached_track_enabled_;
RtpReceiverObserverInterface* observer_ = nullptr;
bool received_first_packet_ = false;
}; };
class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> { class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal>,
public sigslot::has_slots<> {
public: public:
VideoRtpReceiver(MediaStreamInterface* stream, VideoRtpReceiver(MediaStreamInterface* stream,
const std::string& track_id, const std::string& track_id,
@ -103,7 +113,13 @@ class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
// RtpReceiverInternal implementation. // RtpReceiverInternal implementation.
void Stop() override; void Stop() override;
void SetObserver(RtpReceiverObserverInterface* observer) override;
cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_VIDEO; }
private: private:
void OnFirstVideoPacketReceived();
std::string id_; std::string id_;
uint32_t ssrc_; uint32_t ssrc_;
VideoProviderInterface* provider_; VideoProviderInterface* provider_;
@ -115,6 +131,8 @@ 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_;
RtpReceiverObserverInterface* observer_ = nullptr;
bool received_first_packet_ = false;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -20,9 +20,18 @@
#include "webrtc/api/proxy.h" #include "webrtc/api/proxy.h"
#include "webrtc/base/refcount.h" #include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/pc/mediasession.h"
namespace webrtc { namespace webrtc {
class RtpReceiverObserverInterface {
public:
virtual void OnFirstPacketReceived(cricket::MediaType media_type) = 0;
protected:
virtual ~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;
@ -37,6 +46,10 @@ class RtpReceiverInterface : public rtc::RefCountInterface {
virtual RtpParameters GetParameters() const = 0; virtual RtpParameters GetParameters() const = 0;
virtual bool SetParameters(const RtpParameters& parameters) = 0; virtual bool SetParameters(const RtpParameters& parameters) = 0;
virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0;
virtual cricket::MediaType media_type() = 0;
protected: protected:
virtual ~RtpReceiverInterface() {} virtual ~RtpReceiverInterface() {}
}; };
@ -47,6 +60,8 @@ PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
PROXY_CONSTMETHOD0(std::string, id) PROXY_CONSTMETHOD0(std::string, id)
PROXY_CONSTMETHOD0(RtpParameters, GetParameters); PROXY_CONSTMETHOD0(RtpParameters, GetParameters);
PROXY_METHOD1(bool, SetParameters, const RtpParameters&) PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*);
PROXY_METHOD0(cricket::MediaType, media_type);
END_SIGNALING_PROXY() END_SIGNALING_PROXY()
} // namespace webrtc } // namespace webrtc

View File

@ -1767,6 +1767,8 @@ bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content,
voice_channel_->SignalDtlsSetupFailure.connect( voice_channel_->SignalDtlsSetupFailure.connect(
this, &WebRtcSession::OnDtlsSetupFailure); this, &WebRtcSession::OnDtlsSetupFailure);
voice_channel_->SignalFirstPacketReceived.connect(
this, &WebRtcSession::OnChannelFirstPacketReceived);
SignalVoiceChannelCreated(); SignalVoiceChannelCreated();
voice_channel_->SignalSentPacket.connect(this, voice_channel_->SignalSentPacket.connect(this,
@ -1790,6 +1792,8 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content,
} }
video_channel_->SignalDtlsSetupFailure.connect( video_channel_->SignalDtlsSetupFailure.connect(
this, &WebRtcSession::OnDtlsSetupFailure); this, &WebRtcSession::OnDtlsSetupFailure);
video_channel_->SignalFirstPacketReceived.connect(
this, &WebRtcSession::OnChannelFirstPacketReceived);
SignalVideoChannelCreated(); SignalVideoChannelCreated();
video_channel_->SignalSentPacket.connect(this, video_channel_->SignalSentPacket.connect(this,
@ -1831,6 +1835,21 @@ void WebRtcSession::OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp) {
rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp); rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp);
} }
void WebRtcSession::OnChannelFirstPacketReceived(
cricket::BaseChannel* channel) {
ASSERT(signaling_thread()->IsCurrent());
if (!received_first_audio_packet_ &&
channel->media_type() == cricket::MEDIA_TYPE_AUDIO) {
received_first_audio_packet_ = true;
SignalFirstAudioPacketReceived();
} else if (!received_first_video_packet_ &&
channel->media_type() == cricket::MEDIA_TYPE_VIDEO) {
received_first_video_packet_ = true;
SignalFirstVideoPacketReceived();
}
}
void WebRtcSession::OnDataChannelMessageReceived( void WebRtcSession::OnDataChannelMessageReceived(
cricket::DataChannel* channel, cricket::DataChannel* channel,
const cricket::ReceiveDataParams& params, const cricket::ReceiveDataParams& params,

View File

@ -310,6 +310,8 @@ class WebRtcSession : public AudioProviderInterface,
void OnCertificateReady( void OnCertificateReady(
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate); const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
void OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp); void OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp);
// Called when the channel received the first packet.
void OnChannelFirstPacketReceived(cricket::BaseChannel*);
// For unit test. // For unit test.
bool waiting_for_certificate_for_testing() const; bool waiting_for_certificate_for_testing() const;
@ -527,6 +529,9 @@ class WebRtcSession : public AudioProviderInterface,
// Declares the RTCP mux policy for the WebRTCSession. // Declares the RTCP mux policy for the WebRTCSession.
PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy_; PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy_;
bool received_first_video_packet_ = false;
bool received_first_audio_packet_ = false;
RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcSession); RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcSession);
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -168,6 +168,8 @@ class BaseChannel
SrtpFilter* srtp_filter() { return &srtp_filter_; } SrtpFilter* srtp_filter() { return &srtp_filter_; }
virtual cricket::MediaType media_type() = 0;
protected: protected:
virtual MediaChannel* media_channel() const { return media_channel_; } virtual MediaChannel* media_channel() const { return media_channel_; }
// Sets the |transport_channel_| (and |rtcp_transport_channel_|, if |rtcp_| is // Sets the |transport_channel_| (and |rtcp_transport_channel_|, if |rtcp_| is
@ -436,6 +438,7 @@ class VoiceChannel : public BaseChannel {
webrtc::RtpParameters GetRtpReceiveParameters_w(uint32_t ssrc) const; webrtc::RtpParameters GetRtpReceiveParameters_w(uint32_t ssrc) const;
bool SetRtpReceiveParameters_w(uint32_t ssrc, bool SetRtpReceiveParameters_w(uint32_t ssrc,
webrtc::RtpParameters parameters); webrtc::RtpParameters parameters);
cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_AUDIO; }
private: private:
// overrides from BaseChannel // overrides from BaseChannel
@ -520,6 +523,7 @@ class VideoChannel : public BaseChannel {
webrtc::RtpParameters GetRtpReceiveParameters(uint32_t ssrc) const; webrtc::RtpParameters GetRtpReceiveParameters(uint32_t ssrc) const;
bool SetRtpReceiveParameters(uint32_t ssrc, bool SetRtpReceiveParameters(uint32_t ssrc,
const webrtc::RtpParameters& parameters); const webrtc::RtpParameters& parameters);
cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_VIDEO; }
private: private:
// overrides from BaseChannel // overrides from BaseChannel
@ -591,6 +595,7 @@ class DataChannel : public BaseChannel {
sigslot::signal1<bool> SignalReadyToSendData; sigslot::signal1<bool> SignalReadyToSendData;
// Signal for notifying that the remote side has closed the DataChannel. // Signal for notifying that the remote side has closed the DataChannel.
sigslot::signal1<uint32_t> SignalStreamClosedRemotely; sigslot::signal1<uint32_t> SignalStreamClosedRemotely;
cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_DATA; }
protected: protected:
// downcasts a MediaChannel. // downcasts a MediaChannel.