Camera_CustomCamera

演示如何使用非系统API的自定义摄像头创建一个EasyAR应用。

你可以参考这个sample,自己定制一个CameraDevice。这个sample使用系统API作为示例,不直接支持Android USB摄像头,如果需要应集成libuvc,可以参考 这个帖子

注:Windows USB摄像头有自带支持,不需要使用此示例。

注:使用视频流作为Camera也是可以的,你可以参考接口文档修改这个样例来实现。

用法

../../_images/image_20.png

详解

使用自定义FrameSource

在场景中使用自定义相机设备,只需要使用自定义的FrameSource替换VideoCamera。将它放到ARSession节点下面,session将会自动使用它。

../../_images/image_s15_1.png

继承CameraSource

这个sample继承CameraSource来实现camera功能。Override Open/Close/OnEnable/OnDisable 方法来让camera可以运行。

如果需要使用非camera的frame source,可以继承FrameSource而非CameraSource。

public override bool HasSpatialInformation
{
    get { return false; }
}

protected override void OnEnable()
{
    base.OnEnable();
#if !UNITY_EDITOR && UNITY_ANDROID
    if (externalCamera != null)
        externalCamera.Call<bool>("start", cameraCallback);
#elif !UNITY_EDITOR && UNITY_IOS
    if (externalCamera != null)
        externalCamera.start(cameraCallback);
#endif
}

protected override void OnDisable()
{
    base.OnDisable();
#if !UNITY_EDITOR && UNITY_ANDROID
    if (externalCamera != null)
        externalCamera.Call<bool>("stop");
#elif !UNITY_EDITOR && UNITY_IOS
    if (externalCamera != null)
        externalCamera.stop();
#endif
}

public override void Open()
{
}

public override void Close()
{
}

原生camera实现

这个sample使用原生camera代码来提供camera功能。不同平台的代码位于不同的地方。

Android实现在sample的 AndroidProject~ 文件夹内的Gradle工程中,它的输出被预先编译成custom-camera.jar并存在于sample的 Runtime/Android 文件夹中。 AndroidProject~ 在Unity编辑器中不会显示,可以在文件系统上直接查看。

iOS实现在sample的 Runtime/iOS 文件夹的MyCamera文件中。

使用原生代码实现camera设备可以使用系统camera提供最大的灵活性。你可以修改这些代码来让没有被集成到EasyAR VideoCameraDevice中的系统相机的功能工作。

暴露原生相机接口道C#

sample中有一部分代码用来将原生接口包装成C#接口以便在C#中访问。这些代码会直接调用Java或C接口。

private AndroidJavaObject externalCamera;
private CameraCallback cameraCallback;

private class CameraCallback : AndroidJavaProxy
{
}

private ExternalCamera externalCamera;
private Action<IntPtr, int> cameraCallback;

private class ExternalCamera : IDisposable
{
}

在相机回调中处理InputFrame

sample中Android 和 iOS 的实现都将camera的回调暴露到了C#。在回调中, InputFrameSink.handle 用来处理从原始图像数据创建的InputFrame。

private void HandleSink(Buffer imageBuffer, PixelFormat format, Vector2 imageSize, int orientation, int cameraType, double timestamp)
{
    using (var cameraParams = CameraParameters.createWithDefaultIntrinsics(new Vec2I((int)imageSize.x, (int)imageSize.y), (CameraDeviceType)cameraType, orientation))
    using (var image = new Image(imageBuffer, format, (int)imageSize.x, (int)imageSize.y))
    using (var frame = InputFrame.createWithImageAndCameraParametersAndTemporal(image, cameraParams, timestamp))
    {
        if (sink != null)
            sink.handle(frame);
    }
    imageBuffer.Dispose();
}