Random video player freezes after two hours

edited September 2017 in Library Questions

Hi everybody

For a project I programmed a random video player using the processing video library. If the space bar is pressed a random video is played. After that the player plays a video in a loop until space bar is pressed again. This worked perfectly on my MacBook, however it doesn't in the installation setting with a slightly older iMac. I guess the source for the problem lies in the code. But I cannot figure out were.

Any help is very welcome.

This is the code:

import processing.video.*;

int numMovies = 9;
boolean valid=false;
String[] one = {
  "Video1.mp4", "Video2.mp4", "Video3.mp4", "Video4.mp4", "Video5.mp4", "Video6.mp4", "Video7.mp4", "Video8.mp4", "Video9.mp4"
};

float movieEndDuration = 0.5;

Movie myMovie;
Movie myLoop;

void setup()
{
  fullScreen(P2D);
  myLoop  = new Movie(this, "VideoLoop.mp4");
  myLoop.loop();
}

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


void draw()
{
  if (valid == true) {
    image(myMovie, 0, 0, width, height);
  } else
  {
    image(myLoop, 0, 0, width, height);
  }
  if (valid && myMovie.time()+ movieEndDuration >= myMovie.duration()) {
    myMovie.stop();
    valid=false;
    myLoop = new Movie(this, "VideoLoop.mp4");
    myLoop.loop();
  }
}


void keyPressed() {
  if (key == ' ' && valid==true) {
    myMovie.stop();
    myLoop.stop();
  } 
  if (keyCode == ENTER && valid==true)
  {
    myMovie.stop();
    myLoop.stop();
  }
}


void keyReleased()
{

  if (key == ' ')
  {
    valid=true;
    println(one[int(random(numMovies))]);
    myLoop.stop();
    myMovie = new Movie(this, one[int(random(numMovies))]);
    myMovie.play();
  } 
  if (keyCode == ENTER)
  {
    valid=true;
    myLoop.stop();
    myMovie = new Movie(this, "About.mp4");
    myMovie.play();
  }
}
Tagged:

