Implement RtpCodecParameters::parameters

This will return all the fmtp parameters for the codecs, except for
DTMF codes that don't fit the key=value pattern.

Bug: webrtc:7112
Change-Id: I06a203ff64df2c3bc9bc2082cd0f374718b23510
Reviewed-on: https://webrtc-review.googlesource.com/71801
Commit-Queue: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23250}
This commit is contained in:
Florent Castelli
2018-05-15 18:14:14 +02:00
committed by Commit Bot
parent d2882187b1
commit b7d9d8346f
9 changed files with 56 additions and 13 deletions

View File

@ -498,8 +498,6 @@ struct RtpCodecParameters {
// Contrary to ORTC, these parameters are named using all lowercase strings. // Contrary to ORTC, these parameters are named using all lowercase strings.
// This helps make the mapping to SDP simpler, if an application is using // This helps make the mapping to SDP simpler, if an application is using
// SDP. Boolean values are represented by the string "1". // SDP. Boolean values are represented by the string "1".
//
// TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
std::unordered_map<std::string, std::string> parameters; std::unordered_map<std::string, std::string> parameters;
bool operator==(const RtpCodecParameters& o) const { bool operator==(const RtpCodecParameters& o) const {

View File

@ -143,6 +143,7 @@ webrtc::RtpCodecParameters Codec::ToCodecParameters() const {
codec_params.payload_type = id; codec_params.payload_type = id;
codec_params.name = name; codec_params.name = name;
codec_params.clock_rate = clockrate; codec_params.clock_rate = clockrate;
codec_params.parameters.insert(params.begin(), params.end());
return codec_params; return codec_params;
} }

View File

@ -347,19 +347,27 @@ TEST(CodecTest, TestValidateCodecFormat) {
} }
TEST(CodecTest, TestToCodecParameters) { TEST(CodecTest, TestToCodecParameters) {
const VideoCodec v(96, "V"); VideoCodec v(96, "V");
v.SetParam("p1", "v1");
webrtc::RtpCodecParameters codec_params_1 = v.ToCodecParameters(); webrtc::RtpCodecParameters codec_params_1 = v.ToCodecParameters();
EXPECT_EQ(96, codec_params_1.payload_type); EXPECT_EQ(96, codec_params_1.payload_type);
EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec_params_1.kind); EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec_params_1.kind);
EXPECT_EQ("V", codec_params_1.name); EXPECT_EQ("V", codec_params_1.name);
EXPECT_EQ(cricket::kVideoCodecClockrate, codec_params_1.clock_rate); EXPECT_EQ(cricket::kVideoCodecClockrate, codec_params_1.clock_rate);
EXPECT_EQ(rtc::nullopt, codec_params_1.num_channels); EXPECT_EQ(rtc::nullopt, codec_params_1.num_channels);
ASSERT_EQ(1, codec_params_1.parameters.size());
EXPECT_EQ("p1", codec_params_1.parameters.begin()->first);
EXPECT_EQ("v1", codec_params_1.parameters.begin()->second);
const AudioCodec a(97, "A", 44100, 20000, 2); AudioCodec a(97, "A", 44100, 20000, 2);
a.SetParam("p1", "a1");
webrtc::RtpCodecParameters codec_params_2 = a.ToCodecParameters(); webrtc::RtpCodecParameters codec_params_2 = a.ToCodecParameters();
EXPECT_EQ(97, codec_params_2.payload_type); EXPECT_EQ(97, codec_params_2.payload_type);
EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec_params_2.kind); EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec_params_2.kind);
EXPECT_EQ("A", codec_params_2.name); EXPECT_EQ("A", codec_params_2.name);
EXPECT_EQ(44100, codec_params_2.clock_rate); EXPECT_EQ(44100, codec_params_2.clock_rate);
EXPECT_EQ(2, codec_params_2.num_channels); EXPECT_EQ(2, codec_params_2.num_channels);
ASSERT_EQ(1, codec_params_2.parameters.size());
EXPECT_EQ("p1", codec_params_2.parameters.begin()->first);
EXPECT_EQ("a1", codec_params_2.parameters.begin()->second);
} }

View File

