pion中的TrackRemote

有TrackLocal表示表示本地发往远端的track,对应的自然也会有TrackRemote表示远端发到本地的track: // TrackRemote represents a single inbound source of media type TrackRemote struct { m

TrackLocal表示表示本地发往远端的track,对应的自然也会有TrackRemote表示远端发到本地的track:

// TrackRemote represents a single inbound source of media
type TrackRemote struct {
	mu sync.RWMutex

	id       string
	streamID string

	payloadType PayloadType
	kind        RTPCodecType
	ssrc        SSRC
	codec       RTPCodecParameters
	params      RTPParameters
	rid         string

	receiver         *RTPReceiver
	peeked           []byte
	peekedAttributes interceptor.Attributes
}

TrackRemote就没有像TrackLocal做成接口了,大概是因为参数和数据都是对面给的,用户只需要读取,不需要什么其他侵入pion内部的操作。

那么最核心的就是这个ReadReadRTP了,就是读取数据,不必多讲。

// Read reads data from the track.
func (t *TrackRemote) Read(b []byte) (n int, attributes interceptor.Attributes, err error) {
    ...
}

// ReadRTP is a convenience method that wraps Read and unmarshals for you.
func (t *TrackRemote) ReadRTP() (*rtp.Packet, interceptor.Attributes, error) {
	b := make([]byte, t.receiver.api.settingEngine.getReceiveMTU())
	i, attributes, err := t.Read(b)
	if err != nil {
		return nil, nil, err
	}

	r := &rtp.Packet{}
	if err := r.Unmarshal(b[:i]); err != nil {
		return nil, nil, err
	}
	return r, attributes, nil
}

因为不需要用户自定义什么操作,所以也没有什么继承之类的操作,TrackRemote本身也不需要用户自己去构造,都是在框架里构造好的。

用户要做的最主要的操作就是在OnTrack里面,当有track连接进来时处理之,pion-gocv-receive里面就是:

// Set a handler for when a new remote track starts, this handler copies inbound RTP packets,
// replaces the SSRC and sends them back
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
    // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
    go func() {
        ticker := time.NewTicker(time.Second * 3)
        for range ticker.C {
            errSend := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}})
            if errSend != nil {
                fmt.Println(errSend)
            }
        }
    }()

    fmt.Printf("Track has started, of type %d: %s \n", track.PayloadType(), track.Codec().RTPCodecCapability.MimeType)
    for {
        // Read RTP packets being sent to Pion
        rtp, _, readErr := track.ReadRTP()
        if readErr != nil {
            panic(readErr)
        }

        if ivfWriterErr := ivfWriter.WriteRTP(rtp); ivfWriterErr != nil {
            panic(ivfWriterErr)
        }
    }
})

OnTrack里面直接一个死循环不断用track.ReadRTP读数据拿去ivfWriter.WriteRTP处理。

LICENSED UNDER CC BY-NC-SA 4.0
Comment