###前提・実現したいこと
・背景
最近、間違えてiPhoneのiOSをバージョンアップしてしまい同時にXcodeもバージジョンアップしないといけなくなり、バージョンアップをしてSwift4,Xcode9にしたところ今まで、呼び出せていたカメラが呼び出せなくなりました。(具体的には、カメラが取得した画像がリアルタイムに表示されず真っ白な状態になっている)
・試したこと
前回のSwift3のアップデートはinfo.plistが原因でしたが、今回は
Privacy - Camera Usage Description と
Privacy - Photo Library Additions Usage Descriptionが追加してあるのでinfo.plistが原因ではないということがわかっているのですが、どこのコードが不具合を起こしているなど見つけられず手詰まりとなっています。
お手数をおかけしますがご教授お願いいたします。
###該当のソースコード
CameraUtil.swift
import Foundation import UIKit import AVFoundation import SpriteKit class CameraUtil { //sampleBufferからUIImageへ変換 class func imageFromSamleBuffer(_ sampleBuffer: CMSampleBuffer) -> UIImage { let imageBuffer: CVImageBuffer! = CMSampleBufferGetImageBuffer(sampleBuffer) //ベースアドレスをロック CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: CVOptionFlags(0))) //画像データの情報を取得 let baseAddress: UnsafeMutableRawPointer = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)! let bytesPerRow: Int = CVPixelBufferGetBytesPerRow(imageBuffer) let width: Int = CVPixelBufferGetWidth(imageBuffer) let height: Int = CVPixelBufferGetHeight(imageBuffer) //RGB色空間を作成 let colorSpace: CGColorSpace! = CGColorSpaceCreateDeviceRGB() //Bitmap graphic contextを作成 let bitsPerCompornent: Int = 8 let bitmapInfo = CGBitmapInfo(rawValue: (CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue) as UInt32) let newContext: CGContext! = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: bitsPerCompornent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) as CGContext! //Quartz image を作成 let imageRef: CGImage! = newContext!.makeImage() //ベースアドレスをアンロック CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: CVOptionFlags(0))) //UIImage作成 let resultImage: UIImage = UIImage(cgImage: imageRef) return resultImage } }
ViewController.swift
import UIKit import AVFoundation import SpriteKit class ViewController: UIViewController { @IBOutlet weak var viewImage: UIImageView! //セッション キャプチャに関する入力と出力の管理 var mySession : AVCaptureSession! //カメラデバイス カメラやマイクといったデバイスそのものを表現 var myDevice : AVCaptureDevice! //出力先 サブクラス 動画フレームデータ var myOutput : AVCaptureVideoDataOutput! //カメラの準備処理 func initCamera() -> Bool { //セッションの作成 mySession = AVCaptureSession() //解像度の指定 mySession.sessionPreset = AVCaptureSession.Preset.vga640x480 //デバイス一覧の取得 let devices = AVCaptureDevice.devices() //バックカメラをmyDeviceに格納 for device in devices { //全面か背面かの指定(どちらかをコメントアウトしておくこと) //全面 //if((device as AnyObject).position == AVCaptureDevicePosition.front){ //背面 if((device as AnyObject).position == AVCaptureDevice.Position.back){ myDevice = device } } if myDevice == nil{ return false } //バックカメラからVideoInputを取得 var myInput : AVCaptureDeviceInput! = nil do { myInput = try AVCaptureDeviceInput(device: myDevice) as AVCaptureDeviceInput } catch let error { print(error) } //セッションに追加 if mySession.canAddInput(myInput){ mySession.addInput(myInput) } else { return false } //出力先を設定 myOutput = AVCaptureVideoDataOutput() myOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable as! String:Int(kCVPixelFormatType_32BGRA)] //FPSを設定 do { try myDevice.lockForConfiguration() myDevice.activeVideoMinFrameDuration = CMTimeMake(1, 30) myDevice.unlockForConfiguration() } catch let error { print("lock error: (error)") return false } //デリケートを設定 let queue: DispatchQueue = DispatchQueue(label: "myqueue", attributes: []) myOutput.setSampleBufferDelegate(self as? AVCaptureVideoDataOutputSampleBufferDelegate, queue: queue) //遅れてきたフレームは無視するかしないか myOutput.alwaysDiscardsLateVideoFrames = true //セッションに追加 if mySession.canAddOutput(myOutput){ mySession.addOutput(myOutput) } else { return false } //カメラの向きを合わせる for connection in myOutput.connections{ let conn = connection if conn.isVideoOrientationSupported{ conn.videoOrientation = AVCaptureVideoOrientation.portrait } } return true } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //カメラを準備 if initCamera(){ mySession.startRunning() } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //毎フレーム実行される処理 func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!){ //同期処理(非同期処理ではキューが溜まりすぎて画面がついていけない) DispatchQueue.main.sync(execute:{ //CMSampleBufferRefからUIImageへ変換 let image = CameraUtil.imageFromSamleBuffer(sampleBuffer) self.viewImage.image = image }) } }
###補足情報(言語/FW/ツール等のバージョンなど)
Xcode9 Swift4 iOS11
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。