# Frame stepping with GStreamer StepEvent

**URL:** https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993
**Category:** Libraries
**Created:** [May 9, 2021, 9:27pm UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993 "2021-05-09T21:27:31Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![ermaciu](https://avatars.discourse-cdn.com/v4/letter/e/bbce88/32.png) [@ermaciu](https://discourse.processing.org/u/ermaciu)
#### Post date: [May 9, 2021, 9:27pm UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/1 "2021-05-09T21:27:32Z")

</div>

Hey everyone.  
I’m trying to use Processing for analyzing movement manually in videos. Unfortunately the video library doesn’t appear to have frame-stepping functionality built in, and the suggested [example](https://github.com/processing/processing-video/blob/master/examples/Movie/Frames/Frames.pde) of calculating the frame time and seeking (or jumping) to it often skips frames, which doesn’t work for what I need.

I took some time to learn a little about the GStreamer backend and it seemed that I should be able to put the following in somewhere with a Listener and get it to framestep.

`myMovie.playbin.sendEvent(new StepEvent(Format.BUFFERS, 1, 1, true, false));`

However I find that in practice it comes up with a lot of unexpected (by me) behavior. In the following example I illustrate a couple of things.

```auto
import processing.core.*;
import java.util.EnumSet;
import org.freedesktop.gstreamer.event.SeekFlags;
import org.freedesktop.gstreamer.event.SeekType;
import processing.video.*;
import org.freedesktop.gstreamer.*;
import org.freedesktop.gstreamer.event.*;

Movie myMovie; 
float zoom;

void setup() {
  size(800,600);
  myMovie = new Movie(this, "Slow motion video of vertical jump with synchronized vertical force data.mp4");
  myMovie.play();
  myMovie.pause();
  myMovie.read();
  zoom = width*1.0 / myMovie.width;
  noLoop();
}

>void draw() {
    scale(zoom);
    myMovie.play();
    myMovie.pause();
    myMovie.read();
    background (128);  
    image(myMovie, 0, 0); 
}

void keyPressed() {
    if (key == CODED) {
      if (keyCode == LEFT) {
         myMovie.playbin.sendEvent(new StepEvent(Format.BUFFERS, 1, 1, true, false));
         redraw();
      } else if (keyCode == RIGHT) {
         myMovie.playbin.seek(1, Format.TIME, EnumSet.of(SeekFlags.FLUSH, SeekFlags.ACCURATE), SeekType.SET, myMovie.playbin.queryPosition(Format.TIME), SeekType.END, 0);
         myMovie.playbin.sendEvent(new StepEvent(Format.BUFFERS, 1, 1, true, false));
         redraw();
      }
    }
}

```

- If I don´t play-pause before reading after sending the event, no change takes effect. Probably [not surprising](https://forum.processing.org/two/discussion/20383/video-1-0-1-read-a-frame-from-a-paused-video), but I´m wondering if there is a way around it.
- In my example when I click the LEFT arrow, I send the step event without seeking beforehand. In this case it seems to step over about 5-6 frames. Probably something going on her I´m not seeing.
- For the RIGHT arrow I added a seek event to the present time with rate 1. In this case I only step one frame, although sometimes it doesn’t load and I click twice and on the second press I jump forward two frames. What surprises me is that if I click RIGHT, it steps 1 frame, but then if I click LEFT afterwards it steps 6 frames.

My guess is there is a lot about the way the video library uses GStreamer that I am ignoring. I’d like to know if it is going to be possible to find a way to hack exact frame stepping in (and perhaps a hint at where to start), or if I am in way over my head. Any suggestions or pushes in the right direction will be much appreciated.

---

<div class="post-metadata">

### Author: ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)
#### Post date: [May 10, 2021, 7:32pm UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/2 "2021-05-10T19:32:46Z")

</div>

Hi! Welcome to the forum!

First of all please format the code:

[https://www.khm.de/~n.hieda/discourse-code.mp4](https://www.khm.de/~n.hieda/discourse-code.mp4)

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [May 11, 2021, 9:17am UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/3 "2021-05-11T09:17:35Z")

</div>

> [@ermaciu](#):
>
> If I don´t play-pause before reading after sending the event, no change takes effect. Probably [not surprising](https://forum.processing.org/two/discussion/20383/video-1-0-1-read-a-frame-from-a-paused-video), but I´m wondering if there is a way around it.

If you play-pause it’s never going to work as you want! Unfortunately no-one saw fit to finish implementing the preroll listener correctly to make this work 😖 - [processing-video/src/processing/video/Movie.java at main · processing/processing-video · GitHub](https://github.com/processing/processing-video/blob/master/src/processing/video/Movie.java#L853)

---

<div class="post-metadata">

### Author: ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)
#### Post date: [May 11, 2021, 10:20am UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/4 "2021-05-11T10:20:58Z")

</div>

What would need to be added to this for it to work? Provided its not too complex we should be able to add the desired code and recompile the sound library.

Is it a case of adding some logic to handle framecount on pause and play?

---

<div class="post-metadata">

### Author: ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)
#### Post date: [May 11, 2021, 10:37am UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/5 "2021-05-11T10:37:47Z")

</div>

It might be you could change the variables in the seek method.

```auto
private void seek(double rate, long start, long stop) {
    Gst.invokeLater(new Runnable() {
      public void run() {
        boolean res;
        if (stop == -1) {
          res = playbin.seek(rate, Format.TIME, EnumSet.of(SeekFlags.FLUSH, SeekFlags.ACCURATE), SeekType.SET, start, SeekType.NONE, stop);
        } else {
          res = playbin.seek(rate, Format.TIME, EnumSet.of(SeekFlags.FLUSH, SeekFlags.ACCURATE), SeekType.SET, start, SeekType.SET, stop);  
        }
        if (!res) {
          PGraphics.showWarning("Seek operation failed.");
        }
      }
    });    
  }

```

Format.time is likely the culprit here…

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [May 11, 2021, 11:13am UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/6 "2021-05-11T11:13:36Z")

</div>

> [@paulgoux](#):
>
> Provided its not too complex we should be able to add the desired code and recompile the sound library.

Assuming you mean “video” library?! 😃 It needs an implementation of the new preroll listener that actually does something, ie. the same or similar behaviour to the new sample listener. eg. if you look at the implementation in PraxisLIVE, where this actually works, the new preroll listener is identical - [praxiscore/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/PImageSink.java at master · praxis-live/praxiscore · GitHub](https://github.com/praxis-live/praxiscore/blob/master/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/PImageSink.java#L183)

@ermaciu do you need to be using Processing and/or Processing Video for your task? Because the underlying GStreamer Java library sounds like a better bet.

---

<div class="post-metadata">

### Author: ![ermaciu](https://avatars.discourse-cdn.com/v4/letter/e/bbce88/32.png) [@ermaciu](https://discourse.processing.org/u/ermaciu)
#### Post date: [May 11, 2021, 10:35pm UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/7 "2021-05-11T22:35:36Z")

</div>

@micuat yes, good suggestion (and very easy I might add).

@neilcsmith makes sense that I can’t control what will happen if I do play-pause. I probably don’t need Processing to do what I want (mainly panning, zooming and registering clicks), but it did seem like the easiest option, until frame-stepping fell through. I might well turn to using the GStreamer library and a GUI toolkit. The [SwingPlayer example](https://github.com/gstreamer-java/gst1-java-examples/blob/master/SwingPlayer/src/main/java/org/freedesktop/gstreamer/examples/SwingPlayer.java) probably gives me enough to send me in the right direction. Thanks for the guidance!

---

<div class="post-metadata">

### Author: ![ermaciu](https://avatars.discourse-cdn.com/v4/letter/e/bbce88/32.png) [@ermaciu](https://discourse.processing.org/u/ermaciu)
#### Post date: [May 11, 2021, 10:36pm UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/8 "2021-05-11T22:36:20Z")

</div>

@paulgoux I don’t really understand what you are suggesting I try. Something about trying different seek-formats? Sorry, I’m a bit green here. I’m happy to go in and play around with the library if I can figure out what you mean 🙂 Thanks!

---

<div class="post-metadata">

### Author: ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)
#### Post date: [May 11, 2021, 10:39pm UTC](https://discourse.processing.org/t/frame-stepping-with-gstreamer-stepevent/29993/9 "2021-05-11T22:39:48Z")

</div>

Dont worry im pretty green myself. Its just ive finally learned to compile libraries with processing, and so was wondering how much work was actually needed for this. Is it a case of adding a few lines and recompiling the library or is it a lot more involved.
