duration method return 0.0 in setup ()

Help
2010-04-08
2012-12-26
  • sebastien loss
    sebastien loss
    2010-04-08

    Hi,

    I try to get duration of movie create with new GSMovie in setup section but it returns me 0.0. In Draw section no problem but I want to assign duration value to a controlP5.Slider max value in aim to make a seeking video slider from setup section.
    Is it a bug or there is a good manner to get duration before draw loop ?

    ex :
    movie = new GSMovie(this, "movie.mov");
    println (movie.duration());

    Thanks for GSMovie

     
  • Andres Colubri
    Andres Colubri
    2010-04-09

    The problem is that the duration of the video stream doesn't get updated until the first frame is read. This is a behaviour of gstremaer and not of gsvideo. I'll check if the latest release of the gstreamer libs changes this.

    In the meantime, I suggest you add a boolean variable so you get the duration of the clip when the first read takes place, and set your slide bars accordingly. Look at this code:

    import codeanticode.gsvideo.*;

    GSMovie myMovie;
    boolean firstRead = true;

    void setup() {
      size(640, 480, P3D);
      background(0);
      myMovie = new GSMovie(this, "station.mov");
      myMovie.loop();
    }

    void movieEvent(GSMovie myMovie) {
      if (firstRead) println(myMovie.duration()); 
      firstRead = false; 
      myMovie.read();
    }

    void draw() {
      tint(255, 20);
      image(myMovie, mouseX-myMovie.width/2, mouseY-myMovie.height/2);
    }

    I hope this helps.

    ac

     
  • sebastien loss
    sebastien loss
    2010-04-09

    Thank for reply ac,

    Ok no pb. I'll try your method.

    During this time I succed in a dirty workaround placing some setup stuff in draw() loop because I figure out reading video in a setup() section doesnt work…strange…I'm a newbie after all ;)
    In fact, I try to make a little videoprojection app with videos (in a first step) this is my code (yet ugly, no cool class object by now) :

    //import promidi.*;

    import controlP5.*;
    import processing.opengl.*;
    import codeanticode.gsvideo.*;
    import codeanticode.glgraphics.*;
    import deadpixel.keystone.*;

    ControlP5 controlP5;
    //MyControlListener myListener;

    GSMovie movie1, movie2;
    GLTexture tex, tex2;

    // this object is key! you can use it to render fully accelerated
    // OpenGL scenes directly to a texture

    GLGraphicsOffScreen offscreen, offscreen2;

    Keystone ks, k2;
    CornerPinSurface surface, surface2;

    // fonts
    PFont fontReperage, fontTimer;

    boolean notReady;

    void setup() {

      size(1280, 690, GLConstants.GLGRAPHICS);
     
      // Movies 
      movie1 = new GSMovie(this, "ac_my_girls_m720p.mov");
      movie2 = new GSMovie(this, "ac_summertimeclothes_m720p.mov");

      movie1.play();
      movie1.loop();
      movie2.play();
      movie2.loop();
      movie2.volume(0);

      // workaround of the gstreamer bug
      // to get videos durations
      notReady = true;
      println(movie1.width);
      println(movie1.height);
      println(movie1.duration());
     

      tex = new GLTexture(this);
      tex2 = new GLTexture(this);
     
      // Fonts
      fontReperage = loadFont("Ziggurat-32.vlw");
      fontTimer = loadFont("Pro-20.vlw");

      // GUI
      controlP5 = new ControlP5(this);
      controlP5.addKnob("volume",0 ,255 ,200, 100, 80, 40) ;
      controlP5.addToggle("mute",false,170,100,20,20);
     
    //  myListener = new MyControlListener();
    //  controlP5.controller("seeking").addListener(myListener);

     
    }

    void draw() {

      // Waiting for reading videos properties
      while (notReady == true){
       
        println("please wait…");
        if (movie1.available() && movie2.available()){

          // set some GUI elements and surface dimensions
          if ((1 < movie1.width) && (1 < movie1.height) && (0.0 < movie1.duration())) {

            println("OK");
            controlP5.addSlider("seeking",0,movie1.duration(),0,100,20,300,9);
            controlP5.controller("seeking").setBehavior(new updatePosition());
            // Offscreen buffers
            offscreen = new GLGraphicsOffScreen(this, movie1.width, movie1.height);
            offscreen2 = new GLGraphicsOffScreen(this, movie2.width, movie2.height);
         
            // Surfaces 
            ks = new Keystone(this);
           
            surface = ks.createCornerPinSurface(movie1.width ,movie1.height, 8);
            surface2 = ks.createCornerPinSurface(movie2.width ,movie2.height, 8);
           
            // can exit
            notReady = false;
           
          }
         
          movie1.read();
          movie2.read();
        }
      }

      // convert
      PVector mouse = surface.getTransformedMouse();

      if (movie1.available() && movie2.available()){
          movie1.read();
          movie2.read();
          tex.putPixelsIntoTexture(movie1);
          tex2.putPixelsIntoTexture(movie2);
         
          offscreen.beginDraw();

          offscreen.beginShape();
          offscreen.texture(tex);
          offscreen.vertex(0, 0, -10, 0, 0);
          offscreen.vertex(movie1.width, 0, -10, 1280, 0);
          offscreen.vertex(movie1.width, movie1.height, -10, 1280, 690);
          offscreen.vertex(0, movie1.height, -10, 0, 690);
          offscreen.endShape();

          offscreen.fill(250);

          offscreen.textFont(fontReperage);
          offscreen.textSize(128);
          offscreen.text("1", width / 2, height / 2);    
          offscreen.endDraw();

          offscreen2.beginDraw();

          offscreen2.beginShape();
          offscreen2.texture(tex2);
          offscreen2.vertex(0, 0, -10, 0, 0);
          offscreen2.vertex(movie2.width, 0, -10, 1280, 0);
          offscreen2.vertex(movie2.width, movie2.height, -10, 1280, 690);
          offscreen2.vertex(0, movie2.height, -10, 0, 690);
          offscreen2.endShape();

          offscreen2.fill(250);
          offscreen2.textFont(fontReperage);
          offscreen2.textSize(128);
          offscreen2.text("2", width / 2, height / 2);    
         
          offscreen2.endDraw();
         
      }

          // render the sketch using the
          // keystoned surface
          background(0);
          surface.render(offscreen.getTexture());
         
          surface2.render(offscreen2.getTexture());
         
          time();

    }

    void time() {
      int s = second();
      int m = minute();
      int h = hour();
      // The nf() function spaces the numbers nicely
      String t = nf(h,2) + ":" + nf(m,2) + ":" + nf(s,2);
      textFont(fontTimer);
      text(t, 10, 55);
    }

    // Controls for the Keystone object
    void seeking(float thePosition) {
        //movie1.jump(thePosition);
    }

    void mute(boolean theFlag) {
      if(theFlag==true) {
        movie1.volume(0);
      } else {
        movie1.volume(1);
      }
    }

    void volume(float theVolume) {
      movie1.volume(map(theVolume, 0 ,255 ,0.0 ,1.0));
    }

    // Controls Behaviors
    class updatePosition extends ControlBehavior {

      public void update() {
        setValue(movie1.time());
      }
    }

    void keyPressed() {

      switch(key) {
      case 'c':
        // entrer / quitter le mode de calibration, les surfaces peuvent y être
        // manipulées.
        ks.toggleCalibration();
        break;

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

      case 's':
        // saves the layout
        ks.save();
        break;
       
      case 'j':
        // jump to 220s in movie1 for testing
        movie1.jump(220.0);     
        break;
      }
     
    }

    //class MyControlListener implements ControlListener {
    //  int col;
    //  public void controlEvent(ControlEvent theEvent) {
    //    movie1.jump(theEvent.controller().value());
    //  }
    //}

    Another question : It is possible to seek in video with GSPipeline ? Because I want this app synced with midi time. Jump() is ok but too slow with HD video (video samples in my sketch were found on apple hd gallery). I try to seek in video with the slider with listener but my code "bites itself" because update slider for each frame make an event…I think..maybe I dont understand.
    Voilà. Bye

     
  • Andres Colubri
    Andres Colubri
    2010-04-11

    Thanks for posting your code. I'm glad to know that glgraphics is also useful for your project

    In regards to seeking in GSPipeline, unfortunately the functionality is not available, although it does exists inside the gstreamer object wrapped by GSPipeline. I'll include this in the next release of gsvideo.