XPC Service and AVFoundation



是否可以在XPC服务中使用AVFoundation和OpenCV?我有这么简单的代码

#include <opencv2/opencv.hpp>
#import <AVFoundation/AVFoundation.h>
@interface AppDelegate(){
    cv::VideoCapture m_vidCap;
}

//Hacky way of forcing OpenCV to call AVFoundation for the first time
    //before the camera arrives
    //OpenCV should add a better way of mapping camera indexes to cameras
    //This way we force that devices are enumerated in the same order here
    //and in their code
    m_vidCap.open(-1);
    m_vidCap.release();
[AVCaptureDevice devices]; //Force avfoundation "startup"
@autoreleasepool {
    std::vector<std::wstring> devices;
    // chosen device.
    NSArray *osDevices=[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    NSStringEncoding encoding    =   CFStringConvertEncodingToNSStringEncoding ( kCFStringEncodingUTF32LE );
    AVCaptureDevice *device;
    int did=0;
    for(device in osDevices) {
        NSString *deviceName=[device localizedName];
        NSData* wstrdata  = [deviceName dataUsingEncoding : encoding ];
        std::wstring cppDeviceName=std::wstring((wchar_t*) [ wstrdata bytes ], [ wstrdata length] / sizeof ( wchar_t ) );
        devices.push_back(cppDeviceName);
        //NSLog("Device %d: %S at position %ld",did,cppDeviceName.c_str(),device.position);
        did++;
    }
}

在常规 Cocoa 应用程序中启动时根据需要工作。它将枚举两个摄像头,FaceTime摄像头和USB摄像头。

如果我在我的XPC服务中放置相同的确切代码,它将永远挂起

m_vidCap.open(-1);

并且永远不会进一步执行。

我假设在XPC服务中可以使用的内容有一些限制,但我无法谷歌任何有用的东西。任何意见都非常感谢。感谢

你快到了!我认为AVFoundation需要使用NSRunLoop,但XPC服务默认使用dispatch_main。您需要向 XPC 服务的info.plist文件中的XPCService键标识的字典值添加一个键。默认情况下,它应该有一个ServiceType密钥。添加一个 RunLoopType 键,并为其指定字符串值 NSRunLoop

有关详细信息,请参阅创建 XPC 服务。

好吧,经过多次尝试并检查苹果的样本,我已经让它工作了。问题是如何创建NSXPCListener。在我像常规服务一样拥有它之前

NSXPCListener *listener = [NSXPCListener serviceListener];

这行不通。

在我改为

ToolMonitorDelegate *myDelegate = [[ToolMonitorDelegate alloc] initWithHardwareType:HT_Vision];
NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:bundleId];
listener.delegate = myDelegate;
[listener resume];
[[NSRunLoop currentRunLoop] run];

一切都立即工作。在我看来,OpenCV 需要运行应用程序循环才能正常工作。如果我错了或有其他解释,请纠正我。

最新更新