使用AVAssetWriter停止视频录制(finishWriting)并且不会崩溃的正确方法

时间:2017-07-27 10:08:06

标签: ios swift avassetwriter cmsamplebuffer avassetwriterinput

我使用AVAssetWriter录制视频。用户可以发送视频,然后拨打finishWriting或取消录制,然后拨打cancelWriting

我如何录制:

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!){
        guard !message_to_send else{
            return
        }
        guard is_recording else{
            return
        }
        guard CMSampleBufferDataIsReady(sampleBuffer) else{
            print("data not ready")
            return
        }
        guard let w=file_writer else{
            print("video writer nil")
            return
        }
        guard let sb=sampleBuffer else{
            return
        }

        if w.status == .unknown /*&& start_recording_time==nil*/{
            if captureOutput==video_output{
                print("\nSTART RECORDING")
                w.startWriting()
                start_recording_time=CMSampleBufferGetPresentationTimeStamp(sb)
                w.startSession(atSourceTime: start_recording_time!)
            }else{
                return
            }
        }

        if w.status == .failed{
            print("failed with error:", w.error ?? "")
            stop_record()
            return
        }

        guard w.status == .writing else{
            print("not writing")
            return
        }

        if captureOutput==audio_output{
            if audio_writer.isReadyForMoreMediaData && video_written{
                audio_writer.append(sb)
            }else{
                print("audio writer not ready OR video not written yet")
            }
        }else if captureOutput==video_output{
            if video_writer.isReadyForMoreMediaData /*&& is_recording*/{
                video_writer.append(sb)   // << this line gets called after stop_record is called and causes a crash
                if !video_written{
                    print("added 1st video frame")
                    video_written=true
                }
                //print("write video")
            }else{
                print("video writer not ready")
            }
        }
    }
}

我如何停止录制:

func stop_record(){
        print("\nstop_record")
        guard is_recording else{
            print("not recording > return")
            return
        }

        is_recording=false
        cam_q.async{
            self.is_recording=false
        }

        print("file writer status", file_writer.status.rawValue)
        if file_writer.status.rawValue==1{
            self.video_writer?.markAsFinished()
            print("video finished")
            self.audio_writer?.markAsFinished()
            print("audio finished")
        }else{
            print("not writing")
        }

        if !self.message_to_send{
            print("cancel writing")
            self.file_writer.cancelWriting()
            return
        }

        file_writer.finishWriting(){
            print("finished writing")
            DispatchQueue.main.async{
                let st=self.file_writer.status
                if st == .failed{
                    print("status: failed")
                }else if st == .completed{
                    print("status: completed")
                }else if st == .cancelled{
                    print("status: cancelled")
                }else{
                    print("status: unknown")
                }

                if let e=self.file_writer.error{
                    print("stop record error:", e)
                }

                if self.message_to_send{
                    send_message()
                }
            }
        }
    }

当我致电stop_record时,有时它会崩溃。即使file_writer应该停止写作,如果我在didOutputSampleBuffer中进行多次验证,也会调用此行:

  

video_writer.append(SB)

我得到了:

  

STOP_RECORD

     

文件编写者状态1

     

视频已完成

     

音频完了

     

libc ++ abi.dylib:以未捕获的类型异常终止   NSException

我尝试了相同的代码而没有调用markAsFinished,但它也崩溃了(我经常说)。

我想知道这是否是一个线程问题(因为在同一个线程上没有调用stop_recorddidOutputSampleBuffer方法)。无论如何,我不知道我做错了什么。如果有人可以帮我这个,我真的很感激。

0 个答案:

没有答案