001/*
002 * Copyright (C) Photon Vision.
003 *
004 * This program is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package org.photonvision.vision.camera.csi;
019
020import edu.wpi.first.cscore.VideoMode;
021import edu.wpi.first.util.PixelFormat;
022import org.photonvision.common.configuration.CameraConfiguration;
023import org.photonvision.common.configuration.ConfigManager;
024import org.photonvision.common.logging.LogGroup;
025import org.photonvision.common.logging.Logger;
026import org.photonvision.vision.camera.CameraType;
027import org.photonvision.vision.camera.QuirkyCamera;
028import org.photonvision.vision.frame.FrameProvider;
029import org.photonvision.vision.frame.provider.LibcameraGpuFrameProvider;
030import org.photonvision.vision.processes.VisionSource;
031import org.photonvision.vision.processes.VisionSourceSettables;
032
033public class LibcameraGpuSource extends VisionSource {
034    static final Logger logger = new Logger(LibcameraGpuSource.class, LogGroup.Camera);
035
036    private final LibcameraGpuSettables settables;
037    private LibcameraGpuFrameProvider frameProvider;
038
039    public LibcameraGpuSource(CameraConfiguration configuration) {
040        super(configuration);
041        if (configuration.matchedCameraInfo.type() != CameraType.ZeroCopyPicam) {
042            throw new IllegalArgumentException(
043                    "GPUAcceleratedPicamSource only accepts CameraConfigurations with type Picam");
044        }
045
046        if (getCameraConfiguration().cameraQuirks == null)
047            getCameraConfiguration().cameraQuirks = QuirkyCamera.ZeroCopyPiCamera;
048
049        settables = new LibcameraGpuSettables(configuration);
050        frameProvider = new LibcameraGpuFrameProvider(settables);
051    }
052
053    @Override
054    public FrameProvider getFrameProvider() {
055        return frameProvider;
056    }
057
058    @Override
059    public VisionSourceSettables getSettables() {
060        return settables;
061    }
062
063    @Override
064    public void remakeSettables() {
065        // Nothing to do, settables for this type of VisionSource should never be
066        // remade.
067        return;
068    }
069
070    /**
071     * On the OV5649 the actual FPS we want to request from the GPU can be higher than the FPS that we
072     * can do after processing. On the IMX219 these FPSes match pretty closely, except for the
073     * 1280x720 mode. We use this to present a rated FPS to the user that's lower than the actual FPS
074     * we request from the GPU. This is important for setting user expectations, and is also used by
075     * the frontend to detect and explain FPS drops. This class should ONLY be used by Picam video
076     * modes! This is to make sure it shows up nice in the frontend
077     */
078    public static class FPSRatedVideoMode extends VideoMode {
079        public final int fpsActual;
080        public final double fovMultiplier;
081
082        public FPSRatedVideoMode(
083                PixelFormat pixelFormat,
084                int width,
085                int height,
086                int ratedFPS,
087                int actualFPS,
088                double fovMultiplier) {
089            super(pixelFormat, width, height, ratedFPS);
090
091            this.fpsActual = actualFPS;
092            this.fovMultiplier = fovMultiplier;
093        }
094    }
095
096    @Override
097    public boolean isVendorCamera() {
098        return ConfigManager.getInstance().getConfig().getHardwareConfig().hasPresetFOV();
099    }
100
101    @Override
102    public boolean hasLEDs() {
103        return (ConfigManager.getInstance().getConfig().getHardwareConfig().ledPins.size() > 0);
104    }
105
106    @Override
107    public void release() {
108        frameProvider.release();
109        frameProvider = null;
110    }
111}