rlm@3: package com.aurellem.capture;
rlm@3:
rlm@3: import java.awt.image.BufferedImage;
rlm@3: import java.io.File;
rlm@3: import java.io.IOException;
rlm@3: import java.nio.ByteBuffer;
rlm@3:
rlm@3: import com.jme3.app.Application;
rlm@3: import com.jme3.app.state.AppState;
rlm@3: import com.jme3.app.state.AppStateManager;
rlm@3: import com.jme3.post.SceneProcessor;
rlm@3: import com.jme3.renderer.Camera;
rlm@3: import com.jme3.renderer.RenderManager;
rlm@3: import com.jme3.renderer.ViewPort;
rlm@3: import com.jme3.renderer.queue.RenderQueue;
rlm@3: import com.jme3.texture.FrameBuffer;
rlm@3: import com.jme3.util.BufferUtils;
rlm@3: import com.jme3.util.Screenshots;
rlm@3:
rlm@3: /**
rlm@3: * VideoProcessor
copies the frames it receives to video.
rlm@3: * To ensure smooth video at a constant framerate, you should set your
rlm@3: * application's timer to a new {@link IsoTimer}. This class will
rlm@3: * auto-determine the framerate of the video based on the time difference
rlm@3: * between the first two frames it receives, although you can manually set
rlm@3: * the framerate by calling setFps(newFramerate)
. Be sure to
rlm@3: * place this processor *after* any other processors whose effects you want
rlm@3: * to be included in the output video. You can attach multiple
rlm@3: * VideoProcessor
s to the same ViewPort
.
rlm@3: *
rlm@3: * For example,
rlm@3: *
rlm@3: * someViewPort.addProcessor(new VideoProcessor(file1));
rlm@3: * someViewPort.addProcessor(someShadowRenderer);
rlm@3: * someViewPort.addProcessor(new VideoProcessor(file2));
rlm@3: *
rlm@3: *
rlm@3: * will output a video without shadows to file1
and a video
rlm@3: * with shadows to file2
rlm@3: *
rlm@3: * @author Robert McIntyre
rlm@3: *
rlm@3: */
rlm@3:
rlm@3: public abstract class AbstractVideoRecorder
rlm@3: implements SceneProcessor, IVideoRecorder, AppState{
rlm@3:
rlm@3: final File output;
rlm@3: Camera camera;
rlm@3: int width;
rlm@3: int height;
rlm@3: String targetFileName;
rlm@3: FrameBuffer frameBuffer;
rlm@3: Double fps = null;
rlm@3: RenderManager renderManager;
rlm@3: ByteBuffer byteBuffer;
rlm@3: BufferedImage rawFrame;
rlm@3: boolean isInitilized = false;
rlm@3: boolean paused = false;
rlm@3:
rlm@3: public AbstractVideoRecorder(File output) throws IOException {
rlm@3: this.output = output;
rlm@3: this.targetFileName = this.output.getCanonicalPath();
rlm@3: }
rlm@3:
rlm@3:
rlm@3: public double getFps() {return this.fps;}
rlm@3:
rlm@3: public AbstractVideoRecorder setFps(double fps) {
rlm@3: this.fps = fps;
rlm@3: return this;
rlm@3: }
rlm@3:
rlm@3: public void initialize(RenderManager rm, ViewPort viewPort) {
rlm@3: Camera camera = viewPort.getCamera();
rlm@3: this.width = camera.getWidth();
rlm@3: this.height = camera.getHeight();
rlm@3:
rlm@3: rawFrame = new BufferedImage(width, height,
rlm@3: BufferedImage.TYPE_4BYTE_ABGR);
rlm@3: byteBuffer = BufferUtils.createByteBuffer(width * height * 4 );
rlm@3: this.renderManager = rm;
rlm@3: this.isInitilized = true;
rlm@3: }
rlm@3:
rlm@3: public void reshape(ViewPort vp, int w, int h) {}
rlm@3:
rlm@3: public boolean isInitialized() {return this.isInitilized;}
rlm@3:
rlm@3: public void preFrame(float tpf) {
rlm@3: if (null == this.fps){
rlm@3: this.setFps(1.0 / tpf);}
rlm@3: }
rlm@3:
rlm@3: public void postQueue(RenderQueue rq) {}
rlm@3:
rlm@3: public void postFrame(FrameBuffer out) {
rlm@3: if (!this.paused){
rlm@3: byteBuffer.clear();
rlm@3: renderManager.getRenderer().readFrameBuffer(out, byteBuffer);
rlm@3: Screenshots.convertScreenShot(byteBuffer, rawFrame);
rlm@3: record(rawFrame);
rlm@3: }
rlm@3: }
rlm@3:
rlm@3: public void cleanup(){
rlm@3: this.pause();
rlm@3: this.finish();
rlm@3: };
rlm@3:
rlm@3: public void pause(){
rlm@3: this.paused = true;
rlm@3: }
rlm@3:
rlm@3: public void start(){
rlm@3: this.paused = false;
rlm@3: }
rlm@3:
rlm@3: // methods from AppState
rlm@3: public void initialize(AppStateManager stateManager, Application app) {}
rlm@3:
rlm@3: public void setEnabled(boolean active) {
rlm@3: if (active) {this.start();}
rlm@3: else {this.pause();}
rlm@3: }
rlm@3:
rlm@3: public boolean isEnabled() {
rlm@3: return this.paused;
rlm@3: }
rlm@3:
rlm@3: public void stateAttached(AppStateManager stateManager) {}
rlm@3:
rlm@3:
rlm@3: public void stateDetached(AppStateManager stateManager) {
rlm@3: this.pause();
rlm@3: this.finish();
rlm@3: }
rlm@3:
rlm@3: public void update(float tpf) {}
rlm@3: public void render(RenderManager rm) {}
rlm@3: public void postRender() {}
rlm@3:
rlm@3: }