在iOS中使用dispatch_async时出现内存警告
我有下面的代码,以 30fps 捕获 jpeg 帧并以 mp4 格式录制视频。我试图将 processFrame 方法包装在dispatch_async 调用中,以便录制过程不会锁定视频播放器。问题是我收到了 2 级内存警告,并且应用程序最终在几秒钟后崩溃。我可以看到,dispatch_async 方法在尝试将每个帧附加到录制的视频输出中时将队列加载到内存中,并且在 30fps 时,它没有足够的时间来处理帧并释放已用内存。我尝试使用dispatch_after来延迟processFrame的执行,但它没有帮助。有什么想法吗?我应该采取不同的做法吗?
此方法每秒被调用约 30 次。
//Process the data sent by the server and send follow-up commands if needed
-(void)processServerData:(NSData *)data{
//render the video in the UIImage control
UIImage *image =[UIImage imageWithData:data];
imageCtrl.image = image;
//record the frame in the background
dispatch_async(recordingQueue,^{[self processFrame:image];});
}
}
processFrame 方法
//function for processing each frame for recording
-(void) processFrame:(UIImage *) image {
if (myRecorder.frameCounter < myRecorder.maxFrames)
{
if([myRecorder.writerInput isReadyForMoreMediaData])
{
CMTime frameTime = CMTimeMake(1, myRecorder.timeScale);
CMTime lastTime=CMTimeMake(myRecorder.frameCounter, myRecorder.timeScale);
CMTime presentTime=CMTimeAdd(lastTime, frameTime);
buffer = [Recorder pixelBufferFromCGImage:image.CGImage size:myRecorder.imageSize];
if(buffer)
{
[myRecorder.adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
myRecorder.frameCounter++;
CVBufferRelease(buffer);
if (myRecorder.frameCounter==myRecorder.maxFrames)
{
[myRecorder finishSession];
myRecorder.frameCounter=0;
myRecorder.isRecording = NO;
}
}
else
{
NSLog(@"Buffer is empty");
}
}
else
{
NSLog(@"adaptor not ready frameCounter=%d ",myRecorder.frameCounter );
}
}
}
I have the code below that captures jpeg frames at 30fps and records the video in mp4 format. I'm trying to wrap the processFrame method in a dispatch_async call so that the recording process will not lockup the video player. The problem with this is I'm getting Memory Warning level 2 and the app ultimately crashes after a few seconds. I can see that the dispatch_async method loads the queue in memory as it tries to append each frame in the recorded video output ,and at 30fps, it doesn't have enough time to process the frame and release used memory. I tried using dispatch_after to delay execution of processFrame but it doesn't help. Any ideas? Should I be doing this differently?
This method gets called at around 30 times per second.
//Process the data sent by the server and send follow-up commands if needed
-(void)processServerData:(NSData *)data{
//render the video in the UIImage control
UIImage *image =[UIImage imageWithData:data];
imageCtrl.image = image;
//record the frame in the background
dispatch_async(recordingQueue,^{[self processFrame:image];});
}
}
processFrame method
//function for processing each frame for recording
-(void) processFrame:(UIImage *) image {
if (myRecorder.frameCounter < myRecorder.maxFrames)
{
if([myRecorder.writerInput isReadyForMoreMediaData])
{
CMTime frameTime = CMTimeMake(1, myRecorder.timeScale);
CMTime lastTime=CMTimeMake(myRecorder.frameCounter, myRecorder.timeScale);
CMTime presentTime=CMTimeAdd(lastTime, frameTime);
buffer = [Recorder pixelBufferFromCGImage:image.CGImage size:myRecorder.imageSize];
if(buffer)
{
[myRecorder.adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
myRecorder.frameCounter++;
CVBufferRelease(buffer);
if (myRecorder.frameCounter==myRecorder.maxFrames)
{
[myRecorder finishSession];
myRecorder.frameCounter=0;
myRecorder.isRecording = NO;
}
}
else
{
NSLog(@"Buffer is empty");
}
}
else
{
NSLog(@"adaptor not ready frameCounter=%d ",myRecorder.frameCounter );
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
解决了!我发现我可以使用dispatch_async_semaphore来防止队列因太多请求而过载,从而导致没有足够的时间来释放分配的资源。
这是我更新的代码:
在我的代码中的某处创建的dispatch_semaphore。在这里,我告诉信号量首先只接受最多 50 个请求,并在接受更多请求之前完成处理。
Solved! I discovered that I can use dispatch_async_semaphore to prevent the queue from being overloaded with too much request that it won't have enough time to release allocated resources.
Here's my updated code:
The dispatch_semaphore created somewhere in my code. Here, I told the semaphore to accept up to only 50 request first and finish the processing before accepting anymore request.