9

AVAssetWriterInput 的 readyForMoreMediaData 是否在后台线程中更新?如果 readyForMoreMediaData 为 NO,我可以在主线程中阻塞并等待值变为 YES 吗?

我通过向 AVAssetWriterInput 推送数据(即不使用 requestMediaDataWhenReadyOnQueue)来使用 AVAssetWriterInput,并且我已经设置了 expectsMediaDataInRealTime,并且 99.9% 的时间我可以在其上调用 appendSampleBuffer(或 appendPixelBuffer),其速度与我的应用程序生成帧的速度一样快。

除非您在 AVAssetWriter 会话中间让设备 (iPhone 3GS) 休眠 15 分钟左右,否则这工作正常。唤醒设备后,appendPixelBuffer 有时会收到错误消息:“当 readyForMoreMediaData 为 NO 时,无法附加像素缓冲区”。因此我的问题 - 如何最好地响应 readyForMoreMediaData=NO 以及我是否可以像这样在主线程中稍等片刻:

while ( ![assetWriterInput readyForMoreMediaData] )
{
    Sleep for a few milliseconds
}
4

4 回答 4

4

小心不要仅仅阻塞线程,这是我在此之前所做的事情不起作用:

while (adaptor.assetWriterInput.readyForMoreMediaData == FALSE) {
  [NSThread sleepForTimeInterval:0.1];
}

上述方法有时会在我的 iPad2 上失败。这样做可以解决问题:

while (adaptor.assetWriterInput.readyForMoreMediaData == FALSE) {
  NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:0.1];
  [[NSRunLoop currentRunLoop] runUntilDate:maxDate];
}
于 2012-07-22T00:11:17.150 回答
2

找不到类似的东西,所以我把它留在这里。斯威夫特 4解决方案。最好使用精确的技术来解决这个问题。Fe 使用 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()
        }
    })
}

下一个:

func grabFrame(time: CMTime? = nil) {
    readyForMediaCondition?.lock()
    while !pixelBufferInput!.assetWriterInput.isReadyForMoreMediaData {
        readyForMediaCondition?.wait()
    }
    readyForMediaCondition?.unlock()

    // append your framebuffer here
}

最后不要忘记使观察者无效

readyForMediaObservation?.invalidate()
于 2018-03-27T09:12:48.707 回答
1
        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
        }
于 2018-09-29T08:44:22.273 回答
0

轮询不是可取的解决方案。

您应该使用requestMediaDataWhenReadyOnQueue

[writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{
    [writerInput appendSampleBuffer:nextBuffer];
}
于 2022-02-09T07:34:35.330 回答