From c5426b0fbc60dbca90c68d0e32090ca49055e6ab Mon Sep 17 00:00:00 2001
From: 21pages <sunboeasy@gmail.com>
Date: Mon, 18 Nov 2024 23:03:27 +0800
Subject: [PATCH] Fix hevc decode error "Could not find ref with POC" (#9960)

1. Dropping frames can cause this error, reset encoder when this
   happens.
2. There are some logic error for clear video queue, because video queue
   message is not cleared. This need to be fixed.

Signed-off-by: 21pages <sunboeasy@gmail.com>
---
 Cargo.lock                       |  4 ++--
 libs/scrap/src/common/hwcodec.rs |  3 ++-
 src/client.rs                    | 18 ++++++++++++++++++
 src/client/io_loop.rs            |  8 ++++++--
 4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5930b8721..b8a427f72 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1683,7 +1683,7 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
 dependencies = [
- "libloading 0.8.4",
+ "libloading 0.7.4",
 ]
 
 [[package]]
@@ -3051,7 +3051,7 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 [[package]]
 name = "hwcodec"
 version = "0.7.0"
-source = "git+https://github.com/rustdesk-org/hwcodec#8bbd05bb300ad07cc345356ad85570f9ea99fbfa"
+source = "git+https://github.com/rustdesk-org/hwcodec#da7dab48df19edb5a7138ff9e01bf9f148b523da"
 dependencies = [
  "bindgen 0.59.2",
  "cc",
diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs
index a0e730c91..2a83afacc 100644
--- a/libs/scrap/src/common/hwcodec.rs
+++ b/libs/scrap/src/common/hwcodec.rs
@@ -15,7 +15,7 @@ use hbb_common::{
 };
 use hwcodec::{
     common::{
-        DataFormat,
+        DataFormat, HwcodecErrno,
         Quality::{self, *},
         RateControl::{self, *},
     },
@@ -31,6 +31,7 @@ const DEFAULT_PIXFMT: AVPixelFormat = AVPixelFormat::AV_PIX_FMT_NV12;
 pub const DEFAULT_FPS: i32 = 30;
 const DEFAULT_GOP: i32 = i32::MAX;
 const DEFAULT_HW_QUALITY: Quality = Quality_Default;
+pub const ERR_HEVC_POC: i32 = HwcodecErrno::HWCODEC_ERR_HEVC_COULD_NOT_FIND_POC as i32;
 
 crate::generate_call_macro!(call_yuv, false);
 
diff --git a/src/client.rs b/src/client.rs
index c36063530..18c3d268b 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -2417,6 +2417,24 @@ where
                                     // to-do: fix the error
                                     log::error!("handle video frame error, {}", e);
                                     session.refresh_video(display as _);
+                                    #[cfg(feature = "hwcodec")]
+                                    if format == CodecFormat::H265 {
+                                        if let Some(&scrap::hwcodec::ERR_HEVC_POC) =
+                                            e.downcast_ref::<i32>()
+                                        {
+                                            for (i, handler_controler) in
+                                                handler_controller_map.iter_mut()
+                                            {
+                                                if *i != display
+                                                    && handler_controler.handler.decoder.format()
+                                                        == CodecFormat::H265
+                                                {
+                                                    log::info!("refresh video {} due to hevc poc not found", i);
+                                                    session.refresh_video(*i as _);
+                                                }
+                                            }
+                                        }
+                                    }
                                 }
                                 _ => {}
                             }
diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs
index 9aec89dd3..0766b6b51 100644
--- a/src/client/io_loop.rs
+++ b/src/client/io_loop.rs
@@ -1146,9 +1146,13 @@ impl<T: InvokeUiSession> Remote<T> {
                             .ok();
                     } else {
                         if let Some(video_queue) = video_queue_write.get_mut(&display) {
-                            video_queue.force_push(vf);
+                            if video_queue.force_push(vf).is_some() {
+                                while let Some(_) = video_queue.pop() {}
+                                self.handler.refresh_video(display as _);
+                            } else {
+                                self.video_sender.send(MediaData::VideoQueue(display)).ok();
+                            }
                         }
-                        self.video_sender.send(MediaData::VideoQueue(display)).ok();
                     }
                     self.fps_control
                         .last_active_time