Expose setCodecPreferences/getCapabilities for android
Bug: webrtc:15177 Change-Id: If61ef9a87bc4f68d73cef6e681461682ca48f034 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/304880 Reviewed-by: Sergey Silkin <ssilkin@webrtc.org> Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Cr-Commit-Position: refs/heads/main@{#40071}
This commit is contained in:
parent
54519aa378
commit
784c339f34
1
AUTHORS
1
AUTHORS
@ -154,6 +154,7 @@ HyperConnect Inc. <*@hpcnt.com>
|
||||
Intel Corporation <*@intel.com>
|
||||
LG Electronics, Inc. <*@lge.com>
|
||||
Life On Air Inc. <*@lifeonair.com>
|
||||
LiveKit <*@livekit.io>
|
||||
Meta Platforms, Inc. <*@meta.com>
|
||||
Microsoft Corporation <*@microsoft.com>
|
||||
MIPS Technologies <*@mips.com>
|
||||
|
||||
@ -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",
|
||||
@ -734,6 +735,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",
|
||||
@ -1391,6 +1394,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",
|
||||
@ -1486,6 +1490,7 @@ if (is_android) {
|
||||
"instrumentationtests/src/org/webrtc/PeerConnectionTest.java",
|
||||
"instrumentationtests/src/org/webrtc/RendererCommonTest.java",
|
||||
"instrumentationtests/src/org/webrtc/RtcCertificatePemTest.java",
|
||||
"instrumentationtests/src/org/webrtc/RtpCapabilitiesTest.java",
|
||||
"instrumentationtests/src/org/webrtc/RtpSenderTest.java",
|
||||
"instrumentationtests/src/org/webrtc/RtpTransceiverTest.java",
|
||||
"instrumentationtests/src/org/webrtc/SoftwareVideoDecoderFactoryTest.java",
|
||||
|
||||
@ -15,7 +15,9 @@ import android.os.Process;
|
||||
import androidx.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import org.webrtc.Logging.Severity;
|
||||
import org.webrtc.MediaStreamTrack;
|
||||
import org.webrtc.PeerConnection;
|
||||
import org.webrtc.RtpCapabilities;
|
||||
import org.webrtc.audio.AudioDeviceModule;
|
||||
import org.webrtc.audio.JavaAudioDeviceModule;
|
||||
|
||||
@ -471,6 +473,16 @@ public class PeerConnectionFactory {
|
||||
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.
|
||||
@ -615,4 +627,8 @@ public class PeerConnectionFactory {
|
||||
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);
|
||||
}
|
||||
|
||||
125
sdk/android/api/org/webrtc/RtpCapabilities.java
Normal file
125
sdk/android/api/org/webrtc/RtpCapabilities.java
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -215,6 +215,11 @@ public class RtpTransceiver {
|
||||
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.
|
||||
@ -263,4 +268,6 @@ public class RtpTransceiver {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -582,7 +582,7 @@ public class PeerConnectionEndToEndTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static class SdpObserverLatch implements SdpObserver {
|
||||
static class SdpObserverLatch implements SdpObserver {
|
||||
private boolean success;
|
||||
private @Nullable SessionDescription sdp;
|
||||
private @Nullable String error;
|
||||
|
||||
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.webrtc.PeerConnectionEndToEndTest.SdpObserverLatch;
|
||||
import org.webrtc.RtpParameters.Encoding;
|
||||
import org.webrtc.RtpTransceiver.RtpTransceiverInit;
|
||||
|
||||
/**
|
||||
* Unit-tests for {@link RtpCapabilities}.
|
||||
*/
|
||||
public class RtpCapabilitiesTest {
|
||||
private PeerConnectionFactory factory;
|
||||
private PeerConnection pc;
|
||||
|
||||
static class CustomHardwareVideoEncoderFactory implements VideoEncoderFactory {
|
||||
private final List<VideoCodecInfo> supportedCodecs;
|
||||
|
||||
public CustomHardwareVideoEncoderFactory(List<VideoCodecInfo> supportedCodecs) {
|
||||
this.supportedCodecs = supportedCodecs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable VideoEncoder createEncoder(VideoCodecInfo info) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoCodecInfo[] getSupportedCodecs() {
|
||||
return supportedCodecs.toArray(new VideoCodecInfo[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static class CustomHardwareVideoDecoderFactory implements VideoDecoderFactory {
|
||||
private final List<VideoCodecInfo> supportedCodecs;
|
||||
|
||||
public CustomHardwareVideoDecoderFactory(List<VideoCodecInfo> supportedCodecs) {
|
||||
this.supportedCodecs = supportedCodecs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VideoDecoder createDecoder(VideoCodecInfo videoCodecInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoCodecInfo[] getSupportedCodecs() {
|
||||
return supportedCodecs.toArray(new VideoCodecInfo[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions
|
||||
.builder(InstrumentationRegistry.getTargetContext())
|
||||
.setNativeLibraryName(TestConstants.NATIVE_LIBRARY)
|
||||
.createInitializationOptions());
|
||||
|
||||
VideoCodecInfo vp8Codec = new VideoCodecInfo("VP8", new HashMap<>());
|
||||
VideoCodecInfo h264Codec = new VideoCodecInfo("H264", new HashMap<>());
|
||||
List<VideoCodecInfo> supportedCodecs = new ArrayList<>();
|
||||
supportedCodecs.add(vp8Codec);
|
||||
supportedCodecs.add(h264Codec);
|
||||
|
||||
factory = PeerConnectionFactory.builder()
|
||||
.setVideoEncoderFactory(new CustomHardwareVideoEncoderFactory(supportedCodecs))
|
||||
.setVideoDecoderFactory(new CustomHardwareVideoDecoderFactory(supportedCodecs))
|
||||
.createPeerConnectionFactory();
|
||||
|
||||
PeerConnection.RTCConfiguration config =
|
||||
new PeerConnection.RTCConfiguration(Collections.emptyList());
|
||||
// RtpTranceiver is part of new unified plan semantics.
|
||||
config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
|
||||
pc = factory.createPeerConnection(config, mock(PeerConnection.Observer.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getRtpSenderCapabilities returns the codecs supported by the video encoder factory.
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
public void testGetSenderCapabilities() {
|
||||
RtpCapabilities capabilities =
|
||||
factory.getRtpSenderCapabilities(MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO);
|
||||
List<String> codecNames = new ArrayList<>();
|
||||
for (RtpCapabilities.CodecCapability codec : capabilities.getCodecs()) {
|
||||
codecNames.add(codec.name);
|
||||
}
|
||||
|
||||
assertTrue(codecNames.containsAll(Arrays.asList("VP8", "H264")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getRtpReceiverCapabilities returns the codecs supported by the video decoder factory.
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
public void testGetReceiverCapabilities() {
|
||||
RtpCapabilities capabilities =
|
||||
factory.getRtpReceiverCapabilities(MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO);
|
||||
List<String> codecNames = new ArrayList<>();
|
||||
for (RtpCapabilities.CodecCapability codec : capabilities.getCodecs()) {
|
||||
codecNames.add(codec.name);
|
||||
}
|
||||
|
||||
assertTrue(codecNames.containsAll(Arrays.asList("VP8", "H264")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a created offer reflects the codec capabilities passed into setCodecPreferences.
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
public void testSetCodecPreferences() {
|
||||
List<Encoding> encodings = new ArrayList<>();
|
||||
encodings.add(new Encoding("1", true, null));
|
||||
|
||||
RtpTransceiverInit init = new RtpTransceiverInit(
|
||||
RtpTransceiver.RtpTransceiverDirection.SEND_ONLY, Collections.emptyList(), encodings);
|
||||
RtpTransceiver transceiver =
|
||||
pc.addTransceiver(MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO, init);
|
||||
|
||||
RtpCapabilities capabilities =
|
||||
factory.getRtpSenderCapabilities(MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO);
|
||||
RtpCapabilities.CodecCapability targetCodec = null;
|
||||
for (RtpCapabilities.CodecCapability codec : capabilities.getCodecs()) {
|
||||
if (codec.name.equals("VP8")) {
|
||||
targetCodec = codec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertNotNull(targetCodec);
|
||||
|
||||
transceiver.setCodecPreferences(Arrays.asList(targetCodec));
|
||||
|
||||
SdpObserverLatch sdpLatch = new SdpObserverLatch();
|
||||
pc.createOffer(sdpLatch, new MediaConstraints());
|
||||
assertTrue(sdpLatch.await());
|
||||
|
||||
SessionDescription offerSdp = sdpLatch.getSdp();
|
||||
assertNotNull(offerSdp);
|
||||
|
||||
String[] sdpDescriptionLines = offerSdp.description.split("\r\n");
|
||||
List<String> mediaDescriptions = getMediaDescriptions(sdpDescriptionLines);
|
||||
assertEquals(1, mediaDescriptions.size());
|
||||
|
||||
List<String> payloads = getMediaPayloads(mediaDescriptions.get(0));
|
||||
assertEquals(1, payloads.size());
|
||||
|
||||
String targetPayload = payloads.get(0);
|
||||
List<String> rtpMaps = getRtpMaps(sdpDescriptionLines);
|
||||
assertEquals(1, rtpMaps.size());
|
||||
|
||||
String rtpMap = rtpMaps.get(0);
|
||||
|
||||
String expected =
|
||||
"a=rtpmap:" + targetPayload + " " + targetCodec.name + "/" + targetCodec.getClockRate();
|
||||
assertEquals(expected, rtpMap);
|
||||
}
|
||||
|
||||
private List<String> getMediaDescriptions(String[] sdpDescriptionLines) {
|
||||
List<String> mediaDescriptions = new ArrayList<>();
|
||||
for (String line : sdpDescriptionLines) {
|
||||
if (line.charAt(0) == 'm') {
|
||||
mediaDescriptions.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
return mediaDescriptions;
|
||||
}
|
||||
|
||||
private List<String> getMediaPayloads(String mediaDescription) {
|
||||
String[] fields = mediaDescription.split(" ");
|
||||
assertTrue(fields.length >= 4);
|
||||
|
||||
// Media formats are described from the fourth field onwards.
|
||||
return Arrays.asList(Arrays.copyOfRange(fields, 3, fields.length));
|
||||
}
|
||||
|
||||
private List<String> getRtpMaps(String[] sdpDescriptionLines) {
|
||||
List<String> rtpMaps = new ArrayList<>();
|
||||
for (String line : sdpDescriptionLines) {
|
||||
if (line.startsWith("a=rtpmap")) {
|
||||
rtpMaps.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
return rtpMaps;
|
||||
}
|
||||
}
|
||||
@ -40,8 +40,10 @@
|
||||
#include "sdk/android/src/jni/pc/android_network_monitor.h"
|
||||
#include "sdk/android/src/jni/pc/audio.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/rtp_capabilities.h"
|
||||
#include "sdk/android/src/jni/pc/ssl_certificate_verifier_wrapper.h"
|
||||
#include "sdk/android/src/jni/pc/video.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
@ -393,6 +395,27 @@ 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,
|
||||
|
||||
119
sdk/android/src/jni/pc/rtp_capabilities.cc
Normal file
119
sdk/android/src/jni/pc/rtp_capabilities.cc
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
37
sdk/android/src/jni/pc/rtp_capabilities.h
Normal file
37
sdk/android/src/jni/pc/rtp_capabilities.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
#ifndef SDK_ANDROID_SRC_JNI_PC_RTP_CAPABILITIES_H_
|
||||
#define SDK_ANDROID_SRC_JNI_PC_RTP_CAPABILITIES_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_CAPABILITIES_H_
|
||||
@ -16,6 +16,7 @@
|
||||
#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"
|
||||
#include "sdk/android/src/jni/pc/rtp_capabilities.h"
|
||||
#include "sdk/android/src/jni/pc/rtp_parameters.h"
|
||||
#include "sdk/android/src/jni/pc/rtp_receiver.h"
|
||||
#include "sdk/android/src/jni/pc/rtp_sender.h"
|
||||
@ -139,6 +140,17 @@ ScopedJavaLocalRef<jobject> JNI_RtpTransceiver_CurrentDirection(
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void JNI_RtpTransceiver_SetCodecPreferences(
|
||||
JNIEnv* jni,
|
||||
jlong j_rtp_transceiver_pointer,
|
||||
const JavaParamRef<jobject>& j_codecs) {
|
||||
std::vector<RtpCodecCapability> codecs =
|
||||
JavaListToNativeVector<RtpCodecCapability, jobject>(
|
||||
jni, j_codecs, &JavaToNativeRtpCodecCapability);
|
||||
reinterpret_cast<RtpTransceiverInterface*>(j_rtp_transceiver_pointer)
|
||||
->SetCodecPreferences(codecs);
|
||||
}
|
||||
|
||||
void JNI_RtpTransceiver_StopInternal(JNIEnv* jni,
|
||||
jlong j_rtp_transceiver_pointer) {
|
||||
reinterpret_cast<RtpTransceiverInterface*>(j_rtp_transceiver_pointer)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user