Phantom Video Frame in Sketch

I am new to Processing so I’ve hit a wall. I’ve developed a simple sketch for an interactive work which triggers videos on keypress d,f,g. When a key is pressed the video should start from the beginning and play. If no other keys are pressed it just plays the full 30-second video and then switches to a full-screen video which loops. At any point, if a key is pressed the animation will play from the start - sometimes this needs to be halfway through another video playing. It should stop one and start the other from the first frame. The animation videos are spaced out from left to right. The problem I’m having is that when an animation video is triggered, then you trigger a different video halfway through - when you trigger the previous video, it flashes one frame from where it was last seen before starting from frame 0.

I’m sure it is something simple that I’m not seeing. I made a print line to see what the time was doing but it never prints the existence of this stored/old frame. Thus I have entitles it the ‘PHANTOM’ frame. Any help or advice would be amazing!

import processing.video.*;
// Animation Videos. Array called 'mov' with 3 slots for video files.
Movie[] mov = new Movie[3];
// Glow Video.
Movie movg;

// integer i stores which movie to be played.
int i = 0;


void setup() {
  fullScreen(P2D, 1);
  background(0);
  noStroke();
  frameRate(25);
  
  // Identifies which 3 video files are in the 'mov' animation array.
  mov[0] = new Movie(this, "01 Poutama.mov");
  mov[1] = new Movie(this, "02 Patikitiki.mov");
  mov[2] = new Movie(this, "03 Roimata.mov");
  // Identifies file for Glow Video.
  movg = new Movie(this, "glows.mov");
}


// Prepares videos to be played.
void movieEvent(Movie m) {
  m.read();
}


void draw() {
  println("mov = ", i," | mov 0 time", mov[0].time()," | mov 1 time", mov[1].time()," | mov 2 time", mov[2].time()); // print line to identify which video is playing and what the time is of the first video.
  background(0);
  
  // if an animation movie gets to the end, play and loop the glow video 
  if (mov[i].time() == mov[i].duration()) {
    image(movg, 0, 0, width, height);
    movg.loop();
    }
  else { //movie not finished - so play next frame of movie
    image(mov[i], width/3*i, 0, width/3, height);
    mov[i].play();
  }
}


void keyPressed() {
      mov[i].jump(30); // jumps current video to the end before switching i to trigger another video.
  
  //set i based on key pressed
  if (key == 'd') {
    i=0;
    mov[i].jump(0); // Videos will jump to the first frame ready to play.
  }
  if (key == 'f') {
    i=1;
    mov[i].jump(0);
  }
  if (key == 'g') {
    i=2;
    mov[i].jump(0);
  }
}
1 Like

Think I figured this one out, was definitely a bit tricky, but in the end something simple. I had to do with the placement of m.read() function, since it seems like that was being triggered before the keypressed and causing the video to jump to a different point. I also added a showAnimation boolean to have some control over which video is playing. But was able to get it to play from the first frame.

import processing.video.*;

Movie[] mov = new Movie[3];
// Glow Video
Movie movg;
int i=2;

Movie currentMovie;
Movie prevMovie;

boolean showAnimation = false;

void setup(){
  fullScreen(P2D);
  background(0);
  noStroke();
  frameRate(25);

  mov[0] = new Movie(this, "mov4.mov");
  mov[1] = new Movie(this, "mov4.mov");
  mov[2] = new Movie(this, "mov3.mov");

  currentMovie = mov[i];
  currentMovie.noLoop();

  movg = new Movie(this, "glows.mov");
  movg.loop();
}

void draw(){
  println("mov = ", i," | mov 0 time", mov[0].time()," | mov 1 time", mov[1].time()," | mov 2 time", mov[2].time()); // print line to identify which video is playing and what the time is of the first video.

  background(0);

  // if an animation movie gets to the end, play and loop the glow video 
  if (showAnimation) {

  	movg.read();
  	
    image(movg, 0, 0, width, height);
    movg.loop();
    
  } else { //movie not finished - so play next frame of movie

  	currentMovie.read();
  	
    currentMovie.play();
    image(currentMovie, width/3*i, 0, width/3, height);
  }

  if(currentMovie.time() >= currentMovie.duration()){
  	showAnimation = true;
  	currentMovie.stop();
    currentMovie.jump(0);
  }
}

