【发布时间】:2014-03-28 15:42:57
【问题描述】:
我正在尝试在 iOS 中播放来自 IP 摄像头的视频,但目前我尝试了 2 种方法,它们似乎都非常快地填满了我的 iOS 设备的内存。我在这个项目中使用 ARC。
我的 IP 摄像机使用 Videostream.cgi (Foscam),这是一种众所周知的 IP 摄像机通过浏览器流式传输“视频”的方式。
所以,我尝试了 3 种方法,最终都导致我的 iOS 应用程序崩溃,并出现内存不足异常。
1. 将UIWebView 放在我的UIViewController 上,然后使用NSURLRequest 直接调用CGI。
NSString* url = [NSString stringWithFormat:@"http://%@:%@/videostream.cgi?user=%@&pwd=%@&rate=0&resolution=%ld", camera.ip, camera.port, camera.username, camera.password, (long)_resolution];
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
webView = [[UIWebView alloc] init];
[webView loadRequest:request];
2. 在我的UIViewController 上放置一个UIWebView 并创建一段HTML(在代码中),其中包含一个<img> 标记,该标记具有前面提到的CGI 的来源。 (见:IP camera stream with UIWebview works on IOS 5 but not on IOS 6)
NSString* imgHtml = [NSString stringWithFormat:@"<img src='%@'>", url];
webView = [[UIWebView alloc] init];
[webView loadHTMLString:imgHtml];
3. 使用基于UIImageView 的自定义控件,该控件连续获取数据。 https://github.com/mateagar/Motion-JPEG-Image-View-for-iOS
所有这些东西都会烧毁内存,即使我尝试删除它们并在一段时间后重新添加它们,但这似乎并不能解决问题。内存不会被释放,iPad会崩溃。
更新:
我目前正在修改我尝试过的解决方案的选项 3。它基于NSURLConnection 及其检索的数据。
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (!_receivedData) {
_receivedData = [NSMutableData new];
}
[_receivedData appendData:data];
NSRange endRange = [_receivedData rangeOfData:_endMarkerData
options:0
range:NSMakeRange(0, _receivedData.length)];
NSUInteger endLocation = endRange.location + endRange.length;
if (_receivedData.length >= endLocation) {
NSData *imageData = [_receivedData subdataWithRange:NSMakeRange(0, endLocation)];
UIImage *receivedImage = [UIImage imageWithData:imageData];
if (receivedImage) {
NSLog(@"_receivedData length: %d", [_receivedData length]);
self.image = receivedImage;
_receivedData = nil;
_receivedData = [NSMutableData new];
}
}
if (_shouldStop) {
[connection cancel];
}
}
_receivedData 是一个 NSMutableData 对象。一旦从流中检索到图像,我就会尝试“清空”它。 if (receivedImage) 中的部分在应该被调用时被调用。 _receivedData 对象的长度也没有增加,它保持在相同的大小(~ 14k)左右,所以这似乎有效。
但不知何故,每didReceiveData 一次,我的应用程序使用的内存就会增加,即使我禁用self.image = receivedImage 行也是如此。
更新 正如 iosengineer 所建议的,我一直在使用自动释放池,但这并不能解决问题。
使用 Instruments 我发现大部分分配都是由CFNetwork 完成的,方法是HTTPBodyData::appendBytes(unsigned char const*, long)。 (这一次分配 64KB 并让它们保持活动状态)。
【问题讨论】:
标签: ios iphone objective-c video-streaming