diff options
Diffstat (limited to 'sdk')
52 files changed, 459 insertions, 231 deletions
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index e01ab97a6e..e7d186aa4b 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -390,6 +390,7 @@ if (is_ios || is_mac) { "../api/video:video_rtp_headers", "../common_video", "../media:rtc_media_base", + "../pc:rtc_pc_base", "../rtc_base", "../rtc_base:checks", "../rtc_base:threading", @@ -487,7 +488,10 @@ if (is_ios || is_mac) { rtc_library("ui_objc") { visibility = [ "*" ] - allow_poison = [ "audio_codecs" ] # TODO(bugs.webrtc.org/8396): Remove. + allow_poison = [ + "audio_codecs", # TODO(bugs.webrtc.org/8396): Remove. + "default_task_queue", + ] if (is_ios) { sources = [ "objc/components/renderer/opengl/RTCDisplayLinkTimer.h", @@ -506,61 +510,60 @@ if (is_ios || is_mac) { deps = [ ":base_objc", ":helpers_objc", + ":metal_objc", ":video_objc", ":videocapture_objc", ":videoframebuffer_objc", ] } - if (rtc_use_metal_rendering) { - rtc_library("metal_objc") { - visibility = [ "*" ] - allow_poison = [ - "audio_codecs", # TODO(bugs.webrtc.org/8396): Remove. - "default_task_queue", - ] - sources = [ - "objc/components/renderer/metal/RTCMTLI420Renderer.h", - "objc/components/renderer/metal/RTCMTLI420Renderer.mm", - "objc/components/renderer/metal/RTCMTLRenderer+Private.h", - "objc/components/renderer/metal/RTCMTLRenderer.h", - "objc/components/renderer/metal/RTCMTLRenderer.mm", - ] - if (is_ios) { - sources += [ - "objc/components/renderer/metal/RTCMTLNV12Renderer.h", - "objc/components/renderer/metal/RTCMTLNV12Renderer.mm", - "objc/components/renderer/metal/RTCMTLRGBRenderer.h", - "objc/components/renderer/metal/RTCMTLRGBRenderer.mm", - "objc/components/renderer/metal/RTCMTLVideoView.h", - "objc/components/renderer/metal/RTCMTLVideoView.m", - ] - } - frameworks = [ - "CoreVideo.framework", - "Metal.framework", - "MetalKit.framework", + rtc_library("metal_objc") { + visibility = [ "*" ] + allow_poison = [ + "audio_codecs", # TODO(bugs.webrtc.org/8396): Remove. + "default_task_queue", + ] + sources = [ + "objc/components/renderer/metal/RTCMTLI420Renderer.h", + "objc/components/renderer/metal/RTCMTLI420Renderer.mm", + "objc/components/renderer/metal/RTCMTLNV12Renderer.h", + "objc/components/renderer/metal/RTCMTLNV12Renderer.mm", + "objc/components/renderer/metal/RTCMTLRGBRenderer.h", + "objc/components/renderer/metal/RTCMTLRGBRenderer.mm", + "objc/components/renderer/metal/RTCMTLRenderer+Private.h", + "objc/components/renderer/metal/RTCMTLRenderer.h", + "objc/components/renderer/metal/RTCMTLRenderer.mm", + ] + frameworks = [ + "CoreVideo.framework", + "Metal.framework", + "MetalKit.framework", + ] + if (is_ios) { + sources += [ + "objc/components/renderer/metal/RTCMTLVideoView.h", + "objc/components/renderer/metal/RTCMTLVideoView.m", ] - if (is_mac) { - sources += [ - "objc/components/renderer/metal/RTCMTLNSVideoView.h", - "objc/components/renderer/metal/RTCMTLNSVideoView.m", - ] - frameworks += [ "AppKit.framework" ] - } - deps = [ - ":base_objc", - ":peerconnectionfactory_base_objc", - ":video_objc", - ":videoframebuffer_objc", - "../api/video:video_frame", - "../api/video:video_rtp_headers", - "../rtc_base:checks", - "../rtc_base:rtc_base_approved", + } + if (is_mac) { + sources += [ + "objc/components/renderer/metal/RTCMTLNSVideoView.h", + "objc/components/renderer/metal/RTCMTLNSVideoView.m", ] - configs += [ "..:common_objc" ] - public_configs = [ ":common_config_objc" ] + frameworks += [ "AppKit.framework" ] } + deps = [ + ":base_objc", + ":peerconnectionfactory_base_objc", + ":video_objc", + ":videoframebuffer_objc", + "../api/video:video_frame", + "../api/video:video_rtp_headers", + "../rtc_base:checks", + "../rtc_base:rtc_base_approved", + ] + configs += [ "..:common_objc" ] + public_configs = [ ":common_config_objc" ] } # TODO(bugs.webrtc.org/9627): Remove this target. @@ -1026,6 +1029,7 @@ if (is_ios || is_mac) { "objc/unittests/RTCEncodedImage_xctest.mm", "objc/unittests/RTCFileVideoCapturer_xctest.mm", "objc/unittests/RTCH264ProfileLevelId_xctest.m", + "objc/unittests/RTCMTLVideoView_xctest.m", "objc/unittests/RTCNV12TextureCache_xctest.m", "objc/unittests/RTCPeerConnectionFactory_xctest.m", "objc/unittests/frame_buffer_helpers.h", @@ -1050,6 +1054,7 @@ if (is_ios || is_mac) { ":callback_logger_objc", ":framework_objc", ":mediaconstraints_objc", + ":metal_objc", ":native_api", ":native_api_audio_device_module", ":native_video", @@ -1073,11 +1078,6 @@ if (is_ios || is_mac) { "//third_party/libyuv", ] - if (rtc_use_metal_rendering) { - sources += [ "objc/unittests/RTCMTLVideoView_xctest.m" ] - deps += [ ":metal_objc" ] - } - public_deps = [ "//build/config/ios:xctest", "//third_party/ocmock", @@ -1318,9 +1318,6 @@ if (is_ios || is_mac) { ":videotoolbox_objc", "../rtc_base:rtc_base_approved", ] - if (rtc_use_metal_rendering) { - deps += [ ":metal_objc" ] - } if (!build_with_chromium) { deps += [ ":callback_logger_objc", @@ -1452,9 +1449,6 @@ if (is_ios || is_mac) { ":videotoolbox_objc", "../rtc_base:rtc_base_approved", ] - if (rtc_use_metal_rendering) { - deps += [ ":metal_objc" ] - } if (!build_with_chromium) { deps += [ ":callback_logger_objc", diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index 9b6a5dcdb1..be15a7d643 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -43,6 +43,7 @@ if (is_android) { ":filevideo_java", ":hwcodecs_java", ":java_audio_device_module_java", + ":libaom_av1_java", ":libjingle_peerconnection_java", ":libjingle_peerconnection_metrics_default_java", ":libvpx_vp8_java", @@ -233,6 +234,7 @@ if (is_android) { "src/java/org/webrtc/GlGenericDrawer.java", "src/java/org/webrtc/H264Utils.java", "src/java/org/webrtc/NV21Buffer.java", + "src/java/org/webrtc/VideoCodecMimeType.java", "src/java/org/webrtc/VideoDecoderWrapper.java", "src/java/org/webrtc/VideoEncoderWrapper.java", "src/java/org/webrtc/WrappedNativeI420Buffer.java", @@ -402,7 +404,6 @@ if (is_android) { "src/java/org/webrtc/MediaCodecWrapperFactory.java", "src/java/org/webrtc/MediaCodecWrapperFactoryImpl.java", "src/java/org/webrtc/NV12Buffer.java", - "src/java/org/webrtc/VideoCodecMimeType.java", ] deps = [ @@ -500,6 +501,20 @@ if (is_android) { ] } + rtc_android_library("libaom_av1_java") { + visibility = [ "*" ] + sources = [ + "api/org/webrtc/LibaomAv1Decoder.java", + "api/org/webrtc/LibaomAv1Encoder.java", + ] + deps = [ + ":base_java", + ":video_api_java", + ":video_java", + "//rtc_base:base_java", + ] + } + rtc_android_library("swcodecs_java") { visibility = [ "*" ] sources = [ @@ -509,6 +524,7 @@ if (is_android) { deps = [ ":base_java", + ":libaom_av1_java", ":libvpx_vp8_java", ":libvpx_vp9_java", ":video_api_java", @@ -825,10 +841,24 @@ if (current_os == "linux" || is_android) { ] } + rtc_library("libaom_av1_jni") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + sources = [ "src/jni/av1_codec.cc" ] + deps = [ + ":base_jni", + ":generated_libaom_av1_jni", + ":video_jni", + "../../modules/video_coding/codecs/av1:libaom_av1_decoder", + "../../modules/video_coding/codecs/av1:libaom_av1_encoder", + ] + } + rtc_library("swcodecs_jni") { visibility = [ "*" ] allow_poison = [ "software_video_codecs" ] deps = [ + ":libaom_av1_jni", ":libvpx_vp8_jni", ":libvpx_vp9_jni", ] @@ -1264,6 +1294,16 @@ if (current_os == "linux" || is_android) { jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h" } + generate_jni("generated_libaom_av1_jni") { + sources = [ + "api/org/webrtc/LibaomAv1Decoder.java", + "api/org/webrtc/LibaomAv1Encoder.java", + ] + + namespace = "webrtc::jni" + jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h" + } + generate_jni("generated_peerconnection_jni") { sources = [ "api/org/webrtc/AddIceObserver.java", diff --git a/sdk/android/api/org/webrtc/Camera2Enumerator.java b/sdk/android/api/org/webrtc/Camera2Enumerator.java index b32b3ad302..2c6bb57b68 100644 --- a/sdk/android/api/org/webrtc/Camera2Enumerator.java +++ b/sdk/android/api/org/webrtc/Camera2Enumerator.java @@ -55,7 +55,7 @@ public class Camera2Enumerator implements CameraEnumerator { // catch statement with an Exception from a newer API, even if the code is never executed. // https://code.google.com/p/android/issues/detail?id=209129 } catch (/* CameraAccessException */ AndroidException e) { - Logging.e(TAG, "Camera access exception: " + e); + Logging.e(TAG, "Camera access exception", e); return new String[] {}; } } @@ -97,7 +97,7 @@ public class Camera2Enumerator implements CameraEnumerator { // catch statement with an Exception from a newer API, even if the code is never executed. // https://code.google.com/p/android/issues/detail?id=209129 } catch (/* CameraAccessException */ AndroidException e) { - Logging.e(TAG, "Camera access exception: " + e); + Logging.e(TAG, "Camera access exception", e); return null; } } @@ -123,8 +123,8 @@ public class Camera2Enumerator implements CameraEnumerator { // On Android OS pre 4.4.2, a class will not load because of VerifyError if it contains a // catch statement with an Exception from a newer API, even if the code is never executed. // https://code.google.com/p/android/issues/detail?id=209129 - } catch (/* CameraAccessException */ AndroidException e) { - Logging.e(TAG, "Camera access exception: " + e); + } catch (/* CameraAccessException */ AndroidException | RuntimeException e) { + Logging.e(TAG, "Failed to check if camera2 is supported", e); return false; } return true; @@ -186,7 +186,7 @@ public class Camera2Enumerator implements CameraEnumerator { try { cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId); } catch (Exception ex) { - Logging.e(TAG, "getCameraCharacteristics(): " + ex); + Logging.e(TAG, "getCameraCharacteristics()", ex); return new ArrayList<CaptureFormat>(); } diff --git a/sdk/android/api/org/webrtc/DataChannel.java b/sdk/android/api/org/webrtc/DataChannel.java index f51dab97af..bcbf6f093f 100644 --- a/sdk/android/api/org/webrtc/DataChannel.java +++ b/sdk/android/api/org/webrtc/DataChannel.java @@ -123,6 +123,7 @@ public class DataChannel { public void unregisterObserver() { checkDataChannelExists(); nativeUnregisterObserver(nativeObserver); + nativeObserver = 0; } public String label() { diff --git a/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java b/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java index 8fe8b36909..c9831c1843 100644 --- a/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java +++ b/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java @@ -94,7 +94,7 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory { return null; } - VideoCodecMimeType type = VideoCodecMimeType.valueOf(input.name); + VideoCodecMimeType type = VideoCodecMimeType.fromSdpCodecName(input.getName()); MediaCodecInfo info = findCodecForType(type); if (info == null) { @@ -137,12 +137,12 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory { List<VideoCodecInfo> supportedCodecInfos = new ArrayList<VideoCodecInfo>(); // Generate a list of supported codecs in order of preference: - // VP8, VP9, H264 (high profile), and H264 (baseline profile). - for (VideoCodecMimeType type : new VideoCodecMimeType[] { - VideoCodecMimeType.VP8, VideoCodecMimeType.VP9, VideoCodecMimeType.H264}) { + // VP8, VP9, H264 (high profile), H264 (baseline profile) and AV1. + for (VideoCodecMimeType type : new VideoCodecMimeType[] {VideoCodecMimeType.VP8, + VideoCodecMimeType.VP9, VideoCodecMimeType.H264, VideoCodecMimeType.AV1}) { MediaCodecInfo codec = findCodecForType(type); if (codec != null) { - String name = type.name(); + String name = type.toSdpCodecName(); // TODO(sakal): Always add H264 HP once WebRTC correctly removes codecs that are not // supported by the decoder. if (type == VideoCodecMimeType.H264 && isH264HighProfileSupported(codec)) { @@ -202,6 +202,8 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory { return isHardwareSupportedInCurrentSdkVp9(info); case H264: return isHardwareSupportedInCurrentSdkH264(info); + case AV1: + return false; } return false; } @@ -248,6 +250,7 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory { switch (type) { case VP8: // Fallthrough intended. case VP9: + case AV1: return 100; case H264: return 20; diff --git a/sdk/android/api/org/webrtc/LibaomAv1Decoder.java b/sdk/android/api/org/webrtc/LibaomAv1Decoder.java new file mode 100644 index 0000000000..609203fe3f --- /dev/null +++ b/sdk/android/api/org/webrtc/LibaomAv1Decoder.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 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; + +public class LibaomAv1Decoder extends WrappedNativeVideoDecoder { + @Override + public long createNativeVideoDecoder() { + return nativeCreateDecoder(); + } + + static native long nativeCreateDecoder(); + + static native boolean nativeIsSupported(); +} diff --git a/sdk/android/api/org/webrtc/LibaomAv1Encoder.java b/sdk/android/api/org/webrtc/LibaomAv1Encoder.java new file mode 100644 index 0000000000..26648c589e --- /dev/null +++ b/sdk/android/api/org/webrtc/LibaomAv1Encoder.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 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; + +public class LibaomAv1Encoder extends WrappedNativeVideoEncoder { + @Override + public long createNativeVideoEncoder() { + return nativeCreateEncoder(); + } + + static native long nativeCreateEncoder(); + + @Override + public boolean isHardwareEncoder() { + return false; + } + + static native boolean nativeIsSupported(); +} diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java index 38d2d38deb..67705ba3d5 100644 --- a/sdk/android/api/org/webrtc/PeerConnection.java +++ b/sdk/android/api/org/webrtc/PeerConnection.java @@ -141,7 +141,14 @@ public class PeerConnection { * Triggered when a new track is signaled by the remote peer, as a result of * setRemoteDescription. */ - @CalledByNative("Observer") void onAddTrack(RtpReceiver receiver, MediaStream[] mediaStreams); + @CalledByNative("Observer") + default void onAddTrack(RtpReceiver receiver, MediaStream[] mediaStreams){}; + + /** + * Triggered when a previously added remote track is removed by the remote + * peer, as a result of setRemoteDescription. + */ + @CalledByNative("Observer") default void onRemoveTrack(RtpReceiver receiver){}; /** * Triggered when the signaling from SetRemoteDescription indicates that a transceiver diff --git a/sdk/android/api/org/webrtc/RTCStats.java b/sdk/android/api/org/webrtc/RTCStats.java index 7ad7634c82..573d95300f 100644 --- a/sdk/android/api/org/webrtc/RTCStats.java +++ b/sdk/android/api/org/webrtc/RTCStats.java @@ -62,6 +62,7 @@ public class RTCStats { * - Double * - String * - The array form of any of the above (e.g., Integer[]) + * - Map of String keys to BigInteger / Double values */ public Map<String, Object> getMembers() { return members; diff --git a/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java b/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java index 7abe3505a6..c59db3b47b 100644 --- a/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java +++ b/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java @@ -16,22 +16,22 @@ import java.util.HashMap; import java.util.List; public class SoftwareVideoDecoderFactory implements VideoDecoderFactory { - @Deprecated @Nullable @Override - public VideoDecoder createDecoder(String codecType) { - return createDecoder(new VideoCodecInfo(codecType, new HashMap<>())); - } + public VideoDecoder createDecoder(VideoCodecInfo codecInfo) { + String codecName = codecInfo.getName(); - @Nullable - @Override - public VideoDecoder createDecoder(VideoCodecInfo codecType) { - if (codecType.getName().equalsIgnoreCase("VP8")) { + if (codecName.equalsIgnoreCase(VideoCodecMimeType.VP8.toSdpCodecName())) { return new LibvpxVp8Decoder(); } - if (codecType.getName().equalsIgnoreCase("VP9") && LibvpxVp9Decoder.nativeIsSupported()) { + if (codecName.equalsIgnoreCase(VideoCodecMimeType.VP9.toSdpCodecName()) + && LibvpxVp9Decoder.nativeIsSupported()) { return new LibvpxVp9Decoder(); } + if (codecName.equalsIgnoreCase(VideoCodecMimeType.AV1.toSdpCodecName()) + && LibaomAv1Decoder.nativeIsSupported()) { + return new LibaomAv1Decoder(); + } return null; } @@ -44,9 +44,12 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory { static VideoCodecInfo[] supportedCodecs() { List<VideoCodecInfo> codecs = new ArrayList<VideoCodecInfo>(); - codecs.add(new VideoCodecInfo("VP8", new HashMap<>())); + codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP8.toSdpCodecName(), new HashMap<>())); if (LibvpxVp9Decoder.nativeIsSupported()) { - codecs.add(new VideoCodecInfo("VP9", new HashMap<>())); + codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP9.toSdpCodecName(), new HashMap<>())); + } + if (LibaomAv1Decoder.nativeIsSupported()) { + codecs.add(new VideoCodecInfo(VideoCodecMimeType.AV1.toSdpCodecName(), new HashMap<>())); } return codecs.toArray(new VideoCodecInfo[codecs.size()]); diff --git a/sdk/android/api/org/webrtc/SoftwareVideoEncoderFactory.java b/sdk/android/api/org/webrtc/SoftwareVideoEncoderFactory.java index ed70d228ef..4de39dcdba 100644 --- a/sdk/android/api/org/webrtc/SoftwareVideoEncoderFactory.java +++ b/sdk/android/api/org/webrtc/SoftwareVideoEncoderFactory.java @@ -18,13 +18,20 @@ import java.util.List; public class SoftwareVideoEncoderFactory implements VideoEncoderFactory { @Nullable @Override - public VideoEncoder createEncoder(VideoCodecInfo info) { - if (info.name.equalsIgnoreCase("VP8")) { + public VideoEncoder createEncoder(VideoCodecInfo codecInfo) { + String codecName = codecInfo.getName(); + + if (codecName.equalsIgnoreCase(VideoCodecMimeType.VP8.toSdpCodecName())) { return new LibvpxVp8Encoder(); } - if (info.name.equalsIgnoreCase("VP9") && LibvpxVp9Encoder.nativeIsSupported()) { + if (codecName.equalsIgnoreCase(VideoCodecMimeType.VP9.toSdpCodecName()) + && LibvpxVp9Encoder.nativeIsSupported()) { return new LibvpxVp9Encoder(); } + if (codecName.equalsIgnoreCase(VideoCodecMimeType.AV1.toSdpCodecName()) + && LibaomAv1Encoder.nativeIsSupported()) { + return new LibaomAv1Encoder(); + } return null; } @@ -37,9 +44,12 @@ public class SoftwareVideoEncoderFactory implements VideoEncoderFactory { static VideoCodecInfo[] supportedCodecs() { List<VideoCodecInfo> codecs = new ArrayList<VideoCodecInfo>(); - codecs.add(new VideoCodecInfo("VP8", new HashMap<>())); + codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP8.toSdpCodecName(), new HashMap<>())); if (LibvpxVp9Encoder.nativeIsSupported()) { - codecs.add(new VideoCodecInfo("VP9", new HashMap<>())); + codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP9.toSdpCodecName(), new HashMap<>())); + } + if (LibaomAv1Encoder.nativeIsSupported()) { + codecs.add(new VideoCodecInfo(VideoCodecMimeType.AV1.toSdpCodecName(), new HashMap<>())); } return codecs.toArray(new VideoCodecInfo[codecs.size()]); diff --git a/sdk/android/api/org/webrtc/VideoCodecInfo.java b/sdk/android/api/org/webrtc/VideoCodecInfo.java index 8dd9295fd7..e11782dedd 100644 --- a/sdk/android/api/org/webrtc/VideoCodecInfo.java +++ b/sdk/android/api/org/webrtc/VideoCodecInfo.java @@ -69,6 +69,11 @@ public class VideoCodecInfo { return Arrays.hashCode(values); } + @Override + public String toString() { + return "VideoCodec{" + name + " " + params + "}"; + } + @CalledByNative String getName() { return name; diff --git a/sdk/android/api/org/webrtc/VideoDecoderFactory.java b/sdk/android/api/org/webrtc/VideoDecoderFactory.java index 2dd09670bd..3f0168f23e 100644 --- a/sdk/android/api/org/webrtc/VideoDecoderFactory.java +++ b/sdk/android/api/org/webrtc/VideoDecoderFactory.java @@ -18,18 +18,7 @@ public interface VideoDecoderFactory { * Creates a VideoDecoder for the given codec. Supports the same codecs supported by * VideoEncoderFactory. */ - @Deprecated - @Nullable - default VideoDecoder createDecoder(String codecType) { - throw new UnsupportedOperationException("Deprecated and not implemented."); - } - - /** Creates a decoder for the given video codec. */ - @Nullable - @CalledByNative - default VideoDecoder createDecoder(VideoCodecInfo info) { - return createDecoder(info.getName()); - } + @Nullable @CalledByNative VideoDecoder createDecoder(VideoCodecInfo info); /** * Enumerates the list of supported video codecs. diff --git a/sdk/android/api/org/webrtc/VideoEncoder.java b/sdk/android/api/org/webrtc/VideoEncoder.java index cb8eb81767..460428192d 100644 --- a/sdk/android/api/org/webrtc/VideoEncoder.java +++ b/sdk/android/api/org/webrtc/VideoEncoder.java @@ -86,6 +86,8 @@ public interface VideoEncoder { public class CodecSpecificInfoH264 extends CodecSpecificInfo {} + public class CodecSpecificInfoAV1 extends CodecSpecificInfo {} + /** * Represents bitrate allocated for an encoder to produce frames. Bitrate can be divided between * spatial and temporal layers. diff --git a/sdk/android/api/org/webrtc/YuvConverter.java b/sdk/android/api/org/webrtc/YuvConverter.java index 0e2d5055f7..9c00678900 100644 --- a/sdk/android/api/org/webrtc/YuvConverter.java +++ b/sdk/android/api/org/webrtc/YuvConverter.java @@ -12,6 +12,8 @@ package org.webrtc; import android.graphics.Matrix; import android.opengl.GLES20; +import android.opengl.GLException; +import android.support.annotation.Nullable; import java.nio.ByteBuffer; import org.webrtc.VideoFrame.I420Buffer; import org.webrtc.VideoFrame.TextureBuffer; @@ -20,7 +22,9 @@ import org.webrtc.VideoFrame.TextureBuffer; * Class for converting OES textures to a YUV ByteBuffer. It can be constructed on any thread, but * should only be operated from a single thread with an active EGL context. */ -public class YuvConverter { +public final class YuvConverter { + private static final String TAG = "YuvConverter"; + private static final String FRAGMENT_SHADER = // Difference in texture coordinate corresponding to one // sub-pixel in the x direction. @@ -122,9 +126,17 @@ public class YuvConverter { } /** Converts the texture buffer to I420. */ + @Nullable public I420Buffer convert(TextureBuffer inputTextureBuffer) { - threadChecker.checkIsOnValidThread(); + try { + return convertInternal(inputTextureBuffer); + } catch (GLException e) { + Logging.w(TAG, "Failed to convert TextureBuffer", e); + } + return null; + } + private I420Buffer convertInternal(TextureBuffer inputTextureBuffer) { TextureBuffer preparedBuffer = (TextureBuffer) videoFrameDrawer.prepareBufferForViewportSize( inputTextureBuffer, inputTextureBuffer.getWidth(), inputTextureBuffer.getHeight()); diff --git a/sdk/android/instrumentationtests/src/org/webrtc/DefaultVideoEncoderFactoryTest.java b/sdk/android/instrumentationtests/src/org/webrtc/DefaultVideoEncoderFactoryTest.java index 69b0129c36..8135e80eaf 100644 --- a/sdk/android/instrumentationtests/src/org/webrtc/DefaultVideoEncoderFactoryTest.java +++ b/sdk/android/instrumentationtests/src/org/webrtc/DefaultVideoEncoderFactoryTest.java @@ -70,13 +70,14 @@ public class DefaultVideoEncoderFactoryTest { VideoEncoderFactory hwFactory = new CustomHardwareVideoEncoderFactory(true, true); DefaultVideoEncoderFactory dvef = new DefaultVideoEncoderFactory(hwFactory); VideoCodecInfo[] videoCodecs = dvef.getSupportedCodecs(); - assertEquals(4, videoCodecs.length); + assertEquals(5, videoCodecs.length); assertEquals("VP8", videoCodecs[0].name); assertEquals("VP9", videoCodecs[1].name); - assertEquals("H264", videoCodecs[2].name); - assertEquals("42e01f", videoCodecs[2].params.get("profile-level-id")); + assertEquals("AV1X", videoCodecs[2].name); assertEquals("H264", videoCodecs[3].name); - assertEquals("640c1f", videoCodecs[3].params.get("profile-level-id")); + assertEquals("42e01f", videoCodecs[3].params.get("profile-level-id")); + assertEquals("H264", videoCodecs[4].name); + assertEquals("640c1f", videoCodecs[4].params.get("profile-level-id")); } @SmallTest @@ -85,11 +86,12 @@ public class DefaultVideoEncoderFactoryTest { VideoEncoderFactory hwFactory = new CustomHardwareVideoEncoderFactory(true, false); DefaultVideoEncoderFactory dvef = new DefaultVideoEncoderFactory(hwFactory); VideoCodecInfo[] videoCodecs = dvef.getSupportedCodecs(); - assertEquals(3, videoCodecs.length); + assertEquals(4, videoCodecs.length); assertEquals("VP8", videoCodecs[0].name); assertEquals("VP9", videoCodecs[1].name); - assertEquals("H264", videoCodecs[2].name); - assertEquals("42e01f", videoCodecs[2].params.get("profile-level-id")); + assertEquals("AV1X", videoCodecs[2].name); + assertEquals("H264", videoCodecs[3].name); + assertEquals("42e01f", videoCodecs[3].params.get("profile-level-id")); } @SmallTest @@ -98,12 +100,13 @@ public class DefaultVideoEncoderFactoryTest { VideoEncoderFactory hwFactory = new CustomHardwareVideoEncoderFactory(false, true); DefaultVideoEncoderFactory dvef = new DefaultVideoEncoderFactory(hwFactory); VideoCodecInfo[] videoCodecs = dvef.getSupportedCodecs(); - assertEquals(4, videoCodecs.length); + assertEquals(5, videoCodecs.length); assertEquals("VP8", videoCodecs[0].name); assertEquals("VP9", videoCodecs[1].name); - assertEquals("H264", videoCodecs[2].name); - assertEquals("42e01f", videoCodecs[2].params.get("profile-level-id")); + assertEquals("AV1X", videoCodecs[2].name); assertEquals("H264", videoCodecs[3].name); - assertEquals("640c1f", videoCodecs[3].params.get("profile-level-id")); + assertEquals("42e01f", videoCodecs[3].params.get("profile-level-id")); + assertEquals("H264", videoCodecs[4].name); + assertEquals("640c1f", videoCodecs[4].params.get("profile-level-id")); } } diff --git a/sdk/android/native_api/video/video_source.cc b/sdk/android/native_api/video/video_source.cc index 56a56722eb..4f1409ef7b 100644 --- a/sdk/android/native_api/video/video_source.cc +++ b/sdk/android/native_api/video/video_source.cc @@ -29,7 +29,7 @@ class JavaVideoTrackSourceImpl : public JavaVideoTrackSourceInterface { bool is_screencast, bool align_timestamps) : android_video_track_source_( - new rtc::RefCountedObject<jni::AndroidVideoTrackSource>( + rtc::make_ref_counted<jni::AndroidVideoTrackSource>( signaling_thread, env, is_screencast, @@ -109,7 +109,7 @@ rtc::scoped_refptr<JavaVideoTrackSourceInterface> CreateJavaVideoSource( rtc::Thread* signaling_thread, bool is_screencast, bool align_timestamps) { - return new rtc::RefCountedObject<JavaVideoTrackSourceImpl>( + return rtc::make_ref_counted<JavaVideoTrackSourceImpl>( jni, signaling_thread, is_screencast, align_timestamps); } diff --git a/sdk/android/native_unittests/android_network_monitor_unittest.cc b/sdk/android/native_unittests/android_network_monitor_unittest.cc index 20e756ae7b..c342ce692e 100644 --- a/sdk/android/native_unittests/android_network_monitor_unittest.cc +++ b/sdk/android/native_unittests/android_network_monitor_unittest.cc @@ -127,7 +127,6 @@ TEST_F(AndroidNetworkMonitorTest, } TEST_F(AndroidNetworkMonitorTest, TestFindNetworkHandleUsingIfName) { - ScopedFieldTrials field_trials("WebRTC-BindUsingInterfaceName/Enabled/"); // Start() updates the states introduced by the field trial. network_monitor_->Start(); jni::NetworkHandle ipv6_handle = 200; diff --git a/sdk/android/native_unittests/stacktrace/stacktrace_unittest.cc b/sdk/android/native_unittests/stacktrace/stacktrace_unittest.cc index fcd9c9b8f1..b77d86719f 100644 --- a/sdk/android/native_unittests/stacktrace/stacktrace_unittest.cc +++ b/sdk/android/native_unittests/stacktrace/stacktrace_unittest.cc @@ -153,28 +153,24 @@ class SleepDeadlock : public DeadlockInterface { } }; -// This is the function that is exectued by the thread that will deadlock and -// have its stacktrace captured. -void ThreadFunction(void* void_params) { - ThreadParams* params = static_cast<ThreadParams*>(void_params); - params->tid = gettid(); - - params->deadlock_region_start_address = GetCurrentRelativeExecutionAddress(); - params->deadlock_start_event.Set(); - params->deadlock_impl->Deadlock(); - params->deadlock_region_end_address = GetCurrentRelativeExecutionAddress(); - - params->deadlock_done_event.Set(); -} - void TestStacktrace(std::unique_ptr<DeadlockInterface> deadlock_impl) { // Set params that will be sent to other thread. ThreadParams params; params.deadlock_impl = deadlock_impl.get(); // Spawn thread. - rtc::PlatformThread thread(&ThreadFunction, ¶ms, "StacktraceTest"); - thread.Start(); + auto thread = rtc::PlatformThread::SpawnJoinable( + [¶ms] { + params.tid = gettid(); + params.deadlock_region_start_address = + GetCurrentRelativeExecutionAddress(); + params.deadlock_start_event.Set(); + params.deadlock_impl->Deadlock(); + params.deadlock_region_end_address = + GetCurrentRelativeExecutionAddress(); + params.deadlock_done_event.Set(); + }, + "StacktraceTest"); // Wait until the thread has entered the deadlock region, and take a very // brief nap to give it time to reach the actual deadlock. @@ -198,8 +194,6 @@ void TestStacktrace(std::unique_ptr<DeadlockInterface> deadlock_impl) { << rtc::ToHex(params.deadlock_region_start_address) << ", " << rtc::ToHex(params.deadlock_region_end_address) << "] not contained in: " << StackTraceToString(stack_trace); - - thread.Stop(); } class LookoutLogSink final : public rtc::LogSink { @@ -259,13 +253,9 @@ TEST(Stacktrace, TestRtcEventDeadlockDetection) { // Start a thread that waits for an event. rtc::Event ev; - rtc::PlatformThread thread( - [](void* arg) { - auto* ev = static_cast<rtc::Event*>(arg); - ev->Wait(rtc::Event::kForever); - }, - &ev, "TestRtcEventDeadlockDetection"); - thread.Start(); + auto thread = rtc::PlatformThread::SpawnJoinable( + [&ev] { ev.Wait(rtc::Event::kForever); }, + "TestRtcEventDeadlockDetection"); // The message should appear after 3 sec. We'll wait up to 10 sec in an // attempt to not be flaky. @@ -273,7 +263,7 @@ TEST(Stacktrace, TestRtcEventDeadlockDetection) { // Unblock the thread and shut it down. ev.Set(); - thread.Stop(); + thread.Finalize(); rtc::LogMessage::RemoveLogToStream(&sink); } diff --git a/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java b/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java index f6d98bd14f..f116fefc83 100644 --- a/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java +++ b/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java @@ -169,7 +169,7 @@ class HardwareVideoEncoder implements VideoEncoder { * intervals, and bitrateAdjuster. * * @param codecName the hardware codec implementation to use - * @param codecType the type of the given video codec (eg. VP8, VP9, or H264) + * @param codecType the type of the given video codec (eg. VP8, VP9, H264 or AV1) * @param surfaceColorFormat color format for surface mode or null if not available * @param yuvColorFormat color format for bytebuffer mode * @param keyFrameIntervalSec interval in seconds between key frames; used to initialize the codec diff --git a/sdk/android/src/java/org/webrtc/MediaCodecUtils.java b/sdk/android/src/java/org/webrtc/MediaCodecUtils.java index cd43098015..b634fb34f5 100644 --- a/sdk/android/src/java/org/webrtc/MediaCodecUtils.java +++ b/sdk/android/src/java/org/webrtc/MediaCodecUtils.java @@ -91,6 +91,7 @@ class MediaCodecUtils { switch (type) { case VP8: case VP9: + case AV1: return new HashMap<String, String>(); case H264: return H264Utils.getDefaultH264Params(highProfile); diff --git a/sdk/android/src/java/org/webrtc/MediaCodecVideoDecoderFactory.java b/sdk/android/src/java/org/webrtc/MediaCodecVideoDecoderFactory.java index 036aca5822..5a1d63e1c5 100644 --- a/sdk/android/src/java/org/webrtc/MediaCodecVideoDecoderFactory.java +++ b/sdk/android/src/java/org/webrtc/MediaCodecVideoDecoderFactory.java @@ -46,7 +46,7 @@ class MediaCodecVideoDecoderFactory implements VideoDecoderFactory { @Nullable @Override public VideoDecoder createDecoder(VideoCodecInfo codecType) { - VideoCodecMimeType type = VideoCodecMimeType.valueOf(codecType.getName()); + VideoCodecMimeType type = VideoCodecMimeType.fromSdpCodecName(codecType.getName()); MediaCodecInfo info = findCodecForType(type); if (info == null) { @@ -64,11 +64,11 @@ class MediaCodecVideoDecoderFactory implements VideoDecoderFactory { List<VideoCodecInfo> supportedCodecInfos = new ArrayList<VideoCodecInfo>(); // Generate a list of supported codecs in order of preference: // VP8, VP9, H264 (high profile), and H264 (baseline profile). - for (VideoCodecMimeType type : new VideoCodecMimeType[] { - VideoCodecMimeType.VP8, VideoCodecMimeType.VP9, VideoCodecMimeType.H264}) { + for (VideoCodecMimeType type : new VideoCodecMimeType[] {VideoCodecMimeType.VP8, + VideoCodecMimeType.VP9, VideoCodecMimeType.H264, VideoCodecMimeType.AV1}) { MediaCodecInfo codec = findCodecForType(type); if (codec != null) { - String name = type.name(); + String name = type.toSdpCodecName(); if (type == VideoCodecMimeType.H264 && isH264HighProfileSupported(codec)) { supportedCodecInfos.add(new VideoCodecInfo( name, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ true))); diff --git a/sdk/android/src/java/org/webrtc/VideoCodecMimeType.java b/sdk/android/src/java/org/webrtc/VideoCodecMimeType.java index f27a9176cf..93a9286165 100644 --- a/sdk/android/src/java/org/webrtc/VideoCodecMimeType.java +++ b/sdk/android/src/java/org/webrtc/VideoCodecMimeType.java @@ -14,7 +14,8 @@ package org.webrtc; enum VideoCodecMimeType { VP8("video/x-vnd.on2.vp8"), VP9("video/x-vnd.on2.vp9"), - H264("video/avc"); + H264("video/avc"), + AV1("video/av01"); private final String mimeType; @@ -25,4 +26,12 @@ enum VideoCodecMimeType { String mimeType() { return mimeType; } + + static VideoCodecMimeType fromSdpCodecName(String codecName) { + return codecName.equals("AV1X") ? AV1 : valueOf(codecName); + } + + String toSdpCodecName() { + return this == AV1 ? "AV1X" : name(); + } } diff --git a/sdk/android/src/jni/android_network_monitor.cc b/sdk/android/src/jni/android_network_monitor.cc index fa82816431..686f94e1e6 100644 --- a/sdk/android/src/jni/android_network_monitor.cc +++ b/sdk/android/src/jni/android_network_monitor.cc @@ -247,7 +247,7 @@ void AndroidNetworkMonitor::Start() { webrtc::field_trial::IsEnabled( "WebRTC-FindNetworkHandleWithoutIpv6TemporaryPart"); bind_using_ifname_ = - webrtc::field_trial::IsEnabled("WebRTC-BindUsingInterfaceName"); + !webrtc::field_trial::IsDisabled("WebRTC-BindUsingInterfaceName"); // This pointer is also accessed by the methods called from java threads. // Assigning it here is safe, because the java monitor is in a stopped state, diff --git a/sdk/android/src/jni/audio_device/audio_device_module.cc b/sdk/android/src/jni/audio_device/audio_device_module.cc index 74a0db00f9..4c9c36b7ac 100644 --- a/sdk/android/src/jni/audio_device/audio_device_module.cc +++ b/sdk/android/src/jni/audio_device/audio_device_module.cc @@ -641,7 +641,7 @@ rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModuleFromInputAndOutput( std::unique_ptr<AudioInput> audio_input, std::unique_ptr<AudioOutput> audio_output) { RTC_DLOG(INFO) << __FUNCTION__; - return new rtc::RefCountedObject<AndroidAudioDeviceModule>( + return rtc::make_ref_counted<AndroidAudioDeviceModule>( audio_layer, is_stereo_playout_supported, is_stereo_record_supported, playout_delay_ms, std::move(audio_input), std::move(audio_output)); } diff --git a/sdk/android/src/jni/audio_device/opensles_common.cc b/sdk/android/src/jni/audio_device/opensles_common.cc index 04c3ae9f7a..0f35b2712a 100644 --- a/sdk/android/src/jni/audio_device/opensles_common.cc +++ b/sdk/android/src/jni/audio_device/opensles_common.cc @@ -106,8 +106,6 @@ OpenSLEngineManager::OpenSLEngineManager() { thread_checker_.Detach(); } -OpenSLEngineManager::~OpenSLEngineManager() = default; - SLObjectItf OpenSLEngineManager::GetOpenSLEngine() { RTC_LOG(INFO) << "GetOpenSLEngine"; RTC_DCHECK(thread_checker_.IsCurrent()); diff --git a/sdk/android/src/jni/audio_device/opensles_common.h b/sdk/android/src/jni/audio_device/opensles_common.h index d812b920ff..9dd1e0f7d7 100644 --- a/sdk/android/src/jni/audio_device/opensles_common.h +++ b/sdk/android/src/jni/audio_device/opensles_common.h @@ -68,10 +68,11 @@ typedef ScopedSLObject<SLObjectItf, const SLObjectItf_*> ScopedSLObjectItf; // Subsequent calls returns the already created engine. // Note: This class must be used single threaded and this is enforced by a // thread checker. -class OpenSLEngineManager : public rtc::RefCountedBase { +class OpenSLEngineManager + : public rtc::RefCountedNonVirtual<OpenSLEngineManager> { public: OpenSLEngineManager(); - ~OpenSLEngineManager() override; + ~OpenSLEngineManager() = default; SLObjectItf GetOpenSLEngine(); private: diff --git a/sdk/android/src/jni/av1_codec.cc b/sdk/android/src/jni/av1_codec.cc new file mode 100644 index 0000000000..02070f7901 --- /dev/null +++ b/sdk/android/src/jni/av1_codec.cc @@ -0,0 +1,39 @@ +/* + * Copyright 2021 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 <jni.h> + +#include "modules/video_coding/codecs/av1/libaom_av1_decoder.h" +#include "modules/video_coding/codecs/av1/libaom_av1_encoder.h" +#include "sdk/android/generated_libaom_av1_jni/LibaomAv1Decoder_jni.h" +#include "sdk/android/generated_libaom_av1_jni/LibaomAv1Encoder_jni.h" +#include "sdk/android/src/jni/jni_helpers.h" + +namespace webrtc { +namespace jni { + +static jlong JNI_LibaomAv1Encoder_CreateEncoder(JNIEnv* jni) { + return jlongFromPointer(webrtc::CreateLibaomAv1Encoder().release()); +} + +static jboolean JNI_LibaomAv1Encoder_IsSupported(JNIEnv* jni) { + return webrtc::kIsLibaomAv1EncoderSupported; +} + +static jlong JNI_LibaomAv1Decoder_CreateDecoder(JNIEnv* jni) { + return jlongFromPointer(webrtc::CreateLibaomAv1Decoder().release()); +} + +static jboolean JNI_LibaomAv1Decoder_IsSupported(JNIEnv* jni) { + return webrtc::kIsLibaomAv1DecoderSupported; +} + +} // namespace jni +} // namespace webrtc diff --git a/sdk/android/src/jni/encoded_image.cc b/sdk/android/src/jni/encoded_image.cc index 839f6a8f6a..189d7e95e4 100644 --- a/sdk/android/src/jni/encoded_image.cc +++ b/sdk/android/src/jni/encoded_image.cc @@ -90,7 +90,7 @@ EncodedImage JavaToNativeEncodedImage(JNIEnv* env, const size_t buffer_size = env->GetDirectBufferCapacity(j_buffer.obj()); EncodedImage frame; - frame.SetEncodedData(new rtc::RefCountedObject<JavaEncodedImageBuffer>( + frame.SetEncodedData(rtc::make_ref_counted<JavaEncodedImageBuffer>( env, j_encoded_image, buffer, buffer_size)); frame._encodedWidth = Java_EncodedImage_getEncodedWidth(env, j_encoded_image); diff --git a/sdk/android/src/jni/pc/add_ice_candidate_observer.h b/sdk/android/src/jni/pc/add_ice_candidate_observer.h index ed72de9df6..1128385389 100644 --- a/sdk/android/src/jni/pc/add_ice_candidate_observer.h +++ b/sdk/android/src/jni/pc/add_ice_candidate_observer.h @@ -20,10 +20,11 @@ namespace webrtc { namespace jni { -class AddIceCandidateObserverJni final : public rtc::RefCountedBase { +class AddIceCandidateObserverJni final + : public rtc::RefCountedNonVirtual<AddIceCandidateObserverJni> { public: AddIceCandidateObserverJni(JNIEnv* env, const JavaRef<jobject>& j_observer); - ~AddIceCandidateObserverJni() override = default; + ~AddIceCandidateObserverJni() = default; void OnComplete(RTCError error); diff --git a/sdk/android/src/jni/pc/peer_connection.cc b/sdk/android/src/jni/pc/peer_connection.cc index 35f6ad56af..09b8f33edb 100644 --- a/sdk/android/src/jni/pc/peer_connection.cc +++ b/sdk/android/src/jni/pc/peer_connection.cc @@ -410,6 +410,16 @@ void PeerConnectionObserverJni::OnAddTrack( NativeToJavaMediaStreamArray(env, streams)); } +void PeerConnectionObserverJni::OnRemoveTrack( + rtc::scoped_refptr<RtpReceiverInterface> receiver) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedJavaLocalRef<jobject> j_rtp_receiver = + NativeToJavaRtpReceiver(env, receiver); + rtp_receivers_.emplace_back(env, j_rtp_receiver); + + Java_Observer_onRemoveTrack(env, j_observer_global_, j_rtp_receiver); +} + void PeerConnectionObserverJni::OnTrack( rtc::scoped_refptr<RtpTransceiverInterface> transceiver) { JNIEnv* env = AttachCurrentThreadIfNeeded(); @@ -538,10 +548,12 @@ static ScopedJavaLocalRef<jobject> JNI_PeerConnection_CreateDataChannel( const JavaParamRef<jstring>& j_label, const JavaParamRef<jobject>& j_init) { DataChannelInit init = JavaToNativeDataChannelInit(jni, j_init); - rtc::scoped_refptr<DataChannelInterface> channel( - ExtractNativePC(jni, j_pc)->CreateDataChannel( - JavaToNativeString(jni, j_label), &init)); - return WrapNativeDataChannel(jni, channel); + auto result = ExtractNativePC(jni, j_pc)->CreateDataChannelOrError( + JavaToNativeString(jni, j_label), &init); + if (!result.ok()) { + return WrapNativeDataChannel(jni, nullptr); + } + return WrapNativeDataChannel(jni, result.MoveValue()); } static void JNI_PeerConnection_CreateOffer( @@ -551,9 +563,8 @@ static void JNI_PeerConnection_CreateOffer( const JavaParamRef<jobject>& j_constraints) { std::unique_ptr<MediaConstraints> constraints = JavaToNativeMediaConstraints(jni, j_constraints); - rtc::scoped_refptr<CreateSdpObserverJni> observer( - new rtc::RefCountedObject<CreateSdpObserverJni>(jni, j_observer, - std::move(constraints))); + auto observer = rtc::make_ref_counted<CreateSdpObserverJni>( + jni, j_observer, std::move(constraints)); PeerConnectionInterface::RTCOfferAnswerOptions options; CopyConstraintsIntoOfferAnswerOptions(observer->constraints(), &options); ExtractNativePC(jni, j_pc)->CreateOffer(observer, options); @@ -566,9 +577,8 @@ static void JNI_PeerConnection_CreateAnswer( const JavaParamRef<jobject>& j_constraints) { std::unique_ptr<MediaConstraints> constraints = JavaToNativeMediaConstraints(jni, j_constraints); - rtc::scoped_refptr<CreateSdpObserverJni> observer( - new rtc::RefCountedObject<CreateSdpObserverJni>(jni, j_observer, - std::move(constraints))); + auto observer = rtc::make_ref_counted<CreateSdpObserverJni>( + jni, j_observer, std::move(constraints)); PeerConnectionInterface::RTCOfferAnswerOptions options; CopyConstraintsIntoOfferAnswerOptions(observer->constraints(), &options); ExtractNativePC(jni, j_pc)->CreateAnswer(observer, options); @@ -578,8 +588,8 @@ static void JNI_PeerConnection_SetLocalDescriptionAutomatically( JNIEnv* jni, const JavaParamRef<jobject>& j_pc, const JavaParamRef<jobject>& j_observer) { - rtc::scoped_refptr<SetLocalSdpObserverJni> observer( - new rtc::RefCountedObject<SetLocalSdpObserverJni>(jni, j_observer)); + auto observer = + rtc::make_ref_counted<SetLocalSdpObserverJni>(jni, j_observer); ExtractNativePC(jni, j_pc)->SetLocalDescription(observer); } @@ -588,8 +598,8 @@ static void JNI_PeerConnection_SetLocalDescription( const JavaParamRef<jobject>& j_pc, const JavaParamRef<jobject>& j_observer, const JavaParamRef<jobject>& j_sdp) { - rtc::scoped_refptr<SetLocalSdpObserverJni> observer( - new rtc::RefCountedObject<SetLocalSdpObserverJni>(jni, j_observer)); + auto observer = + rtc::make_ref_counted<SetLocalSdpObserverJni>(jni, j_observer); ExtractNativePC(jni, j_pc)->SetLocalDescription( JavaToNativeSessionDescription(jni, j_sdp), observer); } @@ -599,8 +609,8 @@ static void JNI_PeerConnection_SetRemoteDescription( const JavaParamRef<jobject>& j_pc, const JavaParamRef<jobject>& j_observer, const JavaParamRef<jobject>& j_sdp) { - rtc::scoped_refptr<SetRemoteSdpObserverJni> observer( - new rtc::RefCountedObject<SetRemoteSdpObserverJni>(jni, j_observer)); + auto observer = + rtc::make_ref_counted<SetRemoteSdpObserverJni>(jni, j_observer); ExtractNativePC(jni, j_pc)->SetRemoteDescription( JavaToNativeSessionDescription(jni, j_sdp), observer); } @@ -799,8 +809,7 @@ static jboolean JNI_PeerConnection_OldGetStats( const JavaParamRef<jobject>& j_pc, const JavaParamRef<jobject>& j_observer, jlong native_track) { - rtc::scoped_refptr<StatsObserverJni> observer( - new rtc::RefCountedObject<StatsObserverJni>(jni, j_observer)); + auto observer = rtc::make_ref_counted<StatsObserverJni>(jni, j_observer); return ExtractNativePC(jni, j_pc)->GetStats( observer, reinterpret_cast<MediaStreamTrackInterface*>(native_track), PeerConnectionInterface::kStatsOutputLevelStandard); @@ -810,9 +819,8 @@ static void JNI_PeerConnection_NewGetStats( JNIEnv* jni, const JavaParamRef<jobject>& j_pc, const JavaParamRef<jobject>& j_callback) { - rtc::scoped_refptr<RTCStatsCollectorCallbackWrapper> callback( - new rtc::RefCountedObject<RTCStatsCollectorCallbackWrapper>(jni, - j_callback)); + auto callback = + rtc::make_ref_counted<RTCStatsCollectorCallbackWrapper>(jni, j_callback); ExtractNativePC(jni, j_pc)->GetStats(callback); } diff --git a/sdk/android/src/jni/pc/peer_connection.h b/sdk/android/src/jni/pc/peer_connection.h index a9e2af2a47..86d99f31c4 100644 --- a/sdk/android/src/jni/pc/peer_connection.h +++ b/sdk/android/src/jni/pc/peer_connection.h @@ -72,6 +72,8 @@ class PeerConnectionObserverJni : public PeerConnectionObserver { streams) override; void OnTrack( rtc::scoped_refptr<RtpTransceiverInterface> transceiver) override; + void OnRemoveTrack( + rtc::scoped_refptr<RtpReceiverInterface> receiver) override; private: typedef std::map<MediaStreamInterface*, JavaMediaStream> diff --git a/sdk/android/src/jni/pc/peer_connection_factory.cc b/sdk/android/src/jni/pc/peer_connection_factory.cc index 2392db2403..53e715bd08 100644 --- a/sdk/android/src/jni/pc/peer_connection_factory.cc +++ b/sdk/android/src/jni/pc/peer_connection_factory.cc @@ -471,14 +471,14 @@ static jlong JNI_PeerConnectionFactory_CreatePeerConnection( jni, j_sslCertificateVerifier); } - rtc::scoped_refptr<PeerConnectionInterface> pc = - PeerConnectionFactoryFromJava(factory)->CreatePeerConnection( + auto result = + PeerConnectionFactoryFromJava(factory)->CreatePeerConnectionOrError( rtc_config, std::move(peer_connection_dependencies)); - if (!pc) + if (!result.ok()) return 0; - return jlongFromPointer( - new OwnedPeerConnection(pc, std::move(observer), std::move(constraints))); + return jlongFromPointer(new OwnedPeerConnection( + result.MoveValue(), std::move(observer), std::move(constraints))); } static jlong JNI_PeerConnectionFactory_CreateVideoSource( diff --git a/sdk/android/src/jni/pc/rtc_stats_collector_callback_wrapper.cc b/sdk/android/src/jni/pc/rtc_stats_collector_callback_wrapper.cc index b334bb4a72..baa3f276e7 100644 --- a/sdk/android/src/jni/pc/rtc_stats_collector_callback_wrapper.cc +++ b/sdk/android/src/jni/pc/rtc_stats_collector_callback_wrapper.cc @@ -94,6 +94,23 @@ ScopedJavaLocalRef<jobject> MemberToJava( case RTCStatsMemberInterface::kSequenceString: return NativeToJavaStringArray( env, *member.cast_to<RTCStatsMember<std::vector<std::string>>>()); + + case RTCStatsMemberInterface::kMapStringUint64: + return NativeToJavaMap( + env, + *member.cast_to<RTCStatsMember<std::map<std::string, uint64_t>>>(), + [](JNIEnv* env, const auto& entry) { + return std::make_pair(NativeToJavaString(env, entry.first), + NativeToJavaBigInteger(env, entry.second)); + }); + + case RTCStatsMemberInterface::kMapStringDouble: + return NativeToJavaMap( + env, *member.cast_to<RTCStatsMember<std::map<std::string, double>>>(), + [](JNIEnv* env, const auto& entry) { + return std::make_pair(NativeToJavaString(env, entry.first), + NativeToJavaDouble(env, entry.second)); + }); } RTC_NOTREACHED(); return nullptr; diff --git a/sdk/android/src/jni/pc/video.cc b/sdk/android/src/jni/pc/video.cc index 513a0059f2..ee5ecbea6f 100644 --- a/sdk/android/src/jni/pc/video.cc +++ b/sdk/android/src/jni/pc/video.cc @@ -46,9 +46,8 @@ void* CreateVideoSource(JNIEnv* env, rtc::Thread* worker_thread, jboolean is_screencast, jboolean align_timestamps) { - rtc::scoped_refptr<AndroidVideoTrackSource> source( - new rtc::RefCountedObject<AndroidVideoTrackSource>( - signaling_thread, env, is_screencast, align_timestamps)); + auto source = rtc::make_ref_counted<AndroidVideoTrackSource>( + signaling_thread, env, is_screencast, align_timestamps); return source.release(); } diff --git a/sdk/android/src/jni/video_frame.cc b/sdk/android/src/jni/video_frame.cc index c92561afc2..98728032e8 100644 --- a/sdk/android/src/jni/video_frame.cc +++ b/sdk/android/src/jni/video_frame.cc @@ -77,8 +77,8 @@ rtc::scoped_refptr<AndroidVideoI420Buffer> AndroidVideoI420Buffer::Adopt( int width, int height, const JavaRef<jobject>& j_video_frame_buffer) { - return new rtc::RefCountedObject<AndroidVideoI420Buffer>( - jni, width, height, j_video_frame_buffer); + return rtc::make_ref_counted<AndroidVideoI420Buffer>(jni, width, height, + j_video_frame_buffer); } AndroidVideoI420Buffer::AndroidVideoI420Buffer( @@ -123,8 +123,7 @@ int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni, rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBuffer::Adopt( JNIEnv* jni, const JavaRef<jobject>& j_video_frame_buffer) { - return new rtc::RefCountedObject<AndroidVideoBuffer>(jni, - j_video_frame_buffer); + return rtc::make_ref_counted<AndroidVideoBuffer>(jni, j_video_frame_buffer); } rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBuffer::Create( @@ -180,6 +179,10 @@ rtc::scoped_refptr<I420BufferInterface> AndroidVideoBuffer::ToI420() { JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedJavaLocalRef<jobject> j_i420_buffer = Java_Buffer_toI420(jni, j_video_frame_buffer_); + // In case I420 conversion fails, we propagate the nullptr. + if (j_i420_buffer.is_null()) { + return nullptr; + } // We don't need to retain the buffer because toI420 returns a new object that // we are assumed to take the ownership of. diff --git a/sdk/media_constraints.cc b/sdk/media_constraints.cc index f4d72bdf36..6f4901c97e 100644 --- a/sdk/media_constraints.cc +++ b/sdk/media_constraints.cc @@ -118,7 +118,6 @@ const char MediaConstraints::kUseRtpMux[] = "googUseRtpMUX"; // Below constraints should be used during PeerConnection construction. const char MediaConstraints::kEnableDtlsSrtp[] = "DtlsSrtpKeyAgreement"; -const char MediaConstraints::kEnableRtpDataChannels[] = "RtpDataChannels"; // Google-specific constraint keys. const char MediaConstraints::kEnableDscp[] = "googDscp"; const char MediaConstraints::kEnableIPv6[] = "googIPv6"; diff --git a/sdk/media_constraints.h b/sdk/media_constraints.h index b85dc472e0..15cb363f7c 100644 --- a/sdk/media_constraints.h +++ b/sdk/media_constraints.h @@ -85,8 +85,6 @@ class MediaConstraints { // PeerConnection constraint keys. // Temporary pseudo-constraints used to enable DTLS-SRTP static const char kEnableDtlsSrtp[]; // Enable DTLS-SRTP - // Temporary pseudo-constraints used to enable DataChannels - static const char kEnableRtpDataChannels[]; // Enable RTP DataChannels // Google-specific constraint keys. // Temporary pseudo-constraint for enabling DSCP through JS. static const char kEnableDscp[]; // googDscp diff --git a/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm b/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm index 1ded45d670..cb75f061d8 100644 --- a/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm +++ b/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm @@ -23,14 +23,12 @@ std::string labelString = [NSString stdStringForString:label]; const webrtc::DataChannelInit nativeInit = configuration.nativeDataChannelInit; - rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel = - self.nativePeerConnection->CreateDataChannel(labelString, - &nativeInit); - if (!dataChannel) { + auto result = self.nativePeerConnection->CreateDataChannelOrError(labelString, &nativeInit); + if (!result.ok()) { return nil; } return [[RTC_OBJC_TYPE(RTCDataChannel) alloc] initWithFactory:self.factory - nativeDataChannel:dataChannel]; + nativeDataChannel:result.MoveValue()]; } @end diff --git a/sdk/objc/api/peerconnection/RTCPeerConnection.mm b/sdk/objc/api/peerconnection/RTCPeerConnection.mm index 8a47d22772..05fe581d08 100644 --- a/sdk/objc/api/peerconnection/RTCPeerConnection.mm +++ b/sdk/objc/api/peerconnection/RTCPeerConnection.mm @@ -348,11 +348,12 @@ void PeerConnectionDelegateAdapter::OnRemoveTrack( webrtc::PeerConnectionDependencies deps = std::move(*dependencies.release()); deps.observer = _observer.get(); - _peerConnection = factory.nativeFactory->CreatePeerConnection(*config, std::move(deps)); + auto result = factory.nativeFactory->CreatePeerConnectionOrError(*config, std::move(deps)); - if (!_peerConnection) { + if (!result.ok()) { return nil; } + _peerConnection = result.MoveValue(); _factory = factory; _localStreams = [[NSMutableArray alloc] init]; _delegate = delegate; diff --git a/sdk/objc/api/peerconnection/RTCRtpCodecParameters.h b/sdk/objc/api/peerconnection/RTCRtpCodecParameters.h index afa2fd5fe2..6135223720 100644 --- a/sdk/objc/api/peerconnection/RTCRtpCodecParameters.h +++ b/sdk/objc/api/peerconnection/RTCRtpCodecParameters.h @@ -31,7 +31,7 @@ RTC_EXTERN const NSString *const kRTCVp8CodecName; RTC_EXTERN const NSString *const kRTCVp9CodecName; RTC_EXTERN const NSString *const kRTCH264CodecName; -/** Defined in http://w3c.github.io/webrtc-pc/#idl-def-RTC_OBJC_TYPE(RTCRtpCodecParameters) */ +/** Defined in https://www.w3.org/TR/webrtc/#idl-def-rtcrtpcodecparameters */ RTC_OBJC_EXPORT @interface RTC_OBJC_TYPE (RTCRtpCodecParameters) : NSObject diff --git a/sdk/objc/api/peerconnection/RTCStatisticsReport.h b/sdk/objc/api/peerconnection/RTCStatisticsReport.h index 38d93e8771..06dbf48d88 100644 --- a/sdk/objc/api/peerconnection/RTCStatisticsReport.h +++ b/sdk/objc/api/peerconnection/RTCStatisticsReport.h @@ -44,8 +44,8 @@ RTC_OBJC_EXPORT @property(nonatomic, readonly) NSString *type; /** The keys and values of the subreport, e.g. "totalFramesDuration = 5.551". - The values are either NSNumbers or NSStrings, or NSArrays encapsulating NSNumbers - or NSStrings. */ + The values are either NSNumbers or NSStrings or NSArrays encapsulating NSNumbers + or NSStrings, or NSDictionary of NSString keys to NSNumber values. */ @property(nonatomic, readonly) NSDictionary<NSString *, NSObject *> *values; - (instancetype)init NS_UNAVAILABLE; diff --git a/sdk/objc/api/peerconnection/RTCStatisticsReport.mm b/sdk/objc/api/peerconnection/RTCStatisticsReport.mm index 1dd72772ed..967683fc91 100644 --- a/sdk/objc/api/peerconnection/RTCStatisticsReport.mm +++ b/sdk/objc/api/peerconnection/RTCStatisticsReport.mm @@ -16,7 +16,7 @@ namespace webrtc { /** Converts a single value to a suitable NSNumber, NSString or NSArray containing NSNumbers - or NSStrings.*/ + or NSStrings, or NSDictionary of NSString keys to NSNumber values.*/ NSObject *ValueFromStatsMember(const RTCStatsMemberInterface *member) { if (member->is_defined()) { switch (member->type()) { @@ -91,6 +91,26 @@ NSObject *ValueFromStatsMember(const RTCStatsMemberInterface *member) { } return [array copy]; } + case RTCStatsMemberInterface::kMapStringUint64: { + std::map<std::string, uint64_t> map = + *member->cast_to<RTCStatsMember<std::map<std::string, uint64_t>>>(); + NSMutableDictionary<NSString *, NSNumber *> *dictionary = + [NSMutableDictionary dictionaryWithCapacity:map.size()]; + for (const auto &item : map) { + dictionary[[NSString stringForStdString:item.first]] = @(item.second); + } + return [dictionary copy]; + } + case RTCStatsMemberInterface::kMapStringDouble: { + std::map<std::string, double> map = + *member->cast_to<RTCStatsMember<std::map<std::string, double>>>(); + NSMutableDictionary<NSString *, NSNumber *> *dictionary = + [NSMutableDictionary dictionaryWithCapacity:map.size()]; + for (const auto &item : map) { + dictionary[[NSString stringForStdString:item.first]] = @(item.second); + } + return [dictionary copy]; + } default: RTC_NOTREACHED(); } diff --git a/sdk/objc/api/peerconnection/RTCVideoSource.mm b/sdk/objc/api/peerconnection/RTCVideoSource.mm index 15b0d6f1be..3a1ea6a322 100644 --- a/sdk/objc/api/peerconnection/RTCVideoSource.mm +++ b/sdk/objc/api/peerconnection/RTCVideoSource.mm @@ -10,7 +10,7 @@ #import "RTCVideoSource+Private.h" -#include "api/video_track_source_proxy.h" +#include "pc/video_track_source_proxy.h" #include "rtc_base/checks.h" #include "sdk/objc/native/src/objc_video_track_source.h" diff --git a/sdk/objc/api/video_codec/RTCWrappedNativeVideoEncoder.mm b/sdk/objc/api/video_codec/RTCWrappedNativeVideoEncoder.mm index 843b6ad001..ea2a459360 100644 --- a/sdk/objc/api/video_codec/RTCWrappedNativeVideoEncoder.mm +++ b/sdk/objc/api/video_codec/RTCWrappedNativeVideoEncoder.mm @@ -69,4 +69,14 @@ return nil; } +- (NSInteger)resolutionAlignment { + RTC_NOTREACHED(); + return 1; +} + +- (BOOL)applyAlignmentToAllSimulcastLayers { + RTC_NOTREACHED(); + return NO; +} + @end diff --git a/sdk/objc/base/RTCVideoEncoder.h b/sdk/objc/base/RTCVideoEncoder.h index 29e8a89901..26cf4ec03f 100644 --- a/sdk/objc/base/RTCVideoEncoder.h +++ b/sdk/objc/base/RTCVideoEncoder.h @@ -28,7 +28,7 @@ RTC_OBJC_EXPORT @protocol RTC_OBJC_TYPE (RTCVideoEncoder)<NSObject> - - (void)setCallback : (RTCVideoEncoderCallback)callback; +- (void)setCallback:(nullable RTCVideoEncoderCallback)callback; - (NSInteger)startEncodeWithSettings:(RTC_OBJC_TYPE(RTCVideoEncoderSettings) *)settings numberOfCores:(int)numberOfCores; - (NSInteger)releaseEncoder; @@ -43,6 +43,13 @@ RTC_OBJC_EXPORT * disables quality scaling. */ - (nullable RTC_OBJC_TYPE(RTCVideoEncoderQpThresholds) *)scalingSettings; +/** Resolutions should be aligned to this value. */ +@property(nonatomic, readonly) NSInteger resolutionAlignment; + +/** If enabled, resolution alignment is applied to all simulcast layers simultaneously so that when + scaled, all resolutions comply with 'resolutionAlignment'. */ +@property(nonatomic, readonly) BOOL applyAlignmentToAllSimulcastLayers; + @end NS_ASSUME_NONNULL_END diff --git a/sdk/objc/components/audio/RTCAudioSession.h b/sdk/objc/components/audio/RTCAudioSession.h index f917e327a4..79658e3c81 100644 --- a/sdk/objc/components/audio/RTCAudioSession.h +++ b/sdk/objc/components/audio/RTCAudioSession.h @@ -137,8 +137,6 @@ RTC_OBJC_EXPORT * AVAudioSession. */ @property(nonatomic, readonly) BOOL isActive; -/** Whether RTCAudioSession is currently locked for configuration. */ -@property(nonatomic, readonly) BOOL isLocked; /** If YES, WebRTC will not initialize the audio unit automatically when an * audio track is ready for playout or recording. Instead, applications should diff --git a/sdk/objc/components/renderer/metal/RTCMTLVideoView.h b/sdk/objc/components/renderer/metal/RTCMTLVideoView.h index 5678112ade..3320d12076 100644 --- a/sdk/objc/components/renderer/metal/RTCMTLVideoView.h +++ b/sdk/objc/components/renderer/metal/RTCMTLVideoView.h @@ -21,8 +21,6 @@ NS_ASSUME_NONNULL_BEGIN * * It has id<RTCVideoRenderer> property that renders video frames in the view's * bounds using Metal. - * NOTE: always check if metal is available on the running device via - * RTC_SUPPORTS_METAL macro before initializing this class. */ NS_CLASS_AVAILABLE_IOS(9) diff --git a/sdk/objc/components/renderer/metal/RTCMTLVideoView.m b/sdk/objc/components/renderer/metal/RTCMTLVideoView.m index f5be7c061c..4c50bcf9c1 100644 --- a/sdk/objc/components/renderer/metal/RTCMTLVideoView.m +++ b/sdk/objc/components/renderer/metal/RTCMTLVideoView.m @@ -86,11 +86,7 @@ #pragma mark - Private + (BOOL)isMetalAvailable { -#if defined(RTC_SUPPORTS_METAL) return MTLCreateSystemDefaultDevice() != nil; -#else - return NO; -#endif } + (MTKView *)createMetalView:(CGRect)frame { diff --git a/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm b/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm index e64f61912a..345170388d 100644 --- a/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm +++ b/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm @@ -529,6 +529,14 @@ NSUInteger GetMaxSampleRate(const webrtc::H264ProfileLevelId &profile_level_id) return WEBRTC_VIDEO_CODEC_OK; } +- (NSInteger)resolutionAlignment { + return 1; +} + +- (BOOL)applyAlignmentToAllSimulcastLayers { + return NO; +} + #pragma mark - Private - (NSInteger)releaseEncoder { @@ -759,6 +767,10 @@ NSUInteger GetMaxSampleRate(const webrtc::H264ProfileLevelId &profile_level_id) renderTimeMs:(int64_t)renderTimeMs timestamp:(uint32_t)timestamp rotation:(RTCVideoRotation)rotation { + RTCVideoEncoderCallback callback = _callback; + if (!callback) { + return; + } if (status != noErr) { RTC_LOG(LS_ERROR) << "H264 encode failed with code: " << status; return; @@ -805,7 +817,7 @@ NSUInteger GetMaxSampleRate(const webrtc::H264ProfileLevelId &profile_level_id) _h264BitstreamParser.ParseBitstream(*buffer); frame.qp = @(_h264BitstreamParser.GetLastSliceQp().value_or(-1)); - BOOL res = _callback(frame, codecSpecificInfo); + BOOL res = callback(frame, codecSpecificInfo); if (!res) { RTC_LOG(LS_ERROR) << "Encode callback failed"; return; diff --git a/sdk/objc/native/api/video_capturer.mm b/sdk/objc/native/api/video_capturer.mm index 6dd0edbcd9..cae7a50318 100644 --- a/sdk/objc/native/api/video_capturer.mm +++ b/sdk/objc/native/api/video_capturer.mm @@ -11,7 +11,8 @@ #include "sdk/objc/native/api/video_capturer.h" #include "absl/memory/memory.h" -#include "api/video_track_source_proxy.h" +#include "api/video_track_source_proxy_factory.h" +#include "rtc_base/ref_counted_object.h" #include "sdk/objc/native/src/objc_video_track_source.h" namespace webrtc { @@ -24,8 +25,7 @@ rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> ObjCToNativeVideoCapturer( rtc::scoped_refptr<webrtc::ObjCVideoTrackSource> objc_video_track_source( new rtc::RefCountedObject<webrtc::ObjCVideoTrackSource>(adapter)); rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> video_source = - webrtc::VideoTrackSourceProxy::Create( - signaling_thread, worker_thread, objc_video_track_source); + webrtc::CreateVideoTrackSourceProxy(signaling_thread, worker_thread, objc_video_track_source); objc_video_capturer.delegate = adapter; diff --git a/sdk/objc/native/src/objc_video_encoder_factory.mm b/sdk/objc/native/src/objc_video_encoder_factory.mm index e51fc9d319..b66554b1a4 100644 --- a/sdk/objc/native/src/objc_video_encoder_factory.mm +++ b/sdk/objc/native/src/objc_video_encoder_factory.mm @@ -48,21 +48,24 @@ class ObjCVideoEncoder : public VideoEncoder { } int32_t RegisterEncodeCompleteCallback(EncodedImageCallback *callback) override { - [encoder_ setCallback:^BOOL(RTC_OBJC_TYPE(RTCEncodedImage) * _Nonnull frame, - id<RTC_OBJC_TYPE(RTCCodecSpecificInfo)> _Nonnull info) { - EncodedImage encodedImage = [frame nativeEncodedImage]; - - // Handle types that can be converted into one of CodecSpecificInfo's hard coded cases. - CodecSpecificInfo codecSpecificInfo; - if ([info isKindOfClass:[RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) class]]) { - codecSpecificInfo = - [(RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) *)info nativeCodecSpecificInfo]; - } - - EncodedImageCallback::Result res = callback->OnEncodedImage(encodedImage, &codecSpecificInfo); - return res.error == EncodedImageCallback::Result::OK; - }]; - + if (callback) { + [encoder_ setCallback:^BOOL(RTC_OBJC_TYPE(RTCEncodedImage) * _Nonnull frame, + id<RTC_OBJC_TYPE(RTCCodecSpecificInfo)> _Nonnull info) { + EncodedImage encodedImage = [frame nativeEncodedImage]; + + // Handle types that can be converted into one of CodecSpecificInfo's hard coded cases. + CodecSpecificInfo codecSpecificInfo; + if ([info isKindOfClass:[RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) class]]) { + codecSpecificInfo = + [(RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) *)info nativeCodecSpecificInfo]; + } + + EncodedImageCallback::Result res = callback->OnEncodedImage(encodedImage, &codecSpecificInfo); + return res.error == EncodedImageCallback::Result::OK; + }]; + } else { + [encoder_ setCallback:nil]; + } return WEBRTC_VIDEO_CODEC_OK; } @@ -95,6 +98,8 @@ class ObjCVideoEncoder : public VideoEncoder { info.scaling_settings = qp_thresholds ? ScalingSettings(qp_thresholds.low, qp_thresholds.high) : ScalingSettings::kOff; + info.requested_resolution_alignment = encoder_.resolutionAlignment > 0 ?: 1; + info.apply_alignment_to_all_simulcast_layers = encoder_.applyAlignmentToAllSimulcastLayers; info.is_hardware_accelerated = true; info.has_internal_source = false; return info; |