1use tokio::{spawn, task};
2use tokio::sync::mpsc;
3use tokio::net::UdpSocket;
4use bytebuffer::ByteBuffer;
5
6use crate::errors::Result;
7
8pub const VIDEO_WIDTH:u32 = 960;
9pub const VIDEO_HEIGHT:u32 = 720;
10
11const VIDEO_UDP_PORT:u32 = 11111;
12const MAX_CHUNK_SIZE:usize = 1460;
13
14
15pub type TelloVideoSender = mpsc::UnboundedSender<TelloVideoFrame>;
16pub type TelloVideoReceiver = mpsc::UnboundedReceiver<TelloVideoFrame>;
17
18pub fn make_tello_video_channel() -> (TelloVideoSender, TelloVideoReceiver) {
19 mpsc::unbounded_channel()
20}
21
22#[derive(Debug)]
24pub struct TelloVideoFrame {
25 pub data: Vec<u8>
26}
27
28#[derive(Debug)]
29pub(crate) struct VideoListener {
30 task: task::JoinHandle<()>
31}
32
33impl VideoListener {
34 pub(crate) async fn start_listening(sender:TelloVideoSender) -> Result<Self> {
35 let local_address = format!("0.0.0.0:{VIDEO_UDP_PORT}");
36 println!("[Video] START LISTENING at {local_address}");
37
38 let sock = UdpSocket::bind(&local_address).await?;
39
40 let task = spawn(async move {
41 let mut buf = ByteBuffer::new();
42 loop {
43 let s = &sock;
44 let mut chunk = vec![0; MAX_CHUNK_SIZE]; let n = s.recv(&mut chunk).await.unwrap();
46 if n != 0 {
47 buf.write_bytes(&chunk);
48
49 if n < MAX_CHUNK_SIZE {
50 let frame = TelloVideoFrame { data: buf.into_vec() };
51 sender.send(frame).unwrap();
52 buf = ByteBuffer::new();
53 }
54 }
55 }
56 });
57
58 Ok(Self { task })
59 }
60
61 pub(crate) async fn stop_listening(&self) -> Result<()> {
62 println!("[Video] STOP LISTENING");
63 self.task.abort();
64 Ok(())
67 }
68 }