Problem playing multiple movie files in a sequence

Dear everyone,

I’m working on a project where I have several video files I want to play back in a sequence, and have the sequence itself repeat indefinitely. Every other video clip, Processing writes to the serial port which is received by my Arduino UNO board. Additionally, the output is mapped to a surface using the Keystone plugin (I adapted the code to from the example to fit my needs).

At first, everything worked as it should EXCEPT after a few repetitions of the sequence (ca. 3.5 times through for a sequence of 5 videos between ca. 10 and 40 seconds) it seems to get stuck, simply freezing on a frame and not incrementing the clips. I came back to the sketch later and it seemed to run fine indefinitely. Then, more recently, I ran the sketch and it exhibited the freezing behavior almost immediately.

I’ve searched forums and consulted some friends and I’m still not sure exactly what I’m doing wrong here. Thanks for any advice!

import processing.video.*;
import deadpixel.keystone.*;
import processing.serial.*;

Serial myPort;
Keystone ks; // the keystone object
CornerPinSurface surface; // this is the surface

int numClips =5;
Movie[] clips = new Movie[numClips];

boolean isPlaying = false;
boolean pause = true;
//boolean reset = false;
//int step =0;
//int prev = 0;
//int count=0;
int next=0;
int last = 0;
int index = 0;

// the offsceen buffer for keystone
PGraphics offscreen;

void setup() {

  size(1200, 800, P3D);
  //fullScreen(P3D);

  //write to serial port
  //get a bug if write to arduino and its not plugged in
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);

  //keystone object for projection mapping
  ks = new Keystone(this);
  surface = ks.createCornerPinSurface(width, height, 20);
  offscreen = createGraphics(width, height, P3D);

  for (int i = 0; i < clips.length; i ++ ) {
    clips[i] = new Movie(this, "SuH_" +(i+1)+ ".mov");
  }

  println("this many clips:"+clips.length);
}

void draw() {

  // start writing into the offscreen buffer
  offscreen.beginDraw();
  offscreen.background(255);

  if (isPlaying) {
    playClip();
  };

  if (!isPlaying) {
    nextClip();
  }

  serialWrite();
  pauseClip();

  //finished writing to offscreen buffer
  offscreen.endDraw();
  background(0);
  
  // add everything to the surface
  surface.render(offscreen);
}

void playClip() {

  //when clip time goes above clip duration increment variable 'next'
  if (clips[index].time() < clips[index].duration()) {
    offscreen.image(clips[index], 0, 0, width, height);
  } else if (clips[index].time() >= clips[index].duration() ) {
    println("next");
    next++;
    isPlaying = false;
  }
}

void nextClip() {

  //when change in variable 'next' detected, play next clip
  if ( next != last && index < (clips.length-1)) {
    next = last;
    index++;
    println("index is "+ index);
    offscreen.image(clips[index], 0, 0, width, height);
    clips[index].play();
    clips[index].jump(0);
    isPlaying = true;

  //when index reaches length of clip array, reset routine and play first clip
  } else if (next!=last && index >= (clips.length-1)) {

    // next = last;
    index = 0;
    next = 0;
    last = 0;
    isPlaying = true;
    pause = false;
    offscreen.image(clips[index], 0, 0, width, height);
    clips[index].play();
    clips[index].jump(0);
  }
}

void pauseClip() {
  if (!isPlaying && pause) {
    offscreen.image(clips[index], 0, 0, width, height);
  }
}

//write to serial port every other clip
void serialWrite() {
  if (isPlaying && clips[index].time() < clips[index].duration() && index%2 == 1) {
    myPort.write('1');
  } else if (isPlaying && clips[index].time() < clips[index].duration() && index%2 == 0) {
    myPort.write('0');
  }
}

void keyPressed() {

  switch(key) {
  case 'c':
    // enter/leave calibration mode, where surfaces can be warped
    // and moved
    ks.toggleCalibration();
    break;

  case 'l':
    // loads the saved layout
    ks.load();
    break;

  case 's':
    // saves the layout
    ks.save();
    break;

  case 'p':
    // play/pause the movie on keypress
    if (!isPlaying && pause) {
      index = 0;
      clips[index].play();
      println("index is "+ index);
      println("playing");
      isPlaying = true;
      pause = false;
    } else if (isPlaying && !pause) {
      clips[index].pause();
      println("paused");
      isPlaying = false;
      pause = true;
    }
    break;
  }
}

void movieEvent(Movie m) {
  m.read();
}

I get the following error:

  1. How did you install the keystone library?
  2. Where are the movie clips?
  3. Is there Arduino source code that we need to have in order to run your project?

Hi svan,

Thanks for your response.

  1. How did you install the keystone library?

I simply installed keystone from the library manager (https://keystonep5.sourceforge.net/).

  1. Where are the movie clips?

They’re in the data folder of the project and are named sequentially according to the naming protocol in this code:

for (int i = 0; i < clips.length; i ++ ) {
    clips[i] = new Movie(this, "SuH_" +(i+1)+ ".mov");
  }
  1. Is there Arduino source code that we need to have in order to run your project?

The Arduino shouldn’t be essential. One simply has to disable the ‘serialWrite()’ function or select a different serial port if the Arduino board isn’t plugged in. I’ll post the code here anyway just in case:



int relayPin = 6;
int val;
String command;

void setup() {

  Serial.begin(9600);

  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);
  delay(2000);
}

void loop() {
  if (Serial.available()) {  // If data is available to read,
    val = Serial.read();     // read it and store it in val
  }
  if (val == '1') {                // If 1 was received
    digitalWrite(relayPin, LOW);  // turn the LED on
  } else {
    digitalWrite(relayPin, HIGH);  // otherwise turn it off
  }
  delay(10);  // Wait 10 milliseconds for next reading
}