openigtlink_rust/protocol/types/
videometa.rs1use crate::error::{IgtlError, Result};
7use crate::protocol::message::Message;
8use bytes::{Buf, BufMut};
9
10use super::video::CodecType;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct VideoMetaMessage {
20 pub codec: CodecType,
22 pub width: u16,
24 pub height: u16,
26 pub framerate: u8,
28 pub bitrate: u32,
30}
31
32impl VideoMetaMessage {
33 pub fn new(codec: CodecType, width: u16, height: u16, framerate: u8, bitrate: u32) -> Self {
35 VideoMetaMessage {
36 codec,
37 width,
38 height,
39 framerate,
40 bitrate,
41 }
42 }
43
44 pub fn hd1080(codec: CodecType, framerate: u8, bitrate: u32) -> Self {
46 VideoMetaMessage {
47 codec,
48 width: 1920,
49 height: 1080,
50 framerate,
51 bitrate,
52 }
53 }
54
55 pub fn hd720(codec: CodecType, framerate: u8, bitrate: u32) -> Self {
57 VideoMetaMessage {
58 codec,
59 width: 1280,
60 height: 720,
61 framerate,
62 bitrate,
63 }
64 }
65
66 pub fn sd(codec: CodecType, framerate: u8, bitrate: u32) -> Self {
68 VideoMetaMessage {
69 codec,
70 width: 640,
71 height: 480,
72 framerate,
73 bitrate,
74 }
75 }
76
77 pub fn pixels_per_frame(&self) -> u32 {
79 self.width as u32 * self.height as u32
80 }
81
82 pub fn bandwidth_bps(&self) -> u32 {
84 self.bitrate * 1000 / 8 }
86}
87
88impl Message for VideoMetaMessage {
89 fn message_type() -> &'static str {
90 "VIDEOMETA"
91 }
92
93 fn encode_content(&self) -> Result<Vec<u8>> {
94 let mut buf = Vec::with_capacity(12);
95
96 buf.put_u8(self.codec as u8);
98
99 buf.put_u16(self.width);
101
102 buf.put_u16(self.height);
104
105 buf.put_u8(self.framerate);
107
108 buf.put_u32(self.bitrate);
110
111 buf.put_u16(0);
113
114 Ok(buf)
115 }
116
117 fn decode_content(mut data: &[u8]) -> Result<Self> {
118 if data.len() != 12 {
119 return Err(IgtlError::InvalidSize {
120 expected: 12,
121 actual: data.len(),
122 });
123 }
124
125 let codec = CodecType::from_u8(data.get_u8())?;
127
128 let width = data.get_u16();
130
131 let height = data.get_u16();
133
134 let framerate = data.get_u8();
136
137 let bitrate = data.get_u32();
139
140 let _reserved = data.get_u16();
142
143 Ok(VideoMetaMessage {
144 codec,
145 width,
146 height,
147 framerate,
148 bitrate,
149 })
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[test]
158 fn test_message_type() {
159 assert_eq!(VideoMetaMessage::message_type(), "VIDEOMETA");
160 }
161
162 #[test]
163 fn test_new() {
164 let meta = VideoMetaMessage::new(CodecType::H264, 1920, 1080, 30, 5000);
165
166 assert_eq!(meta.codec, CodecType::H264);
167 assert_eq!(meta.width, 1920);
168 assert_eq!(meta.height, 1080);
169 assert_eq!(meta.framerate, 30);
170 assert_eq!(meta.bitrate, 5000);
171 }
172
173 #[test]
174 fn test_hd1080() {
175 let meta = VideoMetaMessage::hd1080(CodecType::H264, 60, 10000);
176
177 assert_eq!(meta.width, 1920);
178 assert_eq!(meta.height, 1080);
179 assert_eq!(meta.framerate, 60);
180 }
181
182 #[test]
183 fn test_hd720() {
184 let meta = VideoMetaMessage::hd720(CodecType::VP9, 30, 3000);
185
186 assert_eq!(meta.width, 1280);
187 assert_eq!(meta.height, 720);
188 }
189
190 #[test]
191 fn test_sd() {
192 let meta = VideoMetaMessage::sd(CodecType::MJPEG, 25, 1000);
193
194 assert_eq!(meta.width, 640);
195 assert_eq!(meta.height, 480);
196 }
197
198 #[test]
199 fn test_pixels_per_frame() {
200 let meta = VideoMetaMessage::new(CodecType::H264, 100, 100, 30, 1000);
201 assert_eq!(meta.pixels_per_frame(), 10000);
202 }
203
204 #[test]
205 fn test_bandwidth_bps() {
206 let meta = VideoMetaMessage::new(CodecType::H264, 1920, 1080, 30, 8000);
207 assert_eq!(meta.bandwidth_bps(), 1000000);
209 }
210
211 #[test]
212 fn test_encode() {
213 let meta = VideoMetaMessage::new(CodecType::H264, 1920, 1080, 30, 5000);
214 let encoded = meta.encode_content().unwrap();
215
216 assert_eq!(encoded.len(), 12);
217 assert_eq!(encoded[0], CodecType::H264 as u8);
218 }
219
220 #[test]
221 fn test_roundtrip() {
222 let original = VideoMetaMessage::new(CodecType::H264, 1920, 1080, 30, 5000);
223
224 let encoded = original.encode_content().unwrap();
225 let decoded = VideoMetaMessage::decode_content(&encoded).unwrap();
226
227 assert_eq!(decoded.codec, original.codec);
228 assert_eq!(decoded.width, original.width);
229 assert_eq!(decoded.height, original.height);
230 assert_eq!(decoded.framerate, original.framerate);
231 assert_eq!(decoded.bitrate, original.bitrate);
232 }
233
234 #[test]
235 fn test_roundtrip_vp9() {
236 let original = VideoMetaMessage::hd720(CodecType::VP9, 60, 4000);
237
238 let encoded = original.encode_content().unwrap();
239 let decoded = VideoMetaMessage::decode_content(&encoded).unwrap();
240
241 assert_eq!(decoded.codec, CodecType::VP9);
242 assert_eq!(decoded.width, 1280);
243 assert_eq!(decoded.height, 720);
244 assert_eq!(decoded.framerate, 60);
245 }
246
247 #[test]
248 fn test_decode_invalid_size() {
249 let data = vec![0u8; 11]; let result = VideoMetaMessage::decode_content(&data);
251 assert!(result.is_err());
252 }
253
254 #[test]
255 fn test_decode_too_long() {
256 let data = vec![0u8; 13]; let result = VideoMetaMessage::decode_content(&data);
258 assert!(result.is_err());
259 }
260
261 #[test]
262 fn test_decode_invalid_codec() {
263 let mut data = vec![0u8; 12];
264 data[0] = 99; let result = VideoMetaMessage::decode_content(&data);
266 assert!(result.is_err());
267 }
268}