changeset 39:784a3f4e6202

updating capture-video
author Robert McIntyre <rlm@mit.edu>
date Thu, 03 Nov 2011 16:00:46 -0700
parents adeb88787645
children 56dc950feaed
files .hgignore src/ca/randelshofer/AVIOutputStream.java src/com/aurellem/capture/Capture.java src/com/aurellem/capture/audio/AudioSendRenderer.java src/com/aurellem/capture/audio/SoundProcessor.java src/com/aurellem/capture/examples/AdvancedAudio.java src/com/aurellem/capture/examples/HelloVideo.java src/com/aurellem/capture/video/AVIVideoRecorder.java src/com/aurellem/capture/video/AbstractVideoRecorder.java src/com/aurellem/capture/video/FileVideoRecorder.java src/com/aurellem/capture/video/IVideoRecorder.java src/com/aurellem/capture/video/VideoRecorder.java
diffstat 12 files changed, 200 insertions(+), 140 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/.hgignore	Mon Oct 31 07:43:44 2011 -0700
     1.2 +++ b/.hgignore	Thu Nov 03 16:00:46 2011 -0700
     1.3 @@ -8,5 +8,5 @@
     1.4  dist*
     1.5  lib*
     1.6  .ant*
     1.7 +output/*
     1.8  
     1.9 -
     2.1 --- a/src/ca/randelshofer/AVIOutputStream.java	Mon Oct 31 07:43:44 2011 -0700
     2.2 +++ b/src/ca/randelshofer/AVIOutputStream.java	Thu Nov 03 16:00:46 2011 -0700
     2.3 @@ -627,7 +627,7 @@
     2.4      }
     2.5  
     2.6      /**
     2.7 -     * Sets the state of the QuickTimeOutpuStream to started.
     2.8 +     * Sets the state of the AVIOutputStream to 'started'.
     2.9       * <p>
    2.10       * If the state is changed by this method, the prolog is
    2.11       * written.
     3.1 --- a/src/com/aurellem/capture/Capture.java	Mon Oct 31 07:43:44 2011 -0700
     3.2 +++ b/src/com/aurellem/capture/Capture.java	Thu Nov 03 16:00:46 2011 -0700
     3.3 @@ -8,6 +8,7 @@
     3.4  import com.aurellem.capture.audio.WaveFileWriter;
     3.5  import com.aurellem.capture.video.AVIVideoRecorder;
     3.6  import com.aurellem.capture.video.AbstractVideoRecorder;
     3.7 +import com.aurellem.capture.video.FileVideoRecorder;
     3.8  import com.aurellem.capture.video.XuggleVideoRecorder;
     3.9  import com.jme3.app.Application;
    3.10  import com.jme3.audio.AudioRenderer;
    3.11 @@ -27,6 +28,8 @@
    3.12  
    3.13  		if (file.getCanonicalPath().endsWith(".avi")){
    3.14  			videoRecorder = new AVIVideoRecorder(file);}
    3.15 +		else if (file.isDirectory()){
    3.16 +			videoRecorder = new FileVideoRecorder(file);}
    3.17  		else { videoRecorder = new XuggleVideoRecorder(file);}
    3.18  
    3.19  		Callable<Object> thunk = new Callable<Object>(){
     4.1 --- a/src/com/aurellem/capture/audio/AudioSendRenderer.java	Mon Oct 31 07:43:44 2011 -0700
     4.2 +++ b/src/com/aurellem/capture/audio/AudioSendRenderer.java	Thu Nov 03 16:00:46 2011 -0700
     4.3 @@ -136,8 +136,7 @@
     4.4  		this.audioSend = new AudioSend(this.deviceID);
     4.5  		this.outFormat = audioSend.getAudioFormat();
     4.6  		initBuffer();
     4.7 -		System.out.println(outFormat);
     4.8 -		
     4.9 +				
    4.10  		// The LWJGL context must be established as the master context before 
    4.11  		// any other listeners can be created on this device.
    4.12  		audioSend.initDevice();
    4.13 @@ -173,22 +172,14 @@
    4.14  	}
    4.15  	
    4.16  	
    4.17 -	//public final static int BYTES_PER_SAMPLE = 4;
    4.18 -	
    4.19 -	
    4.20  	private ByteBuffer buffer;;
    4.21 -	private byte[] debug0;
    4.22 -	private byte[] debug1;
    4.23 -	
    4.24 +
    4.25  	public static final int MIN_FRAMERATE = 10;
    4.26  	
    4.27  	private void initBuffer(){
    4.28  		int bufferSize = (int)(this.outFormat.getSampleRate() / ((float)MIN_FRAMERATE)) * 
    4.29  					this.outFormat.getFrameSize();
    4.30  		this.buffer = BufferUtils.createByteBuffer(bufferSize);
    4.31 -		debug0 = new byte[4096];
    4.32 -		debug1 = new byte[4096];
    4.33 -			
    4.34  	}
    4.35  	/*
    4.36  	
    4.37 @@ -196,33 +187,19 @@
    4.38  	public void dispatchAudio(float tpf){
    4.39  		
    4.40  		int samplesToGet = (int) (tpf * outFormat.getSampleRate());
    4.41 -		System.out.println("want " + samplesToGet + " samples");
    4.42  		try {latch.await();} 
    4.43  		catch (InterruptedException e) {e.printStackTrace();}
    4.44  		audioSend.step(samplesToGet);
    4.45  		updateAllListeners();
    4.46 -		
    4.47 +
    4.48  		for (int i = 0; i < this.listeners.size(); i++){		
    4.49  			buffer.clear();
    4.50  			audioSend.getSamples(buffer, samplesToGet, i);
    4.51 -			if (i == 0 ) buffer.get(debug0);
    4.52 -			if (i == 1 ) buffer.get(debug1);
    4.53  			SoundProcessor sp = 
    4.54 -			this.soundProcessorMap.get(this.listeners.get(i));
    4.55 +					this.soundProcessorMap.get(this.listeners.get(i));
    4.56  			if (null != sp){sp.process(buffer, samplesToGet*outFormat.getFrameSize(), outFormat);}
    4.57  		}
    4.58 -		
    4.59 -		for (int i = 0; i < samplesToGet; i++){
    4.60 -			if (debug1[i] != debug0[i]){
    4.61 -				System.out.println("inconsistency detected @ sample " + i);
    4.62 -				System.out.println("main : " + debug0[i]);
    4.63 -				System.out.println("aux : " + debug1[i]);
    4.64 -				
    4.65 -				break;
    4.66 -			}
    4.67 -			
    4.68 -		}
    4.69 -		
    4.70 +
    4.71  	}
    4.72  		
    4.73  	public void update(float tpf){
     5.1 --- a/src/com/aurellem/capture/audio/SoundProcessor.java	Mon Oct 31 07:43:44 2011 -0700
     5.2 +++ b/src/com/aurellem/capture/audio/SoundProcessor.java	Thu Nov 03 16:00:46 2011 -0700
     5.3 @@ -6,8 +6,25 @@
     5.4  
     5.5  public interface SoundProcessor {
     5.6  
     5.7 -	void cleanup();
     5.8 +    /**
     5.9 +     * Called when the SoundProcessor is being destroyed, and
    5.10 +     * there are no more samples to process.  This happens at the
    5.11 +     * latest when the Application is shutting down.
    5.12 +     * 
    5.13 +     */
    5.14 +    void cleanup();
    5.15  	
    5.16 -	void process(ByteBuffer audioSamples, int numSamples, AudioFormat format);
    5.17 +    /**
    5.18 +     * 
    5.19 +     * Called whenever there are new audio samples to process. The
    5.20 +     * audioSamples ByteBuffer contains 3D audio data rendered by
    5.21 +     * OpenAL.
    5.22 +     * 
    5.23 +     * @param audioSamples a ByteBuffer containing processed audio
    5.24 +     * samples
    5.25 +     * @param numSamples the number of samples, in bytes, that are valid
    5.26 +     * @param format the format of the audio samples in audioSamples
    5.27 +     */
    5.28 +    void process(ByteBuffer audioSamples, int numSamples, AudioFormat format);
    5.29  	
    5.30  }
     6.1 --- a/src/com/aurellem/capture/examples/AdvancedAudio.java	Mon Oct 31 07:43:44 2011 -0700
     6.2 +++ b/src/com/aurellem/capture/examples/AdvancedAudio.java	Thu Nov 03 16:00:46 2011 -0700
     6.3 @@ -19,7 +19,6 @@
     6.4  import com.aurellem.capture.audio.WaveFileWriter;
     6.5  import com.jme3.app.SimpleApplication;
     6.6  import com.jme3.audio.AudioNode;
     6.7 -import com.jme3.audio.AudioParam;
     6.8  import com.jme3.audio.Listener;
     6.9  import com.jme3.audio.ListenerParam;
    6.10  import com.jme3.cinematic.MotionPath;
    6.11 @@ -34,7 +33,6 @@
    6.12  import com.jme3.math.Vector3f;
    6.13  import com.jme3.scene.Geometry;
    6.14  import com.jme3.scene.Node;
    6.15 -import com.jme3.scene.Spatial;
    6.16  import com.jme3.scene.shape.Box;
    6.17  import com.jme3.scene.shape.Sphere;
    6.18  import com.jme3.system.AppSettings;
    6.19 @@ -69,16 +67,18 @@
    6.20  			app.setSettings(settings);
    6.21  			app.setShowSettings(false);
    6.22  			app.setPauseOnLostFocus(false);
    6.23 -			org.lwjgl.input.Mouse.setGrabbed(false);
    6.24 -			//try {Capture.captureVideo(app, new File("/home/r/tmp/out.avi"));}
    6.25 -			//catch (IOException e) {e.printStackTrace();}
    6.26 +			
    6.27 +			try {Capture.captureVideo(app, new File("/home/r/tmp/out"));
    6.28 +				 Capture.captureAudio(app, new File("/home/r/tmp/main.wav"));}
    6.29 +			catch (IOException e) {e.printStackTrace();}
    6.30  			app.start();
    6.31 +			
    6.32  	  }
    6.33  	 
    6.34  	 private MotionTrack motionControl;
    6.35  	
    6.36  	 
    6.37 -	 private Spatial makeEar(Node root, Vector3f position){
    6.38 +	 private Geometry makeEar(Node root, Vector3f position){
    6.39  		 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    6.40  		 Geometry ear = new Geometry("ear", new Box(1.0f, 1.0f, 1.0f));
    6.41  		 ear.setLocalTranslation(position);
    6.42 @@ -90,10 +90,10 @@
    6.43  	 
    6.44  	 private Geometry bell;
    6.45  	 
    6.46 -	 private Spatial ear1;
    6.47 -	 //private Spatial ear2;
    6.48 -	 //private Spatial ear3;
    6.49 -	 //private Spatial ear4;
    6.50 +	 private Geometry ear1;
    6.51 +	 private Geometry ear2;
    6.52 +	 private Geometry ear3;
    6.53 +	 
    6.54  	 
    6.55  	 
    6.56  	 private Vector3f[] path = new Vector3f[]{
    6.57 @@ -160,9 +160,9 @@
    6.58  		 rootNode.addLight(light);
    6.59  
    6.60  		 ear1 = makeEar(rootNode, new Vector3f(0, 0 ,-20));
    6.61 -		 //ear2 = makeEar(rootNode, new Vector3f(0, 0 ,-20));
    6.62 -		 //ear3 = makeEar(rootNode, new Vector3f(20, 0 ,0));
    6.63 -		 //ear4 = makeEar(rootNode, new Vector3f(-20, 0 ,0));
    6.64 +		 ear2 = makeEar(rootNode, new Vector3f(0, 0 ,20));
    6.65 +		 ear3 = makeEar(rootNode, new Vector3f(20, 0 ,0));
    6.66 +		 
    6.67  
    6.68  		 MotionPath track = new MotionPath();
    6.69  		 
    6.70 @@ -204,7 +204,7 @@
    6.71     
    6.72    
    6.73    private void initAudio() {
    6.74 -
    6.75 +	org.lwjgl.input.Mouse.setGrabbed(false);	
    6.76  	music = new AudioNode(assetManager, "Sound/Environment/sqr-1kHz.wav", false);
    6.77  	
    6.78      rootNode.attachChild(music);
    6.79 @@ -234,14 +234,10 @@
    6.80  
    6.81  
    6.82    public class Dancer implements SoundProcessor {
    6.83 -
    6.84 -	  Spatial entity;
    6.85 -
    6.86 +	  Geometry entity;
    6.87  	  float scale = 2;
    6.88 -	  String debug;
    6.89 -	  public Dancer(Spatial entity, String debug){
    6.90 +	  public Dancer(Geometry entity){
    6.91  		  this.entity = entity;
    6.92 -		  this.debug = debug;
    6.93  	  }
    6.94  
    6.95  	  /**
    6.96 @@ -265,10 +261,9 @@
    6.97  		  float max = Float.NEGATIVE_INFINITY;
    6.98  		  for (float f : out){if (f > max) max = f;}
    6.99  		  audioSamples.clear();
   6.100 -		  System.out.println(debug);
   6.101 -		  System.out.println(max);
   6.102  		  
   6.103 -		  
   6.104 +		  if (max > 0.1){entity.getMaterial().setColor("Color", ColorRGBA.Green);}
   6.105 +		  else {entity.getMaterial().setColor("Color", ColorRGBA.Gray);}
   6.106  		  
   6.107  		  //entity.scale(this.scale);
   6.108  		  //if (this.scale == 2f){this.scale = 0.5f;}
   6.109 @@ -280,38 +275,35 @@
   6.110  
   6.111    
   6.112    
   6.113 +  private void prepareEar(Geometry ear, int n){
   6.114 +	  if (this.audioRenderer instanceof MultiListener){
   6.115 +			MultiListener rf = (MultiListener)this.audioRenderer;
   6.116 +				
   6.117 +			auxListener = new Listener();
   6.118 +			auxListener.setLocation(ear.getLocalTranslation());
   6.119 +			
   6.120 +			rf.addListener(auxListener);
   6.121 +			WaveFileWriter aux = null;
   6.122 +			
   6.123 +			try {aux = new WaveFileWriter(new File("/home/r/tmp/ear"+n+".wav"));} 
   6.124 +			catch (FileNotFoundException e) {e.printStackTrace();}
   6.125 +									
   6.126 +			rf.registerSoundProcessor(auxListener, 
   6.127 +					new CompositeSoundProcessor(new Dancer(ear), aux));
   6.128 +			
   6.129 +		}   
   6.130 +  }
   6.131 +  
   6.132    
   6.133    public void simpleInitApp() {
   6.134  	this.setTimer(new IsoTimer(60));
   6.135      initAudio();
   6.136      initKeys();
   6.137  	createScene();
   6.138 -	listener.setLocation(ear1.getLocalTranslation());
   6.139 -	listener.setRotation(new Quaternion().fromAngleAxis(0, Vector3f.UNIT_Y));
   6.140 -	if (this.audioRenderer instanceof MultiListener){
   6.141 -		MultiListener rf = (MultiListener)this.audioRenderer;
   6.142  		
   6.143 -		
   6.144 -		
   6.145 -		auxListener = new Listener(listener);
   6.146 -		
   6.147 -		rf.addListener(auxListener);
   6.148 -		WaveFileWriter aux = null;
   6.149 -		WaveFileWriter main = null;
   6.150 -
   6.151 -		
   6.152 -		try {aux = new WaveFileWriter(new File("/home/r/tmp/aux.wav"));} 
   6.153 -		catch (FileNotFoundException e) {e.printStackTrace();}
   6.154 -		
   6.155 -		try {main = new WaveFileWriter(new File("/home/r/tmp/main.wav"));} 
   6.156 -		catch (FileNotFoundException e) {e.printStackTrace();}
   6.157 -				
   6.158 -		rf.registerSoundProcessor(auxListener, 
   6.159 -				new CompositeSoundProcessor(new Dancer(ear1, "aux"), aux));
   6.160 -		
   6.161 -		rf.registerSoundProcessor(
   6.162 -				new CompositeSoundProcessor(new Dancer(ear1, "--------\nmain"), main));
   6.163 -	}   
   6.164 +	prepareEar(ear1, 1);
   6.165 +	prepareEar(ear2, 1);
   6.166 +	prepareEar(ear3, 1);
   6.167  
   6.168      motionControl.play();
   6.169    }
   6.170 @@ -350,15 +342,15 @@
   6.171  	  if (countdown == 0){
   6.172  		  music.play();
   6.173  	  }
   6.174 -	//Vector3f loc = cam.getLocation();
   6.175 -	//Quaternion rot = cam.getRotation();
   6.176 -    //listener.setLocation(loc);
   6.177 -    listener.setRotation(new Quaternion().fromAngleAxis(0, music.getLocalTranslation().subtract(listener.getLocation())));
   6.178 +	Vector3f loc = cam.getLocation();
   6.179 +	Quaternion rot = cam.getRotation();
   6.180 +    listener.setLocation(loc);
   6.181 +    listener.setRotation(rot);
   6.182      audioRenderer.updateListenerParam(listener, ListenerParam.Rotation);
   6.183      
   6.184 -    System.out.println(countdown);
   6.185 +    //System.out.println(countdown);
   6.186      
   6.187 -    if (countdown++ == 300) { this.requestClose(false);}
   6.188 +    //if (countdown++ == 300) { this.requestClose(false);}
   6.189      
   6.190      //System.out.println("channel "+ music.getChannel());
   6.191      //listener.setLocation(cam.getLocation());
   6.192 @@ -378,8 +370,8 @@
   6.193      
   6.194      music.setLocalTranslation(bell.getLocalTranslation());
   6.195      
   6.196 -    System.out.println("distance: " +
   6.197 -    		music.getLocalTranslation().subtract(listener.getLocation()).length());
   6.198 +    //System.out.println("distance: " +
   6.199 +    //		music.getLocalTranslation().subtract(listener.getLocation()).length());
   6.200      
   6.201      //music.setVelocity(bellVelocity);
   6.202      
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/com/aurellem/capture/examples/HelloVideo.java	Thu Nov 03 16:00:46 2011 -0700
     7.3 @@ -0,0 +1,22 @@
     7.4 +package com.aurellem.capture.examples;
     7.5 +
     7.6 +import java.io.File;
     7.7 +import java.io.IOException;
     7.8 +
     7.9 +import jme3test.helloworld.HelloLoop;
    7.10 +
    7.11 +import com.aurellem.capture.IsoTimer;
    7.12 +import com.aurellem.capture.Capture;
    7.13 +import com.jme3.app.SimpleApplication;
    7.14 +
    7.15 +public class HelloVideo {
    7.16 +
    7.17 +    public static void main(String[] ignore) throws IOException {
    7.18 +	SimpleApplication app = new HelloLoop();
    7.19 +	File video = File.createTempFile("helloVideo", ".avi");
    7.20 +	app.setTimer(new IsoTimer(60));
    7.21 +	Capture.captureVideo(app, video);
    7.22 +	app.start();
    7.23 +	System.out.println(video.getCanonicalPath());
    7.24 +    }
    7.25 +}
     8.1 --- a/src/com/aurellem/capture/video/AVIVideoRecorder.java	Mon Oct 31 07:43:44 2011 -0700
     8.2 +++ b/src/com/aurellem/capture/video/AVIVideoRecorder.java	Thu Nov 03 16:00:46 2011 -0700
     8.3 @@ -9,38 +9,38 @@
     8.4  
     8.5  public class AVIVideoRecorder extends AbstractVideoRecorder{
     8.6  
     8.7 -	AVIOutputStream out = null;
     8.8 -	boolean videoReady = false;
     8.9 -	BufferedImage frame;
    8.10 +    AVIOutputStream out = null;
    8.11 +    boolean videoReady = false;
    8.12 +    BufferedImage frame;
    8.13  	
    8.14 -	public AVIVideoRecorder(File output) throws IOException {
    8.15 -		super(output);
    8.16 -		this.out = new AVIOutputStream(output, AVIOutputStream.VideoFormat.PNG, 24);
    8.17 -		this.out.setVideoCompressionQuality(1.0f);
    8.18 -	}
    8.19 -
    8.20 +    public AVIVideoRecorder(File output) throws IOException {
    8.21 +	super(output);
    8.22 +	this.out = new 
    8.23 +	    AVIOutputStream(output, AVIOutputStream.VideoFormat.RAW, 24);
    8.24 +	this.out.setFrameRate(60);
    8.25 +    }
    8.26  	
    8.27 -	public void initVideo (){
    8.28 -		frame = new BufferedImage(
    8.29 -				width, height,
    8.30 -				BufferedImage.TYPE_INT_RGB);
    8.31 -		out.setFrameRate((int) Math.round(this.fps));
    8.32 -		out.setTimeScale(1);
    8.33 -		out.setVideoDimension(width, height);
    8.34 -		this.videoReady = true;
    8.35 -	}
    8.36 +    public void initVideo (){
    8.37 +	frame = new BufferedImage(
    8.38 +				  width, height,
    8.39 +				  BufferedImage.TYPE_INT_RGB);
    8.40 +	out.setFrameRate((int) Math.round(this.fps));
    8.41 +	out.setTimeScale(1);
    8.42 +	out.setVideoDimension(width, height);
    8.43 +	this.videoReady = true;
    8.44 +    }
    8.45  	
    8.46 -	public void record(BufferedImage rawFrame) {
    8.47 -		if (!videoReady){initVideo();}
    8.48 -		this.frame.getGraphics().drawImage(rawFrame, 0, 0, null);
    8.49 -		try {out.writeFrame(frame);}
    8.50 -		catch (IOException e){e.printStackTrace();}
    8.51 -	}
    8.52 +    public void record(BufferedImage rawFrame) {
    8.53 +	if (!videoReady){initVideo();}
    8.54 +	this.frame.getGraphics().drawImage(rawFrame, 0, 0, null);
    8.55 +	try {out.writeFrame(frame);}
    8.56 +	catch (IOException e){e.printStackTrace();}
    8.57 +    }
    8.58  	
    8.59 -	public void finish() {
    8.60 -		try {out.close();} 
    8.61 -		catch (IOException e) {e.printStackTrace();}
    8.62 -	}
    8.63 +    public void finish() {
    8.64 +	try {out.close();} 
    8.65 +	catch (IOException e) {e.printStackTrace();}
    8.66 +    }
    8.67  
    8.68  	
    8.69  
     9.1 --- a/src/com/aurellem/capture/video/AbstractVideoRecorder.java	Mon Oct 31 07:43:44 2011 -0700
     9.2 +++ b/src/com/aurellem/capture/video/AbstractVideoRecorder.java	Thu Nov 03 16:00:46 2011 -0700
     9.3 @@ -19,9 +19,9 @@
     9.4  import com.jme3.util.Screenshots;
     9.5  
     9.6  /**
     9.7 - * <code>VideoProcessor</code> copies the frames it receives to video. 
     9.8 + * <code>VideoRecorder</code> copies the frames it receives to video. 
     9.9   * To ensure smooth video at a constant framerate, you should set your 
    9.10 - * application's timer to a new {@link IsoTimer}.  This class will 
    9.11 + * application's timer to a new <code>IsoTimer</code>.  This class will 
    9.12   * auto-determine the framerate of the video based on the time difference 
    9.13   * between the first two frames it receives, although you can manually set 
    9.14   * the framerate by calling <code>setFps(newFramerate)</code>.  Be sure to 
    9.15 @@ -44,7 +44,7 @@
    9.16   */
    9.17  
    9.18  public abstract class AbstractVideoRecorder 
    9.19 -	implements SceneProcessor, IVideoRecorder, AppState{
    9.20 +	implements SceneProcessor, VideoRecorder, AppState{
    9.21  
    9.22  	final File output;
    9.23  	Camera camera;
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/com/aurellem/capture/video/FileVideoRecorder.java	Thu Nov 03 16:00:46 2011 -0700
    10.3 @@ -0,0 +1,41 @@
    10.4 +package com.aurellem.capture.video;
    10.5 +
    10.6 +import java.awt.image.BufferedImage;
    10.7 +import java.io.File;
    10.8 +import java.io.IOException;
    10.9 +import javax.imageio.ImageIO;
   10.10 +
   10.11 +public  class FileVideoRecorder extends AbstractVideoRecorder{
   10.12 +    int current;
   10.13 +    File outDir;
   10.14 +    String formatName = "png";
   10.15 +	
   10.16 +    public FileVideoRecorder(File output) throws IOException {
   10.17 +	super(output);
   10.18 +	if (output.exists() 
   10.19 +	    && output.isDirectory() 
   10.20 +	    && (0 == output.listFiles().length)){
   10.21 +	    // good
   10.22 +	}
   10.23 +	else if (!output.exists()){
   10.24 +	    output.mkdir();
   10.25 +	}
   10.26 +	else {
   10.27 +	    throw new IOException("argument must be either an empty " + 
   10.28 +				  "directory or a nonexistent one.");
   10.29 +	}
   10.30 +	this.outDir = output;
   10.31 +    }
   10.32 +
   10.33 +    public void record(BufferedImage rawFrame) {
   10.34 +	String name = String.format("%07d.%s" , current++, formatName);
   10.35 +	File target = new File(output, name);
   10.36 +	try {ImageIO.write(rawFrame, formatName, target);}
   10.37 +	catch (IOException e) {e.printStackTrace();}
   10.38 +    }
   10.39 +
   10.40 +    public void finish() {}
   10.41 +}
   10.42 +
   10.43 +
   10.44 +
    11.1 --- a/src/com/aurellem/capture/video/IVideoRecorder.java	Mon Oct 31 07:43:44 2011 -0700
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,21 +0,0 @@
    11.4 -package com.aurellem.capture.video;
    11.5 -
    11.6 -import java.awt.image.BufferedImage;
    11.7 -
    11.8 -public interface IVideoRecorder{
    11.9 -
   11.10 -	void record(BufferedImage image);
   11.11 -	
   11.12 -	void pause();
   11.13 -	
   11.14 -	void start();
   11.15 -	
   11.16 -	/**
   11.17 -	 * closes the video file, writing appropriate headers, trailers, etc.
   11.18 -	 * After this is called, no more recording can be done.
   11.19 -	 */
   11.20 -	void finish();
   11.21 -	
   11.22 -}
   11.23 -
   11.24 -
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/com/aurellem/capture/video/VideoRecorder.java	Thu Nov 03 16:00:46 2011 -0700
    12.3 @@ -0,0 +1,29 @@
    12.4 +package com.aurellem.capture.video;
    12.5 +
    12.6 +import java.awt.image.BufferedImage;
    12.7 +
    12.8 +public interface VideoRecorder{
    12.9 +
   12.10 +	/**	
   12.11 +	 * Write this image to video, disk, etc.
   12.12 +	 * @param image the image to write
   12.13 +	 */
   12.14 +	void record(BufferedImage image);
   12.15 +	
   12.16 +	/**
   12.17 +	 * stop recording temporarally.  The recording can be started again
   12.18 +	 * with start()
   12.19 +	 */
   12.20 +	void pause();
   12.21 +	
   12.22 +	/**
   12.23 +	 * start the recording.
   12.24 +	 */
   12.25 +	void start();
   12.26 +	
   12.27 +	/**
   12.28 +	 * closes the video file, writing appropriate headers, trailers, etc.
   12.29 +	 * After this is called, no more recording can be done.
   12.30 +	 */
   12.31 +	void finish();	
   12.32 +}
   12.33 \ No newline at end of file