Commit 2a98890e authored by petter's avatar petter

now camera recording should definitely work


git-svn-id: https://www2.in.tum.de/repos/ttt/trunk@60 0463f305-d864-43cb-8a47-61cf597d4139
parent 6c99e2ec
......@@ -9,5 +9,7 @@
<classpathentry kind="lib" path="lib/swing-layout-1.0.2.jar"/>
<classpathentry kind="lib" path="lib/jmf-2.1.1e.jar"/>
<classpathentry kind="lib" path="lib/mp3plugin.jar"/>
<classpathentry kind="lib" path="lib/v4l4j.jar"/>
<classpathentry kind="lib" path="lib/lti-civil.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<project name="TTT" default ="all" basedir=".">
<property name="java" location="java" />
<property name="lib" location="lib" />
<property name="native" location="native" />
<property name="classes" location="bin" />
<property name="dist" location="dist"/>
<property name="etc" location="etc" />
......@@ -68,6 +69,8 @@
</manifest>
</jar>
<copy todir="${dist}"><fileset dir="${lib}"></fileset></copy>
<copy todir="${dist}"><fileset dir="${native}"></fileset></copy>
<copy todir="${dist}" file="run.sh" />
<zip destfile="./ttt.zip" basedir="${dist}" update="true"/>
</target>
......
// TeleTeachingTool - Presentation Recording With Automated Indexing
//
// Copyright (C) 2003-2008 Peter Ziewer - Technische Universitt Mnchen
// Copyright (C) 2003-2008 Peter Ziewer - Technische Universit�t M�nchen
//
// This file is part of TeleTeachingTool.
//
......@@ -45,11 +45,13 @@ public class LectureProfile {
private int port = 5900;
private boolean record = true;
private boolean recordVideo = true;
private boolean recordWebcam = true;
private boolean recordLinearAudio = true; // linear = wav
private boolean loopbackRecorder = false;
private int colorDepth = Constants.defaultColorDepth;
private String RecordingCamera;
private ttt.videoRecorder.TTTVideoFormat Format;
private float VideoQuality;
// used whether to show info box or not
// stored in profile because other profile might be used by other person
//
......@@ -101,7 +103,9 @@ public class LectureProfile {
profile.loopbackRecorder = preferences.getBoolean("loopback_recorder", false);
profile.showRecordControlsInfo = preferences.getBoolean("show_record_controls_info", true);
profile.showRecordPlayRecordWarning = preferences.getBoolean("show_record_play_record_warning", true);
profile.RecordingCamera = preferences.get("RecordingCamera", "");
profile.Format = new ttt.videoRecorder.TTTVideoFormat(preferences.getInt("FormatWidth", 160), preferences.getInt("FormatHeight", 120));
profile.VideoQuality = preferences.getFloat("VideoQuality", 0.1f);
return profile;
}
} catch (Exception e) {
......@@ -139,7 +143,12 @@ public class LectureProfile {
preferences.putBoolean("loopback_recorder", loopbackRecorder);
preferences.putBoolean("show_record_controls_info", showRecordControlsInfo);
preferences.putBoolean("show_record_play_record_warning", showRecordPlayRecordWarning);
if(RecordingCamera != null)
preferences.put("RecordingCamera", RecordingCamera);
preferences.putFloat("VideoQuality", VideoQuality);
if(Format != null){
preferences.putInt("FormatWidth", Format.getWidth());
preferences.putInt("FormatHeight", Format.getHeight());}
preferences.flush();
} catch (Exception e) {
System.out.println("failed to write Lecture Profile: " + e);
......@@ -317,9 +326,9 @@ public class LectureProfile {
else if (within(calendar, Calendar.OCTOBER, 2005, Calendar.FEBRUARY, 2006, Calendar.WEDNESDAY, 13, 15))
title = "Berlea: Programmiersprachen " + fmt.format(calendar.getTime());
else if (within(calendar, Calendar.OCTOBER, 2005, Calendar.FEBRUARY, 2006, Calendar.MONDAY, 12, 14))
title = "Bode: Einfhrung in die techn. Informatik " + fmt.format(calendar.getTime());
title = "Bode: Einfhrung in die techn. Informatik " + fmt.format(calendar.getTime());
else if (within(calendar, Calendar.OCTOBER, 2005, Calendar.FEBRUARY, 2006, Calendar.THURSDAY, 8, 10))
title = "Bode: Einfhrung in die techn. Informatik " + fmt.format(calendar.getTime());
title = "Bode: Einfhrung in die techn. Informatik " + fmt.format(calendar.getTime());
// SS 2005
else if (within(calendar, Calendar.APRIL, 2005, Calendar.JULY, 2005, Calendar.TUESDAY, 11, 14))
......@@ -486,6 +495,34 @@ public class LectureProfile {
return recordVideo;
}
public void setRecordingFormat (ttt.videoRecorder.TTTVideoFormat format) {
this.Format = format;
}
public String getRecordingCamera(){
return RecordingCamera;
}
public void setRecordingCamera(String recordCameraID) {
this.RecordingCamera = recordCameraID;
}
public ttt.videoRecorder.TTTVideoFormat getVideoFormat(){
return Format;
}
public float getVideoQuality(){
return VideoQuality;
}
public void setVideoQualiy(float Quality){
VideoQuality = Quality;
}
public void setRecordVideoEnabled(boolean recordVideo) {
this.recordVideo = recordVideo;
}
......
......@@ -50,6 +50,10 @@ import javax.swing.SpringLayout;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import ttt.videoRecorder.OSUtils;
import ttt.videoRecorder.WebCamControl;
import ttt.videoRecorder.OSUtils.CameraException;
public class LectureProfileDialog {
public static void showLectureProfileDialog() {
new LectureProfileDialog().show();
......@@ -210,24 +214,25 @@ public class LectureProfileDialog {
recorderCheckBox.setSelected(true);
recorderCheckBox.setEnabled(false);
// video recording
final JCheckBox recordVideoCheckBox = new JCheckBox("incl. video");
recordVideoCheckBox.setToolTipText("enable video recoding");
recordVideoCheckBox.setOpaque(false);
recordVideoCheckBox.setSelected(true);
recordVideoCheckBox.setEnabled(false);
// video recording
final ttt.videoRecorder.VideoSettingPanel CameraSettings;
JButton CameraSettingsButton = new JButton("Camera Setting");
CameraSettingsButton.setEnabled(false);
CameraSettings = new ttt.videoRecorder.VideoSettingPanel();
CameraSettings.show(false);
CameraSettingsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
CameraSettings.show(true);
}
});
// cam recording
final JCheckBox camCheckBox = new JCheckBox("incl. Webcam");
camCheckBox.setToolTipText("enable Webcam recoding");
camCheckBox.setOpaque(false);
camCheckBox.setSelected(true);
camCheckBox.setEnabled(false);
// enable/disable according to recorder selection
recorderCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
recordVideoCheckBox.setVisible(recorderCheckBox.isSelected());
filenameField.setVisible(recorderCheckBox.isSelected());
filenameLabel.setVisible(recorderCheckBox.isSelected());
}
......@@ -308,8 +313,8 @@ public class LectureProfileDialog {
panel.add(label);
panel.add(recorderCheckBox);
panel.add(new JLabel(" "));
panel.add(recordVideoCheckBox);
// panel.add(recordVideoCheckBox);
panel.add(filenameLabel);
panel.add(filenameField);
}
......@@ -371,13 +376,12 @@ public class LectureProfileDialog {
videoRecordingPanel.add(Box.createVerticalStrut(5));
label = new JLabel("Video Recording:");
label.setEnabled(false);
videoRecordingPanel.add(label);
final JLabel videolabel = new JLabel("Video Recording:");
videolabel.setEnabled(false);
videoRecordingPanel.add(videolabel);
videoRecordingPanel.add(videoRecordingOnCheckbox);
videoRecordingPanel.add(videoRecordingOffCheckbox);
videoRecordingPanel.add(Box.createVerticalGlue());
videoRecordingPanel.add(CameraSettingsButton);
videoRecordingPanel.add(audioFormatLabel);
videoRecordingPanel.add(wavRadioButton);
......@@ -430,8 +434,6 @@ public class LectureProfileDialog {
portField.setText("5900");
displayDesktopCheckBox.setSelected(false);
recorderCheckBox.setSelected(true);
recordVideoCheckBox.setSelected(true);
recordVideoCheckBox.setVisible(recorderCheckBox.isSelected());
videoRecordingOnCheckbox.setSelected(true);
filenameField.setVisible(recorderCheckBox.isSelected());
filenameLabel.setVisible(recorderCheckBox.isSelected());
......@@ -459,11 +461,13 @@ public class LectureProfileDialog {
// buttons
final JButton okButton = new JButton("ok");
okButton.setEnabled(false);
okButton.setEnabled(false);
JButton cancelButton = new JButton("cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
CameraSettings.release();
// close dialog
if (monitorPanel != null)
monitorPanel.close();
......@@ -544,6 +548,10 @@ public class LectureProfileDialog {
// set values
if (profile != null) {
// CameraSettings.getCameraIDs().contains(profile.getRecordingCamera());
lectureComboBox.setSelectedItem(profile.getLecture());
teacherComboBox.setSelectedItem(profile.getTeacher());
hostField.setText(profile.getHost());
......@@ -562,10 +570,16 @@ public class LectureProfileDialog {
displayDesktopCheckBox.setSelected(!loopback);
recorderCheckBox.setSelected(profile.isRecordEnabled());
recordVideoCheckBox.setSelected(profile.isRecordVideoEnabled());
recordVideoCheckBox.setVisible(recorderCheckBox.isSelected());
videoRecordingOnCheckbox.setSelected(profile.isRecordVideoEnabled());
videoRecordingOffCheckbox.setSelected(!profile.isRecordVideoEnabled());
// recordVideoCheckBox.setSelected(profile.isRecordVideoEnabled());
// recordVideoCheckBox.setVisible(recorderCheckBox.isSelected());
if (CameraSettings!=null) if(CameraSettings.CamerasFound()){
videoRecordingOnCheckbox.setSelected(profile.isRecordVideoEnabled());
videoRecordingOffCheckbox.setSelected(!profile.isRecordVideoEnabled());
if( CameraSettings.getCameraIDs().contains(profile.getRecordingCamera()))
CameraSettings.setRecordingCamera(profile.getRecordingCamera());
CameraSettings.setRecordingFormat(profile.getVideoFormat());
CameraSettings.setQuality(profile.getVideoQuality());
}
//Always use wave encoding in order to set profile.isRecordLinearAudioEnabled() to true
wavRadioButton.setSelected(true);
mp3RadioButton.setSelected(false);
......@@ -579,12 +593,13 @@ public class LectureProfileDialog {
// else
CameraSettings.release();
// store profile
LectureProfile lectureProfile = LectureProfile.getProfile((String) lectureComboBox
.getSelectedItem());
if (lectureProfile == null)
lectureProfile = new LectureProfile((String) lectureComboBox.getSelectedItem());
final LectureProfile profile = lectureProfile;
profile.setTeacher((String) teacherComboBox.getSelectedItem());
......@@ -592,11 +607,17 @@ public class LectureProfileDialog {
profile.setPort(portField.getNumber() >= 100 ? portField.getNumber()
: (portField.getNumber() + 5900));
profile.setRecordEnabled(recorderCheckBox.isSelected());
profile.setRecordVideoEnabled(recordVideoCheckBox.isSelected());
profile.setRecordVideoEnabled(videoRecordingOnCheckbox.isSelected());
profile.setRecordLinearAudioEnabled(wavRadioButton.isSelected());
profile.setLoopbackRecorder(!displayDesktopCheckBox.isSelected());
profile.setRecordingFormat(CameraSettings.getRecordingFormat());
profile.setRecordingCamera(CameraSettings.getRecordingCamera());
profile.setVideoQualiy(CameraSettings.getQuality());
CameraSettings.show(false);
profile.storeProfile();
TTT.userPrefs.put("last_used_lecture_profile", profile.getLecture());
......@@ -648,11 +669,18 @@ public class LectureProfileDialog {
for (int i = 0; i < components.length; i++) {
components[i].setEnabled(true);
}
components = videoRecordingPanel.getComponents();
for (int i = 0; i < components.length; i++) {
components[i].setEnabled(true);
if(CameraSettings.CamerasFound()){
components = videoRecordingPanel.getComponents();
for (int i = 0; i < components.length; i++) {
components[i].setEnabled(true);
}
}else{
videolabel.setText("No Camera available");
videoRecordingOffCheckbox.setSelected(true);
}
avLabel.setEnabled(true);
audioVolumeLabel.setEnabled(true);
recordingPathButton.setEnabled(true);
......
......@@ -45,7 +45,6 @@ import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitor;
/**
*
* @author ziewer
......
......@@ -61,7 +61,7 @@ public class Recorder implements MessageConsumer, Closeable {
private DataOutputStream out;
private AudioRecorder audioVideoRecorder;
private VideoRecorder VideoRecorder;
private VideoRecorderPanel VideoRecorder;
private LectureProfile lectureProfile;
......@@ -330,14 +330,17 @@ public class Recorder implements MessageConsumer, Closeable {
if (audioVideoRecorder != null)
audioVideoRecorder.startRec(file.getCanonicalPath());
//VideoRecStuff start
// TODO VideoRecStart
//VideoRec start
//TODO recording options
if(lectureProfile.isRecordVideoEnabled()){
VideoRecorder = new VideoRecorder();
VideoRecorder = new VideoRecorderPanel();
VideoRecorder.setRecordingFormat(lectureProfile.getVideoFormat());
VideoRecorder.setRecordingCamera(lectureProfile.getRecordingCamera());
VideoRecorder.setVideoQuality(lectureProfile.getVideoQuality());
VideoRecorder.setRecordpath(file.getCanonicalPath().substring(0, file.getCanonicalPath().length()-4));
VideoRecorder.Start();
}
//VideoRecStuff end
// startime
long starttime = System.currentTimeMillis();
......@@ -414,27 +417,27 @@ public class Recorder implements MessageConsumer, Closeable {
audioVideoRecorder.stopRec();
}
//TODO VideorecStop
if (VideoRecorder != null) {
if (closing) {
if (closing) {
VideoRecorder.close();
VideoRecorder = null;
} else
VideoRecorder = null;
} else{
VideoRecorder.Stop();
}
}
}
out.flush();
out.close();
out = null;
}
TTT.userPrefs.put("last_opened_recording", file.getCanonicalPath());
System.out.println("Recorder stop.");
}
}
// modified by Ziewer - 10.05.2007
// NOTE: writes file header WITHOUT starttime
......
......@@ -37,8 +37,10 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.imageio.ImageIO;
public class ScriptCreator {
final static int HTML_SCRIPT = 1;
......@@ -311,6 +313,9 @@ public class ScriptCreator {
out.close();
}
// css style sheet
void writeStyleSheet() {
try {
......
......@@ -91,7 +91,7 @@ import ttt.messaging.gui.NetworkInterfaceDialog;
import ttt.messaging.server.TTTMessaging;
public class TTT extends JFrame {
static final String version = "05.10.2009";
static final String version = "22.05.2009";
public static boolean debug =! true;
static boolean verbose = true;
......@@ -1091,7 +1091,7 @@ public class TTT extends JFrame {
// TODO: position management
private int position;
void addInternalFrameCentered(JInternalFrame frame) {
public void addInternalFrameCentered(JInternalFrame frame) {
frame.pack();
......
package ttt.videoRecorder;
//handles the incoming pictures for linuxcam and windowscam
public interface CaptureInterface {
public void onNewImage(byte[] image, String RecordPath, float Quality);
}
/**
*
* @author sigl ludwig
*
*/
package ttt.videoRecorder;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.io.File;
import java.lang.Thread;
import javax.swing.ImageIcon;
import com.lti.civil.Image;
import au.edu.jcu.v4l4j.FrameGrabber;
import au.edu.jcu.v4l4j.ImageFormat;
import au.edu.jcu.v4l4j.V4L4JConstants;
import au.edu.jcu.v4l4j.VideoDevice;
import au.edu.jcu.v4l4j.ResolutionInfo.DiscreteResolution;
import au.edu.jcu.v4l4j.exceptions.V4L4JException;
//This classs set and get methods are completly unfished!
public class LinuxCam implements WebCamControl, Runnable {
public static String RecordPath = "C:\\TTTImplement\\";
private static VideoDevice vd;
private static FrameGrabber fg;
private Thread captureThread;
public static boolean isRecording = false;
public LinuxCam() throws V4L4JException{
String dev = "/dev/video0";
int w=160, h=120, std=0, channel = 0, qty = 60;
initFrameGrabber(dev, w, h, std, channel, qty);
}
/* Shouldn't be needed but untetested...
public void setImage(byte[] b) {
GUIMain.myLabel.setIcon(new ImageIcon(b));
}*/
/**
* is called in start by the new capture thread stuff
*/
public void run(){
ByteBuffer bb;
byte[] b;
try {
//OnCapture.RecordPath = RecordPath;
while(isRecording){
bb = fg.getFrame();
b = new byte[bb.limit()];
bb.get(b);
OnCapture SafePic = new OnCapture();
SafePic.onNewImage((Image) new ImageIcon(b).getImage(),RecordPath);
// setImage(b);
}
} catch (V4L4JException e) {
e.printStackTrace();
System.out.println("Failed to capture image");
}
}
private void initFrameGrabber(String dev, int w, int h, int std, int channel, int qty) throws V4L4JException{
vd = new VideoDevice(dev);
fg = vd.getJPEGFrameGrabber(w, h, channel, std, qty);
}
@Override
public boolean Start() {
private CaptureInterface CI;
private String v4lSysfsPath = "/sys/class/video4linux/";
private String RecordPath;
private List<VideoDevice> system = new LinkedList<VideoDevice>();
private FrameGrabber fg;
private Thread captureThread;
int w = 160, h = 120;
private boolean CamFound = false;
private float CompressionQuality = 0.1f;
public boolean isRecording = false;
String dev = "/dev/video0";
int currentdev = 0;
public LinuxCam() throws V4L4JException {
initializeDevices();
}
protected void initializeDevices() throws V4L4JException {
for (Object i : listV4LDeviceFiles()) {
system.add(new VideoDevice(i.toString()));
}
}
/**
* Implements the capture thread: get a frame from the FrameGrabber, and
* display it
*/
public void run() {
ByteBuffer bb;
byte[] image;
try {
if(!isRecording){
fg.startCapture();
captureThread = new Thread(this, "Capture Thread");
captureThread.start();
isRecording = true;
while (isRecording) {
if (isRecording) {
bb = fg.getFrame();
image = new byte[bb.limit()];
bb.get(image);
CI.onNewImage(image, RecordPath, CompressionQuality);
}
}
} catch (V4L4JException e) {
} catch (V4L4JException e) {
e.printStackTrace();
System.out.println("Failed to capture image");
}
return false;
}
private Object[] listV4LDeviceFiles() {
Vector<String> sdev = new Vector<String>();
File dir = new File(v4lSysfsPath);
String[] files = dir.list();
for (String file : files)
// the following test the presence of "video" in
// each file name - not very portable - relying on HAL
// would be much better ...
if (file.indexOf("video") != -1)
sdev.add("/dev/" + file);
if (sdev.size() != 0) {
CamFound = true;
}
return sdev.toArray();
}
private void initFrameGrabber(int std, int channel)
throws V4L4JException {
fg = system.get(currentdev)
.getJPEGFrameGrabber(w, h, channel, std, V4L4JConstants.MAX_JPEG_QUALITY);
}
@Override
public boolean Stopp() {
if(isRecording){
fg.stopCapture();
isRecording =false;
// OnCapture.ZipOnStop();
public void release() {
for (VideoDevice x : system) {
x.releaseFrameGrabber();
x.release();
}
}
@Override
public boolean Start() {
if (CamFound)
try {
initFrameGrabber(0, 0);
if (!isRecording) {
fg.startCapture();
captureThread = new Thread(this, "Capture Thread");
isRecording = true;
captureThread.start();
}
} catch (V4L4JException e) {
e.printStackTrace();
}
return false;
}
//returns the intern device id
@Override
public String getDeviceID(int Device) {
try {
return vd.getDeviceInfo().toString();
} catch (V4L4JException e) {
e.printStackTrace();
public boolean Stop() {
if (isRecording) {
captureThread = null;
isRecording = false;
fg.stopCapture();
fg = null;
system.get(currentdev).releaseFrameGrabber();
}
return false;
}
@Override
public String getDeviceID(int Device) {
if (CamFound)
return "/dev/video" + Device;
return null;
}
//it can currently handle only the default cam
@SuppressWarnings("unchecked")
@Override
public List getDeviceList() {
List lista = new LinkedList();
lista.add(vd.getDevicefile());
return lista;
public List<String> getDeviceList() {
List<String> deviselist = new LinkedList<String>();
if (CamFound)
for (VideoDevice i : system) {
try {
deviselist.add(i.getDeviceInfo().getName());
return deviselist;
} catch (V4L4JException e) {
e.printStackTrace();
}
}
return null;
}
@SuppressWarnings("unchecked")
@Override
public List getSupportedFormats(int Device) {
List empty = new LinkedList();
empty.add("Width=160 Height=120");
return empty;
public List<TTTVideoFormat> getSupportedFormats(int Device) {
currentdev = Device;
List<TTTVideoFormat> SupportedFormats = new LinkedList<TTTVideoFormat>();
if (CamFound)
try {
for (ImageFormat i : system.get(Device).getDeviceInfo()
.getFormatList().getJPEGEncodableFormats()) {
if (i.getResolutionInfo().getType().toString().equals(
"DISCRETE")) {
for (DiscreteResolution j : i.getResolutionInfo()
.getDiscreteResolutions()) {
SupportedFormats.add(new TTTVideoFormat(j
.getWidth(), j.getHeight()));
}
}
}
if(!SupportedFormats.isEmpty())
return SupportedFormats;
} catch (V4L4JException e) {
e.printStackTrace();
}
return null;
}
//TODO Implement set Format
@Override
public void setFormat(int Width, int Height) {
w = Width;
h = Height;
}
@Override
public void setSelectedCam(String DeviceID) {
// TODO Auto-generated method stub
dev = DeviceID;
}
@Override
public void setRecordPath(String Path) {
RecordPath = Path;