diff --git a/client/src/output/video.rs b/client/src/output/video.rs index 1cf3806..6a6a6d3 100644 --- a/client/src/output/video.rs +++ b/client/src/output/video.rs @@ -7,6 +7,14 @@ use winit::{ window::{Window, WindowAttributes}, }; +const DESC: &str = concat!( + "appsrc name=src is-live=true format=time do-timestamp=true block=false ! ", + "queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 leaky=downstream ! ", + "capsfilter caps=video/x-h264,stream-format=byte-stream,alignment=au ! ", + "h264parse disable-passthrough=true ! decodebin ! ", + "queue ! videoconvert ! autovideosink sync=false" +); + pub struct MonitorWindow { id: u32, _window: Window, @@ -30,25 +38,7 @@ impl MonitorWindow { .field("alignment", &"au") .build(); - // Optional HW decode with VA‑API if LESAVKA_HW_DEC is set. - let desc = if std::env::var_os("LESAVKA_HW_DEC").is_some() { - concat!( - "appsrc name=src is-live=true format=time do-timestamp=true block=false ! ", - "capsfilter caps=video/x-h264,stream-format=byte-stream,alignment=au ! ", - "queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 leaky=downstream ! ", - "h264parse ! vaapih264dec low-latency=true ! videoconvert ! ", - "direct-render-synchronised-videosink ! autovideosink sync=false", - ) - } else { - concat!( - "appsrc name=src is-live=true format=time do-timestamp=true block=false ! ", - "capsfilter caps=video/x-h264,stream-format=byte-stream,alignment=au ! ", - "queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 leaky=downstream ! ", - "h264parse ! decodebin ! videoconvert ! autovideosink sync=false", - ) - }; - - let pipeline = gst::parse::launch(desc)? + let pipeline = gst::parse::launch(DESC)? .downcast::() .expect("pipeline down‑cast"); @@ -59,7 +49,7 @@ impl MonitorWindow { .expect("appsink down‑cast"); src.set_caps(Some(&caps)); - src.set_format(gst::Format::Undefined); // running‑time PTS + src.set_format(gst::Format::Time); // running‑time PTS src.set_property("blocksize", &0u32); // whole AU per buffer src.set_latency(gst::ClockTime::NONE, gst::ClockTime::NONE); @@ -71,6 +61,9 @@ impl MonitorWindow { /// Push one encoded access‑unit into the local pipeline. pub fn push_packet(&self, pkt: VideoPacket) { let buf = gst::Buffer::from_slice(pkt.data); // no PTS manipulation + if let Some(mut b) = buf.get_mut() { + b.set_pts(Some(gst::ClockTime::from_useconds(pkt.pts))); + } let _ = self.src.push_buffer(buf); } diff --git a/server/Cargo.toml b/server/Cargo.toml index 95cd08e..c5d544c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -11,6 +11,7 @@ edition = "2024" tokio = { version = "1.45", features = ["full", "fs"] } tokio-stream = "0.1" tonic = { version = "0.13", features = ["transport"] } +tonic-reflection = "0.13" anyhow = "1.0" lesavka_common = { path = "../common" } tracing = { version = "0.1", features = ["std"] } diff --git a/server/src/main.rs b/server/src/main.rs index add0e86..8fb95ac 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -14,6 +14,7 @@ use tokio::{ use tokio_stream::wrappers::ReceiverStream; use tonic::{Request, Response, Status}; use tonic::transport::Server; +use tonic_reflection::server::{Builder as ReflBuilder}; use tracing::{info, warn, error, trace}; use tracing_subscriber::{filter::EnvFilter, fmt, prelude::*}; use tracing_appender::non_blocking::WorkerGuard; @@ -198,6 +199,7 @@ async fn main() -> anyhow::Result<()> { .tcp_nodelay(true) .max_frame_size(Some(256*1024)) .add_service(RelayServer::new(handler)) + .add_service(ReflBuilder::configure().build_v1().unwrap()) .serve(([0,0,0,0], 50051).into()) .await?; Ok(())