Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions Documentation/iOSInstallation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ Set it to '12.0' or above or you'll get an error when running `pod install`.
platform :ios, '12.0'
```

## Pod source

The native module depends on the `LiveKitWebRTC` pod, which is published on the
CocoaPods trunk, so no extra `source` lines are needed in your `Podfile`.

If a `LiveKitWebRTC` version has not reached the trunk CDN yet, the
[livekit/podspecs](https://github.com/livekit/podspecs) repository serves the
same podspecs and can be added as an additional source:

```ruby
source 'https://cdn.cocoapods.org/'
source 'https://github.com/livekit/podspecs.git'
```

## Declaring Permissions

Navigate to `<ProjectFolder>/ios/<ProjectName>/` and edit `Info.plist`, add the following lines.
Expand All @@ -29,17 +43,17 @@ Navigate to `<ProjectFolder>/ios/<ProjectName>/` and edit `Info.plist`, add the
## CallKit

If your app uses a CallKit integration to handle incoming calls, then your
CXProviderDelegate should call through to `RTCAudioSession.sharedInstance.audioSessionDidActivate/Deactivate` accordingly.
CXProviderDelegate should call through to `LKRTCAudioSession.sharedInstance.audioSessionDidActivate/Deactivate` accordingly.

```
#import <WebRTC/RTCAudioSession.h>
#import <LiveKitWebRTC/RTCAudioSession.h>

- (void) provider:(CXProvider *) provider didActivateAudioSession:(AVAudioSession *) audioSession {
[[RTCAudioSession sharedInstance] audioSessionDidActivate:[AVAudioSession sharedInstance]];
[[LKRTCAudioSession sharedInstance] audioSessionDidActivate:[AVAudioSession sharedInstance]];
}

