/** * WebcamStudio for GNU/Linux * Copyright (C) 2008 Patrick Balleux * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * */ /* * Original code was from: * mjpegtools_yuv_to_v4l.c * Copyright (c) Jan Panteltje 2008-always * This software is distributed under the GNU public license version 2 * See also the file 'COPYING'. * * See his site : http://panteltje.com/panteltje/mcamip/ * * Thanks for your work Jan! * * Recoded in java by Patrick Balleux (2008) * * */ package webcamstudio.exporter.vloopback; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; import webcamstudio.InfoListener; /** * * @author pballeux */ public class V4LLoopback extends VideoOutput { final static int VIDEO_PALETTE_YUV420P = 15; final static int VIDEO_PALETTE_RGB24 = 4; final static int VIDEO_PALETTE_RGB32 = 5; final static int VIDEO_PALETTE_UYVY = 9; final static int O_RDWR = 2; final static int VIDIOCGCAP = -2143521279; final static int VIDIOCGPICT = -2146535930; private static final int VIDIOCSPICT = 1074689543; private static int VIDIOCGWIN = -2145356279; private static int VIDIOCSWIN = 1075869194; private int fmt = VIDEO_PALETTE_YUV420P; private byte[] buffer = null; public V4LLoopback(InfoListener l) { //We have to detect if we are in 32bits or 64bits listener = l; // System.out.println("Pointer Size: " + com.sun.jna.Native.POINTER_SIZE); switch (Native.POINTER_SIZE) { case 4: VIDIOCGWIN = -2145356279; VIDIOCSWIN = 1075869194; break; case 8: VIDIOCGWIN = -2144831991; VIDIOCSWIN = 1076393482; break; } } @Override public void open(String path, int w, int h, int pixFormat) { this.w = w; this.h = h; V4LLoopback.pixFormat = pixFormat; switch (pixFormat) { case VideoOutput.RGB24: fmt = VIDEO_PALETTE_RGB24; break; case VideoOutput.UYVY: fmt = VIDEO_PALETTE_UYVY; break; default: fmt = VIDEO_PALETTE_RGB24; break; } devicePath = path; devFD = CLibrary.INSTANCE.open(devicePath, 4002); if (devFD <= 0) { if (listener != null) { listener.error("Unable to open device: " + devicePath); } } else { video_capability.ByReference vid_caps = new video_capability.ByReference(); video_window.ByReference vid_win = new video_window.ByReference(); video_picture.ByReference vid_pic = new video_picture.ByReference(); if (CLibrary.INSTANCE.ioctl(devFD, VIDIOCGCAP, vid_caps) == -1) { listener.error("Unable to open device: " + devicePath); } if (CLibrary.INSTANCE.ioctl(devFD, VIDIOCGWIN, vid_win) == -1) { listener.error("Unable to open device: " + devicePath); } vid_win.x = 0; vid_win.y = 0; vid_win.flags = 0; vid_win.width = w; vid_win.height = h; if (CLibrary.INSTANCE.ioctl(devFD, VIDIOCSWIN, vid_win) == -1) { listener.error("Unable to open device: " + devicePath); } if (CLibrary.INSTANCE.ioctl(devFD, VIDIOCGPICT, vid_pic) == -1) { listener.error("Unable to open device: " + devicePath); } vid_pic.brightness = 0; vid_pic.color = 0; vid_pic.contrast = 0; vid_pic.depth = 24; vid_pic.hue = 0; vid_pic.palette = (short) fmt; vid_pic.whiteness = 0; if (CLibrary.INSTANCE.ioctl(devFD, VIDIOCSPICT, vid_pic) == -1) { listener.error("Unable to open device: " + devicePath); } } } @Override public void close() { if (devFD != 0) { if (listener != null) { listener.info("Closing device : " + devicePath); } int status = CLibrary.INSTANCE.close(devFD); if (status != 0) { System.out.println("Error closing device : " + devFD); if (listener != null) { listener.error("Error closing device : " + devicePath); } } if (listener != null) { listener.info("Virtual Webcam Stopped"); } } } @Override public void write(int[] data) { if (devFD != 0) { switch (fmt) { case VIDEO_PALETTE_RGB24: buffer = img2rgb24(data); break; case VIDEO_PALETTE_UYVY: buffer = img2uyvy(data); break; } int countWritten = 0; countWritten = CLibrary.INSTANCE.write(devFD, buffer, buffer.length); if (countWritten != buffer.length && listener != null) { listener.error("WebcamStudio: Error while writing image..."); } } } public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); void printf(String format, Object... args); int open(String device, int mode); int close(int device); int ioctl(int device, int command, Object struct); String strerr(int no); int write(int device, byte[] buffer, int count); } }