@ -11,8 +11,9 @@
package org.webrtc; package org.webrtc;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.webrtc.MediaStreamTrack; import org.webrtc.MediaStreamTrack;
/** /**
@ -72,15 +73,18 @@ public class RtpParameters {
public Integer clockRate; public Integer clockRate;
// The number of audio channels used. Set to null for video codecs. // The number of audio channels used. Set to null for video codecs.
public Integer numChannels; public Integer numChannels;
// The "format specific parameters" field from the "a=fmtp" line in the SDP
public Map<String, String> parameters;
@CalledByNative("Codec") @CalledByNative("Codec")
Codec(int payloadType, String name, MediaStreamTrack.MediaType kind, Integer clockRate, Codec(int payloadType, String name, MediaStreamTrack.MediaType kind, Integer clockRate,
Integer numChannels) { Integer numChannels, Map<String, String> parameters) {
this.payloadType = payloadType; this.payloadType = payloadType;
this.name = name; this.name = name;
this.kind = kind; this.kind = kind;
this.clockRate = clockRate; this.clockRate = clockRate;
this.numChannels = numChannels; this.numChannels = numChannels;
this.parameters = parameters;
} }
@CalledByNative("Codec") @CalledByNative("Codec")
@ -107,6 +111,11 @@ public class RtpParameters {
Integer getNumChannels() { Integer getNumChannels() {
return numChannels; return numChannels;
} }
@CalledByNative("Codec")
Map getParameters() {
return parameters;
}
} }
public final String transactionId; public final String transactionId;

View File

@ -285,6 +285,18 @@ ScopedJavaLocalRef<jobject> NativeToJavaMap(JNIEnv* env,
return builder.GetJavaMap(); return builder.GetJavaMap();
} }
template <typename C>
ScopedJavaLocalRef<jobject> NativeToJavaStringMap(JNIEnv* env,
const C& container) {
JavaMapBuilder builder(env);
for (const auto& e : container) {
const auto key_value_pair = std::make_pair(
NativeToJavaString(env, e.first), NativeToJavaString(env, e.second));
builder.put(key_value_pair.first, key_value_pair.second);
}
return builder.GetJavaMap();
}
// Return a |jlong| that will correctly convert back to |ptr|. This is needed // Return a |jlong| that will correctly convert back to |ptr|. This is needed
// because the alternative (of silently passing a 32-bit pointer to a vararg // because the alternative (of silently passing a 32-bit pointer to a vararg
// function expecting a 64-bit param) picks up garbage in the high 32 bits. // function expecting a 64-bit param) picks up garbage in the high 32 bits.

View File

@ -35,7 +35,8 @@ ScopedJavaLocalRef<jobject> NativeToJavaRtpCodecParameter(
NativeToJavaString(env, codec.name), NativeToJavaString(env, codec.name),
NativeToJavaMediaType(env, codec.kind), NativeToJavaMediaType(env, codec.kind),
NativeToJavaInteger(env, codec.clock_rate), NativeToJavaInteger(env, codec.clock_rate),
NativeToJavaInteger(env, codec.num_channels)); NativeToJavaInteger(env, codec.num_channels),
NativeToJavaStringMap(env, codec.parameters));
} }
} // namespace } // namespace
@ -85,6 +86,9 @@ RtpParameters JavaToNativeRtpParameters(JNIEnv* jni,
JavaToNativeOptionalInt(jni, Java_Codec_getClockRate(jni, j_codec)); JavaToNativeOptionalInt(jni, Java_Codec_getClockRate(jni, j_codec));
codec.num_channels = codec.num_channels =
JavaToNativeOptionalInt(jni, Java_Codec_getNumChannels(jni, j_codec)); JavaToNativeOptionalInt(jni, Java_Codec_getNumChannels(jni, j_codec));
auto parameters_map =
JavaToNativeStringMap(jni, Java_Codec_getParameters(jni, j_codec));
codec.parameters.insert(parameters_map.begin(), parameters_map.end());
parameters.codecs.push_back(codec); parameters.codecs.push_back(codec);
} }
return parameters; return parameters;

View File

@ -27,12 +27,8 @@ SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni,
ScopedJavaLocalRef<jobject> SdpVideoFormatToVideoCodecInfo( ScopedJavaLocalRef<jobject> SdpVideoFormatToVideoCodecInfo(
JNIEnv* jni, JNIEnv* jni,
const SdpVideoFormat& format) { const SdpVideoFormat& format) {
ScopedJavaLocalRef<jobject> j_params = NativeToJavaMap( ScopedJavaLocalRef<jobject> j_params =
jni, format.parameters, NativeToJavaStringMap(jni, format.parameters);
[](JNIEnv* env, const std::pair<std::string, std::string>& entry) {
return std::make_pair(NativeToJavaString(env, entry.first),
NativeToJavaString(env, entry.second));
});
return Java_VideoCodecInfo_Constructor( return Java_VideoCodecInfo_Constructor(
jni, NativeToJavaString(jni, format.name), j_params); jni, NativeToJavaString(jni, format.name), j_params);
} }

View File

@ -41,6 +41,7 @@ const NSString * const kRTCH264CodecName = @(cricket::kH264CodecName);
@synthesize kind = _kind; @synthesize kind = _kind;
@synthesize clockRate = _clockRate; @synthesize clockRate = _clockRate;
@synthesize numChannels = _numChannels; @synthesize numChannels = _numChannels;
@synthesize parameters = _parameters;
- (instancetype)init { - (instancetype)init {
return [super init]; return [super init];
@ -68,6 +69,12 @@ const NSString * const kRTCH264CodecName = @(cricket::kH264CodecName);
if (nativeParameters.num_channels) { if (nativeParameters.num_channels) {
_numChannels = [NSNumber numberWithInt:*nativeParameters.num_channels]; _numChannels = [NSNumber numberWithInt:*nativeParameters.num_channels];
} }
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
for (const auto &parameter : nativeParameters.parameters) {
[parameters setObject:[NSString stringForStdString:parameter.second]
forKey:[NSString stringForStdString:parameter.first]];
}
_parameters = parameters;
} }
return self; return self;
} }
@ -91,6 +98,11 @@ const NSString * const kRTCH264CodecName = @(cricket::kH264CodecName);
if (_numChannels != nil) { if (_numChannels != nil) {
parameters.num_channels = rtc::Optional<int>(_numChannels.intValue); parameters.num_channels = rtc::Optional<int>(_numChannels.intValue);
} }
for (NSString *paramKey in _parameters.allKeys) {
std::string key = [NSString stdStringForString:paramKey];
std::string value = [NSString stdStringForString:_parameters[paramKey]];
parameters.parameters[key] = value;
}
return parameters; return parameters;
} }

View File

@ -63,6 +63,9 @@ RTC_EXPORT
**/ **/
@property(nonatomic, readonly, nullable) NSNumber *numChannels; @property(nonatomic, readonly, nullable) NSNumber *numChannels;
/** The "format specific parameters" field from the "a=fmtp" line in the SDP */
@property(nonatomic, readonly, nonnull) NSDictionary *parameters;
- (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_DESIGNATED_INITIALIZER;
@end @end