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:
parent
d1f5fdac5c
commit
e702b30fec
@ -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); }
|
||||
};
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user