Answers

  • edit post, highlight code, press ctrl-o to format

  • @oehin -- Re:

    This worked perfectly on my MacBook, however it doesn't in the installation setting with a slightly older iMac

    • What model is your new MacBook, what model is your old?
    • What macOS version is each one running?
    • What version of Processing is each one running?
  • Hi Jeremy,

    thanks for your reply. As the installation is 100 km from where I live I cannot check yet what version of iMac it is (except that it is older and 21,5"). However I will do so tomorrow. I will probably also be able to attach the bug report. As it will crash anyway.

    The MacBook I have is a MacBook Pro Retina, 15" with Sierra 10.12.6 installed, 16 GB memory, 2.5 GHz Intel Core i7 Processor and AMD Radeon R9 M370X 2048 MB Intel Iris Pro 1536 MB Graphic Card.

    Both computers are running the latest version of Processing (3.3.6).

  • I could check the computer which is used for the installation:

    21.5 inch iMac, late 2012 Processor: 2.9 GHz Intel Core i5 Memory: 16 GB 1600 MHz DDR3 Graphic Card: NIVIDIA GeForce GT 650M 512 MB

    Its running on MacOS Sierra 10.12.5

  • It crashed already twice this morning. Therefore I have two reports:

    Report 1

    ERROR: transport error 202: recv error: Operation timed out java.lang.NullPointerException at java.util.LinkedList.unlink(LinkedList.java:211) at java.util.LinkedList.remove(LinkedList.java:526) at processing.opengl.Texture.bufferUpdate(Texture.java:899) at processing.opengl.PGraphicsOpenGL.getTexture(PGraphicsOpenGL.java:6375) at processing.opengl.PGraphicsOpenGL$TexCache.getTexture(PGraphicsOpenGL.java:7406) at processing.opengl.PGraphicsOpenGL.flushPolys(PGraphicsOpenGL.java:2370) at processing.opengl.PGraphicsOpenGL.flush(PGraphicsOpenGL.java:2311) at processing.opengl.PGraphicsOpenGL.endDraw(PGraphicsOpenGL.java:1480) at processing.core.PApplet.handleDraw(PApplet.java:2455) at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:849) at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692) at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674) at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443) at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293) at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147) at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:759) at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81) at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452) at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178) at java.util.TimerThread.mainLoop(Timer.java:555) at java.util.TimerThread.run(Timer.java:505)

    Report 2

    java.lang.NullPointerException at java.util.LinkedList.unlink(LinkedList.java:211) at java.util.LinkedList.remove(LinkedList.java:526) at processing.opengl.Texture.bufferUpdate(Texture.java:899) at processing.opengl.PGraphicsOpenGL.getTexture(PGraphicsOpenGL.java:6375) at processing.opengl.PGraphicsOpenGL$TexCache.getTexture(PGraphicsOpenGL.java:7406) at processing.opengl.PGraphicsOpenGL.flushPolys(PGraphicsOpenGL.java:2370) at processing.opengl.PGraphicsOpenGL.flush(PGraphicsOpenGL.java:2311) at processing.opengl.PGraphicsOpenGL.endDraw(PGraphicsOpenGL.java:1480) at processing.core.PApplet.handleDraw(PApplet.java:2455) at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:849) at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692) at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674) at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443) at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293) at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147) at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:759) at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81) at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452) at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178) at java.util.TimerThread.mainLoop(Timer.java:555) at java.util.TimerThread.run(Timer.java:505)

  • Has anybody an idea where the problem ist. Why does the code freeze? I still couldn't find any solution. Thank you in advance.

  • Could you check your java version on each machine?

    It is hard to address this question unless the error is reproduced in another system. I would suggest adding debugging lines in your code to identify what line in your code is causing this error. This might not help but it would be the first thing I would try. If the error is thrown at the same line (for example, beginning of draw) then it is possible to find a work around. I was checking some online posts and it could be a synchronization problem in the java.util.LinkedList. However take what I say with a grain of salt.

    Kf

  • Answer ✓

    Can you load all the videos in setup and then just switch to them as needed? The repeated calling of new Movie irks me.

    I'd certainly try and keep the loop in memory.

  • @oehin did you find the cause or solution to the issue?

  • edited February 20

    Hi together

    Thanks for your help.

    I'm sorry for the late reply. I tried a lot of changes on my code but couldn't figure out the problem. However, I'm exhibiting again in a month to come so I want to give it another try.

    I cleaned up my code a little bit by defining only one movie variable (myMovie) instead of two (myMovie and myLoop). I don't know if this helps as I don't have the iMac which caused the bug at hand. I will only be able to test it again in three weeks.

    I also changed “Movie m” to “Movie myMovie” as m wasn't defined. Maybe this also caused the bug.

    And I eliminated the void key pressed function.

    Do you have other suggestion where my code could be further cleaned? Thank you in advance!

    @koogs I tried to load all the videos in setup but it didn't work as the player needs to switch back to VideoLoop after playing one of the Videos 1 to 9. However, I don't know if I understood your input correctly. What do you mean with “keep the loop in memory”?

         import processing.video.*;
    
        boolean valid=false;
        String[] one = {
          "Video1.mp4", "Video2.mp4", "Video3.mp4", "Video4.mp4", "Video5.mp4", "Video6.mp4", "Video7.mp4", "Video8.mp4", "Video9.mp4"
        };
    
        float movieEndDuration = 0.5;
    
    
        Movie myMovie;
    
        void setup()
        {
          background(0);
          fullScreen(P2D);
          noCursor();
    
          myMovie  = new Movie(this, "VideoLoop.mp4");
          myMovie.loop();
        }
    
    
        void movieEvent(Movie myMovie) {
          myMovie.read();
        }
    
    
        void draw() {
          image(myMovie, 0, 0, width, height);
    
          if (valid==true && myMovie.time()+ movieEndDuration >= myMovie.duration()) {
            myMovie.stop();
            myMovie = new Movie(this, "VideoLoop.mp4");
            myMovie.loop();
          }
        }
    
    
        void keyReleased()
        {
    
          if (key == ' ')
          {
            valid=true;
            println(one[int(random(one.length))]);
            myMovie.stop();
            myMovie = new Movie(this, one[int(random(one.length))]);
            myMovie.play();
          } 
          if (keyCode == ENTER)
          {
            valid=true;
            myMovie.stop();
            myMovie = new Movie(this, "About.mp4");
            myMovie.play();
          }
        }
    
  • @oehin yes, don't keep creating a new Movie in keyReleased - use a Movie[] field, create all the Movie in the array in setup(). You could also try the new beta release of the Video library with GStreamer 1.x support. There are potentially some memory issues in the old GStreamer 0.10 Java bindings. Only GStreamer 1.x and the Java bindings for it are actually maintained by anyone (the latter mainly by me).

    Having said that, your stack traces look like it could be a threading issue - try changing your keyReleased() code to set one or two boolean flags, and actually switch stop / switch the movie in draw() instead.

  • edited February 25

    @neilcsmith_net @GoToLoop @koogs @kfrajer Thank you so much for your help. As I'm not so much into programming, I struggled quite a lot on reelaborating my code based on your inputs. However, I think I have now a better code which uses an array, avoids repeated calling of NewMovie and plays / stops movies in draw. Thank you!

    The player is now looping on Video11 and randomly plays Video1 to Video9 when pressing the space button and plays Video10 when pressing the Enter button. It then goes back to looping Video11.

    As I still cannot test the code on the final computer / setting, I'm happy if you can comment if you see any other issues with the code. Thanks again!

            import processing.video.*;
    
            int numMovies = 11; // Quantità video 
            Movie[] Videos= new Movie[numMovies];// Video 10 = About, Video 11 = Loop
    
            int idx = 10;//indice per video attuale
    
            float movieEndDuration = 0.5; // numero magico
    
            void setup() {
              background(0);
              size(960, 540);
              //size(1920, 1080/2);
              //fullScreen(P2D);
    
              for (int i = 0; i < numMovies; i++) {
                Videos[i] = new Movie(this, "Video"+(i+1)+".mp4");// carica tutti i video
              }
              Videos[idx].loop();
            }
    
            void draw() {
    
              if (idx!=10) {
                image(Videos[idx], 0, 0, width, height); 
                Videos[idx].play();
              } else if (idx==10) {
                image(Videos[10], 0, 0, width, height);
                Videos[10].loop();
              }  
              if (idx!=10 && (Videos[idx].time() + movieEndDuration >= Videos[idx].duration())) {
                image(Videos[10], 0, 0, width, height);
                Videos[10].loop();
                idx=10;
              }
            }
    
            void movieEvent(Movie m) {
              m.read();
            }
    
    
            void keyPressed() {
    
              //println(keyCode);
    
              if (key == ' ') {
                Videos[idx].stop(); 
                idx=int(random(9));
                println(idx);
              } else if (keyCode == ENTER) {
                Videos[idx].stop(); 
                idx=9;
              }
            }
    
  • idx=int(random(9));
    

    Random integer between 0 and 8 (inclusive)...

  • There seems to be confusion between how many videos you have. Why 9 in line 53?

    Make numMovies a constant (NUM_MOVIES) and use that everywhere, don't litter the code with 9s and 10s.

  • @koogs Thank you yes, my comment was wrong I edited it. It randomly plays Video1 to Video9, i.e. 0 to 8 in the array.

  • Answer ✓
    if (idx!=10) {
    ...
    } else if (idx==10) {
    

    Second if is redundant here, just else will work. If it's not != then it's got to be equal.

  • The 9 in 53 is to randomly play only the Videos 1 to 9 . 10 is only triggered with enter key, 11 loops before any key is pressed and after any movie stops.

  • Answer ✓

    So in total you have 11 movies, from index 0 to index 11. The last movie is played when your press enter.

    I would have this layout instead:

    Global:

    final int NUMMOVIES=10;
    Movie[] videosSpaceKey= new Movie[NUMMOVIES];
    Movie video EnterKey;
    

    Setup():

    for (int i = 0; i < NUMMOVIES; i++) {
      videosSpaceKey[i] = new Movie(this, "Video"+(i+1)+".mp4");// carica tutti i video
    }
    EnterKey= new Movie(this, "Video11.mp4");
    

    Then in draw(), you need to display the proper movie, probably based on index or by detecting if you are in ENTER mode or SPACE-BAR mode. For this, you need implement states in your code. Also you need to update your keyPressed() as well to reflect in the changes of the movie structures and either the index or the state, if you decide to go for it.

    You need to make two more changes:

    1. The call videos[idx].play(); should be move to keyPressed(). This is needs to be tested but to me it is more natural to call play() in keyPressed() instead of calling it in draw()which is executed 30 fps.
    2. The name of your movie array needs to be changed. The first letter must be lower case. Notice, the name of the class is Movie. The name of the object should be video not Video.

    My comments here are suggestions. The last two are easier to implement. Moving the call of play from draw to keyPressed needs to be tested before doing any additional changes. Other changes that I suggested are just suggestions.

    Kf

  • edited March 24

    Hey @kfrajer, thanks a lot for your great input. I tried to implement it in the code. It works quite smoothly now.

        import processing.video.*;
    
        int numMovies = 9; // Quantità video 
        Movie[] videos= new Movie[numMovies];// 9 movies randomly played when space key is pressed
        Movie About; // About video which is played when Enter key is pressed
        Movie Loop; // Loop, plays when code is started and after every other video stopped playing, including About
    
        int mySwitch = 1;
        int idx = 1;// index for current video
        float movieEndDuration = 0.5; // magic number
    
        void setup() {
          background(0);
          noCursor();
          fullScreen(P2D);
    
          for (int i = 0; i < numMovies; i++) {
            videos[i] = new Movie(this, "Video"+(i+1)+".mp4");// loads all 9 videos in the array "videos[idx]"
          }
          About = new Movie(this, "About.mp4"); //loads "About.mp4" 
          Loop = new Movie(this, "Loop.mp4"); // loads "Loop.mp4" 
          Loop.loop(); // plays loop video immediately when starting the code
        }
    
        void draw() {
          if (mySwitch==1) {
            image(Loop, 0, 0, width, height); // loads image for "Loop"
          } else if  (mySwitch==2) {
            image(videos[idx], 0, 0, width, height); //loads image for the array "videos[idx]"
          } else if (mySwitch==3) {
            image(About, 0, 0, width, height); // loads image for "About"
          }
    
    
          if (mySwitch==2 && (videos[idx].time() + movieEndDuration >= videos[idx].duration())) {
            mySwitch=1;
            Loop.loop(); //loops "Loop" after any of the movies in the array "videos" finishes
          } else if (mySwitch==3 && (About.time() + movieEndDuration >= About.duration())) {
            mySwitch=1;
            Loop.loop(); //loops "Loop" after "About" finishes
          }
        }
    
        void movieEvent(Movie m) {
          m.read();
        }
    
        /*void keyPressed() {
          if (key == ' ' || keyCode == ENTER) {
            Loop.stop();
            About.stop();
            videos[idx].stop();
          }
        }*/
    
        void keyReleased() {
    
          if (key == ' ') { //when space key is released any video is stopped, "mySwitch" switches to "2" and a random video of the array "videos[idx] is played
            Loop.stop();
            About.stop();
            videos[idx].stop();
            mySwitch=2;
            idx=int(random(numMovies));
            videos[idx].play();
            println(idx);
          }  
          if (keyCode == ENTER) { // when the enter key is released any video stops, "mySwitch" switches to "3" and "About" is played
            Loop.stop();
            About.stop();
            videos[idx].stop();
            mySwitch=3;
            About.play();
          }
        }
    
  • I'm exhibiting again right now. The player runs without any problems for 5 hours, however, sometimes it crashes again. This is the error code I got yesterday. Anybody knows what the problem could be?

    However, many thanks to everybody who helped me to improve my basic processing skills! It's much better now anyway than before when it crashed once an hour.

    IMG_3742

Sign In or Register to comment.