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.raspi;
019
020import java.io.File;
021import java.io.FileOutputStream;
022import java.io.IOException;
023import org.photonvision.common.logging.LogGroup;
024import org.photonvision.common.logging.Logger;
025
026/**
027 * Helper for extracting photon-libcamera-gl-driver shared library files. TODO: Refactor to use
028 * PhotonJNICommon
029 */
030public class LibCameraJNILoader {
031    private static boolean libraryLoaded = false;
032    private static final Logger logger = new Logger(LibCameraJNILoader.class, LogGroup.Camera);
033
034    public static synchronized void forceLoad() throws IOException {
035        if (libraryLoaded) return;
036
037        var libraryName = "photonlibcamera";
038
039        try {
040            // We always extract the shared object (we could hash each so, but that's a lot of work)
041            var arch_name = "linuxarm64";
042            var nativeLibName = System.mapLibraryName(libraryName);
043            var resourcePath = "/nativelibraries/" + arch_name + "/" + nativeLibName;
044            var in = LibCameraJNILoader.class.getResourceAsStream(resourcePath);
045
046            if (in == null) {
047                logger.error("Failed to find internal native library at path " + resourcePath);
048                libraryLoaded = false;
049                return;
050            }
051
052            // It's important that we don't mangle the names of these files on Windows at least
053            File temp = new File(System.getProperty("java.io.tmpdir"), nativeLibName);
054            FileOutputStream fos = new FileOutputStream(temp);
055
056            int read = -1;
057            byte[] buffer = new byte[1024];
058            while ((read = in.read(buffer)) != -1) {
059                fos.write(buffer, 0, read);
060            }
061            fos.close();
062            in.close();
063
064            System.load(temp.getAbsolutePath());
065
066            logger.info("Successfully loaded shared object " + temp.getName());
067
068        } catch (UnsatisfiedLinkError e) {
069            logger.error("Couldn't load shared object " + libraryName, e);
070            e.printStackTrace();
071            // logger.error(System.getProperty("java.library.path"));
072        }
073        libraryLoaded = true;
074    }
075
076    public static boolean isSupported() {
077        return libraryLoaded && LibCameraJNI.isSupported();
078    }
079}