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

Add scalabilityMode support for AV1/VP9. #90

Merged
merged 12 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 11 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
2 changes: 1 addition & 1 deletion api/video_codecs/video_encoder_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class VideoEncoderFactory {
// specified format is supported. Returns false if scalability_mode is
// specified.
CodecSupport codec_support;
if (!scalability_mode) {
cloudwebrtc marked this conversation as resolved.
Show resolved Hide resolved
if (scalability_mode) {
codec_support.is_supported = format.IsCodecInList(GetSupportedFormats());
}
return codec_support;
Expand Down
4 changes: 2 additions & 2 deletions sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ public VideoCodecInfo[] getSupportedCodecs() {
// supported by the decoder.
if (type == VideoCodecMimeType.H264 && isH264HighProfileSupported(codec)) {
supportedCodecInfos.add(new VideoCodecInfo(
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ true)));
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ true), new ArrayList<>()));
}

supportedCodecInfos.add(new VideoCodecInfo(
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ false)));
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ false), new ArrayList<>()));
}
}

Expand Down
7 changes: 7 additions & 0 deletions sdk/android/api/org/webrtc/LibaomAv1Encoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

package org.webrtc;
import java.util.List;

public class LibaomAv1Encoder extends WrappedNativeVideoEncoder {
@Override
Expand All @@ -22,4 +23,10 @@ public long createNativeVideoEncoder() {
public boolean isHardwareEncoder() {
return false;
}

static List<String> scalabilityModes() {
return nativeGetSupportedScalabilityModes();
}

static native List<String> nativeGetSupportedScalabilityModes();
}
7 changes: 7 additions & 0 deletions sdk/android/api/org/webrtc/LibvpxVp9Encoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

package org.webrtc;
import java.util.List;

public class LibvpxVp9Encoder extends WrappedNativeVideoEncoder {
@Override
Expand All @@ -24,4 +25,10 @@ public boolean isHardwareEncoder() {
}

static native boolean nativeIsSupported();

static List<String> scalabilityModes() {
return nativeGetSupportedScalabilityModes();
}

static native List<String> nativeGetSupportedScalabilityModes();
}
13 changes: 11 additions & 2 deletions sdk/android/api/org/webrtc/RtpParameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public static class Encoding {
// If non-null, scale the width and height down by this factor for video. If null,
// implementation default scaling factor will be used.
@Nullable public Double scaleResolutionDownBy;
// Scalability modes are used to represent simulcast and SVC layers.
@Nullable public String scalabilityMode;
// SSRC to be used by this encoding.
// Can't be changed between getParameters/setParameters.
public Long ssrc;
Expand All @@ -93,8 +95,8 @@ public Encoding(String rid, boolean active, Double scaleResolutionDownBy) {
@CalledByNative("Encoding")
Encoding(String rid, boolean active, double bitratePriority, @Priority int networkPriority,
Integer maxBitrateBps, Integer minBitrateBps, Integer maxFramerate,
Integer numTemporalLayers, Double scaleResolutionDownBy, Long ssrc,
boolean adaptiveAudioPacketTime) {
Integer numTemporalLayers, Double scaleResolutionDownBy, String scalabilityMode,
Long ssrc, boolean adaptiveAudioPacketTime) {
this.rid = rid;
this.active = active;
this.bitratePriority = bitratePriority;
Expand All @@ -104,6 +106,7 @@ public Encoding(String rid, boolean active, Double scaleResolutionDownBy) {
this.maxFramerate = maxFramerate;
this.numTemporalLayers = numTemporalLayers;
this.scaleResolutionDownBy = scaleResolutionDownBy;
this.scalabilityMode = scalabilityMode;
this.ssrc = ssrc;
this.adaptiveAudioPacketTime = adaptiveAudioPacketTime;
}
Expand Down Expand Up @@ -160,6 +163,12 @@ Double getScaleResolutionDownBy() {
return scaleResolutionDownBy;
}

@Nullable
@CalledByNative("Encoding")
String getScalabilityMode() {
return scalabilityMode;
}

@CalledByNative("Encoding")
Long getSsrc() {
return ssrc;
Expand Down
13 changes: 12 additions & 1 deletion sdk/android/api/org/webrtc/VideoCodecInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;

/**
* Represent a video codec as encoded in SDP.
Expand All @@ -34,20 +36,24 @@ public class VideoCodecInfo {

public final String name;
public final Map<String, String> params;
public final List<String> scalabilityModes;

@Deprecated public final int payload;

@CalledByNative
public VideoCodecInfo(String name, Map<String, String> params) {
public VideoCodecInfo(String name, Map<String, String> params, List<String> scalabilityModes) {
this.payload = 0;
this.name = name;
this.params = params;
this.scalabilityModes = scalabilityModes;
}

@Deprecated
public VideoCodecInfo(int payload, String name, Map<String, String> params) {
this.payload = payload;
this.name = name;
this.params = params;
this.scalabilityModes = new ArrayList<>();
}

@Override
Expand Down Expand Up @@ -83,4 +89,9 @@ String getName() {
Map getParams() {
return params;
}

@CalledByNative
List<String> getScalabilityModes() {
return scalabilityModes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public AndroidVideoDecoderInstrumentationTest(String codecName, boolean useEglCo
if (codecName.equals("H264")) {
this.codecType = H264Utils.DEFAULT_H264_BASELINE_PROFILE_CODEC;
} else {
this.codecType = new VideoCodecInfo(codecName, new HashMap<>());
this.codecType = new VideoCodecInfo(codecName, new HashMap<>(), new ArrayList<>());
}
this.useEglContext = useEglContext;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void setUp() {
@SmallTest
@Test
public void getSupportedCodecs_hwVp8SameParamsAsSwVp8_oneVp8() {
VideoCodecInfo hwVp8Encoder = new VideoCodecInfo("VP8", new HashMap<>());
VideoCodecInfo hwVp8Encoder = new VideoCodecInfo("VP8", new HashMap<>(), new ArrayList<>());
VideoEncoderFactory hwFactory = new CustomHardwareVideoEncoderFactory(hwVp8Encoder);
DefaultVideoEncoderFactory defFactory = new DefaultVideoEncoderFactory(hwFactory);
VideoCodecInfo[] supportedCodecs = defFactory.getSupportedCodecs();
Expand All @@ -62,7 +62,7 @@ public void getSupportedCodecs_hwVp8SameParamsAsSwVp8_oneVp8() {
public void getSupportedCodecs_hwVp8WithDifferentParams_twoVp8() {
VideoCodecInfo hwVp8Encoder = new VideoCodecInfo("VP8", new HashMap<String, String>() {
{ put("param", "value"); }
});
}, new ArrayList<>());
VideoEncoderFactory hwFactory = new CustomHardwareVideoEncoderFactory(hwVp8Encoder);
DefaultVideoEncoderFactory defFactory = new DefaultVideoEncoderFactory(hwFactory);
VideoCodecInfo[] supportedCodecs = defFactory.getSupportedCodecs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
import java.util.ArrayList;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -55,7 +56,7 @@ public void createDecoder_supportedCodec_returnsNotNull() {
@Test
public void createDecoder_unsupportedCodec_returnsNull() {
VideoDecoderFactory factory = new SoftwareVideoDecoderFactory();
VideoCodecInfo codec = new VideoCodecInfo("unsupported", new HashMap<String, String>());
VideoCodecInfo codec = new VideoCodecInfo("unsupported", new HashMap<String, String>(), new ArrayList<>());
VideoDecoder decoder = factory.createDecoder(codec);
assertThat(decoder).isNull();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
import java.util.ArrayList;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -52,7 +53,7 @@ public void createEncoder_supportedCodec_returnsNotNull() {
@Test
public void createEncoder_unsupportedCodec_returnsNull() {
VideoEncoderFactory factory = new SoftwareVideoEncoderFactory();
VideoCodecInfo codec = new VideoCodecInfo("unsupported", new HashMap<String, String>());
VideoCodecInfo codec = new VideoCodecInfo("unsupported", new HashMap<String, String>(), new ArrayList<>());
VideoEncoder encoder = factory.createEncoder(codec);
assertThat(encoder).isNull();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;

public class CodecsWrapperTestHelper {
@CalledByNative
Expand All @@ -20,7 +21,7 @@ public static VideoCodecInfo createTestVideoCodecInfo() {
params.put(
VideoCodecInfo.H264_FMTP_PROFILE_LEVEL_ID, VideoCodecInfo.H264_CONSTRAINED_BASELINE_3_1);

VideoCodecInfo codec_info = new VideoCodecInfo("H264", params);
VideoCodecInfo codec_info = new VideoCodecInfo("H264", params, new ArrayList<>());
return codec_info;
}

Expand Down
5 changes: 3 additions & 2 deletions sdk/android/src/java/org/webrtc/H264Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;

/** Container for static helper functions related to dealing with H264 codecs. */
class H264Utils {
Expand All @@ -38,9 +39,9 @@ public static Map<String, String> getDefaultH264Params(boolean isHighProfile) {
}

public static VideoCodecInfo DEFAULT_H264_BASELINE_PROFILE_CODEC =
new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ false));
new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ false), new ArrayList<>());
public static VideoCodecInfo DEFAULT_H264_HIGH_PROFILE_CODEC =
new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ true));
new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ true), new ArrayList<>());

