Recording Video from a quad view

I implement a four views quad to animate my animation from 4 different cams with 4 different viewports. I want to be able to record what I see - the 4 views in the same screen (And not the each viewport separately).



I currently implement the 4 views like this (thanks to users on this forum):

[java]

// Setup lighting

DirectionalLight sun = new DirectionalLight();

sun.setColor(ColorRGBA.White);

sun.setDirection(Vector3f.UNIT_XYZ.negate());

rootNode.addLight(sun);



// Setup first view - upper left

viewPort.setBackgroundColor(ColorRGBA.Blue); // blue background only

// for this view

cam.setViewPort(0f, .5f, 0.5f, 1f); // resize the viewPort to upper

// left

cam.setLocation(new Vector3f(10.0f, 10.0f, 80.0f));



// Setup second view - upper right

Camera cam2 = cam.clone();

cam2.setViewPort(0.5f, 1f, 0.5f, 1f);

cam2.setLocation(new Vector3f(0, -50.0f, 20));

cam2.lookAt(new Vector3f(0, 0, 0), new Vector3f(0, 0, 0));



ViewPort view2 = renderManager.createMainView("Bottom Left", cam2);

view2.setBackgroundColor(ColorRGBA.Blue);

view2.setClearFlags(true, true, true);

view2.attachScene(rootNode);



// Setup third view - bottom right (2D VIEW)

Camera cam3 = cam.clone();

cam3.setViewPort(.5f, 1f, 0f, 0.5f);

cam3.setLocation(new Vector3f(0, 35.484704f, 0));

cam3.lookAt(new Vector3f(0, 0, 0), new Vector3f(0, 0, 0));



ViewPort view3 = renderManager.createMainView("Top Left", cam3);

view3.setClearFlags(true, true, true);

view3.setBackgroundColor(ColorRGBA.Blue);

view3.attachScene(rootNode);



// Setup fourth view - bottom left

Camera cam4 = cam.clone();

cam4.setViewPort(0f, .5f, 0f, .5f); // resize the viewPort to upper

// left

cam4.setLocation(new Vector3f(0, -20.0f, 20));

cam4.lookAt(new Vector3f(0, 0, 0), new Vector3f(0, 0, 0));



ViewPort view4 = renderManager.createMainView("Top Left", cam4);

view4.setClearFlags(true, true, true);

view4.setBackgroundColor(ColorRGBA.Blue);

view4.attachScene(rootNode);

[/java]





my video recording function that records only from 1 viewport is (I use Xuggler):

[java]

try { // set the timer to 30fps lock-step

this.setTimer(new VideoTimer(30));

this.viewPort.addProcessor(new VideoProcessor(myVideoFile)

.setFps(30));

} catch (IOException e) {

e.printStackTrace();

}



[/java]



1- how can I record from the quad (4 screens)?

2- I realized the performance dropped SIGNIFICANTLY is the engine now loading my scene X 4??? any work around it?



thx

I guess you add more VideoProcessors to the other view ports?

Already tried it, all I get is an empty video.



[java] try { // set the timer to 30fps lock-step

this.setTimer(new VideoTimer(30));

this.viewPort.addProcessor(new VideoProcessor(myVideoFile).setFps(30));

view4.addProcessor(new VideoProcessor(myVideoFile).setFps(30));

view3.addProcessor(new VideoProcessor(myVideoFile).setFps(30));

view2.addProcessor(new VideoProcessor(myVideoFile).setFps(30));



} catch (IOException e) {

e.printStackTrace();

}[/java]

Did you take the VideoProcessor out of VideoRecorderAppState? If so, you should rewrite it. It does not support multiple cameras. You would want not to take just one screenshot from the one provided camera, but 4 screenshots, merge them to one bigger image and write that image to the MjpegFileWriter.

Let me be more accurate:



I am using 3 files for the video processing



1- VideoProcessor.java



