Video loop() choppy

I am using standard code from the example page to loop a video file (720p30 AVC). The initial buffering is quite long. Worse yet, the looping is far from smooth, with pauses up to two seconds (!) at the transition.

The computer is capable of smooth 4K rendering, so it’s certainly NOT the issue.

Any tips/tricks?

Perhaps try the FX2D and/or P2D renderers and see if that helps performance.

Specifying image dimensions causes the image (or video) to be resized every frame.
This severely reduces performance when using a renderer that is not totally hardware-accelerated.

Thanks for the suggestions. I need to keep this in pure Processing environment since it is being used for teaching. However I can suggest compiling to my students.

Try a different codec. There are ways to control the buffering in the GStreamer pipeline, as well as improve the loop positioning that the Video library is using, but the best bet is to use a video codec that is better suited to random access / has only key frames. If storage space isn’t too much of a concern, MJPEG would be a good thing to try.

This has very little to do with heap size, as the GStreamer data is not on the heap.

1 Like

Playing JVM settings whack-a-mole is never a good idea! :wink: At best this will have no effect, but it could make the problem worse.

In detail, if you’re interested : Managing off-heap (native) memory via the Java garbage collector is awkward at the best of times. This memory is outside of your 512M setting. If the setting you have allocates far more memory for the JVM than necessary, and therefore reduces the frequency of garbage collection (GC), it might lead to an increase in memory usage and stuttering in the GStreamer pipeline. I’m one of the authors of the GStreamer bindings used here, and wrote the current memory management. It supports implicit (via GC) and explicit memory management, but Processing mostly relies on the GC route.

You can try out the Processing 4 VLCJVideo library.

See what you think!

import VLCJVideo.VLCJVideo;
private VLCJVideo video;
void setup() {
  size(800, 600);
  fill(255);
  video = new VLCJVideo(this);
  video.openAndPlay(sketchPath("hai-yorokonde.mp4"));
}
void draw() {
  background(0);
  image(video, 0, 0);
  text("FPS: "+frameRate, 0, 40);
}

VERY IMPORTANT: Specifying the image dimensions doubles resource consumption and reduces performance.
I recommend you avoid image(img, x, y, width, height) entirely.
I strongly encourage image(img, x, y), it doubles FPS when using the default renderer.

This code works very well:

import VLCJVideo.VLCJVideo;
private VLCJVideo video;
private int x, y;
void setup() {
  size(800, 450);
  video = new VLCJVideo(this);
  video.open(sketchPath("Dragostea Din Tei.mpg"));
  Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    video.stop();
    println("Closing resources...");
    video.dispose();
    println("Closed resources.");
  }
  ));
  fill(255);
  imageMode(CENTER);
  x = Math.round(width/2);
  y = Math.round(height/2);
  video.play();
}
void draw() {
  background(0);
  image(video, x, y);
  if (video.isStopped()) {
    video.dispose();
  }
}

See what you think!