From 0cd086b70ec939cad25768d5e17a61da23613281 Mon Sep 17 00:00:00 2001 From: Taylor Brandstetter Date: Wed, 20 Apr 2016 16:23:10 -0700 Subject: [PATCH] Adding codecs to the RtpParameters returned by an RtpSender. Contains every field except for sdpFmtpLine. Setting a reordered list of codecs is not yet supported. R=glaznev@webrtc.org, pthatcher@webrtc.org, skvlad@webrtc.org, tkchin@webrtc.org Review URL: https://codereview.webrtc.org/1885473004 . Cr-Commit-Position: refs/heads/master@{#12453} --- webrtc/api/BUILD.gn | 3 + webrtc/api/api.gyp | 3 + webrtc/api/java/jni/peerconnection_jni.cc | 67 +++++++++++++++++-- .../java/src/org/webrtc/RtpParameters.java | 9 +++ .../api/objc/RTCRtpCodecParameters+Private.h | 30 +++++++++ webrtc/api/objc/RTCRtpCodecParameters.h | 55 +++++++++++++++ webrtc/api/objc/RTCRtpCodecParameters.mm | 63 +++++++++++++++++ webrtc/api/objc/RTCRtpParameters.h | 4 ++ webrtc/api/objc/RTCRtpParameters.mm | 13 ++++ webrtc/api/rtpparameters.h | 23 +++++++ webrtc/media/base/codec.cc | 14 ++++ webrtc/media/base/codec.h | 5 ++ webrtc/media/engine/webrtcvideoengine2.cc | 13 +++- webrtc/media/engine/webrtcvideoengine2.h | 1 + .../engine/webrtcvideoengine2_unittest.cc | 37 ++++++++++ webrtc/media/engine/webrtcvoiceengine.cc | 16 ++++- webrtc/media/engine/webrtcvoiceengine.h | 1 + .../engine/webrtcvoiceengine_unittest.cc | 38 +++++++++++ 18 files changed, 388 insertions(+), 7 deletions(-) create mode 100644 webrtc/api/objc/RTCRtpCodecParameters+Private.h create mode 100644 webrtc/api/objc/RTCRtpCodecParameters.h create mode 100644 webrtc/api/objc/RTCRtpCodecParameters.mm diff --git a/webrtc/api/BUILD.gn b/webrtc/api/BUILD.gn index 9bc4c27fc6..65039536c3 100644 --- a/webrtc/api/BUILD.gn +++ b/webrtc/api/BUILD.gn @@ -61,6 +61,9 @@ if (is_ios) { #"objc/RTCPeerConnectionFactory+Private.h", #"objc/RTCPeerConnectionFactory.h", #"objc/RTCPeerConnectionFactory.mm", + #"objc/RTCRtpCodecParameters+Private.h", + #"objc/RTCRtpCodecParameters.h", + #"objc/RTCRtpCodecParameters.mm", #"objc/RTCRtpEncodingParameters+Private.h", #"objc/RTCRtpEncodingParameters.h", #"objc/RTCRtpEncodingParameters.mm", diff --git a/webrtc/api/api.gyp b/webrtc/api/api.gyp index cfa8d9b8ef..3d47053ab4 100644 --- a/webrtc/api/api.gyp +++ b/webrtc/api/api.gyp @@ -172,6 +172,9 @@ 'objc/RTCPeerConnectionFactory+Private.h', 'objc/RTCPeerConnectionFactory.h', 'objc/RTCPeerConnectionFactory.mm', + 'objc/RTCRtpCodecParameters+Private.h', + 'objc/RTCRtpCodecParameters.h', + 'objc/RTCRtpCodecParameters.mm', 'objc/RTCRtpEncodingParameters+Private.h', 'objc/RTCRtpEncodingParameters.h', 'objc/RTCRtpEncodingParameters.mm', diff --git a/webrtc/api/java/jni/peerconnection_jni.cc b/webrtc/api/java/jni/peerconnection_jni.cc index cbdcbe0285..fdd2d44bae 100644 --- a/webrtc/api/java/jni/peerconnection_jni.cc +++ b/webrtc/api/java/jni/peerconnection_jni.cc @@ -2058,6 +2058,29 @@ static bool JavaEncodingToJsepRtpEncodingParameters( return true; } +static bool JavaCodecToJsepRtpCodecParameters( + JNIEnv* jni, + jobject j_codecs, + std::vector* codecs) { + 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"); + + 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); + codecs->push_back(codec); + } + return true; +} + JOW(jboolean, RtpSender_nativeSetParameters) (JNIEnv* jni, jclass, jlong j_rtp_sender_pointer, jobject j_parameters) { if (IsNull(jni, j_parameters)) { @@ -2067,11 +2090,15 @@ JOW(jboolean, RtpSender_nativeSetParameters) jclass encoding_class = jni->FindClass("org/webrtc/RtpParameters$Encoding"); jfieldID encodings_id = GetFieldID(jni, parameters_class, "encodings", "Ljava/util/LinkedList;"); + jfieldID codecs_id = + GetFieldID(jni, parameters_class, "codecs", "Ljava/util/LinkedList;"); jobject j_encodings = GetObjectField(jni, j_parameters, encodings_id); + jobject j_codecs = GetObjectField(jni, j_parameters, codecs_id); webrtc::RtpParameters parameters; JavaEncodingToJsepRtpEncodingParameters(jni, j_encodings, ¶meters.encodings); + JavaCodecToJsepRtpCodecParameters(jni, j_codecs, ¶meters.codecs); return reinterpret_cast(j_rtp_sender_pointer) ->SetParameters(parameters); } @@ -2093,8 +2120,8 @@ JOW(jobject, RtpSender_nativeGetParameters) jfieldID encodings_id = GetFieldID(jni, parameters_class, "encodings", "Ljava/util/LinkedList;"); jobject j_encodings = GetObjectField(jni, j_parameters, encodings_id); - jmethodID add = GetMethodID(jni, GetObjectClass(jni, j_encodings), "add", - "(Ljava/lang/Object;)Z"); + jmethodID encodings_add = GetMethodID(jni, GetObjectClass(jni, j_encodings), + "add", "(Ljava/lang/Object;)Z"); jfieldID active_id = GetFieldID(jni, encoding_class, "active", "Z"); jfieldID bitrate_id = @@ -2116,10 +2143,42 @@ JOW(jobject, RtpSender_nativeGetParameters) jni->SetObjectField(j_encoding_parameters, bitrate_id, j_bitrate_value); CHECK_EXCEPTION(jni) << "error during SetObjectField"; } - jboolean added = - jni->CallBooleanMethod(j_encodings, add, j_encoding_parameters); + jboolean added = jni->CallBooleanMethod(j_encodings, encodings_add, + j_encoding_parameters); CHECK_EXCEPTION(jni) << "error during CallBooleanMethod"; + RTC_CHECK(added); } + + jclass codec_class = jni->FindClass("org/webrtc/RtpParameters$Codec"); + jmethodID codec_ctor = GetMethodID(jni, codec_class, "", "()V"); + 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"); + 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"); + + 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)); + 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"; + jboolean added = jni->CallBooleanMethod(j_codecs, codecs_add, j_codec); + CHECK_EXCEPTION(jni) << "error during CallBooleanMethod"; + RTC_CHECK(added); + } + return j_parameters; } diff --git a/webrtc/api/java/src/org/webrtc/RtpParameters.java b/webrtc/api/java/src/org/webrtc/RtpParameters.java index d689517c3b..4aa10fbce6 100644 --- a/webrtc/api/java/src/org/webrtc/RtpParameters.java +++ b/webrtc/api/java/src/org/webrtc/RtpParameters.java @@ -24,9 +24,18 @@ public class RtpParameters { public Integer maxBitrateBps; } + public static class Codec { + int payloadType; + String mimeType; + int clockRate; + int channels = 1; + } + public final LinkedList encodings; + public final LinkedList codecs; public RtpParameters() { encodings = new LinkedList(); + codecs = new LinkedList(); } } diff --git a/webrtc/api/objc/RTCRtpCodecParameters+Private.h b/webrtc/api/objc/RTCRtpCodecParameters+Private.h new file mode 100644 index 0000000000..aabbf7d0a1 --- /dev/null +++ b/webrtc/api/objc/RTCRtpCodecParameters+Private.h @@ -0,0 +1,30 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import + +#import "webrtc/api/objc/RTCRtpCodecParameters.h" + +#include "webrtc/api/rtpparameters.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RTCRtpCodecParameters () + +/** Returns the equivalent native RtpCodecParameters structure. */ +@property(nonatomic, readonly) webrtc::RtpCodecParameters nativeParameters; + +/** Initialize the object with a native RtpCodecParameters structure. */ +- (instancetype)initWithNativeParameters: + (const webrtc::RtpCodecParameters &)nativeParameters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/webrtc/api/objc/RTCRtpCodecParameters.h b/webrtc/api/objc/RTCRtpCodecParameters.h new file mode 100644 index 0000000000..ec0c647b58 --- /dev/null +++ b/webrtc/api/objc/RTCRtpCodecParameters.h @@ -0,0 +1,55 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern const NSString * const kRtxCodecMimeType; +extern const NSString * const kRedCodecMimeType; +extern const NSString * const kUlpfecCodecMimeType; +extern const NSString * const kOpusCodecMimeType; +extern const NSString * const kIsacCodecMimeType; +extern const NSString * const kL16CodecMimeType; +extern const NSString * const kG722CodecMimeType; +extern const NSString * const kIlbcCodecMimeType; +extern const NSString * const kPcmuCodecMimeType; +extern const NSString * const kPcmaCodecMimeType; +extern const NSString * const kDtmfCodecMimeType; +extern const NSString * const kComfortNoiseCodecMimeType; +extern const NSString * const kVp8CodecMimeType; +extern const NSString * const kVp9CodecMimeType; +extern const NSString * const kH264CodecMimeType; + +/** Defined in http://w3c.github.io/webrtc-pc/#idl-def-RTCRtpCodecParameters */ +@interface RTCRtpCodecParameters : NSObject + +/** The RTP payload type. */ +@property(nonatomic, assign) int payloadType; + +/** + * The codec MIME type. 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; + +/** The codec clock rate expressed in Hertz. */ +@property(nonatomic, assign) int clockRate; + +/** The number of channels (mono=1, stereo=2). */ +@property(nonatomic, assign) int channels; + +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/webrtc/api/objc/RTCRtpCodecParameters.mm b/webrtc/api/objc/RTCRtpCodecParameters.mm new file mode 100644 index 0000000000..8bc2204b29 --- /dev/null +++ b/webrtc/api/objc/RTCRtpCodecParameters.mm @@ -0,0 +1,63 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import "RTCRtpCodecParameters+Private.h" + +#import "webrtc/base/objc/NSString+StdString.h" +#import "webrtc/media/base/mediaconstants.h" + +const NSString * const kRtxCodecMimeType = @(cricket::kRtxCodecName); +const NSString * const kRedCodecMimeType = @(cricket::kRedCodecName); +const NSString * const kUlpfecCodecMimeType = @(cricket::kUlpfecCodecName); +const NSString * const kOpusCodecMimeType = @(cricket::kOpusCodecName); +const NSString * const kIsacCodecMimeType = @(cricket::kIsacCodecName); +const NSString * const kL16CodecMimeType = @(cricket::kL16CodecName); +const NSString * const kG722CodecMimeType = @(cricket::kG722CodecName); +const NSString * const kIlbcCodecMimeType = @(cricket::kIlbcCodecName); +const NSString * const kPcmuCodecMimeType = @(cricket::kPcmuCodecName); +const NSString * const kPcmaCodecMimeType = @(cricket::kPcmaCodecName); +const NSString * const kDtmfCodecMimeType = @(cricket::kDtmfCodecName); +const NSString * const kComfortNoiseCodecMimeType = @(cricket::kComfortNoiseCodecName); +const NSString * const kVp8CodecMimeType = @(cricket::kVp8CodecName); +const NSString * const kVp9CodecMimeType = @(cricket::kVp9CodecName); +const NSString * const kH264CodecMimeType = @(cricket::kH264CodecName); + +@implementation RTCRtpCodecParameters + +@synthesize payloadType = _payloadType; +@synthesize mimeType = _mimeType; +@synthesize clockRate = _clockRate; +@synthesize channels = _channels; + +- (instancetype)init { + return [super init]; +} + +- (instancetype)initWithNativeParameters: + (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; + } + return self; +} + +- (webrtc::RtpCodecParameters)nativeParameters { + webrtc::RtpCodecParameters parameters; + parameters.payload_type = _payloadType; + parameters.mime_type = [NSString stdStringForString:_mimeType]; + parameters.clock_rate = _clockRate; + parameters.channels = _channels; + return parameters; +} + +@end diff --git a/webrtc/api/objc/RTCRtpParameters.h b/webrtc/api/objc/RTCRtpParameters.h index 91d8108371..7b66f37dd0 100644 --- a/webrtc/api/objc/RTCRtpParameters.h +++ b/webrtc/api/objc/RTCRtpParameters.h @@ -10,6 +10,7 @@ #import +#import "webrtc/api/objc/RTCRtpCodecParameters.h" #import "webrtc/api/objc/RTCRtpEncodingParameters.h" #import "webrtc/base/objc/RTCMacros.h" @@ -21,6 +22,9 @@ RTC_EXPORT /** The currently active encodings in the order of preference. */ @property(nonatomic, copy) NSArray *encodings; +/** The negotiated set of send codecs in order of preference. */ +@property(nonatomic, copy) NSArray *codecs; + - (instancetype)init NS_DESIGNATED_INITIALIZER; @end diff --git a/webrtc/api/objc/RTCRtpParameters.mm b/webrtc/api/objc/RTCRtpParameters.mm index e8c4a44ce5..5e791066df 100644 --- a/webrtc/api/objc/RTCRtpParameters.mm +++ b/webrtc/api/objc/RTCRtpParameters.mm @@ -9,11 +9,14 @@ */ #import "RTCRtpParameters+Private.h" + +#import "RTCRtpCodecParameters+Private.h" #import "RTCRtpEncodingParameters+Private.h" @implementation RTCRtpParameters @synthesize encodings = _encodings; +@synthesize codecs = _codecs; - (instancetype)init { return [super init]; @@ -28,6 +31,13 @@ initWithNativeParameters:encoding]]; } _encodings = encodings; + + NSMutableArray *codecs = [[NSMutableArray alloc] init]; + for (const auto &codec : nativeParameters.codecs) { + [codecs addObject:[[RTCRtpCodecParameters alloc] + initWithNativeParameters:codec]]; + } + _codecs = codecs; } return self; } @@ -37,6 +47,9 @@ for (RTCRtpEncodingParameters *encoding in _encodings) { parameters.encodings.push_back(encoding.nativeParameters); } + for (RTCRtpCodecParameters *codec in _codecs) { + parameters.codecs.push_back(codec.nativeParameters); + } return parameters; } diff --git a/webrtc/api/rtpparameters.h b/webrtc/api/rtpparameters.h index 2c29d9843d..729f841ab6 100644 --- a/webrtc/api/rtpparameters.h +++ b/webrtc/api/rtpparameters.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_API_RTPPARAMETERS_H_ #define WEBRTC_API_RTPPARAMETERS_H_ +#include #include namespace webrtc { @@ -20,10 +21,32 @@ namespace webrtc { struct RtpEncodingParameters { bool active = true; int max_bitrate_bps = -1; + + bool operator==(const RtpEncodingParameters& o) const { + return active == o.active && max_bitrate_bps == o.max_bitrate_bps; + } +}; + +struct RtpCodecParameters { + int payload_type; + std::string mime_type; + int clock_rate; + int channels = 1; + // TODO(deadbeef): Add sdpFmtpLine field. + + 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; + } }; struct RtpParameters { std::vector encodings; + std::vector codecs; + + bool operator==(const RtpParameters& o) const { + return encodings == o.encodings && codecs == o.codecs; + } }; } // namespace webrtc diff --git a/webrtc/media/base/codec.cc b/webrtc/media/base/codec.cc index 9e54d2971a..01350f7123 100644 --- a/webrtc/media/base/codec.cc +++ b/webrtc/media/base/codec.cc @@ -142,6 +142,14 @@ void Codec::IntersectFeedbackParams(const Codec& other) { feedback_params.Intersect(other.feedback_params); } +webrtc::RtpCodecParameters Codec::ToCodecParameters() const { + webrtc::RtpCodecParameters codec_params; + codec_params.payload_type = id; + codec_params.mime_type = name; + codec_params.clock_rate = clockrate; + return codec_params; +} + AudioCodec::AudioCodec(int id, const std::string& name, int clockrate, @@ -182,6 +190,12 @@ 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 = channels; + return codec_params; +} + std::string AudioCodec::ToString() const { std::ostringstream os; os << "AudioCodec[" << id << ":" << name << ":" << clockrate << ":" << bitrate diff --git a/webrtc/media/base/codec.h b/webrtc/media/base/codec.h index c79a3fafc8..c16158ffb2 100644 --- a/webrtc/media/base/codec.h +++ b/webrtc/media/base/codec.h @@ -16,6 +16,7 @@ #include #include +#include "webrtc/api/rtpparameters.h" #include "webrtc/media/base/mediaconstants.h" namespace cricket { @@ -95,6 +96,8 @@ struct Codec { // and |other| are kept. void IntersectFeedbackParams(const Codec& other); + virtual webrtc::RtpCodecParameters ToCodecParameters() const; + Codec& operator=(const Codec& c); bool operator==(const Codec& c) const; @@ -124,6 +127,8 @@ struct AudioCodec : public Codec { std::string ToString() const; + webrtc::RtpCodecParameters ToCodecParameters() const override; + AudioCodec& operator=(const AudioCodec& c); bool operator==(const AudioCodec& c) const; diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc index 799596afb8..46b033e4f2 100644 --- a/webrtc/media/engine/webrtcvideoengine2.cc +++ b/webrtc/media/engine/webrtcvideoengine2.cc @@ -864,6 +864,7 @@ bool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) { send_params_ = params; return true; } + webrtc::RtpParameters WebRtcVideoChannel2::GetRtpParameters( uint32_t ssrc) const { rtc::CritScope stream_lock(&stream_crit_); @@ -874,7 +875,13 @@ webrtc::RtpParameters WebRtcVideoChannel2::GetRtpParameters( return webrtc::RtpParameters(); } - return it->second->GetRtpParameters(); + webrtc::RtpParameters rtp_params = it->second->GetRtpParameters(); + // Need to add the common list of codecs to the send stream-specific + // RTP parameters. + for (const VideoCodec& codec : send_params_.codecs) { + rtp_params.codecs.push_back(codec.ToCodecParameters()); + } + return rtp_params; } bool WebRtcVideoChannel2::SetRtpParameters( @@ -889,6 +896,8 @@ bool WebRtcVideoChannel2::SetRtpParameters( return false; } + // TODO(deadbeef): Handle setting parameters with a list of codecs in a + // different order (which should change the send codec). return it->second->SetRtpParameters(parameters); } @@ -1828,6 +1837,8 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( pending_encoder_reconfiguration_ = true; } rtp_parameters_ = new_parameters; + // Codecs are currently handled at the WebRtcVideoChannel2 level. + rtp_parameters_.codecs.clear(); // Encoding may have been activated/deactivated. UpdateSendState(); return true; diff --git a/webrtc/media/engine/webrtcvideoengine2.h b/webrtc/media/engine/webrtcvideoengine2.h index 014bd4d207..5c84a79b53 100644 --- a/webrtc/media/engine/webrtcvideoengine2.h +++ b/webrtc/media/engine/webrtcvideoengine2.h @@ -380,6 +380,7 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { // entire channel. VideoSendStreamParameters parameters_ GUARDED_BY(lock_); // Contains settings that are unique for each stream, such as max_bitrate. + // Does *not* contain codecs, however. // TODO(skvlad): Move ssrcs_ and ssrc_groups_ into rtp_parameters_. // TODO(skvlad): Combine parameters_ and rtp_parameters_ once we have only // one stream per MediaChannel. diff --git a/webrtc/media/engine/webrtcvideoengine2_unittest.cc b/webrtc/media/engine/webrtcvideoengine2_unittest.cc index 5075aa20ea..b202207f21 100644 --- a/webrtc/media/engine/webrtcvideoengine2_unittest.cc +++ b/webrtc/media/engine/webrtcvideoengine2_unittest.cc @@ -3426,6 +3426,43 @@ TEST_F(WebRtcVideoChannel2Test, SetRtpParametersEncodingsActive) { EXPECT_TRUE(stream->IsSending()); } +// Test that GetRtpParameters returns the currently configured codecs. +TEST_F(WebRtcVideoChannel2Test, GetRtpParametersCodecs) { + AddSendStream(); + cricket::VideoSendParameters parameters; + parameters.codecs.push_back(kVp8Codec); + parameters.codecs.push_back(kVp9Codec); + EXPECT_TRUE(channel_->SetSendParameters(parameters)); + + webrtc::RtpParameters rtp_parameters = channel_->GetRtpParameters(last_ssrc_); + ASSERT_EQ(2u, rtp_parameters.codecs.size()); + EXPECT_EQ(kVp8Codec.id, rtp_parameters.codecs[0].payload_type); + EXPECT_EQ(kVp8Codec.name, rtp_parameters.codecs[0].mime_type); + EXPECT_EQ(kVp8Codec.clockrate, rtp_parameters.codecs[0].clock_rate); + EXPECT_EQ(1, rtp_parameters.codecs[0].channels); + EXPECT_EQ(kVp9Codec.id, rtp_parameters.codecs[1].payload_type); + EXPECT_EQ(kVp9Codec.name, rtp_parameters.codecs[1].mime_type); + EXPECT_EQ(kVp9Codec.clockrate, rtp_parameters.codecs[1].clock_rate); + EXPECT_EQ(1, rtp_parameters.codecs[1].channels); +} + +// Test that if we set/get parameters multiple times, we get the same results. +TEST_F(WebRtcVideoChannel2Test, SetAndGetRtpParameters) { + AddSendStream(); + cricket::VideoSendParameters parameters; + parameters.codecs.push_back(kVp8Codec); + parameters.codecs.push_back(kVp9Codec); + EXPECT_TRUE(channel_->SetSendParameters(parameters)); + + webrtc::RtpParameters initial_params = channel_->GetRtpParameters(last_ssrc_); + + // We should be able to set the params we just got. + EXPECT_TRUE(channel_->SetRtpParameters(last_ssrc_, initial_params)); + + // ... And this shouldn't change the params returned by GetRtpParameters. + EXPECT_EQ(initial_params, channel_->GetRtpParameters(last_ssrc_)); +} + void WebRtcVideoChannel2Test::TestReceiverLocalSsrcConfiguration( bool receiver_first) { EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index c6cda5ed85..8561aa2dc4 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -1411,7 +1411,13 @@ webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpParameters( return webrtc::RtpParameters(); } - return it->second->rtp_parameters(); + webrtc::RtpParameters rtp_params = it->second->rtp_parameters(); + // Need to add the common list of codecs to the send stream-specific + // RTP parameters. + for (const AudioCodec& codec : send_codecs_) { + rtp_params.codecs.push_back(codec.ToCodecParameters()); + } + return rtp_params; } bool WebRtcVoiceMediaChannel::SetRtpParameters( @@ -1432,7 +1438,10 @@ bool WebRtcVoiceMediaChannel::SetRtpParameters( LOG(LS_WARNING) << "Failed to set RtpParameters."; return false; } - it->second->set_rtp_parameters(parameters); + // Codecs are handled at the WebRtcVoiceMediaChannel level. + webrtc::RtpParameters reduced_params = parameters; + reduced_params.codecs.clear(); + it->second->set_rtp_parameters(reduced_params); return true; } @@ -1663,6 +1672,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( } } + send_codecs_ = codecs; return true; } @@ -2390,6 +2400,8 @@ bool WebRtcVoiceMediaChannel::SetChannelParameters( int channel, const webrtc::RtpParameters& parameters) { RTC_CHECK_EQ(1UL, parameters.encodings.size()); + // TODO(deadbeef): Handle setting parameters with a list of codecs in a + // different order (which should change the send codec). return SetSendBitrate( channel, MinPositive(send_bitrate_bps_, parameters.encodings[0].max_bitrate_bps)); diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h index c59fcaa05a..4c53ad0222 100644 --- a/webrtc/media/engine/webrtcvoiceengine.h +++ b/webrtc/media/engine/webrtcvoiceengine.h @@ -240,6 +240,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, rtc::ThreadChecker worker_thread_checker_; WebRtcVoiceEngine* const engine_ = nullptr; + std::vector send_codecs_; std::vector recv_codecs_; int send_bitrate_bps_ = 0; AudioOptions options_; diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc index 60aa869a4b..d3437265a1 100644 --- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc +++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc @@ -918,6 +918,44 @@ TEST_F(WebRtcVoiceEngineTestFake, RtpParametersArePerStream) { EXPECT_EQ(64000, GetCodecBitrate(kSsrcs4[2])); } +// Test that GetRtpParameters returns the currently configured codecs. +TEST_F(WebRtcVoiceEngineTestFake, GetRtpParametersCodecs) { + EXPECT_TRUE(SetupSendStream()); + cricket::AudioSendParameters parameters; + parameters.codecs.push_back(kIsacCodec); + parameters.codecs.push_back(kPcmuCodec); + EXPECT_TRUE(channel_->SetSendParameters(parameters)); + + webrtc::RtpParameters rtp_parameters = channel_->GetRtpParameters(kSsrc1); + ASSERT_EQ(2u, rtp_parameters.codecs.size()); + EXPECT_EQ(kIsacCodec.id, rtp_parameters.codecs[0].payload_type); + EXPECT_EQ(kIsacCodec.name, rtp_parameters.codecs[0].mime_type); + EXPECT_EQ(kIsacCodec.clockrate, rtp_parameters.codecs[0].clock_rate); + EXPECT_EQ(kIsacCodec.channels, rtp_parameters.codecs[0].channels); + EXPECT_EQ(kPcmuCodec.id, rtp_parameters.codecs[1].payload_type); + EXPECT_EQ(kPcmuCodec.name, rtp_parameters.codecs[1].mime_type); + EXPECT_EQ(kPcmuCodec.clockrate, rtp_parameters.codecs[1].clock_rate); + EXPECT_EQ(kPcmuCodec.channels, rtp_parameters.codecs[1].channels); +} + +// Test that if we set/get parameters multiple times, we get the same results. +TEST_F(WebRtcVoiceEngineTestFake, SetAndGetRtpParameters) { + EXPECT_TRUE(SetupSendStream()); + cricket::AudioSendParameters parameters; + parameters.codecs.push_back(kIsacCodec); + parameters.codecs.push_back(kPcmuCodec); + EXPECT_TRUE(channel_->SetSendParameters(parameters)); + + webrtc::RtpParameters initial_params = channel_->GetRtpParameters(kSsrc1); + + // We should be able to set the params we just got. + EXPECT_TRUE(channel_->SetRtpParameters(kSsrc1, initial_params)); + + // ... And this shouldn't change the params returned by GetRtpParameters. + webrtc::RtpParameters new_params = channel_->GetRtpParameters(kSsrc1); + EXPECT_EQ(initial_params, channel_->GetRtpParameters(kSsrc1)); +} + // Test that we apply codecs properly. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecs) { EXPECT_TRUE(SetupSendStream());