github.com/pion/webrtc/v3@v3.2.24/rtpreceiver.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 //go:build !js 5 // +build !js 6 7 package webrtc 8 9 import ( 10 "fmt" 11 "io" 12 "sync" 13 "time" 14 15 "github.com/pion/interceptor" 16 "github.com/pion/rtcp" 17 "github.com/pion/srtp/v2" 18 "github.com/pion/webrtc/v3/internal/util" 19 ) 20 21 // trackStreams maintains a mapping of RTP/RTCP streams to a specific track 22 // a RTPReceiver may contain multiple streams if we are dealing with Simulcast 23 type trackStreams struct { 24 track *TrackRemote 25 26 streamInfo, repairStreamInfo *interceptor.StreamInfo 27 28 rtpReadStream *srtp.ReadStreamSRTP 29 rtpInterceptor interceptor.RTPReader 30 31 rtcpReadStream *srtp.ReadStreamSRTCP 32 rtcpInterceptor interceptor.RTCPReader 33 34 repairReadStream *srtp.ReadStreamSRTP 35 repairInterceptor interceptor.RTPReader 36 37 repairRtcpReadStream *srtp.ReadStreamSRTCP 38 repairRtcpInterceptor interceptor.RTCPReader 39 } 40 41 // RTPReceiver allows an application to inspect the receipt of a TrackRemote 42 type RTPReceiver struct { 43 kind RTPCodecType 44 transport *DTLSTransport 45 46 tracks []trackStreams 47 48 closed, received chan interface{} 49 mu sync.RWMutex 50 51 tr *RTPTransceiver 52 53 // A reference to the associated api object 54 api *API 55 } 56 57 // NewRTPReceiver constructs a new RTPReceiver 58 func (api *API) NewRTPReceiver(kind RTPCodecType, transport *DTLSTransport) (*RTPReceiver, error) { 59 if transport == nil { 60 return nil, errRTPReceiverDTLSTransportNil 61 } 62 63 r := &RTPReceiver{ 64 kind: kind, 65 transport: transport, 66 api: api, 67 closed: make(chan interface{}), 68 received: make(chan interface{}), 69 tracks: []trackStreams{}, 70 } 71 72 return r, nil 73 } 74 75 func (r *RTPReceiver) setRTPTransceiver(tr *RTPTransceiver) { 76 r.mu.Lock() 77 defer r.mu.Unlock() 78 r.tr = tr 79 } 80 81 // Transport returns the currently-configured *DTLSTransport or nil 82 // if one has not yet been configured 83 func (r *RTPReceiver) Transport() *DTLSTransport { 84 r.mu.RLock() 85 defer r.mu.RUnlock() 86 return r.transport 87 } 88 89 func (r *RTPReceiver) getParameters() RTPParameters { 90 parameters := r.api.mediaEngine.getRTPParametersByKind(r.kind, []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly}) 91 if r.tr != nil { 92 parameters.Codecs = r.tr.getCodecs() 93 } 94 return parameters 95 } 96 97 // GetParameters describes the current configuration for the encoding and 98 // transmission of media on the receiver's track. 99 func (r *RTPReceiver) GetParameters() RTPParameters { 100 r.mu.RLock() 101 defer r.mu.RUnlock() 102 return r.getParameters() 103 } 104 105 // Track returns the RtpTransceiver TrackRemote 106 func (r *RTPReceiver) Track() *TrackRemote { 107 r.mu.RLock() 108 defer r.mu.RUnlock() 109 110 if len(r.tracks) != 1 { 111 return nil 112 } 113 return r.tracks[0].track 114 } 115 116 // Tracks returns the RtpTransceiver tracks 117 // A RTPReceiver to support Simulcast may now have multiple tracks 118 func (r *RTPReceiver) Tracks() []*TrackRemote { 119 r.mu.RLock() 120 defer r.mu.RUnlock() 121 122 var tracks []*TrackRemote 123 for i := range r.tracks { 124 tracks = append(tracks, r.tracks[i].track) 125 } 126 return tracks 127 } 128 129 // RTPTransceiver returns the RTPTransceiver this 130 // RTPReceiver belongs too, or nil if none 131 func (r *RTPReceiver) RTPTransceiver() *RTPTransceiver { 132 r.mu.Lock() 133 defer r.mu.Unlock() 134 135 return r.tr 136 } 137 138 // configureReceive initialize the track 139 func (r *RTPReceiver) configureReceive(parameters RTPReceiveParameters) { 140 r.mu.Lock() 141 defer r.mu.Unlock() 142 143 for i := range parameters.Encodings { 144 t := trackStreams{ 145 track: newTrackRemote( 146 r.kind, 147 parameters.Encodings[i].SSRC, 148 parameters.Encodings[i].RID, 149 r, 150 ), 151 } 152 153 r.tracks = append(r.tracks, t) 154 } 155 } 156 157 // startReceive starts all the transports 158 func (r *RTPReceiver) startReceive(parameters RTPReceiveParameters) error { 159 r.mu.Lock() 160 defer r.mu.Unlock() 161 select { 162 case <-r.received: 163 return errRTPReceiverReceiveAlreadyCalled 164 default: 165 } 166 defer close(r.received) 167 168 globalParams := r.getParameters() 169 codec := RTPCodecCapability{} 170 if len(globalParams.Codecs) != 0 { 171 codec = globalParams.Codecs[0].RTPCodecCapability 172 } 173 174 for i := range parameters.Encodings { 175 if parameters.Encodings[i].RID != "" { 176 // RID based tracks will be set up in receiveForRid 177 continue 178 } 179 180 var t *trackStreams 181 for idx, ts := range r.tracks { 182 if ts.track != nil && parameters.Encodings[i].SSRC != 0 && ts.track.SSRC() == parameters.Encodings[i].SSRC { 183 t = &r.tracks[idx] 184 break 185 } 186 } 187 if t == nil { 188 return fmt.Errorf("%w: %d", errRTPReceiverWithSSRCTrackStreamNotFound, parameters.Encodings[i].SSRC) 189 } 190 191 if parameters.Encodings[i].SSRC != 0 { 192 t.streamInfo = createStreamInfo("", parameters.Encodings[i].SSRC, 0, codec, globalParams.HeaderExtensions) 193 var err error 194 if t.rtpReadStream, t.rtpInterceptor, t.rtcpReadStream, t.rtcpInterceptor, err = r.transport.streamsForSSRC(parameters.Encodings[i].SSRC, *t.streamInfo); err != nil { 195 return err 196 } 197 } 198 199 if rtxSsrc := parameters.Encodings[i].RTX.SSRC; rtxSsrc != 0 { 200 streamInfo := createStreamInfo("", rtxSsrc, 0, codec, globalParams.HeaderExtensions) 201 rtpReadStream, rtpInterceptor, rtcpReadStream, rtcpInterceptor, err := r.transport.streamsForSSRC(rtxSsrc, *streamInfo) 202 if err != nil { 203 return err 204 } 205 206 if err = r.receiveForRtx(rtxSsrc, "", streamInfo, rtpReadStream, rtpInterceptor, rtcpReadStream, rtcpInterceptor); err != nil { 207 return err 208 } 209 } 210 } 211 212 return nil 213 } 214 215 // Receive initialize the track and starts all the transports 216 func (r *RTPReceiver) Receive(parameters RTPReceiveParameters) error { 217 r.configureReceive(parameters) 218 return r.startReceive(parameters) 219 } 220 221 // Read reads incoming RTCP for this RTPReceiver 222 func (r *RTPReceiver) Read(b []byte) (n int, a interceptor.Attributes, err error) { 223 select { 224 case <-r.received: 225 return r.tracks[0].rtcpInterceptor.Read(b, a) 226 case <-r.closed: 227 return 0, nil, io.ErrClosedPipe 228 } 229 } 230 231 // ReadSimulcast reads incoming RTCP for this RTPReceiver for given rid 232 func (r *RTPReceiver) ReadSimulcast(b []byte, rid string) (n int, a interceptor.Attributes, err error) { 233 select { 234 case <-r.received: 235 for _, t := range r.tracks { 236 if t.track != nil && t.track.rid == rid { 237 return t.rtcpInterceptor.Read(b, a) 238 } 239 } 240 return 0, nil, fmt.Errorf("%w: %s", errRTPReceiverForRIDTrackStreamNotFound, rid) 241 case <-r.closed: 242 return 0, nil, io.ErrClosedPipe 243 } 244 } 245 246 // ReadRTCP is a convenience method that wraps Read and unmarshal for you. 247 // It also runs any configured interceptors. 248 func (r *RTPReceiver) ReadRTCP() ([]rtcp.Packet, interceptor.Attributes, error) { 249 b := make([]byte, r.api.settingEngine.getReceiveMTU()) 250 i, attributes, err := r.Read(b) 251 if err != nil { 252 return nil, nil, err 253 } 254 255 pkts, err := rtcp.Unmarshal(b[:i]) 256 if err != nil { 257 return nil, nil, err 258 } 259 260 return pkts, attributes, nil 261 } 262 263 // ReadSimulcastRTCP is a convenience method that wraps ReadSimulcast and unmarshal for you 264 func (r *RTPReceiver) ReadSimulcastRTCP(rid string) ([]rtcp.Packet, interceptor.Attributes, error) { 265 b := make([]byte, r.api.settingEngine.getReceiveMTU()) 266 i, attributes, err := r.ReadSimulcast(b, rid) 267 if err != nil { 268 return nil, nil, err 269 } 270 271 pkts, err := rtcp.Unmarshal(b[:i]) 272 return pkts, attributes, err 273 } 274 275 func (r *RTPReceiver) haveReceived() bool { 276 select { 277 case <-r.received: 278 return true 279 default: 280 return false 281 } 282 } 283 284 // Stop irreversibly stops the RTPReceiver 285 func (r *RTPReceiver) Stop() error { 286 r.mu.Lock() 287 defer r.mu.Unlock() 288 var err error 289 290 select { 291 case <-r.closed: 292 return err 293 default: 294 } 295 296 select { 297 case <-r.received: 298 for i := range r.tracks { 299 errs := []error{} 300 301 if r.tracks[i].rtcpReadStream != nil { 302 errs = append(errs, r.tracks[i].rtcpReadStream.Close()) 303 } 304 305 if r.tracks[i].rtpReadStream != nil { 306 errs = append(errs, r.tracks[i].rtpReadStream.Close()) 307 } 308 309 if r.tracks[i].repairReadStream != nil { 310 errs = append(errs, r.tracks[i].repairReadStream.Close()) 311 } 312 313 if r.tracks[i].repairRtcpReadStream != nil { 314 errs = append(errs, r.tracks[i].repairRtcpReadStream.Close()) 315 } 316 317 if r.tracks[i].streamInfo != nil { 318 r.api.interceptor.UnbindRemoteStream(r.tracks[i].streamInfo) 319 } 320 321 if r.tracks[i].repairStreamInfo != nil { 322 r.api.interceptor.UnbindRemoteStream(r.tracks[i].repairStreamInfo) 323 } 324 325 err = util.FlattenErrs(errs) 326 } 327 default: 328 } 329 330 close(r.closed) 331 return err 332 } 333 334 func (r *RTPReceiver) streamsForTrack(t *TrackRemote) *trackStreams { 335 for i := range r.tracks { 336 if r.tracks[i].track == t { 337 return &r.tracks[i] 338 } 339 } 340 return nil 341 } 342 343 // readRTP should only be called by a track, this only exists so we can keep state in one place 344 func (r *RTPReceiver) readRTP(b []byte, reader *TrackRemote) (n int, a interceptor.Attributes, err error) { 345 <-r.received 346 if t := r.streamsForTrack(reader); t != nil { 347 return t.rtpInterceptor.Read(b, a) 348 } 349 350 return 0, nil, fmt.Errorf("%w: %d", errRTPReceiverWithSSRCTrackStreamNotFound, reader.SSRC()) 351 } 352 353 // receiveForRid is the sibling of Receive expect for RIDs instead of SSRCs 354 // It populates all the internal state for the given RID 355 func (r *RTPReceiver) receiveForRid(rid string, params RTPParameters, streamInfo *interceptor.StreamInfo, rtpReadStream *srtp.ReadStreamSRTP, rtpInterceptor interceptor.RTPReader, rtcpReadStream *srtp.ReadStreamSRTCP, rtcpInterceptor interceptor.RTCPReader) (*TrackRemote, error) { 356 r.mu.Lock() 357 defer r.mu.Unlock() 358 359 for i := range r.tracks { 360 if r.tracks[i].track.RID() == rid { 361 r.tracks[i].track.mu.Lock() 362 r.tracks[i].track.kind = r.kind 363 r.tracks[i].track.codec = params.Codecs[0] 364 r.tracks[i].track.params = params 365 r.tracks[i].track.ssrc = SSRC(streamInfo.SSRC) 366 r.tracks[i].track.mu.Unlock() 367 368 r.tracks[i].streamInfo = streamInfo 369 r.tracks[i].rtpReadStream = rtpReadStream 370 r.tracks[i].rtpInterceptor = rtpInterceptor 371 r.tracks[i].rtcpReadStream = rtcpReadStream 372 r.tracks[i].rtcpInterceptor = rtcpInterceptor 373 374 return r.tracks[i].track, nil 375 } 376 } 377 378 return nil, fmt.Errorf("%w: %s", errRTPReceiverForRIDTrackStreamNotFound, rid) 379 } 380 381 // receiveForRtx starts a routine that processes the repair stream 382 // These packets aren't exposed to the user yet, but we need to process them for 383 // TWCC 384 func (r *RTPReceiver) receiveForRtx(ssrc SSRC, rsid string, streamInfo *interceptor.StreamInfo, rtpReadStream *srtp.ReadStreamSRTP, rtpInterceptor interceptor.RTPReader, rtcpReadStream *srtp.ReadStreamSRTCP, rtcpInterceptor interceptor.RTCPReader) error { 385 var track *trackStreams 386 if ssrc != 0 && len(r.tracks) == 1 { 387 track = &r.tracks[0] 388 } else { 389 for i := range r.tracks { 390 if r.tracks[i].track.RID() == rsid { 391 track = &r.tracks[i] 392 } 393 } 394 } 395 396 if track == nil { 397 return fmt.Errorf("%w: ssrc(%d) rsid(%s)", errRTPReceiverForRIDTrackStreamNotFound, ssrc, rsid) 398 } 399 400 track.repairStreamInfo = streamInfo 401 track.repairReadStream = rtpReadStream 402 track.repairInterceptor = rtpInterceptor 403 track.repairRtcpReadStream = rtcpReadStream 404 track.repairRtcpInterceptor = rtcpInterceptor 405 406 go func() { 407 b := make([]byte, r.api.settingEngine.getReceiveMTU()) 408 for { 409 if _, _, readErr := track.repairInterceptor.Read(b, nil); readErr != nil { 410 return 411 } 412 } 413 }() 414 return nil 415 } 416 417 // SetReadDeadline sets the max amount of time the RTCP stream will block before returning. 0 is forever. 418 func (r *RTPReceiver) SetReadDeadline(t time.Time) error { 419 r.mu.RLock() 420 defer r.mu.RUnlock() 421 422 return r.tracks[0].rtcpReadStream.SetReadDeadline(t) 423 } 424 425 // SetReadDeadlineSimulcast sets the max amount of time the RTCP stream for a given rid will block before returning. 0 is forever. 426 func (r *RTPReceiver) SetReadDeadlineSimulcast(deadline time.Time, rid string) error { 427 r.mu.RLock() 428 defer r.mu.RUnlock() 429 430 for _, t := range r.tracks { 431 if t.track != nil && t.track.rid == rid { 432 return t.rtcpReadStream.SetReadDeadline(deadline) 433 } 434 } 435 return fmt.Errorf("%w: %s", errRTPReceiverForRIDTrackStreamNotFound, rid) 436 } 437 438 // setRTPReadDeadline sets the max amount of time the RTP stream will block before returning. 0 is forever. 439 // This should be fired by calling SetReadDeadline on the TrackRemote 440 func (r *RTPReceiver) setRTPReadDeadline(deadline time.Time, reader *TrackRemote) error { 441 r.mu.RLock() 442 defer r.mu.RUnlock() 443 444 if t := r.streamsForTrack(reader); t != nil { 445 return t.rtpReadStream.SetReadDeadline(deadline) 446 } 447 return fmt.Errorf("%w: %d", errRTPReceiverWithSSRCTrackStreamNotFound, reader.SSRC()) 448 }