summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordyknon dyknonr5fjp2025-02-20 23:38:43 +0900
committerdyknon dyknonr5fjp2025-02-20 23:38:43 +0900
commit551373efc490b8d570254ee46b09d4e953e2a2d4 (patch)
treea343851586fe0248094632f79905ad2ca32b0c84
parent5633cf1b5fb1d07c2ae0cf4749bef3d08dde260a (diff)
reuse ImageSurface.
-rw-r--r--src/main.rs51
1 files changed, 33 insertions, 18 deletions
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<cairo::ImageSurface> = 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: &gtk::Application){
});
let draw = gtk::DrawingArea::new();
- let mut frame_cache = None;
+ let mut frame_cache: Option<cairo::ImageSurface> = 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));