본문 바로가기

프로그래밍/iOS,macOS

[iOS] GPUImage

constraint 관련 에러

GPUImage2
실행에는 문제가 없는데 콘솔로그상으로 Background Thread 에서 ui 요소에 접근했다는 오류 발생
아래 주소의 jwoodrow comment.
https://github.com/BradLarson/GPUImage2/issues/226

/Outputs/iOS/RenderView-UIKit.swift

func createDisplayFramebuffer() {
    .
    .
    .
    
    let group = DispatchGroup()
    group.enter()
    DispatchQueue.main.async {
        sharedImageProcessingContext.context.renderbufferStorate(
            Int(GL_RENDERBUFFER), 
            from: self.layer as! CAEAGLLayer )
        group.leave()
    }
    group.wait()
    
    .
    .
    .
}

 


GPUImage

private func startCapture() -> Void {

    // 비디오 카메라 초기화
    videoCamera = GPUImageVideoCamera.init(
        sessionPreset: AVCaptureSession.Preset.hd1280x720.rawValue,
        cameraPosition: AVCaptureDevice.Position.front)
    
    guard let videoCamera = self.videoCamera
    else {
        // 비디오 카메라 생성 실패
        return
    }
    
    // 카메라 출력 설정
    // RemonSampleCapturer는 입력되는 소스의 orientation을 그대로 전송합니다.
    // 다양한 카메라 방향을 지원하려면 해당 라이브러리를 통해 직접 처리해야 합니다.
    // 본 예제에서는 세로모드(portrait)의 출력 데이터를 사용합니다.
    videoCamera.outputImageOrientation = UIInterfaceOrientation.portrait
    videoCamera.horizontallyMirrorFrontFacingCamera = false
    videoCamera.horizontallyMirrorRearFacingCamera = false
    videoCamera.frameRate = 24

    
    
    // 카메라 필터 예
    let filter:GPUImageToonFilter = GPUImageToonFilter()
    filter.quantizationLevels = 5.0
    filter.threshold = 10.0
    
    // 카메라에 필터 추가
    videoCamera.addTarget(filter)

    
    // raw data output
    // 보통 GPUImageRawDataOutput 클래스를 상속받아 newFrameReady, newFrameAvailableBlock을 사용
    guard let op = GPUImageRawDataOutput.init(
                       imageSize: CGSize.init(width: 720, height: 1280), 
                       resultsInBGRAFormat: true)  else {
        return
    }
    filter.addTarget(op)
    
    // 캡처 시작
    videoCamera.startCapture()

    // 라이브러리의 프레임 출력 : GPUImageOutput, 타임스탬프
    filter.frameProcessingCompletionBlock = { [weak self](imageOutput, time) in
        self?.cmTime = time
        
        
    }
    
    
    // CVPixelBuffer 를 생성해 복사뒤 SDK로 전달
    op.newFrameAvailableBlock = { [weak self]() in
        op.lockFramebufferForReading()
        let pointer = op.rawBytesForImage
        let bytesPerRow = Int(op.bytesPerRowInOutput())
        let width = Int(op.maximumOutputSize().width)
        let height = Int(op.maximumOutputSize().height)
        let data = CFDataCreate(kCFAllocatorDefault, 
                                op.rawBytesForImage, 
                                bytesPerRow*height)
        op.unlockFramebufferAfterReading()
        
        let unmanagedData = Unmanaged<CFData>.passRetained(data!)
        var pixelBuffer: CVPixelBuffer?
        let status = CVPixelBufferCreateWithBytes( 
                         kCFAllocatorDefault,
                         width,
                         height,
                         kCVPixelFormatType_32BGRA,
                         pointer!,
                         bytesPerRow,
                         { 
                             (releaseContext, baseAddress) in
                             let contextData = Unmanaged<CFData>.fromOpaque(releaseContext!)
                             contextData.release() 
                         },
                         unmanagedData.toOpaque(),
                         nil,
                         &pixelBuffer)

        if (status != kCVReturnSuccess) {
            return
        }

        // pixelBuffer를 전달하거나 사용
            .
            .
            .
        
    }
}

 


GPUImage2 RawDataOutput
* 색상이 이상하게 나온다면 RawDataOutput 의 glReadPixels() 메쏘드의 픽셀포맷을 GLenum(GL_BGRA) 로 변경 필요

// 버퍼의 가로 세로 크기는 각 입력 필터에 따라 변경
// 카메라인 경우 AVCaptureSessionPreset 의 값으로 설정
// 이미지프로세싱 필터들은 overriddenOutputSize 에 값을 설정후 해당 사이즈로 width, height 설정
let width = 1080
let height = 1920

self.rawDataOutput = RawDataOutput()
self.rawDataOutput.dataAvailableCallback = {
    array in
    array.withUnsafeBytes {
        (ptr:UnsafeRawBufferPointer) in
        let rawPointer = UnsafeMutableRawPointer(mutating: ptr.baseAddress!)
        
        var pixelBuffer: CVPixelBuffer?
        let status = CVPixelBufferCreateWithBytes(
                           kCFAllocatiorDefault,
                           width,
                           height,
                           kCVPixelFormatType_32BGRA,
                           rawPointer,
                           Int( width*4 ),
                           nil,
                           nil,
                           nil,
                           &pixelBuffer)
    }

}