Skip to main content

dynlink_nvidia_encode/
queue.rs

1// Copyright (C) The Strand-Braid Authors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4/// A data structure for handling a queue of frames to be processed.
5///
6/// Circular buffer with a leading index ("available") and
7/// a potentially lagging index ("pending"). Get an available item and then,
8///
9/// modeled after CNvQueue in nvidia Samples in Video Codec SDK
10#[expect(non_snake_case)]
11pub struct Queue<T> {
12    m_pBuffer: Vec<T>,
13    m_uPendingCount: usize,
14    m_uAvailableIdx: usize,
15    m_uPendingndex: usize,
16}
17
18#[expect(non_snake_case)]
19impl<T> Queue<T> {
20    #[expect(non_snake_case)]
21    pub fn new(pBuffer: Vec<T>) -> Self {
22        Self {
23            m_pBuffer: pBuffer,
24            m_uPendingCount: 0,
25            m_uAvailableIdx: 0,
26            m_uPendingndex: 0,
27        }
28    }
29
30    pub fn get_available(&mut self) -> Option<&mut T> {
31        let sz = self.m_pBuffer.len();
32        if self.m_uPendingCount == sz {
33            None
34        } else {
35            let pItem = &mut self.m_pBuffer[self.m_uAvailableIdx];
36            self.m_uAvailableIdx = (self.m_uAvailableIdx + 1) % sz;
37            self.m_uPendingCount += 1;
38            Some(pItem)
39        }
40    }
41
42    pub fn get_pending(&mut self) -> Option<&mut T> {
43        let sz = self.m_pBuffer.len();
44        if self.m_uPendingCount == 0 {
45            None
46        } else {
47            let pItem = &mut self.m_pBuffer[self.m_uPendingndex];
48            self.m_uPendingndex = (self.m_uPendingndex + 1) % sz;
49            self.m_uPendingCount -= 1;
50            Some(pItem)
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use crate::queue::Queue;
58
59    #[test]
60    fn test_queue() {
61        let items = vec![
62            "Buffer 1".to_string(),
63            "Buffer 2".to_string(),
64            "Buffer 3".to_string(),
65        ];
66        {
67            let mut q = Queue::new(items);
68
69            assert!(q.get_pending().is_none());
70
71            let i1 = q.get_available().unwrap();
72            println!("i1 {:?}", i1);
73
74            *i1 = "Buffer 1 modified".to_string();
75
76            let i2 = q.get_available().unwrap();
77            println!("i2 {:?}", i2);
78
79            let i3 = q.get_available().unwrap();
80            println!("i3 {:?}", i3);
81
82            assert!(q.get_available().is_none());
83
84            let p1 = q.get_pending().unwrap();
85            println!("p1 {:?}", p1);
86
87            assert_eq!(p1.as_str(), "Buffer 1 modified");
88        }
89    }
90}