public static boolean isSameH264Profile(
Map<String, String> params1, Map<String, String> params2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ public VideoCodecInfo[] getSupportedCodecs() {
String name = type.name();
if (type == VideoCodecMimeType.H264 && isH264HighProfileSupported(codec)) {
supportedCodecInfos.add(new VideoCodecInfo(
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ true)));
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ true), new ArrayList<>()));
}

supportedCodecInfos.add(new VideoCodecInfo(
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ false)));
name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ false), new ArrayList<>()));
}
}

Expand Down
12 changes: 12 additions & 0 deletions sdk/android/src/jni/libaom_av1_encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,24 @@
#include "sdk/android/generated_libaom_av1_encoder_jni/LibaomAv1Encoder_jni.h"
#include "sdk/android/src/jni/jni_helpers.h"

#include<vector>
#include<string>

namespace webrtc {
namespace jni {

static jlong JNI_LibaomAv1Encoder_CreateEncoder(JNIEnv* jni) {
return jlongFromPointer(webrtc::CreateLibaomAv1Encoder().release());
}

static webrtc::ScopedJavaLocalRef<jobject> JNI_LibaomAv1Encoder_GetSupportedScalabilityModes(JNIEnv* jni) {
std::vector<std::string> modes;
for (const auto scalability_mode : webrtc::kAllScalabilityModes) {
if (webrtc::ScalabilityStructureConfig(scalability_mode).has_value()) {
modes.push_back(std::string(webrtc::ScalabilityModeToString(scalability_mode)));
}
}
return NativeToJavaStringArray(jni, modes);
}
} // namespace jni
} // namespace webrtc
6 changes: 6 additions & 0 deletions sdk/android/src/jni/pc/rtp_parameters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ ScopedJavaLocalRef<jobject> NativeToJavaRtpEncodingParameter(
NativeToJavaInteger(env, encoding.max_framerate),
NativeToJavaInteger(env, encoding.num_temporal_layers),
NativeToJavaDouble(env, encoding.scale_resolution_down_by),
NativeToJavaString(env, encoding.scalability_mode),
encoding.ssrc ? NativeToJavaLong(env, *encoding.ssrc) : nullptr,
encoding.adaptive_ptime);
}
Expand Down Expand Up @@ -116,6 +117,11 @@ RtpEncodingParameters JavaToNativeRtpEncodingParameters(
Java_Encoding_getScaleResolutionDownBy(jni, j_encoding_parameters);
encoding.scale_resolution_down_by =
JavaToNativeOptionalDouble(jni, j_scale_resolution_down_by);
ScopedJavaLocalRef<jstring> j_scalability_mode =
Java_Encoding_getScalabilityMode(jni, j_encoding_parameters);
if (!IsNull(jni, j_scalability_mode)) {
encoding.scalability_mode = JavaToNativeString(jni,j_scalability_mode);
}
encoding.adaptive_ptime =
Java_Encoding_getAdaptivePTime(jni, j_encoding_parameters);
ScopedJavaLocalRef<jobject> j_ssrc =
Expand Down
26 changes: 24 additions & 2 deletions sdk/android/src/jni/video_codec_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,46 @@
#include "sdk/android/generated_video_jni/VideoCodecInfo_jni.h"
#include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "api/video_codecs/scalability_mode.h"
#include "modules/video_coding/svc/scalability_mode_util.h"

namespace webrtc {
namespace jni {

SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni,
const JavaRef<jobject>& j_info) {
std::vector<std::string> params =
JavaToStdVectorStrings(jni, Java_VideoCodecInfo_getScalabilityModes(jni, j_info));
absl::InlinedVector<ScalabilityMode, kScalabilityModeCount>
scalability_modes;
for (auto mode : params) {
auto scalability_mode = ScalabilityModeFromString(mode);
if (scalability_mode != absl::nullopt) {
scalability_modes.push_back(*scalability_mode);
}
}
return SdpVideoFormat(
JavaToNativeString(jni, Java_VideoCodecInfo_getName(jni, j_info)),
JavaToNativeStringMap(jni, Java_VideoCodecInfo_getParams(jni, j_info)));
JavaToNativeStringMap(jni, Java_VideoCodecInfo_getParams(jni, j_info)),
scalability_modes);
}

ScopedJavaLocalRef<jobject> SdpVideoFormatToVideoCodecInfo(
JNIEnv* jni,
const SdpVideoFormat& format) {
ScopedJavaLocalRef<jobject> j_params =
NativeToJavaStringMap(jni, format.parameters);
webrtc::ScopedJavaLocalRef<jobject> j_scalability_modes;
if (!format.scalability_modes.empty()) {
JavaListBuilder builder(jni);
for (auto mode : format.scalability_modes) {
std::string scalability_mode(ScalabilityModeToString(mode));
builder.add(NativeToJavaString(jni, scalability_mode));
}
j_scalability_modes = builder.java_list();
}
return Java_VideoCodecInfo_Constructor(
jni, NativeToJavaString(jni, format.name), j_params);
jni, NativeToJavaString(jni, format.name), j_params, j_scalability_modes);
}

} // namespace jni
Expand Down
16 changes: 16 additions & 0 deletions sdk/android/src/jni/vp9_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@

