How to play same GL video on two windows

Hello P5 friends,

how can I play the same GLMovie instance on two windows? Here’s my code, with the error line marked:

import gohai.glvideo.*;

ControlFrame cf;
GLMovie myMovie;

void settings() {
  size(400, 400, P3D);
}

void setup() {
  cf = new ControlFrame(this, 400, 400, "Controls");

  myMovie = new GLMovie(this, "Timecode-1920x1080-30fps.mp4");
  myMovie.loop();
}

void draw() {
  if (myMovie.available()) { myMovie.read(); }
  image(myMovie,0,0,400,400);
}


class ControlFrame extends PApplet {
  int w, h;
  PApplet parent;

  public ControlFrame(PApplet _parent, int _w, int _h, String _name) {
    super();   
    parent = _parent;
    w=_w;
    h=_h;
    PApplet.runSketch(new String[]{this.getClass().getName()}, this);
  }

  public void settings() {
    size(w, h);
  }

  void draw() {
    // next line throws NullPointException error:
    //image(myMovie,0,0);
  }
}
1 Like

Do you mind sharing ther reference where you got this code from? Was it from Gohai’s repository or any of his sites?

Kf

This is almost certainly not possible. The two windows have different GL contexts for one. What OS?

The code basis for this controlFrame is from the controlP5 examples. I just added the movie playing code.

I’m developing it on Mac OS, but would like the code to be cross platform.

Well Mac might be the one thing it could be hacked to work on. Asked because was going to suggest Syphon or Spout, but not cross platform then. Could also draw to an (ideally small) offscreen graphics and grab the pixel array from that to transfer. Your control window isn’t using GL anyway.

1 Like

Thanks a lot, neilsmith! It worked like a charm!
Here’s the code:

import gohai.glvideo.*;

ControlFrame cf;
GLMovie myMovie;

PGraphics myMovieIconPre;
PImage myMovieIcon;

void settings() {
  size(400, 400, P3D);
}

void setup() {
  cf = new ControlFrame(this, 400, 400, "Controls");

  myMovieIconPre = createGraphics(64, 64, P2D);
  myMovieIcon = createImage(64, 64, RGB);

  myMovie = new GLMovie(this, "Timecode-1920x1080-30fps.mp4");
  myMovie.loop();
}

void draw() {
  if (myMovie.available()) { myMovie.read(); }
  image(myMovie,0,0,400,400);
  
  myMovieIconPre.beginDraw();
  myMovieIconPre.image(myMovie,0,0,64,64);
  myMovieIconPre.endDraw();
  
  //myMovieIconPre.loadPixels();
  //myMovieIcon.loadPixels(); 
  //arrayCopy(myMovieIconPre.pixels, myMovieIcon.pixels);   
  //myMovieIcon.updatePixels(); 
  
  myMovieIcon = myMovieIconPre.get();
}


class ControlFrame extends PApplet {
  int w, h;
  PApplet parent;

  public ControlFrame(PApplet _parent, int _w, int _h, String _name) {
    super();   
    parent = _parent;
    w=_w;
    h=_h;
    PApplet.runSketch(new String[]{this.getClass().getName()}, this);
  }

  public void settings() {
    size(w, h);
  }

  void draw() {
    image(myMovieIcon,0,0);
  }
}
2 Likes

Thanks for posting this.

It’s interesting that if I try to simplify it and remove the intermediate PGraphics and use .copy() to copy the video into the thumbnail it still works, but the playback frame rate of the large video drops below 1 fps, drawing a frame every few seconds. Maybe caused by some kind of locking issue?

With the proposed approach it works on Linux. Useful if you’re creating a video mixing tool with two windows (the gui and the rendered view).

ps. the updating of the thumbnail can be moved into if statement for better performance.

1 Like

@hamoid doesn’t copy() work with the pixel array rather than doing things on the GPU, if I’m remembering correctly?!

@neilcsmith Yes I thought so. And I thought that by copying pixels it might avoid issues of two graphics threads accessing the same texture in memory. But I guess my intuition doesn’t help :slight_smile:

Clarifying the weird behavior: the original video fps becomes extremely slow, but the thumbnail updates at the normal rate.

If you re-read the code posted you’ll notice that it specifically doesn’t do that - all texture access is in the main animation thread. What you’re doing will force the full size texture to be downloaded from the GPU to the pixel array. This scales into an intermediate graphics on the GPU, then downloads just the scaled down pixel array. That’s not to say this couldn’t be improved to not create lots of small images. And myMovieIcon should in theory be marked volatile.