Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ionorg/ion-sfu
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.7.0
Choose a base ref
...
head repository: ionorg/ion-sfu
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.7.1
Choose a head ref
  • 4 commits
  • 12 files changed
  • 6 contributors

Commits on Jan 4, 2021

  1. Copy the full SHA
    36d20fe View commit details
  2. feat: metrics port (#356)

    * added sync drift stats interceptor
    
    * updated to set drift values on streams
    
    * added prometheus stats for rtp packets
    
    * cleanup rebase
    
    * migrate
    
    * Fix stats to new buffer
    
    Co-authored-by: Robin Raymond <robin@pop-os.localdomain>
    Co-authored-by: OrlandoCo <luisorlando.co@gmail.com>
    3 people authored Jan 4, 2021
    Copy the full SHA
    f76ccc5 View commit details
  3. chore: mod tidy

    tarrencev committed Jan 4, 2021
    Copy the full SHA
    9ba62d8 View commit details
  4. chore(deps): update module prometheus/client_golang to v1.9.0 (#342)

    Generated by renovateBot
    
    Co-authored-by: Renovate Bot <bot@renovateapp.com>
    renovate[bot] and renovate-bot authored Jan 4, 2021

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    grahamc Graham Christensen
    Copy the full SHA
    0303a92 View commit details
Showing with 416 additions and 53 deletions.
  1. +31 −5 cmd/signal/json-rpc/main.go
  2. +2 −0 config.toml
  3. +3 −3 go.mod
  4. +11 −13 go.sum
  5. +98 −29 pkg/buffer/buffer.go
  6. +1 −1 pkg/buffer/buffer_test.go
  7. +6 −0 pkg/buffer/factory.go
  8. +19 −0 pkg/sfu/helpers.go
  9. +3 −0 pkg/sfu/receiver.go
  10. +86 −2 pkg/sfu/router.go
  11. +6 −0 pkg/sfu/sfu.go
  12. +150 −0 pkg/stats/stream.go
36 changes: 31 additions & 5 deletions cmd/signal/json-rpc/main.go
Original file line number Diff line number Diff line change
@@ -4,12 +4,14 @@ package main
import (
"flag"
"fmt"
"net"
"net/http"
"os"

_ "net/http/pprof"

"github.com/gorilla/websocket"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sourcegraph/jsonrpc2"
websocketjsonrpc2 "github.com/sourcegraph/jsonrpc2/websocket"
"github.com/spf13/viper"
@@ -20,11 +22,12 @@ import (
)

var (
conf = sfu.Config{}
file string
cert string
key string
addr string
conf = sfu.Config{}
file string
cert string
key string
addr string
metricsAddr string
)

const (
@@ -79,6 +82,7 @@ func parse() bool {
flag.StringVar(&cert, "cert", "", "cert file")
flag.StringVar(&key, "key", "", "key file")
flag.StringVar(&addr, "a", ":7000", "address to use")
flag.StringVar(&metricsAddr, "m", ":8100", "merics to use")
help := flag.Bool("h", false, "help info")
flag.Parse()
if !load() {
@@ -91,6 +95,26 @@ func parse() bool {
return true
}

func startMetrics(addr string) {
// start metrics server
m := http.NewServeMux()
m.Handle("/metrics", promhttp.Handler())
srv := &http.Server{
Handler: m,
}

metricsLis, err := net.Listen("tcp", addr)
if err != nil {
log.Panicf("cannot bind to metrics endpoint %s. err: %s", addr, err)
}
log.Infof("Metrics Listening at %s", addr)

err = srv.Serve(metricsLis)
if err != nil {
log.Errorf("debug server stopped. got err: %s", err)
}
}

func main() {
if !parse() {
showHelp()
@@ -125,6 +149,8 @@ func main() {
<-jc.DisconnectNotify()
}))

go startMetrics(metricsAddr)

var err error
if key != "" && cert != "" {
log.Infof("Listening at https://[%s]", addr)
2 changes: 2 additions & 0 deletions config.toml
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@ maxbandwidth = 1500
# max buffer time by ms for video tracks
maxbuffertime = 1000

withstats = false

[router.simulcast]
# Prefer best quality initially
bestqualityfirst = true
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -15,9 +15,9 @@ require (
github.com/pion/rtcp v1.2.6
github.com/pion/rtp v1.6.2
github.com/pion/sdp/v3 v3.0.3
github.com/pion/transport v0.12.1-0.20201219000622-967df9be8a00
github.com/pion/webrtc/v3 v3.0.1-0.20201219004454-9e04a0a4122f
github.com/prometheus/client_golang v1.8.0
github.com/pion/transport v0.12.2
github.com/pion/webrtc/v3 v3.0.3
github.com/prometheus/client_golang v1.9.0
github.com/rs/cors v1.7.0 // indirect
github.com/soheilhy/cmux v0.1.4
github.com/sourcegraph/jsonrpc2 v0.0.0-20200429184054-15c2290dcb37
24 changes: 11 additions & 13 deletions go.sum
Original file line number Diff line number Diff line change
@@ -288,8 +288,8 @@ github.com/pion/dtls/v2 v2.0.4 h1:WuUcqi6oYMu/noNTz92QrF1DaFj4eXbhQ6dzaaAwOiI=
github.com/pion/dtls/v2 v2.0.4/go.mod h1:qAkFscX0ZHoI1E07RfYPoRw3manThveu+mlTDdOxoGI=
github.com/pion/ice/v2 v2.0.14 h1:FxXxauyykf89SWAtkQCfnHkno6G8+bhRkNguSh9zU+4=
github.com/pion/ice/v2 v2.0.14/go.mod h1:wqaUbOq5ObDNU5ox1hRsEst0rWfsKuH1zXjQFEWiZwM=
github.com/pion/interceptor v0.0.8 h1:qsVJv9RF7mPq/RUnUV5iZCzxwGizO880FuiFKkEGQaE=
github.com/pion/interceptor v0.0.8/go.mod h1:dHgEP5dtxOTf21MObuBAjJeAayPxLUAZjerGH8Xr07c=
github.com/pion/interceptor v0.0.9 h1:fk5hTdyLO3KURQsf/+RjMpEm4NE3yeTY9Kh97b5BvwA=
github.com/pion/interceptor v0.0.9/go.mod h1:dHgEP5dtxOTf21MObuBAjJeAayPxLUAZjerGH8Xr07c=
github.com/pion/ion-log v1.0.0 h1:2lJLImCmfCWCR38hLWsjQfBWe6NFz/htbqiYHwvOP/Q=
github.com/pion/ion-log v1.0.0/go.mod h1:jwcla9KoB9bB/4FxYDSRJPcPYSLp5XiUUMnOLaqwl4E=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
@@ -307,8 +307,8 @@ github.com/pion/sctp v1.7.11 h1:UCnj7MsobLKLuP/Hh+JMiI/6W5Bs/VF45lWKgHFjSIE=
github.com/pion/sctp v1.7.11/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0=
github.com/pion/sdp/v3 v3.0.3 h1:gJK9hk+JFD2NGIM1nXmqNCq1DkVaIZ9dlA3u3otnkaw=
github.com/pion/sdp/v3 v3.0.3/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk=
github.com/pion/srtp/v2 v2.0.0-rc.3.0.20201219001609-888371fe3846 h1:r/jym7aZAkYGFxPGHOVJaUvY3NG1+Ywqoma+RywM7Ws=
github.com/pion/srtp/v2 v2.0.0-rc.3.0.20201219001609-888371fe3846/go.mod h1:3pLnsU2YIEM8aWhrkjFvnqEg/+/zHWhXMH9Zi+SLIXo=
github.com/pion/srtp/v2 v2.0.1 h1:kgfh65ob3EcnFYA4kUBvU/menCp9u7qaJLXwWgpobzs=
github.com/pion/srtp/v2 v2.0.1/go.mod h1:c8NWHhhkFf/drmHTAblkdu8++lsISEBBdAuiyxgqIsE=
github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg=
github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA=
github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRhSzR+CZ8=
@@ -317,14 +317,14 @@ github.com/pion/transport v0.10.1 h1:2W+yJT+0mOQ160ThZYUx5Zp2skzshiNgxrNE9GUfhJM
github.com/pion/transport v0.10.1/go.mod h1:PBis1stIILMiis0PewDw91WJeLJkyIMcEk+DwKOzf4A=
github.com/pion/transport v0.12.0 h1:UFmOBBZkTZ3LgvLRf/NGrfWdZEubcU6zkLU3PsA9YvU=
github.com/pion/transport v0.12.0/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
github.com/pion/transport v0.12.1-0.20201219000622-967df9be8a00 h1:NpvgQgfOQqlfbKgWwXGZ8VqTLfLLSuezO1SRSJnFOY4=
github.com/pion/transport v0.12.1-0.20201219000622-967df9be8a00/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
github.com/pion/transport v0.12.2 h1:WYEjhloRHt1R86LhUKjC5y+P52Y11/QqEUalvtzVoys=
github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA=
github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyrTqMw=
github.com/pion/udp v0.1.0 h1:uGxQsNyrqG3GLINv36Ff60covYmfrLoxzwnCsIYspXI=
github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths=
github.com/pion/webrtc/v3 v3.0.1-0.20201219004454-9e04a0a4122f h1:8IhPyBitQFIfCFUX9cMA2YPF1qB/PK+K5vafRhYz3dA=
github.com/pion/webrtc/v3 v3.0.1-0.20201219004454-9e04a0a4122f/go.mod h1:ffOpJ0AVxCIhQssqTZPD2RC8x3PpikUdsBMjIpKRnTI=
github.com/pion/webrtc/v3 v3.0.3 h1:nAXJ5niRFRRMneuhM56xsh3J76sv+HAHCNuBmab3YR0=
github.com/pion/webrtc/v3 v3.0.3/go.mod h1:DZonLDfkjMlsY/IGixAbcq8izHu0zJIk04DYx51KUvk=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -340,8 +340,7 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw=
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM=
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -358,8 +357,7 @@ github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
@@ -547,8 +545,8 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo=
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
127 changes: 98 additions & 29 deletions pkg/buffer/buffer.go
Original file line number Diff line number Diff line change
@@ -5,12 +5,12 @@ import (
"io"
"strings"
"sync"
"sync/atomic"
"time"

"github.com/pion/rtp"

log "github.com/pion/ion-log"
"github.com/pion/rtcp"
"github.com/pion/rtp"
"github.com/pion/sdp/v3"
"github.com/pion/webrtc/v3"
)
@@ -44,7 +44,6 @@ type Buffer struct {
twccExt uint8
bound bool
closed bool
onClose func()

// supported feedbacks
remb bool
@@ -56,21 +55,31 @@ type Buffer struct {
lastSRRecv int64 // Represents wall clock of the most recent sender report arrival
baseSN uint16
cycles uint32
lastExpected uint32
lastReceived uint32
lostRate float32
lastRtcpPacketTime int64 // Time the last RTCP packet was received.
lastRtcpSrTime int64 // Time the last RTCP SR was received. Required for DLSR computation.
packetCount uint32 // Number of packets received from this source.
lastRtcpPacketTime int64 // Time the last RTCP packet was received.
lastRtcpSrTime int64 // Time the last RTCP SR was received. Required for DLSR computation.
lastTransit uint32
maxSeqNo uint16 // The highest sequence number received in an RTP data packet
jitter float64 // An estimate of the statistical variance of the RTP data packet inter-arrival time.
totalByte uint64
maxSeqNo uint16 // The highest sequence number received in an RTP data packet

stats Stats

latestTimestamp uint32 // latest received RTP timestamp on packet
latestTimestampTime int64 // Time of the latest timestamp (in nanos since unix epoch)

// callbacks
onClose func()
feedbackCB func([]rtcp.Packet)
feedbackTWCC func(sn uint16, timeNS int64, marker bool)
}

type Stats struct {
LastExpected uint32
LastReceived uint32
LostRate float32
PacketCount uint32 // Number of packets received from this source.
Jitter float64 // An estimate of the statistical variance of the RTP data packet inter-arrival time.
TotalByte uint64
}

// BufferOptions provides configuration options for the buffer
type Options struct {
BufferTime int
@@ -232,7 +241,7 @@ func (b *Buffer) OnClose(fn func()) {
func (b *Buffer) calc(pkt []byte, arrivalTime int64) {
sn := binary.BigEndian.Uint16(pkt[2:4])

if b.packetCount == 0 {
if b.stats.PacketCount == 0 {
b.baseSN = sn
b.maxSeqNo = sn
b.bucket.headSN = sn - 1
@@ -243,23 +252,29 @@ func (b *Buffer) calc(pkt []byte, arrivalTime int64) {
}
b.maxSeqNo = sn
}
b.totalByte += uint64(len(pkt))
b.packetCount++
b.stats.TotalByte += uint64(len(pkt))
b.stats.PacketCount++

var p rtp.Packet
if err := p.Unmarshal(b.bucket.addPacket(pkt, sn, sn == b.maxSeqNo)); err != nil {
return
}
b.packetChan <- p

// if first time update or the timestamp is later (factoring timestamp wrap around)
if (b.latestTimestampTime == 0) || IsLaterTimestamp(p.Timestamp, b.latestTimestamp) {
b.latestTimestamp = p.Timestamp
b.latestTimestampTime = arrivalTime
}

arrival := uint32(arrivalTime / 1e6 * int64(b.clockRate/1e3))
transit := arrival - p.Timestamp
if b.lastTransit != 0 {
d := int32(transit - b.lastTransit)
if d < 0 {
d = -d
}
b.jitter += (float64(d) - b.jitter) / 16
b.stats.Jitter += (float64(d) - b.stats.Jitter) / 16
}
b.lastTransit = transit

@@ -275,20 +290,20 @@ func (b *Buffer) calc(pkt []byte, arrivalTime int64) {
}

func (b *Buffer) buildREMBPacket() *rtcp.ReceiverEstimatedMaximumBitrate {
br := b.totalByte * 8
if b.lostRate < 0.02 {
br := b.stats.TotalByte * 8
if b.stats.LostRate < 0.02 {
br = uint64(float64(br)*1.09) + 2000
}
if b.lostRate > .1 {
br = uint64(float64(br) * float64(1-0.5*b.lostRate))
if b.stats.LostRate > .1 {
br = uint64(float64(br) * float64(1-0.5*b.stats.LostRate))
}
if br > b.maxBitrate {
br = b.maxBitrate
}
if br < 100000 {
br = 100000
}
b.totalByte = 0
b.stats.TotalByte = 0

return &rtcp.ReceiverEstimatedMaximumBitrate{
Bitrate: br,
@@ -299,19 +314,19 @@ func (b *Buffer) buildREMBPacket() *rtcp.ReceiverEstimatedMaximumBitrate {
func (b *Buffer) buildReceptionReport() rtcp.ReceptionReport {
extMaxSeq := b.cycles | uint32(b.maxSeqNo)
expected := extMaxSeq - uint32(b.baseSN) + 1
lost := expected - b.packetCount
if b.packetCount == 0 {
lost := expected - b.stats.PacketCount
if b.stats.PacketCount == 0 {
lost = 0
}
expectedInterval := expected - b.lastExpected
b.lastExpected = expected
expectedInterval := expected - b.stats.LastExpected
b.stats.LastExpected = expected

receivedInterval := b.packetCount - b.lastReceived
b.lastReceived = b.packetCount
receivedInterval := b.stats.PacketCount - b.stats.LastReceived
b.stats.LastReceived = b.stats.PacketCount

lostInterval := expectedInterval - receivedInterval

b.lostRate = float32(lostInterval) / float32(expectedInterval)
b.stats.LostRate = float32(lostInterval) / float32(expectedInterval)
var fracLost uint8
if expectedInterval != 0 && lostInterval > 0 {
fracLost = uint8((lostInterval << 8) / expectedInterval)
@@ -329,7 +344,7 @@ func (b *Buffer) buildReceptionReport() rtcp.ReceptionReport {
FractionLost: fracLost,
TotalLost: lost,
LastSequenceNumber: extMaxSeq,
Jitter: uint32(b.jitter),
Jitter: uint32(b.stats.Jitter),
LastSenderReport: uint32(b.lastSRNTPTime >> 16),
Delay: dlsr,
}
@@ -374,3 +389,57 @@ func (b *Buffer) OnTransportWideCC(fn func(sn uint16, timeNS int64, marker bool)
func (b *Buffer) OnFeedback(fn func(fb []rtcp.Packet)) {
b.feedbackCB = fn
}

// GetMediaSSRC returns the associated SSRC of the RTP stream
func (b *Buffer) GetMediaSSRC() uint32 {
return b.mediaSSRC
}

// GetClockRate returns the RTP clock rate
func (b *Buffer) GetClockRate() uint32 {
return b.clockRate
}

// GetSenderReportData returns the rtp, ntp and nanos of the last sender report
func (b *Buffer) GetSenderReportData() (rtpTime uint32, ntpTime uint64, lastReceivedTimeInNanosSinceEpoch int64) {
rtpTime = atomic.LoadUint32(&b.lastSRRTPTime)
ntpTime = atomic.LoadUint64(&b.lastSRNTPTime)
lastReceivedTimeInNanosSinceEpoch = atomic.LoadInt64(&b.lastSRRecv)

return rtpTime, ntpTime, lastReceivedTimeInNanosSinceEpoch
}

// GetStats returns the raw statistics about a particular buffer state
func (b *Buffer) GetStats() (stats Stats) {
b.Lock()
stats = b.stats
b.Unlock()
return
}

// GetLatestTimestamp returns the latest RTP timestamp factoring in potential RTP timestamp wrap-around
func (b *Buffer) GetLatestTimestamp() (latestTimestamp uint32, latestTimestampTimeInNanosSinceEpoch int64) {
latestTimestamp = atomic.LoadUint32(&b.latestTimestamp)
latestTimestampTimeInNanosSinceEpoch = atomic.LoadInt64(&b.latestTimestampTime)

return latestTimestamp, latestTimestampTimeInNanosSinceEpoch
}

// IsTimestampWrapAround returns true if wrap around happens from timestamp1 to timestamp2
func IsTimestampWrapAround(timestamp1 uint32, timestamp2 uint32) bool {
return (timestamp1&0xC000000 == 0) && (timestamp2&0xC000000 == 0xC000000)
}

// IsLaterTimestamp returns true if timestamp1 is later in time than timestamp2 factoring in timestamp wrap-around
func IsLaterTimestamp(timestamp1 uint32, timestamp2 uint32) bool {
if timestamp1 > timestamp2 {
if IsTimestampWrapAround(timestamp2, timestamp1) {
return false
}
return true
}
if IsTimestampWrapAround(timestamp1, timestamp2) {
return true
}
return false
}
Loading