ofxGstreamer range video loop

#1

hi everyone;

i’ve been trying to select a range of a video, using ofxGstreamer, changing its first and last frame reference to let it loop into that portion of time. now, I only achieved with success to scrub the video throught its pixels, but not defining its beggining and end moments.

does anyone ever did it?

as I am working with long videos, I need to select a portion of the total time and loop into that range. for example, in a video of 30 minutes, one time I need it to play from 01:10 to 03:20, other time from 15:22 to 22:25. if the solution isnt in time, but in pixels reference, will also be nice.

obs: ofxHPVPlayer has that range control, but I would like to continue using gstreamer to its very good performance.

thank you!!

#2

you can use gstreamer directly to precisely set the start and end playback points. Using https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstEvent.html#gst-event-new-seek and the pointer to the internal gstreamer pipeline.

Haven’t tested it but should be something like:

auto gstvideo = std::dynamic_pointer_cast<ofGstVideoPlayer>(videoplayer.getPlayer());
auto gstpipeline = gstvideo.getGstVideoUtils().getPipeline();
double playrate = 1.;
auto seekEvent = gst_event_new_seek(
    playrate,
    GST_FORMAT_TIME, 
    GST_SEEK_FLAG_NONE, 
    GST_SEEK_TYPE_SET,
    startTimeInNanoSeconds,
    GST_SEEK_TYPE_SET,
    endTimeInNanoSeconds);
gst_element_send_event (gstpipeline, seekEvent);

I’m using GST_SEEK_FLAG_NONE but you might need to sue different flags depending on the case and i’m not 100% sure if you send the event to the pipeline or the sink, which you can get with getSink instead of getPipeline

Also if you are setting the player manually using setPlayer before load and play then you can hold a shared_ptr to the ofGstVideoUtils to avoid doing the dynamic cast

#3

thank you, @arturo!

i`ve been trying to adapt your code to mine, but still, i am not able to pass the values of videoStart and videoEnd to the video. my code is as below:

#include "ofApp.h"
#include "ofGstVideoPlayer.h"
void ofApp::setup(){
    player.setPlayer(ofPtr<ofGstVideoPlayer>(new ofGstVideoPlayer));
    
    auto gstvideo = std::dynamic_pointer_cast<ofGstVideoPlayer>(player.getPlayer());
    auto gstpipeline = gstvideo.get()->getGstVideoUtils()->getPipeline();
    double playrate = 1.;
    auto seekEvent = gst_event_new_seek(
            playrate,
            GST_FORMAT_TIME,
            GST_SEEK_FLAG_NONE,
            GST_SEEK_TYPE_SET,
            startTime,
            GST_SEEK_TYPE_SET,
            endTime);
    gst_element_send_event (gstpipeline, seekEvent);

    dirVideo.listDir("videos");
    dirVideo.allowExt("mov");
    dirVideo.sort();
    currentVideo = 0;
    player.load(dirVideo.getPath(currentVideo));
void ofApp::guiGerals() {
    guiGeral.setup();
    //[...]
    guiGeral.add(start1.set("start time", 0, 0, 1000));
    guiGeral.add(end1.set("end time", 1, 0, 1000));
}
void ofApp::update(){
    startTime = start1;
    endTime = end1;
    //[...]
}

hope you can give me some light!
thank you very much!!

#4

i think you need to send the event after the video is playng. also the times are in nano seconds so 1000000000 is one second, that’s 9 zeros.

#5

hi, @arturo!

finally getting it to work, as code below.

but, unfortunately, always after around 30 seconds, the fps downs from 30 to 26/28. that happens equally if I play 1 video or 4 videos simultaneously / or if I use .getSink() / or if ofSetVerticalSync(true or false) / or if shaders on or off / or if after player.play().
also, it only works one time and then loops to frame 0 again.

any ideas how to improve performance? because, ofxGstreamer is getting perfect performance, even with lots of live shaders, and that range time is killing it all!!

below is when I call preset1 with new start time and end time.

void ofApp::preset1Pressed(){
    guiVideo1.loadFromFile("presets/video11.xml");
    guiGeral.loadFromFile("presets/geral1.xml");

    loads1.load("presets/local1.xml");
    auto values = loads1.getChild("data");
    if (values) {
        currentVideo = values.getChild("currentVideo").getIntValue();
        player.load(dirVideo.getPath(currentVideo));
    }

    auto gstvideo = std::dynamic_pointer_cast<ofGstVideoPlayer>(player.getPlayer());
    auto gstpipeline = gstvideo.get()->getGstVideoUtils()->getPipeline();
    auto seekEvent = gst_event_new_seek (speed,
            GST_FORMAT_TIME,
            GST_SEEK_FLAG_FLUSH,
            GST_SEEK_TYPE_SET, start1 * GST_SECOND,
            GST_SEEK_TYPE_SET, end1 * GST_SECOND);
    gst_element_send_event (gstpipeline, seekEvent);

    player.play();
 }

thank you again! :sweat_smile:

#6

actually, tested again with better compression videos and it is working very fine!
thank you a lot for the help

now just need to decode how to set the loop to the videoStart again, and not to frame 0.

best! :v: