From 4ef10b082b6b01c40b2ab5d41d88b3a4b90aaa52 Mon Sep 17 00:00:00 2001 From: valadaptive Date: Sun, 20 Oct 2024 21:50:46 -0400 Subject: [PATCH] Fix variable-framerate videos in standalone app --- crates/gui/src/app/main.rs | 4 +++- crates/gui/src/gst_utils/pipeline_utils.rs | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/gui/src/app/main.rs b/crates/gui/src/app/main.rs index 9331c7d..487a931 100644 --- a/crates/gui/src/app/main.rs +++ b/crates/gui/src/app/main.rs @@ -1381,7 +1381,9 @@ impl NtscApp { .structure(0)? .get::("framerate") .ok()?; - Some(framerate) + + // If the framerate is 0, treat it like it's absent + (framerate.numer() != 0).then_some(framerate) })(); egui::TopBottomPanel::top("video_info") diff --git a/crates/gui/src/gst_utils/pipeline_utils.rs b/crates/gui/src/gst_utils/pipeline_utils.rs index 101050c..de37c8a 100644 --- a/crates/gui/src/gst_utils/pipeline_utils.rs +++ b/crates/gui/src/gst_utils/pipeline_utils.rs @@ -1,5 +1,5 @@ use super::{gstreamer_error::GstreamerError, scale_from_caps}; -use gstreamer::{element_error, element_warning, glib, prelude::*}; +use gstreamer::{element_error, element_warning, glib, prelude::*, query::Duration}; use gstreamer_video::VideoInterlaceMode; use log::debug; use std::{ @@ -220,11 +220,22 @@ pub fn create_pipeline< )) }); - let is_still_image = match framerate { + let mut q = Duration::new(gstreamer::Format::Time); + let _ = src_pad.query(q.query_mut()); + let src_duration = q.result(); + let has_duration = src_duration.is_some(); + + let has_zero_framerate = match framerate { Some(framerate) => framerate.numer() == 0, None => false, }; + // TODO: Videos with a variable framerate have a framerate of 0, so we also check if the input + // has a defined duration (see https://github.com/valadaptive/ntsc-rs/issues/8). Since we do so, + // is it still necessary to have *both* checks? Are there some videos that are not still images + // but still have no duration? + let is_still_image = has_zero_framerate && !has_duration; + let video_sink = video_sink( &pipeline, VideoElemMetadata {