This commit is contained in:
jazzfool 2024-11-03 01:24:37 +11:00
parent 0250a2619b
commit 59b3b21381
3 changed files with 39 additions and 33 deletions

View file

@ -1,7 +1,7 @@
use iced_wgpu::primitive::Primitive; use iced_wgpu::primitive::Primitive;
use iced_wgpu::wgpu; use iced_wgpu::wgpu;
use std::{ use std::{
collections::BTreeMap, collections::{btree_map::Entry, BTreeMap},
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Mutex, Arc, Mutex,
@ -13,20 +13,19 @@ struct Uniforms {
rect: [f32; 4], rect: [f32; 4],
} }
struct VideoEntry {
texture_y: wgpu::Texture,
texture_uv: wgpu::Texture,
uniforms: wgpu::Buffer,
bg0: wgpu::BindGroup,
alive: Arc<AtomicBool>,
}
struct VideoPipeline { struct VideoPipeline {
pipeline: wgpu::RenderPipeline, pipeline: wgpu::RenderPipeline,
bg0_layout: wgpu::BindGroupLayout, bg0_layout: wgpu::BindGroupLayout,
sampler: wgpu::Sampler, sampler: wgpu::Sampler,
textures: BTreeMap< videos: BTreeMap<u64, VideoEntry>,
u64,
(
wgpu::Texture,
wgpu::Texture,
wgpu::Buffer,
wgpu::BindGroup,
Arc<AtomicBool>,
),
>,
} }
impl VideoPipeline { impl VideoPipeline {
@ -130,7 +129,7 @@ impl VideoPipeline {
pipeline, pipeline,
bg0_layout, bg0_layout,
sampler, sampler,
textures: BTreeMap::new(), videos: BTreeMap::new(),
} }
} }
@ -143,7 +142,7 @@ impl VideoPipeline {
(width, height): (u32, u32), (width, height): (u32, u32),
frame: &[u8], frame: &[u8],
) { ) {
if !self.textures.contains_key(&video_id) { if let Entry::Vacant(entry) = self.videos.entry(video_id) {
let texture_y = device.create_texture(&wgpu::TextureDescriptor { let texture_y = device.create_texture(&wgpu::TextureDescriptor {
label: Some("iced_video_player texture"), label: Some("iced_video_player texture"),
size: wgpu::Extent3d { size: wgpu::Extent3d {
@ -230,13 +229,20 @@ impl VideoPipeline {
], ],
}); });
self.textures.insert( entry.insert(VideoEntry {
video_id, texture_y,
(texture_y, texture_uv, buffer, bind_group, Arc::clone(alive)), texture_uv,
); uniforms: buffer,
bg0: bind_group,
alive: Arc::clone(alive),
});
} }
let (texture_y, texture_uv, _, _, _) = self.textures.get(&video_id).unwrap(); let VideoEntry {
texture_y,
texture_uv,
..
} = self.videos.get(&video_id).unwrap();
queue.write_texture( queue.write_texture(
wgpu::ImageCopyTexture { wgpu::ImageCopyTexture {
@ -281,21 +287,21 @@ impl VideoPipeline {
fn cleanup(&mut self) { fn cleanup(&mut self) {
let ids: Vec<_> = self let ids: Vec<_> = self
.textures .videos
.iter() .iter()
.filter_map(|(id, (_, _, _, _, alive))| (!alive.load(Ordering::SeqCst)).then_some(*id)) .filter_map(|(id, entry)| (!entry.alive.load(Ordering::SeqCst)).then_some(*id))
.collect(); .collect();
for id in ids { for id in ids {
if let Some((texture_y, texture_uv, buffer, _, _)) = self.textures.remove(&id) { if let Some(video) = self.videos.remove(&id) {
texture_y.destroy(); video.texture_y.destroy();
texture_uv.destroy(); video.texture_uv.destroy();
buffer.destroy(); video.uniforms.destroy();
} }
} }
} }
fn prepare(&mut self, queue: &wgpu::Queue, video_id: u64, bounds: &iced::Rectangle) { fn prepare(&mut self, queue: &wgpu::Queue, video_id: u64, bounds: &iced::Rectangle) {
if let Some((_, _, buffer, _, _)) = self.textures.get(&video_id) { if let Some(video) = self.videos.get(&video_id) {
let uniforms = Uniforms { let uniforms = Uniforms {
rect: [ rect: [
bounds.x, bounds.x,
@ -304,7 +310,7 @@ impl VideoPipeline {
bounds.y + bounds.height, bounds.y + bounds.height,
], ],
}; };
queue.write_buffer(buffer, 0, unsafe { queue.write_buffer(&video.uniforms, 0, unsafe {
std::slice::from_raw_parts( std::slice::from_raw_parts(
&uniforms as *const _ as *const u8, &uniforms as *const _ as *const u8,
std::mem::size_of::<Uniforms>(), std::mem::size_of::<Uniforms>(),
@ -322,7 +328,7 @@ impl VideoPipeline {
viewport: &iced::Rectangle<u32>, viewport: &iced::Rectangle<u32>,
video_id: u64, video_id: u64,
) { ) {
if let Some((_, _, _, bind_group, _)) = self.textures.get(&video_id) { if let Some(video) = self.videos.get(&video_id) {
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_video_player render pass"), label: Some("iced_video_player render pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment { color_attachments: &[Some(wgpu::RenderPassColorAttachment {
@ -339,7 +345,7 @@ impl VideoPipeline {
}); });
pass.set_pipeline(&self.pipeline); pass.set_pipeline(&self.pipeline);
pass.set_bind_group(0, bind_group, &[]); pass.set_bind_group(0, &video.bg0, &[]);
pass.set_viewport( pass.set_viewport(
viewport.x as _, viewport.x as _,
viewport.y as _, viewport.y as _,

View file

@ -206,7 +206,7 @@ impl Video {
.map_err(|_| Error::Cast)?; .map_err(|_| Error::Cast)?;
let video_sink: gst::Element = pipeline.property("video-sink"); let video_sink: gst::Element = pipeline.property("video-sink");
let pad = video_sink.pads().get(0).cloned().unwrap(); let pad = video_sink.pads().first().cloned().unwrap();
let pad = pad.dynamic_cast::<gst::GhostPad>().unwrap(); let pad = pad.dynamic_cast::<gst::GhostPad>().unwrap();
let bin = pad let bin = pad
.parent_element() .parent_element()
@ -328,7 +328,7 @@ impl Video {
upload_frame_ref.swap(true, Ordering::SeqCst); upload_frame_ref.swap(true, Ordering::SeqCst);
if let Some(at) = clear_subtitles_at.clone() { if let Some(at) = clear_subtitles_at {
if Instant::now() >= at { if Instant::now() >= at {
*subtitle_text_ref *subtitle_text_ref
.lock() .lock()
@ -607,5 +607,5 @@ fn yuv_to_rgba(yuv: &[u8], width: u32, height: u32, downscale: u32) -> Vec<u8> {
} }
} }
return rgba; rgba
} }

View file

@ -187,7 +187,7 @@ where
let last_frame_time = inner let last_frame_time = inner
.last_frame_time .last_frame_time
.lock() .lock()
.map(|time| time.clone()) .map(|time| *time)
.unwrap_or_else(|_| Instant::now()); .unwrap_or_else(|_| Instant::now());
inner.set_av_offset(Instant::now() - last_frame_time); inner.set_av_offset(Instant::now() - last_frame_time);
} }
@ -270,7 +270,7 @@ where
if let Some(on_subtitle_text) = &self.on_subtitle_text { if let Some(on_subtitle_text) = &self.on_subtitle_text {
if inner.upload_text.swap(false, Ordering::SeqCst) { if inner.upload_text.swap(false, Ordering::SeqCst) {
if let Some(text) = inner.subtitle_text.try_lock().ok() { if let Ok(text) = inner.subtitle_text.try_lock() {
shell.publish(on_subtitle_text(text.clone())); shell.publish(on_subtitle_text(text.clone()));
} }
} }