Как я могу захватить видео с меняющимся CIImage без использования камеры? - PullRequest
0 голосов
/ 07 ноября 2019

Я уже задавал вопрос без каких-либо ответов здесь: Как записать изменения в CIImage для видео с использованием AVAssetWriter?

Но, возможно, мой вопрос должен быть проще. Мой поиск в Google оказался бесплодным. Как мне захватить видео с изменяющимся CIImage в реальном времени, без использования камеры?

Используя captureOutput, я получаю CMSampleBuffer, который я могу преобразовать в CVPixelBuffer. MediaType AVAssetWriterInput установлен на видео, но я думаю, что он ожидает сжатое видео. Кроме того, мне неясно, должно ли свойство AVAssetWriterInput ExpectedMediaDataInRealTime быть установлено в true или нет.

Похоже, оно должно быть довольно простым, но все, что я пытался, приводит к сбою статуса моего AVAssetWriter.

Вот моя последняя попытка сделать эту работу. По-прежнему не удается:

@objc func importLivePreview(){

    guard var importedImage = importedDryCIImage else { return }

    DispatchQueue.main.async(){

        // apply filter to camera image
        // this is what makes the CIImage appear that it is changing
        importedImage = self.applyFilterAndReturnImage(ciImage: importedImage, orientation: UIImage.Orientation.right, currentCameraRes:currentCameraRes!)


        if self.videoIsRecording &&
           self.assetWriterPixelBufferInput?.assetWriterInput.isReadyForMoreMediaData == true {

            guard let writer: AVAssetWriter = self.assetWriter, writer.status == .writing else {
                return
            }                       

            guard let cv:CVPixelBuffer = self.buffer(from: importedImage) else {
                print("CVPixelBuffer could not be created.")
                return
            }

            self.MTLContext?.render(_:importedImage, to:cv)

            self.currentSampleTime = CMTimeMakeWithSeconds(0.1, preferredTimescale: 1000000000)

            guard let currentSampleTime = self.currentSampleTime else {
                return
            }

            let success = self.assetWriterPixelBufferInput?.append(cv, withPresentationTime: currentSampleTime)

            if success == false {
                print("Pixel Buffer input failed")
            }

        }

        guard let MTLView = self.MTLCaptureView else {
            print("MTLCaptureView is not found or nil.")
            return
        }

        // update the MTKView with the changed CIImage so the user can see the changed image
        MTLView.image = importedImage


    }           

}

1 Ответ

0 голосов
/ 07 ноября 2019

Я получил это работает. Проблема была в том, что я не компенсировал currentSampleTime. В этом примере нет точных смещений, но он показывает, что его нужно добавить в последний раз.

@objc func importLivePreview(){

    guard var importedImage = importedDryCIImage else { return }

    DispatchQueue.main.async(){

        // apply filter to camera image
        // this is what makes the CIImage appear that it is changing
        importedImage = self.applyFilterAndReturnImage(ciImage: importedImage, orientation: UIImage.Orientation.right, currentCameraRes:currentCameraRes!)


        if self.videoIsRecording &&
           self.assetWriterPixelBufferInput?.assetWriterInput.isReadyForMoreMediaData == true {

            guard let writer: AVAssetWriter = self.assetWriter, writer.status == .writing else {
                return
            }                       

            guard let cv:CVPixelBuffer = self.buffer(from: importedImage) else {
                print("CVPixelBuffer could not be created.")
                return
            }

            self.MTLContext?.render(_:importedImage, to:cv)

            guard let currentSampleTime = self.currentSampleTime else {
                return
            }

            // offset currentSampleTime
            let sampleTimeOffset = CMTimeMakeWithSeconds(0.1, preferredTimescale: 1000000000)

            self.currentSampleTime = CMTimeAdd(currentSampleTime, sampleTimeOffset)

            print("currentSampleTime = \(String(describing: currentSampleTime))")

            let success = self.assetWriterPixelBufferInput?.append(cv, withPresentationTime: currentSampleTime)

            if success == false {
                print("Pixel Buffer input failed")
            }

        }

        guard let MTLView = self.MTLCaptureView else {
            print("MTLCaptureView is not found or nil.")
            return
        }

        // update the MTKView with the changed CIImage so the user can see the changed image
        MTLView.image = importedImage


    }           

}
...