Commit 1dfe3f30 authored by petter's avatar petter

Kameraunterstützung Teil 1

git-svn-id: https://www2.in.tum.de/repos/ttt/trunk@31 0463f305-d864-43cb-8a47-61cf597d4139
parent 7e6db57d
......@@ -64,7 +64,7 @@
<fileset dir="${classes}/ttt/resources"/>
<manifest>
<attribute name="Main-Class" value="ttt/TTT" />
<attribute name="Class-Path" value="itext-1.4.8.jar jsch-0.1.32-patched.jar swing-layout-1.0.2.jar jmf-2.1.1e.jar mp3plugin.jar" />
<attribute name="Class-Path" value="itext-1.4.8.jar jsch-0.1.32-patched.jar swing-layout-1.0.2.jar jmf-2.1.1e.jar mp3plugin.jar lti-civil.jar v4l4j.jar" />
</manifest>
</jar>
<copy todir="${dist}"><fileset dir="${lib}"></fileset></copy>
......
......@@ -45,6 +45,7 @@ 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;
......@@ -488,7 +489,7 @@ public class LectureProfile {
public void setRecordVideoEnabled(boolean recordVideo) {
this.recordVideo = recordVideo;
}
public boolean isRecordLinearAudioEnabled() {
return recordLinearAudio;
}
......
......@@ -216,6 +216,13 @@ public class LectureProfileDialog {
recordVideoCheckBox.setOpaque(false);
recordVideoCheckBox.setSelected(true);
recordVideoCheckBox.setEnabled(false);
// 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() {
......@@ -355,6 +362,7 @@ public class LectureProfileDialog {
ButtonGroup videoRecordingButtonGroup = new ButtonGroup();
videoRecordingButtonGroup.add(videoRecordingOnCheckbox);
videoRecordingButtonGroup.add(videoRecordingOffCheckbox);
final JPanel videoRecordingPanel = new JPanel();
videoRecordingPanel.setLayout(new BoxLayout(videoRecordingPanel, BoxLayout.Y_AXIS));
......@@ -374,6 +382,8 @@ public class LectureProfileDialog {
videoRecordingPanel.add(audioFormatLabel);
videoRecordingPanel.add(wavRadioButton);
videoRecordingPanel.add(mp3RadioButton);
videoRecordingPanel.add(Box.createVerticalStrut(5));
......@@ -551,7 +561,7 @@ public class LectureProfileDialog {
hostPortDividerLabel.setEnabled(!loopback);
displayDesktopCheckBox.setSelected(!loopback);
recorderCheckBox.setSelected(profile.isRecordEnabled());
recorderCheckBox.setSelected(profile.isRecordEnabled());
recordVideoCheckBox.setSelected(profile.isRecordVideoEnabled());
recordVideoCheckBox.setVisible(recorderCheckBox.isSelected());
videoRecordingOnCheckbox.setSelected(profile.isRecordVideoEnabled());
......
......@@ -764,7 +764,7 @@ public class PostProcessor extends JPanel {
Insets insets = new Insets(0, 10, 0, 10);
// ////////////////////////////////////////////////
// infomation about recording
// information about recording
// ////////////////////////////////////////////////
final JLabel titleLabel = new JLabel(recording.prefs.name);
......
......@@ -340,6 +340,15 @@ public class PostProcessorPanel extends GradientPanel {
ocrStatusField.setText("not found");
ocrStatusField.setToolTipText(null);
}
if (recording.getExistingFileBySuffix("zip").exists()) {
camStatusField.setForeground(Color.GREEN);
camStatusField.setText("folder found");
camStatusField.setToolTipText("folder exists - content not confirmed");
} else {
camStatusField.setForeground(Color.RED);
camStatusField.setText("not found");
camStatusField.setToolTipText(null);
}
if (recording.getExistingFileBySuffix("mp3").exists()) {
mp3StatusField.setForeground(Color.GREEN);
mp3StatusField.setText("found");
......@@ -475,10 +484,12 @@ public class PostProcessorPanel extends GradientPanel {
pdfStatusField = new javax.swing.JLabel();
ocrStatusField = new javax.swing.JLabel();
flashStatusField = new javax.swing.JLabel();
mp3CheckBox = new javax.swing.JCheckBox();
mp3CheckBox = new javax.swing.JCheckBox();
mp3StatusField = new javax.swing.JLabel();
mp4CheckBox = new javax.swing.JCheckBox();
mp4StatusField = new javax.swing.JLabel();
camCheckBox = new javax.swing.JCheckBox();
camStatusField = new javax.swing.JLabel();
jPanel3 = new javax.swing.JPanel();
jLabel10 = new javax.swing.JLabel();
searchStatusField = new javax.swing.JLabel();
......@@ -625,6 +636,11 @@ public class PostProcessorPanel extends GradientPanel {
flashCheckBox.setText("Flash/SWF");
flashCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
camCheckBox.setSelected(true);
camCheckBox.setText("Cam");
camCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
createButton.setText("Create");
createButton.setMargin(new java.awt.Insets(0, 8, 0, 8));
createButton.addActionListener(new java.awt.event.ActionListener() {
......@@ -676,7 +692,9 @@ public class PostProcessorPanel extends GradientPanel {
.add(ocrCheckBox)
.add(mp3CheckBox)
.add(flashCheckBox)
.add(mp4CheckBox))
.add(mp4CheckBox)
.add(camCheckBox)
)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(ocrStatusField)
......@@ -687,7 +705,9 @@ public class PostProcessorPanel extends GradientPanel {
.add(htmlStatusField)
.add(mp3StatusField)
.add(flashStatusField)
.add(mp4StatusField))
.add(mp4StatusField)
.add(camStatusField)
)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 370, Short.MAX_VALUE)
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(createHelpButton)
......@@ -732,6 +752,10 @@ public class PostProcessorPanel extends GradientPanel {
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(mp4CheckBox)
.add(mp4StatusField))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(camCheckBox)
.add(camStatusField))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel2Layout.createSequentialGroup()
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
......@@ -1004,7 +1028,9 @@ public class PostProcessorPanel extends GradientPanel {
htmlCheckBox.setEnabled(enabled);
pdfCheckBox.setEnabled(enabled && ctrlSatus.get(pdfCheckBox)); //---
ocrCheckBox.setEnabled(enabled);
flashCheckBox.setEnabled(enabled && ctrlSatus.get(flashCheckBox)); //---
camCheckBox.setEnabled(enabled);
mp3CheckBox.setEnabled(enabled && ctrlSatus.get(mp3CheckBox)); //---
mp4CheckBox.setEnabled(enabled && ctrlSatus.get(mp4CheckBox)); //---
createHelpButton.setEnabled(enabled);
......@@ -1333,6 +1359,8 @@ public class PostProcessorPanel extends GradientPanel {
mode |= ScriptCreator.PDF_SCRIPT;
if (ocrCheckBox.isSelected())
mode |= ScriptCreator.OCR_OPTIMIZED;
// compute everything specified by mode
recording.createScript(mode, batch);
} catch (Exception e) {
......@@ -1376,6 +1404,18 @@ public class PostProcessorPanel extends GradientPanel {
e.printStackTrace();
}
//create camVid
try {
if (camCheckBox.isSelected()) {
ttt.videoRecorder.VideoCreator newVideo = new ttt.videoRecorder.VideoCreator();
newVideo.create(recording.getExistingFileBySuffix("bjpg").getPath());//TODO convert
}
} catch (Exception e) {
TTT.showMessage("CamVid creation failed: " + e);
e.printStackTrace();
}
// update status fields
updateStatusFields();
......@@ -1490,6 +1530,7 @@ public class PostProcessorPanel extends GradientPanel {
private javax.swing.JButton doneButton;
private javax.swing.JLabel durationField;
private javax.swing.JLabel filenameField;
private javax.swing.JCheckBox camCheckBox;
private javax.swing.JCheckBox flashCheckBox;
private javax.swing.JLabel flashStatusField;
private javax.swing.JCheckBox htmlCheckBox;
......@@ -1519,6 +1560,7 @@ public class PostProcessorPanel extends GradientPanel {
private javax.swing.JLabel mp4StatusField;
private javax.swing.JCheckBox ocrCheckBox;
private javax.swing.JLabel ocrStatusField;
private javax.swing.JLabel camStatusField;
private javax.swing.JButton openSearchbaseFileDialogButton;
private javax.swing.JTextField pathField;
private javax.swing.JCheckBox pdfCheckBox;
......
......@@ -51,6 +51,8 @@ import ttt.messages.DeleteAllAnnotation;
import ttt.messages.Message;
import ttt.messages.MessageConsumer;
import ttt.messages.WhiteboardMessage;
import ttt.videoRecorder.*;
public class Recorder implements MessageConsumer, Closeable {
......@@ -59,7 +61,8 @@ public class Recorder implements MessageConsumer, Closeable {
private DataOutputStream out;
private AudioRecorder audioVideoRecorder;
private VideoRecorder VideoRecorder;
private LectureProfile lectureProfile;
public Recorder(RfbProtocol protocol, LectureProfile lectureProfile) throws IOException {
......@@ -327,6 +330,15 @@ public class Recorder implements MessageConsumer, Closeable {
if (audioVideoRecorder != null)
audioVideoRecorder.startRec(file.getCanonicalPath());
//VideoRecStuff start
// TODO VideoRecStart
if(lectureProfile.isRecordVideoEnabled()){
VideoRecorder = new VideoRecorder();
VideoRecorder.setRecordpath(file.getCanonicalPath().substring(0, file.getCanonicalPath().length()-4));
VideoRecorder.Start();
}
//VideoRecStuff end
// startime
long starttime = System.currentTimeMillis();
new_out.writeLong(starttime);
......@@ -402,6 +414,18 @@ public class Recorder implements MessageConsumer, Closeable {
audioVideoRecorder.stopRec();
}
//TODO VideorecStop
if (VideoRecorder != null) {
if (closing) {
VideoRecorder.close();
VideoRecorder = null;
} else
VideoRecorder.Stop();
}
out.flush();
out.close();
out = null;
......
This diff is collapsed.
/**
*
* @author sigl ludwig
*
*/
package ttt.videoRecorder;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.lang.Thread;
import javax.swing.ImageIcon;
import com.lti.civil.Image;
import au.edu.jcu.v4l4j.FrameGrabber;
import au.edu.jcu.v4l4j.VideoDevice;
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() {
try {
if(!isRecording){
fg.startCapture();
captureThread = new Thread(this, "Capture Thread");
captureThread.start();
isRecording = true;
}
} catch (V4L4JException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean Stopp() {
if(isRecording){
fg.stopCapture();
isRecording =false;
// OnCapture.ZipOnStop();
}
return false;
}
//returns the intern device id
@Override
public String getDeviceID(int Device) {
try {
return vd.getDeviceInfo().toString();
} catch (V4L4JException e) {
e.printStackTrace();
}
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;
}
@SuppressWarnings("unchecked")
@Override
public List getSupportedFormats(int Device) {
List empty = new LinkedList();
empty.add("Width=160 Height=120");
return empty;
}
//TODO Implement set Format
@Override
public void setFormat(int Width, int Height) {
}
@Override
public void setSelectedCam(String DeviceID) {
// TODO Auto-generated method stub
}
@Override
public void SetRecordPath(String path) {
RecordPath = path;
}
}
package ttt.videoRecorder;
import java.util.logging.Logger;
/**
*
* @author ken lti-Civil
*
*/
public final class OSUtils
{
@SuppressWarnings("deprecation")
private static final Logger logger = Logger.global;
private OSUtils()
{ super();
logger.fine("OS: " + System.getProperty("os.name"));
}
public static final boolean isLinux()
{
return System.getProperty("os.name").equals("Linux");
}
public static final boolean isMacOSX()
{
return System.getProperty("os.name").equals("Mac OS X");
}
public static final boolean isWindows()
{
return System.getProperty("os.name").startsWith("Windows");
}
public static final boolean isSolaris()
{
return System.getProperty("os.name").equals("SunOS");
}
}
/**
*
* @author sigl ludwig
*
*/
package ttt.videoRecorder;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import javax.swing.ImageIcon;
import com.lti.civil.Image;
import com.lti.civil.awt.AWTImageConverter;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
//
// Gets called every time a new picture is taken. it saves them under the recordpath set direction
//
public class OnCapture {
static private String RecordPath = "C:\\TTTImplement\\";
public static String getRecordPath(){
return OnCapture.RecordPath;
}
public void onNewImage(Image image, String RecordPath)
{
OnCapture.RecordPath = RecordPath;
final BufferedImage bimg;
try
{
bimg = AWTImageConverter.toBufferedImage(image);
}
catch (Exception e)
{ e.printStackTrace();
return;
}
try
{
File ImageFile = new File( RecordPath+".bjpg");
FileOutputStream fos = new FileOutputStream (ImageFile, true);
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
JPEGEncodeParam EncodePar = jpeg.getDefaultJPEGEncodeParam(bimg);
EncodePar.setQuality(0.1f, true);
jpeg.setJPEGEncodeParam(EncodePar);
jpeg.encode(bimg);
fos.close();
FileWriter fw = new FileWriter(ImageFile, true);
fw.write(" FileEnd");
fw.close();
ImageIcon myImage2 = new ImageIcon();
myImage2.setImage(bimg);
VideoRecorder.myLabel.setIcon(myImage2);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
*
* @author sigl ludwig
*
*/
package ttt.videoRecorder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import javax.media.MediaLocator;
public class VideoCreator {
public void create(String Path) throws IOException{
try {
FileInputStream fis = new FileInputStream(Path); //looks for the 'end' of a jpg
InputStream fis2 = new FileInputStream(Path); //actually fills the buffer
int i;
String v;
Vector<byte[]> InFiles = new Vector<byte[]>();
byte[] buffer;
StringBuffer strContent = new StringBuffer("");
int FrameRate = 15;
Boolean first = true;
while((i= fis.read()) != -1){
strContent.append((char)i);
v = strContent.toString();
if(v.contains("FileEnd")){
buffer = new byte[v.length()-7];
if(!first){
//skipping fileEnd
fis2.read(buffer, 0, 7);
}
fis2.read(buffer, 0, buffer.length);
first = false;
System.out.println(buffer.length);
InFiles.add(buffer);
strContent = new StringBuffer("");
}
//calculates the framerate
if(v.contains("ElapsedTime")){
v = v.substring(0,v.length()-12);
FrameRate = InFiles.size() / Integer.parseInt(v);
}
}
Path = Path.substring(0, Path.length()-4); //remove the ".bjpg" from path
MediaLocator outML = new MediaLocator("file:"+Path+".mov");
JpegImagesToMovie test = new JpegImagesToMovie();
test.doIt(160, 120, FrameRate, InFiles, outML);
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
/**
*
* @author sigl ludwig
*
*/
package ttt.videoRecorder;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import au.edu.jcu.v4l4j.exceptions.V4L4JException;
import com.lti.civil.CaptureException;
public class VideoRecorder implements WindowListener{
JFrame frame = new JFrame("TTTCam");
JPanel panel = new JPanel ();
long start;
public static JLabel myLabel = new JLabel();
public boolean isRecording = false;
public WebCamControl WBC;
public VideoRecorder() {
if(OSUtils.isWindows()) {
try {
WBC = new WindowsCam();
} catch (CaptureException e) {
e.printStackTrace();
}
}
if(OSUtils.isLinux()){
try {
WBC = new LinuxCam();
} catch (V4L4JException e) {
e.printStackTrace();
}
}
WBC.setSelectedCam (WBC.getDeviceID(0));
WBC.setFormat(160, 120);
panel.add(myLabel);
//
//frame
//
frame.addWindowListener(this);
frame.setSize(160, 160);
frame.add (panel);
frame.setVisible(true);
}// End Constructor
public void Start(){
if(!isRecording){
WBC.Start();
start = System.nanoTime();
isRecording = true;}
}
public void Stop() {
if(isRecording){
WBC.Stopp();
isRecording = false;
}
}
public void saveelapsedTime(){
long elapsed = System.nanoTime() - start;
File TimeWriter = new File(OnCapture.getRecordPath()+".bjpg");
FileWriter fw;
try {
fw = new FileWriter(TimeWriter, true);
fw.write(elapsed+"ElapsedTime");
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void close(){
frame.dispose();
}
public void setRecordpath(String Path){
WBC.SetRecordPath(Path);
}
@Override
public void windowClosing(WindowEvent arg0) {
Stop();
}
@Override
public void windowActivated(WindowEvent arg0) { }
@Override
public void windowClosed(WindowEvent arg0) {}
@Override
public void windowDeactivated(WindowEvent arg0) {}
@Override
public void windowDeiconified(WindowEvent arg0) {}
@Override
public void windowIconified(WindowEvent arg0) {}
@Override
public void windowOpened(WindowEvent arg0) {}
}