Movie.duration() always returns 0.0, framerate() and speed() do not seem to affect playback

I've just started to experiment with the Movie library and I've run into some basic questions.

Here's the testbed code:

import processing.video.*;
Movie myMovie;
int screenSizeX = 800;
int screenSizeY = 600;
float duration = 0;

void settings()
{
  size(screenSizeX, screenSizeY);
}
void setup() {

  myMovie = new Movie(this, "20180201103135_20180201103155_01_M.dav");
  myMovie.frameRate(25);
  myMovie.speed(0.01);
  duration = myMovie.duration();
  println("setup duration =" + duration);
  duration = myMovie.playbin.queryDuration().toSeconds();
  println("setup playbin.queryDuration() duration =" + duration);
  myMovie.loop();
}

void draw() {
  image(myMovie, 0, 0);
  println("Duration=" + myMovie.duration());
}

// Called every time a new frame is available to read
void movieEvent(Movie m) {
  m.read();
  duration = myMovie.duration();
  println("movieEvent duration =" + duration);
}

When I run it, duration always appear to return 0.0 regardless of when I test it -- including if I call playbin directly (mimicking the library code at line 270 here: https://github.com/processing/processing-video/blob/master/src/processing/video/Movie.java ).

The console output is:
setup duration =0.0
setup playbin.queryDuration() duration =0.0
movieEvent duration =0.0
Duration=0.0
Duration=0.0
movieEvent duration =0.0
Duration=0.0
:

What I was really trying to do (apart from experimenting with playback at various speeds) was figure out how to detect when a Movie has finished playing? I've seen some example code that did this:

if (myMovie.time() >= myMovie.duration()) // Test if the playhead is at the end
{
   // end of Movie
}

Of course that's destined to fail if .duration() always returns zero. So that raises the question, how do you tell when a movie has finished?? I supposed I could check when .time() stops changing, but that squawks a dreaded red text error on the console when the code runs "off the end" of the Movie.

Anyone got any ideas how you test for when a Movie has finished playing? I need to work my way through a directory with hundreds of different movie files and extract individual frames -- I've figured out what I thought would be the hard part only to screech to a halt on this "simple" problem. :(

Oh....and anyone got any ideas why myMovie.frameRate() and .speed() don't appear to do anything?

Thanks in advance Andy

Answers

  • Hey, cool. Thanks GoToLoop. I've been searching for that for the past hour. Never thought to use the appropriate search terms like "event." Duh.

    Any thoughts on the frameRate() and speed() issues?

    Cheers

    Andy.

  • Dunno. Never used those methods. Sorry. X_X

  • When I run it, duration always appear to return 0.0 regardless of when I test it

    Do you get the same results running other video samples? Using mp4 files? That is the first thing I would do. There is not point to try to figure out the end of the movie if you cannot get duration to return a valid value or if the movie is not being played at all.

    Kf

  • edited February 2018

    Thanks, kf. I take your point, although GoToLoop's strategy (at https://Forum.Processing.org/two/discussion/14990/movie-begin-and-end-events#Item_1 of overriding the Movie eosEvent is pretty effective -- although it appears that sometimes draw() may get the same frame twice based on a calculation using myMovie.time().

    I think I have figured out the required code although note the myMovie.noLoop() at line 19 below. It seems to be necessary to prevent a spurious "Seek operation failed."

    I do still have one question, though -- I wanted to figure out which of two possible places in Movie.java was causing the "Seek operation failed." I found the library code at /Processing/libraries/video/src/processing/video/Movie.java -- however, when I edited the two instances of that message and then run the sketch, the changes are not reflected in the output message. So the question is: Is that the library code that really gets used when you do an import processing.video.* ? (I did a sudo find / -name 'Movie.*' -print but could not find any a Movie.jar or other likely source for the source (so to speak). So where does Processing do the import from, I wonder?

    Alternatively, of course, there is another place in the Movie-related code that is producing the "Seek operation failed" message.

    Anyway, the code that appears to work correctly is below -- I was trying to create a minimum verifiable test case so apologies @GoToLoop for hacking out the myEos()

    Andy

            import processing.video.*;
            Movie myMovie;
            float myMovieFramesPerSecond = 25;
            float duration = 0;
            float myMovieCurrentTime = 0;
            int myMovieCurrentFrame = 0;
            boolean movieFrameReady = false;
            boolean movieEnded = false;
    
            void settings()
            {
              size(800, 600);
            }
            void setup() {
    
              myMovie = new Movie(this, "test2.asf") {
                @ Override public void eosEvent() { // Private eosEvent
                  movieEnded = true;
                  myMovie.noLoop();    // Without this I get a red "Seek operation failed" when the movie ends
                  super.eosEvent();
                }
              };
              myMovie.loop();
            }
    
            void draw() {
              if (!movieEnded)    // If movie is still playing and frame available for display
              {
                if (movieFrameReady)  // Prevents draw() from displaying the same frame twice
                {
                  image(myMovie, 0, 0);     // Display the image
                  movieFrameReady = false;  // Knock down frame ready flag
                  myMovieCurrentTime = myMovie.time();  // Get playhead position in seconds
                  myMovieCurrentFrame = int(myMovieCurrentTime * myMovieFramesPerSecond) + 1;  // Calculate frame
                  print("myMovieCurrentTime)=" + myMovieCurrentTime);
                  print(" myMovieCurrentFrame=" + myMovieCurrentFrame);    
                  println(" myMovie.duration()=" + myMovie.duration());
                }
              } else
              {
                println("Movie Ended");
                exit();
              }
            }
    
            void movieEvent(Movie m) { // Called every time a new frame is available to read
              if (!movieEnded)  // If we are not at the end of the movie
              {
                m.read();     // Read the next frame
                movieFrameReady = true;  // Prevents draw() displaying the same frame twice
              }
            }
    
  • edited February 2018

    Oh...I forgot to add, @kf -- I've tried .asf, .mp4, and .dav -- in all cases, myMovie.duration() returns 0.0.

    Andy

  • edited February 2018

    Is that the library code that really gets used when you do an import processing.video.*;?
    ... but could not find any a "Movie.jar" or...

    • Movie is the name of the class.
    • processing.video is the name of the package it belongs to.
    • The whole library itself is compressed & packaged inside file "video.jar".
    • That library depends on & it's actually merely a wrapper for "gstreamer-java.jar".
  • edited February 2018

    Aaaaah......(faceplant). Sorry...I'm coming at this from the world of C/C++.

    Thanks Andy

Sign In or Register to comment.