void keyPressed() {
  
      
  //currentMovie.jump(currentMovie.duration()); // jumps current video to the end before switching i to trigger another video.

  //set i based on key pressed
  if (key == 'd') {
    i=0;
    currentMovie = mov[i];
  }
  if (key == 'f') {
    i=1;
    currentMovie = mov[i];
  }
  if (key == 'g') {
    i=2;
    currentMovie = mov[i];
  }

  currentMovie.jump(0); // Videos will jump to the first frame ready to play.

  showAnimation = false;
}
1 Like

Brilliant! Matthew you’re a legend! I had assumed that the m.read would only occur once during setup.

I like what you’ve done to make what’s happening more visible too.

Thanks for the support!

Glad to help! Also glad to for this to be my first forum post!

1 Like

Just to add on here for anyone having this problem in the future: m.read() was indeed happening multiple times in the original code because it was in the movieEvent function. That is a special callback function for the video library – it gets called any time there is a new frame in any playing movie (so, a lot).

This event function is run when a new movie frame is available. Use the read() method to capture this frame. If there is more than one movie in the program, movieEvent() is called each time any of the movies has a new frame available.

1 Like

Hi again,
I have experimented with a few options and have come up with the streamline code below which I think simplifies everything. @matthewortega and @jeremydouglass

Any advice of why the memory of the computer seems to go through the roof over a day of running this?

import processing.video.*;
Movie mov;

int section = 90;

void setup() {
  fullScreen(P2D, 1);
  frameRate(25);
  mov = new Movie(this, "full.mov");
  mov.play();
  mov.jump(section);
  noCursor();
}

void draw() {
  //println("Section = ", section, " | Seconds = ", mov.time());
 // background(0);
  image(mov, 0, 0, width, height);
  if (mov.time() >= section + 30) {
    section = 90;
    mov.jump(section);
  }
    else if (mov.time() >= 103) {
       mov.jump(90);
       mov.stop();
       mov.play();
    }
}


void keyPressed() {
  
  if (key == 'd') {
   section = 0;
  }
  if (key == 'f') {
   section = 30;
  }
  if (key == 'g') {
   section = 60;
  }  
  mov.jump(section);
}

// Prepares videos to be played.
void movieEvent(Movie m) {
  m.read();
}
1 Like

I don’t think I can help here but I would like to toss some suggestions:

  1. Would you get the same problem if you change image(mov, 0, 0, width, height); to image(mov, 0, 0);. If that is a problem, I suggest you resize your movie to the proper dimensions. Not sure if this will solve the problem. Also, I believe if you don’t resize, you could use ‘set()’ insteead of image(). Or maybe you are not allowed to use set if you change the pixels via loadPixels/updatePixels. Give it a hot.

  2. Do you need OpenGL for this? Could you run using either JAVA2D or RX2D renderers? Do you get the same memory consumption?

Kf

1 Like

@lukemcconnell have you tried with the beta version of the video library using GStreamer 1.x? There are potential memory leaks in the old GStreamer 0.10 libraries.

Thanks @neailsmith I had a quick look and it seems that I am using GStreamer 1.x.

This electronic mail transmission is intended for the named recipients only. It may contain private and confidential information. If this has come to you in error you must take no action based upon it, nor must you copy it or show it to anyone; please telephone or email the sender at Wintec immediately and return the original email. We cannot accept any liability for any loss or damage sustained as a result of software viruses. It is your responsibility to carry out such virus checking as is necessary before opening any attachment which may be included with this message.

So video library version 2? That’s worrying if you are. Why do you think it’s using up memory? Does it eventually crash with an out of memory error?

You might want to be careful with email signatures! :smile: