Swift - 从凸轮到服务器的实时图像

时间:2015-07-23 11:00:20

标签: ios swift real-time nsdata

我希望有人可以帮助我! 我正在制作一个应用程序,将相机的帧发送到服务器,服务器进行一些处理。应用程序每秒发送5-8张图像(在NSData格式上)

我尝试过不同的方法,这两种方法有效,但有不同的问题。 我将解释这些情况,也许有人可以帮助我。

我尝试的第一种情况是使用 AVCaptureVideoDataOutput 模式。

以下代码:

let captureSession = AVCaptureSession()
captureSession.sessionPreset=AVCaptureSessionPresetiFrame960x540
captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &error))

let output=AVCaptureVideoDataOutput();
    output.videoSettings=[kCVPixelBufferPixelFormatTypeKey:kCVPixelFormatType_32BGRA]

let cameraQueue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL)
        output.setSampleBufferDelegate(self, queue: cameraQueue)
        captureSession.addOutput(output)

        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        videoPreviewLayer?.frame = view.layer.bounds
        viewPreview?.layer.addSublayer(videoPreviewLayer)


        captureSession.startRunning()

此视图代表: 的 AVCaptureMetadataOutputObjectsDelegate AVCaptureVideoDataOutputSampleBufferDelegate 并调用委托方法:

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBufferRef!, fromConnection connection: AVCaptureConnection!)
    {
      let imagen:UIImage=imageFromSampleBuffer(sampleBuffer)
      let dataImg:NSdata=UIImageJPEGRepresentation(imagen,1.0)
      //Here I send the NSData to server correctly.
    }

此方法调用imageFromSampleBuffer并将samplebuffer转换为uiimage。

    func imageFromSampleBuffer(sampleBuffer :CMSampleBufferRef) -> UIImage {
                let imageBuffer: CVImageBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)
                CVPixelBufferLockBaseAddress(imageBuffer, 0)
                let baseAddress: UnsafeMutablePointer<Void> = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, Int(0))

                let bytesPerRow: Int = CVPixelBufferGetBytesPerRow(imageBuffer)
                let width: Int = CVPixelBufferGetWidth(imageBuffer)
                let height: Int = CVPixelBufferGetHeight(imageBuffer)

                let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()

                let bitsPerCompornent: Int = 8
                var bitmapInfo = CGBitmapInfo((CGBitmapInfo.ByteOrder32Little.rawValue | CGImageAlphaInfo.PremultipliedFirst.rawValue) as UInt32)
                let newContext: CGContextRef = CGBitmapContextCreate(baseAddress, width, height, bitsPerCompornent, bytesPerRow, colorSpace, bitmapInfo) as CGContextRef

                let imageRef: CGImageRef = CGBitmapContextCreateImage(newContext)
                let resultImage = UIImage(CGImage: imageRef, scale: 1.0, orientation: UIImageOrientation.Right)!
                return resultImage
            } 

这里完成第一个方法,问题是“无限内存使用”,应用程序在...... 2分钟后崩溃。

我调试和问题是在 UIImageJPEGRepresentation(imagen,1.0)方法,有任何形式在使用方法后释放内存???

第二个(我认为最好的方法)是使用“AVCaptureStillImageOutput”

以下代码:

var stillImageOutput: AVCaptureStillImageOutput = AVCaptureStillImageOutput()
            if session.canAddOutput(stillImageOutput){
                stillImageOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
                session.addOutput(stillImageOutput)

                self.stillImageOutput = stillImageOutput
            }

var timer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector:  Selector("methodToBeCalled"), userInfo: nil, repeats: true)


 func methodToBeCalled(){

            dispatch_async(self.sessionQueue!, {
                // Update the orientation on the still image output video connection before capturing.
                let videoOrientation =  (self.previewView.layer as! AVCaptureVideoPreviewLayer).connection.videoOrientation
                self.stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo).videoOrientation = videoOrientation
                self.stillImageOutput!.captureStillImageAsynchronouslyFromConnection(self.stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo), completionHandler: {
                    (imageDataSampleBuffer: CMSampleBuffer!, error: NSError!) in

                    if error == nil {
                        let dataImg:NSdata= AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
//Here I send the NSData to server correctly.

                    }else{println(error)}
                })
            })

    }

这很完美,没有内存泄漏,但当应用程序采用屏幕截图时,手机发出“拍照”的典型声音,我不能允许它,有任何方法可以做到这一点而不发出声音??。

如果有人需要代码,我可以分享我找到它们的链接。

非常感谢!

2 个答案:

答案 0 :(得分:0)

你有没有设法自己解决这个问题?

我偶然发现了这个问题,因为我正在将一个带有AVCaptureSession的Objective-C项目转换为Swift。我的代码做的不同的是丢弃AVCaptureVideoDataOutput中的后期帧,这可能会导致你的内存问题。

output.alwaysDiscardsLateVideoFrames = true

在定义视频数据输出之后和创建队列之前立即插入此行:

let output=AVCaptureVideoDataOutput();
output.videoSettings=[kCVPixelBufferPixelFormatTypeKey:kCVPixelFormatType_32BGRA]
output.alwaysDiscardsLateVideoFrames = true
let cameraQueue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL)

我当然是指你的两个解决方案中的第一个。

答案 1 :(得分:-3)

无法禁止用户截屏。甚至连Snapchat也无法做到。