arturoc / gstreamer1.0-rs

Idiomatic bindings for Gstreamer on Rust.
MIT License
36 stars 14 forks source link

How to batch-process a video faster than real-time? #20

Closed ReactorScram closed 8 years ago

ReactorScram commented 8 years ago

I'm reading through AVI files from my roadcam so I can OCR the GPS coordinates printed over the video.

But with the GStreamer binding, it will only play at 30 FPS, so a 10-minute video takes 10 minutes to process even though the processing is very simple.

Since I'm not displaying the video, can I disable GStreamer's timing and just pull frames sequentially as fast as possible?

arturoc commented 8 years ago

it's not fully wrapped in safe methods yet but you can use the ffi:

you need to set the sink in your pipeline to not sync, if you are using an appsink for example

appsink.set("sync", false);

then every time you want a new frame:

unsafe{
    use gst::ffi::*;
    let gst_sample = gst_app_sink_pull_sample(appsink.gst_element());
    let sample = gst::Sample::new(gst_sample);
    ...
}

i'l try to add this functionality to appsink as safe methods when i have a moment

ReactorScram commented 8 years ago

I am trying that but it hangs inside gst_app_sink_pull_sample. According to the GST docs, this likely means the pipeline is not playing. But I did set it to playing.

It runs through one loop and then hangs on the second loop, so gst::Sample::new is not crashing but something is misbehaving.

I used appsink.get_appsink_mut () instead of gst_element () because the types matched up.

arturoc commented 8 years ago

The problem is that appsink is internally setting the callbacks so when you try to poll a frame all have been already received in the internal callback. I've just created a new struct, AppSinkPoll that doesn't setup the callbacks and the receiver and has pull_sample and pull_preroll methods to directly pull the samples from the main thread. there's also an example on how to use it.

Using the normal appsink and recv instead of poll should work the same as long as you set sync to false as it's done on the example

arturoc commented 8 years ago

thinking about it better i've just changed the example to use the plain appsink without sync and removed the new class.

it should do what you are looking after, just receive frames as fast as possible without syncing to the clock but with the same api as before

i might change the way appsink works in the future and don't set the callbacks internally by default but by now i've left it as it was

ReactorScram commented 8 years ago

It works, thanks! The video is now running at 100 FPS.

allComputableThings commented 1 year ago

@arturoc Thanks! Is this feture available in the command line? I'm using opencv with a gstreamer backend (it takes the command-line pipe paramters as input). I'd quite like to disable buffers, real-time syncing, dropping of expired frames, etc.... and just receive everything that comes in (in this case, over a TCP).