comparison src/com/aurellem/capture/Capture.java @ 56:afc437f637bd

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