Skip to content

Commit

Permalink
feat: Expose setCodecPreferences/getCapabilities for android. (#61)
Browse files Browse the repository at this point in the history
* feat: Expose setCodecPreferences/getCapabilities.

* chore: update license.

* fix bugs.
  • Loading branch information
cloudwebrtc committed Jun 6, 2023
1 parent 6a70604 commit 4c181eb
Show file tree
Hide file tree
Showing 8 changed files with 338 additions and 0 deletions.
4 changes: 4 additions & 0 deletions sdk/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ if (is_android) {
"api/org/webrtc/RTCStatsCollectorCallback.java",
"api/org/webrtc/RTCStatsReport.java",
"api/org/webrtc/RtcCertificatePem.java",
"api/org/webrtc/RtpCapabilities.java",
"api/org/webrtc/RtpParameters.java",
"api/org/webrtc/RtpReceiver.java",
"api/org/webrtc/RtpSender.java",
Expand Down Expand Up @@ -736,6 +737,8 @@ if (current_os == "linux" || is_android) {
"src/jni/pc/rtc_certificate.h",
"src/jni/pc/rtc_stats_collector_callback_wrapper.cc",
"src/jni/pc/rtc_stats_collector_callback_wrapper.h",
"src/jni/pc/rtp_capabilities.cc",
"src/jni/pc/rtp_capabilities.h",
"src/jni/pc/rtp_parameters.cc",
"src/jni/pc/rtp_parameters.h",
"src/jni/pc/rtp_receiver.cc",
Expand Down Expand Up @@ -1409,6 +1412,7 @@ if (current_os == "linux" || is_android) {
"api/org/webrtc/RTCStatsCollectorCallback.java",
"api/org/webrtc/RTCStatsReport.java",
"api/org/webrtc/RtcCertificatePem.java",
"api/org/webrtc/RtpCapabilities.java",
"api/org/webrtc/RtpParameters.java",
"api/org/webrtc/RtpReceiver.java",
"api/org/webrtc/RtpSender.java",
Expand Down
13 changes: 13 additions & 0 deletions sdk/android/api/org/webrtc/PeerConnectionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.webrtc.PeerConnection;
import org.webrtc.audio.AudioDeviceModule;
import org.webrtc.audio.JavaAudioDeviceModule;
import org.webrtc.RtpCapabilities;

/**
* Java wrapper for a C++ PeerConnectionFactoryInterface. Main entry point to
Expand Down Expand Up @@ -471,6 +472,16 @@ public AudioTrack createAudioTrack(String id, AudioSource source) {
return new AudioTrack(nativeCreateAudioTrack(nativeFactory, id, source.getNativeAudioSource()));
}

public RtpCapabilities getRtpReceiverCapabilities(MediaStreamTrack.MediaType mediaType) {
checkPeerConnectionFactoryExists();
return nativeGetRtpReceiverCapabilities(nativeFactory, mediaType);
}

public RtpCapabilities getRtpSenderCapabilities(MediaStreamTrack.MediaType mediaType) {
checkPeerConnectionFactoryExists();
return nativeGetRtpSenderCapabilities(nativeFactory, mediaType);
}

// Starts recording an AEC dump. Ownership of the file is transfered to the
// native code. If an AEC dump is already in progress, it will be stopped and
// a new one will start using the provided file.
Expand Down Expand Up @@ -615,4 +626,6 @@ private static native boolean nativeStartAecDump(
private static native void nativeInjectLoggable(JNILogging jniLogging, int severity);
private static native void nativeDeleteLoggable();
private static native void nativePrintStackTrace(int tid);
private static native RtpCapabilities nativeGetRtpSenderCapabilities(long factory, MediaStreamTrack.MediaType mediaType);
private static native RtpCapabilities nativeGetRtpReceiverCapabilities(long factory, MediaStreamTrack.MediaType mediaType);
}
131 changes: 131 additions & 0 deletions sdk/android/api/org/webrtc/RtpCapabilities.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright 2023 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.webrtc;

import androidx.annotation.Nullable;
import java.util.List;
import java.util.Map;
import org.webrtc.MediaStreamTrack;

public class RtpCapabilities {
public static class CodecCapability {
public int preferredPayloadType;
// 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.
public 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;
// The "format specific parameters" field from the "a=fmtp" line in the SDP
public Map<String, String> parameters;
// The MIME type of the codec. This is a convenience field.
public String mimeType;

public CodecCapability() {}

@CalledByNative("CodecCapability")
CodecCapability(int preferredPayloadType, String name, MediaStreamTrack.MediaType kind,
Integer clockRate, Integer numChannels, String mimeType, Map<String, String> parameters) {
this.preferredPayloadType = preferredPayloadType;
this.name = name;
this.kind = kind;
this.clockRate = clockRate;
this.numChannels = numChannels;
this.parameters = parameters;
this.mimeType = mimeType;
}

@CalledByNative("CodecCapability")
int getPreferredPayloadType() {
return preferredPayloadType;
}

@CalledByNative("CodecCapability")
String getName() {
return name;
}

@CalledByNative("CodecCapability")
MediaStreamTrack.MediaType getKind() {
return kind;
}

@CalledByNative("CodecCapability")
Integer getClockRate() {
return clockRate;
}

@CalledByNative("CodecCapability")
Integer getNumChannels() {
return numChannels;
}

@CalledByNative("CodecCapability")
Map getParameters() {
return parameters;
}
}

public static class HeaderExtensionCapability {
private final String uri;
private final int preferredId;
private final boolean preferredEncrypted;

@CalledByNative("HeaderExtensionCapability")
HeaderExtensionCapability(String uri, int preferredId, boolean preferredEncrypted) {
this.uri = uri;
this.preferredId = preferredId;
this.preferredEncrypted = preferredEncrypted;
}

@CalledByNative("HeaderExtensionCapability")
public String getUri() {
return uri;
}

@CalledByNative("HeaderExtensionCapability")
public int getPreferredId() {
return preferredId;
}

@CalledByNative("HeaderExtensionCapability")
public boolean getPreferredEncrypted() {
return preferredEncrypted;
}
}

public List<CodecCapability> codecs;
public List<HeaderExtensionCapability> headerExtensions;

@CalledByNative
RtpCapabilities(List<CodecCapability> codecs, List<HeaderExtensionCapability> headerExtensions) {
this.headerExtensions = headerExtensions;
this.codecs = codecs;
}

@CalledByNative
public List<HeaderExtensionCapability> getHeaderExtensions() {
return headerExtensions;
}

@CalledByNative
List<CodecCapability> getCodecs() {
return codecs;
}
}
6 changes: 6 additions & 0 deletions sdk/android/api/org/webrtc/RtpTransceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ public void stop() {
nativeStopInternal(nativeRtpTransceiver);
}

public void setCodecPreferences(List<RtpCapabilities.CodecCapability> codecs) {
checkRtpTransceiverExists();
nativeSetCodecPreferences(nativeRtpTransceiver, codecs);
}

/**
* The StopInternal method stops the RtpTransceiver, like Stop, but goes
* immediately to Stopped state.
Expand Down Expand Up @@ -263,4 +268,5 @@ private void checkRtpTransceiverExists() {
private static native void nativeStopStandard(long rtpTransceiver);
private static native boolean nativeSetDirection(
long rtpTransceiver, RtpTransceiverDirection rtpTransceiverDirection);
private static native void nativeSetCodecPreferences(long rtpTransceiver, List<RtpCapabilities.CodecCapability> codecs);
}
18 changes: 18 additions & 0 deletions sdk/android/src/jni/pc/peer_connection_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
#include "sdk/android/src/jni/logging/log_sink.h"
#include "sdk/android/src/jni/pc/android_network_monitor.h"
#include "sdk/android/src/jni/pc/audio.h"
#include "sdk/android/src/jni/pc/rtp_capabilities.h"
#include "sdk/android/src/jni/pc/ice_candidate.h"
#include "sdk/android/src/jni/pc/media_stream_track.h"
#include "sdk/android/src/jni/pc/owned_factory_and_threads.h"
#include "sdk/android/src/jni/pc/peer_connection.h"
#include "sdk/android/src/jni/pc/ssl_certificate_verifier_wrapper.h"
Expand Down Expand Up @@ -393,6 +395,22 @@ jlong JNI_PeerConnectionFactory_CreateAudioTrack(
return jlongFromPointer(track.release());
}

ScopedJavaLocalRef<jobject> JNI_PeerConnectionFactory_GetRtpSenderCapabilities(
JNIEnv* jni,
jlong native_factory,
const JavaParamRef<jobject>& media_type) {
auto factory = PeerConnectionFactoryFromJava(native_factory);
return NativeToJavaRtpCapabilities(jni, factory->GetRtpSenderCapabilities(JavaToNativeMediaType(jni, media_type)));
}

ScopedJavaLocalRef<jobject> JNI_PeerConnectionFactory_GetRtpReceiverCapabilities(
JNIEnv* jni,
jlong native_factory,
const JavaParamRef<jobject>& media_type) {
auto factory = PeerConnectionFactoryFromJava(native_factory);
return NativeToJavaRtpCapabilities(jni, factory->GetRtpReceiverCapabilities(JavaToNativeMediaType(jni, media_type)));
}

static jboolean JNI_PeerConnectionFactory_StartAecDump(
JNIEnv* jni,
jlong native_factory,
Expand Down
114 changes: 114 additions & 0 deletions sdk/android/src/jni/pc/rtp_capabilities.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright 2023 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "sdk/android/src/jni/pc/rtp_capabilities.h"

#include "sdk/android/generated_peerconnection_jni/RtpCapabilities_jni.h"
#include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/pc/media_stream_track.h"

namespace webrtc {
namespace jni {

namespace {

ScopedJavaLocalRef<jobject> NativeToJavaRtpCodecParameter(
JNIEnv* env,
const RtpCodecCapability& codec) {
return Java_CodecCapability_Constructor(env, codec.preferred_payload_type.value(),
NativeToJavaString(env, codec.name),
NativeToJavaMediaType(env, codec.kind),
NativeToJavaInteger(env, codec.clock_rate),
NativeToJavaInteger(env, codec.num_channels),
NativeToJavaString(env, codec.mime_type()),
NativeToJavaStringMap(env, codec.parameters));
}

ScopedJavaLocalRef<jobject> NativeToJavaRtpHeaderExtensionParameter(
JNIEnv* env,
const RtpHeaderExtensionCapability& extension) {
return Java_HeaderExtensionCapability_Constructor(
env, NativeToJavaString(env, extension.uri), extension.preferred_id.value(),
extension.preferred_encrypt);
}
} // namespace

RtpCapabilities JavaToNativeRtpCapabilities(JNIEnv* jni,
const JavaRef<jobject>& j_capabilities) {
RtpCapabilities capabilities;

ScopedJavaLocalRef<jobject> j_header_extensions =
Java_RtpCapabilities_getHeaderExtensions(jni, j_capabilities);
for (const JavaRef<jobject>& j_header_extension :
Iterable(jni, j_header_extensions)) {
RtpHeaderExtensionCapability header_extension;
header_extension.uri = JavaToStdString(
jni, Java_HeaderExtensionCapability_getUri(jni, j_header_extension));
header_extension.preferred_id = Java_HeaderExtensionCapability_getPreferredId(jni, j_header_extension);
header_extension.preferred_encrypt =
Java_HeaderExtensionCapability_getPreferredEncrypted(jni, j_header_extension);
capabilities.header_extensions.push_back(header_extension);
}

// Convert codecs.
ScopedJavaLocalRef<jobject> j_codecs =
Java_RtpCapabilities_getCodecs(jni, j_capabilities);
for (const JavaRef<jobject>& j_codec : Iterable(jni, j_codecs)) {
RtpCodecCapability codec;
codec.preferred_payload_type = Java_CodecCapability_getPreferredPayloadType(jni, j_codec);
codec.name = JavaToStdString(jni, Java_CodecCapability_getName(jni, j_codec));
codec.kind = JavaToNativeMediaType(jni, Java_CodecCapability_getKind(jni, j_codec));
codec.clock_rate =
JavaToNativeOptionalInt(jni, Java_CodecCapability_getClockRate(jni, j_codec));
codec.num_channels =
JavaToNativeOptionalInt(jni, Java_CodecCapability_getNumChannels(jni, j_codec));
auto parameters_map =
JavaToNativeStringMap(jni, Java_CodecCapability_getParameters(jni, j_codec));
codec.parameters.insert(parameters_map.begin(), parameters_map.end());
capabilities.codecs.push_back(codec);
}
return capabilities;
}

ScopedJavaLocalRef<jobject> NativeToJavaRtpCapabilities(
JNIEnv* env,
const RtpCapabilities& capabilities) {
return Java_RtpCapabilities_Constructor(
env, NativeToJavaList(env, capabilities.codecs, &NativeToJavaRtpCodecParameter),
NativeToJavaList(env, capabilities.header_extensions,
&NativeToJavaRtpHeaderExtensionParameter)
);
}

RtpCodecCapability JavaToNativeRtpCodecCapability(JNIEnv* jni,
const JavaRef<jobject>& j_codec) {
RtpCodecCapability codec;
codec.preferred_payload_type = Java_CodecCapability_getPreferredPayloadType(jni, j_codec);
codec.name = JavaToStdString(jni, Java_CodecCapability_getName(jni, j_codec));
codec.kind = JavaToNativeMediaType(jni, Java_CodecCapability_getKind(jni, j_codec));
codec.clock_rate =
JavaToNativeOptionalInt(jni, Java_CodecCapability_getClockRate(jni, j_codec));
codec.num_channels =
JavaToNativeOptionalInt(jni, Java_CodecCapability_getNumChannels(jni, j_codec));
auto parameters_map =
JavaToNativeStringMap(jni, Java_CodecCapability_getParameters(jni, j_codec));
codec.parameters.insert(parameters_map.begin(), parameters_map.end());
return codec;
}

} // namespace jni
} // namespace webrtc
41 changes: 41 additions & 0 deletions sdk/android/src/jni/pc/rtp_capabilities.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2023 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef SDK_ANDROID_SRC_JNI_PC_RTP_CAPABLILITES_H_
#define SDK_ANDROID_SRC_JNI_PC_RTP_CAPABLILITES_H_

#include <jni.h>

#include "api/rtp_parameters.h"
#include "sdk/android/native_api/jni/scoped_java_ref.h"

namespace webrtc {
namespace jni {

RtpCapabilities JavaToNativeRtpCapabilities(JNIEnv* jni,
const JavaRef<jobject>& j_capabilities);

ScopedJavaLocalRef<jobject> NativeToJavaRtpCapabilities(
JNIEnv* jni,
const RtpCapabilities& capabilities);

RtpCodecCapability JavaToNativeRtpCodecCapability(JNIEnv* jni,
const JavaRef<jobject>& j_codec_capability);

} // namespace jni
} // namespace webrtc

#endif // SDK_ANDROID_SRC_JNI_PC_RTP_CAPABLILITES_H_
Loading

0 comments on commit 4c181eb

Please sign in to comment.