requestMediaDataWhenReadyOnQueue:usingBlock: 并行创建多个块 ->崩溃
我正在尝试将 CGPixelBufferRefs 附加到 AVAssetWriterInput 以创建 QuickTime 影片。
我正在使用以下代码:
BOOL __block shouldContinue = YES;
[self.assetWriterInput requestMediaDataWhenReadyOnQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
usingBlock:^(void)
{
BXLog(@"processing Block");
while ([self.assetWriterInput isReadyForMoreMediaData] && shouldContinue)
{
BXLog(@"assetWriter isReadyForMoreMediaData, shouldContinue %i", shouldContinue);
NSError *error = nil;
CGImageRef image = [inClip copyImageAtIndex:frameCounter withSize:CGSizeZero error:&error];
CGFloat progress = (CGFloat)frameCounter / (CGFloat)inRange.length;
if (image != NULL)
{
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
CVPixelBufferRef pixelBuffer = [self pixelBufferFromCGImage:image andSize:CGSizeMake(width, height)];
if (! [self.assetWriterInputPixelBufferAdaptor appendPixelBuffer:pixelBuffer
withPresentationTime:CMTimeMake(frameCounter * inClip.lengthOfOneFrame.value, inClip.lengthOfOneFrame.timescale)])
{
[self.assetWriter finishWriting];
BXLogInDomain(kLogDomainSharing, kLogLevelError, @"Error while appending pixel butter: %@", self.assetWriter.error);
error = [NSError errorWithDomain:kErrorDomainExport
code:ZBExportAppendImageError
userInfo:nil];
}
CVPixelBufferRelease(pixelBuffer);
}
else
{
[self.assetWriter finishWriting];
BXLogInDomain(kLogDomainSharing, kLogLevelError, @"Error while coping image from clip %@", self.assetWriter.error);
// create a Framedrop Error - we couldn't find a frame
error = [NSError errorWithDomain:kErrorDomainExport
code:ZBExportFrameDropError
userInfo:nil];
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^(void)
{
self.currentProgress = flag ? progress * 0.5 : progress;
}];
dispatch_sync(handlerQueue,
^(void)
{
shouldContinue = inProgressHandler(progress, image);
});
BXLog(@"should continue %i", shouldContinue);
CGImageRelease(image);
frameCounter++;
// Movie is finished
if (frameCounter >= inRange.location + inRange.length)
{
[self.assetWriterInput markAsFinished];
[self.assetWriter finishWriting];
[[NSOperationQueue mainQueue] addOperationWithBlock:^(void)
{
self.currentProgress = 1.0;
}];
dispatch_async(handlerQueue, ^(void)
{
inCompletionHandler(self.filePath, error);
dispatch_release(handlerQueue);
});
shouldContinue = NO;
}
else if (shouldContinue == NO)
{
[self.assetWriterInput markAsFinished];
[self.assetWriter finishWriting];
// call the completion handler
if (frameCounter < inRange.location + inRange.length)
{
dispatch_async(handlerQueue, ^(void)
{
// cancel error
inCompletionHandler(NULL, [NSError errorWithDomain:kErrorDomainEport
code:ZBExportCancelError
userInfo:nil]);
dispatch_release(handlerQueue);
});
}
// do not export any longer
// simply calling the completion handler is not enough
BXLog(@"End of while – should continue %i - asset writer is ready for more media %i", shouldContinue, [self.assetWriterInput isReadyForMoreMediaData]);
}
BXLog(@"out of while");
}];
}
大多数时候它运行良好,但有时会崩溃。我可以将崩溃情况分解为以下情况:
- 对于大多数导出,仅创建一个块,while 循环逐帧处理,最后块退出。
- 有一个出口,其中使用了多个块。创建一个块,处理 4 或 5 个图像,然后使用 [self.assetWriterInput isReadyForMoreMediaData == NO 离开 while 循环。创建一个新块,处理更多帧,然后离开 while 循环。
- 有时会发生这样的情况:不是创建一个块,而是创建两个块,并且两个块都并行工作。
我得到以下输出:
2011-11-08 12:42:41.161 iStopMotion[22804:1c003] processing Block
2011-11-08 12:42:41.168 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.278 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.279 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.285 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.370 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.391 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.399 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.420 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.422 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.423 iStopMotion[22804:1c003] out of while
2011-11-08 12:42:41.442 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.457 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.476 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.476 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.477 iStopMotion[22804:1e507] out of while
2011-11-08 12:42:41.498 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.515 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.541 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.553 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.583 iStopMotion[22804:1e507] out of while
2011-11-08 12:42:41.614 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.628 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.689 iStopMotion[22804:1f107] processing Block
2011-11-08 12:42:41.710 iStopMotion[22804:1f107] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.668 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.730 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.751 iStopMotion[22804:1f107] should continue 1
2011-11-08 12:42:41.766 iStopMotion[22804:1f107] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.789 iStopMotion[22804:1f107] out of while
2011-11-08 12:42:41.766 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
这会引发异常:
'NSInternalInconsistencyException', reason: '*** -[AVAssetWriterInputPixelBufferAdaptor appendPixelBuffer:withPresentationTime:]
A pixel buffer cannot be appended when readyForMoreMediaData is NO.'
看起来 AVAssetWriterInput 正在处理来自第一个块的数据,因此尚未准备好 ForMoreMediaData,其中第二个块也尝试附加像素缓冲区。
有谁知道这是如何发生的以及如何应对?
I am trying to append CGPixelBufferRefs to an AVAssetWriterInput to create a QuickTime movie.
I'm using the following code:
BOOL __block shouldContinue = YES;
[self.assetWriterInput requestMediaDataWhenReadyOnQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
usingBlock:^(void)
{
BXLog(@"processing Block");
while ([self.assetWriterInput isReadyForMoreMediaData] && shouldContinue)
{
BXLog(@"assetWriter isReadyForMoreMediaData, shouldContinue %i", shouldContinue);
NSError *error = nil;
CGImageRef image = [inClip copyImageAtIndex:frameCounter withSize:CGSizeZero error:&error];
CGFloat progress = (CGFloat)frameCounter / (CGFloat)inRange.length;
if (image != NULL)
{
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
CVPixelBufferRef pixelBuffer = [self pixelBufferFromCGImage:image andSize:CGSizeMake(width, height)];
if (! [self.assetWriterInputPixelBufferAdaptor appendPixelBuffer:pixelBuffer
withPresentationTime:CMTimeMake(frameCounter * inClip.lengthOfOneFrame.value, inClip.lengthOfOneFrame.timescale)])
{
[self.assetWriter finishWriting];
BXLogInDomain(kLogDomainSharing, kLogLevelError, @"Error while appending pixel butter: %@", self.assetWriter.error);
error = [NSError errorWithDomain:kErrorDomainExport
code:ZBExportAppendImageError
userInfo:nil];
}
CVPixelBufferRelease(pixelBuffer);
}
else
{
[self.assetWriter finishWriting];
BXLogInDomain(kLogDomainSharing, kLogLevelError, @"Error while coping image from clip %@", self.assetWriter.error);
// create a Framedrop Error - we couldn't find a frame
error = [NSError errorWithDomain:kErrorDomainExport
code:ZBExportFrameDropError
userInfo:nil];
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^(void)
{
self.currentProgress = flag ? progress * 0.5 : progress;
}];
dispatch_sync(handlerQueue,
^(void)
{
shouldContinue = inProgressHandler(progress, image);
});
BXLog(@"should continue %i", shouldContinue);
CGImageRelease(image);
frameCounter++;
// Movie is finished
if (frameCounter >= inRange.location + inRange.length)
{
[self.assetWriterInput markAsFinished];
[self.assetWriter finishWriting];
[[NSOperationQueue mainQueue] addOperationWithBlock:^(void)
{
self.currentProgress = 1.0;
}];
dispatch_async(handlerQueue, ^(void)
{
inCompletionHandler(self.filePath, error);
dispatch_release(handlerQueue);
});
shouldContinue = NO;
}
else if (shouldContinue == NO)
{
[self.assetWriterInput markAsFinished];
[self.assetWriter finishWriting];
// call the completion handler
if (frameCounter < inRange.location + inRange.length)
{
dispatch_async(handlerQueue, ^(void)
{
// cancel error
inCompletionHandler(NULL, [NSError errorWithDomain:kErrorDomainEport
code:ZBExportCancelError
userInfo:nil]);
dispatch_release(handlerQueue);
});
}
// do not export any longer
// simply calling the completion handler is not enough
BXLog(@"End of while – should continue %i - asset writer is ready for more media %i", shouldContinue, [self.assetWriterInput isReadyForMoreMediaData]);
}
BXLog(@"out of while");
}];
}
The most time it works great, but sometimes it crashes. I could break down the crash situation to the following:
- For most exports, only one block is created, the while loop handels frame by frame and in the end the block exits.
- There is an export, where more than one block is used. A block is created, handels 4 or 5 images then leaves the while loop with [self.assetWriterInput isReadyForMoreMediaData == NO. A new block is created, handling some more frame, then leaving while loop.
- It happens, that sometimes not one block is created but two and both are working in parallel.
I get the following output:
2011-11-08 12:42:41.161 iStopMotion[22804:1c003] processing Block
2011-11-08 12:42:41.168 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.278 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.279 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.285 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.370 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.391 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.399 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.420 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.422 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.423 iStopMotion[22804:1c003] out of while
2011-11-08 12:42:41.442 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.457 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.476 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.476 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.477 iStopMotion[22804:1e507] out of while
2011-11-08 12:42:41.498 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.515 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.541 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.553 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.583 iStopMotion[22804:1e507] out of while
2011-11-08 12:42:41.614 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.628 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.689 iStopMotion[22804:1f107] processing Block
2011-11-08 12:42:41.710 iStopMotion[22804:1f107] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.668 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.730 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.751 iStopMotion[22804:1f107] should continue 1
2011-11-08 12:42:41.766 iStopMotion[22804:1f107] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.789 iStopMotion[22804:1f107] out of while
2011-11-08 12:42:41.766 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
This throws an exception:
'NSInternalInconsistencyException', reason: '*** -[AVAssetWriterInputPixelBufferAdaptor appendPixelBuffer:withPresentationTime:]
A pixel buffer cannot be appended when readyForMoreMediaData is NO.'
It looks like the AVAssetWriterInput is processing data from first block and is therefore not readyForMoreMediaData, where the second block tries to append a pixel buffer, too.
Has anyone an idea, how this comes and what to do against it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论