/**
* 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);
}
}