1 use crate::global_trait::Marshal; 2 3 use super::global_trait::Unmarshal; 4 use super::rtsp_utils; 5 6 #[derive(Debug, Clone, Default, PartialEq)] 7 pub enum RtspRangeType { 8 #[default] 9 NPT, 10 CLOCK, 11 } 12 13 #[derive(Debug, Clone, Default)] 14 pub struct RtspRange { 15 range_type: RtspRangeType, 16 begin: i64, 17 end: Option<i64>, 18 } 19 20 impl Unmarshal for RtspRange { unmarshal(raw_data: &str) -> Option<Self>21 fn unmarshal(raw_data: &str) -> Option<Self> { 22 let mut rtsp_range = RtspRange::default(); 23 24 let kv: Vec<&str> = raw_data.splitn(2, '=').collect(); 25 if kv.len() < 2 { 26 return None; 27 } 28 29 match kv[0] { 30 "clock" => { 31 rtsp_range.range_type = RtspRangeType::CLOCK; 32 let ranges: Vec<&str> = kv[1].split('-').collect(); 33 34 let get_clock_time = |range_time: &str| -> i64 { 35 let datetime = 36 match chrono::NaiveDateTime::parse_from_str(range_time, "%Y%m%dT%H%M%SZ") { 37 Ok(dt) => dt, 38 Err(err) => { 39 println!("get_clock_time error: {err}"); 40 return -1; 41 } 42 }; 43 datetime.timestamp() 44 }; 45 46 rtsp_range.begin = get_clock_time(ranges[0]); 47 if ranges.len() > 1 { 48 rtsp_range.end = Some(get_clock_time(ranges[1])); 49 } 50 } 51 "npt" => { 52 rtsp_range.range_type = RtspRangeType::NPT; 53 let ranges: Vec<&str> = kv[1].split('-').collect(); 54 55 let get_npt_time = |range_time: &str| -> i64 { 56 if let (Some(hour), Some(minute), Some(second), mill) = 57 rtsp_utils::scanf!(range_time, |c| c == ':' || c == '.', i64, i64, i64, i64) 58 { 59 let mut result = (hour * 3600 + minute * 60 + second) * 1000; 60 if let Some(m) = mill { 61 result += m; 62 } 63 result 64 } else { 65 0 66 } 67 }; 68 69 match ranges[0] { 70 "now" => { 71 rtsp_range.begin = 0; 72 } 73 _ => { 74 rtsp_range.begin = get_npt_time(ranges[0]); 75 } 76 } 77 78 if ranges.len() == 2 && !ranges[1].is_empty() { 79 rtsp_range.end = Some(get_npt_time(ranges[1])); 80 } 81 } 82 _ => { 83 log::info!("{} not parsed..", kv[0]); 84 } 85 } 86 87 Some(rtsp_range) 88 } 89 } 90 91 impl Marshal for RtspRange { marshal(&self) -> String92 fn marshal(&self) -> String { 93 String::default() 94 } 95 } 96 97 #[cfg(test)] 98 mod tests { 99 100 use super::RtspRange; 101 use crate::global_trait::Unmarshal; 102 103 #[test] test_parse_transport()104 fn test_parse_transport() { 105 //a=range: 106 //a=range:npt=now- 107 //a=range:npt=0- 108 let parser = RtspRange::unmarshal("clock=20220520T064812Z-20230520T064816Z").unwrap(); 109 110 println!(" parser: {parser:?}"); 111 112 let parser1 = RtspRange::unmarshal("npt=now-").unwrap(); 113 114 println!(" parser1: {:?}, {}", parser1, parser1.end.is_none()); 115 116 let parser2 = RtspRange::unmarshal("npt=0-").unwrap(); 117 println!(" parser2: {:?}, {}", parser2, parser2.end.is_none()); 118 } 119 } 120