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:
Yura Yaroshevich
2018-07-11 12:55:04 +03:00
committed by Commit Bot
parent cd8f382557
commit 7a16c54571
5 changed files with 121 additions and 17 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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