pion学习总结:等待传出track的一般流程

先创建设置然后创建PeerConnection: 和传入连接一样的过程 创建track 这一步主要是要生成一个TrackLocal子类,在里面指定你要给远端发什么东西以及怎么发。 比如在pion-play-from-disk里面用的是pion给的样例track: // Create a vi

先创建设置然后创建PeerConnection:

和传入连接一样的过程

创建track

这一步主要是要生成一个TrackLocal子类,在里面指定你要给远端发什么东西以及怎么发。

比如在pion-play-from-disk里面用的是pion给的样例track:

    // Create a video track
    videoTrack, videoTrackErr := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion")
    if videoTrackErr != nil {
        panic(videoTrackErr)
    }

// Create a video track
videoTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion")
if err != nil {
    panic(err)
}

将track添加到PeerConnection

就是一个AddTrack函数,不必多讲:

rtpSender, err := peerConnection.AddTrack(videoTrack)
if err != nil {
    panic(err)
}

等待连接传入

和上篇博客一样

开始往track里写数据

有连接连上了就可以通过track向对方发数据了,也就是往track里写数据。往track里写数据的操作是用户自己定义的,其归根结底就是不断调用TrackLocalContext里的TrackLocalWriter.WriteRTP(这个TrackLocalContext来自于pion里调用用户实现的TrackLocal.Bind

比如在pion-play-from-disk》里,调用TrackLocalWriter.WriteRTP的过程就封装在WriteSample里,读取视频后这边只要没隔一帧的时间发一次数据即可:

        // Keep track of last granule, the difference is the amount of samples in the buffer
        var lastGranule uint64

        // It is important to use a time.Ticker instead of time.Sleep because
        // * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
        // * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
        ticker := time.NewTicker(oggPageDuration)
        for ; true; <-ticker.C {
            pageData, pageHeader, oggErr := ogg.ParseNextPage()
            if oggErr == io.EOF {
                fmt.Printf("All audio pages parsed and sent")
                os.Exit(0)
            }

            if oggErr != nil {
                panic(oggErr)
            }

            // The amount of samples is the difference between the last and current timestamp
            sampleCount := float64(pageHeader.GranulePosition - lastGranule)
            lastGranule = pageHeader.GranulePosition
            sampleDuration := time.Duration((sampleCount/48000)*1000) * time.Millisecond

            if oggErr = audioTrack.WriteSample(media.Sample{Data: pageData, Duration: sampleDuration}); oggErr != nil {
                panic(oggErr)
            }
        }

再比如在pion-rtp-to-webrtc里,track用的是pion内置的TrackLocalStaticRTP

// Read RTP packets forever and send them to the WebRTC Client
inboundRTPPacket := make([]byte, 1600) // UDP MTU
for {
    n, _, err := listener.ReadFrom(inboundRTPPacket)
    if err != nil {
        panic(fmt.Sprintf("error during read: %s", err))
    }

    if _, err = videoTrack.Write(inboundRTPPacket[:n]); err != nil {
        if errors.Is(err, io.ErrClosedPipe) {
            // The peerConnection has been closed.
            return
        }

        panic(err)
    }
}

TrackLocalStaticRTP是一种编解码方式不变的TrackLocal,调用TrackLocalWriter.WriteRTP的过程就在TrackLocalStaticRTP.WriteRTP里。

LICENSED UNDER CC BY-NC-SA 4.0
Comment