[java]public class VideoProcessor implements SceneProcessor{

final File output;

Camera camera;

int width;

int height;

String targetFileName;

FrameBuffer frameBuffer;

Double fps = null;

RenderManager renderManager;

ByteBuffer byteBuffer;

BufferedImage rawFrame;

BufferedImage frame;

IMediaWriter writer;

int videoChannel = 0;

long currentTimeStamp = 0;

boolean isInitilized = false;



public VideoProcessor(File output) throws IOException{

this.output = output;

this.targetFileName = this.output.getCanonicalPath();

}



public double getFps() {return this.fps;}



public VideoProcessor setFps(double fps) {

this.fps = fps;

return this;

}

public void initialize(RenderManager rm, ViewPort viewPort) {

this.camera = viewPort.getCamera();

this.width = camera.getWidth();

this.height = camera.getHeight();

/* JME3 outputs images of type BufferedImage.TYPE_4BYTE_ABGR,

  • while Xuggle can only handle images of type
  • BufferedImage.TYPE_3BYTE_BGR, so we will need to convert.

    */

    rawFrame = new BufferedImage(width, height,

    BufferedImage.TYPE_4BYTE_ABGR);

    frame = new BufferedImage(width, height,

    BufferedImage.TYPE_3BYTE_BGR);

    byteBuffer = BufferUtils.createByteBuffer(width * height * 4 );

    this.renderManager = rm;

    this.isInitilized = true;

    }



    public void reshape(ViewPort vp, int w, int h) {}



    public boolean isInitialized() {return this.isInitilized;}



    public void preFrame(float tpf) {

    if (null == this.fps){

    this.fps = (1.0 / tpf);}

    if (null == this.writer){

    writer = ToolFactory.makeWriter(targetFileName);

    writer.addVideoStream(videoChannel,

    0, IRational.make(fps),

    width, height);

    }

    }



    public void postQueue(RenderQueue rq) {}



    public void postFrame(FrameBuffer out) {

    byteBuffer.clear();

    renderManager.getRenderer().readFrameBuffer(out, byteBuffer);

    synchronized (frame){

    Screenshots.convertScreenShot(byteBuffer, rawFrame);

    // convert the Image into the form that Xuggle likes.

    frame.getGraphics().drawImage(rawFrame, 0, 0, null);

    writer.encodeVideo(videoChannel,

    frame,

    currentTimeStamp, TimeUnit.NANOSECONDS);

    }

    currentTimeStamp += (long) (1000000000.0 / fps);

    }



    public void cleanup() { writer.close(); }

    }[/java]







    2- VideoRecorder.java (interface)



    [java]public interface VideoRecorder {



    /**
  • Write this image to video, disk, etc.
  • @param image the image to write

    */

    void record(BufferedImage image);



    /**
  • stop recording temporarily. The recording can be started again
  • with start()

    */

    void pause();



    /**
  • start the recording.

    */

    void start();



    /**
  • closes the video file, writing appropriate headers, trailers, etc.
  • After this is called, no more recording can be done.

    */

    void finish();



    }

    [/java]



    and 3- VideoTimer.java



    [java]public class VideoTimer extends Timer {



    private float framerate;

    private int ticks;



    public VideoTimer(float framerate)

    {

    this.framerate = framerate;

    this.ticks = 0;

    }



    public long getTime()

    {

    return (long) ( this.ticks / this.framerate);

    }



    public long getResolution() { return 1000000000L; }



    public float getFrameRate() { return this.framerate; }



    public float getTimePerFrame()

    {

    return (float) ( 1.0f / this.framerate);

    }



    public void update() { this.ticks++; }



    public void reset() { this.ticks = 0; }



    }

    [/java]



    which file are you referring to?

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:capture_audio_video_to_a_file?s[]=video

1 Like

yeah I already saw it, that’s where I got my code (I used the simple video). I see that he had a video about recording in quad but really didn’t understand the approach or how he managed to do it.

Anyone have any idea on how to implement this?

Okay I’ve never done it but it doesn’t sound as complicated. So you can record a video for one viewport at the moment right? And you can show the quad, but the issue is that now you have 4 viewports. So I can see two solutions:



1- create a parent viewport and one processor that records the quad view and not 4 processors individually and try to mesh them, cz I really don’t see how you’re gonna be able to mesh all 4 together internally.



2- If you still can’t get it and running late on something, just use a software like camStudio or something. I would recommend a fancier software to catch the correct frame/s.



I don’t know, wish I knew more, let me know if you figure it out.

1 Like

Did anyone do anything similar? I’ve been struggling on this for three weeks now and still can’t figure it out. Can anyone at least give me the approach I should follow to get this working??



thanks

Well @garnaout gave you 3 approaches, all of them may work, did you try them?

yes I did. I am not being lazy… I don’t want to use CamStudio to record quad, that’s so inconveniant, I want it to be built in.



I also read the wiki and I don’t know how to proceed further. I successfully did it with one camera. I need a pseudo core or some more details to do it in quad…