mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Temp
This commit is contained in:
@@ -20,6 +20,7 @@ objc_library(
|
||||
"-DWEBRTC_IOS",
|
||||
"-DWEBRTC_MAC",
|
||||
"-DWEBRTC_POSIX",
|
||||
"-std=c++14",
|
||||
],
|
||||
includes = [
|
||||
"PublicHeaders",
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#import "components/renderer/metal/RTCMTLVideoView.h"
|
||||
#import "components/renderer/opengl/RTCEAGLVideoView.h"
|
||||
|
||||
#import "RtcConnection.h"
|
||||
|
||||
static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
|
||||
static void voipLog(NSString* format, ...) {
|
||||
@@ -38,82 +40,6 @@ static void voipLog(NSString* format, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
@interface NativePeerConnectionDelegate : NSObject <RTCPeerConnectionDelegate> {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||
void (^_didGenerateIceCandidate)(RTCIceCandidate *);
|
||||
void (^_didChangeIceState)(OngoingCallStateWebrtcCustom);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NativePeerConnectionDelegate
|
||||
|
||||
- (instancetype)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom>)queue didGenerateIceCandidate:(void (^)(RTCIceCandidate *))didGenerateIceCandidate didChangeIceState:(void (^)(OngoingCallStateWebrtcCustom))didChangeIceState {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queue = queue;
|
||||
_didGenerateIceCandidate = [didGenerateIceCandidate copy];
|
||||
_didChangeIceState = [didChangeIceState copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeSignalingState:(RTCSignalingState)stateChanged {
|
||||
switch (stateChanged) {
|
||||
case RTCSignalingStateStable:
|
||||
_didChangeIceState(OngoingCallStateConnected);
|
||||
break;
|
||||
case RTCSignalingStateHaveLocalOffer:
|
||||
_didChangeIceState(OngoingCallStateInitializing);
|
||||
break;
|
||||
case RTCSignalingStateHaveLocalPrAnswer:
|
||||
_didChangeIceState(OngoingCallStateInitializing);
|
||||
break;
|
||||
case RTCSignalingStateHaveRemoteOffer:
|
||||
_didChangeIceState(OngoingCallStateInitializing);
|
||||
break;
|
||||
case RTCSignalingStateHaveRemotePrAnswer:
|
||||
_didChangeIceState(OngoingCallStateInitializing);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
voipLog(@"didChangeSignalingState: %d", stateChanged);
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection didAddStream:(RTCMediaStream *)stream {
|
||||
voipLog(@"Added stream: %@", stream.streamId);
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveStream:(RTCMediaStream *)stream {
|
||||
}
|
||||
|
||||
- (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection {
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceConnectionState:(RTCIceConnectionState)newState {
|
||||
voipLog(@"IceConnectionState: %d", newState);
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceGatheringState:(RTCIceGatheringState)newState {
|
||||
voipLog(@"didChangeIceGatheringState: %d", newState);
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection didGenerateIceCandidate:(RTCIceCandidate *)candidate {
|
||||
[_queue dispatch:^{
|
||||
_didGenerateIceCandidate(candidate);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveIceCandidates:(NSArray<RTCIceCandidate *> *)candidates {
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
||||
didOpenDataChannel:(RTCDataChannel *)dataChannel {
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation OngoingCallConnectionDescriptionWebrtcCustom
|
||||
|
||||
- (instancetype _Nonnull)initWithConnectionId:(int64_t)connectionId ip:(NSString * _Nonnull)ip ipv6:(NSString * _Nonnull)ipv6 port:(int32_t)port peerTag:(NSData * _Nonnull)peerTag {
|
||||
@@ -136,8 +62,6 @@ static void voipLog(NSString* format, ...) {
|
||||
|
||||
bool _isOutgoing;
|
||||
void (^_sendSignalingData)(NSData * _Nonnull);
|
||||
|
||||
NativePeerConnectionDelegate *_peerConnectionDelegate;
|
||||
|
||||
OngoingCallNetworkTypeWebrtcCustom _networkType;
|
||||
NSTimeInterval _callReceiveTimeout;
|
||||
@@ -148,13 +72,11 @@ static void voipLog(NSString* format, ...) {
|
||||
OngoingCallStateWebrtcCustom _state;
|
||||
int32_t _signalBars;
|
||||
|
||||
RTCPeerConnectionFactory *_peerConnectionFactory;
|
||||
RtcConnection *_connection;
|
||||
|
||||
RTCPeerConnection *_peerConnection;
|
||||
|
||||
RTCVideoCapturer *_videoCapturer;
|
||||
RTCVideoTrack *_localVideoTrack;
|
||||
RTCVideoTrack *_remoteVideoTrack;
|
||||
//RTCVideoCapturer *_videoCapturer;
|
||||
//RTCVideoTrack *_localVideoTrack;
|
||||
//RTCVideoTrack *_remoteVideoTrack;
|
||||
|
||||
bool _receivedRemoteDescription;
|
||||
|
||||
@@ -222,54 +144,31 @@ static void voipLog(NSString* format, ...) {
|
||||
[RTCAudioSession sharedInstance].useManualAudio = true;
|
||||
[RTCAudioSession sharedInstance].isAudioEnabled = true;
|
||||
|
||||
RTCDefaultVideoDecoderFactory *decoderFactory = [[RTCDefaultVideoDecoderFactory alloc] init];
|
||||
RTCDefaultVideoEncoderFactory *encoderFactory = [[RTCDefaultVideoEncoderFactory alloc] init];
|
||||
|
||||
_peerConnectionFactory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory decoderFactory:decoderFactory];
|
||||
|
||||
NSArray<NSString *> *iceServers = @[
|
||||
@"stun:stun.l.google.com:19302"
|
||||
];
|
||||
|
||||
RTCConfiguration *config = [[RTCConfiguration alloc] init];
|
||||
config.iceServers = @[
|
||||
[[RTCIceServer alloc] initWithURLStrings:iceServers]
|
||||
];
|
||||
config.sdpSemantics = RTCSdpSemanticsUnifiedPlan;
|
||||
config.continualGatheringPolicy = RTCContinualGatheringPolicyGatherContinually;
|
||||
|
||||
RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil optionalConstraints:@{ @"DtlsSrtpKeyAgreement": kRTCMediaConstraintsValueTrue }];
|
||||
|
||||
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
||||
|
||||
_peerConnectionDelegate = [[NativePeerConnectionDelegate alloc] initWithQueue:_queue didGenerateIceCandidate:^(RTCIceCandidate *iceCandidate) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf sendCandidate:iceCandidate];
|
||||
} didChangeIceState: ^(OngoingCallStateWebrtcCustom state) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
if (strongSelf.stateChanged) {
|
||||
strongSelf.stateChanged(state);
|
||||
}
|
||||
_connection = [[RtcConnection alloc] initWithDiscoveredIceCandidate:^(NSString *sdp, int mLineIndex, NSString *sdpMid) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf sendCandidateWithSdp:sdp mLineIndex:mLineIndex sdpMid:sdpMid];
|
||||
}];
|
||||
} connectionStateChanged:^(bool isConnected) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
if (strongSelf.stateChanged) {
|
||||
strongSelf.stateChanged(isConnected ? OngoingCallStateConnected : OngoingCallStateInitializing);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
|
||||
_peerConnection = [_peerConnectionFactory peerConnectionWithConfiguration:config constraints:constraints delegate:_peerConnectionDelegate];
|
||||
//RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil optionalConstraints:@{ @"DtlsSrtpKeyAgreement": kRTCMediaConstraintsValueTrue }];
|
||||
|
||||
NSString *streamId = @"stream";
|
||||
|
||||
RTCMediaConstraints *audioConstrains = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil optionalConstraints:nil];
|
||||
|
||||
RTCAudioSource *audioSource = [_peerConnectionFactory audioSourceWithConstraints:audioConstrains];
|
||||
RTCAudioTrack * _Nonnull audioTrack = [_peerConnectionFactory audioTrackWithSource:audioSource trackId:@"audio0"];
|
||||
|
||||
[_peerConnection addTrack:audioTrack streamIds:@[streamId]];
|
||||
|
||||
RTCVideoSource *videoSource = [_peerConnectionFactory videoSource];
|
||||
/*RTCVideoSource *videoSource = [_peerConnectionFactory videoSource];
|
||||
|
||||
#if TARGET_OS_SIMULATOR
|
||||
_videoCapturer = [[RTCFileVideoCapturer alloc] initWithDelegate:videoSource];
|
||||
@@ -278,31 +177,25 @@ static void voipLog(NSString* format, ...) {
|
||||
#endif
|
||||
|
||||
_localVideoTrack = [_peerConnectionFactory videoTrackWithSource:videoSource trackId:@"video0"];
|
||||
[_peerConnection addTrack:_localVideoTrack streamIds:@[streamId]];
|
||||
[_peerConnection addTrack:_localVideoTrack streamIds:@[streamId]];*/
|
||||
|
||||
if (isOutgoing) {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = _queue;
|
||||
NSDictionary *mediaConstraints = @{
|
||||
kRTCMediaConstraintsOfferToReceiveAudio: kRTCMediaConstraintsValueTrue,
|
||||
kRTCMediaConstraintsOfferToReceiveVideo: kRTCMediaConstraintsValueTrue
|
||||
};
|
||||
|
||||
RTCMediaConstraints *connectionConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mediaConstraints optionalConstraints:nil];
|
||||
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
||||
[_peerConnection offerForConstraints:connectionConstraints completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
|
||||
[_connection getOffer:^(NSString *sdp, NSString *type) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[strongSelf->_peerConnection setLocalDescription:sdp completionHandler:^(__unused NSError * _Nullable error) {
|
||||
[strongSelf->_connection setLocalDescription:sdp type:type completion:^{
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf tryAdvertising:sdp];
|
||||
[strongSelf tryAdvertising:sdp type:type];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
@@ -318,24 +211,24 @@ static void voipLog(NSString* format, ...) {
|
||||
assert([_queue isCurrent]);
|
||||
}
|
||||
|
||||
- (void)tryAdvertising:(RTCSessionDescription *)sessionDescription {
|
||||
- (void)tryAdvertising:(NSString *)sdp type:(NSString *)type {
|
||||
if (_receivedRemoteDescription) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self sendSdp:sessionDescription];
|
||||
[self sendSdp:sdp type:type];
|
||||
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
||||
[_queue dispatchAfter:1.0 block:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf tryAdvertising:sessionDescription];
|
||||
[strongSelf tryAdvertising:sdp type:type];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)startLocalVideo {
|
||||
if (_videoCapturer == nil || ![_videoCapturer isKindOfClass:[RTCCameraVideoCapturer class]]) {
|
||||
/*if (_videoCapturer == nil || ![_videoCapturer isKindOfClass:[RTCCameraVideoCapturer class]]) {
|
||||
return;
|
||||
}
|
||||
RTCCameraVideoCapturer *cameraCapturer = (RTCCameraVideoCapturer *)_videoCapturer;
|
||||
@@ -383,7 +276,7 @@ static void voipLog(NSString* format, ...) {
|
||||
}
|
||||
|
||||
[cameraCapturer startCaptureWithDevice:frontCamera format:bestFormat fps:27 completionHandler:^(NSError * _Nonnull error) {
|
||||
}];
|
||||
}];*/
|
||||
}
|
||||
|
||||
- (bool)needRate {
|
||||
@@ -391,11 +284,11 @@ static void voipLog(NSString* format, ...) {
|
||||
}
|
||||
|
||||
- (void)stop:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion {
|
||||
if ([_videoCapturer isKindOfClass:[RTCCameraVideoCapturer class]]) {
|
||||
/*if ([_videoCapturer isKindOfClass:[RTCCameraVideoCapturer class]]) {
|
||||
RTCCameraVideoCapturer *cameraCapturer = (RTCCameraVideoCapturer *)_videoCapturer;
|
||||
[cameraCapturer stopCapture];
|
||||
}
|
||||
[_peerConnection close];
|
||||
}*/
|
||||
[_connection close];
|
||||
if (completion) {
|
||||
completion(@"", 0, 0, 0, 0);
|
||||
}
|
||||
@@ -414,30 +307,24 @@ static void voipLog(NSString* format, ...) {
|
||||
return [NSData data];
|
||||
}
|
||||
|
||||
- (void)sendSdp:(RTCSessionDescription *)rtcSdp {
|
||||
- (void)sendSdp:(NSString *)sdp type:(NSString *)type {
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
json[@"messageType"] = @"sessionDescription";
|
||||
json[@"sdp"] = rtcSdp.sdp;
|
||||
if (rtcSdp.type == RTCSdpTypeOffer) {
|
||||
json[@"type"] = @"offer";
|
||||
} else if (rtcSdp.type == RTCSdpTypePrAnswer) {
|
||||
json[@"type"] = @"prAnswer";
|
||||
} else if (rtcSdp.type == RTCSdpTypeAnswer) {
|
||||
json[@"type"] = @"answer";
|
||||
}
|
||||
json[@"sdp"] = sdp;
|
||||
json[@"type"] = type;
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
|
||||
if (data != nil) {
|
||||
_sendSignalingData(data);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendCandidate:(RTCIceCandidate *)rtcIceCandidate {
|
||||
- (void)sendCandidateWithSdp:(NSString *)sdp mLineIndex:(int)mLineIndex sdpMid:(NSString *)sdpMid {
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
json[@"messageType"] = @"iceCandidate";
|
||||
json[@"sdp"] = rtcIceCandidate.sdp;
|
||||
json[@"mLineIndex"] = @(rtcIceCandidate.sdpMLineIndex);
|
||||
if (rtcIceCandidate.sdpMid != nil) {
|
||||
json[@"sdpMid"] = rtcIceCandidate.sdpMid;
|
||||
json[@"sdp"] = sdp;
|
||||
json[@"mLineIndex"] = @(mLineIndex);
|
||||
if (sdpMid != nil) {
|
||||
json[@"sdpMid"] = sdpMid;
|
||||
}
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
|
||||
if (data != nil) {
|
||||
@@ -466,50 +353,31 @@ static void voipLog(NSString* format, ...) {
|
||||
return;
|
||||
}
|
||||
|
||||
RTCSdpType type;
|
||||
if ([typeString isEqualToString:@"offer"]) {
|
||||
type = RTCSdpTypeOffer;
|
||||
} else if ([typeString isEqualToString:@"prAnswer"]) {
|
||||
type = RTCSdpTypePrAnswer;
|
||||
} else if ([typeString isEqualToString:@"answer"]) {
|
||||
type = RTCSdpTypeAnswer;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_receivedRemoteDescription) {
|
||||
return;
|
||||
}
|
||||
_receivedRemoteDescription = true;
|
||||
|
||||
RTCSessionDescription *sessionDescription = [[RTCSessionDescription alloc] initWithType:type sdp:sdp];
|
||||
|
||||
NSDictionary *mediaConstraints = @{
|
||||
kRTCMediaConstraintsOfferToReceiveAudio: kRTCMediaConstraintsValueTrue,
|
||||
kRTCMediaConstraintsOfferToReceiveVideo: kRTCMediaConstraintsValueTrue
|
||||
};
|
||||
|
||||
RTCMediaConstraints *connectionConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mediaConstraints optionalConstraints:nil];
|
||||
|
||||
[_peerConnection setRemoteDescription:sessionDescription completionHandler:^(__unused NSError * _Nullable error) {
|
||||
[_connection setRemoteDescription:sdp type:typeString completion:^{
|
||||
}];
|
||||
|
||||
if (!_isOutgoing) {
|
||||
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
||||
[_peerConnection answerForConstraints:connectionConstraints completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = strongSelf->_queue;
|
||||
[strongSelf->_peerConnection setLocalDescription:sdp completionHandler:^(__unused NSError * _Nullable error) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf sendSdp:sdp];
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = _queue;
|
||||
[_connection getAnswer:^(NSString *sdp, NSString *type) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf->_connection setLocalDescription:sdp type:type completion:^{
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf sendSdp:sdp type:type];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
@@ -531,26 +399,24 @@ static void voipLog(NSString* format, ...) {
|
||||
sdpMid = sdpMidString;
|
||||
}
|
||||
|
||||
RTCIceCandidate *iceCandidate = [[RTCIceCandidate alloc] initWithSdp:sdp sdpMLineIndex:[mLineIndex intValue] sdpMid:sdpMid];
|
||||
voipLog(@"didReceiveIceCandidate: %@", iceCandidate);
|
||||
[_peerConnection addIceCandidate:iceCandidate];
|
||||
[_connection addIceCandidateWithSdp:sdp sdpMLineIndex:[mLineIndex intValue] sdpMid:sdpMid];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setIsMuted:(bool)isMuted {
|
||||
for (RTCRtpTransceiver *transceiver in _peerConnection.transceivers) {
|
||||
/*for (RTCRtpTransceiver *transceiver in _peerConnection.transceivers) {
|
||||
if ([transceiver isKindOfClass:[RTCAudioTrack class]]) {
|
||||
RTCAudioTrack *audioTrack = (RTCAudioTrack *)transceiver;
|
||||
[audioTrack setIsEnabled:!isMuted];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtcCustom)networkType {
|
||||
}
|
||||
|
||||
- (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion {
|
||||
if (_remoteVideoTrack == nil) {
|
||||
/*if (_remoteVideoTrack == nil) {
|
||||
for (RTCRtpTransceiver *transceiver in _peerConnection.transceivers) {
|
||||
if (transceiver.mediaType == RTCRtpMediaTypeVideo && [transceiver.receiver.track isKindOfClass:[RTCVideoTrack class]]) {
|
||||
_remoteVideoTrack = (RTCVideoTrack *)transceiver.receiver.track;
|
||||
@@ -571,7 +437,7 @@ static void voipLog(NSString* format, ...) {
|
||||
[remoteVideoTrack addRenderer:remoteRenderer];
|
||||
completion(remoteRenderer);
|
||||
#endif
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
20
submodules/TgVoipWebrtcCustom/Sources/RtcConnection.h
Normal file
20
submodules/TgVoipWebrtcCustom/Sources/RtcConnection.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef RTCCONNECTION_H
|
||||
#define RTCCONNECTION_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface RtcConnection : NSObject
|
||||
|
||||
- (instancetype)initWithDiscoveredIceCandidate:(void (^)(NSString *, int, NSString *))discoveredIceCandidate connectionStateChanged:(void (^)(bool))connectionStateChanged;
|
||||
|
||||
- (void)close;
|
||||
|
||||
- (void)getOffer:(void (^)(NSString *, NSString *))completion;
|
||||
- (void)getAnswer:(void (^)(NSString *, NSString *))completion;
|
||||
- (void)setLocalDescription:(NSString *)serializedDescription type:(NSString *)type completion:(void (^)())completion;
|
||||
- (void)setRemoteDescription:(NSString *)serializedDescription type:(NSString *)type completion:(void (^)())completion;
|
||||
- (void)addIceCandidateWithSdp:(NSString *)sdp sdpMLineIndex:(int)sdpMLineIndex sdpMid:(NSString *)sdpMid;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
298
submodules/TgVoipWebrtcCustom/Sources/RtcConnection.mm
Normal file
298
submodules/TgVoipWebrtcCustom/Sources/RtcConnection.mm
Normal file
@@ -0,0 +1,298 @@
|
||||
#import "RtcConnection.h"
|
||||
|
||||
#include <memory>
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/task_queue/default_task_queue_factory.h"
|
||||
#include "media/engine/webrtc_media_engine.h"
|
||||
#include "sdk/objc/native/api/audio_device_module.h"
|
||||
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
||||
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
#include "sdk/objc/components/video_codec/RTCVideoEncoderFactoryH264.h"
|
||||
#include "sdk/objc/components/video_codec/RTCVideoDecoderFactoryH264.h"
|
||||
#include "sdk/objc/native/api/video_encoder_factory.h"
|
||||
#include "sdk/objc/native/api/video_decoder_factory.h"
|
||||
#include "api/rtc_event_log/rtc_event_log_factory.h"
|
||||
#include "sdk/media_constraints.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
|
||||
class PeerConnectionObserverImpl : public webrtc::PeerConnectionObserver {
|
||||
private:
|
||||
void (^_discoveredIceCandidate)(NSString *, int, NSString *);
|
||||
void (^_connectionStateChanged)(bool);
|
||||
|
||||
public:
|
||||
PeerConnectionObserverImpl(void (^discoveredIceCandidate)(NSString *, int, NSString *), void (^connectionStateChanged)(bool)) {
|
||||
_discoveredIceCandidate = [discoveredIceCandidate copy];
|
||||
_connectionStateChanged = [connectionStateChanged copy];
|
||||
}
|
||||
|
||||
virtual ~PeerConnectionObserverImpl() {
|
||||
_discoveredIceCandidate = nil;
|
||||
_connectionStateChanged = nil;
|
||||
}
|
||||
|
||||
virtual void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) {
|
||||
bool isConnected = false;
|
||||
if (new_state == webrtc::PeerConnectionInterface::SignalingState::kStable) {
|
||||
isConnected = true;
|
||||
}
|
||||
_connectionStateChanged(isConnected);
|
||||
}
|
||||
|
||||
virtual void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
||||
}
|
||||
|
||||
virtual void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
||||
}
|
||||
|
||||
virtual void OnDataChannel(
|
||||
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
|
||||
}
|
||||
|
||||
virtual void OnRenegotiationNeeded() {
|
||||
}
|
||||
|
||||
virtual void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {
|
||||
}
|
||||
|
||||
virtual void OnStandardizedIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {
|
||||
}
|
||||
|
||||
virtual void OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) {
|
||||
}
|
||||
|
||||
virtual void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) {
|
||||
}
|
||||
|
||||
virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
|
||||
std::string sdp;
|
||||
candidate->ToString(&sdp);
|
||||
NSString *sdpString = [NSString stringWithUTF8String:sdp.c_str()];
|
||||
NSString *sdpMidString = [NSString stringWithUTF8String:candidate->sdp_mid().c_str()];
|
||||
_discoveredIceCandidate(sdpString, candidate->sdp_mline_index(), sdpMidString);
|
||||
}
|
||||
|
||||
virtual void OnIceCandidateError(const std::string& host_candidate, const std::string& url, int error_code, const std::string& error_text) {
|
||||
}
|
||||
|
||||
virtual void OnIceCandidateError(const std::string& address,
|
||||
int port,
|
||||
const std::string& url,
|
||||
int error_code,
|
||||
const std::string& error_text) {
|
||||
}
|
||||
|
||||
virtual void OnIceCandidatesRemoved(const std::vector<cricket::Candidate>& candidates) {
|
||||
}
|
||||
|
||||
virtual void OnIceConnectionReceivingChange(bool receiving) {
|
||||
}
|
||||
|
||||
virtual void OnIceSelectedCandidatePairChanged(const cricket::CandidatePairChangeEvent& event) {
|
||||
}
|
||||
|
||||
virtual void OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& streams) {
|
||||
}
|
||||
|
||||
virtual void OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) {
|
||||
}
|
||||
|
||||
virtual void OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
|
||||
}
|
||||
|
||||
virtual void OnInterestingUsage(int usage_pattern) {
|
||||
}
|
||||
};
|
||||
|
||||
class CreateSessionDescriptionObserverImpl : public webrtc::CreateSessionDescriptionObserver {
|
||||
private:
|
||||
void (^_completion)(NSString *, NSString *);
|
||||
|
||||
public:
|
||||
CreateSessionDescriptionObserverImpl(void (^completion)(NSString *, NSString *)) {
|
||||
_completion = [completion copy];
|
||||
}
|
||||
|
||||
~CreateSessionDescriptionObserverImpl() override {
|
||||
_completion = nil;
|
||||
}
|
||||
|
||||
virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
|
||||
if (desc) {
|
||||
NSString *typeString = [NSString stringWithUTF8String:desc->type().c_str()];
|
||||
std::string sdp;
|
||||
desc->ToString(&sdp);
|
||||
NSString *serializedString = [NSString stringWithUTF8String:sdp.c_str()];
|
||||
if (_completion && typeString && serializedString) {
|
||||
_completion(serializedString, typeString);
|
||||
}
|
||||
}
|
||||
_completion = nil;
|
||||
}
|
||||
|
||||
virtual void OnFailure(webrtc::RTCError error) override {
|
||||
_completion = nil;
|
||||
}
|
||||
};
|
||||
|
||||
class SetSessionDescriptionObserverImpl : public webrtc::SetSessionDescriptionObserver {
|
||||
private:
|
||||
void (^_completion)();
|
||||
|
||||
public:
|
||||
SetSessionDescriptionObserverImpl(void (^completion)()) {
|
||||
_completion = [completion copy];
|
||||
}
|
||||
|
||||
~SetSessionDescriptionObserverImpl() override {
|
||||
_completion = nil;
|
||||
}
|
||||
|
||||
virtual void OnSuccess() override {
|
||||
if (_completion) {
|
||||
_completion();
|
||||
}
|
||||
_completion = nil;
|
||||
}
|
||||
|
||||
virtual void OnFailure(webrtc::RTCError error) override {
|
||||
_completion = nil;
|
||||
}
|
||||
};
|
||||
|
||||
@interface RtcConnection () {
|
||||
void (^_discoveredIceCandidate)(NSString *, int, NSString *);
|
||||
void (^_connectionStateChanged)(bool);
|
||||
|
||||
std::unique_ptr<rtc::Thread> _networkThread;
|
||||
std::unique_ptr<rtc::Thread> _workerThread;
|
||||
std::unique_ptr<rtc::Thread> _signalingThread;
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> _nativeFactory;
|
||||
|
||||
std::unique_ptr<PeerConnectionObserverImpl> _observer;
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
|
||||
std::unique_ptr<webrtc::MediaConstraints> _nativeConstraints;
|
||||
bool _hasStartedRtcEventLog;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RtcConnection
|
||||
|
||||
- (instancetype)initWithDiscoveredIceCandidate:(void (^)(NSString *, int, NSString *))discoveredIceCandidate connectionStateChanged:(void (^)(bool))connectionStateChanged {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_discoveredIceCandidate = [discoveredIceCandidate copy];
|
||||
_connectionStateChanged = [connectionStateChanged copy];
|
||||
|
||||
_networkThread = rtc::Thread::CreateWithSocketServer();
|
||||
_networkThread->SetName("network_thread", _networkThread.get());
|
||||
BOOL result = _networkThread->Start();
|
||||
assert(result);
|
||||
|
||||
_workerThread = rtc::Thread::Create();
|
||||
_workerThread->SetName("worker_thread", _workerThread.get());
|
||||
result = _workerThread->Start();
|
||||
assert(result);
|
||||
|
||||
_signalingThread = rtc::Thread::Create();
|
||||
_signalingThread->SetName("signaling_thread", _signalingThread.get());
|
||||
result = _signalingThread->Start();
|
||||
assert(result);
|
||||
|
||||
webrtc::PeerConnectionFactoryDependencies dependencies;
|
||||
dependencies.network_thread = _networkThread.get();
|
||||
dependencies.worker_thread = _workerThread.get();
|
||||
dependencies.signaling_thread = _signalingThread.get();
|
||||
dependencies.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
|
||||
cricket::MediaEngineDependencies media_deps;
|
||||
media_deps.adm = webrtc::CreateAudioDeviceModule();
|
||||
media_deps.task_queue_factory = dependencies.task_queue_factory.get();
|
||||
media_deps.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
|
||||
media_deps.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
|
||||
media_deps.video_encoder_factory = webrtc::ObjCToNativeVideoEncoderFactory([[RTCVideoEncoderFactoryH264 alloc] init]);
|
||||
media_deps.video_decoder_factory = webrtc::ObjCToNativeVideoDecoderFactory([[RTCVideoDecoderFactoryH264 alloc] init]);
|
||||
media_deps.audio_processing = webrtc::AudioProcessingBuilder().Create();
|
||||
dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
|
||||
dependencies.call_factory = webrtc::CreateCallFactory();
|
||||
dependencies.event_log_factory =
|
||||
std::make_unique<webrtc::RtcEventLogFactory>(dependencies.task_queue_factory.get());
|
||||
dependencies.network_controller_factory = nil;
|
||||
dependencies.media_transport_factory = nil;
|
||||
_nativeFactory = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
|
||||
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
||||
config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
|
||||
config.continual_gathering_policy = webrtc::PeerConnectionInterface::ContinualGatheringPolicy::GATHER_CONTINUALLY;
|
||||
webrtc::PeerConnectionInterface::IceServer iceServer;
|
||||
iceServer.uri = "stun:stun.l.google.com:19302";
|
||||
config.servers.push_back(iceServer);
|
||||
|
||||
_observer.reset(new PeerConnectionObserverImpl(_discoveredIceCandidate, _connectionStateChanged));
|
||||
_peerConnection = _nativeFactory->CreatePeerConnection(config, nullptr, nullptr, _observer.get());
|
||||
|
||||
cricket::AudioOptions options;
|
||||
rtc::scoped_refptr<webrtc::AudioSourceInterface> audioSource = _nativeFactory->CreateAudioSource(options);
|
||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> track = _nativeFactory->CreateAudioTrack("audio0", audioSource);
|
||||
|
||||
std::vector<std::string> streamIds;
|
||||
streamIds.push_back("stream");
|
||||
|
||||
_peerConnection->AddTrack(track, streamIds);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
_peerConnection->Close();
|
||||
}
|
||||
|
||||
- (void)getOffer:(void (^)(NSString *, NSString *))completion {
|
||||
webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
|
||||
options.offer_to_receive_audio = 1;
|
||||
options.offer_to_receive_video = 1;
|
||||
|
||||
rtc::scoped_refptr<CreateSessionDescriptionObserverImpl> observer(new rtc::RefCountedObject<CreateSessionDescriptionObserverImpl>(completion));
|
||||
_peerConnection->CreateOffer(observer, options);
|
||||
}
|
||||
|
||||
- (void)getAnswer:(void (^)(NSString *, NSString *))completion {
|
||||
webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
|
||||
options.offer_to_receive_audio = 1;
|
||||
options.offer_to_receive_video = 1;
|
||||
|
||||
rtc::scoped_refptr<CreateSessionDescriptionObserverImpl> observer(new rtc::RefCountedObject<CreateSessionDescriptionObserverImpl>(completion));
|
||||
_peerConnection->CreateAnswer(observer, options);
|
||||
}
|
||||
|
||||
- (void)setLocalDescription:(NSString *)serializedDescription type:(NSString *)type completion:(void (^)())completion {
|
||||
webrtc::SdpParseError error;
|
||||
webrtc::SessionDescriptionInterface *sessionDescription = webrtc::CreateSessionDescription(type.UTF8String, serializedDescription.UTF8String, &error);
|
||||
if (sessionDescription != nullptr) {
|
||||
rtc::scoped_refptr<SetSessionDescriptionObserverImpl> observer(new rtc::RefCountedObject<SetSessionDescriptionObserverImpl>(completion));
|
||||
_peerConnection->SetLocalDescription(observer, sessionDescription);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setRemoteDescription:(NSString *)serializedDescription type:(NSString *)type completion:(void (^)())completion {
|
||||
webrtc::SdpParseError error;
|
||||
webrtc::SessionDescriptionInterface *sessionDescription = webrtc::CreateSessionDescription(type.UTF8String, serializedDescription.UTF8String, &error);
|
||||
if (sessionDescription != nullptr) {
|
||||
rtc::scoped_refptr<SetSessionDescriptionObserverImpl> observer(new rtc::RefCountedObject<SetSessionDescriptionObserverImpl>(completion));
|
||||
_peerConnection->SetRemoteDescription(observer, sessionDescription);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addIceCandidateWithSdp:(NSString *)sdp sdpMLineIndex:(int)sdpMLineIndex sdpMid:(NSString *)sdpMid {
|
||||
webrtc::SdpParseError error;
|
||||
webrtc::IceCandidateInterface *iceCandidate = webrtc::CreateIceCandidate(sdpMid == nil ? "" : sdpMid.UTF8String, sdpMLineIndex, sdp.UTF8String, &error);
|
||||
if (iceCandidate != nullptr) {
|
||||
std::unique_ptr<webrtc::IceCandidateInterface> nativeCandidate = std::unique_ptr<webrtc::IceCandidateInterface>(iceCandidate);
|
||||
_peerConnection->AddIceCandidate(std::move(nativeCandidate), [](auto error) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user