mirror of
https://github.com/danbulant/cushy_video
synced 2026-06-21 16:01:47 +00:00
update cushy + improved layout
This commit is contained in:
parent
ffaef580df
commit
d2123ba96e
4 changed files with 88 additions and 61 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
|
@ -823,7 +823,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
|
|||
[[package]]
|
||||
name = "cushy"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/khonsulabs/cushy.git?branch=main#57f0c06b12f51cd7ef133794119bf1ba163e88d8"
|
||||
source = "git+https://github.com/khonsulabs/cushy.git?branch=main#5e2819a98386a4d1f7485de23acd6603e43b6368"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"alot",
|
||||
|
|
@ -852,7 +852,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cushy-macros"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/khonsulabs/cushy.git?branch=main#57f0c06b12f51cd7ef133794119bf1ba163e88d8"
|
||||
source = "git+https://github.com/khonsulabs/cushy.git?branch=main#5e2819a98386a4d1f7485de23acd6603e43b6368"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"manyhow",
|
||||
|
|
@ -1576,9 +1576,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.1"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
|
|
@ -1798,7 +1798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.1",
|
||||
"hashbrown 0.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1926,7 +1926,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
|||
[[package]]
|
||||
name = "kludgine"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/khonsulabs/kludgine#1964cea13c1da08fb06d93c5101f3cd1f748c930"
|
||||
source = "git+https://github.com/khonsulabs/kludgine#af4e6450c3bff3b2b6a6a3d7e9c0c2471b622578"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"alot",
|
||||
|
|
@ -4129,9 +4129,9 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
|
|||
|
||||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "23.0.0"
|
||||
version = "23.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76ab52f2d3d18b70d5ab8dd270a1cff3ebe6dbe4a7d13c1cc2557138a9777fdc"
|
||||
checksum = "80f70000db37c469ea9d67defdc13024ddf9a5f1b89cb2941b812ad7cde1735a"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"cfg_aliases 0.1.1",
|
||||
|
|
@ -4154,9 +4154,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "23.0.0"
|
||||
version = "23.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e0c68e7b6322a03ee5b83fcd92caeac5c2a932f6457818179f4652ad2a9c065"
|
||||
checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-vec",
|
||||
|
|
@ -4179,9 +4179,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-hal"
|
||||
version = "23.0.0"
|
||||
version = "23.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de6e7266b869de56c7e3ed72a954899f71d14fec6cc81c102b7530b92947601b"
|
||||
checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"arrayvec",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ use std::{
|
|||
};
|
||||
|
||||
use cushy::{
|
||||
figures::{units::UPx, Rect},
|
||||
figures::{
|
||||
units::{Px, UPx},
|
||||
IntoUnsigned, Rect,
|
||||
},
|
||||
kludgine::{self, wgpu},
|
||||
RenderOperation,
|
||||
};
|
||||
|
|
@ -304,7 +307,7 @@ impl VideoPipeline {
|
|||
}
|
||||
}
|
||||
|
||||
fn prepare(&mut self, queue: &wgpu::Queue, video_id: u64, bounds: Rect<UPx>) {
|
||||
fn prepare(&mut self, queue: &wgpu::Queue, video_id: u64, bounds: Rect<Px>) {
|
||||
if let Some(video) = self.videos.get(&video_id) {
|
||||
let uniforms = Uniforms {
|
||||
rect: [
|
||||
|
|
@ -327,38 +330,23 @@ impl VideoPipeline {
|
|||
|
||||
fn draw(&self, pass: &mut wgpu::RenderPass, viewport: Rect<UPx>, video_id: u64) {
|
||||
if let Some(video) = self.videos.get(&video_id) {
|
||||
// let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
// label: Some("iced_video_player render pass"),
|
||||
// color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
// view: target,
|
||||
// resolve_target: None,
|
||||
// ops: wgpu::Operations {
|
||||
// load: wgpu::LoadOp::Load,
|
||||
// store: wgpu::StoreOp::Store,
|
||||
// },
|
||||
// })],
|
||||
// depth_stencil_attachment: None,
|
||||
// timestamp_writes: None,
|
||||
// occlusion_query_set: None,
|
||||
// });
|
||||
|
||||
pass.set_pipeline(&self.pipeline);
|
||||
pass.set_bind_group(0, &video.bg0, &[]);
|
||||
// pass.set_viewport(
|
||||
// viewport.origin.x as _,
|
||||
// viewport.origin.y as _,
|
||||
// viewport.size.width as _,
|
||||
// viewport.size.height as _,
|
||||
// 0.0,
|
||||
// 1.0,
|
||||
// );
|
||||
pass.set_viewport(
|
||||
viewport.origin.x.get() as _,
|
||||
viewport.origin.y.get() as _,
|
||||
viewport.size.width.get() as f32,
|
||||
viewport.size.height.get() as f32,
|
||||
0.0,
|
||||
1.0,
|
||||
);
|
||||
pass.draw(0..4, 0..1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct VideoRO {
|
||||
pipeline: Option<VideoPipeline>,
|
||||
pipeline: VideoPipeline,
|
||||
}
|
||||
|
||||
impl RenderOperation for VideoRO {
|
||||
|
|
@ -366,21 +354,19 @@ impl RenderOperation for VideoRO {
|
|||
type Prepared = VideoPrimitive;
|
||||
|
||||
fn new(graphics: &mut cushy::kludgine::Graphics<'_>) -> Self {
|
||||
VideoRO { pipeline: None }
|
||||
VideoRO {
|
||||
pipeline: VideoPipeline::new(graphics),
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare(
|
||||
&mut self,
|
||||
context: Self::DrawInfo,
|
||||
origin: cushy::figures::Point<cushy::figures::units::Px>,
|
||||
rect: Rect<Px>,
|
||||
graphics: &mut cushy::kludgine::Graphics<'_>,
|
||||
) -> Self::Prepared {
|
||||
let pipeline = self
|
||||
.pipeline
|
||||
.get_or_insert_with(|| VideoPipeline::new(graphics));
|
||||
|
||||
if context.upload_frame {
|
||||
pipeline.upload(
|
||||
self.pipeline.upload(
|
||||
graphics.device(),
|
||||
graphics.queue(),
|
||||
context.video_id,
|
||||
|
|
@ -389,26 +375,22 @@ impl RenderOperation for VideoRO {
|
|||
context.frame.lock().expect("lock frame mutex").as_slice(),
|
||||
);
|
||||
}
|
||||
|
||||
pipeline.prepare(graphics.queue(), context.video_id, graphics.clip_rect());
|
||||
self.pipeline
|
||||
.prepare(graphics.queue(), context.video_id, rect);
|
||||
context
|
||||
}
|
||||
|
||||
fn render(
|
||||
&self,
|
||||
prepared: &Self::Prepared,
|
||||
origin: cushy::figures::Point<cushy::figures::units::Px>,
|
||||
opacity: f32,
|
||||
_rect: Rect<Px>,
|
||||
_opacity: f32,
|
||||
graphics: &mut cushy::kludgine::RenderingGraphics<'_, '_>,
|
||||
) {
|
||||
let pipeline = self.pipeline.as_ref().expect("prepare sets pipeline");
|
||||
let rect = graphics.clip_rect();
|
||||
pipeline.draw(
|
||||
// target,
|
||||
graphics.pass_mut(),
|
||||
rect,
|
||||
prepared.video_id,
|
||||
);
|
||||
dbg!(rect);
|
||||
self.pipeline
|
||||
.draw(graphics.pass_mut(), rect.into_unsigned(), prepared.video_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,15 +5,19 @@ use std::{
|
|||
|
||||
use cushy::{
|
||||
context::{GraphicsContext, LayoutContext},
|
||||
figures::{units::UPx, Size},
|
||||
value::{Destination, Dynamic, DynamicReader, Generation, Source},
|
||||
figures::{
|
||||
units::{Px, UPx},
|
||||
FloatConversion, IntoSigned, IntoUnsigned, Point, Rect, Size,
|
||||
},
|
||||
value::{Destination, Dynamic, DynamicReader, Generation, Source, Value},
|
||||
widget::Widget,
|
||||
widgets::image::{Aspect, ImageScaling},
|
||||
ConstraintLimit,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
pipeline::{VideoPrimitive, VideoRO},
|
||||
video::Video,
|
||||
video::{Internal, Video},
|
||||
Error,
|
||||
};
|
||||
|
||||
|
|
@ -26,6 +30,7 @@ pub struct VideoPlayer {
|
|||
subtitles: Dynamic<Option<String>>,
|
||||
frame: Dynamic<()>,
|
||||
last_frame: Generation,
|
||||
scaling: Value<ImageScaling>,
|
||||
}
|
||||
|
||||
impl VideoPlayer {
|
||||
|
|
@ -37,6 +42,7 @@ impl VideoPlayer {
|
|||
video,
|
||||
last_frame: Generation::default(),
|
||||
frame,
|
||||
scaling: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +67,41 @@ impl VideoPlayer {
|
|||
pub fn video(&self) -> &Video {
|
||||
&self.video
|
||||
}
|
||||
|
||||
fn calculate_video_rect(
|
||||
&self,
|
||||
video: &Internal,
|
||||
within_size: Size<UPx>,
|
||||
context: &mut GraphicsContext<'_, '_, '_, '_>,
|
||||
) -> Rect<Px> {
|
||||
let within_size = within_size.into_signed();
|
||||
let size = Size {
|
||||
width: Px::new(video.width),
|
||||
height: Px::new(video.height),
|
||||
};
|
||||
match self.scaling.get_tracking_invalidate(context) {
|
||||
ImageScaling::Aspect { mode, orientation } => {
|
||||
let scale_width = within_size.width.into_float() / size.width.into_float();
|
||||
let scale_height = within_size.height.into_float() / size.height.into_float();
|
||||
|
||||
let effective_scale = match mode {
|
||||
Aspect::Fill => scale_width.max(scale_height),
|
||||
Aspect::Fit => scale_width.min(scale_height),
|
||||
};
|
||||
let scaled = size * effective_scale;
|
||||
|
||||
let x = (within_size.width - scaled.width) * *orientation.width;
|
||||
let y = (within_size.height - scaled.height) * *orientation.height;
|
||||
|
||||
Rect::new(Point::new(x, y), scaled)
|
||||
}
|
||||
ImageScaling::Stretch => within_size.into(),
|
||||
ImageScaling::Scale(factor) => {
|
||||
let size = size.map(|px| px * factor);
|
||||
size.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for VideoPlayer {
|
||||
|
|
@ -93,8 +134,11 @@ impl Widget for VideoPlayer {
|
|||
fn layout(
|
||||
&mut self,
|
||||
available_space: Size<ConstraintLimit>,
|
||||
_context: &mut LayoutContext<'_, '_, '_, '_>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
available_space.map(ConstraintLimit::max)
|
||||
let inner = self.video.read();
|
||||
let rect =
|
||||
self.calculate_video_rect(&inner, available_space.map(ConstraintLimit::max), context);
|
||||
rect.size.into_unsigned()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// This file is taken nearly one to one from https://github.com/jazzfool/iced_video_player
|
||||
use crate::Error;
|
||||
use cushy::value::{Destination, Dynamic};
|
||||
use glib::property::PropertyGet;
|
||||
use gstreamer as gst;
|
||||
use gstreamer_app as gst_app;
|
||||
use gstreamer_app::prelude::*;
|
||||
|
|
|
|||
Loading…
Reference in a new issue