Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Expose setCodecPreferences/getCapabilities for android. #61

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -754,6 +755,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 @@ -1423,6 +1426,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 @@ -413,6 +415,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