blob: 25848809def697495f79e3ea6b763d7fdf2f3db1 [file] [log] [blame]
/*
* Copyright (C) 2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "LibWebRTCUtils.h"
#if USE(LIBWEBRTC)
#include "LibWebRTCMacros.h"
#include "RTCPeerConnection.h"
#include "RTCRtpSendParameters.h"
#include <wtf/text/WTFString.h>
ALLOW_UNUSED_PARAMETERS_BEGIN
#include <webrtc/api/rtp_parameters.h>
#include <webrtc/api/rtp_transceiver_interface.h>
ALLOW_UNUSED_PARAMETERS_END
namespace WebCore {
static inline RTCRtpEncodingParameters toRTCEncodingParameters(const webrtc::RtpEncodingParameters& rtcParameters)
{
RTCRtpEncodingParameters parameters;
if (rtcParameters.ssrc)
parameters.ssrc = *rtcParameters.ssrc;
parameters.active = rtcParameters.active;
if (rtcParameters.max_bitrate_bps)
parameters.maxBitrate = *rtcParameters.max_bitrate_bps;
if (rtcParameters.max_framerate)
parameters.maxFramerate = *rtcParameters.max_framerate;
parameters.rid = fromStdString(rtcParameters.rid);
if (rtcParameters.scale_resolution_down_by)
parameters.scaleResolutionDownBy = *rtcParameters.scale_resolution_down_by;
return parameters;
}
static inline RTCRtpHeaderExtensionParameters toRTCHeaderExtensionParameters(const webrtc::RtpExtension& rtcParameters)
{
RTCRtpHeaderExtensionParameters parameters;
parameters.uri = fromStdString(rtcParameters.uri);
parameters.id = rtcParameters.id;
return parameters;
}
static inline webrtc::RtpExtension fromRTCHeaderExtensionParameters(const RTCRtpHeaderExtensionParameters& parameters)
{
webrtc::RtpExtension rtcParameters;
rtcParameters.uri = parameters.uri.utf8().data();
rtcParameters.id = parameters.id;
return rtcParameters;
}
static inline RTCRtpCodecParameters toRTCCodecParameters(const webrtc::RtpCodecParameters& rtcParameters)
{
RTCRtpCodecParameters parameters;
parameters.payloadType = rtcParameters.payload_type;
parameters.mimeType = fromStdString(rtcParameters.mime_type());
if (rtcParameters.clock_rate)
parameters.clockRate = *rtcParameters.clock_rate;
if (rtcParameters.num_channels)
parameters.channels = *rtcParameters.num_channels;
StringBuilder sdpFmtpLineBuilder;
sdpFmtpLineBuilder.append("a=fmtp:", parameters.payloadType, ' ');
bool isFirst = true;
for (auto& keyValue : rtcParameters.parameters) {
if (!isFirst)
sdpFmtpLineBuilder.append(';');
else
isFirst = false;
sdpFmtpLineBuilder.append(keyValue.first.c_str(), '=', keyValue.second.c_str());
}
parameters.sdpFmtpLine = sdpFmtpLineBuilder.toString();
return parameters;
}
RTCRtpParameters toRTCRtpParameters(const webrtc::RtpParameters& rtcParameters)
{
RTCRtpParameters parameters;
for (auto& extension : rtcParameters.header_extensions)
parameters.headerExtensions.append(toRTCHeaderExtensionParameters(extension));
for (auto& codec : rtcParameters.codecs)
parameters.codecs.append(toRTCCodecParameters(codec));
return parameters;
}
RTCRtpSendParameters toRTCRtpSendParameters(const webrtc::RtpParameters& rtcParameters)
{
RTCRtpSendParameters parameters { toRTCRtpParameters(rtcParameters) };
parameters.transactionId = fromStdString(rtcParameters.transaction_id);
for (auto& rtcEncoding : rtcParameters.encodings)
parameters.encodings.append(toRTCEncodingParameters(rtcEncoding));
if (rtcParameters.degradation_preference) {
switch (*rtcParameters.degradation_preference) {
// FIXME: Support DegradationPreference::DISABLED.
case webrtc::DegradationPreference::DISABLED:
case webrtc::DegradationPreference::MAINTAIN_FRAMERATE:
parameters.degradationPreference = RTCDegradationPreference::MaintainFramerate;
break;
case webrtc::DegradationPreference::MAINTAIN_RESOLUTION:
parameters.degradationPreference = RTCDegradationPreference::MaintainResolution;
break;
case webrtc::DegradationPreference::BALANCED:
parameters.degradationPreference = RTCDegradationPreference::Balanced;
break;
};
}
return parameters;
}
void updateRTCRtpSendParameters(const RTCRtpSendParameters& parameters, webrtc::RtpParameters& rtcParameters)
{
rtcParameters.transaction_id = parameters.transactionId.utf8().data();
if (parameters.encodings.size() != rtcParameters.encodings.size()) {
// If encodings size is different, setting parameters will fail. Let's make it so.
rtcParameters.encodings.clear();
return;
}
// We copy all current encodings parameters and only update parameters that can actually be usefully updated.
for (size_t i = 0; i < parameters.encodings.size(); ++i) {
rtcParameters.encodings[i].active = parameters.encodings[i].active;
if (parameters.encodings[i].maxBitrate)
rtcParameters.encodings[i].max_bitrate_bps = parameters.encodings[i].maxBitrate;
if (parameters.encodings[i].maxFramerate)
rtcParameters.encodings[i].max_framerate = parameters.encodings[i].maxFramerate;
}
rtcParameters.header_extensions.clear();
for (auto& extension : parameters.headerExtensions)
rtcParameters.header_extensions.push_back(fromRTCHeaderExtensionParameters(extension));
// Codecs parameters are readonly
switch (parameters.degradationPreference) {
case RTCDegradationPreference::MaintainFramerate:
rtcParameters.degradation_preference = webrtc::DegradationPreference::MAINTAIN_FRAMERATE;
break;
case RTCDegradationPreference::MaintainResolution:
rtcParameters.degradation_preference = webrtc::DegradationPreference::MAINTAIN_RESOLUTION;
break;
case RTCDegradationPreference::Balanced:
rtcParameters.degradation_preference = webrtc::DegradationPreference::BALANCED;
break;
}
}
RTCRtpTransceiverDirection toRTCRtpTransceiverDirection(webrtc::RtpTransceiverDirection rtcDirection)
{
switch (rtcDirection) {
case webrtc::RtpTransceiverDirection::kSendRecv:
return RTCRtpTransceiverDirection::Sendrecv;
case webrtc::RtpTransceiverDirection::kSendOnly:
return RTCRtpTransceiverDirection::Sendonly;
case webrtc::RtpTransceiverDirection::kRecvOnly:
return RTCRtpTransceiverDirection::Recvonly;
case webrtc::RtpTransceiverDirection::kInactive:
case webrtc::RtpTransceiverDirection::kStopped:
return RTCRtpTransceiverDirection::Inactive;
};
RELEASE_ASSERT_NOT_REACHED();
}
webrtc::RtpTransceiverDirection fromRTCRtpTransceiverDirection(RTCRtpTransceiverDirection direction)
{
switch (direction) {
case RTCRtpTransceiverDirection::Sendrecv:
return webrtc::RtpTransceiverDirection::kSendRecv;
case RTCRtpTransceiverDirection::Sendonly:
return webrtc::RtpTransceiverDirection::kSendOnly;
case RTCRtpTransceiverDirection::Recvonly:
return webrtc::RtpTransceiverDirection::kRecvOnly;
case RTCRtpTransceiverDirection::Inactive:
return webrtc::RtpTransceiverDirection::kInactive;
};
RELEASE_ASSERT_NOT_REACHED();
}
webrtc::RtpTransceiverInit fromRtpTransceiverInit(const RTCRtpTransceiverInit& init)
{
webrtc::RtpTransceiverInit rtcInit;
rtcInit.direction = fromRTCRtpTransceiverDirection(init.direction);
for (auto& stream : init.streams)
rtcInit.stream_ids.push_back(stream->id().utf8().data());
return rtcInit;
}
ExceptionCode toExceptionCode(webrtc::RTCErrorType type)
{
switch (type) {
case webrtc::RTCErrorType::INVALID_PARAMETER:
return InvalidAccessError;
case webrtc::RTCErrorType::INVALID_RANGE:
return RangeError;
case webrtc::RTCErrorType::SYNTAX_ERROR:
return SyntaxError;
case webrtc::RTCErrorType::INVALID_STATE:
return InvalidStateError;
case webrtc::RTCErrorType::INVALID_MODIFICATION:
return InvalidModificationError;
case webrtc::RTCErrorType::NETWORK_ERROR:
return NetworkError;
default:
return OperationError;
}
}
Exception toException(const webrtc::RTCError& error)
{
ASSERT(!error.ok());
return Exception { toExceptionCode(error.type()), error.message() };
}
} // namespace WebCore
#endif // USE(LIBWEBRTC)