AVAssetWriterInput和readyForMoreMediaData

时间:2011-05-04 00:12:00

标签: iphone ios4 iphone-sdk-3.0 avfoundation avassetwriter

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

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

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

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

3 个答案:

答案 0 :(得分:3)

小心不要只是阻止线程,这是我在做的之前没做的事情:

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];
}

答案 1 :(得分:0)

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

答案 2 :(得分:0)

        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
        }