From 551373efc490b8d570254ee46b09d4e953e2a2d4 Mon Sep 17 00:00:00 2001 From: dyknon Date: Thu, 20 Feb 2025 23:38:43 +0900 Subject: reuse ImageSurface. --- src/main.rs | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index b1a4404..ab54508 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,9 +66,24 @@ fn videothread(apps: AppState) -> Result<()>{ let s = c.bytesperline(); loop{ let img: Result = c.next(|frame, _|{ - let mut img = cairo::ImageSurface::create( - cairo::Format::Rgb24, - w.try_into()?, h.try_into()?)?; + let mut img = None; + let mut fbpool = apps.fbpool.lock().unwrap(); + while let Some(i) = fbpool.pop(){ + let i = i.into_inner(); + if i.width() as usize == w && i.height() as usize == h{ + img = Some(i); + break; + } + } + drop(fbpool); + let mut img = match img{ + Some(i) => i, + None => { + cairo::ImageSurface::create( + cairo::Format::Rgb24, + w.try_into()?, h.try_into()?)? + }, + }; let stride: usize = img.stride().try_into()?; let mut imgslice = img.data()?; match c.pixelformat().as_str(){ @@ -81,6 +96,7 @@ fn videothread(apps: AppState) -> Result<()>{ imgslice[stride*y + x*4 + 0] = b; imgslice[stride*y + x*4 + 1] = g; imgslice[stride*y + x*4 + 2] = r; + imgslice[stride*y + x*4 + 3] = 0; } drop(imgslice); Ok(img) @@ -92,17 +108,21 @@ fn videothread(apps: AppState) -> Result<()>{ .filter(|i| frame[*i] == 0xff && frame[i+1] == 0xd8) .next() .ok_or(anyhow!("jpeg not found"))?; + let mut jpeg = JpegDec::new(&frame[jindex..]); let b = jpeg.decode()?; let info = jpeg.info().unwrap(); + assert!((info.width as usize, info.height as usize) == (w, h)); for (x, y) in (0..h).map( |y| (0..w).map(move |x|(x, y))).flatten(){ - imgslice[stride*y + x*4 + 0] = b[(y*w+x)*3 + 0]; + imgslice[stride*y + x*4 + 0] = b[(y*w+x)*3 + 2]; imgslice[stride*y + x*4 + 1] = b[(y*w+x)*3 + 1]; - imgslice[stride*y + x*4 + 2] = b[(y*w+x)*3 + 2]; + imgslice[stride*y + x*4 + 2] = b[(y*w+x)*3 + 0]; + imgslice[stride*y + x*4 + 3] = 0; } + drop(imgslice); Ok(img) }, @@ -135,29 +155,24 @@ fn gtkmain(app: >k::Application){ }); let draw = gtk::DrawingArea::new(); - let mut frame_cache = None; + let mut frame_cache: Option = None; draw.set_draw_func(clone!{ #[strong(rename_to=frame_buf)] apps.frame_buf, + #[strong(rename_to=fbpool)] apps.fbpool, move |_draw, ctx, canvas_w, canvas_h|{ ctx.set_source_rgb(0., 0., 0.); ctx.paint().unwrap(); if let Some(newfb) = frame_buf.lock().unwrap().take(){ + if let Some(mut lastframe) = frame_cache.take(){ + let mut fbpool = fbpool.lock().unwrap(); + if fbpool.len() < 8{ + fbpool.push(lastframe.take_data().unwrap()); + } + } frame_cache = Some(newfb.into_inner()); } if let Some(image) = frame_cache.clone(){ - //{ - // let stride: usize = isurface.stride().try_into().unwrap(); - // let mut isdata = isurface.data().unwrap(); - // for y in 0..image.height{ - // for x in 0..image.width{ - // for c in 0..4{ - // isdata[stride*y + x*4 + c] - // = image.buf[(image.width*y+x)*4 + c]; - // } - // } - // } - //} let ipat = cairo::SurfacePattern::create(&image); let scale = ((canvas_w as f64) / (image.width() as f64)).min( (canvas_h as f64) / (image.height() as f64)); -- cgit v1.2.3