我正在构建一个应该使用WebRTC实施形式webrtc.org的iOS应用。我创建了演示应用程序,一切正常。在将框架集成到我自己的应用程序后,我遇到了有关解除资源分配的问题。
作为第一步,我想创建一个本地媒体流,并为其添加音频和视频轨道。在我的测试中,我意识到,解除分配RTCMediaStream
(和VideoTrackProxy
)对象会阻塞主线程大约10秒钟。
为了重现这一点,我创建了一个单独的测试,它创建了一个媒体流,为它添加了一个视频轨道并在之后解除分配(在范围的末尾释放对象)。
@interface RTCTests : XCTestCase
@property (nonatomic, strong) RTCPeerConnectionFactory *factory;
@end
@implementation RTCTests
- (void)setUp
{
[super setUp];
self.factory = [[RTCPeerConnectionFactory alloc] init];
}
- (void)tearDown
{
self.factory = nil;
[super tearDown];
}
- (void)testLocalMediaStream
{
RTCMediaStream *mediaStream = [self.factory mediaStreamWithLabel:@"stream-a"];
XCTestExpectation *expectation = [self expectationWithDescription:@"Create Media Stream"];
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
completionHandler:^(BOOL granted){
dispatch_async(dispatch_get_main_queue(), ^{
if (granted == NO) {
XCTFail(@"Access to camera not granted.");
[expectation fulfill];
} else {
NSString *cameraID = nil;
for (AVCaptureDevice *captureDevice in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if (captureDevice.position == AVCaptureDevicePositionFront) {
cameraID = [captureDevice localizedName];
break;
}
}
if (cameraID) {
RTCVideoCapturer *capturer = [RTCVideoCapturer capturerWithDeviceName:cameraID];
RTCMediaConstraints *mediaConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@[]
optionalConstraints:@[]];
RTCVideoSource *videoSource = [self.factory videoSourceWithCapturer:capturer
constraints:mediaConstraints];
RTCVideoTrack *track = [self.factory videoTrackWithID:@"stream-a-v" source:videoSource];
if (track) {
[mediaStream addVideoTrack:track];
}
}
[expectation fulfill];
}
});
}];
[self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) {
XCTAssertNil(error, @"Failed with error: %@", [error localizedDescription]);
}];
XCTAssertEqual([mediaStream.videoTracks count], 1);
XCTAssertEqualObjects([[[mediaStream videoTracks] firstObject] label], @"stream-a-v");
NSLog(@"Done! %@", [NSDate date]);
}
@end
测试本身按预期工作,它或多或少立即成功,如下面的日志中所示:
Test Case '-[RTCTests testLocalMediaStream]' started.
2015-03-02 14:51:36.458 App[9043:2810016] Begin! 2015-03-02 13:51:36 +0000
2015-03-02 14:51:36.643 App[9043:2810016] End! 2015-03-02 13:51:36 +0000
Test Case '-[RTCTests testLocalMediaStream]' passed (9.266 seconds).
但是需要另外9秒来释放资源(在这种情况下是VideoTrackProxy
),它同步调用析构函数中另一个线程上的方法(如果我正确读取sources of the proxy)。不幸的是,这个线程接缝成为主线程,这会导致死锁并且我会猜到超时解决。
* thread #1: tid = 0x2ae4a8, 0x00000001978db078 libsystem_kernel.dylib`__psynch_cvwait + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* frame #0: 0x00000001978db078 libsystem_kernel.dylib`__psynch_cvwait + 8
frame #1: 0x0000000197976fe4 libsystem_pthread.dylib`_pthread_cond_wait + 624
frame #2: 0x0000000100cbc2c0 RTCTests`rtc::Event::Wait(int) + 232
frame #3: 0x0000000100b210cc RTCTests`webrtc::VideoTrackProxy::~VideoTrackProxy() + 120
frame #4: 0x0000000100b206b0 RTCTests`rtc::RefCountedObject::~RefCountedObject() + 12
frame #5: 0x0000000100b20690 RTCTests`rtc::RefCountedObject::Release() + 52
frame #6: 0x0000000197152b1c libobjc.A.dylib`object_cxxDestructFromClass(objc_object*, objc_class*) + 148
frame #7: 0x000000019715ff38 libobjc.A.dylib`objc_destructInstance + 92
frame #8: 0x000000019715ff90 libobjc.A.dylib`object_dispose + 28
frame #9: 0x0000000100b58db4 RTCTests`-[RTCMediaStreamTrack(Internal) dealloc] + 92
frame #10: 0x0000000100b5ef6c RTCTests`-[RTCVideoTrack dealloc] + 356
frame #11: 0x000000018692d228 CoreFoundation`CFRelease + 524
frame #12: 0x0000000186935308 CoreFoundation`-[__NSArrayI dealloc] + 88
frame #13: 0x000000019716d724 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 564
frame #14: 0x00000001011f1c54 XCTest`-[XCTestCase invokeTest] + 336
...
WebRTC框架是否可以配置为不将主线程用于其内部任务?或者我在这里错过了其他什么?
我很欣赏各种提示。