- (void) provider:(CXProvider *) provider didDeactivateAudioSession:(AVAudioSession *) audioSession {
[[RTCAudioSession sharedInstance] audioSessionDidDeactivate:[AVAudioSession sharedInstance]];
[[LKRTCAudioSession sharedInstance] audioSessionDidDeactivate:[AVAudioSession sharedInstance]];
}
```

Expand Down
14 changes: 14 additions & 0 deletions Documentation/tvOSInstallation.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ Older versions of tvOS don't support WebRTC.
```
platform :tvos, '16.0'
```

## Pod source

The native module depends on the `LiveKitWebRTC` pod, which is published on the
CocoaPods trunk, so no extra `source` lines are needed in your `Podfile`.

If a `LiveKitWebRTC` version has not reached the trunk CDN yet, the
[livekit/podspecs](https://github.com/livekit/podspecs) repository serves the
same podspecs and can be added as an additional source:

```ruby
source 'https://cdn.cocoapods.org/'
source 'https://github.com/livekit/podspecs.git'
```
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ android {

dependencies {
implementation "com.facebook.react:react-android:+"
api 'io.github.webrtc-sdk:android-prefixed:144.7559.14'
api 'io.github.webrtc-sdk:android-prefixed:144.7559.15'
implementation "androidx.core:core:1.7.0"
}
4 changes: 2 additions & 2 deletions ios/RCTWebRTC/AudioDeviceModuleObserver.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#import <WebRTC/WebRTC.h>
#import <LiveKitWebRTC/LiveKitWebRTC.h>
#import "WebRTCModule.h"

NS_ASSUME_NONNULL_BEGIN

@interface AudioDeviceModuleObserver : NSObject<RTCAudioDeviceModuleDelegate>
@interface AudioDeviceModuleObserver : NSObject<LKRTCAudioDeviceModuleDelegate>

- (instancetype)initWithWebRTCModule:(WebRTCModule *)module;

Expand Down
40 changes: 20 additions & 20 deletions ios/RCTWebRTC/AudioDeviceModuleObserver.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ @interface AudioDeviceModuleObserver ()
@property(nonatomic, assign) NSInteger awaitingRequestId;

// Whether the native auto-config path currently holds an
// RTCAudioSession activation it must later release. RTCAudioSession refcounts
// LKRTCAudioSession activation it must later release. LKRTCAudioSession refcounts
// setActive, so a mismatched activate/release leaves the OS session stuck active.
// Touched only on the serial worker thread; atomic as insurance against future
// cross-thread reads.
Expand Down Expand Up @@ -158,11 +158,11 @@ - (NSInteger)sendEventAndWaitWithName:(NSString *)eventName
return resultBlock();
}

#pragma mark - RTCAudioDeviceModuleDelegate
#pragma mark - LKRTCAudioDeviceModuleDelegate

- (void)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
didReceiveSpeechActivityEvent:(RTCSpeechActivityEvent)speechActivityEvent {
NSString *eventType = speechActivityEvent == RTCSpeechActivityEventStarted ? @"started" : @"ended";
- (void)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule
didReceiveSpeechActivityEvent:(LKRTCSpeechActivityEvent)speechActivityEvent {
NSString *eventType = speechActivityEvent == LKRTCSpeechActivityEventStarted ? @"started" : @"ended";

[self.module sendEventWithName:kEventAudioDeviceModuleSpeechActivity
body:@{
Expand All @@ -172,7 +172,7 @@ - (void)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
RCTLog(@"[AudioDeviceModuleObserver] Speech activity event: %@", eventType);
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule didCreateEngine:(AVAudioEngine *)engine {
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule didCreateEngine:(AVAudioEngine *)engine {
BOOL isActive = self.isEngineCreatedActive;

if (isActive) {
Expand All @@ -193,7 +193,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule didCrea
return result;
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule
willEnableEngine:(AVAudioEngine *)engine
isPlayoutEnabled:(BOOL)isPlayoutEnabled
isRecordingEnabled:(BOOL)isRecordingEnabled {
Expand Down Expand Up @@ -234,7 +234,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
return result;
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule
willStartEngine:(AVAudioEngine *)engine
isPlayoutEnabled:(BOOL)isPlayoutEnabled
isRecordingEnabled:(BOOL)isRecordingEnabled {
Expand Down Expand Up @@ -263,7 +263,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
return result;
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule
didStopEngine:(AVAudioEngine *)engine
isPlayoutEnabled:(BOOL)isPlayoutEnabled
isRecordingEnabled:(BOOL)isRecordingEnabled {
Expand Down Expand Up @@ -292,7 +292,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
return result;
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule
didDisableEngine:(AVAudioEngine *)engine
isPlayoutEnabled:(BOOL)isPlayoutEnabled
isRecordingEnabled:(BOOL)isRecordingEnabled {
Expand Down Expand Up @@ -344,7 +344,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
return result;
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule willReleaseEngine:(AVAudioEngine *)engine {
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule willReleaseEngine:(AVAudioEngine *)engine {
BOOL isActive = self.isWillReleaseEngineActive;

if (isActive) {
Expand All @@ -365,7 +365,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule willRel
return result;
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule
engine:(AVAudioEngine *)engine
configureInputFromSource:(nullable AVAudioNode *)source
toDestination:(AVAudioNode *)destination
Expand All @@ -375,7 +375,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
return 0;
}

- (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
- (NSInteger)audioDeviceModule:(LKRTCAudioDeviceModule *)audioDeviceModule
engine:(AVAudioEngine *)engine
configureOutputFromSource:(AVAudioNode *)source
toDestination:(nullable AVAudioNode *)destination
Expand All @@ -385,7 +385,7 @@ - (NSInteger)audioDeviceModule:(RTCAudioDeviceModule *)audioDeviceModule
return 0;
}

- (void)audioDeviceModuleDidUpdateDevices:(RTCAudioDeviceModule *)audioDeviceModule {
- (void)audioDeviceModuleDidUpdateDevices:(LKRTCAudioDeviceModule *)audioDeviceModule {
[self.module sendEventWithName:kEventAudioDeviceModuleDevicesUpdated body:@{}];

RCTLog(@"[AudioDeviceModuleObserver] Devices updated");
Expand Down Expand Up @@ -470,7 +470,7 @@ - (void)resolveWillReleaseEngineWithRequestId:(NSInteger)requestId result:(NSInt
// - optionally deactivates on stop,
// - returns a non-zero error code on failure so libwebrtc rolls the operation back.
//
// Activation is decided against RTCAudioSession's own state rather than a mirror
// Activation is decided against LKRTCAudioSession's own state rather than a mirror
// of past engine states, so a policy re-push mid-call (setupIOSAudioManagement
// called again), a path switch, or an interruption cannot desync it:
// - session already active (previous hold, custom JS path, or the app) ->
Expand All @@ -489,7 +489,7 @@ - (NSInteger)applyAutomaticAudioSessionConfigForPlayout:(BOOL)isPlayoutEnabled r
// the native path is disarmed.
if (!nowActive && self.autoSessionHoldsActivation) {
os_log(ADMObserverLog(), "Native auto-config: releasing orphaned activation hold");
RTCAudioSession *session = [RTCAudioSession sharedInstance];
LKRTCAudioSession *session = [LKRTCAudioSession sharedInstance];
[session lockForConfiguration];
NSError *releaseError = nil;
[session setActive:NO error:&releaseError];
Expand All @@ -504,7 +504,7 @@ - (NSInteger)applyAutomaticAudioSessionConfigForPlayout:(BOOL)isPlayoutEnabled r
return 0;
}

RTCAudioSession *session = [RTCAudioSession sharedInstance];
LKRTCAudioSession *session = [LKRTCAudioSession sharedInstance];
[session lockForConfiguration];

NSError *error = nil;
Expand All @@ -513,7 +513,7 @@ - (NSInteger)applyAutomaticAudioSessionConfigForPlayout:(BOOL)isPlayoutEnabled r
os_log(ADMObserverLog(), "Native auto-config: deactivating audio session");
NSError *deactivateError = nil;
[session setActive:NO error:&deactivateError];
// RTCAudioSession decrements its activation count even when the OS
// LKRTCAudioSession decrements its activation count even when the OS
// session is already inactive (e.g. an interruption cleared it) or the
// call fails, so the hold is released in every outcome.
self.autoSessionHoldsActivation = NO;
Expand All @@ -532,7 +532,7 @@ - (NSInteger)applyAutomaticAudioSessionConfigForPlayout:(BOOL)isPlayoutEnabled r
// Recording uses the duplex (playAndRecord) config, while playout-only uses
// the playback config. Both are supplied by the SDK in automaticAudioSessionConfig.
NSDictionary *cfg = isRecordingEnabled ? policy[@"recording"] : policy[@"playout"];
RTCAudioSessionConfiguration *rtcConfig = [RTCAudioSessionConfiguration webRTCConfiguration];
LKRTCAudioSessionConfiguration *rtcConfig = [LKRTCAudioSessionConfiguration webRTCConfiguration];
if (cfg[@"audioCategory"] != nil) {
rtcConfig.category = [self avAudioSessionCategoryFromString:cfg[@"audioCategory"]];
}
Expand All @@ -559,7 +559,7 @@ - (NSInteger)applyAutomaticAudioSessionConfigForPlayout:(BOOL)isPlayoutEnabled r
//
// Ordered activate-first deliberately. Releasing before
// reactivating would zero the count whenever the reactivation
// fails, and RTCAudioSession's interruption-end recovery
// fails, and LKRTCAudioSession's interruption-end recovery
// deactivates outright at count zero. A failure must leave the
// prior hold untouched for that recovery to restore it.
os_log(ADMObserverLog(), "Native auto-config: dropping extra count after reactivating");
Expand Down
4 changes: 2 additions & 2 deletions ios/RCTWebRTC/CapturerEventsDelegate.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#import <WebRTC/RTCVideoCapturer.h>
#import <LiveKitWebRTC/RTCVideoCapturer.h>

NS_ASSUME_NONNULL_BEGIN

@protocol CapturerEventsDelegate

/** Called when the capturer is ended and in an irrecoverable state. */
- (void)capturerDidEnd:(RTCVideoCapturer *)capturer;
- (void)capturerDidEnd:(LKRTCVideoCapturer *)capturer;

@end

Expand Down
8 changes: 4 additions & 4 deletions ios/RCTWebRTC/DataChannelWrapper.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#import <Foundation/Foundation.h>
#import <WebRTC/RTCDataChannel.h>
#import <LiveKitWebRTC/RTCDataChannel.h>

NS_ASSUME_NONNULL_BEGIN

Expand All @@ -8,17 +8,17 @@ NS_ASSUME_NONNULL_BEGIN
@protocol DataChannelWrapperDelegate<NSObject>

- (void)dataChannelDidChangeState:(DataChannelWrapper *)dataChannelWrapper;
- (void)dataChannel:(DataChannelWrapper *)dataChannelWrapper didReceiveMessageWithBuffer:(RTCDataBuffer *)buffer;
- (void)dataChannel:(DataChannelWrapper *)dataChannelWrapper didReceiveMessageWithBuffer:(LKRTCDataBuffer *)buffer;
- (void)dataChannel:(DataChannelWrapper *)dataChannelWrapper didChangeBufferedAmount:(uint64_t)amount;

@end

@interface DataChannelWrapper : NSObject

- (instancetype)initWithChannel:(RTCDataChannel *)channel reactTag:(NSString *)tag;
- (instancetype)initWithChannel:(LKRTCDataChannel *)channel reactTag:(NSString *)tag;

@property(nonatomic, nonnull, copy) NSNumber *pcId;
@property(nonatomic, nonnull, readonly) RTCDataChannel *channel;
@property(nonatomic, nonnull, readonly) LKRTCDataChannel *channel;
@property(nonatomic, nonnull, readonly) NSString *reactTag;
@property(nonatomic, nullable, weak) id<DataChannelWrapperDelegate> delegate;

Expand Down
13 changes: 7 additions & 6 deletions ios/RCTWebRTC/DataChannelWrapper.m
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

#import "DataChannelWrapper.h"

#import <WebRTC/RTCDataChannel.h>
#import <LiveKitWebRTC/RTCDataChannel.h>

@interface DataChannelWrapper ()<RTCDataChannelDelegate>
@interface DataChannelWrapper ()<LKRTCDataChannelDelegate>
@end

@implementation DataChannelWrapper

- (instancetype)initWithChannel:(RTCDataChannel *)channel reactTag:(NSString *)tag {
- (instancetype)initWithChannel:(LKRTCDataChannel *)channel reactTag:(NSString *)tag {
self = [super init];
if (self) {
_channel = channel;
Expand All @@ -21,19 +21,20 @@ - (instancetype)initWithChannel:(RTCDataChannel *)channel reactTag:(NSString *)t
return self;
}

- (void)dataChannel:(nonnull RTCDataChannel *)dataChannel didReceiveMessageWithBuffer:(nonnull RTCDataBuffer *)buffer {
- (void)dataChannel:(nonnull LKRTCDataChannel *)dataChannel
didReceiveMessageWithBuffer:(nonnull LKRTCDataBuffer *)buffer {
if (_delegate) {
[_delegate dataChannel:self didReceiveMessageWithBuffer:buffer];
}
}

- (void)dataChannelDidChangeState:(nonnull RTCDataChannel *)dataChannel {
- (void)dataChannelDidChangeState:(nonnull LKRTCDataChannel *)dataChannel {
if (_delegate) {
[_delegate dataChannelDidChangeState:self];
}
}

- (void)dataChannel:(nonnull RTCDataChannel *)dataChannel didChangeBufferedAmount:(uint64_t)amount {
- (void)dataChannel:(nonnull LKRTCDataChannel *)dataChannel didChangeBufferedAmount:(uint64_t)amount {
if (_delegate) {
[_delegate dataChannel:self didChangeBufferedAmount:amount];
}
Expand Down
4 changes: 2 additions & 2 deletions ios/RCTWebRTC/I420Converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
//

#import <Accelerate/Accelerate.h>
#import <LiveKitWebRTC/LiveKitWebRTC.h>
#import <UIKit/UIKit.h>
#import <WebRTC/WebRTC.h>

@interface I420Converter : NSObject

- (vImage_Error)prepareForAccelerateConversion;
- (void)unprepareForAccelerateConversion;
- (CVPixelBufferRef)convertI420ToPixelBuffer:(RTCI420Buffer *)buffer;
- (CVPixelBufferRef)convertI420ToPixelBuffer:(LKRTCI420Buffer *)buffer;
- (void)createPixelBufferPoolWithWidth:(size_t)width height:(size_t)height;

@end
4 changes: 2 additions & 2 deletions ios/RCTWebRTC/I420Converter.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ - (void)createPixelBufferPoolWithWidth:(size_t)width height:(size_t)height {
}
}

- (CVPixelBufferRef)convertI420ToPixelBuffer:(RTCI420Buffer *)buffer {
- (CVPixelBufferRef)convertI420ToPixelBuffer:(LKRTCI420Buffer *)buffer {
if (_conversionInfo == nil) {
NSLog(@"%@: not prepared", NSStringFromSelector(_cmd));
return NULL;
Expand Down Expand Up @@ -106,7 +106,7 @@ - (CVPixelBufferRef)convertI420ToPixelBuffer:(RTCI420Buffer *)buffer {
return pixelBuffer;
}

- (vImage_Error)convertFrameVImageYUV:(RTCI420Buffer *)buffer toBuffer:(CVPixelBufferRef)pixelBufferRef {
- (vImage_Error)convertFrameVImageYUV:(LKRTCI420Buffer *)buffer toBuffer:(CVPixelBufferRef)pixelBufferRef {
if (pixelBufferRef == NULL) {
return kvImageInvalidParameter;
}
Expand Down
4 changes: 2 additions & 2 deletions ios/RCTWebRTC/PIPController.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#import <AVKit/AVKit.h>
#import <LiveKitWebRTC/RTCVideoTrack.h>
#import <UIKit/UIKit.h>
#import <WebRTC/RTCVideoTrack.h>

#import "RTCVideoViewManager.h"

API_AVAILABLE(ios(15.0))
@interface PIPController : NSObject<AVPictureInPictureControllerDelegate>

@property(nonatomic, weak) UIView *sourceView;
@property(nonatomic, strong) RTCVideoTrack *videoTrack;
@property(nonatomic, strong) LKRTCVideoTrack *videoTrack;

@property(nonatomic, assign) BOOL startAutomatically;
@property(nonatomic, assign) BOOL stopAutomatically;
Expand Down
2 changes: 1 addition & 1 deletion ios/RCTWebRTC/PIPController.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ - (void)addToCallViewController:(UIView *)view {
[NSLayoutConstraint activateConstraints:constraints];
}

- (void)setVideoTrack:(RTCVideoTrack *)videoTrack {
- (void)setVideoTrack:(LKRTCVideoTrack *)videoTrack {
if (_videoTrack != videoTrack) {
[_videoTrack removeRenderer:_sampleView];
}
Expand Down
Loading