diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index dd6247a1e2..e7ec3e3614 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -1013,6 +1013,9 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCRtpSender+Private.h", "objc/api/peerconnection/RTCRtpSender.h", "objc/api/peerconnection/RTCRtpSender.mm", + "objc/api/peerconnection/RTCRtpSource+Private.h", + "objc/api/peerconnection/RTCRtpSource.h", + "objc/api/peerconnection/RTCRtpSource.mm", "objc/api/peerconnection/RTCRtpTransceiver+Private.h", "objc/api/peerconnection/RTCRtpTransceiver.h", "objc/api/peerconnection/RTCRtpTransceiver.mm", @@ -1071,6 +1074,7 @@ if (is_ios || is_mac) { "../api/rtc_event_log:rtc_event_log_factory", "../api/task_queue:default_task_queue_factory", "../api/transport:field_trial_based_config", + "../api/transport/rtp:rtp_source", "../api/video:video_frame", "../api/video:video_rtp_headers", "../api/video_codecs:video_codecs_api", @@ -1321,6 +1325,7 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h", "objc/api/peerconnection/RTCRtpParameters.h", "objc/api/peerconnection/RTCRtpReceiver.h", + "objc/api/peerconnection/RTCRtpSource.h", "objc/api/peerconnection/RTCRtpSender.h", "objc/api/peerconnection/RTCRtpTransceiver.h", "objc/api/peerconnection/RTCDtmfSender.h", @@ -1439,6 +1444,7 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCRtpParameters.h", "objc/api/peerconnection/RTCRtpReceiver.h", "objc/api/peerconnection/RTCRtpSender.h", + "objc/api/peerconnection/RTCRtpSource.h", "objc/api/peerconnection/RTCRtpTransceiver.h", "objc/api/peerconnection/RTCSSLAdapter.h", "objc/api/peerconnection/RTCSessionDescription.h", diff --git a/sdk/objc/api/peerconnection/RTCRtpReceiver.h b/sdk/objc/api/peerconnection/RTCRtpReceiver.h index 1e407fd71b..d93330fb93 100644 --- a/sdk/objc/api/peerconnection/RTCRtpReceiver.h +++ b/sdk/objc/api/peerconnection/RTCRtpReceiver.h @@ -25,6 +25,7 @@ typedef NS_ENUM(NSInteger, RTCRtpMediaType) { }; @class RTC_OBJC_TYPE(RTCRtpReceiver); +@class RTC_OBJC_TYPE(RTCRtpSource); RTC_OBJC_EXPORT @protocol RTC_OBJC_TYPE @@ -71,6 +72,13 @@ RTC_OBJC_EXPORT */ @property(nonatomic, readonly, nullable) RTC_OBJC_TYPE(RTCMediaStreamTrack) * track; +/** +Returns an array that contains an object for each unique SSRC (synchronization source) identifier +and for each unique CSRC (contributing source) received by the current RTCRtpReceiver in the last +ten seconds. +*/ +@property(nonatomic, readonly) NSArray *sources; + /** The delegate for this RtpReceiver. */ @property(nonatomic, weak) id delegate; diff --git a/sdk/objc/api/peerconnection/RTCRtpReceiver.mm b/sdk/objc/api/peerconnection/RTCRtpReceiver.mm index 60af86ac1b..d54efc9d02 100644 --- a/sdk/objc/api/peerconnection/RTCRtpReceiver.mm +++ b/sdk/objc/api/peerconnection/RTCRtpReceiver.mm @@ -13,6 +13,7 @@ #import "RTCMediaStreamTrack+Private.h" #import "RTCRtpParameters+Private.h" #import "RTCRtpReceiver+Native.h" +#import "RTCRtpSource+Private.h" #import "base/RTCLogging.h" #import "helpers/NSString+StdString.h" @@ -67,6 +68,16 @@ void RtpReceiverDelegateAdapter::OnFirstPacketReceived( stringWithFormat:@"RTC_OBJC_TYPE(RTCRtpReceiver) {\n receiverId: %@\n}", self.receiverId]; } +- (NSArray *)sources { + std::vector nativeSources = _nativeRtpReceiver->GetSources(); + NSMutableArray *result = + [[NSMutableArray alloc] initWithCapacity:nativeSources.size()]; + for (auto nativeSource : nativeSources) { + [result addObject:[[RTC_OBJC_TYPE(RTCRtpSource) alloc] initWithNativeRtpSource:nativeSource]]; + } + return result; +} + - (void)dealloc { if (_nativeRtpReceiver) { _nativeRtpReceiver->SetObserver(nullptr); diff --git a/sdk/objc/api/peerconnection/RTCRtpSource+Private.h b/sdk/objc/api/peerconnection/RTCRtpSource+Private.h new file mode 100644 index 0000000000..8b5137def3 --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpSource+Private.h @@ -0,0 +1,26 @@ +/* + * Copyright 2024 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. + */ + +#import "RTCRtpSource.h" + +#include "api/transport/rtp/rtp_source.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RTC_OBJC_TYPE (RTCRtpSource) +() + + /** Initialize an RTCRtpSource with a native RtpSource. */ + - (instancetype)initWithNativeRtpSource + : (const webrtc::RtpSource&)nativeRtpSource NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/objc/api/peerconnection/RTCRtpSource.h b/sdk/objc/api/peerconnection/RTCRtpSource.h new file mode 100644 index 0000000000..10e1cb04f2 --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpSource.h @@ -0,0 +1,65 @@ +/* + * Copyright 2024 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. + */ + +#import + +#import "RTCMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Represents the source type of received media. */ +typedef NS_ENUM(NSInteger, RTCRtpSourceType) { + RTCRtpSourceTypeSSRC, + RTCRtpSourceTypeCSRC, +}; + +@class RTC_OBJC_TYPE(RTCRtpSource); + +RTC_OBJC_EXPORT +@protocol RTC_OBJC_TYPE +(RTCRtpSource) + + /** + A positive integer value specifying the CSRC identifier of the contributing source or SSRC + identifier of the synchronization source. This uniquely identifies the source of the particular + stream RTP packets. */ + @property(nonatomic, readonly) uint32_t sourceId; + +@property(nonatomic, readonly) RTCRtpSourceType sourceType; + +/** +A floating-point value between 0.0 and 1.0 specifying the audio level contained in the last RTP +packet played from the contributing source. +*/ +@property(nonatomic, readonly, nullable) NSNumber *audioLevel; + +/** +A timestamp indicating the most recent time at which a frame originating from this source was +delivered to the receiver's track +*/ +@property(nonatomic, readonly) CFTimeInterval timestampUs; + +/** +The RTP timestamp of the media. This source-generated timestamp indicates the time at which the +media in this packet, scheduled for play out at the time indicated by timestamp, was initially +sampled or generated. It may be useful for sequencing and synchronization purposes. +*/ +@property(nonatomic, readonly) uint32_t rtpTimestamp; + +@end + +RTC_OBJC_EXPORT +@interface RTC_OBJC_TYPE (RTCRtpSource) : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/objc/api/peerconnection/RTCRtpSource.mm b/sdk/objc/api/peerconnection/RTCRtpSource.mm new file mode 100644 index 0000000000..aa5d6c2f4b --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpSource.mm @@ -0,0 +1,92 @@ +/* + * Copyright 2024 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. + */ + +#import "RTCRtpSource.h" +#import "RTCRtpSource+Private.h" + +#import "base/RTCLogging.h" +#import "helpers/NSString+StdString.h" + +#include +#include "api/rtp_parameters.h" +#include "api/scoped_refptr.h" +#include "api/transport/rtp/rtp_source.h" + +@implementation RTC_OBJC_TYPE (RTCRtpSource) { + std::optional _nativeRtpSource; +} + +- (uint32_t)sourceId { + return _nativeRtpSource.value().source_id(); +} + +- (CFTimeInterval)timestampUs { + return _nativeRtpSource.value().timestamp().us(); +} + +- (uint32_t)rtpTimestamp { + return _nativeRtpSource.value().rtp_timestamp(); +} + +- (RTCRtpSourceType)sourceType { + return [RTC_OBJC_TYPE(RTCRtpSource) + rtpSourceTypeForNativeRtpSourceType:_nativeRtpSource.value().source_type()]; +} + +- (NSNumber *)audioLevel { + absl::optional level = _nativeRtpSource.value().audio_level(); + if (!level.has_value()) { + return nil; + } + // Converted according to equation defined here: + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpcontributingsource-audiolevel + uint8_t rfcLevel = level.value(); + if (rfcLevel > 127u) { + rfcLevel = 127u; + } + if (rfcLevel == 127u) { + return @(0.0); + } + return @(std::pow(10.0, -(double)rfcLevel / 20.0)); +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"RTC_OBJC_TYPE(RTCRtpSource) {\n sourceId: %d, sourceType: %@\n}", + self.sourceId, + [RTC_OBJC_TYPE(RTCRtpSource) stringForRtpSourceType:self.sourceType]]; +} + +- (instancetype)initWithNativeRtpSource:(const webrtc::RtpSource &)nativeRtpSource { + if (self = [super init]) { + _nativeRtpSource = nativeRtpSource; + } + return self; +} + ++ (RTCRtpSourceType)rtpSourceTypeForNativeRtpSourceType:(webrtc::RtpSourceType)nativeRtpSourceType { + switch (nativeRtpSourceType) { + case webrtc::RtpSourceType::SSRC: + return RTCRtpSourceTypeSSRC; + case webrtc::RtpSourceType::CSRC: + return RTCRtpSourceTypeCSRC; + } +} + ++ (NSString *)stringForRtpSourceType:(RTCRtpSourceType)mediaType { + switch (mediaType) { + case RTCRtpSourceTypeSSRC: + return @"SSRC"; + case RTCRtpSourceTypeCSRC: + return @"CSRC"; + } +} + +@end