2015-07-23 2 views
0

Надеюсь, кто-то может мне помочь! Я делаю приложение, которое отправляет кадры камеры на сервер, а сервер делает какой-то процесс. Приложение отправляет 5-8 изображений в секунду (в формате NSData)Swift - изображения в реальном времени с камеры на сервер

Я пробовал разные способы сделать это, эти два метода работают, но имеют разные проблемы. Я объясню эти ситуации, и, может быть, кто-то может мне помочь.

В первой ситуации я пытался использовать 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 минут.

I Debug and problem is on 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)} 
       }) 
      }) 

    } 

Это прекрасно работает и без утечек памяти, но когда приложение снимает скриншот, телефон делает типичный звук «сфотографировать», и я не могу этого допустить, есть ли способ сделать это без звука.

Если кому-то нужен код, я могу поделиться ссылками, где я их нашел.

Большое спасибо!

ответ

-3

Невозможно запретить пользователям делать снимок экрана. Даже snapchat может это сделать.

+0

Это не вопрос:/ –

+0

Это то, что вы написали: «Я не могу этого допустить, есть ли способ сделать это без звука». –

+0

Я не могу позволить звук, потому что я не могу заставить пользователя отключить телефон. –

0

Вам удалось решить эту проблему самостоятельно?

Я наткнулся на этот вопрос, потому что я конвертирую проект Objective-C с AVCaptureSession в 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) 

Я, конечно, ссылаясь на первый из двух ваших решений.

Смежные вопросы