Explorar o código

app/vid: use a separate thread on android for uploading during decoding phase so video can stream load (before it would pop cos it must load fully before display)

darkfi hai 2 días
pai
achega
d4fffe7951

+ 19 - 11
bin/app/src/ui/vid/decode/android.rs

@@ -38,19 +38,20 @@ pub fn spawn_decoder_thread(
     path: String,
     vid_data: Arc<SyncMutex<Option<Av1VideoData>>>,
     renderer: Renderer,
-) -> thread::JoinHandle<()> {
+) {
     *vid_data.lock() = Some(Av1VideoData::new(150, &renderer));
 
+    let (frame_tx, frame_rx) = mpsc::channel::<DecodedFrame>();
+
+    let decoder_id = vid::register(frame_tx);
+
     spawn_thread("video-decoder-android", move || {
         let now = std::time::Instant::now();
         d!("Decoding MP4 video file: {path}");
 
-        let (frame_tx, frame_rx) = mpsc::channel::<DecodedFrame>();
-
-        let decoder_id = vid::register(frame_tx);
-
         let Some(decoder_handle) = vid::videodecoder_init(&path) else {
             error!(target: "ui:video::decode", "Failed to initialize MediaCodec decoder for: {path}");
+            vid::unregister(decoder_id);
             return;
         };
 
@@ -60,10 +61,21 @@ pub fn spawn_decoder_thread(
 
         drop(decoder_handle);
 
+        // Dropping the sender disconnects the channel which ends the
+        // uploader loop once all queued frames are processed
+        vid::unregister(decoder_id);
+
+        d!("Finished decoding video: {path} in {:?}", now.elapsed());
+    });
+
+    // decodeAll() blocks until the whole video is decoded. Upload frames
+    // from a parallel thread so textures appear while decoding is still
+    // running, otherwise the video only shows up after the full decode.
+    spawn_thread("video-uploader-android", move || {
         let mut frame_idx = 0;
         while let Ok(frame) = frame_rx.recv() {
             if process_frame(frame_idx, frame, &vid_data, &renderer).is_err() {
-                d!("Video stopped, exiting decoder thread");
+                d!("Video stopped, exiting uploader thread");
                 return;
             }
             frame_idx += 1;
@@ -78,11 +90,7 @@ pub fn spawn_decoder_thread(
                 break
             }
         }
-
-        d!("Finished decoding video: {path} in {:?}", now.elapsed());
-
-        vid::unregister(decoder_id);
-    })
+    });
 }
 
 fn process_frame(

+ 1 - 1
bin/app/src/ui/vid/decode/mod.rs

@@ -40,7 +40,7 @@ pub fn spawn_decoder_thread(
     path: String,
     vid_data: Arc<SyncMutex<Option<Av1VideoData>>>,
     renderer: Renderer,
-) -> std::thread::JoinHandle<()> {
+) {
     #[cfg(target_os = "android")]
     return android::spawn_decoder_thread(path, vid_data, renderer);
 

+ 2 - 2
bin/app/src/ui/vid/decode/rav1d.rs

@@ -56,7 +56,7 @@ pub fn spawn_decoder_thread(
     path: String,
     vid_data: Arc<SyncMutex<Option<Av1VideoData>>>,
     renderer: Renderer,
-) -> std::thread::JoinHandle<()> {
+) {
     let mut settings = Rav1dSettings::new();
     // 0 is auto detect
     settings.set_n_threads(4);
@@ -137,7 +137,7 @@ pub fn spawn_decoder_thread(
                 }
             }
         }
-    })
+    });
 }
 
 fn process(

+ 1 - 8
bin/app/src/ui/vid/mod.rs

@@ -78,8 +78,6 @@ pub struct Video {
     dc_key: u64,
 
     vid_data: Arc<SyncMutex<Option<Av1VideoData>>>,
-    _load_handle: SyncMutex<Option<std::thread::JoinHandle<()>>>,
-    _decoder_handle: SyncMutex<Option<std::thread::JoinHandle<()>>>,
 
     rect: PropertyRect,
     uv: PropertyRect,
@@ -120,8 +118,6 @@ impl Video {
             dc_key: OsRng.gen(),
 
             vid_data: Arc::new(SyncMutex::new(None)),
-            _load_handle: SyncMutex::new(None),
-            _decoder_handle: SyncMutex::new(None),
 
             rect,
             uv,
@@ -148,10 +144,7 @@ impl Video {
 
         // Decoder thread:
         // loads path, decodes AV1 -> RGB, creates textures directly
-        let decoder_handle =
-            spawn_decoder_thread(path, self.vid_data.clone(), self.renderer.clone());
-
-        *self._decoder_handle.lock() = Some(decoder_handle);
+        spawn_decoder_thread(path, self.vid_data.clone(), self.renderer.clone());
     }
 
     fn regen_mesh(&self) -> MeshInfo {