1 use super::*; 2 use crate::error::Result; 3 use rtcp::packet::Packet; 4 use util::Marshal; 5 6 #[test] 7 fn test_chunk_add() -> Result<()> { 8 //"fill with not received" 9 { 10 let mut c = Chunk::default(); 11 12 for i in 0..MAX_RUN_LENGTH_CAP { 13 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16), "{}", i); 14 c.add(SymbolTypeTcc::PacketNotReceived as u16); 15 } 16 assert_eq!(vec![0u16; MAX_RUN_LENGTH_CAP], c.deltas); 17 assert!(!c.has_different_types); 18 19 assert!(!c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 20 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16)); 21 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 22 23 let status_chunk = c.encode(); 24 match status_chunk { 25 PacketStatusChunk::RunLengthChunk(_) => assert!(true), 26 _ => assert!(false), 27 }; 28 29 let buf = status_chunk.marshal()?; 30 assert_eq!(&[0x1f, 0xff], &buf[..]); 31 } 32 33 //"fill with small delta" 34 { 35 let mut c = Chunk::default(); 36 37 for i in 0..MAX_ONE_BIT_CAP { 38 assert!( 39 c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16), 40 "{}", 41 i 42 ); 43 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16); 44 } 45 46 assert_eq!(c.deltas, vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); 47 assert!(!c.has_different_types); 48 49 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 50 assert!(!c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 51 52 let status_chunk = c.encode(); 53 match status_chunk { 54 PacketStatusChunk::RunLengthChunk(_) => assert!(true), 55 _ => assert!(false), 56 }; 57 58 let buf = status_chunk.marshal()?; 59 assert_eq!(&[0x20, 0xe], &buf[..]); 60 } 61 62 //"fill with large delta" 63 { 64 let mut c = Chunk::default(); 65 66 for i in 0..MAX_TWO_BIT_CAP { 67 assert!( 68 c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16), 69 "{}", 70 i 71 ); 72 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16); 73 } 74 75 assert_eq!(c.deltas, vec![2, 2, 2, 2, 2, 2, 2]); 76 assert!(c.has_large_delta); 77 assert!(!c.has_different_types); 78 79 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16)); 80 assert!(!c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 81 82 let status_chunk = c.encode(); 83 match status_chunk { 84 PacketStatusChunk::RunLengthChunk(_) => assert!(true), 85 _ => assert!(false), 86 }; 87 88 let buf = status_chunk.marshal()?; 89 assert_eq!(&[0x40, 0x7], &buf[..]); 90 } 91 92 // "fill with different types" 93 { 94 let mut c = Chunk::default(); 95 96 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16)); 97 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16); 98 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16)); 99 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16); 100 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16)); 101 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16); 102 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16)); 103 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16); 104 105 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 106 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16); 107 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 108 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16); 109 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 110 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16); 111 112 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 113 114 let status_chunk = c.encode(); 115 match status_chunk { 116 PacketStatusChunk::StatusVectorChunk(_) => assert!(true), 117 _ => assert!(false), 118 }; 119 120 let buf = status_chunk.marshal()?; 121 assert_eq!(&[0xd5, 0x6a], &buf[..]); 122 } 123 124 //"overfill and encode" 125 { 126 let mut c = Chunk::default(); 127 128 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16)); 129 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16); 130 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 131 c.add(SymbolTypeTcc::PacketNotReceived as u16); 132 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 133 c.add(SymbolTypeTcc::PacketNotReceived as u16); 134 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 135 c.add(SymbolTypeTcc::PacketNotReceived as u16); 136 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 137 c.add(SymbolTypeTcc::PacketNotReceived as u16); 138 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 139 c.add(SymbolTypeTcc::PacketNotReceived as u16); 140 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 141 c.add(SymbolTypeTcc::PacketNotReceived as u16); 142 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16)); 143 c.add(SymbolTypeTcc::PacketNotReceived as u16); 144 145 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 146 147 let status_chunk1 = c.encode(); 148 match status_chunk1 { 149 PacketStatusChunk::StatusVectorChunk(_) => assert!(true), 150 _ => assert!(false), 151 }; 152 assert_eq!(1, c.deltas.len()); 153 154 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16)); 155 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16); 156 157 let status_chunk2 = c.encode(); 158 match status_chunk2 { 159 PacketStatusChunk::StatusVectorChunk(_) => assert!(true), 160 _ => assert!(false), 161 }; 162 assert_eq!(0, c.deltas.len()); 163 164 assert_eq!( 165 PacketStatusChunk::StatusVectorChunk(StatusVectorChunk { 166 type_tcc: StatusChunkTypeTcc::StatusVectorChunk, 167 symbol_size: SymbolSizeTypeTcc::TwoBit, 168 symbol_list: vec![ 169 SymbolTypeTcc::PacketNotReceived, 170 SymbolTypeTcc::PacketReceivedLargeDelta 171 ], 172 }), 173 status_chunk2 174 ); 175 } 176 177 Ok(()) 178 } 179 180 #[test] 181 fn test_feedback() -> Result<()> { 182 //"add simple" 183 { 184 let mut f = Feedback::default(); 185 let got = f.add_received(0, 10); 186 assert!(got); 187 } 188 189 //"add too large" 190 { 191 let mut f = Feedback::default(); 192 193 assert!(!f.add_received(12, 8200 * 1000 * 250)); 194 } 195 196 // "add received 1" 197 { 198 let mut f = Feedback::default(); 199 f.set_base(1, 1000 * 1000); 200 201 let got = f.add_received(1, 1023 * 1000); 202 203 assert!(got); 204 assert_eq!(2, f.next_sequence_number); 205 assert_eq!(15, f.ref_timestamp64ms); 206 207 let got = f.add_received(4, 1086 * 1000); 208 assert!(got); 209 assert_eq!(5, f.next_sequence_number); 210 assert_eq!(15, f.ref_timestamp64ms); 211 212 assert!(f.last_chunk.has_different_types); 213 assert_eq!(4, f.last_chunk.deltas.len()); 214 assert!(!f 215 .last_chunk 216 .deltas 217 .contains(&(SymbolTypeTcc::PacketReceivedLargeDelta as u16))); 218 } 219 220 //"add received 2" 221 { 222 let mut f = Feedback::new(0, 0, 0); 223 f.set_base(5, 320 * 1000); 224 225 let mut got = f.add_received(5, 320 * 1000); 226 assert!(got); 227 got = f.add_received(7, 448 * 1000); 228 assert!(got); 229 got = f.add_received(8, 512 * 1000); 230 assert!(got); 231 got = f.add_received(11, 768 * 1000); 232 assert!(got); 233 234 let pkt = f.get_rtcp(); 235 236 assert!(pkt.header().padding); 237 assert_eq!(7, pkt.header().length); 238 assert_eq!(5, pkt.base_sequence_number); 239 assert_eq!(7, pkt.packet_status_count); 240 assert_eq!(5, pkt.reference_time); 241 assert_eq!(0, pkt.fb_pkt_count); 242 assert_eq!(1, pkt.packet_chunks.len()); 243 244 assert_eq!( 245 vec![PacketStatusChunk::StatusVectorChunk(StatusVectorChunk { 246 type_tcc: StatusChunkTypeTcc::StatusVectorChunk, 247 symbol_size: SymbolSizeTypeTcc::TwoBit, 248 symbol_list: vec![ 249 SymbolTypeTcc::PacketReceivedSmallDelta, 250 SymbolTypeTcc::PacketNotReceived, 251 SymbolTypeTcc::PacketReceivedLargeDelta, 252 SymbolTypeTcc::PacketReceivedLargeDelta, 253 SymbolTypeTcc::PacketNotReceived, 254 SymbolTypeTcc::PacketNotReceived, 255 SymbolTypeTcc::PacketReceivedLargeDelta, 256 ], 257 })], 258 pkt.packet_chunks 259 ); 260 261 let expected_deltas = vec![ 262 RecvDelta { 263 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 264 delta: 0, 265 }, 266 RecvDelta { 267 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta, 268 delta: 0x0200 * TYPE_TCC_DELTA_SCALE_FACTOR, 269 }, 270 RecvDelta { 271 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta, 272 delta: 0x0100 * TYPE_TCC_DELTA_SCALE_FACTOR, 273 }, 274 RecvDelta { 275 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta, 276 delta: 0x0400 * TYPE_TCC_DELTA_SCALE_FACTOR, 277 }, 278 ]; 279 assert_eq!(expected_deltas.len(), pkt.recv_deltas.len()); 280 for (i, d) in expected_deltas.iter().enumerate() { 281 assert_eq!(d, &pkt.recv_deltas[i]); 282 } 283 } 284 285 //"add received wrapped sequence number" 286 { 287 let mut f = Feedback::new(0, 0, 0); 288 f.set_base(65535, 320 * 1000); 289 290 let mut got = f.add_received(65535, 320 * 1000); 291 assert!(got); 292 got = f.add_received(7, 448 * 1000); 293 assert!(got); 294 got = f.add_received(8, 512 * 1000); 295 assert!(got); 296 got = f.add_received(11, 768 * 1000); 297 assert!(got); 298 299 let pkt = f.get_rtcp(); 300 301 assert!(pkt.header().padding); 302 assert_eq!(7, pkt.header().length); 303 assert_eq!(65535, pkt.base_sequence_number); 304 assert_eq!(13, pkt.packet_status_count); 305 assert_eq!(5, pkt.reference_time); 306 assert_eq!(0, pkt.fb_pkt_count); 307 assert_eq!(2, pkt.packet_chunks.len()); 308 309 assert_eq!( 310 vec![ 311 PacketStatusChunk::StatusVectorChunk(StatusVectorChunk { 312 type_tcc: StatusChunkTypeTcc::StatusVectorChunk, 313 symbol_size: SymbolSizeTypeTcc::TwoBit, 314 symbol_list: vec![ 315 SymbolTypeTcc::PacketReceivedSmallDelta, 316 SymbolTypeTcc::PacketNotReceived, 317 SymbolTypeTcc::PacketNotReceived, 318 SymbolTypeTcc::PacketNotReceived, 319 SymbolTypeTcc::PacketNotReceived, 320 SymbolTypeTcc::PacketNotReceived, 321 SymbolTypeTcc::PacketNotReceived, 322 ], 323 }), 324 PacketStatusChunk::StatusVectorChunk(StatusVectorChunk { 325 type_tcc: StatusChunkTypeTcc::StatusVectorChunk, 326 symbol_size: SymbolSizeTypeTcc::TwoBit, 327 symbol_list: vec![ 328 SymbolTypeTcc::PacketNotReceived, 329 SymbolTypeTcc::PacketReceivedLargeDelta, 330 SymbolTypeTcc::PacketReceivedLargeDelta, 331 SymbolTypeTcc::PacketNotReceived, 332 SymbolTypeTcc::PacketNotReceived, 333 SymbolTypeTcc::PacketReceivedLargeDelta, 334 ], 335 }), 336 ], 337 pkt.packet_chunks 338 ); 339 340 let expected_deltas = vec![ 341 RecvDelta { 342 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 343 delta: 0, 344 }, 345 RecvDelta { 346 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta, 347 delta: 0x0200 * TYPE_TCC_DELTA_SCALE_FACTOR, 348 }, 349 RecvDelta { 350 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta, 351 delta: 0x0100 * TYPE_TCC_DELTA_SCALE_FACTOR, 352 }, 353 RecvDelta { 354 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta, 355 delta: 0x0400 * TYPE_TCC_DELTA_SCALE_FACTOR, 356 }, 357 ]; 358 assert_eq!(expected_deltas.len(), pkt.recv_deltas.len()); 359 for (i, d) in expected_deltas.iter().enumerate() { 360 assert_eq!(d, &pkt.recv_deltas[i]); 361 } 362 } 363 364 //"get RTCP" 365 { 366 let tests = vec![(320, 1, 5, 1), (1000, 2, 15, 2)]; 367 for (arrival_ts, sequence_number, want_ref_time, want_base_sequence_number) in tests { 368 let mut f = Feedback::new(0, 0, 0); 369 f.set_base(sequence_number, arrival_ts * 1000); 370 371 let got = f.get_rtcp(); 372 assert_eq!(want_ref_time, got.reference_time); 373 assert_eq!(want_base_sequence_number, got.base_sequence_number); 374 } 375 } 376 377 Ok(()) 378 } 379 380 fn add_run(r: &mut Recorder, sequence_numbers: &[u16], arrival_times: &[i64]) { 381 assert_eq!(sequence_numbers.len(), arrival_times.len()); 382 383 for i in 0..sequence_numbers.len() { 384 r.record(5000, sequence_numbers[i], arrival_times[i]); 385 } 386 } 387 388 const TYPE_TCC_DELTA_SCALE_FACTOR: i64 = 250; 389 const SCALE_FACTOR_REFERENCE_TIME: i64 = 64000; 390 391 fn increase_time(arrival_time: &mut i64, increase_amount: i64) -> i64 { 392 *arrival_time += increase_amount; 393 *arrival_time 394 } 395 396 fn marshal_all(pkts: &[Box<dyn rtcp::packet::Packet + Send + Sync>]) -> Result<()> { 397 for pkt in pkts { 398 let _ = pkt.marshal()?; 399 } 400 Ok(()) 401 } 402 403 #[test] 404 fn test_build_feedback_packet() -> Result<()> { 405 let mut r = Recorder::new(5000); 406 407 let mut arrival_time = SCALE_FACTOR_REFERENCE_TIME as i64; 408 add_run( 409 &mut r, 410 &[0, 1, 2, 3, 4, 5, 6, 7], 411 &[ 412 SCALE_FACTOR_REFERENCE_TIME, 413 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 414 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 415 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 416 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 417 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 418 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 419 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR * 256), 420 ], 421 ); 422 423 let rtcp_packets = r.build_feedback_packet(); 424 assert_eq!(1, rtcp_packets.len()); 425 426 let expected = TransportLayerCc { 427 sender_ssrc: 5000, 428 media_ssrc: 5000, 429 base_sequence_number: 0, 430 reference_time: 1, 431 fb_pkt_count: 0, 432 packet_status_count: 8, 433 packet_chunks: vec![ 434 PacketStatusChunk::RunLengthChunk(RunLengthChunk { 435 type_tcc: StatusChunkTypeTcc::RunLengthChunk, 436 packet_status_symbol: SymbolTypeTcc::PacketReceivedSmallDelta, 437 run_length: 7, 438 }), 439 PacketStatusChunk::RunLengthChunk(RunLengthChunk { 440 type_tcc: StatusChunkTypeTcc::RunLengthChunk, 441 packet_status_symbol: SymbolTypeTcc::PacketReceivedLargeDelta, 442 run_length: 1, 443 }), 444 ], 445 recv_deltas: vec![ 446 RecvDelta { 447 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 448 delta: 0, 449 }, 450 RecvDelta { 451 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 452 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 453 }, 454 RecvDelta { 455 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 456 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 457 }, 458 RecvDelta { 459 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 460 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 461 }, 462 RecvDelta { 463 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 464 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 465 }, 466 RecvDelta { 467 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 468 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 469 }, 470 RecvDelta { 471 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 472 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 473 }, 474 RecvDelta { 475 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta, 476 delta: TYPE_TCC_DELTA_SCALE_FACTOR * 256, 477 }, 478 ], 479 }; 480 481 if let Some(tcc) = rtcp_packets[0].as_any().downcast_ref::<TransportLayerCc>() { 482 assert_eq!(tcc, &expected); 483 } else { 484 assert!(false); 485 } 486 487 marshal_all(&rtcp_packets[..])?; 488 489 Ok(()) 490 } 491 492 #[test] 493 fn test_build_feedback_packet_rolling() -> Result<()> { 494 let mut r = Recorder::new(5000); 495 496 let mut arrival_time = SCALE_FACTOR_REFERENCE_TIME as i64; 497 add_run(&mut r, &[0], &[arrival_time]); 498 499 let rtcp_packets = r.build_feedback_packet(); 500 assert_eq!(1, rtcp_packets.len()); // Empty TWCC 501 502 add_run( 503 &mut r, 504 &[4, 8, 9, 10], 505 &[ 506 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 507 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 508 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 509 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR), 510 ], 511 ); 512 513 let rtcp_packets = r.build_feedback_packet(); 514 assert_eq!(1, rtcp_packets.len()); 515 516 let expected = TransportLayerCc { 517 sender_ssrc: 5000, 518 media_ssrc: 5000, 519 base_sequence_number: 4, 520 reference_time: 1, 521 fb_pkt_count: 1, 522 packet_status_count: 7, 523 packet_chunks: vec![PacketStatusChunk::StatusVectorChunk(StatusVectorChunk { 524 type_tcc: StatusChunkTypeTcc::StatusVectorChunk, 525 symbol_size: SymbolSizeTypeTcc::TwoBit, 526 symbol_list: vec![ 527 SymbolTypeTcc::PacketReceivedSmallDelta, 528 SymbolTypeTcc::PacketNotReceived, 529 SymbolTypeTcc::PacketNotReceived, 530 SymbolTypeTcc::PacketNotReceived, 531 SymbolTypeTcc::PacketReceivedSmallDelta, 532 SymbolTypeTcc::PacketReceivedSmallDelta, 533 SymbolTypeTcc::PacketReceivedSmallDelta, 534 ], 535 })], 536 recv_deltas: vec![ 537 RecvDelta { 538 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 539 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 540 }, 541 RecvDelta { 542 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 543 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 544 }, 545 RecvDelta { 546 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 547 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 548 }, 549 RecvDelta { 550 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta, 551 delta: TYPE_TCC_DELTA_SCALE_FACTOR, 552 }, 553 ], 554 }; 555 556 if let Some(tcc) = rtcp_packets[0].as_any().downcast_ref::<TransportLayerCc>() { 557 assert_eq!(tcc, &expected); 558 } else { 559 assert!(false); 560 } 561 562 marshal_all(&rtcp_packets[..])?; 563 564 Ok(()) 565 } 566