diff --git a/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/MutliCamera/MutliCamera.m b/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/MutliCamera/MutliCamera.m
index 0f62f1bf5..11ad9c66b 100644
--- a/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/MutliCamera/MutliCamera.m
+++ b/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/MutliCamera/MutliCamera.m
@@ -184,13 +184,15 @@ - (void)viewDidDisappear:(BOOL)animated {
[self.agoraKit disableVideo];
[self.agoraKit stopPreview];
[self.agoraKit leaveChannel:nil];
- if (self.isOpenCamera) {
- [self.agoraKit stopCameraCapture:(AgoraVideoSourceTypeScreenSecondary)];
- NSString *channelName = [self.configs objectForKey:@"channelName"];
- AgoraRtcConnection * connection = [[AgoraRtcConnection alloc] initWithChannelId:channelName localUid:self.mutliCameraUid];
- [self.agoraKit leaveChannelEx:connection leaveChannelBlock:nil];
- }
- [AgoraRtcEngineKit destroy];
+ dispatch_async(dispatch_get_global_queue(0, 0), ^{
+ if (self.isOpenCamera) {
+ [self.agoraKit stopCameraCapture:(AgoraVideoSourceTypeScreenSecondary)];
+ NSString *channelName = [self.configs objectForKey:@"channelName"];
+ AgoraRtcConnection * connection = [[AgoraRtcConnection alloc] initWithChannelId:channelName localUid:self.mutliCameraUid];
+ [self.agoraKit leaveChannelEx:connection leaveChannelBlock:nil];
+ }
+ [AgoraRtcEngineKit destroy];
+ });
}
/// callback when error occured for agora sdk, you are recommended to display the error descriptions on demand
diff --git a/iOS/APIExample/APIExample/Examples/Advanced/AudioMixing/AudioMixing.swift b/iOS/APIExample/APIExample/Examples/Advanced/AudioMixing/AudioMixing.swift
index 4c1ef8e92..79cf47a1b 100644
--- a/iOS/APIExample/APIExample/Examples/Advanced/AudioMixing/AudioMixing.swift
+++ b/iOS/APIExample/APIExample/Examples/Advanced/AudioMixing/AudioMixing.swift
@@ -156,7 +156,8 @@ class AudioMixingMain: BaseViewController {
let result = self.agoraKit.joinChannel(byToken: token,
channelId: channelName,
info: nil,
- uid: 0) {[unowned self] (channel, uid, elapsed) -> Void in
+ uid: 0) { [weak self] (channel, uid, elapsed) -> Void in
+ guard let self = self else { return }
self.isJoined = true
LogUtils.log(message: "Join \(channel) with uid \(uid) elapsed \(elapsed)ms", level: .info)
diff --git a/iOS/APIExample/APIExample/Examples/Advanced/AuidoRouterPlayer/AuidoRouterPlayer.swift b/iOS/APIExample/APIExample/Examples/Advanced/AuidoRouterPlayer/AuidoRouterPlayer.swift
index bcb439b8e..ee3db9c51 100644
--- a/iOS/APIExample/APIExample/Examples/Advanced/AuidoRouterPlayer/AuidoRouterPlayer.swift
+++ b/iOS/APIExample/APIExample/Examples/Advanced/AuidoRouterPlayer/AuidoRouterPlayer.swift
@@ -123,7 +123,6 @@ class AuidoRouterPlayerEntry: UIViewController {
class AuidoRouterPlayerMain: BaseViewController {
var localVideo = Bundle.loadVideoView(type: .local, audioOnly: false)
- var remoteVideo = Bundle.loadVideoView(type: .remote, audioOnly: false)
@IBOutlet weak var playerView: UIView!
@IBOutlet weak var speakerSwitch: UISwitch!
@IBOutlet weak var container: AGEVideoContainer!
@@ -161,8 +160,7 @@ class AuidoRouterPlayerMain: BaseViewController {
super.viewDidLoad()
// layout render view
localVideo.setPlaceholder(text: "Local Host".localized)
- remoteVideo.setPlaceholder(text: "Remote Host".localized)
- container.layoutStream(views: [localVideo, remoteVideo])
+ container.layoutStream(views: [localVideo])
// set up agora instance when view loaded
let config = AgoraRtcEngineConfig()
@@ -216,6 +214,8 @@ class AuidoRouterPlayerMain: BaseViewController {
let option = AgoraRtcChannelMediaOptions()
option.publishCameraTrack = GlobalSettings.shared.getUserRole() == .broadcaster
option.publishMicrophoneTrack = GlobalSettings.shared.getUserRole() == .broadcaster
+ option.autoSubscribeVideo = false
+ option.autoSubscribeAudio = false
option.clientRoleType = GlobalSettings.shared.getUserRole()
NetworkManager.shared.generateToken(channelName: channelName, success: { token in
let result = self.agoraKit.joinChannel(byToken: token, channelId: channelName, uid: 0, mediaOptions: option)
@@ -318,15 +318,6 @@ extension AuidoRouterPlayerMain: AgoraRtcEngineDelegate {
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
LogUtils.log(message: "remote user join: \(uid) \(elapsed)ms", level: .info)
- // Only one remote video view is available for this
- // tutorial. Here we check if there exists a surface
- // view tagged as this uid.
- let videoCanvas = AgoraRtcVideoCanvas()
- videoCanvas.uid = uid
- // the view to be binded
- videoCanvas.view = remoteVideo.videoView
- videoCanvas.renderMode = .hidden
- agoraKit.setupRemoteVideo(videoCanvas)
}
/// callback when a remote user is leaving the channel,
@@ -336,16 +327,6 @@ extension AuidoRouterPlayerMain: AgoraRtcEngineDelegate {
/// become an audience in live broadcasting profile
func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) {
LogUtils.log(message: "remote user left: \(uid) reason \(reason)", level: .info)
-
- // to unlink your view from sdk, so that your view reference will be released
- // note the video will stay at its last frame, to completely remove it
- // you will need to remove the EAGL sublayer from your binded view
- let videoCanvas = AgoraRtcVideoCanvas()
- videoCanvas.uid = uid
- // the view to be binded
- videoCanvas.view = nil
- videoCanvas.renderMode = .hidden
- agoraKit.setupRemoteVideo(videoCanvas)
}
/// Reports the statistics of the current call.
@@ -360,16 +341,4 @@ extension AuidoRouterPlayerMain: AgoraRtcEngineDelegate {
func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) {
localVideo.statsInfo?.updateLocalAudioStats(stats)
}
-
- /// Reports the statistics of the video stream from each remote user/host.
- /// @param stats stats struct
- func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) {
- remoteVideo.statsInfo?.updateVideoStats(stats)
- }
-
- /// Reports the statistics of the audio stream from each remote user/host.
- /// @param stats stats struct for current call statistics
- func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) {
- remoteVideo.statsInfo?.updateAudioStats(stats)
- }
}
diff --git a/iOS/APIExample/APIExample/Examples/Advanced/StreamEncryption/StreamEncryption.swift b/iOS/APIExample/APIExample/Examples/Advanced/StreamEncryption/StreamEncryption.swift
index e3b3aeec5..61287da6d 100644
--- a/iOS/APIExample/APIExample/Examples/Advanced/StreamEncryption/StreamEncryption.swift
+++ b/iOS/APIExample/APIExample/Examples/Advanced/StreamEncryption/StreamEncryption.swift
@@ -187,7 +187,8 @@ class StreamEncryptionMain: BaseViewController {
// Salt string should be the output of the following command:
// openssl rand -base64 32
let saltBase64String = "NiIeJ08AbtcQVjvV+oOEvF/4Dz5dy1CIwa805C8J2w0="
- return Data(base64Encoded: saltBase64String.data(using: .utf8)!)!
+ let data = Data(base64Encoded: saltBase64String.data(using: .utf8) ?? Data())
+ return data ?? Data()
}
override func willMove(toParent parent: UIViewController?) {
diff --git a/iOS/APIExample/APIExample/Info.plist b/iOS/APIExample/APIExample/Info.plist
index 448b7a5ce..989504b53 100644
--- a/iOS/APIExample/APIExample/Info.plist
+++ b/iOS/APIExample/APIExample/Info.plist
@@ -43,8 +43,10 @@
Request Camera Access
NSMicrophoneUsageDescription
Request Mic Access
- UIFileSharingEnabled
-
+ UIBackgroundModes
+
+ audio
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
diff --git a/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.h b/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.h
index 2b21b424a..ef100b254 100755
--- a/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.h
+++ b/windows/APIExample/APIExample/Advanced/OriginalVideo/CAgoraOriginalVideoDlg.h
@@ -49,7 +49,13 @@ class CGrayVideoProcFrameObserver :
virtual bool onMediaPlayerVideoFrame(VideoFrame& videoFrame, int mediaPlayerId) override { return true; }
virtual bool onPreEncodeVideoFrame(agora::rtc::VIDEO_SOURCE_TYPE type, VideoFrame& videoFrame) { return true; }
+ virtual VIDEO_FRAME_PROCESS_MODE getVideoFrameProcessMode() {
+ return VIDEO_FRAME_PROCESS_MODE::PROCESS_MODE_READ_WRITE;
+ }
+ virtual uint32_t getObservedFramePosition() {
+ return agora::media::base::POSITION_POST_CAPTURER;
+ }
};
@@ -104,6 +110,13 @@ class CAverageFilterVideoProcFrameObserver :
virtual bool onMediaPlayerVideoFrame(VideoFrame& videoFrame, int mediaPlayerId) override { return true; }
virtual bool onPreEncodeVideoFrame(agora::rtc::VIDEO_SOURCE_TYPE type, VideoFrame& videoFrame) { return true; }
+ virtual VIDEO_FRAME_PROCESS_MODE getVideoFrameProcessMode() {
+ return VIDEO_FRAME_PROCESS_MODE::PROCESS_MODE_READ_WRITE;
+ }
+
+ virtual uint32_t getObservedFramePosition() {
+ return agora::media::base::POSITION_POST_CAPTURER;
+ }
};