1 use crate::global_trait::{Marshal, Unmarshal}; 2 use base64::{engine::general_purpose, Engine as _}; 3 use bytes::{BufMut, BytesMut}; 4 5 // pub trait Fmtp: TMsgConverter {} 6 7 #[derive(Debug, Clone, Default)] 8 pub struct H264Fmtp { 9 pub payload_type: u16, 10 packetization_mode: u8, 11 profile_level_id: BytesMut, 12 pub sps: BytesMut, 13 pub pps: BytesMut, 14 } 15 #[derive(Debug, Clone, Default)] 16 pub struct H265Fmtp { 17 pub payload_type: u16, 18 pub vps: BytesMut, 19 pub sps: BytesMut, 20 pub pps: BytesMut, 21 } 22 #[derive(Debug, Clone, Default)] 23 pub struct Mpeg4Fmtp { 24 pub payload_type: u16, 25 pub asc: BytesMut, 26 profile_level_id: BytesMut, 27 mode: String, 28 size_length: u16, 29 index_length: u16, 30 index_delta_length: u16, 31 } 32 #[derive(Debug, Clone)] 33 pub enum Fmtp { 34 H264(H264Fmtp), 35 H265(H265Fmtp), 36 Mpeg4(Mpeg4Fmtp), 37 } 38 39 impl Fmtp { new(codec: &str, raw_data: &str) -> Option<Fmtp>40 pub fn new(codec: &str, raw_data: &str) -> Option<Fmtp> { 41 match codec.to_lowercase().as_str() { 42 "h264" => { 43 if let Some(h264_fmtp) = H264Fmtp::unmarshal(raw_data) { 44 return Some(Fmtp::H264(h264_fmtp)); 45 } 46 } 47 "h265" => { 48 if let Some(h265_fmtp) = H265Fmtp::unmarshal(raw_data) { 49 return Some(Fmtp::H265(h265_fmtp)); 50 } 51 } 52 "mpeg4-generic" => { 53 if let Some(mpeg4_fmtp) = Mpeg4Fmtp::unmarshal(raw_data) { 54 return Some(Fmtp::Mpeg4(mpeg4_fmtp)); 55 } 56 } 57 _ => {} 58 } 59 None 60 } 61 marshal(&self) -> String62 pub fn marshal(&self) -> String { 63 match self { 64 Fmtp::H264(h264fmtp) => h264fmtp.marshal(), 65 Fmtp::H265(h265fmtp) => h265fmtp.marshal(), 66 Fmtp::Mpeg4(mpeg4fmtp) => mpeg4fmtp.marshal(), 67 } 68 } 69 } 70 71 // a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAFqyyAUBf8uAiAAADAAIAAAMAPB4sXJA=,aOvDyyLA; profile-level-id=640016 72 impl Unmarshal for H264Fmtp { unmarshal(raw_data: &str) -> Option<Self>73 fn unmarshal(raw_data: &str) -> Option<Self> { 74 let mut h264_fmtp = H264Fmtp::default(); 75 let eles: Vec<&str> = raw_data.splitn(2, ' ').collect(); 76 if eles.len() < 2 { 77 log::warn!("H264FmtpSdp parse err: {}", raw_data); 78 return None; 79 } 80 81 if let Ok(payload_type) = eles[0].parse::<u16>() { 82 h264_fmtp.payload_type = payload_type; 83 } 84 85 let parameters: Vec<&str> = eles[1].split(';').collect(); 86 for parameter in parameters { 87 let kv: Vec<&str> = parameter.trim().splitn(2, '=').collect(); 88 if kv.len() < 2 { 89 log::warn!("H264FmtpSdp parse key=value err: {}", parameter); 90 continue; 91 } 92 match kv[0] { 93 "packetization-mode" => { 94 if let Ok(packetization_mode) = kv[1].parse::<u8>() { 95 h264_fmtp.packetization_mode = packetization_mode; 96 } 97 } 98 "sprop-parameter-sets" => { 99 let spspps: Vec<&str> = kv[1].split(',').collect(); 100 let sps = general_purpose::STANDARD.decode(spspps[0]).unwrap(); 101 h264_fmtp.sps.put(&sps[..]); 102 let pps = general_purpose::STANDARD.decode(spspps[1]).unwrap(); 103 h264_fmtp.pps.put(&pps[..]); 104 } 105 "profile-level-id" => { 106 h264_fmtp.profile_level_id = kv[1].into(); 107 } 108 _ => { 109 log::info!("not parsed: {}", kv[0]) 110 } 111 } 112 } 113 114 Some(h264_fmtp) 115 } 116 } 117 118 impl Marshal for H264Fmtp { 119 // a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAFqyyAUBf8uAiAAADAAIAAAMAPB4sXJA=,aOvDyyLA; profile-level-id=640016 marshal(&self) -> String120 fn marshal(&self) -> String { 121 let sps_str = general_purpose::STANDARD.encode(&self.sps); 122 let pps_str = general_purpose::STANDARD.encode(&self.pps); 123 let profile_level_id_str = String::from_utf8(self.profile_level_id.to_vec()).unwrap(); 124 125 let h264_fmtp = format!( 126 "{} packetization-mode={}; sprop-parameter-sets={},{}; profile-level-id={}", 127 self.payload_type, self.packetization_mode, sps_str, pps_str, profile_level_id_str 128 ); 129 130 format!("{h264_fmtp}\r\n") 131 } 132 } 133 134 impl Unmarshal for H265Fmtp { 135 //"a=fmtp:96 sprop-vps=QAEMAf//AWAAAAMAkAAAAwAAAwA/ugJA; sprop-sps=QgEBAWAAAAMAkAAAAwAAAwA/oAUCAXHy5bpKTC8BAQAAAwABAAADAA8I; sprop-pps=RAHAc8GJ" unmarshal(raw_data: &str) -> Option<Self>136 fn unmarshal(raw_data: &str) -> Option<Self> { 137 let mut h265_fmtp = H265Fmtp::default(); 138 let eles: Vec<&str> = raw_data.splitn(2, ' ').collect(); 139 if eles.len() < 2 { 140 log::warn!("H265FmtpSdp parse err: {}", raw_data); 141 return None; 142 } 143 144 if let Ok(payload_type) = eles[0].parse::<u16>() { 145 h265_fmtp.payload_type = payload_type; 146 } 147 148 let parameters: Vec<&str> = eles[1].split(';').collect(); 149 for parameter in parameters { 150 let kv: Vec<&str> = parameter.trim().splitn(2, '=').collect(); 151 if kv.len() < 2 { 152 log::warn!("H265FmtpSdp parse key=value err: {}", parameter); 153 continue; 154 } 155 156 match kv[0] { 157 "sprop-vps" => { 158 h265_fmtp.vps = kv[1].into(); 159 } 160 "sprop-sps" => { 161 h265_fmtp.sps = kv[1].into(); 162 } 163 "sprop-pps" => { 164 h265_fmtp.pps = kv[1].into(); 165 } 166 _ => { 167 log::info!("not parsed: {}", kv[0]) 168 } 169 } 170 } 171 172 Some(h265_fmtp) 173 } 174 } 175 176 impl Marshal for H265Fmtp { 177 //"a=fmtp:96 sprop-vps=QAEMAf//AWAAAAMAkAAAAwAAAwA/ugJA; sprop-sps=QgEBAWAAAAMAkAAAAwAAAwA/oAUCAXHy5bpKTC8BAQAAAwABAAADAA8I; sprop-pps=RAHAc8GJ" marshal(&self) -> String178 fn marshal(&self) -> String { 179 let sps_str = String::from_utf8(self.sps.to_vec()).unwrap(); 180 let pps_str = String::from_utf8(self.pps.to_vec()).unwrap(); 181 let vps_str = String::from_utf8(self.vps.to_vec()).unwrap(); 182 183 let h265_fmtp = format!( 184 "{} sprop-vps={}; sprop-sps={}; sprop-pps={}", 185 self.payload_type, vps_str, sps_str, pps_str 186 ); 187 188 format!("{h265_fmtp}\r\n") 189 } 190 } 191 192 impl Unmarshal for Mpeg4Fmtp { 193 //a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=121056e500 unmarshal(raw_data: &str) -> Option<Self>194 fn unmarshal(raw_data: &str) -> Option<Self> { 195 let mut mpeg4_fmtp = Mpeg4Fmtp::default(); 196 let eles: Vec<&str> = raw_data.splitn(2, ' ').collect(); 197 if eles.len() < 2 { 198 log::warn!("Mpeg4FmtpSdp parse err: {}", raw_data); 199 return None; 200 } 201 202 if let Ok(payload_type) = eles[0].parse::<u16>() { 203 mpeg4_fmtp.payload_type = payload_type; 204 } 205 206 let parameters: Vec<&str> = eles[1].split(';').collect(); 207 for parameter in parameters { 208 let kv: Vec<&str> = parameter.trim().splitn(2, '=').collect(); 209 if kv.len() < 2 { 210 log::warn!("Mpeg4FmtpSdp parse key=value err: {}", parameter); 211 continue; 212 } 213 match kv[0].to_lowercase().as_str() { 214 "mode" => { 215 mpeg4_fmtp.mode = kv[1].to_string(); 216 } 217 "config" => { 218 let asc = hex::decode(kv[1]).unwrap(); 219 mpeg4_fmtp.asc.put(&asc[..]); 220 } 221 "profile-level-id" => { 222 mpeg4_fmtp.profile_level_id = kv[1].into(); 223 } 224 "sizelength" => { 225 if let Ok(size_length) = kv[1].parse::<u16>() { 226 mpeg4_fmtp.size_length = size_length; 227 } 228 } 229 "indexlength" => { 230 if let Ok(index_length) = kv[1].parse::<u16>() { 231 mpeg4_fmtp.index_length = index_length; 232 } 233 } 234 "indexdeltalength" => { 235 if let Ok(index_delta_length) = kv[1].parse::<u16>() { 236 mpeg4_fmtp.index_delta_length = index_delta_length; 237 } 238 } 239 _ => { 240 log::info!("not parsed: {}", kv[0]) 241 } 242 } 243 } 244 245 Some(mpeg4_fmtp) 246 } 247 } 248 249 impl Marshal for Mpeg4Fmtp { 250 //a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=121056e500 marshal(&self) -> String251 fn marshal(&self) -> String { 252 let profile_level_id_str = String::from_utf8(self.profile_level_id.to_vec()).unwrap(); 253 let asc_str = hex::encode(&self.asc); //String::from_utf8(self.asc.to_vec()).unwrap(); 254 255 let mpeg4_fmtp = format!( 256 "{} profile-level-id={};mode={};sizelength={};indexlength={};indexdeltalength={}; config={}", 257 self.payload_type, profile_level_id_str, self.mode, self.size_length, self.index_length, 258 self.index_delta_length,asc_str); 259 260 format!("{mpeg4_fmtp}\r\n") 261 } 262 } 263 264 #[cfg(test)] 265 mod tests { 266 267 use bytes::BytesMut; 268 269 use super::H264Fmtp; 270 use super::H265Fmtp; 271 use super::Mpeg4Fmtp; 272 use crate::global_trait::Marshal; 273 use crate::global_trait::Unmarshal; 274 use crate::rtsp_utils; 275 276 #[test] test_parse_h264fmtpsdp()277 fn test_parse_h264fmtpsdp() { 278 let parser = H264Fmtp::unmarshal("96 packetization-mode=1; sprop-parameter-sets=Z2QAFqyyAUBf8uAiAAADAAIAAAMAPB4sXJA=,aOvDyyLA; profile-level-id=640016").unwrap(); 279 280 println!(" parser: {parser:?}"); 281 282 assert_eq!(parser.packetization_mode, 1); 283 assert_eq!(parser.profile_level_id, "640016"); 284 // assert_eq!(parser.sps, "Z2QAFqyyAUBf8uAiAAADAAIAAAMAPB4sXJA="); 285 // assert_eq!(parser.pps, "aOvDyyLA"); 286 //"96 packetization-mode=1; sprop-parameter-sets=Z2QAFqyyAUBf8uAiAAADAAIAAAMAPB4sXJA=,aOvDyyLA; profile-level-id=640016" 287 288 print!("264 parser: {}", parser.marshal()); 289 290 let parser2 = H264Fmtp::unmarshal("96 packetization-mode=1;\nsprop-parameter-sets=Z2QAFqyyAUBf8uAiAAADAAIAAAMAPB4sXJA=,aOvDyyLA;\nprofile-level-id=640016").unwrap(); 291 292 println!(" parser: {parser2:?}"); 293 294 assert_eq!(parser2.packetization_mode, 1); 295 assert_eq!(parser2.profile_level_id, "640016"); 296 // assert_eq!(parser2.sps, "Z2QAFqyyAUBf8uAiAAADAAIAAAMAPB4sXJA="); 297 // assert_eq!(parser2.pps, "aOvDyyLA"); 298 299 print!("264 parser2: {}", parser2.marshal()); 300 } 301 #[test] test_parse_h265fmtpsdp()302 fn test_parse_h265fmtpsdp() { 303 let parser = H265Fmtp::unmarshal("96 sprop-vps=QAEMAf//AWAAAAMAkAAAAwAAAwA/ugJA; sprop-sps=QgEBAWAAAAMAkAAAAwAAAwA/oAUCAXHy5bpKTC8BAQAAAwABAAADAA8I; sprop-pps=RAHAc8GJ").unwrap(); 304 305 println!(" parser: {parser:?}"); 306 307 assert_eq!(parser.vps, "QAEMAf//AWAAAAMAkAAAAwAAAwA/ugJA"); 308 assert_eq!( 309 parser.sps, 310 "QgEBAWAAAAMAkAAAAwAAAwA/oAUCAXHy5bpKTC8BAQAAAwABAAADAA8I" 311 ); 312 assert_eq!(parser.pps, "RAHAc8GJ"); 313 314 print!("265 parser: {}", parser.marshal()); 315 } 316 317 #[test] test_parse_mpeg4fmtpsdp()318 fn test_parse_mpeg4fmtpsdp() { 319 let parser = Mpeg4Fmtp::unmarshal("97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=23; config=121056e500").unwrap(); 320 321 println!(" parser: {parser:?}"); 322 let en_asc = hex::encode(parser.asc.clone()); 323 324 assert_eq!(en_asc, "121056e500"); 325 assert_eq!(parser.profile_level_id, "1"); 326 assert_eq!(parser.mode, "AAC-hbr"); 327 assert_eq!(parser.size_length, 13); 328 assert_eq!(parser.index_length, 3); 329 assert_eq!(parser.index_delta_length, 23); 330 331 print!("mpeg4 parser: {}", parser.marshal()); 332 } 333 334 #[test] test_string()335 fn test_string() { 336 let s = String::from("119056E500"); 337 let ss = hex::decode(s).unwrap(); 338 let b = BytesMut::from(&ss[..]); 339 340 rtsp_utils::print("test", b); 341 } 342 } 343