Adding C++ versions of currently spec'd "RtpParameters" structs.

These structs will be used for ORTC objects (and their WebRTC
equivalents).

This CL also introduces some minor changes to the existing implemented
structs:

- max_bitrate_bps uses rtc::Optional instead of "-1 means unset"
- "mime_type" turned into "name"/"kind" (which can be used to form the
  MIME type string, if needed).
- clock_rate and channels changed to rtc::Optional, since they will
  need to be for RtpSender.send().
- Renamed "channels" to "num_channels" (the ORTC name, which I prefer).

BUG=webrtc:7013, webrtc:7112

Review-Url: https://codereview.webrtc.org/2651883010
Cr-Commit-Position: refs/heads/master@{#16437}
This commit is contained in:
deadbeef 2017-02-04 12:09:01 -08:00 committed by Commit bot
parent d1f5fdac5c
commit e702b30fec
17 changed files with 681 additions and 172 deletions

View File

@ -12,22 +12,297 @@
#define WEBRTC_API_RTPPARAMETERS_H_
#include <string>
#include <unordered_map>
#include <vector>
#include "webrtc/api/mediatypes.h"
#include "webrtc/base/optional.h"
namespace webrtc {
// These structures are defined as part of the RtpSender interface.
// See http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface for details.
struct RtpEncodingParameters {
// These structures are intended to mirror those defined by:
// http://draft.ortc.org/#rtcrtpdictionaries*
// Contains everything specified as of 2017 Jan 24.
//
// They are used when retrieving or modifying the parameters of an
// RtpSender/RtpReceiver, or retrieving capabilities.
//
// Note on conventions: Where ORTC may use "octet", "short" and "unsigned"
// types, we typically use "int", in keeping with our style guidelines. The
// parameter's actual valid range will be enforced when the parameters are set,
// rather than when the parameters struct is built. An exception is made for
// SSRCs, since they use the full unsigned 32-bit range, and aren't expected to
// be used for any numeric comparisons/operations.
//
// Additionally, where ORTC uses strings, we may use enums for things that have
// a fixed number of supported values. However, for things that can be extended
// (such as codecs, by providing an external encoder factory), a string
// identifier is used.
enum class FecMechanism {
RED,
RED_AND_ULPFEC,
FLEXFEC,
};
// Used in RtcpFeedback struct.
enum class RtcpFeedbackType {
ACK,
CCM,
NACK,
REMB, // "goog-remb"
TRANSPORT_CC,
};
// Used in RtcpFeedback struct when type is ACK, NACK or CCM.
enum class RtcpFeedbackMessageType {
// Equivalent to {type: "nack", parameter: undefined} in ORTC.
GENERIC_NACK,
PLI, // Usable with NACK.
FIR, // Usable with CCM.
};
enum class DtxStatus {
DISABLED,
ENABLED,
};
enum class DegradationPreference {
MAINTAIN_FRAMERATE,
MAINTAIN_RESOLUTION,
BALANCED,
};
enum class PriorityType { VERY_LOW, LOW, MEDIUM, HIGH };
struct RtcpFeedback {
RtcpFeedbackType type = RtcpFeedbackType::ACK;
// Equivalent to ORTC "parameter" field with slight differences:
// 1. It's an enum instead of a string.
// 2. Generic NACK feedback is represented by a GENERIC_NACK message type,
// rather than an unset "parameter" value.
rtc::Optional<RtcpFeedbackMessageType> message_type;
bool operator==(const RtcpFeedback& o) const {
return type == o.type && message_type == o.message_type;
}
bool operator!=(const RtcpFeedback& o) const { return !(*this == o); }
};
// RtpCodecCapability is to RtpCodecParameters as RtpCapabilities is to
// RtpParameters. This represents the static capabilities of an endpoint's
// implementation of a codec.
struct RtpCodecCapability {
// Build MIME "type/subtype" string from |name| and |kind|.
std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
// Used to identify the codec. Equivalent to MIME subtype.
std::string name;
// The media type of this codec. Equivalent to MIME top-level type.
cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO;
// Clock rate in Hertz. If unset, the codec is applicable to any clock rate.
rtc::Optional<int> clock_rate;
// Default payload type for this codec. Mainly needed for codecs that use
// that have statically assigned payload types.
rtc::Optional<int> preferred_payload_type;
// Maximum packetization time supported by an RtpReceiver for this codec.
// TODO(deadbeef): Not implemented.
rtc::Optional<int> max_ptime;
// Preferred packetization time for an RtpReceiver or RtpSender of this
// codec.
// TODO(deadbeef): Not implemented.
rtc::Optional<int> ptime;
// The number of audio channels supported. Unused for video codecs.
rtc::Optional<int> num_channels;
// Feedback mechanisms supported for this codec.
std::vector<RtcpFeedback> rtcp_feedback;
// Codec-specific parameters that must be signaled to the remote party.
// Corresponds to "a=fmtp" parameters in SDP.
std::unordered_map<std::string, std::string> parameters;
// Codec-specific parameters that may optionally be signaled to the remote
// party.
// TODO(deadbeef): Not implemented.
std::unordered_map<std::string, std::string> options;
// Maximum number of temporal layer extensions supported by this codec.
// For example, a value of 1 indicates that 2 total layers are supported.
// TODO(deadbeef): Not implemented.
int max_temporal_layer_extensions = 0;
// Maximum number of spatial layer extensions supported by this codec.
// For example, a value of 1 indicates that 2 total layers are supported.
// TODO(deadbeef): Not implemented.
int max_spatial_layer_extensions = 0;
// Whether the implementation can send/receive SVC layers with distinct
// SSRCs. Always false for audio codecs. True for video codecs that support
// scalable video coding with MRST.
// TODO(deadbeef): Not implemented.
bool svc_multi_stream_support = false;
bool operator==(const RtpCodecCapability& o) const {
return name == o.name && kind == o.kind && clock_rate == o.clock_rate &&
preferred_payload_type == o.preferred_payload_type &&
max_ptime == o.max_ptime && ptime == o.ptime &&
num_channels == o.num_channels && rtcp_feedback == o.rtcp_feedback &&
parameters == o.parameters && options == o.options &&
max_temporal_layer_extensions == o.max_temporal_layer_extensions &&
max_spatial_layer_extensions == o.max_spatial_layer_extensions &&
svc_multi_stream_support == o.svc_multi_stream_support;
}
bool operator!=(const RtpCodecCapability& o) const { return !(*this == o); }
};
// Used in RtpCapabilities; represents the capabilities/preferences of an
// implementation for a header extension.
//
// Just called "RtpHeaderExtension" in ORTC, but the "Capability" suffix was
// added here for consistency and to avoid confusion with
// RtpHeaderExtensionParameters.
//
// Note that ORTC includes a "kind" field, but we omit this because it's
// redundant; if you call "RtpReceiver::GetCapabilities(MEDIA_TYPE_AUDIO)",
// you know you're getting audio capabilities.
struct RtpHeaderExtensionCapability {
// URI of this extension, as defined in RFC5285.
std::string uri;
// Preferred value of ID that goes in the packet.
rtc::Optional<int> preferred_id;
// If true, it's preferred that the value in the header is encrypted.
// TODO(deadbeef): Not implemented.
bool preferred_encrypt = false;
bool operator==(const RtpHeaderExtensionCapability& o) const {
return uri == o.uri && preferred_id == o.preferred_id &&
preferred_encrypt == o.preferred_encrypt;
}
bool operator!=(const RtpHeaderExtensionCapability& o) const {
return !(*this == o);
}
};
// Used in RtpParameters; represents a specific configuration of a header
// extension.
struct RtpHeaderExtensionParameters {
// URI of this extension, as defined in RFC5285.
std::string uri;
// ID value that goes in the packet.
int id = 0;
// If true, the value in the header is encrypted.
// TODO(deadbeef): Not implemented.
bool encrypt = false;
bool operator==(const RtpHeaderExtensionParameters& o) const {
return uri == o.uri && id == o.id && encrypt == o.encrypt;
}
bool operator!=(const RtpHeaderExtensionParameters& o) const {
return !(*this == o);
}
};
struct RtpFecParameters {
// If unset, a value is chosen by the implementation.
rtc::Optional<uint32_t> ssrc;
FecMechanism mechanism = FecMechanism::RED;
bool operator==(const RtpFecParameters& o) const {
return ssrc == o.ssrc && mechanism == o.mechanism;
}
bool operator!=(const RtpFecParameters& o) const { return !(*this == o); }
};
struct RtpRtxParameters {
// If unset, a value is chosen by the implementation.
rtc::Optional<uint32_t> ssrc;
bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; }
bool operator!=(const RtpRtxParameters& o) const { return !(*this == o); }
};
struct RtpEncodingParameters {
// If unset, a value is chosen by the implementation.
rtc::Optional<uint32_t> ssrc;
// Can be used to reference a codec in the |codecs| member of the
// RtpParameters that contains this RtpEncodingParameters. If unset, the
// implementation will choose the first possible codec.
// TODO(deadbeef): Not implemented.
rtc::Optional<int> codec_payload_type;
// Specifies the FEC mechanism, if set.
// TODO(deadbeef): Not implemented.
rtc::Optional<RtpFecParameters> fec;
// Specifies the RTX parameters, if set.
// TODO(deadbeef): Not implemented.
rtc::Optional<RtpRtxParameters> rtx;
// Only used for audio. If set, determines whether or not discontinuous
// transmission will be used, if an available codec supports it. If not
// set, the implementation default setting will be used.
rtc::Optional<DtxStatus> dtx;
// The relative priority of this encoding.
// TODO(deadbeef): Not implemented.
rtc::Optional<PriorityType> priority;
// If set, this represents the Transport Independent Application Specific
// maximum bandwidth defined in RFC3890. If unset, there is no maximum
// bitrate.
// Just called "maxBitrate" in ORTC spec.
rtc::Optional<int> max_bitrate_bps;
// TODO(deadbeef): Not implemented.
rtc::Optional<int> max_framerate;
// For video, scale the resolution down by this factor.
// TODO(deadbeef): Not implemented.
double scale_resolution_down_by = 1.0;
// Scale the framerate down by this factor.
// TODO(deadbeef): Not implemented.
double scale_framerate_down_by = 1.0;
// For an RtpSender, set to true to cause this encoding to be sent, and false
// for it not to be sent. For an RtpReceiver, set to true to cause the
// encoding to be decoded, and false for it to be ignored.
// TODO(deadbeef): RtpReceiver part is not implemented.
bool active = true;
int max_bitrate_bps = -1;
// Value to use for RID RTP header extension.
// Called "encodingId" in ORTC.
// TODO(deadbeef): Not implemented.
std::string rid;
// RIDs of encodings on which this layer depends.
// Called "dependencyEncodingIds" in ORTC spec.
// TODO(deadbeef): Not implemented.
std::vector<std::string> dependency_rids;
bool operator==(const RtpEncodingParameters& o) const {
return ssrc == o.ssrc && active == o.active &&
max_bitrate_bps == o.max_bitrate_bps;
return ssrc == o.ssrc && codec_payload_type == o.codec_payload_type &&
fec == o.fec && rtx == o.rtx && dtx == o.dtx &&
priority == o.priority && max_bitrate_bps == o.max_bitrate_bps &&
max_framerate == o.max_framerate &&
scale_resolution_down_by == o.scale_resolution_down_by &&
scale_framerate_down_by == o.scale_framerate_down_by &&
active == o.active && rid == o.rid &&
dependency_rids == o.dependency_rids;
}
bool operator!=(const RtpEncodingParameters& o) const {
return !(*this == o);
@ -35,25 +310,107 @@ struct RtpEncodingParameters {
};
struct RtpCodecParameters {
int payload_type;
std::string mime_type;
int clock_rate;
int channels = 1;
// TODO(deadbeef): Add sdpFmtpLine field.
// Build MIME "type/subtype" string from |name| and |kind|.
std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
// Used to identify the codec. Equivalent to MIME subtype.
std::string name;
// The media type of this codec. Equivalent to MIME top-level type.
cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO;
// Payload type used to identify this codec in RTP packets.
// This MUST always be present, and must be unique across all codecs using
// the same transport.
int payload_type = 0;
// If unset, the implementation default is used.
rtc::Optional<int> clock_rate;
// The number of audio channels used. Unset for video codecs. If unset for
// audio, the implementation default is used.
// TODO(deadbeef): The "implementation default" part is unimplemented.
rtc::Optional<int> num_channels;
// The maximum packetization time to be used by an RtpSender.
// If |ptime| is also set, this will be ignored.
// TODO(deadbeef): Not implemented.
rtc::Optional<int> max_ptime;
// The packetization time to be used by an RtpSender.
// If unset, will use any time up to max_ptime.
// TODO(deadbeef): Not implemented.
rtc::Optional<int> ptime;
// Feedback mechanisms to be used for this codec.
// TODO(deadbeef): Not implemented.
std::vector<RtcpFeedback> rtcp_feedback;
// Codec-specific parameters that must be signaled to the remote party.
// Corresponds to "a=fmtp" parameters in SDP.
// TODO(deadbeef): Not implemented.
std::unordered_map<std::string, std::string> parameters;
bool operator==(const RtpCodecParameters& o) const {
return payload_type == o.payload_type && mime_type == o.mime_type &&
clock_rate == o.clock_rate && channels == o.channels;
return name == o.name && kind == o.kind && payload_type == o.payload_type &&
clock_rate == o.clock_rate && num_channels == o.num_channels &&
max_ptime == o.max_ptime && ptime == o.ptime &&
rtcp_feedback == o.rtcp_feedback && parameters == o.parameters;
}
bool operator!=(const RtpCodecParameters& o) const { return !(*this == o); }
};
// RtpCapabilities is used to represent the static capabilities of an
// endpoint. An application can use these capabilities to construct an
// RtpParameters.
struct RtpCapabilities {
// Supported codecs.
std::vector<RtpCodecCapability> codecs;
// Supported RTP header extensions.
std::vector<RtpHeaderExtensionCapability> header_extensions;
// Supported Forward Error Correction (FEC) mechanisms.
std::vector<FecMechanism> fec;
bool operator==(const RtpCapabilities& o) const {
return codecs == o.codecs && header_extensions == o.header_extensions &&
fec == o.fec;
}
bool operator!=(const RtpCapabilities& o) const { return !(*this == o); }
};
// Note that unlike in ORTC, an RtcpParameters is not included in
// RtpParameters, because our API will include an additional "RtpTransport"
// abstraction on which RTCP parameters are set.
struct RtpParameters {
std::vector<RtpEncodingParameters> encodings;
// Used when calling getParameters/setParameters with a PeerConnection
// RtpSender, to ensure that outdated parameters are not unintentionally
// applied successfully.
// TODO(deadbeef): Not implemented.
std::string transaction_id;
// Value to use for MID RTP header extension.
// Called "muxId" in ORTC.
// TODO(deadbeef): Not implemented.
std::string mid;
std::vector<RtpCodecParameters> codecs;
// TODO(deadbeef): Not implemented.
std::vector<RtpHeaderExtensionParameters> header_extensions;
std::vector<RtpEncodingParameters> encodings;
// TODO(deadbeef): Not implemented.
DegradationPreference degradation_preference =
DegradationPreference::BALANCED;
bool operator==(const RtpParameters& o) const {
return encodings == o.encodings && codecs == o.codecs;
return mid == o.mid && codecs == o.codecs &&
header_extensions == o.header_extensions &&
encodings == o.encodings &&
degradation_preference == o.degradation_preference;
}
bool operator!=(const RtpParameters& o) const { return !(*this == o); }
};

View File

@ -149,8 +149,8 @@ void Codec::IntersectFeedbackParams(const Codec& other) {
webrtc::RtpCodecParameters Codec::ToCodecParameters() const {
webrtc::RtpCodecParameters codec_params;
codec_params.payload_type = id;
codec_params.mime_type = name;
codec_params.clock_rate = clockrate;
codec_params.name = name;
codec_params.clock_rate = rtc::Optional<int>(clockrate);
return codec_params;
}
@ -190,12 +190,6 @@ bool AudioCodec::Matches(const AudioCodec& codec) const {
((codec.channels < 2 && channels < 2) || channels == codec.channels);
}
webrtc::RtpCodecParameters AudioCodec::ToCodecParameters() const {
webrtc::RtpCodecParameters codec_params = Codec::ToCodecParameters();
codec_params.channels = static_cast<int>(channels);
return codec_params;
}
std::string AudioCodec::ToString() const {
std::ostringstream os;
os << "AudioCodec[" << id << ":" << name << ":" << clockrate << ":" << bitrate
@ -203,12 +197,25 @@ std::string AudioCodec::ToString() const {
return os.str();
}
webrtc::RtpCodecParameters AudioCodec::ToCodecParameters() const {
webrtc::RtpCodecParameters codec_params = Codec::ToCodecParameters();
codec_params.num_channels = rtc::Optional<int>(static_cast<int>(channels));
codec_params.kind = MEDIA_TYPE_AUDIO;
return codec_params;
}
std::string VideoCodec::ToString() const {
std::ostringstream os;
os << "VideoCodec[" << id << ":" << name << "]";
return os.str();
}
webrtc::RtpCodecParameters VideoCodec::ToCodecParameters() const {
webrtc::RtpCodecParameters codec_params = Codec::ToCodecParameters();
codec_params.kind = MEDIA_TYPE_VIDEO;
return codec_params;
}
VideoCodec::VideoCodec(int id, const std::string& name)
: Codec(id, name, kVideoCodecClockrate) {
SetDefaultParameters();

View File

@ -162,6 +162,8 @@ struct VideoCodec : public Codec {
std::string ToString() const;
webrtc::RtpCodecParameters ToCodecParameters() const override;
VideoCodec& operator=(const VideoCodec& c);
VideoCodec& operator=(VideoCodec&& c);

View File

@ -311,14 +311,17 @@ TEST(CodecTest, TestToCodecParameters) {
const VideoCodec v(96, "V");
webrtc::RtpCodecParameters codec_params_1 = v.ToCodecParameters();
EXPECT_EQ(96, codec_params_1.payload_type);
EXPECT_EQ("V", codec_params_1.mime_type);
EXPECT_EQ(cricket::kVideoCodecClockrate, codec_params_1.clock_rate);
EXPECT_EQ(1, codec_params_1.channels);
EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec_params_1.kind);
EXPECT_EQ("V", codec_params_1.name);
EXPECT_EQ(rtc::Optional<int>(cricket::kVideoCodecClockrate),
codec_params_1.clock_rate);
EXPECT_EQ(rtc::Optional<int>(), codec_params_1.num_channels);
const AudioCodec a(97, "A", 44100, 20000, 2);
webrtc::RtpCodecParameters codec_params_2 = a.ToCodecParameters();
EXPECT_EQ(97, codec_params_2.payload_type);
EXPECT_EQ("A", codec_params_2.mime_type);
EXPECT_EQ(44100, codec_params_2.clock_rate);
EXPECT_EQ(2, codec_params_2.channels);
EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec_params_2.kind);
EXPECT_EQ("A", codec_params_2.name);
EXPECT_EQ(rtc::Optional<int>(44100), codec_params_2.clock_rate);
EXPECT_EQ(rtc::Optional<int>(2), codec_params_2.num_channels);
}

View File

@ -1861,9 +1861,12 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
encoder_config.number_of_streams = 1;
}
int stream_max_bitrate =
MinPositive(rtp_parameters_.encodings[0].max_bitrate_bps,
parameters_.max_bitrate_bps);
int stream_max_bitrate = parameters_.max_bitrate_bps;
if (rtp_parameters_.encodings[0].max_bitrate_bps) {
stream_max_bitrate =
MinPositive(*(rtp_parameters_.encodings[0].max_bitrate_bps),
parameters_.max_bitrate_bps);
}
int codec_max_bitrate_kbps;
if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) {

View File

@ -1177,12 +1177,13 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
webrtc::RtpParameters parameters =
channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, parameters.encodings.size());
parameters.encodings[0].max_bitrate_bps = stream_max;
parameters.encodings[0].max_bitrate_bps = rtc::Optional<int>(stream_max);
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
// Read back the parameteres and verify they have the correct value
parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, parameters.encodings.size());
EXPECT_EQ(stream_max, parameters.encodings[0].max_bitrate_bps);
EXPECT_EQ(rtc::Optional<int>(stream_max),
parameters.encodings[0].max_bitrate_bps);
// Verify that the new value propagated down to the encoder
EXPECT_EQ(expected_encoder_bitrate, GetMaxEncoderBitrate());
}

View File

@ -520,10 +520,16 @@ const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[14] = {
{kDtmfCodecName, 8000, 1, 126, false, {}}
};
// |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
// |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
int rtp_max_bitrate_bps,
rtc::Optional<int> rtp_max_bitrate_bps,
const webrtc::CodecInst& codec_inst) {
const int bps = MinPositive(max_send_bitrate_bps, rtp_max_bitrate_bps);
// If application-configured bitrate is set, take minimum of that and SDP
// bitrate.
const int bps = rtp_max_bitrate_bps
? MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
: max_send_bitrate_bps;
const int codec_rate = codec_inst.rate;
if (bps <= 0) {

View File

@ -289,7 +289,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(ssrc);
EXPECT_EQ(1UL, parameters.encodings.size());
parameters.encodings[0].max_bitrate_bps = bitrate;
parameters.encodings[0].max_bitrate_bps = rtc::Optional<int>(bitrate);
return channel_->SetRtpSendParameters(ssrc, parameters);
}

View File

@ -1956,7 +1956,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
return channel1_->SetRemoteContent(&content, CA_OFFER, NULL);
}
webrtc::RtpParameters BitrateLimitedParameters(int limit) {
webrtc::RtpParameters BitrateLimitedParameters(rtc::Optional<int> limit) {
webrtc::RtpParameters parameters;
webrtc::RtpEncodingParameters encoding;
encoding.max_bitrate_bps = limit;
@ -1965,7 +1965,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
}
void VerifyMaxBitrate(const webrtc::RtpParameters& parameters,
int expected_bitrate) {
rtc::Optional<int> expected_bitrate) {
EXPECT_EQ(1UL, parameters.encodings.size());
EXPECT_EQ(expected_bitrate, parameters.encodings[0].max_bitrate_bps);
}
@ -1975,7 +1975,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(
channel1_->SetLocalContent(&local_media_content1_, CA_OFFER, NULL));
EXPECT_EQ(media_channel1_->max_bps(), -1);
VerifyMaxBitrate(media_channel1_->GetRtpSendParameters(kSsrc1), -1);
VerifyMaxBitrate(media_channel1_->GetRtpSendParameters(kSsrc1),
rtc::Optional<int>());
}
void CanChangeMaxBitrate() {
@ -1984,15 +1985,19 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
channel1_->SetLocalContent(&local_media_content1_, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRtpSendParameters(
kSsrc1, BitrateLimitedParameters(1000)));
VerifyMaxBitrate(channel1_->GetRtpSendParameters(kSsrc1), 1000);
VerifyMaxBitrate(media_channel1_->GetRtpSendParameters(kSsrc1), 1000);
kSsrc1, BitrateLimitedParameters(rtc::Optional<int>(1000))));
VerifyMaxBitrate(channel1_->GetRtpSendParameters(kSsrc1),
rtc::Optional<int>(1000));
VerifyMaxBitrate(media_channel1_->GetRtpSendParameters(kSsrc1),
rtc::Optional<int>(1000));
EXPECT_EQ(-1, media_channel1_->max_bps());
EXPECT_TRUE(
channel1_->SetRtpSendParameters(kSsrc1, BitrateLimitedParameters(-1)));
VerifyMaxBitrate(channel1_->GetRtpSendParameters(kSsrc1), -1);
VerifyMaxBitrate(media_channel1_->GetRtpSendParameters(kSsrc1), -1);
EXPECT_TRUE(channel1_->SetRtpSendParameters(
kSsrc1, BitrateLimitedParameters(rtc::Optional<int>())));
VerifyMaxBitrate(channel1_->GetRtpSendParameters(kSsrc1),
rtc::Optional<int>());
VerifyMaxBitrate(media_channel1_->GetRtpSendParameters(kSsrc1),
rtc::Optional<int>());
EXPECT_EQ(-1, media_channel1_->max_bps());
}

