问题
Is AVAssetWriterInput's readyForMoreMediaData updated in a background thread? If readyForMoreMediaData is NO, can I block in the main thread and wait until the value changes to YES?
I'm using an AVAssetWriterInput by pushing data to it (i.e. without using requestMediaDataWhenReadyOnQueue) and I've set expectsMediaDataInRealTime, and 99.9% of the time I can just call appendSampleBuffer (or appendPixelBuffer) on it as fast as my app can generate frames.
This works fine unless you put the device (iPhone 3GS) to sleep for 15 minutes or so in the middle of an AVAssetWriter session. After waking up the device, appendPixelBuffer sometimes gets an error saying, "A pixel buffer cannot be appended when readyForMoreMediaData is NO". Hence my question - how best to respond to readyForMoreMediaData=NO and if I can just wait a bit in the main thread like so:
while ( ![assetWriterInput readyForMoreMediaData] )
{
Sleep for a few milliseconds
}
回答1:
Be careful not to just block the thread, here is what I was doing before that was not working:
while (adaptor.assetWriterInput.readyForMoreMediaData == FALSE) {
[NSThread sleepForTimeInterval:0.1];
}
The above approach would fail sometimes on my iPad2. Doing this instead fixed the problem:
while (adaptor.assetWriterInput.readyForMoreMediaData == FALSE) {
NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:0.1];
[[NSRunLoop currentRunLoop] runUntilDate:maxDate];
}
回答2:
Don't find something similar, so I left it here. Swift 4 solution. Would better using precise technique to solve that problem. F.e. using NSCondition:
func startRecording() {
// start recording code goes here
readyForMediaCondition = NSCondition()
readyForMediaObservation = pixelBufferInput?.assetWriterInput.observe(\.isReadyForMoreMediaData, options: .new, changeHandler: { [weak self](_, change) in
guard let isReady = change.newValue else {
return
}
if isReady {
self?.readyForMediaCondition?.lock()
self?.readyForMediaCondition?.signal()
self?.readyForMediaCondition?.unlock()
}
})
}
Next:
func grabFrame(time: CMTime? = nil) {
readyForMediaCondition?.lock()
while !pixelBufferInput!.assetWriterInput.isReadyForMoreMediaData {
readyForMediaCondition?.wait()
}
readyForMediaCondition?.unlock()
// append your framebuffer here
}
Don't forget to invalidate observer in the end
readyForMediaObservation?.invalidate()
回答3:
int waitTime = 300;
while (weakSelf.input.readyForMoreMediaData == NO) {
NSLog(@"readyForMoreMediaData is NO");
NSTimeInterval waitIntervale = 0.001 * waitTime;
NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:waitIntervale];
[[NSRunLoop currentRunLoop] runUntilDate:maxDate];
waitTime += 200; // add 200ms every time
}
来源:https://stackoverflow.com/questions/5877149/avassetwriterinput-and-readyformoremediadata