1

I'm trying to write a mac app that can capture screenshots/video from an connected ipad like quicktime or zoom can. I'm trying to use the AVCapturePhotoOutput class, but the func capturePhoto(with: AVCapturePhotoSettings, delegate: AVCapturePhotoCaptureDelegate) method isn't calling any of the methods of my delegate, but I don't see any other errors. Am I setting the AVCapturePhotoSettings incorrectly, or missing a step in setting up my capture session?

Here's the code that sets up a AVCaptureSession and tries to call capturePhoto:

let device : AVCaptureDevice = message.object as! AVCaptureDevice;
                    print(device.deviceType, " localized name: ", device.localizedName, " model id", device.modelID)
                    var session = AVCaptureSession();
                    
                    let photoOutput = AVCapturePhotoOutput()
                    
                    session.beginConfiguration()
                    
                    guard session.canAddOutput(photoOutput) else { return }
                    session.sessionPreset = .photo
                    session.addOutput(photoOutput)
                    print("output added to session")
                    do {
                        try session.addInput(AVCaptureDeviceInput(device: device));
                        print("input added to session")
                        session.commitConfiguration();
                        session.startRunning();
                        print("session running")
                        
                        let photoSettings = AVCapturePhotoSettings()

                        print("about to try to capture a photo with",  device.localizedName)
                        photoOutput.capturePhoto(with: photoSettings, delegate: PhotoDelegate(theCV: self))
                        
                    } catch {
                        print("couldn't add capture device as input")
                    }
                }

And here is my Delegate, and none of these methods are being called after I trigger the capture.

class PhotoDelegate : NSObject, AVCapturePhotoCaptureDelegate{
    var cv : ContentView
    init(theCV : ContentView){
        cv = theCV
        print("delegate constructed")
    }

    
    func photoOutput(_ output: AVCapturePhotoOutput,
                     didFinishProcessingPhoto photo: AVCapturePhoto,
                     error: Error?){
        print("got the ipad photo!")
        print(photo.timestamp)
        
    }
    
    func photoOutput(_: AVCapturePhotoOutput, willBeginCaptureFor: AVCaptureResolvedPhotoSettings){
        print("starting the capture")
    }
    
    func photoOutput(_: AVCapturePhotoOutput, didFinishCaptureFor: AVCaptureResolvedPhotoSettings, error: Error?){
        print("did finish capture")
    }
    
   
}

Output that I'm seeing (from what I read, the errors are unrelated logspam, but I'm no expert)

AVCaptureDeviceType(_rawValue: AVCaptureDeviceTypeExternalUnknown)  localized name:  Ben’s iPad  model id iOS Device
output added to session
input added to session
2022-01-07 20:48:26.165436-0700 presenterMode[65303:6394791] [] CMIOHardware.cpp:379:CMIOObjectGetPropertyData Error: 2003332927, failed
2022-01-07 20:48:26.165502-0700 presenterMode[65303:6394791] [] CMIO_DALA_Object.cpp:518:GetPropertyData Error: 2003332927, got an error getting the property data mObjectID 39
2022-01-07 20:48:26.168461-0700 presenterMode[65303:6394791] [] CMIOHardware.cpp:420:CMIOObjectSetPropertyData property isn't settable pft  glob
2022-01-07 20:48:26.168546-0700 presenterMode[65303:6394791] [] CMIOHardware.cpp:450:CMIOObjectSetPropertyData Error: 1852797029, failed
2022-01-07 20:48:26.170321-0700 presenterMode[65303:6394791] [] CMIOHardware.cpp:379:CMIOObjectGetPropertyData Error: 2003332927, failed
2022-01-07 20:48:26.170527-0700 presenterMode[65303:6394791] [] CMIOHardware.cpp:379:CMIOObjectGetPropertyData Error: 2003332927, failed
2022-01-07 20:48:26.170552-0700 presenterMode[65303:6394791] [] CMIO_DALA_Object.cpp:518:GetPropertyData Error: 2003332927, got an error getting the property data mObjectID 39
session running
about to try to capture a photo with Ben’s iPad
delegate constructed

Ben Jones
  • 919
  • 1
  • 8
  • 22
  • 1
    Have you tried holding a strong reference to your `PhotoDelegate`? I'd be willing to believe that `AVCapturePhotoOutput` only holds a weak reference to it, so it gets removed from memory immediately right now. – jnpdx Jan 08 '22 at 04:03
  • That was the issue. Thanks! Is there a better way to make a strong reference than making it a @State var of my view? I don't usually write swift, and am just using it for the APIs for this stuff – Ben Jones Jan 08 '22 at 04:18
  • It's a little hard to say without seeing a [mre]. What I will say is that you *definitely* shouldn't be trying to hold/pass a reference to a `View` like you are passing `self` to `PhotoDelegate` -- you can't rely on SwiftUI views remaining constant over time. Most likely, `PhotoDelegate` should be an `ObservableObject` and be a `@StateObject` on your `View` and the `View` should react to `@Published` properties on it. – jnpdx Jan 08 '22 at 04:21
  • Ah, yeah, that makes a lot of sense. Thanks again for all the help – Ben Jones Jan 08 '22 at 18:45

0 Answers0