blob: 0bce59194211c5babde4bf115f0508502de24e87 [file] [log] [blame]
/*
* 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 "webrtc/ortc/ortcrtpsenderadapter.h"
#include <utility>
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/ortc/rtptransportadapter.h"
#include "webrtc/rtc_base/checks.h"
namespace {
void FillAudioSenderParameters(webrtc::RtpParameters* parameters) {
for (webrtc::RtpCodecParameters& codec : parameters->codecs) {
if (!codec.num_channels) {
codec.num_channels = rtc::Optional<int>(1);
}
}
}
void FillVideoSenderParameters(webrtc::RtpParameters* parameters) {
for (webrtc::RtpCodecParameters& codec : parameters->codecs) {
if (!codec.clock_rate) {
codec.clock_rate = rtc::Optional<int>(cricket::kVideoCodecClockrate);
}
}
}
} // namespace
namespace webrtc {
BEGIN_OWNED_PROXY_MAP(OrtcRtpSender)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_METHOD1(RTCError, SetTrack, MediaStreamTrackInterface*)
PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, 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<OrtcRtpSenderInterface> OrtcRtpSenderAdapter::CreateProxy(
std::unique_ptr<OrtcRtpSenderAdapter> 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<MediaStreamTrackInterface> 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:
internal_sender_ = new AudioRtpSender(
rtp_transport_controller_->voice_channel(), nullptr);
break;
case cricket::MEDIA_TYPE_VIDEO:
internal_sender_ =
new VideoRtpSender(rtp_transport_controller_->video_channel());
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