/* * Copyright 2017 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 "ortc/ortcrtpsenderadapter.h" #include #include "media/base/mediaconstants.h" #include "ortc/rtptransportadapter.h" #include "rtc_base/checks.h" namespace { void FillAudioSenderParameters(webrtc::RtpParameters* parameters) { for (webrtc::RtpCodecParameters& codec : parameters->codecs) { if (!codec.num_channels) { codec.num_channels = 1; } } } void FillVideoSenderParameters(webrtc::RtpParameters* parameters) { for (webrtc::RtpCodecParameters& codec : parameters->codecs) { if (!codec.clock_rate) { codec.clock_rate = cricket::kVideoCodecClockrate; } } } } // namespace namespace webrtc { BEGIN_OWNED_PROXY_MAP(OrtcRtpSender) PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_METHOD1(RTCError, SetTrack, MediaStreamTrackInterface*) PROXY_CONSTMETHOD0(rtc::scoped_refptr, GetTrack) PROXY_METHOD1(RTCError, SetTransport, RtpTransportInterface*) PROXY_CONSTMETHOD0(RtpTransportInterface*, GetTransport) PROXY_METHOD1(RTCError, Send, const RtpParameters&) PROXY_CONSTMETHOD0(RtpParameters, GetParameters) PROXY_CONSTMETHOD0(cricket::MediaType, GetKind) END_PROXY_MAP() // static std::unique_ptr OrtcRtpSenderAdapter::CreateProxy( std::unique_ptr wrapped_sender) { RTC_DCHECK(wrapped_sender); rtc::Thread* signaling = wrapped_sender->rtp_transport_controller_->signaling_thread(); rtc::Thread* worker = wrapped_sender->rtp_transport_controller_->worker_thread(); return OrtcRtpSenderProxy::Create(signaling, worker, std::move(wrapped_sender)); } OrtcRtpSenderAdapter::~OrtcRtpSenderAdapter() { internal_sender_ = nullptr; SignalDestroyed(); } RTCError OrtcRtpSenderAdapter::SetTrack(MediaStreamTrackInterface* track) { if (track && cricket::MediaTypeFromString(track->kind()) != kind_) { LOG_AND_RETURN_ERROR( RTCErrorType::INVALID_PARAMETER, "Track kind (audio/video) doesn't match the kind of this sender."); } if (internal_sender_ && !internal_sender_->SetTrack(track)) { // Since we checked the track type above, this should never happen... RTC_NOTREACHED(); LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR, "Failed to set track on RtpSender."); } track_ = track; return RTCError::OK(); } rtc::scoped_refptr OrtcRtpSenderAdapter::GetTrack() const { return track_; } RTCError OrtcRtpSenderAdapter::SetTransport(RtpTransportInterface* transport) { LOG_AND_RETURN_ERROR( RTCErrorType::UNSUPPORTED_OPERATION, "Changing the transport of an RtpSender is not yet supported."); } RtpTransportInterface* OrtcRtpSenderAdapter::GetTransport() const { return transport_; } RTCError OrtcRtpSenderAdapter::Send(const RtpParameters& parameters) { RtpParameters filled_parameters = parameters; RTCError err; uint32_t ssrc = 0; switch (kind_) { case cricket::MEDIA_TYPE_AUDIO: FillAudioSenderParameters(&filled_parameters); err = rtp_transport_controller_->ValidateAndApplyAudioSenderParameters( filled_parameters, &ssrc); if (!err.ok()) { return err; } break; case cricket::MEDIA_TYPE_VIDEO: FillVideoSenderParameters(&filled_parameters); err = rtp_transport_controller_->ValidateAndApplyVideoSenderParameters( filled_parameters, &ssrc); if (!err.ok()) { return err; } break; case cricket::MEDIA_TYPE_DATA: RTC_NOTREACHED(); return webrtc::RTCError(webrtc::RTCErrorType::INTERNAL_ERROR); } last_applied_parameters_ = filled_parameters; // Now that parameters were applied, can call SetSsrc on the internal sender. // This is analogous to a PeerConnection calling SetSsrc after // SetLocalDescription is successful. // // If there were no encodings, this SSRC may be 0, which is valid. if (!internal_sender_) { CreateInternalSender(); } internal_sender_->SetSsrc(ssrc); return RTCError::OK(); } RtpParameters OrtcRtpSenderAdapter::GetParameters() const { return last_applied_parameters_; } cricket::MediaType OrtcRtpSenderAdapter::GetKind() const { return kind_; } OrtcRtpSenderAdapter::OrtcRtpSenderAdapter( cricket::MediaType kind, RtpTransportInterface* transport, RtpTransportControllerAdapter* rtp_transport_controller) : kind_(kind), transport_(transport), rtp_transport_controller_(rtp_transport_controller) {} void OrtcRtpSenderAdapter::CreateInternalSender() { switch (kind_) { case cricket::MEDIA_TYPE_AUDIO: { auto* audio_sender = new AudioRtpSender( rtp_transport_controller_->worker_thread(), nullptr); auto* voice_channel = rtp_transport_controller_->voice_channel(); RTC_DCHECK(voice_channel); audio_sender->SetMediaChannel(voice_channel->media_channel()); internal_sender_ = audio_sender; break; } case cricket::MEDIA_TYPE_VIDEO: { auto* video_sender = new VideoRtpSender(rtp_transport_controller_->worker_thread()); auto* video_channel = rtp_transport_controller_->video_channel(); RTC_DCHECK(video_channel); video_sender->SetMediaChannel(video_channel->media_channel()); internal_sender_ = video_sender; break; } case cricket::MEDIA_TYPE_DATA: RTC_NOTREACHED(); } if (track_) { if (!internal_sender_->SetTrack(track_)) { // Since we checked the track type when it was set, this should never // happen... RTC_NOTREACHED(); } } } } // namespace webrtc