mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-06 00:56:58 +08:00
📦 NEW: 增加rtpdump的回放功能
This commit is contained in:
@@ -73,6 +73,7 @@ type AVTrack interface {
|
||||
WriteRTP([]byte)
|
||||
WriteRTPPack(*rtp.Packet)
|
||||
Flush()
|
||||
SetSpeedLimit(int)
|
||||
}
|
||||
type VideoTrack interface {
|
||||
AVTrack
|
||||
|
12
go.mod
12
go.mod
@@ -7,11 +7,12 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/lucas-clemente/quic-go v0.29.2
|
||||
github.com/pion/rtp v1.6.2
|
||||
github.com/pion/rtp v1.7.13
|
||||
github.com/pion/webrtc/v3 v3.1.44
|
||||
github.com/q191201771/naza v0.19.1
|
||||
github.com/shirou/gopsutil/v3 v3.22.6
|
||||
go.uber.org/zap v1.21.0
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e
|
||||
golang.org/x/net v0.0.0-20220630215102-69896b714898
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
@@ -20,7 +21,6 @@ require (
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -32,17 +32,17 @@ require (
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664 // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
|
70
go.sum
70
go.sum
@@ -29,11 +29,14 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
@@ -67,16 +70,40 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||
github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ=
|
||||
github.com/pion/dtls/v2 v2.1.3/go.mod h1:o6+WvyLDAlXF7YiPB/RlskRoeK+/JtuaZa5emwQcWus=
|
||||
github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY=
|
||||
github.com/pion/ice/v2 v2.2.6/go.mod h1:SWuHiOGP17lGromHTFadUe1EuPgFh/oCU6FCMZHooVE=
|
||||
github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U=
|
||||
github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo=
|
||||
github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
|
||||
github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/sctp v1.8.0/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s=
|
||||
github.com/pion/sctp v1.8.2/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s=
|
||||
github.com/pion/sdp/v3 v3.0.5/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
|
||||
github.com/pion/srtp/v2 v2.0.10/go.mod h1:XEeSWaK9PfuMs7zxXyiN252AHPbH12NX5q/CFDWtUuA=
|
||||
github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA=
|
||||
github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZIWJ6q9A=
|
||||
github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g=
|
||||
github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg=
|
||||
github.com/pion/turn/v2 v2.0.8/go.mod h1:+y7xl719J8bAEVpSXBXvTxStjJv3hbz9YFflvkpcGPw=
|
||||
github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M=
|
||||
github.com/pion/webrtc/v3 v3.1.44 h1:uY11C9cOupY36bS3Q16NI298c/XKhl5S9EMCo/TxH3Y=
|
||||
github.com/pion/webrtc/v3 v3.1.44/go.mod h1:G/J8k0+grVsjC/rjCZ24AKoCCxcFFODgh7zThNZGs0M=
|
||||
github.com/pixelbender/go-sdp v1.1.0/go.mod h1:6IBlz9+BrUHoFTea7gcp4S54khtOhjCW/nVDLhmZBAs=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
@@ -90,6 +117,7 @@ github.com/q191201771/naza v0.19.1/go.mod h1:5LeGupZZFtYP1g/S203n9vXoUNVdlRnPIfM
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/shirou/gopsutil/v3 v3.22.6 h1:FnHOFOh+cYAM0C30P+zysPISzlknLC5Z1G4EAElznfQ=
|
||||
github.com/shirou/gopsutil/v3 v3.22.6/go.mod h1:EdIubSnZhbAvBS1yJ7Xi+AShB/hxwLHOMz4MCYz7yMs=
|
||||
github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A=
|
||||
@@ -122,8 +150,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8 h1:y+mHpWoQJNAHt26Nhh6JP7hvM71IRZureyvZhoVALIs=
|
||||
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@@ -137,9 +167,18 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220630215102-69896b714898 h1:K7wO6V1IrczY9QOQ2WkVpw4JQSwCd52UsxVEirZUfiw=
|
||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -159,15 +198,23 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664 h1:wEZYwx+kK+KlZ0hpvP2Ls1Xr4+RWnlzGFwPP0aiDjIU=
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -186,8 +233,10 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
@@ -203,6 +252,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
40
http.go
40
http.go
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
"m7s.live/engine/v4/codec"
|
||||
"m7s.live/engine/v4/config"
|
||||
"m7s.live/engine/v4/util"
|
||||
)
|
||||
@@ -193,3 +194,42 @@ func (conf *GlobalConfig) API_stopPush(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "no such pusher", http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (conf *GlobalConfig) API_replay_rtpdump(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
streamPath := q.Get("streamPath")
|
||||
if streamPath == "" {
|
||||
streamPath = "dump/rtsp"
|
||||
}
|
||||
dumpFile := q.Get("dump")
|
||||
if dumpFile == "" {
|
||||
dumpFile = streamPath + ".rtpdump"
|
||||
}
|
||||
cv := q.Get("vcodec")
|
||||
ca := q.Get("acodec")
|
||||
var pub RTPDumpPublisher
|
||||
switch cv {
|
||||
case "h264":
|
||||
pub.VCodec = codec.CodecID_H264
|
||||
case "h265":
|
||||
pub.VCodec = codec.CodecID_H265
|
||||
default:
|
||||
pub.VCodec = codec.CodecID_H264
|
||||
}
|
||||
switch ca {
|
||||
case "aac":
|
||||
pub.ACodec = codec.CodecID_AAC
|
||||
case "pcma":
|
||||
pub.ACodec = codec.CodecID_PCMA
|
||||
case "pcmu":
|
||||
pub.ACodec = codec.CodecID_PCMU
|
||||
default:
|
||||
pub.ACodec = codec.CodecID_AAC
|
||||
}
|
||||
pub.DumpFile = dumpFile
|
||||
if err := Engine.Publish(streamPath, &pub); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
} else {
|
||||
w.Write([]byte("ok"))
|
||||
}
|
||||
}
|
||||
|
64
publisher-rtpdump.go
Normal file
64
publisher-rtpdump.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/pion/webrtc/v3/pkg/media/rtpdump"
|
||||
"go.uber.org/zap"
|
||||
"m7s.live/engine/v4/codec"
|
||||
"m7s.live/engine/v4/track"
|
||||
)
|
||||
|
||||
type RTPDumpPublisher struct {
|
||||
Publisher
|
||||
DumpFile string
|
||||
VCodec codec.VideoCodecID
|
||||
ACodec codec.AudioCodecID
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func (t *RTPDumpPublisher) OnEvent(event any) {
|
||||
var err error
|
||||
t.Publisher.OnEvent(event)
|
||||
switch event.(type) {
|
||||
case IPublisher:
|
||||
t.file, err = os.Open(t.DumpFile)
|
||||
if err != nil {
|
||||
t.Stream.Error("RTPDumpPublisher open file error", zap.Error(err))
|
||||
return
|
||||
}
|
||||
r, h, err := rtpdump.NewReader(t.file)
|
||||
if err != nil {
|
||||
t.Stream.Error("RTPDumpPublisher open file error", zap.Error(err))
|
||||
return
|
||||
}
|
||||
t.Stream.Info("RTPDumpPublisher open file success", zap.String("file", t.DumpFile), zap.String("start", h.Start.String()), zap.String("source", h.Source.String()), zap.Uint16("port", h.Port))
|
||||
switch t.VCodec {
|
||||
case codec.CodecID_H264:
|
||||
t.VideoTrack = track.NewH264(t.Publisher.Stream)
|
||||
case codec.CodecID_H265:
|
||||
t.VideoTrack = track.NewH265(t.Publisher.Stream)
|
||||
}
|
||||
switch t.ACodec {
|
||||
case codec.CodecID_AAC:
|
||||
t.AudioTrack = track.NewAAC(t.Publisher.Stream)
|
||||
case codec.CodecID_PCMA:
|
||||
t.AudioTrack = track.NewG711(t.Publisher.Stream, true)
|
||||
case codec.CodecID_PCMU:
|
||||
t.AudioTrack = track.NewG711(t.Publisher.Stream, false)
|
||||
}
|
||||
t.VideoTrack.SetSpeedLimit(500)
|
||||
t.AudioTrack.SetSpeedLimit(500)
|
||||
for {
|
||||
packet, err := r.Next()
|
||||
if err != nil {
|
||||
t.Stream.Error("RTPDumpPublisher read file error", zap.Error(err))
|
||||
return
|
||||
}
|
||||
if !packet.IsRTCP {
|
||||
t.VideoTrack.WriteRTP(packet.Payload)
|
||||
}
|
||||
// t.AudioTrack.WriteRTP(packet)
|
||||
}
|
||||
}
|
||||
}
|
102
publisher-ts.go
Normal file
102
publisher-ts.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"m7s.live/engine/v4/codec/mpegts"
|
||||
"m7s.live/engine/v4/track"
|
||||
)
|
||||
|
||||
type TSPublisher struct {
|
||||
Publisher
|
||||
*mpegts.MpegTsStream
|
||||
adts []byte
|
||||
}
|
||||
|
||||
func (t *TSPublisher) Feed(r io.Reader) error {
|
||||
return t.MpegTsStream.Feed(r, t.OnPmtStream, t.OnPES)
|
||||
}
|
||||
|
||||
func (t *TSPublisher) OnEvent(event any) {
|
||||
switch v := event.(type) {
|
||||
case IPublisher:
|
||||
t.MpegTsStream = mpegts.NewMpegTsStream()
|
||||
if !t.Equal(v) {
|
||||
t.AudioTrack = v.getAudioTrack()
|
||||
t.VideoTrack = v.getVideoTrack()
|
||||
}
|
||||
default:
|
||||
t.Publisher.OnEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TSPublisher) OnPmtStream(s mpegts.MpegTsPmtStream) {
|
||||
switch s.StreamType {
|
||||
case mpegts.STREAM_TYPE_H264:
|
||||
if t.VideoTrack == nil {
|
||||
t.VideoTrack = track.NewH264(t.Publisher.Stream)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_H265:
|
||||
if t.VideoTrack == nil {
|
||||
t.VideoTrack = track.NewH265(t.Publisher.Stream)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_AAC:
|
||||
if t.AudioTrack == nil {
|
||||
t.AudioTrack = track.NewAAC(t.Publisher.Stream)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_G711A:
|
||||
if t.AudioTrack == nil {
|
||||
t.AudioTrack = track.NewG711(t.Publisher.Stream, true)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_G711U:
|
||||
if t.AudioTrack == nil {
|
||||
t.AudioTrack = track.NewG711(t.Publisher.Stream, false)
|
||||
}
|
||||
default:
|
||||
t.Warn("unsupport stream type:", zap.Uint8("type", s.StreamType))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TSPublisher) OnPES(pes mpegts.MpegTsPESPacket) {
|
||||
if pes.Header.Dts == 0 {
|
||||
pes.Header.Dts = pes.Header.Pts
|
||||
}
|
||||
switch pes.Header.StreamID & 0xF0 {
|
||||
case mpegts.STREAM_ID_AUDIO:
|
||||
if t.AudioTrack != nil {
|
||||
switch t.AudioTrack.(type) {
|
||||
case *track.AAC:
|
||||
if t.adts == nil {
|
||||
t.adts = append(t.adts, pes.Payload[:7]...)
|
||||
t.AudioTrack.WriteADTS(t.adts)
|
||||
}
|
||||
current := t.AudioTrack.CurrentFrame()
|
||||
current.PTS = uint32(pes.Header.Pts)
|
||||
current.DTS = uint32(pes.Header.Dts)
|
||||
remainLen := len(pes.Payload)
|
||||
current.BytesIn += remainLen
|
||||
for remainLen > 0 {
|
||||
// AACFrameLength(13)
|
||||
// xx xxxxxxxx xxx
|
||||
frameLen := (int(pes.Payload[3]&3) << 11) | (int(pes.Payload[4]) << 3) | (int(pes.Payload[5]) >> 5)
|
||||
if frameLen > remainLen {
|
||||
break
|
||||
}
|
||||
|
||||
t.AudioTrack.WriteSlice(pes.Payload[7:frameLen])
|
||||
pes.Payload = pes.Payload[frameLen:remainLen]
|
||||
remainLen -= frameLen
|
||||
t.AudioTrack.Flush()
|
||||
}
|
||||
case *track.G711:
|
||||
t.AudioTrack.WriteRaw(uint32(pes.Header.Pts), pes.Payload)
|
||||
}
|
||||
|
||||
}
|
||||
case mpegts.STREAM_ID_VIDEO:
|
||||
if t.VideoTrack != nil {
|
||||
t.VideoTrack.WriteAnnexB(uint32(pes.Header.Pts), uint32(pes.Header.Dts), pes.Payload)
|
||||
}
|
||||
}
|
||||
}
|
96
publisher.go
96
publisher.go
@@ -1,11 +1,8 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"m7s.live/engine/v4/codec"
|
||||
"m7s.live/engine/v4/codec/mpegts"
|
||||
"m7s.live/engine/v4/common"
|
||||
"m7s.live/engine/v4/config"
|
||||
"m7s.live/engine/v4/track"
|
||||
@@ -132,96 +129,3 @@ func (pub *Puller) Reconnect() (ok bool) {
|
||||
pub.ReConnectCount++
|
||||
return
|
||||
}
|
||||
|
||||
type TSPublisher struct {
|
||||
Publisher
|
||||
*mpegts.MpegTsStream
|
||||
adts []byte
|
||||
}
|
||||
|
||||
func (t *TSPublisher) Feed(r io.Reader) error {
|
||||
return t.MpegTsStream.Feed(r, t.OnPmtStream, t.OnPES)
|
||||
}
|
||||
|
||||
func (t *TSPublisher) OnEvent(event any) {
|
||||
switch v := event.(type) {
|
||||
case IPublisher:
|
||||
t.MpegTsStream = mpegts.NewMpegTsStream()
|
||||
if !t.Equal(v) {
|
||||
t.AudioTrack = v.getAudioTrack()
|
||||
t.VideoTrack = v.getVideoTrack()
|
||||
}
|
||||
default:
|
||||
t.Publisher.OnEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TSPublisher) OnPmtStream(s mpegts.MpegTsPmtStream) {
|
||||
switch s.StreamType {
|
||||
case mpegts.STREAM_TYPE_H264:
|
||||
if t.VideoTrack == nil {
|
||||
t.VideoTrack = track.NewH264(t.Publisher.Stream)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_H265:
|
||||
if t.VideoTrack == nil {
|
||||
t.VideoTrack = track.NewH265(t.Publisher.Stream)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_AAC:
|
||||
if t.AudioTrack == nil {
|
||||
t.AudioTrack = track.NewAAC(t.Publisher.Stream)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_G711A:
|
||||
if t.AudioTrack == nil {
|
||||
t.AudioTrack = track.NewG711(t.Publisher.Stream, true)
|
||||
}
|
||||
case mpegts.STREAM_TYPE_G711U:
|
||||
if t.AudioTrack == nil {
|
||||
t.AudioTrack = track.NewG711(t.Publisher.Stream, false)
|
||||
}
|
||||
default:
|
||||
t.Warn("unsupport stream type:", zap.Uint8("type", s.StreamType))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TSPublisher) OnPES(pes mpegts.MpegTsPESPacket) {
|
||||
if pes.Header.Dts == 0 {
|
||||
pes.Header.Dts = pes.Header.Pts
|
||||
}
|
||||
switch pes.Header.StreamID & 0xF0 {
|
||||
case mpegts.STREAM_ID_AUDIO:
|
||||
if t.AudioTrack != nil {
|
||||
switch t.AudioTrack.(type) {
|
||||
case *track.AAC:
|
||||
if t.adts == nil {
|
||||
t.adts = append(t.adts, pes.Payload[:7]...)
|
||||
t.AudioTrack.WriteADTS(t.adts)
|
||||
}
|
||||
current := t.AudioTrack.CurrentFrame()
|
||||
current.PTS = uint32(pes.Header.Pts)
|
||||
current.DTS = uint32(pes.Header.Dts)
|
||||
remainLen := len(pes.Payload)
|
||||
current.BytesIn += remainLen
|
||||
for remainLen > 0 {
|
||||
// AACFrameLength(13)
|
||||
// xx xxxxxxxx xxx
|
||||
frameLen := (int(pes.Payload[3]&3) << 11) | (int(pes.Payload[4]) << 3) | (int(pes.Payload[5]) >> 5)
|
||||
if frameLen > remainLen {
|
||||
break
|
||||
}
|
||||
|
||||
t.AudioTrack.WriteSlice(pes.Payload[7:frameLen])
|
||||
pes.Payload = pes.Payload[frameLen:remainLen]
|
||||
remainLen -= frameLen
|
||||
t.AudioTrack.Flush()
|
||||
}
|
||||
case *track.G711:
|
||||
t.AudioTrack.WriteRaw(uint32(pes.Header.Pts), pes.Payload)
|
||||
}
|
||||
|
||||
}
|
||||
case mpegts.STREAM_ID_VIDEO:
|
||||
if t.VideoTrack != nil {
|
||||
t.VideoTrack.WriteAnnexB(uint32(pes.Header.Pts), uint32(pes.Header.Dts), pes.Payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import (
|
||||
type 流速控制 struct {
|
||||
起始时间戳 uint32
|
||||
起始时间 time.Time
|
||||
等待上限 time.Duration
|
||||
}
|
||||
|
||||
func (p *流速控制) 重置(绝对时间戳 uint32) {
|
||||
@@ -32,8 +33,8 @@ func (p *流速控制) 控制流速(绝对时间戳 uint32) {
|
||||
// }
|
||||
// 如果收到的帧的时间戳超过实际消耗的时间100ms就休息一下,100ms作为一个弹性区间防止频繁调用sleep
|
||||
if 过快毫秒 := (数据时间差 - 实际时间差) / time.Millisecond; 过快毫秒 > 300 {
|
||||
if 过快毫秒 > time.Duration(config.Global.SpeedLimit) {
|
||||
time.Sleep(time.Millisecond * time.Duration(config.Global.SpeedLimit))
|
||||
if 过快毫秒 > p.等待上限 {
|
||||
time.Sleep(time.Millisecond * p.等待上限)
|
||||
} else {
|
||||
time.Sleep(过快毫秒 * time.Millisecond)
|
||||
}
|
||||
@@ -53,9 +54,14 @@ type Media[T RawSlice] struct {
|
||||
流速控制
|
||||
}
|
||||
|
||||
func (av *Media[T]) SetSpeedLimit(value int) {
|
||||
av.等待上限 = time.Duration(value)
|
||||
}
|
||||
|
||||
func (av *Media[T]) Init(n int) {
|
||||
av.AVRing.Init(n)
|
||||
av.SSRC = uint32(uintptr(unsafe.Pointer(av)))
|
||||
av.等待上限 = time.Duration(config.Global.SpeedLimit)
|
||||
}
|
||||
|
||||
func (av *Media[T]) LastWriteTime() time.Time {
|
||||
@@ -117,7 +123,7 @@ func (av *Media[T]) Flush() {
|
||||
curValue.AbsTime = preValue.AbsTime + curValue.DeltaTime
|
||||
}
|
||||
av.Base.Flush(&curValue.BaseFrame)
|
||||
if config.Global.SpeedLimit > 0 {
|
||||
if av.等待上限 > 0 {
|
||||
av.控制流速(curValue.AbsTime)
|
||||
}
|
||||
av.Step()
|
||||
|
14
track/rtp.go
14
track/rtp.go
@@ -2,24 +2,32 @@ package track
|
||||
|
||||
import (
|
||||
"github.com/pion/rtp"
|
||||
"go.uber.org/zap"
|
||||
. "m7s.live/engine/v4/common"
|
||||
"m7s.live/engine/v4/config"
|
||||
"m7s.live/engine/v4/util"
|
||||
)
|
||||
|
||||
func (av *Media[T]) UnmarshalRTPPacket(p *rtp.Packet) (frame *RTPFrame) {
|
||||
if av.DecoderConfiguration.PayloadType != p.PayloadType {
|
||||
av.Stream.Warn("RTP PayloadType error", zap.Uint8("want", av.DecoderConfiguration.PayloadType), zap.Uint8("got", p.PayloadType))
|
||||
return
|
||||
}
|
||||
frame = &RTPFrame{
|
||||
Packet: *p,
|
||||
}
|
||||
av.Value.BytesIn += len(p.Payload) + 12
|
||||
return av.recorderRTP(frame)
|
||||
}
|
||||
|
||||
func (av *Media[T]) UnmarshalRTP(raw []byte) (frame *RTPFrame) {
|
||||
av.Value.BytesIn += len(raw)
|
||||
if frame = new(RTPFrame); frame.Unmarshal(raw) == nil {
|
||||
var p rtp.Packet
|
||||
err := p.Unmarshal(raw)
|
||||
if err != nil {
|
||||
av.Stream.Warn("RTP Unmarshal error", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return av.recorderRTP(frame)
|
||||
return av.UnmarshalRTPPacket(&p)
|
||||
}
|
||||
|
||||
type RTPDemuxer struct {
|
||||
|
Reference in New Issue
Block a user