annotate src/com/aurellem/capture/Capture.java @ 73:877ae4b2993c tip

merge laptop changes.
author Robert McIntyre <rlm@mit.edu>
date Mon, 10 Mar 2014 18:58:08 -0400
parents dd97f65f940c
children
rev   line source
rlm@3 1 package com.aurellem.capture;
rlm@3 2
rlm@3 3 import java.io.File;
rlm@3 4 import java.io.IOException;
rlm@12 5 import java.util.concurrent.Callable;
rlm@3 6
rlm@12 7 import com.aurellem.capture.audio.MultiListener;
rlm@12 8 import com.aurellem.capture.audio.WaveFileWriter;
rlm@9 9 import com.aurellem.capture.video.AVIVideoRecorder;
rlm@10 10 import com.aurellem.capture.video.AbstractVideoRecorder;
rlm@39 11 import com.aurellem.capture.video.FileVideoRecorder;
rlm@71 12 //import com.aurellem.capture.video.XuggleVideoRecorder;
rlm@3 13 import com.jme3.app.Application;
rlm@12 14 import com.jme3.audio.AudioRenderer;
rlm@12 15 import com.jme3.renderer.ViewPort;
rlm@12 16 import com.jme3.scene.Spatial;
rlm@49 17 import com.jme3.system.AppSettings;
rlm@44 18 import com.jme3.system.JmeSystem;
rlm@3 19
rlm@53 20 /**
rlm@68 21 * Use the methods in this class for capturing consistent,
rlm@68 22 * high quality video and audio from a jMonkeyEngine3
rlm@68 23 * application. To capture audio or video do the following:
rlm@53 24 *
rlm@68 25 * 1.) Set your application's timer to an IsoTimer. Create
rlm@68 26 * the IsoTimer with the desired video
rlm@68 27 * frames-per-second.
rlm@56 28 *
rlm@68 29 * 2.) Call captureAudio and/or captureVideo on the
rlm@68 30 * Application as desired before starting the
rlm@68 31 * Application.
rlm@55 32 *
rlm@68 33 * See the Basic and Advanced demos in the examples section
rlm@68 34 * for more information. If you have any trouble, please PM
rlm@68 35 * me on the jMonkeyEngine forums. My username is bortreb.
rlm@55 36 *
rlm@53 37 * @author Robert McIntyre
rlm@53 38 */
rlm@53 39
rlm@3 40 public class Capture {
rlm@3 41
rlm@56 42 /**
rlm@68 43 * Use this function to capture video from your
rlm@68 44 * application. You specify the framerate at which the
rlm@68 45 * video will be recording by setting the Application's
rlm@68 46 * timer to an IsoTimer created with the desired
rlm@56 47 * frames-per-second.
rlm@56 48 *
rlm@68 49 * There are three ways to record and they are selected
rlm@68 50 * by the properties of the file that you specify.
rlm@56 51 *
rlm@68 52 * 1.) (Preferred) If you supply an empty directory as
rlm@68 53 * the file, then the video will be saved as a
rlm@68 54 * sequence of .png files, one file per frame. The
rlm@68 55 * files start at 0000000.png and increment from
rlm@68 56 * there. You can then combine the frames into your
rlm@68 57 * preferred container/codec. If the directory is
rlm@68 58 * not empty, then writing video frames to it will
rlm@68 59 * fail, and nothing will be written.
rlm@56 60 *
rlm@68 61 * 2.) If the filename ends in ".avi" then the frames
rlm@68 62 * will be encoded as a RAW stream inside an AVI 1.0
rlm@68 63 * container. The resulting file will be quite
rlm@68 64 * large and you will probably want to re-encode it
rlm@68 65 * to your preferred container/codec format. Be
rlm@68 66 * advised that some video payers cannot process AVI
rlm@68 67 * with a RAW stream, and that AVI 1.0 files
rlm@68 68 * generated by this method that exceed 2.0GB are
rlm@68 69 * invalid according to the AVI 1.0 spec (but many
rlm@68 70 * programs can still deal with them.) Thanks to
rlm@68 71 * Werner Randelshofer for his excellent work which
rlm@68 72 * made AVI file writer option possible.
rlm@56 73 *
rlm@68 74 * 3.) Any non-directory file ending in anything other
rlm@68 75 * than ".avi" will be processed through Xuggle.
rlm@68 76 * Xuggle provides the option to use many
rlm@68 77 * codecs/containers, but you will have to install
rlm@68 78 * it on your system yourself in order to use this
rlm@68 79 * option. Please visit http://www.xuggle.com/ to
rlm@68 80 * learn how to do this.
rlm@56 81 *
rlm@56 82 * @param app The Application from which you wish to record Video.
rlm@56 83 * @param file The file to which the video will be captured.
rlm@56 84 * @throws IOException
rlm@56 85 */
rlm@54 86
rlm@68 87 public static void captureVideo
rlm@68 88 (final Application app, final File file) throws IOException{
rlm@56 89 final AbstractVideoRecorder videoRecorder;
rlm@12 90
rlm@56 91 if (file.getCanonicalPath().endsWith(".avi")){
rlm@56 92 videoRecorder = new AVIVideoRecorder(file);}
rlm@72 93 else {
rlm@56 94 videoRecorder = new FileVideoRecorder(file);}
rlm@72 95 //else {
rlm@71 96 //videoRecorder = new XuggleVideoRecorder(file);
rlm@72 97 //}
rlm@12 98
rlm@56 99 Callable<Object> thunk = new Callable<Object>(){
rlm@56 100 public Object call(){
rlm@12 101
rlm@56 102 ViewPort viewPort =
rlm@56 103 app.getRenderManager()
rlm@68 104 .createPostView("aurellem video record",
rlm@68 105 app.getCamera());
rlm@12 106
rlm@56 107 viewPort.setClearFlags(false, false, false);
rlm@12 108
rlm@56 109 // get GUI node stuff
rlm@56 110 for (Spatial s : app.getGuiViewPort().getScenes()){
rlm@56 111 viewPort.attachScene(s);
rlm@56 112 }
rlm@12 113
rlm@56 114 app.getStateManager().attach(videoRecorder);
rlm@56 115 viewPort.addProcessor(videoRecorder);
rlm@56 116 return null;
rlm@56 117 }
rlm@56 118 };
rlm@56 119 app.enqueue(thunk);
rlm@56 120 }
rlm@12 121
rlm@54 122
rlm@56 123 /**
rlm@68 124 * Use this function to capture audio from your
rlm@68 125 * application. Audio data will be saved in linear PCM
rlm@68 126 * format at 44,100 hertz in the wav container format to
rlm@68 127 * the file that you specify.
rlm@56 128 *
rlm@68 129 * Note that you *have* to use an IsoTimer for your
rlm@68 130 * Application's timer while recording audio or the
rlm@68 131 * recording will fail. Also ensure that your IsoTimer
rlm@68 132 * obeys the following constraints:
rlm@56 133 *
rlm@68 134 * 1.) The frames-per-second value of the IsoTimer
rlm@68 135 * cannot be lower than 10 frames-per-second.
rlm@56 136 *
rlm@68 137 * 2.) The frames-per-second value of the IsoTimer must
rlm@68 138 * evenly divide 44,100.
rlm@56 139 *
rlm@68 140 * @param app The Application from which you wish to
rlm@68 141 * record Audio.
rlm@68 142 * @param file the target file to which you want to
rlm@68 143 * record audio data.
rlm@56 144 * @throws IOException
rlm@56 145 */
rlm@12 146
rlm@68 147 public static void captureAudio
rlm@68 148 (final Application app, final File file) throws IOException{
rlm@56 149 AppSettings settings = null;
rlm@68 150 if (app.getContext() != null){
rlm@68 151 settings = app.getContext().getSettings();}
rlm@56 152 if (settings == null){settings = new AppSettings(true);}
rlm@56 153 settings.setAudioRenderer("Send");
rlm@56 154 app.setSettings(settings);
rlm@49 155
rlm@56 156 JmeSystem.setSystemDelegate(new AurellemSystemDelegate());
rlm@49 157
rlm@56 158 final WaveFileWriter writer = new WaveFileWriter(file);
rlm@12 159
rlm@56 160 Callable<Object> thunk = new Callable<Object>(){
rlm@56 161 public Object call(){
rlm@56 162 AudioRenderer ar = app.getAudioRenderer();
rlm@56 163 if (ar instanceof MultiListener){
rlm@56 164 MultiListener ml = (MultiListener)ar;
rlm@56 165 ml.registerSoundProcessor(writer);
rlm@56 166 }
rlm@56 167 return null;
rlm@56 168 }
rlm@56 169 };
rlm@56 170 app.enqueue(thunk);
rlm@56 171 }
rlm@3 172 }