#include <jni.h>

#include "absl/container/inlined_vector.h"
#include "api/video_codecs/sdp_video_format.h"
#include "modules/video_coding/codecs/vp9/include/vp9.h"
#include "modules/video_coding/svc/create_scalability_structure.h"

#include "sdk/android/generated_libvpx_vp9_jni/LibvpxVp9Decoder_jni.h"
#include "sdk/android/generated_libvpx_vp9_jni/LibvpxVp9Encoder_jni.h"
#include "sdk/android/src/jni/jni_helpers.h"

#include<vector>
#include<string>

namespace webrtc {
namespace jni {

Expand All @@ -34,5 +41,14 @@ static jboolean JNI_LibvpxVp9Decoder_IsSupported(JNIEnv* jni) {
return !SupportedVP9Codecs().empty();
}

static webrtc::ScopedJavaLocalRef<jobject> JNI_LibvpxVp9Encoder_GetSupportedScalabilityModes(JNIEnv* jni) {
std::vector<std::string> modes;
for (const auto scalability_mode : webrtc::kAllScalabilityModes) {
if (webrtc::ScalabilityStructureConfig(scalability_mode).has_value()) {
modes.push_back(std::string(webrtc::ScalabilityModeToString(scalability_mode)));
}
}
return NativeToJavaStringArray(jni, modes);
}
} // namespace jni
} // namespace webrtc
Loading