【问题标题】:AVAssetWriterInput and isReadyForMoreMediaData Problem create Video in SwiftAVAssetWriterInput 和 isReadyForMoreMediaData 问题在 Swift 中创建视频
【发布时间】:2019-08-10 17:33:05
【问题描述】:

我从图像创建视频,视频丢失了一些帧,因为 isReadyForMoreMediaData 有一段时间没有准备好。 当我调试时,我看到了循环的原因,它需要一些延迟时间来启动下一个缓冲区,但我不知道该怎么做。

{
           for nextDicData in self.selectedPhotosArray{      
                if (videoWriterInput.isReadyForMoreMediaData) {

                    if let nextImage = nextDicData["img"] as? UIImage
                    {
                        var frameDuration = CMTimeMake(Int64(0), fps)
                        if let timeVl = nextDicData["time"] as? Float{
                               framePerSecond = Int64(timeVl * 1000)
                            print("TIME FRAME : \(timeVl)")

                        }else{
                             framePerSecond = Int64(0.1 * 1000)
                        }

                        frameDuration =  CMTimeMake(framePerSecond ,fps)
                        let lastFrameTime = CMTimeMake(Int64(lastTimeVl), fps)
                        let presentationTime = CMTimeAdd(lastFrameTime, frameDuration)
                        var pixelBuffer: CVPixelBuffer? = nil
                        let status: CVReturn = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pixelBufferAdaptor.pixelBufferPool!, &pixelBuffer)
                        if let pixelBuffer = pixelBuffer, status == 0 {
                            let managedPixelBuffer = pixelBuffer
                            CVPixelBufferLockBaseAddress(managedPixelBuffer, CVPixelBufferLockFlags(rawValue: CVOptionFlags(0)))
                            let data = CVPixelBufferGetBaseAddress(managedPixelBuffer)
                            let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
                            let context = CGContext(data: data, width: Int(self.outputSize.width), height: Int(self.outputSize.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(managedPixelBuffer), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue)
                            context!.clear(CGRect(x: 0, y: 0, width: CGFloat(self.outputSize.width), height: CGFloat(self.outputSize.height)))
                            let horizontalRatio = CGFloat(self.outputSize.width) / nextImage.size.width
                            let verticalRatio = CGFloat(self.outputSize.height) / nextImage.size.height
                            //let aspectRatio = max(horizontalRatio, verticalRatio) // ScaleAspectFill
                            let aspectRatio = min(horizontalRatio, verticalRatio) // ScaleAspectFit
                            let newSize: CGSize = CGSize(width: nextImage.size.width, height: nextImage.size.height)
                            let x = newSize.width < self.outputSize.width ? (self.outputSize.width - newSize.width) / 2 : 0
                            let y = newSize.height < self.outputSize.height ? (self.outputSize.height - newSize.height) / 2 : 0

                            context?.draw(nextImage.cgImage!, in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
                            CVPixelBufferUnlockBaseAddress(managedPixelBuffer, CVPixelBufferLockFlags(rawValue: CVOptionFlags(0)))
                            appendSucceeded = pixelBufferAdaptor.append(pixelBuffer, withPresentationTime: presentationTime)


                        } else {
                            print("Failed to allocate pixel buffer")
                            appendSucceeded = false
                        }
                    }

                }else{
                    //not ready
                       print("write is Not Raady: \(lastTimeVl)")
                }
                if !appendSucceeded {
                    break
                }
                frameCount += 1
                lastTimeVl += framePerSecond
                print("LAST TIME : \(lastTimeVl)")


            }

【问题讨论】:

  • stackoverflow.com/questions/40883784/…> 我希望它会工作。
  • 谢谢,但不是我的问题

标签: swift video


【解决方案1】:

AVAssetWriterInput 可以帮助您管理它,并通过调用requestMediaDataWhenReady 让您知道isReadyForMoreMediaData 何时再次成为true

这是苹果文档中的一个例子(翻译成 Swift):

myAVAssetWriterInput.requestMediaDataWhenReady(on: queue) {
    while myAVAssetWriterInput.isReadyForMoreMediaData {
        let nextSampleBuffer = copyNextSampleBufferToWrite()
        if let nextSampleBuffer = nextSampleBuffer { 
            // you have another frame to add
            myAVAssetWriterInput.append(nextSampleBuffer)
        } else { 
            // finished to add frames
            myAVAssetWriterInput.markAsFinished()
            break
        }
    }
})

现在,当作者“突然”没有准备好时,不用担心, 它将在下一个 requestMediaDataWhenReady 回调中继续添加帧。

【讨论】:

    【解决方案2】:

    斯威夫特 5

    在pixelBufferAdaptor.append之后添加usleep。

    添加睡眠功能的原因是当有多个输入时,AVAssetWriter 会尝试以交错模式写入媒体数据,因此 writer 必须准备好下一个输入(在您的情况下为图像)才能按顺序追加数据。等待一段时间使其为下一次输入做好准备。link

     appendSucceeded = pixelBufferAdaptor.append(pixelBuffer, withPresentationTime: presentationTime)
     //VideoWriterInput must be paused for atleast 50 milliseconds or the buffer wont be ready to append new frame
     usleep(useconds_t(50000) )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      • 1970-01-01
      • 2021-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多