Fixed crash when PCF is destroyed before RTCRtpReceiver in ObjC
Bug: webrtc:9231 Change-Id: Ic532b7661bb8765f0fc2309d2ad530f664ccfd14 Reviewed-on: https://webrtc-review.googlesource.com/87840 Reviewed-by: Kári Helgason <kthelgason@webrtc.org> Commit-Queue: Kári Helgason <kthelgason@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23931}
This commit is contained in:
committed by
Commit Bot
parent
cd8f382557
commit
7a16c54571
@ -231,7 +231,8 @@ void PeerConnectionDelegateAdapter::OnAddTrack(
|
||||
nativeMediaStream:nativeStream];
|
||||
[mediaStreams addObject:mediaStream];
|
||||
}
|
||||
RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithNativeRtpReceiver:receiver];
|
||||
RTCRtpReceiver *rtpReceiver =
|
||||
[[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory nativeRtpReceiver:receiver];
|
||||
|
||||
[peer_connection.delegate peerConnection:peer_connection
|
||||
didAddReceiver:rtpReceiver
|
||||
@ -545,7 +546,7 @@ void PeerConnectionDelegateAdapter::OnAddTrack(
|
||||
NSMutableArray *receivers = [[NSMutableArray alloc] init];
|
||||
for (const auto &nativeReceiver : nativeReceivers) {
|
||||
RTCRtpReceiver *receiver =
|
||||
[[RTCRtpReceiver alloc] initWithNativeRtpReceiver:nativeReceiver];
|
||||
[[RTCRtpReceiver alloc] initWithFactory:self.factory nativeRtpReceiver:nativeReceiver];
|
||||
[receivers addObject:receiver];
|
||||
}
|
||||
return receivers;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class RTCPeerConnectionFactory;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RtpReceiverDelegateAdapter : public RtpReceiverObserverInterface {
|
||||
@ -33,8 +35,8 @@ class RtpReceiverDelegateAdapter : public RtpReceiverObserverInterface {
|
||||
@property(nonatomic, readonly) rtc::scoped_refptr<webrtc::RtpReceiverInterface> nativeRtpReceiver;
|
||||
|
||||
/** Initialize an RTCRtpReceiver with a native RtpReceiverInterface. */
|
||||
- (instancetype)initWithNativeRtpReceiver:
|
||||
(rtc::scoped_refptr<webrtc::RtpReceiverInterface>)nativeRtpReceiver
|
||||
- (instancetype)initWithFactory:(RTCPeerConnectionFactory*)factory
|
||||
nativeRtpReceiver:(rtc::scoped_refptr<webrtc::RtpReceiverInterface>)nativeRtpReceiver
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
+ (RTCRtpMediaType)mediaTypeForNativeMediaType:(cricket::MediaType)nativeMediaType;
|
||||
|
||||
@ -36,6 +36,7 @@ void RtpReceiverDelegateAdapter::OnFirstPacketReceived(
|
||||
} // namespace webrtc
|
||||
|
||||
@implementation RTCRtpReceiver {
|
||||
RTCPeerConnectionFactory *_factory;
|
||||
rtc::scoped_refptr<webrtc::RtpReceiverInterface> _nativeRtpReceiver;
|
||||
std::unique_ptr<webrtc::RtpReceiverDelegateAdapter> _observer;
|
||||
}
|
||||
@ -102,9 +103,11 @@ void RtpReceiverDelegateAdapter::OnFirstPacketReceived(
|
||||
return _nativeRtpReceiver;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNativeRtpReceiver:
|
||||
(rtc::scoped_refptr<webrtc::RtpReceiverInterface>)nativeRtpReceiver {
|
||||
- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
|
||||
nativeRtpReceiver:
|
||||
(rtc::scoped_refptr<webrtc::RtpReceiverInterface>)nativeRtpReceiver {
|
||||
if (self = [super init]) {
|
||||
_factory = factory;
|
||||
_nativeRtpReceiver = nativeRtpReceiver;
|
||||
RTCLogInfo(
|
||||
@"RTCRtpReceiver(%p): created receiver: %@", self, self.description);
|
||||
|
||||
@ -131,7 +131,8 @@
|
||||
_nativeRtpTransceiver = nativeRtpTransceiver;
|
||||
_sender = [[RTCRtpSender alloc] initWithFactory:_factory
|
||||
nativeRtpSender:nativeRtpTransceiver->sender()];
|
||||
_receiver = [[RTCRtpReceiver alloc] initWithNativeRtpReceiver:nativeRtpTransceiver->receiver()];
|
||||
_receiver = [[RTCRtpReceiver alloc] initWithFactory:_factory
|
||||
nativeRtpReceiver:nativeRtpTransceiver->receiver()];
|
||||
RTCLogInfo(@"RTCRtpTransceiver(%p): created transceiver: %@", self, self.description);
|
||||
}
|
||||
return self;
|
||||
|
||||
@ -15,13 +15,13 @@
|
||||
#import <WebRTC/RTCMediaStreamTrack.h>
|
||||
#import <WebRTC/RTCPeerConnection.h>
|
||||
#import <WebRTC/RTCPeerConnectionFactory.h>
|
||||
#import <WebRTC/RTCRtpReceiver.h>
|
||||
#import <WebRTC/RTCRtpSender.h>
|
||||
#import <WebRTC/RTCRtpTransceiver.h>
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface RTCPeerConnectionFactoryTests : XCTestCase
|
||||
- (void)testPeerConnectionLifetime;
|
||||
@end
|
||||
|
||||
@implementation RTCPeerConnectionFactoryTests
|
||||
@ -30,7 +30,7 @@
|
||||
@autoreleasepool {
|
||||
RTCConfiguration *config = [[RTCConfiguration alloc] init];
|
||||
|
||||
RTCMediaConstraints *contraints =
|
||||
RTCMediaConstraints *constraints =
|
||||
[[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil];
|
||||
|
||||
RTCPeerConnectionFactory *factory;
|
||||
@ -39,7 +39,7 @@
|
||||
@autoreleasepool {
|
||||
factory = [[RTCPeerConnectionFactory alloc] init];
|
||||
peerConnection =
|
||||
[factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
|
||||
[factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil];
|
||||
[peerConnection close];
|
||||
factory = nil;
|
||||
}
|
||||
@ -68,7 +68,7 @@
|
||||
- (void)testDataChannelLifetime {
|
||||
@autoreleasepool {
|
||||
RTCConfiguration *config = [[RTCConfiguration alloc] init];
|
||||
RTCMediaConstraints *contraints =
|
||||
RTCMediaConstraints *constraints =
|
||||
[[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil];
|
||||
RTCDataChannelConfiguration *dataChannelConfig = [[RTCDataChannelConfiguration alloc] init];
|
||||
|
||||
@ -79,10 +79,10 @@
|
||||
@autoreleasepool {
|
||||
factory = [[RTCPeerConnectionFactory alloc] init];
|
||||
peerConnection =
|
||||
[factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
|
||||
[factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil];
|
||||
dataChannel =
|
||||
[peerConnection dataChannelForLabel:@"test_channel" configuration:dataChannelConfig];
|
||||
XCTAssertTrue(dataChannel != nil);
|
||||
XCTAssertNotNil(dataChannel);
|
||||
[peerConnection close];
|
||||
peerConnection = nil;
|
||||
factory = nil;
|
||||
@ -110,7 +110,7 @@
|
||||
peerConnection =
|
||||
[factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
|
||||
tranceiver = [peerConnection addTransceiverOfType:RTCRtpMediaTypeAudio init:init];
|
||||
XCTAssertTrue(tranceiver != nil);
|
||||
XCTAssertNotNil(tranceiver);
|
||||
[peerConnection close];
|
||||
peerConnection = nil;
|
||||
factory = nil;
|
||||
@ -124,7 +124,7 @@
|
||||
- (void)testRTCRtpSenderLifetime {
|
||||
@autoreleasepool {
|
||||
RTCConfiguration *config = [[RTCConfiguration alloc] init];
|
||||
RTCMediaConstraints *contraints =
|
||||
RTCMediaConstraints *constraints =
|
||||
[[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil];
|
||||
|
||||
RTCPeerConnectionFactory *factory;
|
||||
@ -134,9 +134,9 @@
|
||||
@autoreleasepool {
|
||||
factory = [[RTCPeerConnectionFactory alloc] init];
|
||||
peerConnection =
|
||||
[factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
|
||||
[factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil];
|
||||
sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo streamId:@"stream"];
|
||||
XCTAssertTrue(sender != nil);
|
||||
XCTAssertNotNil(sender);
|
||||
[peerConnection close];
|
||||
peerConnection = nil;
|
||||
factory = nil;
|
||||
@ -147,4 +147,101 @@
|
||||
XCTAssertTrue(true, "Expect test does not crash");
|
||||
}
|
||||
|
||||
- (void)testRTCRtpReceiverLifetime {
|
||||
@autoreleasepool {
|
||||
RTCConfiguration *config = [[RTCConfiguration alloc] init];
|
||||
RTCMediaConstraints *constraints =
|
||||
[[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil];
|
||||
|
||||
RTCPeerConnectionFactory *factory;
|
||||
RTCPeerConnection *pc1;
|
||||
RTCPeerConnection *pc2;
|
||||
|
||||
NSArray<RTCRtpReceiver *> *receivers1;
|
||||
NSArray<RTCRtpReceiver *> *receivers2;
|
||||
|
||||
@autoreleasepool {
|
||||
factory = [[RTCPeerConnectionFactory alloc] init];
|
||||
pc1 = [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil];
|
||||
[pc1 senderWithKind:kRTCMediaStreamTrackKindAudio streamId:@"stream"];
|
||||
|
||||
pc2 = [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil];
|
||||
[pc2 senderWithKind:kRTCMediaStreamTrackKindAudio streamId:@"stream"];
|
||||
|
||||
NSTimeInterval negotiationTimeout = 15;
|
||||
XCTAssertTrue([self negotiatePeerConnection:pc1
|
||||
withPeerConnection:pc2
|
||||
negotiationTimeout:negotiationTimeout]);
|
||||
|
||||
XCTAssertEqual(pc1.signalingState, RTCSignalingStateStable);
|
||||
XCTAssertEqual(pc2.signalingState, RTCSignalingStateStable);
|
||||
|
||||
receivers1 = pc1.receivers;
|
||||
receivers2 = pc2.receivers;
|
||||
XCTAssertTrue(receivers1.count > 0);
|
||||
XCTAssertTrue(receivers2.count > 0);
|
||||
[pc1 close];
|
||||
[pc2 close];
|
||||
pc1 = nil;
|
||||
pc2 = nil;
|
||||
factory = nil;
|
||||
}
|
||||
receivers1 = nil;
|
||||
receivers2 = nil;
|
||||
}
|
||||
|
||||
XCTAssertTrue(true, "Expect test does not crash");
|
||||
}
|
||||
|
||||
- (bool)negotiatePeerConnection:(RTCPeerConnection *)pc1
|
||||
withPeerConnection:(RTCPeerConnection *)pc2
|
||||
negotiationTimeout:(NSTimeInterval)timeout {
|
||||
__weak RTCPeerConnection *weakPC1 = pc1;
|
||||
__weak RTCPeerConnection *weakPC2 = pc2;
|
||||
RTCMediaConstraints *sdpConstraints =
|
||||
[[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{
|
||||
kRTCMediaConstraintsOfferToReceiveAudio : kRTCMediaConstraintsValueTrue
|
||||
}
|
||||
optionalConstraints:nil];
|
||||
|
||||
dispatch_semaphore_t negotiatedSem = dispatch_semaphore_create(0);
|
||||
[weakPC1 offerForConstraints:sdpConstraints
|
||||
completionHandler:^(RTCSessionDescription *offer, NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertNotNil(offer);
|
||||
[weakPC1
|
||||
setLocalDescription:offer
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
[weakPC2
|
||||
setRemoteDescription:offer
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
[weakPC2
|
||||
answerForConstraints:sdpConstraints
|
||||
completionHandler:^(RTCSessionDescription *answer,
|
||||
NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertNotNil(answer);
|
||||
[weakPC2
|
||||
setLocalDescription:answer
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
[weakPC1
|
||||
setRemoteDescription:answer
|
||||
completionHandler:^(NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
dispatch_semaphore_signal(negotiatedSem);
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
|
||||
return 0 ==
|
||||
dispatch_semaphore_wait(negotiatedSem,
|
||||
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user