首页 > 解决方案 > 使用 Pion/Webrtc 的 Nack 响应者拦截器

问题描述

我正在尝试使用 nack rtx 拦截器。这是我的代码拦截器代码:

func (n *ResponderInterceptor) resendPackets(nack *rtcp.TransportLayerNack) {

    rtpVideoPktDecoded := rtp.Packet{}

    for _, i := range nack.Nacks {
        offsetTotal := Rtop.VideoRTPPacketSequenceNumber - i.PacketID
        var offsetIndex uint16
        offsetIndex = 0
        if offsetTotal < RTP_PACKET_SIZE { // Still in buffer

            // Get the packet from the circular buffer
            if Rtop.VideoRTPPacketIndex <= offsetTotal {
                offsetIndex = RTP_PACKET_SIZE - (offsetTotal - Rtop.VideoRTPPacketIndex) - 1
            } else {
                offsetIndex = Rtop.VideoRTPPacketIndex - offsetTotal - 1
            }
            // We have found the need packet within the buffer
            if Rtop.ClientVideoTrack != nil {
                rtpPacketSize := Rtop.VideoRTPPacketsSize[offsetIndex]
                err := rtpVideoPktDecoded.Unmarshal(Rtop.VideoRTPPackets[offsetIndex][:rtpPacketSize])
                if err != nil {
                    log.Println("Err parser header ", err)
                }

                // Copy the packet 
                // Changing its payload type the Payload according to SDP
                // 121 is the 96 Nack RTX
                rtpVideoPktDecoded.Payload).Elem().Size()
                rtpVideoPktDecoded.PayloadType = 121

                rtxRtpVideoPktDecoded := rtp.Packet{}
                rtxRtpVideoPktDecoded.Header = rtpVideoPktDecoded.Header
                rtxRtpVideoPktDecoded.PayloadType = 121

                rtxRtpVideoPktDecoded.SequenceNumber = Rtop.VideoRTPPacketRtxSequenceNumber
                Rtop.VideoRTPPacketRtxSequenceNumber++

                rtxPayload := RtxPacket{}
                rtxPayload.OriginalSequenceNumber = rtpVideoPktDecoded.SequenceNumber
                rtxPayload.Payload = rtpVideoPktDecoded.Payload

                sz := uintptr(len(rtpVideoPktDecoded.Payload))*reflect.TypeOf(rtpVideoPktDecoded.Payload).Elem().Size() + uintptr(binary.Size(rtxPayload.OriginalSequenceNumber))
                var asByteSlice []byte = (*(*[PKTMAXLEN]byte)(unsafe.Pointer(&rtxPayload)))[:sz]

                rtxRtpVideoPktDecoded.Payload = asByteSlice

                if err := Rtop.ClientVideoTrack.WriteRTP(&rtpVideoPktDecoded); err != nil {
                    log.Println("Error Resend Seq:", i.PacketID)
                }

            } else {
                fmt.Printf("O no ClientVideoTrack")
            }
        } else {
            log.Println("No more in buffer PacketID:", i.PacketID, ", CurrentSequenceNumber:", Rtop.VideoRTPPacketSequenceNumber, ", offsetTotal:", offsetTotal)
        }
    }
}

每当 pion/webrtc 由于检测到数据包丢失而收到 nack 时,此功能就会正确触发并重新发送数据包。但它没有被另一端(chrome 浏览器)正确解释。并且多次询问同一个数据包。因此,溪流冻结了。

这是我使用 pion/webrtc 设置流的方法:

...
    m := webrtc.MediaEngine{}
    videoRTCPFeedback := []webrtc.RTCPFeedback{{"goog-remb", ""}, {"ccm", "fir"}, {"nack", ""}, {"nack", "pli"}}
    //videoRTCPFeedback := []webrtc.RTCPFeedback{{"goog-remb", ""}, {"ccm", "fir"}}
    //videoRtxRTCPFeedback := []webrtc.RTCPFeedback{{"nack", ""}, {"nack", "pli"}}
    //videoUlpFecRTCPFeedback := []webrtc.RTCPFeedback{{"nack", ""}, {"nack", "pli"}}

    m.RegisterCodec(webrtc.RTPCodecParameters{
        RTPCodecCapability: webrtc.RTPCodecCapability{"video/h264", 90000, 0, "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", videoRTCPFeedback},
        PayloadType:        102,
    }, webrtc.RTPCodecTypeVideo)

    m.RegisterCodec(webrtc.RTPCodecParameters{
        RTPCodecCapability: webrtc.RTPCodecCapability{"video/rtx", 90000, 0, "apt=102;rtx-time=3000", nil},
        PayloadType:        121,
    }, webrtc.RTPCodecTypeVideo)

    m.RegisterCodec(webrtc.RTPCodecParameters{
        RTPCodecCapability: webrtc.RTPCodecCapability{"video/ulpfec", 90000, 0, "", nil},
        PayloadType:        116,
    }, webrtc.RTPCodecTypeVideo)

    m.RegisterCodec(webrtc.RTPCodecParameters{
        RTPCodecCapability: webrtc.RTPCodecCapability{"audio/opus", 48000, 2, "minptime=10;useinbandfec=1", nil},
        PayloadType:        111,
    }, webrtc.RTPCodecTypeAudio)

    //m.RegisterFeedback(webrtc.RTCPFeedback{Type: "nack"}, webrtc.RTPCodecTypeVideo)
    //m.RegisterFeedback(webrtc.RTCPFeedback{Type: "nack", Parameter: "pli"}, webrtc.RTPCodecTypeVideo)

    myInterceptor := &interceptor.Registry{}
    generator, _ := nack.NewGeneratorInterceptor()
    responder, _ := NewAirtopCloudResponderInterceptor()
...

谢谢您的帮助

标签: gowebrtcstreaming

解决方案


推荐阅读