Split rtp_receiver for readability.
Bug: webrtc:10304 Change-Id: I85e421060d8560cf36cdb5970ae190efc77e7709 Reviewed-on: https://webrtc-review.googlesource.com/c/122085 Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Commit-Queue: Ruslan Burakov <kuddai@google.com> Cr-Commit-Position: refs/heads/master@{#26634}
This commit is contained in:
parent
b66003ca79
commit
501bfba0cb
@ -128,6 +128,8 @@ rtc_static_library("peerconnection") {
|
||||
visibility = [ "*" ]
|
||||
cflags = []
|
||||
sources = [
|
||||
"audio_rtp_receiver.cc",
|
||||
"audio_rtp_receiver.h",
|
||||
"audio_track.cc",
|
||||
"audio_track.h",
|
||||
"data_channel.cc",
|
||||
@ -175,6 +177,8 @@ rtc_static_library("peerconnection") {
|
||||
"stream_collection.h",
|
||||
"track_media_info_map.cc",
|
||||
"track_media_info_map.h",
|
||||
"video_rtp_receiver.cc",
|
||||
"video_rtp_receiver.h",
|
||||
"video_track.cc",
|
||||
"video_track.h",
|
||||
"video_track_source.cc",
|
||||
|
||||
248
pc/audio_rtp_receiver.cc
Normal file
248
pc/audio_rtp_receiver.cc
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "pc/audio_rtp_receiver.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "api/media_stream_proxy.h"
|
||||
#include "api/media_stream_track_proxy.h"
|
||||
#include "pc/audio_track.h"
|
||||
#include "pc/media_stream.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/location.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> stream_ids)
|
||||
: AudioRtpReceiver(worker_thread,
|
||||
receiver_id,
|
||||
CreateStreamsFromIds(std::move(stream_ids))) {}
|
||||
|
||||
AudioRtpReceiver::AudioRtpReceiver(
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
|
||||
: worker_thread_(worker_thread),
|
||||
id_(receiver_id),
|
||||
source_(new rtc::RefCountedObject<RemoteAudioSource>(worker_thread)),
|
||||
track_(AudioTrackProxy::Create(rtc::Thread::Current(),
|
||||
AudioTrack::Create(receiver_id, source_))),
|
||||
cached_track_enabled_(track_->enabled()),
|
||||
attachment_id_(GenerateUniqueId()) {
|
||||
RTC_DCHECK(worker_thread_);
|
||||
RTC_DCHECK(track_->GetSource()->remote());
|
||||
track_->RegisterObserver(this);
|
||||
track_->GetSource()->RegisterAudioObserver(this);
|
||||
SetStreams(streams);
|
||||
}
|
||||
|
||||
AudioRtpReceiver::~AudioRtpReceiver() {
|
||||
track_->GetSource()->UnregisterAudioObserver(this);
|
||||
track_->UnregisterObserver(this);
|
||||
Stop();
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::OnChanged() {
|
||||
if (cached_track_enabled_ != track_->enabled()) {
|
||||
cached_track_enabled_ = track_->enabled();
|
||||
Reconfigure();
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioRtpReceiver::SetOutputVolume(double volume) {
|
||||
RTC_DCHECK_GE(volume, 0.0);
|
||||
RTC_DCHECK_LE(volume, 10.0);
|
||||
RTC_DCHECK(media_channel_);
|
||||
RTC_DCHECK(ssrc_);
|
||||
return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->SetOutputVolume(*ssrc_, volume);
|
||||
});
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::OnSetVolume(double volume) {
|
||||
RTC_DCHECK_GE(volume, 0);
|
||||
RTC_DCHECK_LE(volume, 10);
|
||||
cached_volume_ = volume;
|
||||
if (!media_channel_ || !ssrc_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
|
||||
return;
|
||||
}
|
||||
// When the track is disabled, the volume of the source, which is the
|
||||
// corresponding WebRtc Voice Engine channel will be 0. So we do not allow
|
||||
// setting the volume to the source when the track is disabled.
|
||||
if (!stopped_ && track_->enabled()) {
|
||||
if (!SetOutputVolume(cached_volume_)) {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> AudioRtpReceiver::stream_ids() const {
|
||||
std::vector<std::string> stream_ids(streams_.size());
|
||||
for (size_t i = 0; i < streams_.size(); ++i)
|
||||
stream_ids[i] = streams_[i]->id();
|
||||
return stream_ids;
|
||||
}
|
||||
|
||||
RtpParameters AudioRtpReceiver::GetParameters() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return RtpParameters();
|
||||
}
|
||||
return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->GetRtpReceiveParameters(*ssrc_);
|
||||
});
|
||||
}
|
||||
|
||||
bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) {
|
||||
TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters");
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return false;
|
||||
}
|
||||
return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
|
||||
});
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
|
||||
frame_decryptor_ = std::move(frame_decryptor);
|
||||
// Special Case: Set the frame decryptor to any value on any existing channel.
|
||||
if (media_channel_ && ssrc_.has_value() && !stopped_) {
|
||||
worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
|
||||
media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface>
|
||||
AudioRtpReceiver::GetFrameDecryptor() const {
|
||||
return frame_decryptor_;
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::Stop() {
|
||||
// TODO(deadbeef): Need to do more here to fully stop receiving packets.
|
||||
if (stopped_) {
|
||||
return;
|
||||
}
|
||||
if (media_channel_ && ssrc_) {
|
||||
// Allow that SetOutputVolume fail. This is the normal case when the
|
||||
// underlying media channel has already been deleted.
|
||||
SetOutputVolume(0.0);
|
||||
}
|
||||
stopped_ = true;
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
|
||||
if (!media_channel_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "AudioRtpReceiver::SetupMediaChannel: No audio channel exists.";
|
||||
return;
|
||||
}
|
||||
if (ssrc_ == ssrc) {
|
||||
return;
|
||||
}
|
||||
if (ssrc_) {
|
||||
source_->Stop(media_channel_, *ssrc_);
|
||||
}
|
||||
ssrc_ = ssrc;
|
||||
source_->Start(media_channel_, *ssrc_);
|
||||
Reconfigure();
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
|
||||
SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetStreams(
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
|
||||
// Remove remote track from any streams that are going away.
|
||||
for (const auto& existing_stream : streams_) {
|
||||
bool removed = true;
|
||||
for (const auto& stream : streams) {
|
||||
if (existing_stream->id() == stream->id()) {
|
||||
RTC_DCHECK_EQ(existing_stream.get(), stream.get());
|
||||
removed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
existing_stream->RemoveTrack(track_);
|
||||
}
|
||||
}
|
||||
// Add remote track to any streams that are new.
|
||||
for (const auto& stream : streams) {
|
||||
bool added = true;
|
||||
for (const auto& existing_stream : streams_) {
|
||||
if (stream->id() == existing_stream->id()) {
|
||||
RTC_DCHECK_EQ(stream.get(), existing_stream.get());
|
||||
added = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (added) {
|
||||
stream->AddTrack(track_);
|
||||
}
|
||||
}
|
||||
streams_ = streams;
|
||||
}
|
||||
|
||||
std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return {};
|
||||
}
|
||||
return worker_thread_->Invoke<std::vector<RtpSource>>(
|
||||
RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::Reconfigure() {
|
||||
RTC_DCHECK(!stopped_);
|
||||
if (!media_channel_ || !ssrc_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "AudioRtpReceiver::Reconfigure: No audio channel exists.";
|
||||
return;
|
||||
}
|
||||
if (!SetOutputVolume(track_->enabled() ? cached_volume_ : 0)) {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
// Reattach the frame decryptor if we were reconfigured.
|
||||
MaybeAttachFrameDecryptorToMediaChannel(
|
||||
ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
|
||||
observer_ = observer;
|
||||
// Deliver any notifications the observer may have missed by being set late.
|
||||
if (received_first_packet_ && observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
|
||||
RTC_DCHECK(media_channel == nullptr ||
|
||||
media_channel->media_type() == media_type());
|
||||
media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::NotifyFirstPacketReceived() {
|
||||
if (observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
received_first_packet_ = true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
126
pc/audio_rtp_receiver.h
Normal file
126
pc/audio_rtp_receiver.h
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef PC_AUDIO_RTP_RECEIVER_H_
|
||||
#define PC_AUDIO_RTP_RECEIVER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/crypto/frame_decryptor_interface.h"
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "pc/remote_audio_source.h"
|
||||
#include "pc/rtp_receiver.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
#include "rtc_base/thread.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioRtpReceiver : public ObserverInterface,
|
||||
public AudioSourceInterface::AudioObserver,
|
||||
public rtc::RefCountedObject<RtpReceiverInternal> {
|
||||
public:
|
||||
AudioRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> stream_ids);
|
||||
// TODO(https://crbug.com/webrtc/9480): Remove this when streams() is removed.
|
||||
AudioRtpReceiver(
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
|
||||
virtual ~AudioRtpReceiver();
|
||||
|
||||
// ObserverInterface implementation
|
||||
void OnChanged() override;
|
||||
|
||||
// AudioSourceInterface::AudioObserver implementation
|
||||
void OnSetVolume(double volume) override;
|
||||
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track() const {
|
||||
return track_.get();
|
||||
}
|
||||
|
||||
// RtpReceiverInterface implementation
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
|
||||
return track_.get();
|
||||
}
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
|
||||
return dtls_transport_;
|
||||
}
|
||||
std::vector<std::string> stream_ids() const override;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
|
||||
const override {
|
||||
return streams_;
|
||||
}
|
||||
|
||||
cricket::MediaType media_type() const override {
|
||||
return cricket::MEDIA_TYPE_AUDIO;
|
||||
}
|
||||
|
||||
std::string id() const override { return id_; }
|
||||
|
||||
RtpParameters GetParameters() const override;
|
||||
bool SetParameters(const RtpParameters& parameters) override;
|
||||
|
||||
void SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
|
||||
const override;
|
||||
|
||||
// RtpReceiverInternal implementation.
|
||||
void Stop() override;
|
||||
void SetupMediaChannel(uint32_t ssrc) override;
|
||||
uint32_t ssrc() const override { return ssrc_.value_or(0); }
|
||||
void NotifyFirstPacketReceived() override;
|
||||
void set_stream_ids(std::vector<std::string> stream_ids) override;
|
||||
void set_transport(
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
|
||||
dtls_transport_ = dtls_transport;
|
||||
}
|
||||
void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
|
||||
streams) override;
|
||||
void SetObserver(RtpReceiverObserverInterface* observer) override;
|
||||
|
||||
void SetMediaChannel(cricket::MediaChannel* media_channel) override;
|
||||
|
||||
std::vector<RtpSource> GetSources() const override;
|
||||
int AttachmentId() const override { return attachment_id_; }
|
||||
|
||||
private:
|
||||
void Reconfigure();
|
||||
bool SetOutputVolume(double volume);
|
||||
|
||||
rtc::Thread* const worker_thread_;
|
||||
const std::string id_;
|
||||
const rtc::scoped_refptr<RemoteAudioSource> source_;
|
||||
const rtc::scoped_refptr<AudioTrackInterface> track_;
|
||||
cricket::VoiceMediaChannel* media_channel_ = nullptr;
|
||||
absl::optional<uint32_t> ssrc_;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
|
||||
bool cached_track_enabled_;
|
||||
double cached_volume_ = 1;
|
||||
bool stopped_ = false;
|
||||
RtpReceiverObserverInterface* observer_ = nullptr;
|
||||
bool received_first_packet_ = false;
|
||||
int attachment_id_ = 0;
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // PC_AUDIO_RTP_RECEIVER_H_
|
||||
@ -30,6 +30,7 @@
|
||||
#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
|
||||
#include "logging/rtc_event_log/rtc_event_log.h"
|
||||
#include "media/sctp/sctp_transport.h"
|
||||
#include "pc/audio_rtp_receiver.h"
|
||||
#include "pc/audio_track.h"
|
||||
#include "pc/channel.h"
|
||||
#include "pc/channel_manager.h"
|
||||
@ -43,6 +44,7 @@
|
||||
#include "pc/sctp_utils.h"
|
||||
#include "pc/sdp_utils.h"
|
||||
#include "pc/stream_collection.h"
|
||||
#include "pc/video_rtp_receiver.h"
|
||||
#include "pc/video_track.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
@ -16,10 +16,7 @@
|
||||
|
||||
#include "api/media_stream_proxy.h"
|
||||
#include "api/media_stream_track_proxy.h"
|
||||
#include "api/video_track_source_proxy.h"
|
||||
#include "pc/audio_track.h"
|
||||
#include "pc/media_stream.h"
|
||||
#include "pc/video_track.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/location.h"
|
||||
#include "rtc_base/logging.h"
|
||||
@ -27,17 +24,15 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// This function is only expected to be called on the signalling thread.
|
||||
int GenerateUniqueId() {
|
||||
int RtpReceiverInternal::GenerateUniqueId() {
|
||||
static int g_unique_id = 0;
|
||||
|
||||
return ++g_unique_id;
|
||||
}
|
||||
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> CreateStreamsFromIds(
|
||||
std::vector<std::string> stream_ids) {
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>>
|
||||
RtpReceiverInternal::CreateStreamsFromIds(std::vector<std::string> stream_ids) {
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams(
|
||||
stream_ids.size());
|
||||
for (size_t i = 0; i < stream_ids.size(); ++i) {
|
||||
@ -50,7 +45,7 @@ std::vector<rtc::scoped_refptr<MediaStreamInterface>> CreateStreamsFromIds(
|
||||
// Attempt to attach the frame decryptor to the current media channel on the
|
||||
// correct worker thread only if both the media channel exists and a ssrc has
|
||||
// been allocated to the stream.
|
||||
void MaybeAttachFrameDecryptorToMediaChannel(
|
||||
void RtpReceiverInternal::MaybeAttachFrameDecryptorToMediaChannel(
|
||||
const absl::optional<uint32_t>& ssrc,
|
||||
rtc::Thread* worker_thread,
|
||||
rtc::scoped_refptr<webrtc::FrameDecryptorInterface> frame_decryptor,
|
||||
@ -63,410 +58,4 @@ void MaybeAttachFrameDecryptorToMediaChannel(
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> stream_ids)
|
||||
: AudioRtpReceiver(worker_thread,
|
||||
receiver_id,
|
||||
CreateStreamsFromIds(std::move(stream_ids))) {}
|
||||
|
||||
AudioRtpReceiver::AudioRtpReceiver(
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
|
||||
: worker_thread_(worker_thread),
|
||||
id_(receiver_id),
|
||||
source_(new rtc::RefCountedObject<RemoteAudioSource>(worker_thread)),
|
||||
track_(AudioTrackProxy::Create(rtc::Thread::Current(),
|
||||
AudioTrack::Create(receiver_id, source_))),
|
||||
cached_track_enabled_(track_->enabled()),
|
||||
attachment_id_(GenerateUniqueId()) {
|
||||
RTC_DCHECK(worker_thread_);
|
||||
RTC_DCHECK(track_->GetSource()->remote());
|
||||
track_->RegisterObserver(this);
|
||||
track_->GetSource()->RegisterAudioObserver(this);
|
||||
SetStreams(streams);
|
||||
}
|
||||
|
||||
AudioRtpReceiver::~AudioRtpReceiver() {
|
||||
track_->GetSource()->UnregisterAudioObserver(this);
|
||||
track_->UnregisterObserver(this);
|
||||
Stop();
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::OnChanged() {
|
||||
if (cached_track_enabled_ != track_->enabled()) {
|
||||
cached_track_enabled_ = track_->enabled();
|
||||
Reconfigure();
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioRtpReceiver::SetOutputVolume(double volume) {
|
||||
RTC_DCHECK_GE(volume, 0.0);
|
||||
RTC_DCHECK_LE(volume, 10.0);
|
||||
RTC_DCHECK(media_channel_);
|
||||
RTC_DCHECK(ssrc_);
|
||||
return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->SetOutputVolume(*ssrc_, volume);
|
||||
});
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::OnSetVolume(double volume) {
|
||||
RTC_DCHECK_GE(volume, 0);
|
||||
RTC_DCHECK_LE(volume, 10);
|
||||
cached_volume_ = volume;
|
||||
if (!media_channel_ || !ssrc_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
|
||||
return;
|
||||
}
|
||||
// When the track is disabled, the volume of the source, which is the
|
||||
// corresponding WebRtc Voice Engine channel will be 0. So we do not allow
|
||||
// setting the volume to the source when the track is disabled.
|
||||
if (!stopped_ && track_->enabled()) {
|
||||
if (!SetOutputVolume(cached_volume_)) {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> AudioRtpReceiver::stream_ids() const {
|
||||
std::vector<std::string> stream_ids(streams_.size());
|
||||
for (size_t i = 0; i < streams_.size(); ++i)
|
||||
stream_ids[i] = streams_[i]->id();
|
||||
return stream_ids;
|
||||
}
|
||||
|
||||
RtpParameters AudioRtpReceiver::GetParameters() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return RtpParameters();
|
||||
}
|
||||
return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->GetRtpReceiveParameters(*ssrc_);
|
||||
});
|
||||
}
|
||||
|
||||
bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) {
|
||||
TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters");
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return false;
|
||||
}
|
||||
return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
|
||||
});
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
|
||||
frame_decryptor_ = std::move(frame_decryptor);
|
||||
// Special Case: Set the frame decryptor to any value on any existing channel.
|
||||
if (media_channel_ && ssrc_.has_value() && !stopped_) {
|
||||
worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
|
||||
media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface>
|
||||
AudioRtpReceiver::GetFrameDecryptor() const {
|
||||
return frame_decryptor_;
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::Stop() {
|
||||
// TODO(deadbeef): Need to do more here to fully stop receiving packets.
|
||||
if (stopped_) {
|
||||
return;
|
||||
}
|
||||
if (media_channel_ && ssrc_) {
|
||||
// Allow that SetOutputVolume fail. This is the normal case when the
|
||||
// underlying media channel has already been deleted.
|
||||
SetOutputVolume(0.0);
|
||||
}
|
||||
stopped_ = true;
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
|
||||
if (!media_channel_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "AudioRtpReceiver::SetupMediaChannel: No audio channel exists.";
|
||||
return;
|
||||
}
|
||||
if (ssrc_ == ssrc) {
|
||||
return;
|
||||
}
|
||||
if (ssrc_) {
|
||||
source_->Stop(media_channel_, *ssrc_);
|
||||
}
|
||||
ssrc_ = ssrc;
|
||||
source_->Start(media_channel_, *ssrc_);
|
||||
Reconfigure();
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
|
||||
SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetStreams(
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
|
||||
// Remove remote track from any streams that are going away.
|
||||
for (const auto& existing_stream : streams_) {
|
||||
bool removed = true;
|
||||
for (const auto& stream : streams) {
|
||||
if (existing_stream->id() == stream->id()) {
|
||||
RTC_DCHECK_EQ(existing_stream.get(), stream.get());
|
||||
removed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
existing_stream->RemoveTrack(track_);
|
||||
}
|
||||
}
|
||||
// Add remote track to any streams that are new.
|
||||
for (const auto& stream : streams) {
|
||||
bool added = true;
|
||||
for (const auto& existing_stream : streams_) {
|
||||
if (stream->id() == existing_stream->id()) {
|
||||
RTC_DCHECK_EQ(stream.get(), existing_stream.get());
|
||||
added = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (added) {
|
||||
stream->AddTrack(track_);
|
||||
}
|
||||
}
|
||||
streams_ = streams;
|
||||
}
|
||||
|
||||
std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return {};
|
||||
}
|
||||
return worker_thread_->Invoke<std::vector<RtpSource>>(
|
||||
RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::Reconfigure() {
|
||||
RTC_DCHECK(!stopped_);
|
||||
if (!media_channel_ || !ssrc_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "AudioRtpReceiver::Reconfigure: No audio channel exists.";
|
||||
return;
|
||||
}
|
||||
if (!SetOutputVolume(track_->enabled() ? cached_volume_ : 0)) {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
// Reattach the frame decryptor if we were reconfigured.
|
||||
MaybeAttachFrameDecryptorToMediaChannel(
|
||||
ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
|
||||
observer_ = observer;
|
||||
// Deliver any notifications the observer may have missed by being set late.
|
||||
if (received_first_packet_ && observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
|
||||
RTC_DCHECK(media_channel == nullptr ||
|
||||
media_channel->media_type() == media_type());
|
||||
media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::NotifyFirstPacketReceived() {
|
||||
if (observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
received_first_packet_ = true;
|
||||
}
|
||||
|
||||
VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> stream_ids)
|
||||
: VideoRtpReceiver(worker_thread,
|
||||
receiver_id,
|
||||
CreateStreamsFromIds(std::move(stream_ids))) {}
|
||||
|
||||
VideoRtpReceiver::VideoRtpReceiver(
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
|
||||
: worker_thread_(worker_thread),
|
||||
id_(receiver_id),
|
||||
source_(new RefCountedObject<VideoRtpTrackSource>()),
|
||||
track_(VideoTrackProxy::Create(
|
||||
rtc::Thread::Current(),
|
||||
worker_thread,
|
||||
VideoTrack::Create(
|
||||
receiver_id,
|
||||
VideoTrackSourceProxy::Create(rtc::Thread::Current(),
|
||||
worker_thread,
|
||||
source_),
|
||||
worker_thread))),
|
||||
attachment_id_(GenerateUniqueId()) {
|
||||
RTC_DCHECK(worker_thread_);
|
||||
SetStreams(streams);
|
||||
source_->SetState(MediaSourceInterface::kLive);
|
||||
}
|
||||
|
||||
VideoRtpReceiver::~VideoRtpReceiver() {
|
||||
// Since cricket::VideoRenderer is not reference counted,
|
||||
// we need to remove it from the channel before we are deleted.
|
||||
Stop();
|
||||
}
|
||||
|
||||
std::vector<std::string> VideoRtpReceiver::stream_ids() const {
|
||||
std::vector<std::string> stream_ids(streams_.size());
|
||||
for (size_t i = 0; i < streams_.size(); ++i)
|
||||
stream_ids[i] = streams_[i]->id();
|
||||
return stream_ids;
|
||||
}
|
||||
|
||||
bool VideoRtpReceiver::SetSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
|
||||
RTC_DCHECK(media_channel_);
|
||||
RTC_DCHECK(ssrc_);
|
||||
return worker_thread_->Invoke<bool>(
|
||||
RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); });
|
||||
}
|
||||
|
||||
RtpParameters VideoRtpReceiver::GetParameters() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return RtpParameters();
|
||||
}
|
||||
return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->GetRtpReceiveParameters(*ssrc_);
|
||||
});
|
||||
}
|
||||
|
||||
bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) {
|
||||
TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters");
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return false;
|
||||
}
|
||||
return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
|
||||
});
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
|
||||
frame_decryptor_ = std::move(frame_decryptor);
|
||||
// Special Case: Set the frame decryptor to any value on any existing channel.
|
||||
if (media_channel_ && ssrc_.has_value() && !stopped_) {
|
||||
worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
|
||||
media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface>
|
||||
VideoRtpReceiver::GetFrameDecryptor() const {
|
||||
return frame_decryptor_;
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::Stop() {
|
||||
// TODO(deadbeef): Need to do more here to fully stop receiving packets.
|
||||
if (stopped_) {
|
||||
return;
|
||||
}
|
||||
source_->SetState(MediaSourceInterface::kEnded);
|
||||
if (!media_channel_ || !ssrc_) {
|
||||
RTC_LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists.";
|
||||
} else {
|
||||
// Allow that SetSink fail. This is the normal case when the underlying
|
||||
// media channel has already been deleted.
|
||||
SetSink(nullptr);
|
||||
}
|
||||
stopped_ = true;
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
|
||||
if (!media_channel_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "VideoRtpReceiver::SetupMediaChannel: No video channel exists.";
|
||||
}
|
||||
if (ssrc_ == ssrc) {
|
||||
return;
|
||||
}
|
||||
if (ssrc_) {
|
||||
SetSink(nullptr);
|
||||
}
|
||||
ssrc_ = ssrc;
|
||||
SetSink(source_->sink());
|
||||
// Attach any existing frame decryptor to the media channel.
|
||||
MaybeAttachFrameDecryptorToMediaChannel(
|
||||
ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
|
||||
SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetStreams(
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
|
||||
// Remove remote track from any streams that are going away.
|
||||
for (const auto& existing_stream : streams_) {
|
||||
bool removed = true;
|
||||
for (const auto& stream : streams) {
|
||||
if (existing_stream->id() == stream->id()) {
|
||||
RTC_DCHECK_EQ(existing_stream.get(), stream.get());
|
||||
removed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
existing_stream->RemoveTrack(track_);
|
||||
}
|
||||
}
|
||||
// Add remote track to any streams that are new.
|
||||
for (const auto& stream : streams) {
|
||||
bool added = true;
|
||||
for (const auto& existing_stream : streams_) {
|
||||
if (stream->id() == existing_stream->id()) {
|
||||
RTC_DCHECK_EQ(stream.get(), existing_stream.get());
|
||||
added = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (added) {
|
||||
stream->AddTrack(track_);
|
||||
}
|
||||
}
|
||||
streams_ = streams;
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
|
||||
observer_ = observer;
|
||||
// Deliver any notifications the observer may have missed by being set late.
|
||||
if (received_first_packet_ && observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
|
||||
RTC_DCHECK(media_channel == nullptr ||
|
||||
media_channel->media_type() == media_type());
|
||||
media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::NotifyFirstPacketReceived() {
|
||||
if (observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
received_first_packet_ = true;
|
||||
}
|
||||
|
||||
std::vector<RtpSource> VideoRtpReceiver::GetSources() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return {};
|
||||
}
|
||||
return worker_thread_->Invoke<std::vector<RtpSource>>(
|
||||
RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include "api/video/video_source_interface.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "media/base/video_broadcaster.h"
|
||||
#include "pc/remote_audio_source.h"
|
||||
#include "pc/video_track_source.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
#include "rtc_base/thread.h"
|
||||
@ -78,203 +77,19 @@ class RtpReceiverInternal : public RtpReceiverInterface {
|
||||
// otherwise remains constant. Used to generate IDs for stats.
|
||||
// The special value zero means that no track is attached.
|
||||
virtual int AttachmentId() const = 0;
|
||||
};
|
||||
|
||||
class AudioRtpReceiver : public ObserverInterface,
|
||||
public AudioSourceInterface::AudioObserver,
|
||||
public rtc::RefCountedObject<RtpReceiverInternal> {
|
||||
public:
|
||||
AudioRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> stream_ids);
|
||||
// TODO(https://crbug.com/webrtc/9480): Remove this when streams() is removed.
|
||||
AudioRtpReceiver(
|
||||
protected:
|
||||
static int GenerateUniqueId();
|
||||
|
||||
static std::vector<rtc::scoped_refptr<MediaStreamInterface>>
|
||||
CreateStreamsFromIds(std::vector<std::string> stream_ids);
|
||||
|
||||
static void MaybeAttachFrameDecryptorToMediaChannel(
|
||||
const absl::optional<uint32_t>& ssrc,
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
|
||||
virtual ~AudioRtpReceiver();
|
||||
|
||||
// ObserverInterface implementation
|
||||
void OnChanged() override;
|
||||
|
||||
// AudioSourceInterface::AudioObserver implementation
|
||||
void OnSetVolume(double volume) override;
|
||||
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track() const {
|
||||
return track_.get();
|
||||
}
|
||||
|
||||
// RtpReceiverInterface implementation
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
|
||||
return track_.get();
|
||||
}
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
|
||||
return dtls_transport_;
|
||||
}
|
||||
std::vector<std::string> stream_ids() const override;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
|
||||
const override {
|
||||
return streams_;
|
||||
}
|
||||
|
||||
cricket::MediaType media_type() const override {
|
||||
return cricket::MEDIA_TYPE_AUDIO;
|
||||
}
|
||||
|
||||
std::string id() const override { return id_; }
|
||||
|
||||
RtpParameters GetParameters() const override;
|
||||
bool SetParameters(const RtpParameters& parameters) override;
|
||||
|
||||
void SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
|
||||
const override;
|
||||
|
||||
// RtpReceiverInternal implementation.
|
||||
void Stop() override;
|
||||
void SetupMediaChannel(uint32_t ssrc) override;
|
||||
uint32_t ssrc() const override { return ssrc_.value_or(0); }
|
||||
void NotifyFirstPacketReceived() override;
|
||||
void set_stream_ids(std::vector<std::string> stream_ids) override;
|
||||
void set_transport(
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
|
||||
dtls_transport_ = dtls_transport;
|
||||
}
|
||||
void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
|
||||
streams) override;
|
||||
void SetObserver(RtpReceiverObserverInterface* observer) override;
|
||||
|
||||
void SetMediaChannel(cricket::MediaChannel* media_channel) override;
|
||||
|
||||
std::vector<RtpSource> GetSources() const override;
|
||||
int AttachmentId() const override { return attachment_id_; }
|
||||
|
||||
private:
|
||||
void Reconfigure();
|
||||
bool SetOutputVolume(double volume);
|
||||
|
||||
rtc::Thread* const worker_thread_;
|
||||
const std::string id_;
|
||||
const rtc::scoped_refptr<RemoteAudioSource> source_;
|
||||
const rtc::scoped_refptr<AudioTrackInterface> track_;
|
||||
cricket::VoiceMediaChannel* media_channel_ = nullptr;
|
||||
absl::optional<uint32_t> ssrc_;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
|
||||
bool cached_track_enabled_;
|
||||
double cached_volume_ = 1;
|
||||
bool stopped_ = false;
|
||||
RtpReceiverObserverInterface* observer_ = nullptr;
|
||||
bool received_first_packet_ = false;
|
||||
int attachment_id_ = 0;
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
|
||||
};
|
||||
|
||||
class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
|
||||
public:
|
||||
// An SSRC of 0 will create a receiver that will match the first SSRC it
|
||||
// sees.
|
||||
VideoRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> streams_ids);
|
||||
// TODO(hbos): Remove this when streams() is removed.
|
||||
// https://crbug.com/webrtc/9480
|
||||
VideoRtpReceiver(
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
|
||||
|
||||
virtual ~VideoRtpReceiver();
|
||||
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track() const {
|
||||
return track_.get();
|
||||
}
|
||||
|
||||
// RtpReceiverInterface implementation
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
|
||||
return track_.get();
|
||||
}
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
|
||||
return dtls_transport_;
|
||||
}
|
||||
std::vector<std::string> stream_ids() const override;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
|
||||
const override {
|
||||
return streams_;
|
||||
}
|
||||
|
||||
cricket::MediaType media_type() const override {
|
||||
return cricket::MEDIA_TYPE_VIDEO;
|
||||
}
|
||||
|
||||
std::string id() const override { return id_; }
|
||||
|
||||
RtpParameters GetParameters() const override;
|
||||
bool SetParameters(const RtpParameters& parameters) override;
|
||||
|
||||
void SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
|
||||
const override;
|
||||
|
||||
// RtpReceiverInternal implementation.
|
||||
void Stop() override;
|
||||
void SetupMediaChannel(uint32_t ssrc) override;
|
||||
uint32_t ssrc() const override { return ssrc_.value_or(0); }
|
||||
void NotifyFirstPacketReceived() override;
|
||||
void set_stream_ids(std::vector<std::string> stream_ids) override;
|
||||
void set_transport(
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
|
||||
dtls_transport_ = dtls_transport;
|
||||
}
|
||||
void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
|
||||
streams) override;
|
||||
|
||||
void SetObserver(RtpReceiverObserverInterface* observer) override;
|
||||
|
||||
void SetMediaChannel(cricket::MediaChannel* media_channel) override;
|
||||
|
||||
int AttachmentId() const override { return attachment_id_; }
|
||||
|
||||
std::vector<RtpSource> GetSources() const override;
|
||||
|
||||
private:
|
||||
class VideoRtpTrackSource : public VideoTrackSource {
|
||||
public:
|
||||
VideoRtpTrackSource() : VideoTrackSource(true /* remote */) {}
|
||||
|
||||
rtc::VideoSourceInterface<VideoFrame>* source() override {
|
||||
return &broadcaster_;
|
||||
}
|
||||
rtc::VideoSinkInterface<VideoFrame>* sink() { return &broadcaster_; }
|
||||
|
||||
private:
|
||||
// |broadcaster_| is needed since the decoder can only handle one sink.
|
||||
// It might be better if the decoder can handle multiple sinks and consider
|
||||
// the VideoSinkWants.
|
||||
rtc::VideoBroadcaster broadcaster_;
|
||||
};
|
||||
|
||||
bool SetSink(rtc::VideoSinkInterface<VideoFrame>* sink);
|
||||
|
||||
rtc::Thread* const worker_thread_;
|
||||
const std::string id_;
|
||||
cricket::VideoMediaChannel* media_channel_ = nullptr;
|
||||
absl::optional<uint32_t> ssrc_;
|
||||
// |source_| is held here to be able to change the state of the source when
|
||||
// the VideoRtpReceiver is stopped.
|
||||
rtc::scoped_refptr<VideoRtpTrackSource> source_;
|
||||
rtc::scoped_refptr<VideoTrackInterface> track_;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
|
||||
bool stopped_ = false;
|
||||
RtpReceiverObserverInterface* observer_ = nullptr;
|
||||
bool received_first_packet_ = false;
|
||||
int attachment_id_ = 0;
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
|
||||
rtc::scoped_refptr<webrtc::FrameDecryptorInterface> frame_decryptor,
|
||||
cricket::MediaChannel* media_channel,
|
||||
bool stopped);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
#include "p2p/base/dtls_transport_internal.h"
|
||||
#include "p2p/base/fake_dtls_transport.h"
|
||||
#include "p2p/base/p2p_constants.h"
|
||||
#include "pc/audio_rtp_receiver.h"
|
||||
#include "pc/audio_track.h"
|
||||
#include "pc/channel.h"
|
||||
#include "pc/channel_manager.h"
|
||||
@ -51,6 +52,7 @@
|
||||
#include "pc/rtp_sender.h"
|
||||
#include "pc/rtp_transport_internal.h"
|
||||
#include "pc/test/fake_video_track_source.h"
|
||||
#include "pc/video_rtp_receiver.h"
|
||||
#include "pc/video_track.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/gunit.h"
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "api/rtp_transceiver_interface.h"
|
||||
#include "pc/channel_interface.h"
|
||||
#include "pc/rtp_receiver.h"
|
||||
#include "pc/rtp_sender.h"
|
||||
|
||||
|
||||
213
pc/video_rtp_receiver.cc
Normal file
213
pc/video_rtp_receiver.cc
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "pc/video_rtp_receiver.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "api/media_stream_proxy.h"
|
||||
#include "api/media_stream_track_proxy.h"
|
||||
#include "api/video_track_source_proxy.h"
|
||||
#include "pc/media_stream.h"
|
||||
#include "pc/video_track.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/location.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> stream_ids)
|
||||
: VideoRtpReceiver(worker_thread,
|
||||
receiver_id,
|
||||
CreateStreamsFromIds(std::move(stream_ids))) {}
|
||||
|
||||
VideoRtpReceiver::VideoRtpReceiver(
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
|
||||
: worker_thread_(worker_thread),
|
||||
id_(receiver_id),
|
||||
source_(new RefCountedObject<VideoRtpTrackSource>()),
|
||||
track_(VideoTrackProxy::Create(
|
||||
rtc::Thread::Current(),
|
||||
worker_thread,
|
||||
VideoTrack::Create(
|
||||
receiver_id,
|
||||
VideoTrackSourceProxy::Create(rtc::Thread::Current(),
|
||||
worker_thread,
|
||||
source_),
|
||||
worker_thread))),
|
||||
attachment_id_(GenerateUniqueId()) {
|
||||
RTC_DCHECK(worker_thread_);
|
||||
SetStreams(streams);
|
||||
source_->SetState(MediaSourceInterface::kLive);
|
||||
}
|
||||
|
||||
VideoRtpReceiver::~VideoRtpReceiver() {
|
||||
// Since cricket::VideoRenderer is not reference counted,
|
||||
// we need to remove it from the channel before we are deleted.
|
||||
Stop();
|
||||
}
|
||||
|
||||
std::vector<std::string> VideoRtpReceiver::stream_ids() const {
|
||||
std::vector<std::string> stream_ids(streams_.size());
|
||||
for (size_t i = 0; i < streams_.size(); ++i)
|
||||
stream_ids[i] = streams_[i]->id();
|
||||
return stream_ids;
|
||||
}
|
||||
|
||||
bool VideoRtpReceiver::SetSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
|
||||
RTC_DCHECK(media_channel_);
|
||||
RTC_DCHECK(ssrc_);
|
||||
return worker_thread_->Invoke<bool>(
|
||||
RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); });
|
||||
}
|
||||
|
||||
RtpParameters VideoRtpReceiver::GetParameters() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return RtpParameters();
|
||||
}
|
||||
return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->GetRtpReceiveParameters(*ssrc_);
|
||||
});
|
||||
}
|
||||
|
||||
bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) {
|
||||
TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters");
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return false;
|
||||
}
|
||||
return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
|
||||
return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
|
||||
});
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
|
||||
frame_decryptor_ = std::move(frame_decryptor);
|
||||
// Special Case: Set the frame decryptor to any value on any existing channel.
|
||||
if (media_channel_ && ssrc_.has_value() && !stopped_) {
|
||||
worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
|
||||
media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface>
|
||||
VideoRtpReceiver::GetFrameDecryptor() const {
|
||||
return frame_decryptor_;
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::Stop() {
|
||||
// TODO(deadbeef): Need to do more here to fully stop receiving packets.
|
||||
if (stopped_) {
|
||||
return;
|
||||
}
|
||||
source_->SetState(MediaSourceInterface::kEnded);
|
||||
if (!media_channel_ || !ssrc_) {
|
||||
RTC_LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists.";
|
||||
} else {
|
||||
// Allow that SetSink fail. This is the normal case when the underlying
|
||||
// media channel has already been deleted.
|
||||
SetSink(nullptr);
|
||||
}
|
||||
stopped_ = true;
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
|
||||
if (!media_channel_) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "VideoRtpReceiver::SetupMediaChannel: No video channel exists.";
|
||||
}
|
||||
if (ssrc_ == ssrc) {
|
||||
return;
|
||||
}
|
||||
if (ssrc_) {
|
||||
SetSink(nullptr);
|
||||
}
|
||||
ssrc_ = ssrc;
|
||||
SetSink(source_->sink());
|
||||
// Attach any existing frame decryptor to the media channel.
|
||||
MaybeAttachFrameDecryptorToMediaChannel(
|
||||
ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
|
||||
SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetStreams(
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
|
||||
// Remove remote track from any streams that are going away.
|
||||
for (const auto& existing_stream : streams_) {
|
||||
bool removed = true;
|
||||
for (const auto& stream : streams) {
|
||||
if (existing_stream->id() == stream->id()) {
|
||||
RTC_DCHECK_EQ(existing_stream.get(), stream.get());
|
||||
removed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
existing_stream->RemoveTrack(track_);
|
||||
}
|
||||
}
|
||||
// Add remote track to any streams that are new.
|
||||
for (const auto& stream : streams) {
|
||||
bool added = true;
|
||||
for (const auto& existing_stream : streams_) {
|
||||
if (stream->id() == existing_stream->id()) {
|
||||
RTC_DCHECK_EQ(stream.get(), existing_stream.get());
|
||||
added = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (added) {
|
||||
stream->AddTrack(track_);
|
||||
}
|
||||
}
|
||||
streams_ = streams;
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
|
||||
observer_ = observer;
|
||||
// Deliver any notifications the observer may have missed by being set late.
|
||||
if (received_first_packet_ && observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
|
||||
RTC_DCHECK(media_channel == nullptr ||
|
||||
media_channel->media_type() == media_type());
|
||||
media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
|
||||
}
|
||||
|
||||
void VideoRtpReceiver::NotifyFirstPacketReceived() {
|
||||
if (observer_) {
|
||||
observer_->OnFirstPacketReceived(media_type());
|
||||
}
|
||||
received_first_packet_ = true;
|
||||
}
|
||||
|
||||
std::vector<RtpSource> VideoRtpReceiver::GetSources() const {
|
||||
if (!media_channel_ || !ssrc_ || stopped_) {
|
||||
return {};
|
||||
}
|
||||
return worker_thread_->Invoke<std::vector<RtpSource>>(
|
||||
RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
144
pc/video_rtp_receiver.h
Normal file
144
pc/video_rtp_receiver.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef PC_VIDEO_RTP_RECEIVER_H_
|
||||
#define PC_VIDEO_RTP_RECEIVER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/crypto/frame_decryptor_interface.h"
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_receiver_interface.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/video/video_frame.h"
|
||||
#include "api/video/video_sink_interface.h"
|
||||
#include "api/video/video_source_interface.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "media/base/video_broadcaster.h"
|
||||
#include "pc/rtp_receiver.h"
|
||||
#include "pc/video_track_source.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
#include "rtc_base/thread.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
|
||||
public:
|
||||
// An SSRC of 0 will create a receiver that will match the first SSRC it
|
||||
// sees.
|
||||
VideoRtpReceiver(rtc::Thread* worker_thread,
|
||||
std::string receiver_id,
|
||||
std::vector<std::string> streams_ids);
|
||||
// TODO(hbos): Remove this when streams() is removed.
|
||||
// https://crbug.com/webrtc/9480
|
||||
VideoRtpReceiver(
|
||||
rtc::Thread* worker_thread,
|
||||
const std::string& receiver_id,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
|
||||
|
||||
virtual ~VideoRtpReceiver();
|
||||
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track() const {
|
||||
return track_.get();
|
||||
}
|
||||
|
||||
// RtpReceiverInterface implementation
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
|
||||
return track_.get();
|
||||
}
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
|
||||
return dtls_transport_;
|
||||
}
|
||||
std::vector<std::string> stream_ids() const override;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
|
||||
const override {
|
||||
return streams_;
|
||||
}
|
||||
|
||||
cricket::MediaType media_type() const override {
|
||||
return cricket::MEDIA_TYPE_VIDEO;
|
||||
}
|
||||
|
||||
std::string id() const override { return id_; }
|
||||
|
||||
RtpParameters GetParameters() const override;
|
||||
bool SetParameters(const RtpParameters& parameters) override;
|
||||
|
||||
void SetFrameDecryptor(
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) override;
|
||||
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor()
|
||||
const override;
|
||||
|
||||
// RtpReceiverInternal implementation.
|
||||
void Stop() override;
|
||||
void SetupMediaChannel(uint32_t ssrc) override;
|
||||
uint32_t ssrc() const override { return ssrc_.value_or(0); }
|
||||
void NotifyFirstPacketReceived() override;
|
||||
void set_stream_ids(std::vector<std::string> stream_ids) override;
|
||||
void set_transport(
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
|
||||
dtls_transport_ = dtls_transport;
|
||||
}
|
||||
void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
|
||||
streams) override;
|
||||
|
||||
void SetObserver(RtpReceiverObserverInterface* observer) override;
|
||||
|
||||
void SetMediaChannel(cricket::MediaChannel* media_channel) override;
|
||||
|
||||
int AttachmentId() const override { return attachment_id_; }
|
||||
|
||||
std::vector<RtpSource> GetSources() const override;
|
||||
|
||||
private:
|
||||
class VideoRtpTrackSource : public VideoTrackSource {
|
||||
public:
|
||||
VideoRtpTrackSource() : VideoTrackSource(true /* remote */) {}
|
||||
|
||||
rtc::VideoSourceInterface<VideoFrame>* source() override {
|
||||
return &broadcaster_;
|
||||
}
|
||||
rtc::VideoSinkInterface<VideoFrame>* sink() { return &broadcaster_; }
|
||||
|
||||
private:
|
||||
// |broadcaster_| is needed since the decoder can only handle one sink.
|
||||
// It might be better if the decoder can handle multiple sinks and consider
|
||||
// the VideoSinkWants.
|
||||
rtc::VideoBroadcaster broadcaster_;
|
||||
};
|
||||
|
||||
bool SetSink(rtc::VideoSinkInterface<VideoFrame>* sink);
|
||||
|
||||
rtc::Thread* const worker_thread_;
|
||||
const std::string id_;
|
||||
cricket::VideoMediaChannel* media_channel_ = nullptr;
|
||||
absl::optional<uint32_t> ssrc_;
|
||||
// |source_| is held here to be able to change the state of the source when
|
||||
// the VideoRtpReceiver is stopped.
|
||||
rtc::scoped_refptr<VideoRtpTrackSource> source_;
|
||||
rtc::scoped_refptr<VideoTrackInterface> track_;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
|
||||
bool stopped_ = false;
|
||||
RtpReceiverObserverInterface* observer_ = nullptr;
|
||||
bool received_first_packet_ = false;
|
||||
int attachment_id_ = 0;
|
||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
|
||||
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // PC_VIDEO_RTP_RECEIVER_H_
|
||||
Loading…
x
Reference in New Issue
Block a user