@@ -284,7 +284,20 @@ impl PeerConnectionInternal {
284284 }
285285 }
286286
287- self . start_rtp_receivers ( & mut track_details, & current_transceivers)
287+ // VALIDATION LOGGING: H15 (incoming_tracks empty?) and H14 (transceiver list)
288+ log:: info!( "π VALIDATION: start_rtp() called, is_renegotiation={}" , is_renegotiation) ;
289+ log:: info!( "π VALIDATION: incoming_tracks.len() = {}" , track_details. len( ) ) ;
290+ for ( i, track) in track_details. iter ( ) . enumerate ( ) {
291+ log:: info!( "π VALIDATION: incoming_track[{}]: mid={}, kind={:?}, ssrcs={:?}" ,
292+ i, track. mid, track. kind, track. ssrcs) ;
293+ }
294+ log:: info!( "π VALIDATION: current_transceivers.len() = {}" , current_transceivers. len( ) ) ;
295+ for ( i, t) in current_transceivers. iter ( ) . enumerate ( ) {
296+ log:: info!( "π VALIDATION: transceiver[{}]: mid={:?}, kind={:?}, direction={:?}" ,
297+ i, t. mid( ) , t. kind( ) , t. direction( ) ) ;
298+ }
299+
300+ self . start_rtp_receivers ( & mut track_details, & current_transceivers, is_renegotiation)
288301 . await ?;
289302 if let Some ( parsed_remote) = & remote_desc. parsed {
290303 let current_local_desc = self . current_local_description . lock ( ) . await ;
@@ -418,42 +431,97 @@ impl PeerConnectionInternal {
418431 self : & Arc < Self > ,
419432 incoming_tracks : & mut Vec < TrackDetails > ,
420433 local_transceivers : & [ Arc < RTCRtpTransceiver > ] ,
434+ is_renegotiation : bool ,
421435 ) -> Result < ( ) > {
422436 // Ensure we haven't already started a transceiver for this ssrc
437+ // SKIP filtering during renegotiation - let receiver reset logic handle it
438+ log:: info!( "π VALIDATION: start_rtp_receivers() - incoming_tracks.len()={}, is_renegotiation={}" , incoming_tracks. len( ) , is_renegotiation) ;
423439 let mut filtered_tracks = incoming_tracks. clone ( ) ;
424- for incoming_track in incoming_tracks {
425- // If we already have a TrackRemote for a given SSRC don't handle it again
426- for t in local_transceivers {
427- let receiver = t. receiver ( ) . await ;
428- for track in receiver. tracks ( ) . await {
429- for ssrc in & incoming_track. ssrcs {
430- if * ssrc == track. ssrc ( ) {
431- filter_track_with_ssrc ( & mut filtered_tracks, track. ssrc ( ) ) ;
440+
441+ if !is_renegotiation {
442+ log:: info!( "π VALIDATION: Filtering tracks (initial negotiation)" ) ;
443+ for incoming_track in incoming_tracks {
444+ // If we already have a TrackRemote for a given SSRC don't handle it again
445+ for t in local_transceivers {
446+ let receiver = t. receiver ( ) . await ;
447+ let existing_tracks = receiver. tracks ( ) . await ;
448+ log:: info!( "π VALIDATION: Receiver has {} existing tracks" , existing_tracks. len( ) ) ;
449+ for track in existing_tracks {
450+ log:: info!( "π VALIDATION: Existing track ssrc={}" , track. ssrc( ) ) ;
451+ for ssrc in & incoming_track. ssrcs {
452+ log:: info!( "π VALIDATION: Comparing with incoming ssrc={}" , ssrc) ;
453+ if * ssrc == track. ssrc ( ) {
454+ log:: warn!( "π VALIDATION: β FILTERING OUT track with ssrc={} (already exists)" , ssrc) ;
455+ filter_track_with_ssrc ( & mut filtered_tracks, track. ssrc ( ) ) ;
456+ }
432457 }
433458 }
434459 }
435460 }
461+ } else {
462+ log:: info!( "π VALIDATION: Skipping filtering (renegotiation - receiver reset logic will handle duplicates)" ) ;
463+ }
464+
465+ log:: info!( "π VALIDATION: After filtering - filtered_tracks.len()={}" , filtered_tracks. len( ) ) ;
466+ for ( i, track) in filtered_tracks. iter ( ) . enumerate ( ) {
467+ log:: info!( "π VALIDATION: filtered_track[{}]: mid={}, ssrcs={:?}" , i, track. mid, track. ssrcs) ;
436468 }
437469
438470 let mut unhandled_tracks = vec ! [ ] ; // filtered_tracks[:0]
439471 for incoming_track in filtered_tracks. iter ( ) {
472+ log:: info!( "π VALIDATION: Processing incoming_track mid={}" , incoming_track. mid) ;
440473 let mut track_handled = false ;
441- for t in local_transceivers {
442- if t. mid ( ) . as_ref ( ) != Some ( & incoming_track. mid ) {
474+ for ( t_idx, t) in local_transceivers. iter ( ) . enumerate ( ) {
475+ log:: info!( "π VALIDATION: Checking transceiver[{}]" , t_idx) ;
476+
477+ // Check 1: MID match
478+ let mid_match = t. mid ( ) . as_ref ( ) == Some ( & incoming_track. mid ) ;
479+ log:: info!( "π VALIDATION: MID check: t.mid={:?}, track.mid={}, MATCH={}" ,
480+ t. mid( ) , incoming_track. mid, mid_match) ;
481+ if !mid_match {
482+ log:: info!( "π VALIDATION: β SKIPPED: MID mismatch" ) ;
443483 continue ;
444484 }
445485
446- if ( incoming_track. kind != t. kind ( ) )
447- || ( t. direction ( ) != RTCRtpTransceiverDirection :: Recvonly
448- && t. direction ( ) != RTCRtpTransceiverDirection :: Sendrecv )
449- {
486+ // Check 2: Kind match
487+ let kind_match = incoming_track. kind == t. kind ( ) ;
488+ log:: info!( "π VALIDATION: KIND check: track.kind={:?}, t.kind={:?}, MATCH={}" ,
489+ incoming_track. kind, t. kind( ) , kind_match) ;
490+
491+ // Check 3: Direction check
492+ let direction = t. direction ( ) ;
493+ let direction_ok = direction == RTCRtpTransceiverDirection :: Recvonly
494+ || direction == RTCRtpTransceiverDirection :: Sendrecv ;
495+ log:: info!( "π VALIDATION: DIRECTION check: t.direction={:?}, OK={}" ,
496+ direction, direction_ok) ;
497+
498+ if !kind_match || !direction_ok {
499+ log:: info!( "π VALIDATION: β SKIPPED: kind or direction mismatch" ) ;
450500 continue ;
451501 }
452502
503+ // Check 4: have_received check (handle renegotiation)
504+ // Fix(issue-107): During renegotiation, allow reusing transceivers that are already receiving.
505+ // The same SSRC appears in multiple negotiation rounds in mesh topology. Instead of marking
506+ // these tracks as "NOT HANDLED", we recognize the receiver is already active and mark as handled.
453507 let receiver = t. receiver ( ) . await ;
454- if receiver. have_received ( ) . await {
455- continue ;
508+ let already_receiving = receiver. have_received ( ) . await ;
509+ log:: info!( "π VALIDATION: HAVE_RECEIVED check: {}" , already_receiving) ;
510+
511+ if already_receiving {
512+ if !is_renegotiation {
513+ log:: info!( "π VALIDATION: β SKIPPED: already receiving (initial negotiation)" ) ;
514+ continue ;
515+ } else {
516+ // During renegotiation, receiver already active - just mark as handled
517+ log:: info!( "π VALIDATION: β
Renegotiation: receiver already active, marking as handled (no restart needed)" ) ;
518+ track_handled = true ;
519+ break ;
520+ }
456521 }
522+
523+ // All checks passed - start receiver (only if not already receiving)
524+ log:: info!( "π VALIDATION: β
ALL CHECKS PASSED - Starting receiver" ) ;
457525 PeerConnectionInternal :: start_receiver (
458526 self . setting_engine . get_receive_mtu ( ) ,
459527 incoming_track,
@@ -463,10 +531,15 @@ impl PeerConnectionInternal {
463531 )
464532 . await ;
465533 track_handled = true ;
534+ log:: info!( "π VALIDATION: β
Receiver started successfully" ) ;
466535 }
467536
468537 if !track_handled {
538+ log:: warn!( "π VALIDATION: β οΈ Track NOT HANDLED: mid={}, kind={:?}, ssrcs={:?}" ,
539+ incoming_track. mid, incoming_track. kind, incoming_track. ssrcs) ;
469540 unhandled_tracks. push ( incoming_track) ;
541+ } else {
542+ log:: info!( "π VALIDATION: β
Track HANDLED: mid={}" , incoming_track. mid) ;
470543 }
471544 }
472545
0 commit comments