From bb5940ff67704505b5553cf29db5aad97b80f01a Mon Sep 17 00:00:00 2001 From: tiif Date: Sat, 30 Dec 2023 18:18:27 +0800 Subject: [PATCH 01/12] Improved prefetching --- src/bin/vvplay_async.rs | 4 ++ src/dash/buffer.rs | 7 ++ src/render/wgpu/reader.rs | 7 +- src/vvplay_async_prefetch/buffer_manager.rs | 71 ++++++++++++++------- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/bin/vvplay_async.rs b/src/bin/vvplay_async.rs index 11a9297..c884a37 100644 --- a/src/bin/vvplay_async.rs +++ b/src/bin/vvplay_async.rs @@ -326,7 +326,11 @@ fn main() { }, }; decoder.start().unwrap(); + //t: the unbound receiver for PointCloud is here, trace this down + // Everytime a PointCloud is ready, an unbounded channel is created + // t: For case of Noop, only one PointCloud will be produced each time, not sure about other decoder let (output_sx, output_rx) = tokio::sync::mpsc::unbounded_channel(); + // Send BufMsg to inform the buffer that the PointCloud is ready _ = to_buf_sx .send(BufMsg::PointCloud(( PCMetadata { diff --git a/src/dash/buffer.rs b/src/dash/buffer.rs index ae5cbe6..116e662 100644 --- a/src/dash/buffer.rs +++ b/src/dash/buffer.rs @@ -102,6 +102,9 @@ impl Buffer { #[inline] /// Update the request and state of a frame. Panics if key is not found. If the new_state is Ready(0, _), the frame is removed. pub fn update(&mut self, key: FrameRequest, new_key: FrameRequest, new_state: FrameStatus) { + //t: who called this while the frame is decoding in the buffer + //t: this caused a crash because the frames are removed + println!("update is called from {:?} to {:?} with state {:?}", key, new_key, new_state); let idx = self .frames .iter() @@ -177,4 +180,8 @@ impl Buffer { pub fn iter_mut(&mut self) -> impl Iterator { self.frames.iter_mut() } + + pub fn clear(&mut self) { + self.frames.clear(); + } } diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index 083b232..f6145fe 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -263,9 +263,8 @@ impl RenderReaderCameraPos> for PcdAsyncReader { */ let index = index as u64; if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { - //t: - //it: f the result is already inside the cache, just return - //can improve this find algorithm + //if the result is already inside the cache, just return + //can improve this O(size) find algorithm return (camera_pos, Some(result.1.clone())); } _ = self.tx.send(BufMsg::FrameRequest(FrameRequest { @@ -309,10 +308,8 @@ impl RenderReader> for PcdAsyncReader { } fn get_at(&mut self, index: usize) -> Option> { - /* println!("----------------------------------"); println!{"get at request index: {}", index}; - */ let index = index as u64; // Everytime a request is made, find it from the playback cache first if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { diff --git a/src/vvplay_async_prefetch/buffer_manager.rs b/src/vvplay_async_prefetch/buffer_manager.rs index 5c20db8..88098fa 100644 --- a/src/vvplay_async_prefetch/buffer_manager.rs +++ b/src/vvplay_async_prefetch/buffer_manager.rs @@ -73,9 +73,13 @@ impl BufferManager { //Send fetch request for the next frame and add it to the buffer pub fn prefetch_frame(&mut self, camera_pos: Option) { - assert!(camera_pos.is_some()); + //t: temporary fix, fix this later + let camera_pos_temp = Some(camera_pos.unwrap_or(CameraPosition::default())); + assert!(camera_pos_temp.is_some()); + //assert!(camera_pos.is_some()); let last_req = FrameRequest { - camera_pos, + //camera_pos, + camera_pos: camera_pos_temp, ..self.buffer.back().unwrap().req }; // The frame prefetched is the next frame of the frame at the back of the buffer @@ -111,47 +115,45 @@ impl BufferManager { camera_trace: Option, mut record_camera_trace: Option, ) { + //t: keep a variable for front and back of the buffer so don't need to take in and out everytime + //t: even the frame is taken, it will still be running, is there any way to get around this? // Since we prefetch after a `FetchDone` event, once the buffer is full, we can't prefetch anymore. // So, we set this flag to true once the buffer is full, so that when the frames are consumed and the first channels are discarded, we can prefetch again. + //t: use this let mut is_desired_buffer_level_reached = false; let mut last_req: Option = None; loop { - /* println!{"---------------------------"}; println!("buffer: {:?}", &self.buffer); - */ - //wait for message in self.shutdown_recv and self.to_buf_Rx - //if a message is received, match the message with the bufmsg enum + //wait for message in self.shutdown_recv and self.to_buf_rx if !self.buffer.is_full() && !self.buffer.is_empty() { + // This is executed when there is some frame inside the buffer, and the buffer is not full. + println!("---------------------------"); + println!{"buffer is not full neither empty, prefetching frame"}; self.prefetch_frame(Some(CameraPosition::default())); } else if self.buffer.is_empty() && last_req.is_some() { - //temporary fix: right not just assign default camera position + // If the buffer is currently empty, we continue to prefetch the frame, necessary for the case buffer size = 1 + println!{"---------------------------"}; + println!{"buffer is empty and there is last request, prefetching frame"}; self.prefetch_frame_with_request( + // temporary fix: right not just assign default camera position Some(CameraPosition::default()), last_req.unwrap(), ); } + //t: might need to handle this in order to let ctrl-c work properly tokio::select! { _ = self.shutdown_recv.changed() => { - /* - println!{"---------------------------"}; - println!{"in vvplay_async:"} - println!{"[buffer mgr] received shutdown signal"}; - */ break; } Some(msg) = self.to_buf_rx.recv() => { match msg { BufMsg::FrameRequest(mut renderer_req) => { - /* println!{"---------------------------"}; println!{"[buffer mgr] renderer sent a frame request {:?}", &renderer_req}; - */ - // record camera trace if record_camera_trace.is_some() && renderer_req.camera_pos.is_some() { if let Some(ct) = record_camera_trace.as_mut() { ct.add(renderer_req.camera_pos.unwrap()) } } - // If the camera trace is provided, we will use the camera trace to override the camera position for the next frame // else we will feed this into the viewport predictor if camera_trace.is_some() { @@ -160,10 +162,28 @@ impl BufferManager { viewport_predictor.add(renderer_req.camera_pos.unwrap_or_else(|| original_position)); renderer_req.camera_pos = viewport_predictor.predict(); } - - // First, attempt to fulfill the request from the buffer. - // Check in cache whether it exists + + // First, attempt to fulfill the request from the renderer. + // If the request is out of range + if !self.buffer.is_empty() && (renderer_req.frame_offset < self.buffer.front().unwrap().req.frame_offset + || renderer_req.frame_offset > self.buffer.back().unwrap().req.frame_offset) { + self.buffer.clear(); + //t: it will be added to the buffer after that, but need to tidy up the logic + } else if !self.buffer.is_empty() && renderer_req.frame_offset > self.buffer.front().unwrap().req.frame_offset + && renderer_req.frame_offset <= self.buffer.back().unwrap().req.frame_offset { + // Check if the request is inside the buffer. + // Remove all the previous frame to achieve that frame + // When the frame requested is inside the buffer, but not at the front, we will pop all the previous frame + let num_frames_to_remove = renderer_req.frame_offset - self.buffer.front().unwrap().req.frame_offset; + for _ in 0..num_frames_to_remove { + self.buffer.pop_front(); + } + } + // Check if the request is at the front of the buffer. + //t: make this part better later, if better, abstract the logic if !self.buffer.is_empty() && self.buffer.front().unwrap().req.frame_offset == renderer_req.frame_offset { + //t: renderer requested frame == buffer front frame + //t: Can get the front and back frame from the buffer vecdeque let mut front = self.buffer.pop_front().unwrap(); match front.state { FrameStatus::Fetching | FrameStatus::Decoding => { @@ -173,6 +193,7 @@ impl BufferManager { } FrameStatus::Ready(remaining_frames, mut rx) => { // send to the renderer + //t: what is this logic? and how to ensure the frame we get is the correct one? match rx.recv().await { Some(pc) => { // if camera trace is not provided, we should not send camera_pos back to the renderer @@ -188,12 +209,15 @@ impl BufferManager { front.req.frame_offset += 1; front.state = FrameStatus::Ready(remaining_frames - 1, rx); //println!("In FrameStatus::Ready, the front is {:?}", front); + //t: why this matter? if remaining_frames > 1 { // we only reinsert it if there are more frames to render self.buffer.push_front(front); } else if !is_desired_buffer_level_reached { + //t: is this necessary? //println!("in FrameStatus::Ready::!is_desired_buffer_level_reached"); //if the desired buffer level is not reached, should add in a new frame + //t: fix this later self.prefetch_frame(original_camera_pos); } } @@ -207,6 +231,7 @@ impl BufferManager { } } } else { + println!("The request is not at the front of the buffer"); // It has not been requested, so we send a request to the fetcher to fetch the data _ = self.buf_in_sx.send(FetchRequest::new(renderer_req, self.buffer.len())); @@ -219,10 +244,8 @@ impl BufferManager { } BufMsg::FetchDone(req) => { // upon receiving fetch result, immediately schedule the next fetch request - /* println!{"---------------------------"}; println!("the current buffer message is fetch done for {:?}", req); - */ self.buffer.update_state(req, FrameStatus::Decoding); if !self.buffer.is_full() { @@ -233,11 +256,12 @@ impl BufferManager { } } BufMsg::PointCloud((mut metadata, mut rx)) => { - /* println!{"---------------------------"}; println!("[buffer mgr] received a point cloud result {:?}", &metadata); - */ let orig_metadata: FrameRequest = metadata.into(); + // Only update when the frame is still in the buffer + if !self.buffer.is_empty() && orig_metadata.frame_offset >= self.buffer.front().unwrap().req.frame_offset + && orig_metadata.frame_offset <= self.buffer.back().unwrap().req.frame_offset { //if this frame is the one that the renderer is awaiting, do not put it back and send it to the renderer let mut remaining = self.segment_size as usize; if self.frame_to_answer.is_some() @@ -255,6 +279,7 @@ impl BufferManager { self.buffer.update(orig_metadata, metadata.into(), FrameStatus::Ready(remaining, rx)); last_req = Some(orig_metadata); } + } } } else => break, From 000f645fdf7c87a14311f445e92c342fa61764ef Mon Sep 17 00:00:00 2001 From: tiif Date: Sat, 30 Dec 2023 22:11:51 +0800 Subject: [PATCH 02/12] Cleaned up code --- src/dash/buffer.rs | 14 ++++- src/render/wgpu/reader.rs | 2 + src/vvplay_async_prefetch/buffer_manager.rs | 68 ++++++++------------- 3 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/dash/buffer.rs b/src/dash/buffer.rs index 116e662..bd7309b 100644 --- a/src/dash/buffer.rs +++ b/src/dash/buffer.rs @@ -102,9 +102,6 @@ impl Buffer { #[inline] /// Update the request and state of a frame. Panics if key is not found. If the new_state is Ready(0, _), the frame is removed. pub fn update(&mut self, key: FrameRequest, new_key: FrameRequest, new_state: FrameStatus) { - //t: who called this while the frame is decoding in the buffer - //t: this caused a crash because the frames are removed - println!("update is called from {:?} to {:?} with state {:?}", key, new_key, new_state); let idx = self .frames .iter() @@ -184,4 +181,15 @@ impl Buffer { pub fn clear(&mut self) { self.frames.clear(); } + + pub fn is_frame_in_buffer(&self, req: FrameRequest) -> bool { + // This implementation assumes that the frame stored in the buffer is sequential. + // If the first frame offset is 2, last frame offset is 5, then frame 3, 4 will also exist in current buffer. + if req.frame_offset >= self.front().unwrap().req.frame_offset + && req.frame_offset <= self.back().unwrap().req.frame_offset + { + return true; + } + return false; + } } diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index f6145fe..d68b8b2 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -308,8 +308,10 @@ impl RenderReader> for PcdAsyncReader { } fn get_at(&mut self, index: usize) -> Option> { + /* println!("----------------------------------"); println!{"get at request index: {}", index}; + */ let index = index as u64; // Everytime a request is made, find it from the playback cache first if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { diff --git a/src/vvplay_async_prefetch/buffer_manager.rs b/src/vvplay_async_prefetch/buffer_manager.rs index 88098fa..dfa4259 100644 --- a/src/vvplay_async_prefetch/buffer_manager.rs +++ b/src/vvplay_async_prefetch/buffer_manager.rs @@ -115,33 +115,28 @@ impl BufferManager { camera_trace: Option, mut record_camera_trace: Option, ) { - //t: keep a variable for front and back of the buffer so don't need to take in and out everytime - //t: even the frame is taken, it will still be running, is there any way to get around this? // Since we prefetch after a `FetchDone` event, once the buffer is full, we can't prefetch anymore. // So, we set this flag to true once the buffer is full, so that when the frames are consumed and the first channels are discarded, we can prefetch again. - //t: use this let mut is_desired_buffer_level_reached = false; let mut last_req: Option = None; loop { - println!{"---------------------------"}; - println!("buffer: {:?}", &self.buffer); - //wait for message in self.shutdown_recv and self.to_buf_rx + //println!{"---------------------------"}; + //println!("buffer: {:?}", &self.buffer); if !self.buffer.is_full() && !self.buffer.is_empty() { // This is executed when there is some frame inside the buffer, and the buffer is not full. - println!("---------------------------"); - println!{"buffer is not full neither empty, prefetching frame"}; + //println!("---------------------------"); + //println!{"buffer is not full neither empty, prefetching frame"}; self.prefetch_frame(Some(CameraPosition::default())); } else if self.buffer.is_empty() && last_req.is_some() { // If the buffer is currently empty, we continue to prefetch the frame, necessary for the case buffer size = 1 - println!{"---------------------------"}; - println!{"buffer is empty and there is last request, prefetching frame"}; + //println!{"---------------------------"}; + //println!{"buffer is empty and there is last request, prefetching frame"}; self.prefetch_frame_with_request( // temporary fix: right not just assign default camera position Some(CameraPosition::default()), last_req.unwrap(), ); } - //t: might need to handle this in order to let ctrl-c work properly tokio::select! { _ = self.shutdown_recv.changed() => { break; @@ -149,8 +144,8 @@ impl BufferManager { Some(msg) = self.to_buf_rx.recv() => { match msg { BufMsg::FrameRequest(mut renderer_req) => { - println!{"---------------------------"}; - println!{"[buffer mgr] renderer sent a frame request {:?}", &renderer_req}; + //println!{"---------------------------"}; + //println!{"[buffer mgr] renderer sent a frame request {:?}", &renderer_req}; if record_camera_trace.is_some() && renderer_req.camera_pos.is_some() { if let Some(ct) = record_camera_trace.as_mut() { ct.add(renderer_req.camera_pos.unwrap()) } } @@ -164,36 +159,28 @@ impl BufferManager { } // First, attempt to fulfill the request from the renderer. - // If the request is out of range - if !self.buffer.is_empty() && (renderer_req.frame_offset < self.buffer.front().unwrap().req.frame_offset - || renderer_req.frame_offset > self.buffer.back().unwrap().req.frame_offset) { + // If the requested frame is not inside the buffer, we will clear the buffer. + if !self.buffer.is_empty() && !self.buffer.is_frame_in_buffer(renderer_req) { self.buffer.clear(); - //t: it will be added to the buffer after that, but need to tidy up the logic - } else if !self.buffer.is_empty() && renderer_req.frame_offset > self.buffer.front().unwrap().req.frame_offset - && renderer_req.frame_offset <= self.buffer.back().unwrap().req.frame_offset { - // Check if the request is inside the buffer. - // Remove all the previous frame to achieve that frame - // When the frame requested is inside the buffer, but not at the front, we will pop all the previous frame + } else if !self.buffer.is_empty() && self.buffer.is_frame_in_buffer(renderer_req) { + // If the frame requested is inside the buffer, we will pop all previous frame such that the requested frame is at front. let num_frames_to_remove = renderer_req.frame_offset - self.buffer.front().unwrap().req.frame_offset; for _ in 0..num_frames_to_remove { self.buffer.pop_front(); } } - // Check if the request is at the front of the buffer. - //t: make this part better later, if better, abstract the logic + + // When the requested frame is in front of the buffer if !self.buffer.is_empty() && self.buffer.front().unwrap().req.frame_offset == renderer_req.frame_offset { - //t: renderer requested frame == buffer front frame - //t: Can get the front and back frame from the buffer vecdeque let mut front = self.buffer.pop_front().unwrap(); match front.state { FrameStatus::Fetching | FrameStatus::Decoding => { - // we update frame_to_answer to indicate that we are waiting to send back this data to renderer. + // We update frame_to_answer to indicate that we are waiting to send back this data to renderer. self.frame_to_answer = Some(renderer_req); self.buffer.push_front(front); } FrameStatus::Ready(remaining_frames, mut rx) => { - // send to the renderer - //t: what is this logic? and how to ensure the frame we get is the correct one? + // Receive the point cloud from the UnboundedReceiver match rx.recv().await { Some(pc) => { // if camera trace is not provided, we should not send camera_pos back to the renderer @@ -208,16 +195,12 @@ impl BufferManager { self.frame_to_answer = None; front.req.frame_offset += 1; front.state = FrameStatus::Ready(remaining_frames - 1, rx); - //println!("In FrameStatus::Ready, the front is {:?}", front); - //t: why this matter? if remaining_frames > 1 { // we only reinsert it if there are more frames to render self.buffer.push_front(front); } else if !is_desired_buffer_level_reached { - //t: is this necessary? //println!("in FrameStatus::Ready::!is_desired_buffer_level_reached"); //if the desired buffer level is not reached, should add in a new frame - //t: fix this later self.prefetch_frame(original_camera_pos); } } @@ -231,8 +214,7 @@ impl BufferManager { } } } else { - println!("The request is not at the front of the buffer"); - // It has not been requested, so we send a request to the fetcher to fetch the data + // If the requested frame is not inside the buffer, we send a request to the fetcher to fetch the data _ = self.buf_in_sx.send(FetchRequest::new(renderer_req, self.buffer.len())); // we update frame_to_answer to indicate that we are waiting to send back this data to renderer. @@ -244,8 +226,8 @@ impl BufferManager { } BufMsg::FetchDone(req) => { // upon receiving fetch result, immediately schedule the next fetch request - println!{"---------------------------"}; - println!("the current buffer message is fetch done for {:?}", req); + //println!{"---------------------------"}; + //println!("the current buffer message is fetch done for {:?}", req); self.buffer.update_state(req, FrameStatus::Decoding); if !self.buffer.is_full() { @@ -256,20 +238,18 @@ impl BufferManager { } } BufMsg::PointCloud((mut metadata, mut rx)) => { - println!{"---------------------------"}; - println!("[buffer mgr] received a point cloud result {:?}", &metadata); + //println!{"---------------------------"}; + //println!("[buffer mgr] received a point cloud result {:?}", &metadata); let orig_metadata: FrameRequest = metadata.into(); - // Only update when the frame is still in the buffer - if !self.buffer.is_empty() && orig_metadata.frame_offset >= self.buffer.front().unwrap().req.frame_offset - && orig_metadata.frame_offset <= self.buffer.back().unwrap().req.frame_offset { - //if this frame is the one that the renderer is awaiting, do not put it back and send it to the renderer + // Only update the frame state in buffer when the frame is still in the buffer + if !self.buffer.is_empty() && self.buffer.is_frame_in_buffer(orig_metadata) { let mut remaining = self.segment_size as usize; if self.frame_to_answer.is_some() && metadata.frame_offset == self.frame_to_answer.as_ref().unwrap().frame_offset { let pc = rx.recv().await.unwrap(); - // send results to the renderer + // Send results to the renderer _ = self.buf_out_sx.send((self.frame_to_answer.unwrap(), pc)); self.frame_to_answer = None; metadata.frame_offset += 1; From 0ebd43a5d3253820aec1e15bed5f5b267069caaa Mon Sep 17 00:00:00 2001 From: tiif Date: Sat, 30 Dec 2023 22:12:27 +0800 Subject: [PATCH 03/12] Ran cargo fmt --- src/render/wgpu/reader.rs | 2 +- src/vvplay_async_prefetch/buffer_manager.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index d68b8b2..a53aa0c 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -308,7 +308,7 @@ impl RenderReader> for PcdAsyncReader { } fn get_at(&mut self, index: usize) -> Option> { - /* + /* println!("----------------------------------"); println!{"get at request index: {}", index}; */ diff --git a/src/vvplay_async_prefetch/buffer_manager.rs b/src/vvplay_async_prefetch/buffer_manager.rs index dfa4259..add62df 100644 --- a/src/vvplay_async_prefetch/buffer_manager.rs +++ b/src/vvplay_async_prefetch/buffer_manager.rs @@ -157,20 +157,20 @@ impl BufferManager { viewport_predictor.add(renderer_req.camera_pos.unwrap_or_else(|| original_position)); renderer_req.camera_pos = viewport_predictor.predict(); } - + // First, attempt to fulfill the request from the renderer. - // If the requested frame is not inside the buffer, we will clear the buffer. + // If the requested frame is not inside the buffer, we will clear the buffer. if !self.buffer.is_empty() && !self.buffer.is_frame_in_buffer(renderer_req) { self.buffer.clear(); } else if !self.buffer.is_empty() && self.buffer.is_frame_in_buffer(renderer_req) { - // If the frame requested is inside the buffer, we will pop all previous frame such that the requested frame is at front. + // If the frame requested is inside the buffer, we will pop all previous frame such that the requested frame is at front. let num_frames_to_remove = renderer_req.frame_offset - self.buffer.front().unwrap().req.frame_offset; for _ in 0..num_frames_to_remove { self.buffer.pop_front(); } } - // When the requested frame is in front of the buffer + // When the requested frame is in front of the buffer if !self.buffer.is_empty() && self.buffer.front().unwrap().req.frame_offset == renderer_req.frame_offset { let mut front = self.buffer.pop_front().unwrap(); match front.state { @@ -241,7 +241,7 @@ impl BufferManager { //println!{"---------------------------"}; //println!("[buffer mgr] received a point cloud result {:?}", &metadata); let orig_metadata: FrameRequest = metadata.into(); - // Only update the frame state in buffer when the frame is still in the buffer + // Only update the frame state in buffer when the frame is still in the buffer if !self.buffer.is_empty() && self.buffer.is_frame_in_buffer(orig_metadata) { let mut remaining = self.segment_size as usize; if self.frame_to_answer.is_some() From 29633d63baef1f6b5edf62c1b2ffee9908d0ba32 Mon Sep 17 00:00:00 2001 From: tiif Date: Sat, 30 Dec 2023 23:05:18 +0800 Subject: [PATCH 04/12] Updated comment --- src/dash/buffer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dash/buffer.rs b/src/dash/buffer.rs index bd7309b..e887390 100644 --- a/src/dash/buffer.rs +++ b/src/dash/buffer.rs @@ -183,7 +183,7 @@ impl Buffer { } pub fn is_frame_in_buffer(&self, req: FrameRequest) -> bool { - // This implementation assumes that the frame stored in the buffer is sequential. + // This implementation assumes that the frame index stored in the buffer form contiguous sequence. // If the first frame offset is 2, last frame offset is 5, then frame 3, 4 will also exist in current buffer. if req.frame_offset >= self.front().unwrap().req.frame_offset && req.frame_offset <= self.back().unwrap().req.frame_offset From 0576898d68678b71b9db37f935cd204f6269593e Mon Sep 17 00:00:00 2001 From: tiif Date: Fri, 5 Jan 2024 15:43:33 +0800 Subject: [PATCH 05/12] Removed result.txt --- src/render/wgpu/result.txt | 0 src/result.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/render/wgpu/result.txt delete mode 100644 src/result.txt diff --git a/src/render/wgpu/result.txt b/src/render/wgpu/result.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/result.txt b/src/result.txt deleted file mode 100644 index e69de29..0000000 From 503e9b69ddd527d260590e950c310ba964146979 Mon Sep 17 00:00:00 2001 From: tiif Date: Sat, 6 Jan 2024 02:14:32 +0800 Subject: [PATCH 06/12] Fixed CameraPosition related problem --- src/render/wgpu/reader.rs | 21 ++++----- src/vvplay_async_prefetch/buffer_manager.rs | 47 +++++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index a53aa0c..6f37224 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -9,8 +9,7 @@ use std::path::{Path, PathBuf}; use std::sync::mpsc::Receiver; use tokio::sync::mpsc::UnboundedSender; -use super::camera::CameraPosition; -use super::camera::CameraState; +use super::camera::{CameraPosition, CameraState}; use super::renderable::Renderable; //RenderReader for the original RenderReader @@ -119,7 +118,7 @@ impl RenderReader> for PointCloudFileReader { impl RenderReaderCameraPos> for PointCloudFileReader { fn start(&mut self) -> (Option, Option>) { - RenderReaderCameraPos::get_at(self, 0, None) + RenderReaderCameraPos::get_at(self, 0, Some(CameraPosition::default())) } fn get_at( @@ -128,7 +127,7 @@ impl RenderReaderCameraPos> for PointCloudFileReader { _camera_pos: Option, ) -> (Option, Option>) { let file_path = self.files.get(index).unwrap(); - (None, read_file_to_point_cloud(file_path)) + (Some(CameraPosition::default()), read_file_to_point_cloud(file_path)) } fn len(&self) -> usize { @@ -249,7 +248,7 @@ impl PcdAsyncReader { #[cfg(feature = "dash")] impl RenderReaderCameraPos> for PcdAsyncReader { fn start(&mut self) -> (Option, Option>) { - RenderReaderCameraPos::get_at(self, 0, None) + RenderReaderCameraPos::get_at(self, 0, Some(CameraPosition::default())) } fn get_at( @@ -276,10 +275,10 @@ impl RenderReaderCameraPos> for PcdAsyncReader { if self.cache.len() >= 10 { self.cache.pop(); } - println!( - "one frame is added to the point cloud cache: index:{}", - index - ); + //println!( + // "one frame is added to the point cloud cache: index:{}", + // index + //); self.cache.push((index, pc.clone())); (frame_req.camera_pos, Some(pc)) } else { @@ -308,10 +307,8 @@ impl RenderReader> for PcdAsyncReader { } fn get_at(&mut self, index: usize) -> Option> { - /* println!("----------------------------------"); println!{"get at request index: {}", index}; - */ let index = index as u64; // Everytime a request is made, find it from the playback cache first if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { @@ -322,7 +319,7 @@ impl RenderReader> for PcdAsyncReader { _ = self.tx.send(BufMsg::FrameRequest(FrameRequest { object_id: 0, frame_offset: index % self.total_frames, - camera_pos: None, + camera_pos: Some(CameraPosition::default()), })); // Wait for the point cloud to be ready, cache it then return if let Ok((_frame_req, pc)) = self.rx.recv() { diff --git a/src/vvplay_async_prefetch/buffer_manager.rs b/src/vvplay_async_prefetch/buffer_manager.rs index add62df..c337938 100644 --- a/src/vvplay_async_prefetch/buffer_manager.rs +++ b/src/vvplay_async_prefetch/buffer_manager.rs @@ -73,13 +73,10 @@ impl BufferManager { //Send fetch request for the next frame and add it to the buffer pub fn prefetch_frame(&mut self, camera_pos: Option) { - //t: temporary fix, fix this later - let camera_pos_temp = Some(camera_pos.unwrap_or(CameraPosition::default())); - assert!(camera_pos_temp.is_some()); - //assert!(camera_pos.is_some()); + assert!(camera_pos.is_some()); let last_req = FrameRequest { //camera_pos, - camera_pos: camera_pos_temp, + camera_pos: camera_pos, ..self.buffer.back().unwrap().req }; // The frame prefetched is the next frame of the frame at the back of the buffer @@ -118,22 +115,23 @@ impl BufferManager { // Since we prefetch after a `FetchDone` event, once the buffer is full, we can't prefetch anymore. // So, we set this flag to true once the buffer is full, so that when the frames are consumed and the first channels are discarded, we can prefetch again. let mut is_desired_buffer_level_reached = false; + // last_req is only use for buffer size = 1, and it is update after the last PointCloud is received. let mut last_req: Option = None; loop { - //println!{"---------------------------"}; - //println!("buffer: {:?}", &self.buffer); + println!{"---------------------------"}; + println!("buffer: {:?}", &self.buffer); + //This logic can be improved but it needs to be thoroughly tested. if !self.buffer.is_full() && !self.buffer.is_empty() { // This is executed when there is some frame inside the buffer, and the buffer is not full. - //println!("---------------------------"); - //println!{"buffer is not full neither empty, prefetching frame"}; + println!("---------------------------"); + println!{"buffer is not full neither empty, prefetching frame"}; self.prefetch_frame(Some(CameraPosition::default())); } else if self.buffer.is_empty() && last_req.is_some() { - // If the buffer is currently empty, we continue to prefetch the frame, necessary for the case buffer size = 1 - //println!{"---------------------------"}; - //println!{"buffer is empty and there is last request, prefetching frame"}; + // If the buffer is currently empty, we continue to prefetch the frame, necessary for buffer size = 1 + println!{"---------------------------"}; + println!{"buffer is empty and there is last request, prefetching frame"}; self.prefetch_frame_with_request( - // temporary fix: right not just assign default camera position - Some(CameraPosition::default()), + Some(last_req.unwrap().camera_pos.unwrap()), last_req.unwrap(), ); } @@ -144,13 +142,15 @@ impl BufferManager { Some(msg) = self.to_buf_rx.recv() => { match msg { BufMsg::FrameRequest(mut renderer_req) => { - //println!{"---------------------------"}; - //println!{"[buffer mgr] renderer sent a frame request {:?}", &renderer_req}; + println!{"---------------------------"}; + println!{"[buffer mgr] renderer sent a frame request {:?}", &renderer_req}; if record_camera_trace.is_some() && renderer_req.camera_pos.is_some() { if let Some(ct) = record_camera_trace.as_mut() { ct.add(renderer_req.camera_pos.unwrap()) } } // If the camera trace is provided, we will use the camera trace to override the camera position for the next frame // else we will feed this into the viewport predictor + // camera for the whole duratio, camera predictor predict where the user will be in the future + // just use the same frame request for prefetching if camera_trace.is_some() { renderer_req.camera_pos = camera_trace.as_ref().map(|ct| ct.next()); } else { @@ -199,7 +199,7 @@ impl BufferManager { // we only reinsert it if there are more frames to render self.buffer.push_front(front); } else if !is_desired_buffer_level_reached { - //println!("in FrameStatus::Ready::!is_desired_buffer_level_reached"); + println!("in FrameStatus::Ready::!is_desired_buffer_level_reached"); //if the desired buffer level is not reached, should add in a new frame self.prefetch_frame(original_camera_pos); } @@ -226,8 +226,8 @@ impl BufferManager { } BufMsg::FetchDone(req) => { // upon receiving fetch result, immediately schedule the next fetch request - //println!{"---------------------------"}; - //println!("the current buffer message is fetch done for {:?}", req); + println!{"---------------------------"}; + println!("the current buffer message is fetch done for {:?}", req); self.buffer.update_state(req, FrameStatus::Decoding); if !self.buffer.is_full() { @@ -238,8 +238,9 @@ impl BufferManager { } } BufMsg::PointCloud((mut metadata, mut rx)) => { - //println!{"---------------------------"}; - //println!("[buffer mgr] received a point cloud result {:?}", &metadata); + println!{"---------------------------"}; + println!("[buffer mgr] received a point cloud result {:?}", &metadata); + // When using PCMetaData::into(), there is no CameraPosition by default let orig_metadata: FrameRequest = metadata.into(); // Only update the frame state in buffer when the frame is still in the buffer if !self.buffer.is_empty() && self.buffer.is_frame_in_buffer(orig_metadata) { @@ -255,9 +256,11 @@ impl BufferManager { metadata.frame_offset += 1; remaining -= 1; } - // cache the point cloud if there is still point clouds to render + // Cache the point cloud if there is still point clouds to render self.buffer.update(orig_metadata, metadata.into(), FrameStatus::Ready(remaining, rx)); + // Store the metadata and assign default CameraPosition for the next frame. last_req = Some(orig_metadata); + last_req.unwrap().camera_pos = Some(CameraPosition::default()); } } } From afcabff6126d059520b19a058ec2b706ef791c28 Mon Sep 17 00:00:00 2001 From: tiif Date: Sat, 6 Jan 2024 02:46:51 +0800 Subject: [PATCH 07/12] Clean up println --- src/render/wgpu/reader.rs | 21 +++++++++++--- src/vvplay_async_prefetch/buffer_manager.rs | 32 ++++++++++----------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index 6f37224..e1321cb 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -34,6 +34,7 @@ pub trait RenderReaderCameraPos { fn len(&self) -> usize; fn is_empty(&self) -> bool; fn set_len(&mut self, len: usize); + fn set_cache_size(&mut self, size: usize); fn set_camera_state(&mut self, camera_state: Option); } @@ -127,7 +128,10 @@ impl RenderReaderCameraPos> for PointCloudFileReader { _camera_pos: Option, ) -> (Option, Option>) { let file_path = self.files.get(index).unwrap(); - (Some(CameraPosition::default()), read_file_to_point_cloud(file_path)) + ( + Some(CameraPosition::default()), + read_file_to_point_cloud(file_path), + ) } fn len(&self) -> usize { @@ -140,6 +144,8 @@ impl RenderReaderCameraPos> for PointCloudFileReader { fn set_len(&mut self, _len: usize) {} + fn set_cache_size(&mut self, size: usize) {} + fn set_camera_state(&mut self, _camera_state: Option) {} } @@ -204,7 +210,9 @@ impl RenderReader> for PcdMemoryReader { pub struct PcdAsyncReader { total_frames: u64, rx: Receiver<(FrameRequest, PointCloud)>, + //playback cache cache: Vec<(u64, PointCloud)>, + cache_size: usize, tx: UnboundedSender, } @@ -240,6 +248,7 @@ impl PcdAsyncReader { // buffer_size, // cache: HashMap::with_capacity(buffer_size as usize), cache: vec![], + cache_size: 10, //default number of size, Use `set_size` to overwrite this value total_frames: 30, // default number of frames. Use `set_len` to overwrite this value } } @@ -272,7 +281,7 @@ impl RenderReaderCameraPos> for PcdAsyncReader { camera_pos, })); if let Ok((frame_req, pc)) = self.rx.recv() { - if self.cache.len() >= 10 { + if self.cache.len() >= self.cache_size { self.cache.pop(); } //println!( @@ -298,6 +307,10 @@ impl RenderReaderCameraPos> for PcdAsyncReader { self.total_frames = len as u64; } + fn set_cache_size(&mut self, size: usize) { + self.cache_size = size; + } + fn set_camera_state(&mut self, _camera_state: Option) {} } @@ -307,8 +320,8 @@ impl RenderReader> for PcdAsyncReader { } fn get_at(&mut self, index: usize) -> Option> { - println!("----------------------------------"); - println!{"get at request index: {}", index}; + //println!("----------------------------------"); + //println!{"get at request index: {}", index}; let index = index as u64; // Everytime a request is made, find it from the playback cache first if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { diff --git a/src/vvplay_async_prefetch/buffer_manager.rs b/src/vvplay_async_prefetch/buffer_manager.rs index c337938..6cf029f 100644 --- a/src/vvplay_async_prefetch/buffer_manager.rs +++ b/src/vvplay_async_prefetch/buffer_manager.rs @@ -115,21 +115,21 @@ impl BufferManager { // Since we prefetch after a `FetchDone` event, once the buffer is full, we can't prefetch anymore. // So, we set this flag to true once the buffer is full, so that when the frames are consumed and the first channels are discarded, we can prefetch again. let mut is_desired_buffer_level_reached = false; - // last_req is only use for buffer size = 1, and it is update after the last PointCloud is received. + // last_req is only use for buffer size = 1, and it is update after the last PointCloud is received. let mut last_req: Option = None; loop { - println!{"---------------------------"}; - println!("buffer: {:?}", &self.buffer); - //This logic can be improved but it needs to be thoroughly tested. + //println!{"---------------------------"}; + //println!("buffer: {:?}", &self.buffer); + //This logic can be improved but it needs to be thoroughly tested. if !self.buffer.is_full() && !self.buffer.is_empty() { // This is executed when there is some frame inside the buffer, and the buffer is not full. - println!("---------------------------"); - println!{"buffer is not full neither empty, prefetching frame"}; + //println!("---------------------------"); + //println!{"buffer is not full neither empty, prefetching frame"}; self.prefetch_frame(Some(CameraPosition::default())); } else if self.buffer.is_empty() && last_req.is_some() { // If the buffer is currently empty, we continue to prefetch the frame, necessary for buffer size = 1 - println!{"---------------------------"}; - println!{"buffer is empty and there is last request, prefetching frame"}; + //println!{"---------------------------"}; + //println!{"buffer is empty and there is last request, prefetching frame"}; self.prefetch_frame_with_request( Some(last_req.unwrap().camera_pos.unwrap()), last_req.unwrap(), @@ -142,8 +142,8 @@ impl BufferManager { Some(msg) = self.to_buf_rx.recv() => { match msg { BufMsg::FrameRequest(mut renderer_req) => { - println!{"---------------------------"}; - println!{"[buffer mgr] renderer sent a frame request {:?}", &renderer_req}; + //println!{"---------------------------"}; + //println!{"[buffer mgr] renderer sent a frame request {:?}", &renderer_req}; if record_camera_trace.is_some() && renderer_req.camera_pos.is_some() { if let Some(ct) = record_camera_trace.as_mut() { ct.add(renderer_req.camera_pos.unwrap()) } } @@ -199,7 +199,7 @@ impl BufferManager { // we only reinsert it if there are more frames to render self.buffer.push_front(front); } else if !is_desired_buffer_level_reached { - println!("in FrameStatus::Ready::!is_desired_buffer_level_reached"); + //println!("in FrameStatus::Ready::!is_desired_buffer_level_reached"); //if the desired buffer level is not reached, should add in a new frame self.prefetch_frame(original_camera_pos); } @@ -226,8 +226,8 @@ impl BufferManager { } BufMsg::FetchDone(req) => { // upon receiving fetch result, immediately schedule the next fetch request - println!{"---------------------------"}; - println!("the current buffer message is fetch done for {:?}", req); + //println!{"---------------------------"}; + //println!("the current buffer message is fetch done for {:?}", req); self.buffer.update_state(req, FrameStatus::Decoding); if !self.buffer.is_full() { @@ -238,8 +238,8 @@ impl BufferManager { } } BufMsg::PointCloud((mut metadata, mut rx)) => { - println!{"---------------------------"}; - println!("[buffer mgr] received a point cloud result {:?}", &metadata); + //println!{"---------------------------"}; + //println!("[buffer mgr] received a point cloud result {:?}", &metadata); // When using PCMetaData::into(), there is no CameraPosition by default let orig_metadata: FrameRequest = metadata.into(); // Only update the frame state in buffer when the frame is still in the buffer @@ -258,7 +258,7 @@ impl BufferManager { } // Cache the point cloud if there is still point clouds to render self.buffer.update(orig_metadata, metadata.into(), FrameStatus::Ready(remaining, rx)); - // Store the metadata and assign default CameraPosition for the next frame. + // Store the metadata and assign default CameraPosition for the next frame. last_req = Some(orig_metadata); last_req.unwrap().camera_pos = Some(CameraPosition::default()); } From 30e003ffe8ce4de9f2ebe8e07789e35e6570c35e Mon Sep 17 00:00:00 2001 From: tiif Date: Tue, 9 Jan 2024 20:44:56 +0800 Subject: [PATCH 08/12] Added vvplay_async to README --- README.md | 64 ++++++++++++++++++++++++++++++- src/render/wgpu/reader.rs | 6 +-- src/vvplay_async_prefetch/args.rs | 3 -- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 63d3066..cebd06f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ 3. If you are using **linux**, make sure `gcc`, `g++`, `cmake`, `libssl-dev`, `pkg-config`, `libfontconfig1-dev` are installed 4. Compile and build the binaries with `cargo build --release --bins` 5. Install the binaries if you want to use it anywhere you want. `cargo install --path .` -6. Use `vv` and `vvplay` in other directory. Now you are good to go! +6. Use `vv`, `vvplay` and `vvplay_async` in other directory. Now you are good to go! 7. Download the [8i_dataset](https://plenodb.jpeg.org/pc/8ilabs/) to use and test our tool! ## Commands @@ -468,6 +468,68 @@ Options: -h, --help Print help ``` + +### `vvplay_async` + +Plays a folder of ply files in lexicographical order, leveraging prefetching and playback caching for optimized performance. A window will appear upon running the binary from which you can navigate using your mouse and keyboard. Controls are described further below. + +```shell +Usage: vvplay_async [OPTIONS] + +Arguments: + src can be: + +Options: + -f, --fps + [default: 30] + -x, --camera-x + [default: 0] + -y, --camera-y + [default: 0] + -z, --camera-z + [default: 1.5] + --pitch + [default: 0] + --yaw + [default: -90] + -W, --width + Set the screen width [default: 1600] + -H, --height + Set the screen height [default: 900] + --controls + + -b, --buffer-capacity + buffer capacity in seconds + -m, --metrics + + --abr + [default: quetra] [possible values: quetra, quetra-multiview, mckp] + --decoder + [default: noop] [possible values: noop, draco, tmc2rs] + --multiview + Set this flag if each view is encoded separately, i.e. multiview + --decoder-path + Path to the decoder binary (only for Draco) + --tp + [default: last] [possible values: last, avg, ema, gaema, lpema] + --throughput-alpha + Alpha for throughput prediction. Only used for EMA, GAEMA, and LPEMA [default: 0.1] + --vp + [default: last] [possible values: last] + --network-trace + Path to network trace for repeatable simulation. Network trace is expected to be given in Kbps + --camera-trace + Path to camera trace for repeatable simulation. Camera trace is expected to be given in (pos_x, pos_y, pos_z, rot_pitch, rot_yaw, rot_roll). Rotation is in degrees + --record-camera-trace + Path to record camera trace from the player + --enable-fetcher-optimizations + Enable fetcher optimizations + --bg-color + [default: rgb(255,255,255)] + -h, --help + Print help (see more with '--help') +``` + ### Controls With the main screen focused, diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index e1321cb..ab724ae 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -12,7 +12,7 @@ use tokio::sync::mpsc::UnboundedSender; use super::camera::{CameraPosition, CameraState}; use super::renderable::Renderable; -//RenderReader for the original RenderReader +//RenderReader for the original RenderReader used by vvplay pub trait RenderReader { fn start(&mut self) -> Option; fn get_at(&mut self, index: usize) -> Option; @@ -28,7 +28,7 @@ pub trait RenderReaderCameraPos { /// Returns the optional new camera position requested by the player backend and the `index`-th frame given the current camera position fn get_at( &mut self, - index: usize, + index: usize, camera_pos: Option, ) -> (Option, Option); fn len(&self) -> usize; @@ -144,7 +144,7 @@ impl RenderReaderCameraPos> for PointCloudFileReader { fn set_len(&mut self, _len: usize) {} - fn set_cache_size(&mut self, size: usize) {} + fn set_cache_size(&mut self, _size: usize) {} fn set_camera_state(&mut self, _camera_state: Option) {} } diff --git a/src/vvplay_async_prefetch/args.rs b/src/vvplay_async_prefetch/args.rs index f07ed21..59d71bd 100644 --- a/src/vvplay_async_prefetch/args.rs +++ b/src/vvplay_async_prefetch/args.rs @@ -6,9 +6,6 @@ use crate::vvplay_async_prefetch::enums::AbrType; use crate::vvplay_async_prefetch::enums::DecoderType; use crate::vvplay_async_prefetch::enums::ThroughputPredictionType; use crate::vvplay_async_prefetch::enums::ViewportPredictionType; -/** - * This file contains all the command line argumentfor vvplay_async_prefetch.rs - */ #[derive(Parser)] pub struct Args { From a9e705be4dd7a138c1a05e97a0ac5a35b58b52e3 Mon Sep 17 00:00:00 2001 From: tiif Date: Tue, 9 Jan 2024 20:47:18 +0800 Subject: [PATCH 09/12] Update README --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cebd06f..11fe704 100644 --- a/README.md +++ b/README.md @@ -517,9 +517,13 @@ Options: --vp [default: last] [possible values: last] --network-trace - Path to network trace for repeatable simulation. Network trace is expected to be given in Kbps + Path to network trace for repeatable simulation. + Network trace is expected to be given in Kbps --camera-trace - Path to camera trace for repeatable simulation. Camera trace is expected to be given in (pos_x, pos_y, pos_z, rot_pitch, rot_yaw, rot_roll). Rotation is in degrees + Path to camera trace for repeatable simulation. + Camera trace is expected to be given in + (pos_x, pos_y, pos_z, rot_pitch, rot_yaw, rot_roll). + Rotation is in degrees --record-camera-trace Path to record camera trace from the player --enable-fetcher-optimizations From cc94b2da4fd951f0435d53de4928b77233fe38be Mon Sep 17 00:00:00 2001 From: tiif Date: Tue, 9 Jan 2024 21:17:34 +0800 Subject: [PATCH 10/12] Transform vec to VecDeque --- src/render/wgpu/reader.rs | 26 +++++++++++---------- src/vvplay_async_prefetch/buffer_manager.rs | 4 ++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index ab724ae..bcad7bf 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -4,6 +4,7 @@ use crate::pcd::read_pcd_file; use crate::BufMsg; use crate::utils::read_file_to_point_cloud; +use std::collections::VecDeque; use std::fmt::Debug; use std::path::{Path, PathBuf}; use std::sync::mpsc::Receiver; @@ -211,7 +212,7 @@ pub struct PcdAsyncReader { total_frames: u64, rx: Receiver<(FrameRequest, PointCloud)>, //playback cache - cache: Vec<(u64, PointCloud)>, + cache: VecDeque<(u64, PointCloud)>, cache_size: usize, tx: UnboundedSender, } @@ -247,8 +248,8 @@ impl PcdAsyncReader { tx, // buffer_size, // cache: HashMap::with_capacity(buffer_size as usize), - cache: vec![], - cache_size: 10, //default number of size, Use `set_size` to overwrite this value + cache: VecDeque::new(), + cache_size: 10, //default number of size, Use `set_cache_size` to overwrite this value total_frames: 30, // default number of frames. Use `set_len` to overwrite this value } } @@ -265,10 +266,8 @@ impl RenderReaderCameraPos> for PcdAsyncReader { index: usize, camera_pos: Option, ) -> (Option, Option>) { - /* println!("----------------------------------"); println!{"get at request index: {}", index}; - */ let index = index as u64; if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { //if the result is already inside the cache, just return @@ -282,13 +281,13 @@ impl RenderReaderCameraPos> for PcdAsyncReader { })); if let Ok((frame_req, pc)) = self.rx.recv() { if self.cache.len() >= self.cache_size { - self.cache.pop(); + self.cache.pop_front(); } //println!( // "one frame is added to the point cloud cache: index:{}", // index //); - self.cache.push((index, pc.clone())); + self.cache.push_back((index, pc.clone())); (frame_req.camera_pos, Some(pc)) } else { (None, None) @@ -314,18 +313,21 @@ impl RenderReaderCameraPos> for PcdAsyncReader { fn set_camera_state(&mut self, _camera_state: Option) {} } +//This is used by vvplay_async impl RenderReader> for PcdAsyncReader { fn start(&mut self) -> Option> { RenderReader::get_at(self, 0) } fn get_at(&mut self, index: usize) -> Option> { - //println!("----------------------------------"); - //println!{"get at request index: {}", index}; + println!("----------------------------------"); + println!{"get at request index: {}", index}; let index = index as u64; // Everytime a request is made, find it from the playback cache first if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { //can improve this O(n) find algorithm in future + println!("----------------------------------"); + println!{"{} is found in the cache", index}; return Some(result.1.clone()); } // Send request to prepare for the frame @@ -337,10 +339,10 @@ impl RenderReader> for PcdAsyncReader { // Wait for the point cloud to be ready, cache it then return if let Ok((_frame_req, pc)) = self.rx.recv() { if self.cache.len() >= 10 { - self.cache.pop(); + self.cache.pop_front(); } - //println!("one frame is added to the point cloud cache: index:{}", index); - self.cache.push((index, pc.clone())); + println!("one frame is added to the point cloud cache: index:{}", index); + self.cache.push_back((index, pc.clone())); Some(pc) } else { None diff --git a/src/vvplay_async_prefetch/buffer_manager.rs b/src/vvplay_async_prefetch/buffer_manager.rs index 6cf029f..8d2d312 100644 --- a/src/vvplay_async_prefetch/buffer_manager.rs +++ b/src/vvplay_async_prefetch/buffer_manager.rs @@ -118,8 +118,8 @@ impl BufferManager { // last_req is only use for buffer size = 1, and it is update after the last PointCloud is received. let mut last_req: Option = None; loop { - //println!{"---------------------------"}; - //println!("buffer: {:?}", &self.buffer); + println!{"---------------------------"}; + println!("buffer: {:?}", &self.buffer); //This logic can be improved but it needs to be thoroughly tested. if !self.buffer.is_full() && !self.buffer.is_empty() { // This is executed when there is some frame inside the buffer, and the buffer is not full. From e524a8253813796c3767209eb424585a6296a159 Mon Sep 17 00:00:00 2001 From: tiif Date: Sun, 21 Jan 2024 19:14:46 +0800 Subject: [PATCH 11/12] Correct the buffer_capacity value --- src/bin/vvplay_async.rs | 3 ++- src/render/wgpu/reader.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bin/vvplay_async.rs b/src/bin/vvplay_async.rs index c884a37..248fbc2 100644 --- a/src/bin/vvplay_async.rs +++ b/src/bin/vvplay_async.rs @@ -109,7 +109,8 @@ fn main() { let (total_frames_tx, total_frames_rx) = tokio::sync::oneshot::channel(); // initialize variables based on args - let buffer_capacity = args.buffer_capacity.unwrap_or(11); + // the real buffer capacity is buffer capacity in seconds * fps + let buffer_capacity = args.buffer_capacity.unwrap_or(11) * args.fps as u64; let simulated_network_trace = args.network_trace.map(|path| NetworkTrace::new(&path)); let simulated_camera_trace = args.camera_trace.map(|path| CameraTrace::new(&path, false)); let record_camera_trace = args diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index bcad7bf..ac5ba2f 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -13,7 +13,7 @@ use tokio::sync::mpsc::UnboundedSender; use super::camera::{CameraPosition, CameraState}; use super::renderable::Renderable; -//RenderReader for the original RenderReader used by vvplay +// RenderReader for the original RenderReader used by vvplay pub trait RenderReader { fn start(&mut self) -> Option; fn get_at(&mut self, index: usize) -> Option; @@ -22,7 +22,7 @@ pub trait RenderReader { fn set_len(&mut self, len: usize); fn set_camera_state(&mut self, camera_state: Option); } -//RenderReaderCameraPos for the one with CameraPosition +// RenderReaderCameraPos for the one with CameraPosition pub trait RenderReaderCameraPos { /// Initialize the input reader for our renderer. Returns the first frame, if any. fn start(&mut self) -> (Option, Option); @@ -313,7 +313,7 @@ impl RenderReaderCameraPos> for PcdAsyncReader { fn set_camera_state(&mut self, _camera_state: Option) {} } -//This is used by vvplay_async +// This is used by vvplay_async impl RenderReader> for PcdAsyncReader { fn start(&mut self) -> Option> { RenderReader::get_at(self, 0) From ce07fbe60bd13501f6fba50715314acb6e49adb4 Mon Sep 17 00:00:00 2001 From: tiif Date: Tue, 26 Mar 2024 21:48:01 +0800 Subject: [PATCH 12/12] Run cargo fmt --- src/render/wgpu/reader.rs | 15 +++++++++------ src/vvplay_async_prefetch/buffer_manager.rs | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/render/wgpu/reader.rs b/src/render/wgpu/reader.rs index ac5ba2f..4d834d6 100644 --- a/src/render/wgpu/reader.rs +++ b/src/render/wgpu/reader.rs @@ -29,7 +29,7 @@ pub trait RenderReaderCameraPos { /// Returns the optional new camera position requested by the player backend and the `index`-th frame given the current camera position fn get_at( &mut self, - index: usize, + index: usize, camera_pos: Option, ) -> (Option, Option); fn len(&self) -> usize; @@ -267,7 +267,7 @@ impl RenderReaderCameraPos> for PcdAsyncReader { camera_pos: Option, ) -> (Option, Option>) { println!("----------------------------------"); - println!{"get at request index: {}", index}; + println! {"get at request index: {}", index}; let index = index as u64; if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { //if the result is already inside the cache, just return @@ -321,13 +321,13 @@ impl RenderReader> for PcdAsyncReader { fn get_at(&mut self, index: usize) -> Option> { println!("----------------------------------"); - println!{"get at request index: {}", index}; + println! {"get at request index: {}", index}; let index = index as u64; // Everytime a request is made, find it from the playback cache first if let Some(&ref result) = self.cache.iter().find(|&i| i.0 == index) { //can improve this O(n) find algorithm in future - println!("----------------------------------"); - println!{"{} is found in the cache", index}; + println!("----------------------------------"); + println! {"{} is found in the cache", index}; return Some(result.1.clone()); } // Send request to prepare for the frame @@ -341,7 +341,10 @@ impl RenderReader> for PcdAsyncReader { if self.cache.len() >= 10 { self.cache.pop_front(); } - println!("one frame is added to the point cloud cache: index:{}", index); + println!( + "one frame is added to the point cloud cache: index:{}", + index + ); self.cache.push_back((index, pc.clone())); Some(pc) } else { diff --git a/src/vvplay_async_prefetch/buffer_manager.rs b/src/vvplay_async_prefetch/buffer_manager.rs index 8d2d312..c3aa97b 100644 --- a/src/vvplay_async_prefetch/buffer_manager.rs +++ b/src/vvplay_async_prefetch/buffer_manager.rs @@ -118,7 +118,7 @@ impl BufferManager { // last_req is only use for buffer size = 1, and it is update after the last PointCloud is received. let mut last_req: Option = None; loop { - println!{"---------------------------"}; + println! {"---------------------------"}; println!("buffer: {:?}", &self.buffer); //This logic can be improved but it needs to be thoroughly tested. if !self.buffer.is_full() && !self.buffer.is_empty() {