View File

@ -170,13 +170,16 @@ std::unique_ptr<RTCCodecStats> CodecStatsFromRtpCodecParameters(
const RtpCodecParameters& codec_params) {
RTC_DCHECK_GE(codec_params.payload_type, 0);
RTC_DCHECK_LE(codec_params.payload_type, 127);
RTC_DCHECK(codec_params.clock_rate);
uint32_t payload_type = static_cast<uint32_t>(codec_params.payload_type);
std::unique_ptr<RTCCodecStats> codec_stats(new RTCCodecStats(
RTCCodecStatsIDFromDirectionMediaAndPayload(inbound, audio, payload_type),
timestamp_us));
codec_stats->payload_type = payload_type;
codec_stats->codec = (audio ? "audio/" : "video/") + codec_params.mime_type;
codec_stats->clock_rate = static_cast<uint32_t>(codec_params.clock_rate);
codec_stats->codec = codec_params.mime_type();
if (codec_params.clock_rate) {
codec_stats->clock_rate = static_cast<uint32_t>(*codec_params.clock_rate);
}
return codec_stats;
}

View File

@ -765,15 +765,17 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
RtpCodecParameters inbound_audio_codec;
inbound_audio_codec.payload_type = 1;
inbound_audio_codec.mime_type = "opus";
inbound_audio_codec.clock_rate = 1337;
inbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
inbound_audio_codec.name = "opus";
inbound_audio_codec.clock_rate = rtc::Optional<int>(1337);
voice_media_info.receive_codecs.insert(
std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
RtpCodecParameters outbound_audio_codec;
outbound_audio_codec.payload_type = 2;
outbound_audio_codec.mime_type = "isac";
outbound_audio_codec.clock_rate = 1338;
outbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
outbound_audio_codec.name = "isac";
outbound_audio_codec.clock_rate = rtc::Optional<int>(1338);
voice_media_info.send_codecs.insert(
std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
@ -785,15 +787,17 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
RtpCodecParameters inbound_video_codec;
inbound_video_codec.payload_type = 3;
inbound_video_codec.mime_type = "H264";
inbound_video_codec.clock_rate = 1339;
inbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
inbound_video_codec.name = "H264";
inbound_video_codec.clock_rate = rtc::Optional<int>(1339);
video_media_info.receive_codecs.insert(
std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
RtpCodecParameters outbound_video_codec;
outbound_video_codec.payload_type = 4;
outbound_video_codec.mime_type = "VP8";
outbound_video_codec.clock_rate = 1340;
outbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
outbound_video_codec.name = "VP8";
outbound_video_codec.clock_rate = rtc::Optional<int>(1340);
video_media_info.send_codecs.insert(
std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
@ -1687,8 +1691,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
RtpCodecParameters codec_parameters;
codec_parameters.payload_type = 42;
codec_parameters.mime_type = "dummy";
codec_parameters.clock_rate = 0;
codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
codec_parameters.name = "dummy";
codec_parameters.clock_rate = rtc::Optional<int>(0);
voice_media_info.receive_codecs.insert(
std::make_pair(codec_parameters.payload_type, codec_parameters));
@ -1769,8 +1774,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
RtpCodecParameters codec_parameters;
codec_parameters.payload_type = 42;
codec_parameters.mime_type = "dummy";
codec_parameters.clock_rate = 0;
codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
codec_parameters.name = "dummy";
codec_parameters.clock_rate = rtc::Optional<int>(0);
video_media_info.receive_codecs.insert(
std::make_pair(codec_parameters.payload_type, codec_parameters));
@ -1848,8 +1854,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
RtpCodecParameters codec_parameters;
codec_parameters.payload_type = 42;
codec_parameters.mime_type = "dummy";
codec_parameters.clock_rate = 0;
codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
codec_parameters.name = "dummy";
codec_parameters.clock_rate = rtc::Optional<int>(0);
voice_media_info.send_codecs.insert(
std::make_pair(codec_parameters.payload_type, codec_parameters));
@ -1927,8 +1934,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
RtpCodecParameters codec_parameters;
codec_parameters.payload_type = 42;
codec_parameters.mime_type = "dummy";
codec_parameters.clock_rate = 0;
codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
codec_parameters.name = "dummy";
codec_parameters.clock_rate = rtc::Optional<int>(0);
video_media_info.send_codecs.insert(
std::make_pair(codec_parameters.payload_type, codec_parameters));

View File

@ -575,19 +575,19 @@ TEST_F(RtpSenderReceiverTest, SetAudioMaxSendBitrate) {
EXPECT_EQ(-1, voice_media_channel_->max_bps());
webrtc::RtpParameters params = audio_rtp_sender_->GetParameters();
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
params.encodings[0].max_bitrate_bps = 1000;
EXPECT_FALSE(params.encodings[0].max_bitrate_bps);
params.encodings[0].max_bitrate_bps = rtc::Optional<int>(1000);
EXPECT_TRUE(audio_rtp_sender_->SetParameters(params));
// Read back the parameters and verify they have been changed.
params = audio_rtp_sender_->GetParameters();
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
EXPECT_EQ(rtc::Optional<int>(1000), params.encodings[0].max_bitrate_bps);
// Verify that the audio channel received the new parameters.
params = voice_media_channel_->GetRtpSendParameters(kAudioSsrc);
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
EXPECT_EQ(rtc::Optional<int>(1000), params.encodings[0].max_bitrate_bps);
// Verify that the global bitrate limit has not been changed.
EXPECT_EQ(-1, voice_media_channel_->max_bps());
@ -611,19 +611,19 @@ TEST_F(RtpSenderReceiverTest, SetVideoMaxSendBitrate) {
EXPECT_EQ(-1, video_media_channel_->max_bps());
webrtc::RtpParameters params = video_rtp_sender_->GetParameters();
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
params.encodings[0].max_bitrate_bps = 1000;
EXPECT_FALSE(params.encodings[0].max_bitrate_bps);
params.encodings[0].max_bitrate_bps = rtc::Optional<int>(1000);
EXPECT_TRUE(video_rtp_sender_->SetParameters(params));
// Read back the parameters and verify they have been changed.
params = video_rtp_sender_->GetParameters();
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
EXPECT_EQ(rtc::Optional<int>(1000), params.encodings[0].max_bitrate_bps);
// Verify that the video channel received the new parameters.
params = video_media_channel_->GetRtpSendParameters(kVideoSsrc);
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
EXPECT_EQ(rtc::Optional<int>(1000), params.encodings[0].max_bitrate_bps);
// Verify that the global bitrate limit has not been changed.
EXPECT_EQ(-1, video_media_channel_->max_bps());

View File

@ -15,23 +15,43 @@ import java.util.LinkedList;
/**
* The parameters for an {@code RtpSender}, as defined in
* http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface.
*
* Note: These structures use nullable Integer/etc. types because in the
* future, they may be used to construct ORTC RtpSender/RtpReceivers, in
* which case "null" will be used to represent "choose the implementation
* default value".
*/
public class RtpParameters {
public static class Encoding {
// Set to true to cause this encoding to be sent, and false for it not to
// be sent.
public boolean active = true;
// A null value means "no maximum bitrate".
// If non-null, this represents the Transport Independent Application
// Specific maximum bandwidth defined in RFC3890. If null, there is no
// maximum bitrate.
public Integer maxBitrateBps;
// SSRC to be used by this encoding.
// Can't be changed between getParameters/setParameters.
public Long ssrc;
}
public static class Codec {
int payloadType;
String mimeType;
int clockRate;
int channels = 1;
// Payload type used to identify this codec in RTP packets.
public int payloadType;
// Name used to identify the codec. Equivalent to MIME subtype.
public String name;
// The media type of this codec. Equivalent to MIME top-level type.
MediaStreamTrack.MediaType kind;
// Clock rate in Hertz.
public Integer clockRate;
// The number of audio channels used. Set to null for video codecs.
public Integer numChannels;
}
public final LinkedList<Encoding> encodings;
// Codec parameters can't currently be changed between getParameters and
// setParameters. Though in the future it will be possible to reorder them or
// remove them.
public final LinkedList<Codec> codecs;
public RtpParameters() {

View File

@ -158,6 +158,47 @@ static DataChannelInit JavaDataChannelInitToNative(
return init;
}
static cricket::MediaType JavaMediaTypeToJsepMediaType(JNIEnv* jni,
jobject j_media_type) {
jclass j_media_type_class =
FindClass(jni, "org/webrtc/MediaStreamTrack$MediaType");
jmethodID j_name_id =
GetMethodID(jni, j_media_type_class, "name", "()Ljava/lang/String;");
jstring j_type_string =
(jstring)jni->CallObjectMethod(j_media_type, j_name_id);
CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
std::string type_string = JavaToStdString(jni, j_type_string);
RTC_DCHECK(type_string == "MEDIA_TYPE_AUDIO" ||
type_string == "MEDIA_TYPE_VIDEO")
<< "Media type: " << type_string;
return type_string == "MEDIA_TYPE_AUDIO" ? cricket::MEDIA_TYPE_AUDIO
: cricket::MEDIA_TYPE_VIDEO;
}
static jobject JsepMediaTypeToJavaMediaType(JNIEnv* jni,
cricket::MediaType media_type) {
jclass j_media_type_class =
FindClass(jni, "org/webrtc/MediaStreamTrack$MediaType");
const char* media_type_str = nullptr;
switch (media_type) {
case cricket::MEDIA_TYPE_AUDIO:
media_type_str = "MEDIA_TYPE_AUDIO";
break;
case cricket::MEDIA_TYPE_VIDEO:
media_type_str = "MEDIA_TYPE_VIDEO";
break;
case cricket::MEDIA_TYPE_DATA:
RTC_NOTREACHED();
break;
}
jfieldID j_media_type_fid =
GetStaticFieldID(jni, j_media_type_class, media_type_str,
"Lorg/webrtc/MediaStreamTrack$MediaType;");
return GetStaticObjectField(jni, j_media_type_class, j_media_type_fid);
}
class ConstraintsWrapper;
// Adapter between the C++ PeerConnectionObserver interface and the Java
@ -917,20 +958,7 @@ class RtpReceiverObserver : public RtpReceiverObserverInterface {
jni, GetObjectClass(jni, *j_observer_global_), "onFirstPacketReceived",
"(Lorg/webrtc/MediaStreamTrack$MediaType;)V");
// Get the Java version of media type.
jclass j_media_type_class =
FindClass(jni, "org/webrtc/MediaStreamTrack$MediaType");
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
media_type == cricket::MEDIA_TYPE_VIDEO)
<< "Media type: " << media_type;
const char* media_type_str = media_type == cricket::MEDIA_TYPE_AUDIO
? "MEDIA_TYPE_AUDIO"
: "MEDIA_TYPE_VIDEO";
jfieldID j_media_type_fid =
GetStaticFieldID(jni, j_media_type_class, media_type_str,
"Lorg/webrtc/MediaStreamTrack$MediaType;");
jobject JavaMediaType =
GetStaticObjectField(jni, j_media_type_class, j_media_type_fid);
jobject JavaMediaType = JsepMediaTypeToJavaMediaType(jni, media_type);
// Trigger the callback function.
jni->CallVoidMethod(*j_observer_global_, j_on_first_packet_received_mid,
JavaMediaType);
@ -2400,7 +2428,6 @@ static void JavaRtpParametersToJsepRtpParameters(
// Convert encodings.
jobject j_encodings = GetObjectField(jni, j_parameters, encodings_id);
const int kBitrateUnlimited = -1;
jclass j_encoding_parameters_class =
jni->FindClass("org/webrtc/RtpParameters$Encoding");
jfieldID active_id =
@ -2422,9 +2449,7 @@ static void JavaRtpParametersToJsepRtpParameters(
if (!IsNull(jni, j_bitrate)) {
int bitrate_value = jni->CallIntMethod(j_bitrate, int_value_id);
CHECK_EXCEPTION(jni) << "error during CallIntMethod";
encoding.max_bitrate_bps = bitrate_value;
} else {
encoding.max_bitrate_bps = kBitrateUnlimited;
encoding.max_bitrate_bps = rtc::Optional<int>(bitrate_value);
}
jobject j_ssrc =
GetNullableObjectField(jni, j_encoding_parameters, ssrc_id);
@ -2440,18 +2465,33 @@ static void JavaRtpParametersToJsepRtpParameters(
jobject j_codecs = GetObjectField(jni, j_parameters, codecs_id);
jclass codec_class = jni->FindClass("org/webrtc/RtpParameters$Codec");
jfieldID payload_type_id = GetFieldID(jni, codec_class, "payloadType", "I");
jfieldID mime_type_id =
GetFieldID(jni, codec_class, "mimeType", "Ljava/lang/String;");
jfieldID clock_rate_id = GetFieldID(jni, codec_class, "clockRate", "I");
jfieldID channels_id = GetFieldID(jni, codec_class, "channels", "I");
jfieldID name_id = GetFieldID(jni, codec_class, "name", "Ljava/lang/String;");
jfieldID kind_id = GetFieldID(jni, codec_class, "kind",
"Lorg/webrtc/MediaStreamTrack$MediaType;");
jfieldID clock_rate_id =
GetFieldID(jni, codec_class, "clockRate", "Ljava/lang/Integer;");
jfieldID num_channels_id =
GetFieldID(jni, codec_class, "numChannels", "Ljava/lang/Integer;");
for (jobject j_codec : Iterable(jni, j_codecs)) {
webrtc::RtpCodecParameters codec;
codec.payload_type = GetIntField(jni, j_codec, payload_type_id);
codec.mime_type =
JavaToStdString(jni, GetStringField(jni, j_codec, mime_type_id));
codec.clock_rate = GetIntField(jni, j_codec, clock_rate_id);
codec.channels = GetIntField(jni, j_codec, channels_id);
codec.name = JavaToStdString(jni, GetStringField(jni, j_codec, name_id));
codec.kind = JavaMediaTypeToJsepMediaType(
jni, GetObjectField(jni, j_codec, kind_id));
jobject j_clock_rate = GetNullableObjectField(jni, j_codec, clock_rate_id);
if (!IsNull(jni, j_clock_rate)) {
int clock_rate_value = jni->CallIntMethod(j_clock_rate, int_value_id);
CHECK_EXCEPTION(jni) << "error during CallIntMethod";
codec.clock_rate = rtc::Optional<int>(clock_rate_value);
}
jobject j_num_channels =
GetNullableObjectField(jni, j_codec, num_channels_id);
if (!IsNull(jni, j_num_channels)) {
int num_channels_value = jni->CallIntMethod(j_num_channels, int_value_id);
CHECK_EXCEPTION(jni) << "error during CallIntMethod";
codec.num_channels = rtc::Optional<int>(num_channels_value);
}
parameters->codecs.push_back(codec);
}
}
@ -2473,8 +2513,7 @@ static jobject JsepRtpParametersToJavaRtpParameters(
jobject j_encodings = GetObjectField(jni, j_parameters, encodings_id);
jmethodID encodings_add = GetMethodID(jni, GetObjectClass(jni, j_encodings),
"add", "(Ljava/lang/Object;)Z");
jfieldID active_id =
GetFieldID(jni, encoding_class, "active", "Z");
jfieldID active_id = GetFieldID(jni, encoding_class, "active", "Z");
jfieldID bitrate_id =
GetFieldID(jni, encoding_class, "maxBitrateBps", "Ljava/lang/Integer;");
jfieldID ssrc_id =
@ -2491,9 +2530,9 @@ static jobject JsepRtpParametersToJavaRtpParameters(
CHECK_EXCEPTION(jni) << "error during NewObject";
jni->SetBooleanField(j_encoding_parameters, active_id, encoding.active);
CHECK_EXCEPTION(jni) << "error during SetBooleanField";
if (encoding.max_bitrate_bps > 0) {
jobject j_bitrate_value =
jni->NewObject(integer_class, integer_ctor, encoding.max_bitrate_bps);
if (encoding.max_bitrate_bps) {
jobject j_bitrate_value = jni->NewObject(integer_class, integer_ctor,
*(encoding.max_bitrate_bps));
CHECK_EXCEPTION(jni) << "error during NewObject";
jni->SetObjectField(j_encoding_parameters, bitrate_id, j_bitrate_value);
CHECK_EXCEPTION(jni) << "error during SetObjectField";
@ -2517,26 +2556,42 @@ static jobject JsepRtpParametersToJavaRtpParameters(
jfieldID codecs_id =
GetFieldID(jni, parameters_class, "codecs", "Ljava/util/LinkedList;");
jobject j_codecs = GetObjectField(jni, j_parameters, codecs_id);
jmethodID codecs_add = GetMethodID(jni, GetObjectClass(jni, j_codecs),
"add", "(Ljava/lang/Object;)Z");
jmethodID codecs_add = GetMethodID(jni, GetObjectClass(jni, j_codecs), "add",
"(Ljava/lang/Object;)Z");
jfieldID payload_type_id = GetFieldID(jni, codec_class, "payloadType", "I");
jfieldID mime_type_id =
GetFieldID(jni, codec_class, "mimeType", "Ljava/lang/String;");
jfieldID clock_rate_id = GetFieldID(jni, codec_class, "clockRate", "I");
jfieldID channels_id = GetFieldID(jni, codec_class, "channels", "I");
jfieldID name_id = GetFieldID(jni, codec_class, "name", "Ljava/lang/String;");
jfieldID kind_id = GetFieldID(jni, codec_class, "kind",
"Lorg/webrtc/MediaStreamTrack$MediaType;");
jfieldID clock_rate_id =
GetFieldID(jni, codec_class, "clockRate", "Ljava/lang/Integer;");
jfieldID num_channels_id =
GetFieldID(jni, codec_class, "numChannels", "Ljava/lang/Integer;");
for (const webrtc::RtpCodecParameters& codec : parameters.codecs) {
jobject j_codec = jni->NewObject(codec_class, codec_ctor);
CHECK_EXCEPTION(jni) << "error during NewObject";
jni->SetIntField(j_codec, payload_type_id, codec.payload_type);
CHECK_EXCEPTION(jni) << "error during SetIntField";
jni->SetObjectField(j_codec, mime_type_id,
JavaStringFromStdString(jni, codec.mime_type));
jni->SetObjectField(j_codec, name_id,
JavaStringFromStdString(jni, codec.name));
CHECK_EXCEPTION(jni) << "error during SetObjectField";
jni->SetIntField(j_codec, clock_rate_id, codec.clock_rate);
CHECK_EXCEPTION(jni) << "error during SetIntField";
jni->SetIntField(j_codec, channels_id, codec.channels);
CHECK_EXCEPTION(jni) << "error during SetIntField";
jni->SetObjectField(j_codec, kind_id,
JsepMediaTypeToJavaMediaType(jni, codec.kind));
CHECK_EXCEPTION(jni) << "error during SetObjectField";
if (codec.clock_rate) {
jobject j_clock_rate_value =
jni->NewObject(integer_class, integer_ctor, *(codec.clock_rate));
CHECK_EXCEPTION(jni) << "error during NewObject";
jni->SetObjectField(j_codec, clock_rate_id, j_clock_rate_value);
CHECK_EXCEPTION(jni) << "error during SetObjectField";
}
if (codec.num_channels) {
jobject j_num_channels_value =
jni->NewObject(integer_class, integer_ctor, *(codec.num_channels));
CHECK_EXCEPTION(jni) << "error during NewObject";
jni->SetObjectField(j_codec, num_channels_id, j_num_channels_value);
CHECK_EXCEPTION(jni) << "error during SetObjectField";
}
jboolean added = jni->CallBooleanMethod(j_codecs, codecs_add, j_codec);
CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
RTC_CHECK(added);

View File

@ -11,33 +11,36 @@
#import "RTCRtpCodecParameters+Private.h"
#import "NSString+StdString.h"
#import "WebRTC/RTCMediaStreamTrack.h" // For "kind" strings.
#include "webrtc/base/checks.h"
#include "webrtc/media/base/mediaconstants.h"
const NSString * const kRTCRtxCodecMimeType = @(cricket::kRtxCodecName);
const NSString * const kRTCRedCodecMimeType = @(cricket::kRedCodecName);
const NSString * const kRTCUlpfecCodecMimeType = @(cricket::kUlpfecCodecName);
const NSString * const kRTCFlexfecCodecMimeType = @(cricket::kFlexfecCodecName);
const NSString * const kRTCOpusCodecMimeType = @(cricket::kOpusCodecName);
const NSString * const kRTCIsacCodecMimeType = @(cricket::kIsacCodecName);
const NSString * const kRTCL16CodecMimeType = @(cricket::kL16CodecName);
const NSString * const kRTCG722CodecMimeType = @(cricket::kG722CodecName);
const NSString * const kRTCIlbcCodecMimeType = @(cricket::kIlbcCodecName);
const NSString * const kRTCPcmuCodecMimeType = @(cricket::kPcmuCodecName);
const NSString * const kRTCPcmaCodecMimeType = @(cricket::kPcmaCodecName);
const NSString * const kRTCDtmfCodecMimeType = @(cricket::kDtmfCodecName);
const NSString * const kRTCComfortNoiseCodecMimeType =
const NSString * const kRTCRtxCodecName = @(cricket::kRtxCodecName);
const NSString * const kRTCRedCodecName = @(cricket::kRedCodecName);
const NSString * const kRTCUlpfecCodecName = @(cricket::kUlpfecCodecName);
const NSString * const kRTCFlexfecCodecName = @(cricket::kFlexfecCodecName);
const NSString * const kRTCOpusCodecName = @(cricket::kOpusCodecName);
const NSString * const kRTCIsacCodecName = @(cricket::kIsacCodecName);
const NSString * const kRTCL16CodecName = @(cricket::kL16CodecName);
const NSString * const kRTCG722CodecName = @(cricket::kG722CodecName);
const NSString * const kRTCIlbcCodecName = @(cricket::kIlbcCodecName);
const NSString * const kRTCPcmuCodecName = @(cricket::kPcmuCodecName);
const NSString * const kRTCPcmaCodecName = @(cricket::kPcmaCodecName);
const NSString * const kRTCDtmfCodecName = @(cricket::kDtmfCodecName);
const NSString * const kRTCComfortNoiseCodecName =
@(cricket::kComfortNoiseCodecName);
const NSString * const kVp8CodecMimeType = @(cricket::kVp8CodecName);
const NSString * const kVp9CodecMimeType = @(cricket::kVp9CodecName);
const NSString * const kH264CodecMimeType = @(cricket::kH264CodecName);
const NSString * const kVp8CodecName = @(cricket::kVp8CodecName);
const NSString * const kVp9CodecName = @(cricket::kVp9CodecName);
const NSString * const kH264CodecName = @(cricket::kH264CodecName);
@implementation RTCRtpCodecParameters
@synthesize payloadType = _payloadType;
@synthesize mimeType = _mimeType;
@synthesize name = _name;
@synthesize kind = _kind;
@synthesize clockRate = _clockRate;
@synthesize channels = _channels;
@synthesize numChannels = _numChannels;
- (instancetype)init {
return [super init];
@ -47,9 +50,24 @@ const NSString * const kH264CodecMimeType = @(cricket::kH264CodecName);
(const webrtc::RtpCodecParameters &)nativeParameters {
if (self = [self init]) {
_payloadType = nativeParameters.payload_type;
_mimeType = [NSString stringForStdString:nativeParameters.mime_type];
_clockRate = nativeParameters.clock_rate;
_channels = nativeParameters.channels;
_name = [NSString stringForStdString:nativeParameters.name];
switch (nativeParameters.kind) {
case cricket::MEDIA_TYPE_AUDIO:
_kind = kRTCMediaStreamTrackKindAudio;
break;
case cricket::MEDIA_TYPE_VIDEO:
_kind = kRTCMediaStreamTrackKindVideo;
break;
case cricket::MEDIA_TYPE_DATA:
RTC_NOTREACHED();
break;
}
if (nativeParameters.clock_rate) {
_clockRate = [NSNumber numberWithInt:*nativeParameters.clock_rate];
}
if (nativeParameters.num_channels) {
_numChannels = [NSNumber numberWithInt:*nativeParameters.num_channels];
}
}
return self;
}
@ -57,9 +75,22 @@ const NSString * const kH264CodecMimeType = @(cricket::kH264CodecName);
- (webrtc::RtpCodecParameters)nativeParameters {
webrtc::RtpCodecParameters parameters;
parameters.payload_type = _payloadType;
parameters.mime_type = [NSString stdStringForString:_mimeType];
parameters.clock_rate = _clockRate;
parameters.channels = _channels;
parameters.name = [NSString stdStringForString:_name];
// NSString pointer comparison is safe here since "kind" is readonly and only
// populated above.
if (_kind == kRTCMediaStreamTrackKindAudio) {
parameters.kind = cricket::MEDIA_TYPE_AUDIO;
} else if (_kind == kRTCMediaStreamTrackKindVideo) {
parameters.kind = cricket::MEDIA_TYPE_VIDEO;
} else {
RTC_NOTREACHED();
}
if (_clockRate != nil) {
parameters.clock_rate = rtc::Optional<int>(_clockRate.intValue);
}
if (_numChannels != nil) {
parameters.num_channels = rtc::Optional<int>(_numChannels.intValue);
}
return parameters;
}

View File

@ -16,8 +16,6 @@
@synthesize maxBitrateBps = _maxBitrateBps;
@synthesize ssrc = _ssrc;
static const int kBitrateUnlimited = -1;
- (instancetype)init {
return [super init];
}
@ -26,10 +24,9 @@ static const int kBitrateUnlimited = -1;
(const webrtc::RtpEncodingParameters &)nativeParameters {
if (self = [self init]) {
_isActive = nativeParameters.active;
// TODO(skvlad): Replace with rtc::Optional once the C++ code is updated.
if (nativeParameters.max_bitrate_bps != kBitrateUnlimited) {
if (nativeParameters.max_bitrate_bps) {
_maxBitrateBps =
[NSNumber numberWithInt:nativeParameters.max_bitrate_bps];
[NSNumber numberWithInt:*nativeParameters.max_bitrate_bps];
}
if (nativeParameters.ssrc) {
_ssrc = [NSNumber numberWithUnsignedLong:*nativeParameters.ssrc];
@ -42,7 +39,7 @@ static const int kBitrateUnlimited = -1;
webrtc::RtpEncodingParameters parameters;
parameters.active = _isActive;
if (_maxBitrateBps != nil) {
parameters.max_bitrate_bps = _maxBitrateBps.intValue;
parameters.max_bitrate_bps = rtc::Optional<int>(_maxBitrateBps.intValue);
}
if (_ssrc != nil) {
parameters.ssrc = rtc::Optional<uint32_t>(_ssrc.unsignedLongValue);

View File

@ -14,22 +14,22 @@
NS_ASSUME_NONNULL_BEGIN
RTC_EXTERN const NSString * const kRTCRtxCodecMimeType;
RTC_EXTERN const NSString * const kRTCRedCodecMimeType;
RTC_EXTERN const NSString * const kRTCUlpfecCodecMimeType;
RTC_EXTERN const NSString * const kRTCFlexfecCodecMimeType;
RTC_EXTERN const NSString * const kRTCOpusCodecMimeType;
RTC_EXTERN const NSString * const kRTCIsacCodecMimeType;
RTC_EXTERN const NSString * const kRTCL16CodecMimeType;
RTC_EXTERN const NSString * const kRTCG722CodecMimeType;
RTC_EXTERN const NSString * const kRTCIlbcCodecMimeType;
RTC_EXTERN const NSString * const kRTCPcmuCodecMimeType;
RTC_EXTERN const NSString * const kRTCPcmaCodecMimeType;
RTC_EXTERN const NSString * const kRTCDtmfCodecMimeType;
RTC_EXTERN const NSString * const kRTCComfortNoiseCodecMimeType;
RTC_EXTERN const NSString * const kRTCVp8CodecMimeType;
RTC_EXTERN const NSString * const kRTCVp9CodecMimeType;
RTC_EXTERN const NSString * const kRTCH264CodecMimeType;
RTC_EXTERN const NSString * const kRTCRtxCodecName;
RTC_EXTERN const NSString * const kRTCRedCodecName;
RTC_EXTERN const NSString * const kRTCUlpfecCodecName;
RTC_EXTERN const NSString * const kRTCFlexfecCodecName;
RTC_EXTERN const NSString * const kRTCOpusCodecName;
RTC_EXTERN const NSString * const kRTCIsacCodecName;
RTC_EXTERN const NSString * const kRTCL16CodecName;
RTC_EXTERN const NSString * const kRTCG722CodecName;
RTC_EXTERN const NSString * const kRTCIlbcCodecName;
RTC_EXTERN const NSString * const kRTCPcmuCodecName;
RTC_EXTERN const NSString * const kRTCPcmaCodecName;
RTC_EXTERN const NSString * const kRTCDtmfCodecName;
RTC_EXTERN const NSString * const kRTCComfortNoiseCodecName;
RTC_EXTERN const NSString * const kRTCVp8CodecName;
RTC_EXTERN const NSString * const kRTCVp9CodecName;
RTC_EXTERN const NSString * const kRTCH264CodecName;
/** Defined in http://w3c.github.io/webrtc-pc/#idl-def-RTCRtpCodecParameters */
RTC_EXPORT
@ -39,18 +39,29 @@ RTC_EXPORT
@property(nonatomic, assign) int payloadType;
/**
* The codec MIME type. Valid types are listed in:
* The codec MIME subtype. Valid types are listed in:
* http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-2
*
* Several supported types are represented by the constants above.
*/
@property(nonatomic, nonnull) NSString *mimeType;
@property(nonatomic, readonly, nonnull) NSString *name;
/**
* The media type of this codec. Equivalent to MIME top-level type.
*
* Valid values are kRTCMediaStreamTrackKindAudio and
* kRTCMediaStreamTrackKindVideo.
*/
@property(nonatomic, readonly, nonnull) NSString *kind;
/** The codec clock rate expressed in Hertz. */
@property(nonatomic, assign) int clockRate;
@property(nonatomic, readonly, nullable) NSNumber *clockRate;
/** The number of channels (mono=1, stereo=2). */
@property(nonatomic, assign) int channels;
/**
* The number of channels (mono=1, stereo=2).
* Set to null for video codecs.
**/
@property(nonatomic, readonly, nullable) NSNumber *numChannels;
- (instancetype)init NS_DESIGNATED_INITIALIZER;