From cc3f215a23a46e59c8e669d8ff456b8215a848df Mon Sep 17 00:00:00 2001 From: deepch Date: Sun, 12 Mar 2023 00:32:08 +0300 Subject: [PATCH 01/25] mod update --- format/webrtcv3/adapter.go | 3 +- go.mod | 53 ++++--- go.sum | 276 +++++++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+), 23 deletions(-) diff --git a/format/webrtcv3/adapter.go b/format/webrtcv3/adapter.go index c022f83..e2e63f2 100644 --- a/format/webrtcv3/adapter.go +++ b/format/webrtcv3/adapter.go @@ -247,8 +247,7 @@ func (element *Muxer) WritePacket(pkt av.Packet) (err error) { if naltype == 5 { codec := tmp.codec.(h264parser.CodecData) err = tmp.track.WriteSample(media.Sample{Data: append([]byte{0, 0, 0, 1}, bytes.Join([][]byte{codec.SPS(), codec.PPS(), nalu}, []byte{0, 0, 0, 1})...), Duration: pkt.Duration}) - - } else if naltype == 1 { + } else { err = tmp.track.WriteSample(media.Sample{Data: append([]byte{0, 0, 0, 1}, nalu...), Duration: pkt.Duration}) } if err != nil { diff --git a/go.mod b/go.mod index 0ad223e..7f6afcb 100644 --- a/go.mod +++ b/go.mod @@ -4,35 +4,46 @@ go 1.18 require ( github.com/google/uuid v1.3.0 - github.com/pion/interceptor v0.1.11 + github.com/pion/interceptor v0.1.12 github.com/pion/webrtc/v2 v2.2.26 - github.com/pion/webrtc/v3 v3.1.42 + github.com/pion/webrtc/v3 v3.1.58 ) require ( github.com/cheekybits/genny v1.0.0 // indirect - github.com/lucas-clemente/quic-go v0.7.1-0.20190401152353-907071221cf9 // indirect - github.com/marten-seemann/qtls v0.2.3 // indirect - github.com/pion/datachannel v1.5.2 // indirect - github.com/pion/dtls/v2 v2.1.5 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect + github.com/lucas-clemente/quic-go v0.31.1 // indirect + github.com/marten-seemann/qtls v0.10.0 // indirect + github.com/marten-seemann/qtls-go1-18 v0.1.4 // indirect + github.com/marten-seemann/qtls-go1-19 v0.1.2 // indirect + github.com/onsi/ginkgo/v2 v2.9.0 // indirect + github.com/pion/datachannel v1.5.5 // indirect + github.com/pion/dtls/v2 v2.2.6 // indirect github.com/pion/ice v0.7.18 // indirect - github.com/pion/ice/v2 v2.2.6 // indirect + github.com/pion/ice/v2 v2.3.1 // indirect github.com/pion/logging v0.2.2 // indirect - github.com/pion/mdns v0.0.5 // indirect - github.com/pion/quic v0.1.1 // indirect + github.com/pion/mdns v0.0.7 // indirect + github.com/pion/quic v0.1.4 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.9 // indirect + github.com/pion/rtcp v1.2.10 // indirect github.com/pion/rtp v1.7.13 // indirect - github.com/pion/sctp v1.8.2 // indirect + github.com/pion/sctp v1.8.6 // indirect github.com/pion/sdp/v2 v2.4.0 // indirect - github.com/pion/sdp/v3 v3.0.5 // indirect - github.com/pion/srtp v1.5.1 // indirect - github.com/pion/srtp/v2 v2.0.9 // indirect - github.com/pion/stun v0.3.5 // indirect - github.com/pion/transport v0.13.1 // indirect - github.com/pion/turn/v2 v2.0.8 // indirect - github.com/pion/udp v0.1.1 // indirect - golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8 // indirect - golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect - golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 // indirect + github.com/pion/sdp/v3 v3.0.6 // indirect + github.com/pion/srtp v1.5.2 // indirect + github.com/pion/srtp/v2 v2.0.12 // indirect + github.com/pion/stun v0.4.0 // indirect + github.com/pion/transport v0.14.1 // indirect + github.com/pion/transport/v2 v2.0.2 // indirect + github.com/pion/turn/v2 v2.1.0 // indirect + github.com/pion/udp v0.1.4 // indirect + github.com/pion/udp/v2 v2.0.1 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 // indirect + golang.org/x/mod v0.9.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/tools v0.7.0 // indirect ) diff --git a/go.sum b/go.sum index d2d74e9..ca397f4 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,49 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -18,79 +52,148 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lucas-clemente/quic-go v0.7.1-0.20190401152353-907071221cf9 h1:tbuodUh2vuhOVZAdW3NEUvosFHUMJwUNl7jk/VSEiwc= github.com/lucas-clemente/quic-go v0.7.1-0.20190401152353-907071221cf9/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= +github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg= +github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4= +github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/marten-seemann/qpack v0.2.0/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= +github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl55b2pc= +github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs= +github.com/marten-seemann/qtls-go1-15 v0.1.0/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= +github.com/marten-seemann/qtls-go1-18 v0.1.4 h1:ogomB+lWV3Vmwiu6RTwDVTMGx+9j7SEi98e8QB35Its= +github.com/marten-seemann/qtls-go1-18 v0.1.4/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= +github.com/marten-seemann/qtls-go1-19 v0.1.2 h1:ZevAEqKXH0bZmoOBPiqX2h5rhQ7cbZi+X+rlq2JUbCE= +github.com/marten-seemann/qtls-go1-19 v0.1.2/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 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.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= 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/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= 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.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pion/datachannel v1.4.21/go.mod h1:oiNyP4gHx2DIwRzX/MFyH0Rz/Gz05OgBlayAI2hAWjg= github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ= +github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= +github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= github.com/pion/dtls/v2 v2.0.1/go.mod h1:uMQkz2W0cSqY00xav7WByQ4Hb+18xeQh2oH2fRezr5U= github.com/pion/dtls/v2 v2.0.2/go.mod h1:27PEO3MDdaCfo21heT59/vsdmZc0zMt9wQPcSlLu/1I= github.com/pion/dtls/v2 v2.1.3/go.mod h1:o6+WvyLDAlXF7YiPB/RlskRoeK+/JtuaZa5emwQcWus= github.com/pion/dtls/v2 v2.1.5 h1:jlh2vtIyUBShchoTDqpCCqiYCyRFJ/lvf/gQ8TALs+c= github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY= +github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4= +github.com/pion/dtls/v2 v2.2.6/go.mod h1:t8fWJCIquY5rlQZwA2yWxUS1+OCrAdXrhVKXB5oD/wY= github.com/pion/ice v0.7.18 h1:KbAWlzWRUdX9SmehBh3gYpIFsirjhSQsCw6K2MjYMK0= github.com/pion/ice v0.7.18/go.mod h1:+Bvnm3nYC6Nnp7VV6glUkuOfToB/AtMRZpOU8ihuf4c= github.com/pion/ice/v2 v2.2.6 h1:R/vaLlI1J2gCx141L5PEwtuGAGcyS6e7E0hDeJFq5Ig= github.com/pion/ice/v2 v2.2.6/go.mod h1:SWuHiOGP17lGromHTFadUe1EuPgFh/oCU6FCMZHooVE= +github.com/pion/ice/v2 v2.3.1 h1:FQCmUfZe2Jpe7LYStVBOP6z1DiSzbIateih3TztgTjc= +github.com/pion/ice/v2 v2.3.1/go.mod h1:aq2kc6MtYNcn4XmMhobAv6hTNJiHzvD0yXRz80+bnP8= github.com/pion/interceptor v0.1.11 h1:00U6OlqxA3FFB50HSg25J/8cWi7P6FbSzw4eFn24Bvs= github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= +github.com/pion/interceptor v0.1.12 h1:CslaNriCFUItiXS5o+hh5lpL0t0ytQkFnUcbbCs2Zq8= +github.com/pion/interceptor v0.1.12/go.mod h1:bDtgAD9dRkBZpWHGKaoKb42FhDHTG2rX8Ii9LRALLVA= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.4/go.mod h1:R1sL0p50l42S5lJs91oNdUL58nm0QHrhxnSegr++qC0= github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= +github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U= +github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8= github.com/pion/quic v0.1.1 h1:D951FV+TOqI9A0rTF7tHx0Loooqz+nyzjEyj8o3PuMA= github.com/pion/quic v0.1.1/go.mod h1:zEU51v7ru8Mp4AUBJvj6psrSth5eEFNnVQK5K48oV3k= +github.com/pion/quic v0.1.4 h1:bNz9sCJjlM3GqMdq7Fne57FiWfdyiJ++yHVbuqeoD3Y= +github.com/pion/quic v0.1.4/go.mod h1:dBhNvkLoQqRwfi6h3Vqj3IcPLgiW7rkZxBbRdp7Vzvk= github.com/pion/randutil v0.0.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= 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/rtcp v1.2.3/go.mod h1:zGhIv0RPRF0Z1Wiij22pUt5W/c9fevqSzT4jje/oK7I= +github.com/pion/rtcp v1.2.4/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0= github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U= github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= +github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= +github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= github.com/pion/rtp v1.6.0/go.mod h1:QgfogHsMBVE/RFNno467U/KBqfUywEH+HK+0rtnwsdI= +github.com/pion/rtp v1.6.1/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.7.10/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0= github.com/pion/sctp v1.8.0/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= github.com/pion/sctp v1.8.2 h1:yBBCIrUMJ4yFICL3RIvR4eh/H2BTTvlligmSTy+3kiA= github.com/pion/sctp v1.8.2/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= +github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= +github.com/pion/sctp v1.8.6 h1:CUex11Vkt9YS++VhLf8b55O3VqKrWL6W3SDwX4jAqsI= +github.com/pion/sctp v1.8.6/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= github.com/pion/sdp/v2 v2.4.0 h1:luUtaETR5x2KNNpvEMv/r4Y+/kzImzbz4Lm1z8eQNQI= github.com/pion/sdp/v2 v2.4.0/go.mod h1:L2LxrOpSTJbAns244vfPChbciR/ReU1KWfG04OpkR7E= github.com/pion/sdp/v3 v3.0.5 h1:ouvI7IgGl+V4CrqskVtr3AaTrPvPisEOxwgpdktctkU= github.com/pion/sdp/v3 v3.0.5/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= +github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= +github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= github.com/pion/srtp v1.5.1 h1:9Q3jAfslYZBt+C69SI/ZcONJh9049JUHZWYRRf5KEKw= github.com/pion/srtp v1.5.1/go.mod h1:B+QgX5xPeQTNc1CJStJPHzOlHK66ViMDWTT0HZTCkcA= +github.com/pion/srtp v1.5.2 h1:25DmvH+fqKZDqvX64vTwnycVwL9ooJxHF/gkX16bDBY= +github.com/pion/srtp v1.5.2/go.mod h1:NiBff/MSxUwMUwx/fRNyD/xGE+dVvf8BOCeXhjCXZ9U= github.com/pion/srtp/v2 v2.0.9 h1:JJq3jClmDFBPX/F5roEb0U19jSU7eUhyDqR/NZ34EKQ= github.com/pion/srtp/v2 v2.0.9/go.mod h1:5TtM9yw6lsH0ppNCehB/EjEUli7VkUgKSPJqWVqbhQ4= +github.com/pion/srtp/v2 v2.0.12 h1:WrmiVCubGMOAObBU1vwWjG0H3VSyQHawKeer2PVA5rY= +github.com/pion/srtp/v2 v2.0.12/go.mod h1:C3Ep44hlOo2qEYaq4ddsmK5dL63eLehXFbHaZ9F5V9Y= 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/stun v0.4.0 h1:vgRrbBE2htWHy7l3Zsxckk7rkjnjOsSM7PHZnBwo8rk= +github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw= github.com/pion/transport v0.6.0/go.mod h1:iWZ07doqOosSLMhZ+FXUTq+TamDoXSllxpbGcfkCmbE= github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRhSzR+CZ8= github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE= @@ -100,21 +203,68 @@ github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZ github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g= github.com/pion/transport v0.13.1 h1:/UH5yLeQtwm2VZIPjxwnNFxjS4DFhyLfS4GlfuKUzfA= github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg= +github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= +github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= +github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= +github.com/pion/transport/v2 v2.0.2 h1:St+8o+1PEzPT51O9bv+tH/KYYLMNR5Vwm5Z3Qkjsywg= +github.com/pion/transport/v2 v2.0.2/go.mod h1:vrz6bUbFr/cjdwbnxq8OdDDzHf7JJfGsIRkxfpZoTA0= github.com/pion/turn/v2 v2.0.4/go.mod h1:1812p4DcGVbYVBTiraUmP50XoKye++AMkbfp+N27mog= github.com/pion/turn/v2 v2.0.8 h1:KEstL92OUN3k5k8qxsXHpr7WWfrdp7iJZHx99ud8muw= github.com/pion/turn/v2 v2.0.8/go.mod h1:+y7xl719J8bAEVpSXBXvTxStjJv3hbz9YFflvkpcGPw= +github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI= +github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs= github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths= github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o= github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= +github.com/pion/udp v0.1.4 h1:OowsTmu1Od3sD6i3fQUJxJn2fEvJO6L1TidgadtbTI8= +github.com/pion/udp v0.1.4/go.mod h1:G8LDo56HsFwC24LIcnT4YIDU5qcB6NepqqjP0keL2us= +github.com/pion/udp/v2 v2.0.1 h1:xP0z6WNux1zWEjhC7onRA3EwwSliXqu1ElUZAQhUP54= +github.com/pion/udp/v2 v2.0.1/go.mod h1:B7uvTMP00lzWdyMr/1PVZXtV3wpPIxBRd4Wl6AksXn8= github.com/pion/webrtc/v2 v2.2.26 h1:01hWE26pL3LgqfxvQ1fr6O4ZtyRFFJmQEZK39pHWfFc= github.com/pion/webrtc/v2 v2.2.26/go.mod h1:XMZbZRNHyPDe1gzTIHFcQu02283YO45CbiwFgKvXnmc= github.com/pion/webrtc/v3 v3.1.42 h1:wJEQFIXVanptnQcHOLTuIo4AtGB2+mG2x4OhIhnITOA= github.com/pion/webrtc/v3 v3.1.42/go.mod h1:ffD9DulDrPxyWvDPUIPAOSAWx9GUlOExiJPf7cCcMLA= +github.com/pion/webrtc/v3 v3.1.58 h1:husXqiKQuk6gbOqJlPHs185OskAyxUW6iAEgHghgCrc= +github.com/pion/webrtc/v3 v3.1.58/go.mod h1:jJdqoqGBlZiE3y8Z1tg1fjSkyEDCZLL+foypUBn0Lhk= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -122,19 +272,59 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -146,6 +336,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 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= @@ -154,41 +346,114 @@ golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA= golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0= golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 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/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -198,8 +463,10 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -210,3 +477,12 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= From c923e0010bce0b63647af8e37474790249adc9f6 Mon Sep 17 00:00:00 2001 From: deepch Date: Mon, 13 Mar 2023 19:26:29 +0300 Subject: [PATCH 02/25] fix rtmp handshake flashphoner --- format/rtmp/rtmp.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/format/rtmp/rtmp.go b/format/rtmp/rtmp.go index 449132e..67eff90 100644 --- a/format/rtmp/rtmp.go +++ b/format/rtmp/rtmp.go @@ -1623,20 +1623,15 @@ func (self *Conn) handshakeServer() (err error) { clitime := pio.U32BE(C1[0:4]) srvtime := clitime srvver := uint32(0x0d0e0a0d) - cliver := pio.U32BE(C1[4:8]) - if cliver != 0 { - var ok bool - var digest []byte - if ok, digest = hsParse1(C1, hsClientPartialKey, hsServerFullKey); !ok { - err = fmt.Errorf("rtmp: handshake server: C1 invalid") - return - } + var ok bool + var digest []byte + if ok, digest = hsParse1(C1, hsClientPartialKey, hsServerFullKey); ok { hsCreate01(S0S1, srvtime, srvver, hsServerPartialKey) hsCreate2(S2, digest) } else { - copy(S1, C1) - copy(S2, C2) + copy(S1, C2) + copy(S2, C1) } if _, err = self.bufw.Write(S0S1S2); err != nil { From 175afae1c16912fa1e230149f8b5dc7e760d35d4 Mon Sep 17 00:00:00 2001 From: deepch Date: Wed, 22 Mar 2023 21:59:06 +0300 Subject: [PATCH 03/25] test transcode slow --- example/transcoder/main.go | 64 ++++++++++++++++++++++++++++++++++++++ format/mp4m/mp4io/mp4io.go | 8 ++++- format/ts/muxer.go | 38 +++++++++++++++++++++- format/ts/tsio/tsio.go | 13 ++++---- 4 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 example/transcoder/main.go diff --git a/example/transcoder/main.go b/example/transcoder/main.go new file mode 100644 index 0000000..7cd156a --- /dev/null +++ b/example/transcoder/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "context" + "github.com/deepch/vdk/format/rtspv2" + "github.com/deepch/vdk/format/ts" + "log" + "os/exec" + "time" +) + +func main() { + RTSPClient, err := rtspv2.Dial(rtspv2.RTSPClientOptions{URL: "rtsp://url", DisableAudio: true, DialTimeout: 3 * time.Second, ReadWriteTimeout: 5 * time.Second, Debug: true, OutgoingProxy: false}) + if err != nil { + panic(err) + } + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + cmd := exec.CommandContext(ctx, "ffmpeg", "-flags", "low_delay", "-analyzeduration", "1", "-fflags", "-nobuffer", "-probesize", "1024k", "-f", "mpegts", "-i", "-", "-vcodec", "libx264", "-preset", "ultrafast", "-bf", "0", "-f", "mpegts", "-max_muxing_queue_size", "400", "-pes_payload_size", "0", "pipe:1") + inPipe, _ := cmd.StdinPipe() + outPipe, _ := cmd.StdoutPipe() + //cmd.Stderr = os.Stderr + mux := ts.NewMuxer(inPipe) + demuxer := ts.NewDemuxer(outPipe) + codec := RTSPClient.CodecData + mux.WriteHeader(codec) + go func() { + imNewCodec, err := demuxer.Streams() + log.Println("new codec data", imNewCodec, err) + for i, data := range imNewCodec { + log.Println(i, data) + } + for { + pkt, err := demuxer.ReadPacket() + if err != nil { + log.Panic(err) + } + log.Println("im new pkt ===>", pkt.Idx, pkt.Time) + } + }() + cmd.Start() + var start bool + for { + select { + case signals := <-RTSPClient.Signals: + switch signals { + case rtspv2.SignalCodecUpdate: + //? + case rtspv2.SignalStreamRTPStop: + return + } + case packetAV := <-RTSPClient.OutgoingPacketQueue: + if packetAV.IsKeyFrame { + start = true + } + if !start { + continue + } + if err = mux.WritePacket(*packetAV); err != nil { + return + } + } + } +} diff --git a/format/mp4m/mp4io/mp4io.go b/format/mp4m/mp4io/mp4io.go index dfa99d5..5ce5ce8 100644 --- a/format/mp4m/mp4io/mp4io.go +++ b/format/mp4m/mp4io/mp4io.go @@ -376,7 +376,7 @@ func (self *ElemStreamDesc) parseDescHdr(b []byte, offset int) (n int, tag uint8 return } -func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) { +func ReadFileAtoms(r io.ReadSeeker, name string) (atoms []Atom, err error) { for { offset, _ := r.Seek(0, 1) taghdr := make([]byte, 8) @@ -387,6 +387,12 @@ func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) { return } size := pio.U32BE(taghdr[0:]) + + if size == 0 { + err = fmt.Errorf("bad hdr size") + return + } + tag := Tag(pio.U32BE(taghdr[4:])) var atom Atom diff --git a/format/ts/muxer.go b/format/ts/muxer.go index c33f1ff..53bc6a0 100644 --- a/format/ts/muxer.go +++ b/format/ts/muxer.go @@ -2,6 +2,7 @@ package ts import ( "fmt" + "github.com/deepch/vdk/codec/h265parser" "io" "time" @@ -11,7 +12,7 @@ import ( "github.com/deepch/vdk/format/ts/tsio" ) -var CodecTypes = []av.CodecType{av.H264, av.AAC} +var CodecTypes = []av.CodecType{av.H264, av.H265, av.AAC} type Muxer struct { w io.Writer @@ -123,6 +124,11 @@ func (self *Muxer) WritePATPMT() (err error) { StreamType: tsio.ElementaryStreamTypeH264, ElementaryPID: stream.pid, }) + case av.H265: + elemStreams = append(elemStreams, tsio.ElementaryStreamInfo{ + StreamType: tsio.ElementaryStreamTypeH265, + ElementaryPID: stream.pid, + }) } } @@ -210,6 +216,36 @@ func (self *Muxer) WritePacket(pkt av.Packet) (err error) { n := tsio.FillPESHeader(self.peshdr, tsio.StreamIdH264, -1, pkt.Time+pkt.CompositionTime, pkt.Time) datav[0] = self.peshdr[:n] + if err = stream.tsw.WritePackets(self.w, datav, pkt.Time, pkt.IsKeyFrame, false); err != nil { + return + } + case av.H265: + codec := stream.CodecData.(h265parser.CodecData) + + nalus := self.nalus[:0] + if pkt.IsKeyFrame { + nalus = append(nalus, codec.SPS()) + nalus = append(nalus, codec.PPS()) + nalus = append(nalus, codec.VPS()) + } + pktnalus, _ := h265parser.SplitNALUs(pkt.Data) + for _, nalu := range pktnalus { + nalus = append(nalus, nalu) + } + + datav := self.datav[:1] + for i, nalu := range nalus { + if i == 0 { + datav = append(datav, h265parser.AUDBytes) + } else { + datav = append(datav, h265parser.StartCodeBytes) + } + datav = append(datav, nalu) + } + + n := tsio.FillPESHeader(self.peshdr, tsio.StreamIdH264, -1, pkt.Time+pkt.CompositionTime, pkt.Time) + datav[0] = self.peshdr[:n] + if err = stream.tsw.WritePackets(self.w, datav, pkt.Time, pkt.IsKeyFrame, false); err != nil { return } diff --git a/format/ts/tsio/tsio.go b/format/ts/tsio/tsio.go index 3fc616e..362e385 100644 --- a/format/ts/tsio/tsio.go +++ b/format/ts/tsio/tsio.go @@ -36,6 +36,7 @@ const ( ElementaryStreamTypeH264 = 0x1B ElementaryStreamTypeAdtsAAC = 0x0F ElementaryStreamTypeAlignmentDescriptor = 0x06 + ElementaryStreamTypeH265 = 0x24 ) type PATEntry struct { @@ -516,7 +517,7 @@ func NewTSWriter(pid uint16) *TSWriter { return w } -//TSHeader func +// TSHeader func type TSHeader struct { PID uint PCR uint64 @@ -528,7 +529,7 @@ type TSHeader struct { HeaderLength uint } -//WriteTSHeader func +// WriteTSHeader func func WriteTSHeader(w io.Writer, element TSHeader, dataLength int) (written int, err error) { var flags, extFlags uint @@ -688,13 +689,13 @@ func makeRepeatValBytes(val byte, n int) []byte { return b } -//WriteRepeatVal func +// WriteRepeatVal func func WriteRepeatVal(w io.Writer, val byte, n int) (err error) { _, err = w.Write(makeRepeatValBytes(val, n)) return } -//WriteUInt64 func +// WriteUInt64 func func WriteUInt64(w io.Writer, val uint64, n int) (err error) { var b [8]byte for i := n - 1; i >= 0; i-- { @@ -707,12 +708,12 @@ func WriteUInt64(w io.Writer, val uint64, n int) (err error) { return } -//WriteUInt func +// WriteUInt func func WriteUInt(w io.Writer, val uint, n int) (err error) { return WriteUInt64(w, uint64(val), n) } -//PCRToUInt func +// PCRToUInt func func PCRToUInt(pcr uint64) uint64 { base := pcr / 300 ext := pcr % 300 From def88cb695aa222f7bc73dc7bb920c6963badd3c Mon Sep 17 00:00:00 2001 From: deepch Date: Wed, 22 Mar 2023 22:01:39 +0300 Subject: [PATCH 04/25] test transcode slow --- format/mp4m/mp4io/mp4io.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/format/mp4m/mp4io/mp4io.go b/format/mp4m/mp4io/mp4io.go index 5ce5ce8..0aab546 100644 --- a/format/mp4m/mp4io/mp4io.go +++ b/format/mp4m/mp4io/mp4io.go @@ -376,7 +376,7 @@ func (self *ElemStreamDesc) parseDescHdr(b []byte, offset int) (n int, tag uint8 return } -func ReadFileAtoms(r io.ReadSeeker, name string) (atoms []Atom, err error) { +func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) { for { offset, _ := r.Seek(0, 1) taghdr := make([]byte, 8) From 89581975483914418c470eac4b263c50fc0d1d22 Mon Sep 17 00:00:00 2001 From: deepch Date: Sun, 2 Apr 2023 17:58:56 +0300 Subject: [PATCH 05/25] fix ip camera bug --- format/rtsp/client.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/format/rtsp/client.go b/format/rtsp/client.go index 1e54ce6..89a9d89 100644 --- a/format/rtsp/client.go +++ b/format/rtsp/client.go @@ -9,7 +9,6 @@ import ( "encoding/hex" "fmt" "io" - //"log" "net" "net/textproto" "net/url" @@ -147,7 +146,12 @@ func (self *Client) probe() (err error) { } func (self *Client) prepare(stage int) (err error) { + var waitIdle int for self.stage < stage { + waitIdle++ + if waitIdle > 20 { + return fmt.Errorf("codec not ready") + } switch self.stage { case 0: if err = self.Options(); err != nil { @@ -695,7 +699,9 @@ func (self *Client) Describe() (streams []sdp.Media, err error) { self.streams = []*Stream{} for _, media := range medias { stream := &Stream{Sdp: media, client: self} - stream.makeCodecData() + if err = stream.makeCodecData(); err != nil && DebugRtsp { + fmt.Println("rtsp: makeCodecData error", err) + } self.streams = append(self.streams, stream) streams = append(streams, media) } @@ -767,7 +773,7 @@ func (self *Stream) timeScale() int { func (self *Stream) makeCodecData() (err error) { media := self.Sdp - if media.PayloadType >= 96 && media.PayloadType <= 127 { + if (media.PayloadType >= 96 && media.PayloadType <= 127) || media.Type == av.H264 || media.Type == av.AAC { switch media.Type { case av.H264: for _, nalu := range media.SpropParameterSets { From 8d4be0821cc93265a85555611c8c68cfb25b75c9 Mon Sep 17 00:00:00 2001 From: deepch Date: Thu, 25 May 2023 12:00:15 +0300 Subject: [PATCH 06/25] test --- format/rtspv2/proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/format/rtspv2/proxy.go b/format/rtspv2/proxy.go index c5a5f4e..df3ff3f 100644 --- a/format/rtspv2/proxy.go +++ b/format/rtspv2/proxy.go @@ -40,7 +40,7 @@ func NewProxyConn(netconn net.Conn) *ProxyConn { conn.writebuf = make([]byte, 4096) conn.readbuf = make([]byte, 4096) conn.session = uuid.New().String() - conn.cseq = 1 + conn.cseq = 0 return conn } From 9e244f72bfed2498c2b308926b57d0d031e1bd4d Mon Sep 17 00:00:00 2001 From: deepch Date: Thu, 25 May 2023 12:35:12 +0300 Subject: [PATCH 07/25] test --- format/rtspv2/proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/format/rtspv2/proxy.go b/format/rtspv2/proxy.go index df3ff3f..c5a5f4e 100644 --- a/format/rtspv2/proxy.go +++ b/format/rtspv2/proxy.go @@ -40,7 +40,7 @@ func NewProxyConn(netconn net.Conn) *ProxyConn { conn.writebuf = make([]byte, 4096) conn.readbuf = make([]byte, 4096) conn.session = uuid.New().String() - conn.cseq = 0 + conn.cseq = 1 return conn } From 0b08aa7224a0e0dbbfe1833852c80db85c08d3a4 Mon Sep 17 00:00:00 2001 From: deepch Date: Thu, 25 May 2023 13:07:13 +0300 Subject: [PATCH 08/25] test --- format/rtspv2/proxy.go | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/format/rtspv2/proxy.go b/format/rtspv2/proxy.go index c5a5f4e..c46f08c 100644 --- a/format/rtspv2/proxy.go +++ b/format/rtspv2/proxy.go @@ -3,6 +3,7 @@ package rtspv2 import ( "errors" "fmt" + "log" "net" "net/url" "strconv" @@ -25,6 +26,7 @@ type ProxyConn struct { cseq int session string protocol int + in int } type Proxy struct { @@ -40,7 +42,6 @@ func NewProxyConn(netconn net.Conn) *ProxyConn { conn.writebuf = make([]byte, 4096) conn.readbuf = make([]byte, 4096) conn.session = uuid.New().String() - conn.cseq = 1 return conn } @@ -156,6 +157,7 @@ func (self *ProxyConn) prepare() error { return errors.New("no fist cmd") } + cseq := strings.TrimSpace(stringInBetween(string(self.readbuf[:n]), "CSeq:", "\r\n")) switch fistStringsSlice[0] { case OPTIONS: @@ -165,45 +167,47 @@ func (self *ProxyConn) prepare() error { if self.URL, err = url.Parse(fistStringsSlice[1]); err != nil { return err } - _, err := self.netconn.Write([]byte("RTSP/1.0 200 OK\r\nPublic: OPTIONS, DESCRIBE, SETUP, PLAY\r\nSession: " + self.session + "\r\nCSeq: " + strconv.Itoa(self.cseq) + "\r\n\r\n")) + _, err := self.netconn.Write([]byte("RTSP/1.0 200 OK\r\nPublic: OPTIONS, DESCRIBE, SETUP, PLAY\r\nSession: " + self.session + "\r\nCSeq: " + cseq + "\r\n\r\n")) if err != nil { return err } self.options = true case SETUP: - if strings.Contains(string(self.readbuf[:n]), "RTP/AVP/UDP") { - _, err := self.netconn.Write([]byte("RTSP/1.0 461 Unsupported transport\r\nCSeq: " + strconv.Itoa(self.cseq) + "\r\nSession: " + self.session + "\r\n\r\n")) + _, err := self.netconn.Write([]byte("RTSP/1.0 461 Unsupported transport\r\nCSeq: " + cseq + "\r\nSession: " + self.session + "\r\n\r\n")) if err != nil { return err } return nil } - _, err := self.netconn.Write([]byte("RTSP/1.0 200 OK\r\nCSeq: " + strconv.Itoa(self.cseq) + "\r\nSession: " + self.session + "\r\nTransport: RTP/AVP/TCP;unicast;interleaved=0-1\r\n\r\n")) + log.Println("RTSP/1.0 200 OK\r\nCSeq: " + cseq + "\r\nSession: " + self.session + "\r\nTransport: RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(self.in) + "-" + strconv.Itoa(self.in+1) + "\r\n\r\n") + _, err := self.netconn.Write([]byte("RTSP/1.0 200 OK\r\nCSeq: " + cseq + "\r\nSession: " + self.session + "\r\nTransport: RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(self.in) + "-" + strconv.Itoa(self.in+1) + "\r\n\r\n")) if err != nil { return err } - + self.in = self.in + 2 case DESCRIBE: - buf := "RTSP/1.0 200 OK\r\nContent-Type: application/sdp\r\nSession: " + self.session + "\r\nContent-Length: " + strconv.Itoa(len(self.sdp)) + "\r\nCSeq: " + strconv.Itoa(self.cseq) + "\r\n\r\n" + buf := "RTSP/1.0 200 OK\r\nContent-Type: application/sdp\r\nSession: " + self.session + "\r\nContent-Length: " + strconv.Itoa(len(self.sdp)) + "\r\nCSeq: " + cseq + "\r\n\r\n" _, err := self.netconn.Write([]byte(buf + string(self.sdp))) if err != nil { return err } case PLAY: - - _, err := self.netconn.Write([]byte("RTSP/1.0 200 OK\r\nSession: " + self.session + ";timeout=60\r\nCSeq: " + strconv.Itoa(self.cseq) + "\r\n\r\n")) + _, err := self.netconn.Write([]byte("RTSP/1.0 200 OK\r\nSession: " + self.session + ";timeout=60\r\nCSeq: " + cseq + "\r\n\r\n")) if err != nil { return err } self.playing = true + case TEARDOWN: + self.netconn.Close() + return errors.New("exit") default: - return errors.New("metod not found") + return errors.New("metod not found " + fistStringsSlice[0]) } return nil From 5a989a5c40319489e063ee61afb58aac8ec5da03 Mon Sep 17 00:00:00 2001 From: deepch Date: Thu, 25 May 2023 13:08:57 +0300 Subject: [PATCH 09/25] test --- format/rtspv2/proxy.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/format/rtspv2/proxy.go b/format/rtspv2/proxy.go index c46f08c..d7c868d 100644 --- a/format/rtspv2/proxy.go +++ b/format/rtspv2/proxy.go @@ -3,7 +3,6 @@ package rtspv2 import ( "errors" "fmt" - "log" "net" "net/url" "strconv" @@ -181,7 +180,6 @@ func (self *ProxyConn) prepare() error { } return nil } - log.Println("RTSP/1.0 200 OK\r\nCSeq: " + cseq + "\r\nSession: " + self.session + "\r\nTransport: RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(self.in) + "-" + strconv.Itoa(self.in+1) + "\r\n\r\n") _, err := self.netconn.Write([]byte("RTSP/1.0 200 OK\r\nCSeq: " + cseq + "\r\nSession: " + self.session + "\r\nTransport: RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(self.in) + "-" + strconv.Itoa(self.in+1) + "\r\n\r\n")) if err != nil { return err From 9d21d056dde27a4a49be348f86b43b3bc6b14d10 Mon Sep 17 00:00:00 2001 From: deepch Date: Fri, 25 Aug 2023 14:35:34 +0300 Subject: [PATCH 10/25] test --- format/rtspv2/client.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/format/rtspv2/client.go b/format/rtspv2/client.go index 17bf659..8e75717 100644 --- a/format/rtspv2/client.go +++ b/format/rtspv2/client.go @@ -150,9 +150,12 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) { if err != nil { return nil, err } - for _, i2 := range client.mediaSDP { if (i2.AVType != VIDEO && i2.AVType != AUDIO) || (client.options.DisableAudio && i2.AVType == AUDIO) { + //TODO check it + if strings.Contains(string(client.SDPRaw), "LaunchDigital") { + client.chTMP += 2 + } continue } err = client.request(SETUP, map[string]string{"Transport": "RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(client.chTMP) + "-" + strconv.Itoa(client.chTMP+1)}, client.ControlTrack(i2.Control), false, false) @@ -945,14 +948,14 @@ func (client *RTSPClient) CodecUpdateVPS(val []byte) { } -//Println mini logging functions +// Println mini logging functions func (client *RTSPClient) Println(v ...interface{}) { if client.options.Debug { log.Println(v) } } -//binSize +// binSize func binSize(val int) []byte { buf := make([]byte, 4) binary.BigEndian.PutUint32(buf, uint32(val)) From eaab841cfbad405969118cabf2b34272804353d7 Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Mon, 20 Nov 2023 10:00:15 +0300 Subject: [PATCH 11/25] Update mp4io.go --- format/mp4/mp4io/mp4io.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/format/mp4/mp4io/mp4io.go b/format/mp4/mp4io/mp4io.go index dfa99d5..ce410d1 100644 --- a/format/mp4/mp4io/mp4io.go +++ b/format/mp4/mp4io/mp4io.go @@ -387,6 +387,10 @@ func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) { return } size := pio.U32BE(taghdr[0:]) + if size > 5242880 { + err = parseErr("len", 5242880, err) + return + } tag := Tag(pio.U32BE(taghdr[4:])) var atom Atom From 975d994507b8e307e5966929e10171cef95dfc37 Mon Sep 17 00:00:00 2001 From: deepch Date: Mon, 8 Jan 2024 17:35:54 +0300 Subject: [PATCH 12/25] testing --- av/pktque/filters.go | 2 +- codec/h264parser/parser.go | 12 +- format/mse/muxer.go | 77 +++++++++ format/nvr/muxer.go | 321 +++++++++++++++++++++++++++++++------ format/nvr/streams.go | 8 + format/rtmp/rtmp.go | 5 +- format/rtspv2/client.go | 5 +- go.mod | 32 ++-- go.sum | 54 +++++++ 9 files changed, 452 insertions(+), 64 deletions(-) create mode 100644 format/mse/muxer.go create mode 100644 format/nvr/streams.go diff --git a/av/pktque/filters.go b/av/pktque/filters.go index 54f683c..f7c4ab7 100644 --- a/av/pktque/filters.go +++ b/av/pktque/filters.go @@ -36,7 +36,7 @@ type FilterDemuxer struct { audioidx int } -func (self FilterDemuxer) ReadPacket() (pkt av.Packet, err error) { +func (self *FilterDemuxer) ReadPacket() (pkt av.Packet, err error) { if self.streams == nil { if self.streams, err = self.Demuxer.Streams(); err != nil { return diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index 271eb8e..bf1817a 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -665,11 +665,19 @@ func (self CodecData) AVCDecoderConfRecordBytes() []byte { } func (self CodecData) SPS() []byte { - return self.RecordInfo.SPS[0] + if len(self.RecordInfo.SPS) > 0 { + return self.RecordInfo.SPS[0] + } + + return []byte{0} } func (self CodecData) PPS() []byte { - return self.RecordInfo.PPS[0] + if len(self.RecordInfo.PPS) > 0 { + return self.RecordInfo.PPS[0] + } + + return []byte{0} } func (self CodecData) Width() int { diff --git a/format/mse/muxer.go b/format/mse/muxer.go new file mode 100644 index 0000000..b28c9b2 --- /dev/null +++ b/format/mse/muxer.go @@ -0,0 +1,77 @@ +package mse + +import ( + "github.com/deepch/vdk/av" + "github.com/deepch/vdk/format/mp4f" + "github.com/gobwas/ws" + "github.com/gobwas/ws/wsutil" + "net" + "net/http" +) + +var Debug bool + +type Muxer struct { + m *mp4f.Muxer + r *http.Request + w http.ResponseWriter + conn net.Conn +} + +func NewMuxer(r *http.Request, w http.ResponseWriter) (*Muxer, error) { + conn, _, _, err := ws.UpgradeHTTP(r, w) + if err != nil { + return nil, err + } + go func() { + defer func() { + conn.Close() + }() + for { + if _, _, err = wsutil.NextReader(conn, ws.StateServerSide); err != nil { + return + } + } + }() + + return &Muxer{ + conn: conn, + m: mp4f.NewMuxer(nil), + r: r, + w: w, + }, nil +} + +func (m *Muxer) WriteHeader(streams []av.CodecData) (err error) { + if err = m.m.WriteHeader(streams); err != nil { + return + } + meta, fist := m.m.GetInit(streams) + if err = wsutil.WriteServerText(m.conn, []byte(meta)); err != nil { + return + } + if err = wsutil.WriteServerBinary(m.conn, fist); err != nil { + return + } + + return +} + +func (m *Muxer) WritePacket(pkt av.Packet) (err error) { + gotFrame, buffer, err := m.m.WritePacket(pkt, false) + if err != nil { + return + } + if gotFrame { + if err = wsutil.WriteServerBinary(m.conn, buffer); err != nil { + return + } + } + + return +} + +func (m *Muxer) WriteTrailer() (err error) { + + return m.conn.Close() +} diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index 7dbc02b..63347b1 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -1,59 +1,286 @@ package nvr import ( - "log" - "os" - "time" - + "bytes" + "encoding/binary" + "encoding/gob" + "fmt" "github.com/deepch/vdk/av" + "github.com/deepch/vdk/codec/aacparser" + "github.com/deepch/vdk/codec/h264parser" + "github.com/deepch/vdk/format/mp4" + "os" + "path/filepath" + "strings" + "time" +) + +var MIME = []byte{11, 22, 111, 222, 11, 22, 111, 222} +var listTag = []string{"{host_name}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} + +const ( + MP4 = "mp4" + NVR = "nvr" ) type Muxer struct { - name string - patch string - started bool - file *os.File - codec []av.CodecData - buffer []*av.Packet - bufferDur time.Duration - seqDur time.Duration + muxer *mp4.Muxer + format string + limit int + d *os.File + m *os.File + dur time.Duration + h int + gof *Gof + patch string + start, end time.Time + pstart, pend time.Duration + started bool + hostName, streamName, channelName, streamID, channelID string } -//NewMuxer func -func NewMuxer(codec []av.CodecData, name, patch string, seqDur time.Duration) *Muxer { - return &Muxer{ - codec: codec, - name: name, - patch: patch, - seqDur: seqDur, +type Gof struct { + Streams []av.CodecData + Packet []av.Packet +} + +type Data struct { + Time int64 + Start int64 + Dur int64 +} + +const ( + B = 1 + KB = 1024 * B + MB = 1024 * KB + GB = 1024 * MB +) + +func init() { + gob.RegisterName("nvr.Gof", Gof{}) + gob.RegisterName("h264parser.CodecData", h264parser.CodecData{}) + gob.RegisterName("aacparser.CodecData", aacparser.CodecData{}) + +} + +func NewMuxer(hostName, streamName, channelName, streamID, channelID, patch string, format string, limit int) (m *Muxer, err error) { + m = &Muxer{ + patch: patch, + h: -1, + gof: &Gof{}, + format: format, + limit: limit, + hostName: hostName, + streamName: streamName, + channelName: channelName, + streamID: streamID, + channelID: channelID, } -} - -//WritePacket func -func (obj *Muxer) CodecUpdate(val []av.CodecData) { - obj.codec = val -} - -//WritePacket func -func (obj *Muxer) WritePacket(pkt *av.Packet) (err error) { - if !obj.started && pkt.IsKeyFrame { - obj.started = true - } - if obj.started { - if pkt.IsKeyFrame && obj.bufferDur >= obj.seqDur { - log.Println("write to drive", len(obj.buffer), obj.bufferDur) - obj.buffer = nil - obj.bufferDur = 0 - } - obj.buffer = append(obj.buffer, pkt) - if pkt.Idx == 0 { - obj.bufferDur += pkt.Duration - } - } - return nil -} - -//Close func -func (obj *Muxer) Close() { + return +} + +func (m *Muxer) WriteHeader(streams []av.CodecData) (err error) { + m.gof.Streams = streams + if m.format == MP4 { + m.OpenMP4() + } + + return +} + +func (m *Muxer) WritePacket(pkt av.Packet) (err error) { + if len(m.gof.Streams) == 0 { + return + } + if !m.started && pkt.IsKeyFrame { + m.started = true + } + if m.started { + switch m.format { + case MP4: + return m.writePacketMP4(pkt) + case NVR: + return m.writePacketNVR(pkt) + } + } + + return +} + +func (m *Muxer) writePacketMP4(pkt av.Packet) (err error) { + if pkt.IsKeyFrame && m.dur > time.Duration(m.limit)*time.Second { + m.pstart = pkt.Time + m.OpenMP4() + m.dur = 0 + } + m.dur += pkt.Duration + m.pend = pkt.Time + return m.muxer.WritePacket(pkt) +} + +func (m *Muxer) writePacketNVR(pkt av.Packet) (err error) { + if pkt.IsKeyFrame { + if len(m.gof.Packet) > 0 { + if err = m.writeGop(); err != nil { + return + } + } + m.gof.Packet, m.dur = nil, 0 + } + if pkt.Idx == 0 { + m.dur += pkt.Duration + } + m.gof.Packet = append(m.gof.Packet, pkt) + + return +} + +func (m *Muxer) writeGop() (err error) { + t := time.Now().UTC() + if m.h != t.Hour() { + if err = m.OpenNVR(); err != nil { + return + } + } + f := Data{ + Time: t.UnixNano(), + Dur: m.dur.Milliseconds(), + } + if f.Start, err = m.d.Seek(0, 2); err != nil { + return + } + enc := gob.NewEncoder(m.d) + if err = enc.Encode(m.gof); err != nil { + return + } + buf := bytes.NewBuffer([]byte{}) + if err = binary.Write(buf, binary.LittleEndian, f); err != nil { + return + } + if _, err = buf.Write(MIME); err != nil { + return + } + _, err = m.m.Write(buf.Bytes()) + + return +} + +func (m *Muxer) OpenNVR() (err error) { + m.WriteTrailer() + t := time.Now().UTC() + if err = os.MkdirAll(fmt.Sprintf("%s/%s", m.patch, t.Format("2006/01/02")), 0755); err != nil { + return + } + if m.d, err = os.OpenFile(fmt.Sprintf("%s/%s/%d.d", m.patch, t.Format("2006/01/02"), t.Hour()), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660); err != nil { + return + } + if m.m, err = os.OpenFile(fmt.Sprintf("%s/%s/%d.m", m.patch, t.Format("2006/01/02"), t.Hour()), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660); err != nil { + return + } + m.h = t.Hour() + + return +} + +func (m *Muxer) OpenMP4() (err error) { + m.WriteTrailer() + m.start = time.Now().UTC() + if m.d, err = os.CreateTemp("", "rtspvideo.*.mp4"); err != nil { + return + } + m.muxer = mp4.NewMuxer(m.d) + if err = m.muxer.WriteHeader(m.gof.Streams); err != nil { + return + } + + return +} + +func (m *Muxer) filePatch() string { + ts := m.patch + m.end = time.Now().UTC() + for _, s := range listTag { + switch s { + case "{host_name}": + ts = strings.Replace(ts, "{host_name}", m.hostName, -1) + case "{stream_name}": + ts = strings.Replace(ts, "{stream_name}", m.streamName, -1) + case "{channel_name}": + ts = strings.Replace(ts, "{channel_name}", m.channelName, -1) + case "{stream_id}": + ts = strings.Replace(ts, "{stream_id}", m.streamID, -1) + case "{channel_id}": + ts = strings.Replace(ts, "{channel_id}", m.channelID, -1) + case "{start_year}": + ts = strings.Replace(ts, "{start_year}", fmt.Sprintf("%d", m.start.Year()), -1) + case "{start_month}": + ts = strings.Replace(ts, "{start_month}", fmt.Sprintf("%02d", int(m.start.Month())), -1) + case "{start_day}": + ts = strings.Replace(ts, "{start_day}", fmt.Sprintf("%02d", m.start.Day()), -1) + case "{start_minute}": + ts = strings.Replace(ts, "{start_minute}", fmt.Sprintf("%02d", m.start.Minute()), -1) + case "{start_second}": + ts = strings.Replace(ts, "{start_second}", fmt.Sprintf("%02d", m.start.Second()), -1) + case "{start_millisecond}": + ts = strings.Replace(ts, "{start_millisecond}", fmt.Sprintf("%d", m.start.Nanosecond()/1000/1000), -1) + case "{start_unix_millisecond}": + ts = strings.Replace(ts, "{start_unix_millisecond}", fmt.Sprintf("%d", m.end.UnixMilli()), -1) + case "{start_unix_second}": + ts = strings.Replace(ts, "{start_unix_second}", fmt.Sprintf("%d", m.end.Unix()), -1) + case "{start_time}": + ts = strings.Replace(ts, "{start_time}", fmt.Sprintf("%s", m.start.Format("2006-01-02T15:04:05-0700")), -1) + case "{start_pts}": + ts = strings.Replace(ts, "{start_pts}", fmt.Sprintf("%d", m.pstart.Milliseconds()), -1) + case "{end_year}": + ts = strings.Replace(ts, "{end_year}", fmt.Sprintf("%d", m.end.Year()), -1) + case "{end_month}": + ts = strings.Replace(ts, "{end_month}", fmt.Sprintf("%02d", int(m.end.Month())), -1) + case "{end_day}": + ts = strings.Replace(ts, "{end_day}", fmt.Sprintf("%02d", m.end.Day()), -1) + case "{end_minute}": + ts = strings.Replace(ts, "{end_minute}", fmt.Sprintf("%02d", m.end.Minute()), -1) + case "{end_second}": + ts = strings.Replace(ts, "{end_second}", fmt.Sprintf("%02d", m.end.Second()), -1) + case "{end_millisecond}": + ts = strings.Replace(ts, "{end_millisecond}", fmt.Sprintf("%d", m.start.Nanosecond()/1000/1000), -1) + case "{end_unix_millisecond}": + ts = strings.Replace(ts, "{end_unix_millisecond}", fmt.Sprintf("%d", m.end.UnixMilli()), -1) + case "{end_unix_second}": + ts = strings.Replace(ts, "{end_unix_second}", fmt.Sprintf("%d", m.end.Unix()), -1) + case "{end_time}": + ts = strings.Replace(ts, "{end_time}", fmt.Sprintf("%s", m.end.Format("2006-01-02T15:04:05-0700")), -1) + case "{end_pts}": + ts = strings.Replace(ts, "{end_pts}", fmt.Sprintf("%d", m.pend.Milliseconds()), -1) + case "{duration_second}": + ts = strings.Replace(ts, "{duration_second}", fmt.Sprintf("%f", m.dur.Seconds()), -1) + case "{duration_millisecond}": + ts = strings.Replace(ts, "{duration_millisecond}", fmt.Sprintf("%d", m.dur.Milliseconds()), -1) + } + } + + return ts +} + +func (m *Muxer) WriteTrailer() (err error) { + if m.muxer != nil { + m.muxer.WriteTrailer() + } + if m.m != nil { + err = m.m.Close() + } + if m.d != nil { + if m.format == MP4 { + p := m.filePatch() + if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { + return + } + if err = os.Rename(m.d.Name(), p); err != nil { + return + } + } + err = m.d.Close() + } + return } diff --git a/format/nvr/streams.go b/format/nvr/streams.go new file mode 100644 index 0000000..e0d0d9b --- /dev/null +++ b/format/nvr/streams.go @@ -0,0 +1,8 @@ +package nvr + +import "github.com/deepch/vdk/av" + +type Stream struct { + codec av.CodecData + idx int +} diff --git a/format/rtmp/rtmp.go b/format/rtmp/rtmp.go index 67eff90..4ede335 100644 --- a/format/rtmp/rtmp.go +++ b/format/rtmp/rtmp.go @@ -258,7 +258,10 @@ func (self *Conn) RxBytes() uint64 { } func (self *Conn) Close() (err error) { - return self.netconn.Close() + if self.netconn != nil { + return self.netconn.Close() + } + return } func (self *Conn) pollCommand() (err error) { diff --git a/format/rtspv2/client.go b/format/rtspv2/client.go index 8e75717..e244a39 100644 --- a/format/rtspv2/client.go +++ b/format/rtspv2/client.go @@ -592,6 +592,9 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { } } offset += 4 + if len(content) < end { + return nil, false + } switch int(content[1]) { case client.videoID: if client.PreVideoTS == 0 { @@ -750,7 +753,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { } } default: - client.Println("Unsupported NAL Type", naluType) + //client.Println("Unsupported NAL Type", naluType) } } } diff --git a/go.mod b/go.mod index 7f6afcb..8049fd1 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,18 @@ go 1.18 require ( github.com/google/uuid v1.3.0 - github.com/pion/interceptor v0.1.12 + github.com/pion/interceptor v0.1.17 github.com/pion/webrtc/v2 v2.2.26 - github.com/pion/webrtc/v3 v3.1.58 + github.com/pion/webrtc/v3 v3.2.12 ) require ( github.com/cheekybits/genny v1.0.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.3.1 // indirect github.com/golang/mock v1.6.0 // indirect github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect github.com/lucas-clemente/quic-go v0.31.1 // indirect @@ -20,30 +24,34 @@ require ( github.com/marten-seemann/qtls-go1-19 v0.1.2 // indirect github.com/onsi/ginkgo/v2 v2.9.0 // indirect github.com/pion/datachannel v1.5.5 // indirect - github.com/pion/dtls/v2 v2.2.6 // indirect + github.com/pion/dtls/v2 v2.2.7 // indirect github.com/pion/ice v0.7.18 // indirect - github.com/pion/ice/v2 v2.3.1 // indirect + github.com/pion/ice/v2 v2.3.9 // indirect github.com/pion/logging v0.2.2 // indirect github.com/pion/mdns v0.0.7 // indirect github.com/pion/quic v0.1.4 // indirect github.com/pion/randutil v0.1.0 // indirect github.com/pion/rtcp v1.2.10 // indirect github.com/pion/rtp v1.7.13 // indirect - github.com/pion/sctp v1.8.6 // indirect + github.com/pion/sctp v1.8.7 // indirect github.com/pion/sdp/v2 v2.4.0 // indirect github.com/pion/sdp/v3 v3.0.6 // indirect github.com/pion/srtp v1.5.2 // indirect - github.com/pion/srtp/v2 v2.0.12 // indirect - github.com/pion/stun v0.4.0 // indirect + github.com/pion/srtp/v2 v2.0.15 // indirect + github.com/pion/stun v0.6.1 // indirect github.com/pion/transport v0.14.1 // indirect - github.com/pion/transport/v2 v2.0.2 // indirect - github.com/pion/turn/v2 v2.1.0 // indirect + github.com/pion/transport/v2 v2.2.1 // indirect + github.com/pion/turn/v2 v2.1.2 // indirect github.com/pion/udp v0.1.4 // indirect github.com/pion/udp/v2 v2.0.1 // indirect - golang.org/x/crypto v0.7.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/tejasmanohar/timerange-go v1.0.0 // indirect + golang.org/x/crypto v0.10.0 // indirect golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 // indirect golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect + golang.org/x/net v0.11.0 // indirect + golang.org/x/sys v0.9.0 // indirect golang.org/x/tools v0.7.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ca397f4..4e67a7a 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,12 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.3.1 h1:Qi34dfLMWJbiKaNbDVzM9x27nZBjmkaW6i4+Ku+pGVU= +github.com/gobwas/ws v1.3.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -135,16 +141,22 @@ github.com/pion/dtls/v2 v2.1.5 h1:jlh2vtIyUBShchoTDqpCCqiYCyRFJ/lvf/gQ8TALs+c= github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY= github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4= github.com/pion/dtls/v2 v2.2.6/go.mod h1:t8fWJCIquY5rlQZwA2yWxUS1+OCrAdXrhVKXB5oD/wY= +github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= github.com/pion/ice v0.7.18 h1:KbAWlzWRUdX9SmehBh3gYpIFsirjhSQsCw6K2MjYMK0= github.com/pion/ice v0.7.18/go.mod h1:+Bvnm3nYC6Nnp7VV6glUkuOfToB/AtMRZpOU8ihuf4c= github.com/pion/ice/v2 v2.2.6 h1:R/vaLlI1J2gCx141L5PEwtuGAGcyS6e7E0hDeJFq5Ig= github.com/pion/ice/v2 v2.2.6/go.mod h1:SWuHiOGP17lGromHTFadUe1EuPgFh/oCU6FCMZHooVE= github.com/pion/ice/v2 v2.3.1 h1:FQCmUfZe2Jpe7LYStVBOP6z1DiSzbIateih3TztgTjc= github.com/pion/ice/v2 v2.3.1/go.mod h1:aq2kc6MtYNcn4XmMhobAv6hTNJiHzvD0yXRz80+bnP8= +github.com/pion/ice/v2 v2.3.9 h1:7yZpHf3PhPxJGT4JkMj1Y8Rl5cQ6fB709iz99aeMd/U= +github.com/pion/ice/v2 v2.3.9/go.mod h1:lT3kv5uUIlHfXHU/ZRD7uKD/ufM202+eTa3C/umgGf4= github.com/pion/interceptor v0.1.11 h1:00U6OlqxA3FFB50HSg25J/8cWi7P6FbSzw4eFn24Bvs= github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= github.com/pion/interceptor v0.1.12 h1:CslaNriCFUItiXS5o+hh5lpL0t0ytQkFnUcbbCs2Zq8= github.com/pion/interceptor v0.1.12/go.mod h1:bDtgAD9dRkBZpWHGKaoKb42FhDHTG2rX8Ii9LRALLVA= +github.com/pion/interceptor v0.1.17 h1:prJtgwFh/gB8zMqGZoOgJPHivOwVAp61i2aG61Du/1w= +github.com/pion/interceptor v0.1.17/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.4/go.mod h1:R1sL0p50l42S5lJs91oNdUL58nm0QHrhxnSegr++qC0= @@ -176,6 +188,8 @@ github.com/pion/sctp v1.8.2/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0 github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= github.com/pion/sctp v1.8.6 h1:CUex11Vkt9YS++VhLf8b55O3VqKrWL6W3SDwX4jAqsI= github.com/pion/sctp v1.8.6/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= +github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw= +github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU= github.com/pion/sdp/v2 v2.4.0 h1:luUtaETR5x2KNNpvEMv/r4Y+/kzImzbz4Lm1z8eQNQI= github.com/pion/sdp/v2 v2.4.0/go.mod h1:L2LxrOpSTJbAns244vfPChbciR/ReU1KWfG04OpkR7E= github.com/pion/sdp/v3 v3.0.5 h1:ouvI7IgGl+V4CrqskVtr3AaTrPvPisEOxwgpdktctkU= @@ -190,10 +204,14 @@ github.com/pion/srtp/v2 v2.0.9 h1:JJq3jClmDFBPX/F5roEb0U19jSU7eUhyDqR/NZ34EKQ= github.com/pion/srtp/v2 v2.0.9/go.mod h1:5TtM9yw6lsH0ppNCehB/EjEUli7VkUgKSPJqWVqbhQ4= github.com/pion/srtp/v2 v2.0.12 h1:WrmiVCubGMOAObBU1vwWjG0H3VSyQHawKeer2PVA5rY= github.com/pion/srtp/v2 v2.0.12/go.mod h1:C3Ep44hlOo2qEYaq4ddsmK5dL63eLehXFbHaZ9F5V9Y= +github.com/pion/srtp/v2 v2.0.15 h1:+tqRtXGsGwHC0G0IUIAzRmdkHvriF79IHVfZGfHrQoA= +github.com/pion/srtp/v2 v2.0.15/go.mod h1:b/pQOlDrbB0HEH5EUAQXzSYxikFbNcNuKmF8tM0hCtw= 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/stun v0.4.0 h1:vgRrbBE2htWHy7l3Zsxckk7rkjnjOsSM7PHZnBwo8rk= github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= github.com/pion/transport v0.6.0/go.mod h1:iWZ07doqOosSLMhZ+FXUTq+TamDoXSllxpbGcfkCmbE= github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRhSzR+CZ8= github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE= @@ -208,11 +226,17 @@ github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99 github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= github.com/pion/transport/v2 v2.0.2 h1:St+8o+1PEzPT51O9bv+tH/KYYLMNR5Vwm5Z3Qkjsywg= github.com/pion/transport/v2 v2.0.2/go.mod h1:vrz6bUbFr/cjdwbnxq8OdDDzHf7JJfGsIRkxfpZoTA0= +github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= +github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= +github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= github.com/pion/turn/v2 v2.0.4/go.mod h1:1812p4DcGVbYVBTiraUmP50XoKye++AMkbfp+N27mog= github.com/pion/turn/v2 v2.0.8 h1:KEstL92OUN3k5k8qxsXHpr7WWfrdp7iJZHx99ud8muw= github.com/pion/turn/v2 v2.0.8/go.mod h1:+y7xl719J8bAEVpSXBXvTxStjJv3hbz9YFflvkpcGPw= github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI= github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs= +github.com/pion/turn/v2 v2.1.2 h1:wj0cAoGKltaZ790XEGW9HwoUewqjliwmhtxCuB2ApyM= +github.com/pion/turn/v2 v2.1.2/go.mod h1:1kjnPkBcex3dhCU2Am+AAmxDcGhLX3WnMfmkNpvSTQU= github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths= github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o= github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= @@ -226,6 +250,8 @@ github.com/pion/webrtc/v3 v3.1.42 h1:wJEQFIXVanptnQcHOLTuIo4AtGB2+mG2x4OhIhnITOA github.com/pion/webrtc/v3 v3.1.42/go.mod h1:ffD9DulDrPxyWvDPUIPAOSAWx9GUlOExiJPf7cCcMLA= github.com/pion/webrtc/v3 v3.1.58 h1:husXqiKQuk6gbOqJlPHs185OskAyxUW6iAEgHghgCrc= github.com/pion/webrtc/v3 v3.1.58/go.mod h1:jJdqoqGBlZiE3y8Z1tg1fjSkyEDCZLL+foypUBn0Lhk= +github.com/pion/webrtc/v3 v3.2.12 h1:pVqz5NdtTqyhKIhMcXR8bPp709kCf9blyAhDjoVRLvA= +github.com/pion/webrtc/v3 v3.2.12/go.mod h1:/Oz6K95CGWaN+3No+Z0NYvgOPOr3aY8UyTlMm/dec3A= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -276,7 +302,12 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tejasmanohar/timerange-go v1.0.0 h1:yCd/hWz0NRTU5Pu+f82rsFb0fwpVyJt0oKbAkqOi/ZI= +github.com/tejasmanohar/timerange-go v1.0.0/go.mod h1:tic3Puc+uofo0D7502PvYBlu5sJMszF5nGbsYsu7FiI= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -304,6 +335,9 @@ golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw= golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= @@ -314,6 +348,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -353,6 +388,10 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -367,6 +406,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -400,11 +440,19 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -417,6 +465,10 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -430,6 +482,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -477,6 +530,7 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 385d9cc93c58293d61c35a7776f4220f69356004 Mon Sep 17 00:00:00 2001 From: deepch Date: Mon, 8 Jan 2024 18:08:19 +0300 Subject: [PATCH 13/25] testing --- format/nvr/muxer.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index 63347b1..98a8f9d 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -215,13 +215,13 @@ func (m *Muxer) filePatch() string { case "{start_year}": ts = strings.Replace(ts, "{start_year}", fmt.Sprintf("%d", m.start.Year()), -1) case "{start_month}": - ts = strings.Replace(ts, "{start_month}", fmt.Sprintf("%02d", int(m.start.Month())), -1) + ts = strings.Replace(ts, "{start_month}", fmt.Sprintf("%d", int(m.start.Month())), -1) case "{start_day}": - ts = strings.Replace(ts, "{start_day}", fmt.Sprintf("%02d", m.start.Day()), -1) + ts = strings.Replace(ts, "{start_day}", fmt.Sprintf("%d", m.start.Day()), -1) case "{start_minute}": - ts = strings.Replace(ts, "{start_minute}", fmt.Sprintf("%02d", m.start.Minute()), -1) + ts = strings.Replace(ts, "{start_minute}", fmt.Sprintf("%d", m.start.Minute()), -1) case "{start_second}": - ts = strings.Replace(ts, "{start_second}", fmt.Sprintf("%02d", m.start.Second()), -1) + ts = strings.Replace(ts, "{start_second}", fmt.Sprintf("%d", m.start.Second()), -1) case "{start_millisecond}": ts = strings.Replace(ts, "{start_millisecond}", fmt.Sprintf("%d", m.start.Nanosecond()/1000/1000), -1) case "{start_unix_millisecond}": @@ -235,13 +235,13 @@ func (m *Muxer) filePatch() string { case "{end_year}": ts = strings.Replace(ts, "{end_year}", fmt.Sprintf("%d", m.end.Year()), -1) case "{end_month}": - ts = strings.Replace(ts, "{end_month}", fmt.Sprintf("%02d", int(m.end.Month())), -1) + ts = strings.Replace(ts, "{end_month}", fmt.Sprintf("%d", int(m.end.Month())), -1) case "{end_day}": - ts = strings.Replace(ts, "{end_day}", fmt.Sprintf("%02d", m.end.Day()), -1) + ts = strings.Replace(ts, "{end_day}", fmt.Sprintf("%d", m.end.Day()), -1) case "{end_minute}": - ts = strings.Replace(ts, "{end_minute}", fmt.Sprintf("%02d", m.end.Minute()), -1) + ts = strings.Replace(ts, "{end_minute}", fmt.Sprintf("%d", m.end.Minute()), -1) case "{end_second}": - ts = strings.Replace(ts, "{end_second}", fmt.Sprintf("%02d", m.end.Second()), -1) + ts = strings.Replace(ts, "{end_second}", fmt.Sprintf("%d", m.end.Second()), -1) case "{end_millisecond}": ts = strings.Replace(ts, "{end_millisecond}", fmt.Sprintf("%d", m.start.Nanosecond()/1000/1000), -1) case "{end_unix_millisecond}": From 4df258b8990c740468282c2f305cae5ecef2dde2 Mon Sep 17 00:00:00 2001 From: deepch Date: Wed, 10 Jan 2024 18:02:17 +0300 Subject: [PATCH 14/25] testing --- av/pktque/filters.go | 14 +++++++++++++ format/nvr/muxer.go | 49 +++++++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/av/pktque/filters.go b/av/pktque/filters.go index f7c4ab7..12fec5b 100644 --- a/av/pktque/filters.go +++ b/av/pktque/filters.go @@ -170,6 +170,20 @@ func (self *AVSync) check(i int) (start time.Duration, end time.Duration, correc return } +type CalcDuration struct { + LastTime map[int8]time.Duration +} + +func (self *CalcDuration) ModifyPacket(pkt *av.Packet, streams []av.CodecData, videoidx int, audioidx int) (drop bool, err error) { + if tmp, ok := self.LastTime[pkt.Idx]; ok && tmp != 0 { + pkt.Duration = pkt.Time - self.LastTime[pkt.Idx] + } else if pkt.Time < 100*time.Millisecond { + pkt.Duration = pkt.Time + } + self.LastTime[pkt.Idx] = pkt.Time + return +} + // Make packets reading speed as same as walltime, effect like ffmpeg -re option. type Walltime struct { firsttime time.Time diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index 98a8f9d..3be56d4 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -16,7 +16,7 @@ import ( ) var MIME = []byte{11, 22, 111, 222, 11, 22, 111, 222} -var listTag = []string{"{host_name}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} +var listTag = []string{"{server_id}", "{hostname_short}", "{hostname_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} const ( MP4 = "mp4" @@ -24,19 +24,19 @@ const ( ) type Muxer struct { - muxer *mp4.Muxer - format string - limit int - d *os.File - m *os.File - dur time.Duration - h int - gof *Gof - patch string - start, end time.Time - pstart, pend time.Duration - started bool - hostName, streamName, channelName, streamID, channelID string + muxer *mp4.Muxer + format string + limit int + d *os.File + m *os.File + dur time.Duration + h int + gof *Gof + patch string + start, end time.Time + pstart, pend time.Duration + started bool + serverID, streamName, channelName, streamID, channelID, hostname string } type Gof struct { @@ -64,18 +64,20 @@ func init() { } -func NewMuxer(hostName, streamName, channelName, streamID, channelID, patch string, format string, limit int) (m *Muxer, err error) { +func NewMuxer(serverID, streamName, channelName, streamID, channelID, patch string, format string, limit int) (m *Muxer, err error) { + hostname, _ := os.Hostname() m = &Muxer{ patch: patch, h: -1, gof: &Gof{}, format: format, limit: limit, - hostName: hostName, + serverID: serverID, streamName: streamName, channelName: channelName, streamID: streamID, channelID: channelID, + hostname: hostname, } return } @@ -186,7 +188,12 @@ func (m *Muxer) OpenNVR() (err error) { func (m *Muxer) OpenMP4() (err error) { m.WriteTrailer() m.start = time.Now().UTC() - if m.d, err = os.CreateTemp("", "rtspvideo.*.mp4"); err != nil { + + p := m.filePatch() + if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { + return + } + if m.d, err = os.Create(filepath.Dir(p) + "/tmp.mp4"); err != nil { return } m.muxer = mp4.NewMuxer(m.d) @@ -202,8 +209,12 @@ func (m *Muxer) filePatch() string { m.end = time.Now().UTC() for _, s := range listTag { switch s { - case "{host_name}": - ts = strings.Replace(ts, "{host_name}", m.hostName, -1) + case "{server_id}": + ts = strings.Replace(ts, "{host_name}", m.serverID, -1) + case "{hostname_short}": + ts = strings.Replace(ts, "{host_name}", m.hostname, -1) + case "{hostname_long}": + ts = strings.Replace(ts, "{host_name}", m.hostname, -1) case "{stream_name}": ts = strings.Replace(ts, "{stream_name}", m.streamName, -1) case "{channel_name}": From e4035e4407f0afd40b4ce9f9bee08f79786ddb1c Mon Sep 17 00:00:00 2001 From: deepch Date: Mon, 22 Jan 2024 11:36:06 +0300 Subject: [PATCH 15/25] testing --- format/nvr/muxer.go | 68 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index 3be56d4..0837ae1 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -4,11 +4,14 @@ import ( "bytes" "encoding/binary" "encoding/gob" + "errors" "fmt" "github.com/deepch/vdk/av" "github.com/deepch/vdk/codec/aacparser" "github.com/deepch/vdk/codec/h264parser" "github.com/deepch/vdk/format/mp4" + "github.com/moby/sys/mountinfo" + "github.com/shirou/gopsutil/v3/disk" "os" "path/filepath" "strings" @@ -16,7 +19,7 @@ import ( ) var MIME = []byte{11, 22, 111, 222, 11, 22, 111, 222} -var listTag = []string{"{server_id}", "{hostname_short}", "{hostname_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} +var listTag = []string{"{server_id}", "{host_name}", "{host_name_short}", "{host_name_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} const ( MP4 = "mp4" @@ -33,6 +36,7 @@ type Muxer struct { h int gof *Gof patch string + mpoint []string start, end time.Time pstart, pend time.Duration started bool @@ -64,9 +68,10 @@ func init() { } -func NewMuxer(serverID, streamName, channelName, streamID, channelID, patch string, format string, limit int) (m *Muxer, err error) { +func NewMuxer(serverID, streamName, channelName, streamID, channelID string, mpoint []string, patch, format string, limit int) (m *Muxer, err error) { hostname, _ := os.Hostname() m = &Muxer{ + mpoint: mpoint, patch: patch, h: -1, gof: &Gof{}, @@ -85,7 +90,7 @@ func NewMuxer(serverID, streamName, channelName, streamID, channelID, patch stri func (m *Muxer) WriteHeader(streams []av.CodecData) (err error) { m.gof.Streams = streams if m.format == MP4 { - m.OpenMP4() + return m.OpenMP4() } return @@ -113,11 +118,15 @@ func (m *Muxer) WritePacket(pkt av.Packet) (err error) { func (m *Muxer) writePacketMP4(pkt av.Packet) (err error) { if pkt.IsKeyFrame && m.dur > time.Duration(m.limit)*time.Second { m.pstart = pkt.Time - m.OpenMP4() + if err = m.OpenMP4(); err != nil { + return + } m.dur = 0 + } m.dur += pkt.Duration m.pend = pkt.Time + return m.muxer.WritePacket(pkt) } @@ -189,7 +198,10 @@ func (m *Muxer) OpenMP4() (err error) { m.WriteTrailer() m.start = time.Now().UTC() - p := m.filePatch() + p, err := m.filePatch() + if err != nil { + return + } if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { return } @@ -204,17 +216,40 @@ func (m *Muxer) OpenMP4() (err error) { return } -func (m *Muxer) filePatch() string { - ts := m.patch +func (m *Muxer) filePatch() (string, error) { + var ( + mu = float64(100) + ui = -1 + ) + + for i, i2 := range m.mpoint { + if m, err := mountinfo.Mounted(i2); err == nil && m { + if d, err := disk.Usage(i2); err == nil { + if d.UsedPercent < mu { + ui = i + mu = d.UsedPercent + } + } + } + } + + if ui == -1 { + return "", errors.New("not mount ready") + } + + ts := filepath.Join(m.mpoint[ui], m.patch) m.end = time.Now().UTC() + for _, s := range listTag { switch s { case "{server_id}": - ts = strings.Replace(ts, "{host_name}", m.serverID, -1) - case "{hostname_short}": - ts = strings.Replace(ts, "{host_name}", m.hostname, -1) - case "{hostname_long}": + ts = strings.Replace(ts, "{server_id}", m.serverID, -1) + case "{host_name}": ts = strings.Replace(ts, "{host_name}", m.hostname, -1) + case "{host_name_short}": + ts = strings.Replace(ts, "{host_name_short}", m.hostname, -1) + case "{host_name_long}": + ts = strings.Replace(ts, "{host_name_long}", m.hostname, -1) case "{stream_name}": ts = strings.Replace(ts, "{stream_name}", m.streamName, -1) case "{channel_name}": @@ -270,7 +305,7 @@ func (m *Muxer) filePatch() string { } } - return ts + return ts, nil } func (m *Muxer) WriteTrailer() (err error) { @@ -282,12 +317,15 @@ func (m *Muxer) WriteTrailer() (err error) { } if m.d != nil { if m.format == MP4 { - p := m.filePatch() + p, err := m.filePatch() + if err != nil { + return err + } if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { - return + return err } if err = os.Rename(m.d.Name(), p); err != nil { - return + return err } } err = m.d.Close() From a743575ac9904024a56918b94baf79d1b978d2c5 Mon Sep 17 00:00:00 2001 From: deepch Date: Mon, 22 Jan 2024 16:07:30 +0300 Subject: [PATCH 16/25] testing --- format/nvr/muxer.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index 0837ae1..3d061c9 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -10,6 +10,7 @@ import ( "github.com/deepch/vdk/codec/aacparser" "github.com/deepch/vdk/codec/h264parser" "github.com/deepch/vdk/format/mp4" + "github.com/google/uuid" "github.com/moby/sys/mountinfo" "github.com/shirou/gopsutil/v3/disk" "os" @@ -19,7 +20,7 @@ import ( ) var MIME = []byte{11, 22, 111, 222, 11, 22, 111, 222} -var listTag = []string{"{server_id}", "{host_name}", "{host_name_short}", "{host_name_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} +var listTag = []string{"{server_id}", "{host_name}", "{host_name_short}", "{host_name_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_hour}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_hour}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} const ( MP4 = "mp4" @@ -198,14 +199,14 @@ func (m *Muxer) OpenMP4() (err error) { m.WriteTrailer() m.start = time.Now().UTC() - p, err := m.filePatch() + d, err := m.filePatch() if err != nil { return } - if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { + if err = os.MkdirAll(filepath.Dir(d), 0755); err != nil { return } - if m.d, err = os.Create(filepath.Dir(p) + "/tmp.mp4"); err != nil { + if m.d, err = os.Create(filepath.Join(filepath.Dir(d), fmt.Sprintf("tmp_%s_%d.mp4", uuid.New(), time.Now().Unix()))); err != nil { return } m.muxer = mp4.NewMuxer(m.d) @@ -264,6 +265,8 @@ func (m *Muxer) filePatch() (string, error) { ts = strings.Replace(ts, "{start_month}", fmt.Sprintf("%d", int(m.start.Month())), -1) case "{start_day}": ts = strings.Replace(ts, "{start_day}", fmt.Sprintf("%d", m.start.Day()), -1) + case "{start_hour}": + ts = strings.Replace(ts, "{start_hour}", fmt.Sprintf("%d", m.start.Hour()), -1) case "{start_minute}": ts = strings.Replace(ts, "{start_minute}", fmt.Sprintf("%d", m.start.Minute()), -1) case "{start_second}": @@ -284,6 +287,8 @@ func (m *Muxer) filePatch() (string, error) { ts = strings.Replace(ts, "{end_month}", fmt.Sprintf("%d", int(m.end.Month())), -1) case "{end_day}": ts = strings.Replace(ts, "{end_day}", fmt.Sprintf("%d", m.end.Day()), -1) + case "{end_hour}": + ts = strings.Replace(ts, "{end_hour}", fmt.Sprintf("%d", m.end.Hour()), -1) case "{end_minute}": ts = strings.Replace(ts, "{end_minute}", fmt.Sprintf("%d", m.end.Minute()), -1) case "{end_second}": @@ -321,10 +326,7 @@ func (m *Muxer) WriteTrailer() (err error) { if err != nil { return err } - if err = os.MkdirAll(filepath.Dir(p), 0755); err != nil { - return err - } - if err = os.Rename(m.d.Name(), p); err != nil { + if err = os.Rename(m.d.Name(), filepath.Join(filepath.Dir(m.d.Name()), filepath.Base(p))); err != nil { return err } } From 7a563b07e3ba301410e6cf48b8f6b5186df51e3f Mon Sep 17 00:00:00 2001 From: deepch Date: Mon, 29 Jan 2024 12:46:06 +0300 Subject: [PATCH 17/25] testing --- format/mp4/muxer.go | 25 ++++++++++++++----------- format/mp4m/muxer.go | 17 +++++++++++------ format/nvr/muxer.go | 1 + 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/format/mp4/muxer.go b/format/mp4/muxer.go index d0e3578..fdcf696 100644 --- a/format/mp4/muxer.go +++ b/format/mp4/muxer.go @@ -3,23 +3,22 @@ package mp4 import ( "bufio" "fmt" - "io" - "time" - - "github.com/deepch/vdk/codec/h265parser" - "github.com/deepch/vdk/av" "github.com/deepch/vdk/codec/aacparser" "github.com/deepch/vdk/codec/h264parser" + "github.com/deepch/vdk/codec/h265parser" "github.com/deepch/vdk/format/mp4/mp4io" "github.com/deepch/vdk/utils/bits/pio" + "io" + "time" ) type Muxer struct { - w io.WriteSeeker - bufw *bufio.Writer - wpos int64 - streams []*Stream + w io.WriteSeeker + bufw *bufio.Writer + wpos int64 + streams []*Stream + NegativeTsMakeZero bool } func NewMuxer(w io.WriteSeeker) *Muxer { @@ -206,8 +205,12 @@ func (self *Muxer) WritePacket(pkt av.Packet) (err error) { func (self *Stream) writePacket(pkt av.Packet, rawdur time.Duration) (err error) { if rawdur < 0 { - err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) - return + if self.muxer.NegativeTsMakeZero { + rawdur = 0 + } else { + err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) + return + } } if _, err = self.muxer.bufw.Write(pkt.Data); err != nil { diff --git a/format/mp4m/muxer.go b/format/mp4m/muxer.go index f7b2735..76b6522 100644 --- a/format/mp4m/muxer.go +++ b/format/mp4m/muxer.go @@ -14,10 +14,11 @@ import ( ) type Muxer struct { - w io.WriteSeeker - bufw *bufio.Writer - wpos int64 - streams []*Stream + w io.WriteSeeker + bufw *bufio.Writer + wpos int64 + streams []*Stream + NegativeTsMakeZero bool } func NewMuxer(w io.WriteSeeker) *Muxer { @@ -181,8 +182,12 @@ func (self *Muxer) WritePacket(pkt av.Packet) (err error) { func (self *Stream) writePacket(pkt av.Packet, rawdur time.Duration) (err error) { if rawdur < 0 { - err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) - return + if self.muxer.NegativeTsMakeZero { + rawdur = 0 + } else { + err = fmt.Errorf("mp4: stream#%d time=%v < lasttime=%v", pkt.Idx, pkt.Time, self.lastpkt.Time) + return + } } if _, err = self.muxer.bufw.Write(pkt.Data); err != nil { diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index 3d061c9..29a02ad 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -210,6 +210,7 @@ func (m *Muxer) OpenMP4() (err error) { return } m.muxer = mp4.NewMuxer(m.d) + m.muxer.NegativeTsMakeZero = true if err = m.muxer.WriteHeader(m.gof.Streams); err != nil { return } From b84c19f719b78e446976b676570fb3f41b24bb77 Mon Sep 17 00:00:00 2001 From: deepch Date: Fri, 2 Feb 2024 02:48:16 +0300 Subject: [PATCH 18/25] testing --- example/test/main.go | 25 +++++++++++++++++++++++++ format/mp4f/muxer.go | 13 +++++++++---- format/rtsp/client.go | 43 ++++++++++++++++++++++++++++++++++++++----- format/rtsp/server.go | 1 + format/ts/demuxer.go | 6 +++++- 5 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 example/test/main.go create mode 100644 format/rtsp/server.go diff --git a/example/test/main.go b/example/test/main.go new file mode 100644 index 0000000..45ac920 --- /dev/null +++ b/example/test/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "github.com/deepch/vdk/format/ts" + "log" + "os" +) + +func main() { + f, _ := os.Open("edb9708f29b24ba9b175808d6b9df9c6541e25766d4a40209a8f903948b72f3f.ts") + m := ts.NewDemuxer(f) + var i int + for { + p, err := m.ReadPacket() + if err != nil { + return + } + if p.IsKeyFrame { + i = 0 + } + log.Println(i, p.Time, p.Data[4:10], len(p.Data)) + i++ + + } +} diff --git a/format/mp4f/muxer.go b/format/mp4f/muxer.go index 4042c9b..c2f0f47 100644 --- a/format/mp4f/muxer.go +++ b/format/mp4f/muxer.go @@ -3,6 +3,7 @@ package mp4f import ( "bufio" "fmt" + "log" "os" "time" @@ -238,14 +239,15 @@ func (self *Muxer) WriteTrailer() (err error) { return } -func (element *Muxer) WriteHeader(streams []av.CodecData) (err error) { +func (element *Muxer) WriteHeader(streams []av.CodecData) error { element.streams = []*Stream{} for _, stream := range streams { - if err = element.newStream(stream); err != nil { - return + if err := element.newStream(stream); err != nil { + log.Println("WriteHeader", err) } } - return + + return nil } func (element *Muxer) GetInit(streams []av.CodecData) (string, []byte) { @@ -285,6 +287,9 @@ func (element *Muxer) GetInit(streams []av.CodecData) (string, []byte) { } func (element *Muxer) WritePacket(pkt av.Packet, GOP bool) (bool, []byte, error) { + if pkt.Idx+1 > int8(len(element.streams)) { + return false, nil, nil + } stream := element.streams[pkt.Idx] if GOP { ts := time.Duration(0) diff --git a/format/rtsp/client.go b/format/rtsp/client.go index 89a9d89..2aa4791 100644 --- a/format/rtsp/client.go +++ b/format/rtsp/client.go @@ -40,9 +40,10 @@ const ( ) type Client struct { - DebugRtsp bool - DebugRtp bool - Headers []string + DebugRtsp bool + DebugRtp bool + DisableAudio bool + Headers []string SkipErrRtpBlock bool @@ -1076,12 +1077,44 @@ func (self *Stream) handleRtpPacket(packet []byte) (err error) { err = fmt.Errorf("rtp: packet too short") return } - payloadOffset := 12 + int(packet[0]&0xf)*4 + + timestamp := binary.BigEndian.Uint32(packet[4:8]) + + /* + Test offset + */ + Padding := (packet[0]>>5)&1 == 1 + Extension := (packet[0]>>4)&1 == 1 + CSRCCnt := int(packet[0] & 0x0f) + + RTPHeaderSize := 12 + + payloadOffset := RTPHeaderSize + end := len(packet) + if end-payloadOffset >= 4*CSRCCnt { + payloadOffset += 4 * CSRCCnt + } + + if Extension && end-payloadOffset >= 4 { + extLen := 4 * int(binary.BigEndian.Uint16(packet[payloadOffset+2:])) + payloadOffset += 4 + if end-payloadOffset >= extLen { + payloadOffset += extLen + } + } + + if Padding && end-payloadOffset > 0 { + paddingLen := int(packet[end-1]) + if end-payloadOffset >= paddingLen { + end -= paddingLen + } + } + if payloadOffset > len(packet) { err = fmt.Errorf("rtp: packet too short") return } - timestamp := binary.BigEndian.Uint32(packet[4:8]) + payload := packet[payloadOffset:] /* diff --git a/format/rtsp/server.go b/format/rtsp/server.go new file mode 100644 index 0000000..185db25 --- /dev/null +++ b/format/rtsp/server.go @@ -0,0 +1 @@ +package rtsp diff --git a/format/ts/demuxer.go b/format/ts/demuxer.go index 8c02825..3b6e122 100644 --- a/format/ts/demuxer.go +++ b/format/ts/demuxer.go @@ -284,7 +284,11 @@ func (self *Stream) payloadEnd() (n int, err error) { b := make([]byte, 4+len(nalu)) pio.PutU32BE(b[0:4], uint32(len(nalu))) copy(b[4:], nalu) - self.addPacket(b, time.Duration(0), (1000*time.Millisecond)/time.Duration(self.fps)) + fps := self.fps + if self.fps == 0 { + fps = 25 + } + self.addPacket(b, time.Duration(0), (1000*time.Millisecond)/time.Duration(fps)) n++ } } From 0e0666600667d50945b62f65c29f1d31cbd6f682 Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Wed, 7 Feb 2024 20:33:12 +0700 Subject: [PATCH 19/25] fix listTag bug --- format/nvr/muxer.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index 29a02ad..d48d4f1 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -20,7 +20,13 @@ import ( ) var MIME = []byte{11, 22, 111, 222, 11, 22, 111, 222} -var listTag = []string{"{server_id}", "{host_name}", "{host_name_short}", "{host_name_long}", "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", "{start_year}", "{start_month}", "{start_day}", "{start_hour}", "{start_minute}", "{start_second}", "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", "{end_year}", "{end_month}", "{end_day}", "{end_hour}", "{end_minute}", "{end_second}", "{end_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} + +var listTag = []string{"{server_id}", "{host_name}", "{host_name_short}", "{host_name_long}", + "{stream_name}", "{channel_name}", "{stream_id}", "{channel_id}", + "{start_year}", "{start_month}", "{start_day}", "{start_hour}", "{start_minute}", "{start_second}", + "{start_millisecond}", "{start_unix_second}", "{start_unix_millisecond}", "{start_time}", "{start_pts}", + "{end_year}", "{end_month}", "{end_day}", "{end_hour}", "{end_minute}", "{end_second}", + "{end_millisecond}", "{end_unix_millisecond}", "{end_unix_second}", "{end_time}", "{end_pts}", "{duration_second}", "{duration_millisecond}"} const ( MP4 = "mp4" @@ -275,9 +281,9 @@ func (m *Muxer) filePatch() (string, error) { case "{start_millisecond}": ts = strings.Replace(ts, "{start_millisecond}", fmt.Sprintf("%d", m.start.Nanosecond()/1000/1000), -1) case "{start_unix_millisecond}": - ts = strings.Replace(ts, "{start_unix_millisecond}", fmt.Sprintf("%d", m.end.UnixMilli()), -1) + ts = strings.Replace(ts, "{start_unix_millisecond}", fmt.Sprintf("%d", m.start.UnixMilli()), -1) case "{start_unix_second}": - ts = strings.Replace(ts, "{start_unix_second}", fmt.Sprintf("%d", m.end.Unix()), -1) + ts = strings.Replace(ts, "{start_unix_second}", fmt.Sprintf("%d", m.start.Unix()), -1) case "{start_time}": ts = strings.Replace(ts, "{start_time}", fmt.Sprintf("%s", m.start.Format("2006-01-02T15:04:05-0700")), -1) case "{start_pts}": @@ -295,7 +301,7 @@ func (m *Muxer) filePatch() (string, error) { case "{end_second}": ts = strings.Replace(ts, "{end_second}", fmt.Sprintf("%d", m.end.Second()), -1) case "{end_millisecond}": - ts = strings.Replace(ts, "{end_millisecond}", fmt.Sprintf("%d", m.start.Nanosecond()/1000/1000), -1) + ts = strings.Replace(ts, "{end_millisecond}", fmt.Sprintf("%d", m.end.Nanosecond()/1000/1000), -1) case "{end_unix_millisecond}": ts = strings.Replace(ts, "{end_unix_millisecond}", fmt.Sprintf("%d", m.end.UnixMilli()), -1) case "{end_unix_second}": From 9f075c66825dc617c11903dd1a61ff520ac142d0 Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Wed, 7 Feb 2024 20:44:30 +0700 Subject: [PATCH 20/25] fix hostShort / hostLong bug --- format/nvr/muxer.go | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index d48d4f1..f52c80a 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -34,20 +34,20 @@ const ( ) type Muxer struct { - muxer *mp4.Muxer - format string - limit int - d *os.File - m *os.File - dur time.Duration - h int - gof *Gof - patch string - mpoint []string - start, end time.Time - pstart, pend time.Duration - started bool - serverID, streamName, channelName, streamID, channelID, hostname string + muxer *mp4.Muxer + format string + limit int + d *os.File + m *os.File + dur time.Duration + h int + gof *Gof + patch string + mpoint []string + start, end time.Time + pstart, pend time.Duration + started bool + serverID, streamName, channelName, streamID, channelID, hostLong, hostShort string } type Gof struct { @@ -76,7 +76,11 @@ func init() { } func NewMuxer(serverID, streamName, channelName, streamID, channelID string, mpoint []string, patch, format string, limit int) (m *Muxer, err error) { - hostname, _ := os.Hostname() + hostLong, _ := os.Hostname() + var hostShort string + if p, _, ok := strings.Cut(hostLong, "."); ok { + hostShort = p + } m = &Muxer{ mpoint: mpoint, patch: patch, @@ -89,7 +93,8 @@ func NewMuxer(serverID, streamName, channelName, streamID, channelID string, mpo channelName: channelName, streamID: streamID, channelID: channelID, - hostname: hostname, + hostLong: hostLong, + hostShort: hostShort, } return } @@ -253,11 +258,11 @@ func (m *Muxer) filePatch() (string, error) { case "{server_id}": ts = strings.Replace(ts, "{server_id}", m.serverID, -1) case "{host_name}": - ts = strings.Replace(ts, "{host_name}", m.hostname, -1) + ts = strings.Replace(ts, "{host_name}", m.hostLong, -1) case "{host_name_short}": - ts = strings.Replace(ts, "{host_name_short}", m.hostname, -1) + ts = strings.Replace(ts, "{host_name_short}", m.hostShort, -1) case "{host_name_long}": - ts = strings.Replace(ts, "{host_name_long}", m.hostname, -1) + ts = strings.Replace(ts, "{host_name_long}", m.hostLong, -1) case "{stream_name}": ts = strings.Replace(ts, "{stream_name}", m.streamName, -1) case "{channel_name}": From 4b060bc442cd5a1c6bf22f910536d5f8cae6d1ec Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Thu, 8 Feb 2024 01:00:12 +0700 Subject: [PATCH 21/25] fix dig --- format/nvr/muxer.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/format/nvr/muxer.go b/format/nvr/muxer.go index f52c80a..d0e6859 100644 --- a/format/nvr/muxer.go +++ b/format/nvr/muxer.go @@ -274,15 +274,15 @@ func (m *Muxer) filePatch() (string, error) { case "{start_year}": ts = strings.Replace(ts, "{start_year}", fmt.Sprintf("%d", m.start.Year()), -1) case "{start_month}": - ts = strings.Replace(ts, "{start_month}", fmt.Sprintf("%d", int(m.start.Month())), -1) + ts = strings.Replace(ts, "{start_month}", fmt.Sprintf("%02d", int(m.start.Month())), -1) case "{start_day}": - ts = strings.Replace(ts, "{start_day}", fmt.Sprintf("%d", m.start.Day()), -1) + ts = strings.Replace(ts, "{start_day}", fmt.Sprintf("%02d", m.start.Day()), -1) case "{start_hour}": - ts = strings.Replace(ts, "{start_hour}", fmt.Sprintf("%d", m.start.Hour()), -1) + ts = strings.Replace(ts, "{start_hour}", fmt.Sprintf("%02d", m.start.Hour()), -1) case "{start_minute}": - ts = strings.Replace(ts, "{start_minute}", fmt.Sprintf("%d", m.start.Minute()), -1) + ts = strings.Replace(ts, "{start_minute}", fmt.Sprintf("%02d", m.start.Minute()), -1) case "{start_second}": - ts = strings.Replace(ts, "{start_second}", fmt.Sprintf("%d", m.start.Second()), -1) + ts = strings.Replace(ts, "{start_second}", fmt.Sprintf("%02d", m.start.Second()), -1) case "{start_millisecond}": ts = strings.Replace(ts, "{start_millisecond}", fmt.Sprintf("%d", m.start.Nanosecond()/1000/1000), -1) case "{start_unix_millisecond}": @@ -296,15 +296,15 @@ func (m *Muxer) filePatch() (string, error) { case "{end_year}": ts = strings.Replace(ts, "{end_year}", fmt.Sprintf("%d", m.end.Year()), -1) case "{end_month}": - ts = strings.Replace(ts, "{end_month}", fmt.Sprintf("%d", int(m.end.Month())), -1) + ts = strings.Replace(ts, "{end_month}", fmt.Sprintf("%02d", int(m.end.Month())), -1) case "{end_day}": - ts = strings.Replace(ts, "{end_day}", fmt.Sprintf("%d", m.end.Day()), -1) + ts = strings.Replace(ts, "{end_day}", fmt.Sprintf("%02d", m.end.Day()), -1) case "{end_hour}": - ts = strings.Replace(ts, "{end_hour}", fmt.Sprintf("%d", m.end.Hour()), -1) + ts = strings.Replace(ts, "{end_hour}", fmt.Sprintf("%02d", m.end.Hour()), -1) case "{end_minute}": - ts = strings.Replace(ts, "{end_minute}", fmt.Sprintf("%d", m.end.Minute()), -1) + ts = strings.Replace(ts, "{end_minute}", fmt.Sprintf("%02d", m.end.Minute()), -1) case "{end_second}": - ts = strings.Replace(ts, "{end_second}", fmt.Sprintf("%d", m.end.Second()), -1) + ts = strings.Replace(ts, "{end_second}", fmt.Sprintf("%02d", m.end.Second()), -1) case "{end_millisecond}": ts = strings.Replace(ts, "{end_millisecond}", fmt.Sprintf("%d", m.end.Nanosecond()/1000/1000), -1) case "{end_unix_millisecond}": From fd7ecfeaad5500909b940f40a229e26786eb0a9e Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Sat, 10 Feb 2024 23:20:37 +0700 Subject: [PATCH 22/25] style --- format/rtspv2/client.go | 292 +---------------------------------- format/rtspv2/demuxer.go | 322 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+), 288 deletions(-) create mode 100644 format/rtspv2/demuxer.go diff --git a/format/rtspv2/client.go b/format/rtspv2/client.go index e244a39..397f1e7 100644 --- a/format/rtspv2/client.go +++ b/format/rtspv2/client.go @@ -12,7 +12,6 @@ import ( "html" "io" "log" - "math" "net" "net/url" "strconv" @@ -93,6 +92,10 @@ type RTSPClient struct { FPS int WaitCodec bool chTMP int + timestamp int64 + sequenceNumber int + end int + offset int } type RTSPClientOptions struct { @@ -554,293 +557,6 @@ func stringInBetween(str string, start string, end string) (result string) { return str } -func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { - - content := *payloadRAW - firstByte := content[4] - padding := (firstByte>>5)&1 == 1 - extension := (firstByte>>4)&1 == 1 - CSRCCnt := int(firstByte & 0x0f) - SequenceNumber := int(binary.BigEndian.Uint16(content[6:8])) - timestamp := int64(binary.BigEndian.Uint32(content[8:16])) - - if isRTCPPacket(content) { - client.Println("skipping RTCP packet") - return nil, false - } - - offset := RTPHeaderSize - - end := len(content) - if end-offset >= 4*CSRCCnt { - offset += 4 * CSRCCnt - } - if extension && len(content) < 4+offset+2+2 { - return nil, false - } - if extension && end-offset >= 4 { - extLen := 4 * int(binary.BigEndian.Uint16(content[4+offset+2:])) - offset += 4 - if end-offset >= extLen { - offset += extLen - } - } - if padding && end-offset > 0 { - paddingLen := int(content[end-1]) - if end-offset >= paddingLen { - end -= paddingLen - } - } - offset += 4 - if len(content) < end { - return nil, false - } - switch int(content[1]) { - case client.videoID: - if client.PreVideoTS == 0 { - client.PreVideoTS = timestamp - } - if timestamp-client.PreVideoTS < 0 { - if math.MaxUint32-client.PreVideoTS < 90*100 { //100 ms - client.PreVideoTS = 0 - client.PreVideoTS -= (math.MaxUint32 - client.PreVideoTS) - } else { - client.PreVideoTS = 0 - } - } - if client.PreSequenceNumber != 0 && SequenceNumber-client.PreSequenceNumber != 1 { - client.Println("drop packet", SequenceNumber-1) - } - client.PreSequenceNumber = SequenceNumber - if client.BufferRtpPacket.Len() > 4048576 { - client.Println("Big Buffer Flush") - client.BufferRtpPacket.Truncate(0) - client.BufferRtpPacket.Reset() - } - nalRaw, _ := h264parser.SplitNALUs(content[offset:end]) - if len(nalRaw) == 0 || len(nalRaw[0]) == 0 { - return nil, false - } - var retmap []*av.Packet - for _, nal := range nalRaw { - if client.videoCodec == av.H265 { - naluType := (nal[0] >> 1) & 0x3f - switch naluType { - case h265parser.NAL_UNIT_CODED_SLICE_TRAIL_R: - retmap = append(retmap, &av.Packet{ - Data: append(binSize(len(nal)), nal...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: false, - Duration: time.Duration(float32(timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(timestamp/90) * time.Millisecond, - }) - case h265parser.NAL_UNIT_VPS: - client.CodecUpdateVPS(nal) - case h265parser.NAL_UNIT_SPS: - client.CodecUpdateSPS(nal) - case h265parser.NAL_UNIT_PPS: - client.CodecUpdatePPS(nal) - case h265parser.NAL_UNIT_UNSPECIFIED_49: - se := nal[2] >> 6 - naluType := nal[2] & 0x3f - if se == 2 { - client.BufferRtpPacket.Truncate(0) - client.BufferRtpPacket.Reset() - client.BufferRtpPacket.Write([]byte{(nal[0] & 0x81) | (naluType << 1), nal[1]}) - r := make([]byte, 2) - r[1] = nal[1] - r[0] = (nal[0] & 0x81) | (naluType << 1) - client.BufferRtpPacket.Write(nal[3:]) - } else if se == 1 { - client.BufferRtpPacket.Write(nal[3:]) - retmap = append(retmap, &av.Packet{ - Data: append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluType == h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL, - Duration: time.Duration(float32(timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(timestamp/90) * time.Millisecond, - }) - } else { - client.BufferRtpPacket.Write(nal[3:]) - } - default: - //client.Println("Unsupported Nal", naluType) - } - - } else if client.videoCodec == av.H264 { - naluType := nal[0] & 0x1f - switch { - case naluType >= 1 && naluType <= 5: - retmap = append(retmap, &av.Packet{ - Data: append(binSize(len(nal)), nal...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluType == 5, - Duration: time.Duration(float32(timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(timestamp/90) * time.Millisecond, - }) - case naluType == 7: - client.CodecUpdateSPS(nal) - case naluType == 8: - client.CodecUpdatePPS(nal) - case naluType == 24: - packet := nal[1:] - for len(packet) >= 2 { - size := int(packet[0])<<8 | int(packet[1]) - if size+2 > len(packet) { - break - } - naluTypefs := packet[2] & 0x1f - switch { - case naluTypefs >= 1 && naluTypefs <= 5: - retmap = append(retmap, &av.Packet{ - Data: append(binSize(len(packet[2:size+2])), packet[2:size+2]...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluType == 5, - Duration: time.Duration(float32(timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(timestamp/90) * time.Millisecond, - }) - case naluTypefs == 7: - client.CodecUpdateSPS(packet[2 : size+2]) - case naluTypefs == 8: - client.CodecUpdatePPS(packet[2 : size+2]) - } - packet = packet[size+2:] - } - case naluType == 28: - fuIndicator := content[offset] - fuHeader := content[offset+1] - isStart := fuHeader&0x80 != 0 - isEnd := fuHeader&0x40 != 0 - if isStart { - client.fuStarted = true - client.BufferRtpPacket.Truncate(0) - client.BufferRtpPacket.Reset() - client.BufferRtpPacket.Write([]byte{fuIndicator&0xe0 | fuHeader&0x1f}) - } - if client.fuStarted { - client.BufferRtpPacket.Write(content[offset+2 : end]) - if isEnd { - client.fuStarted = false - naluTypef := client.BufferRtpPacket.Bytes()[0] & 0x1f - if naluTypef == 7 || naluTypef == 9 { - bufered, _ := h264parser.SplitNALUs(append([]byte{0, 0, 0, 1}, client.BufferRtpPacket.Bytes()...)) - for _, v := range bufered { - naluTypefs := v[0] & 0x1f - switch { - case naluTypefs == 5: - client.BufferRtpPacket.Reset() - client.BufferRtpPacket.Write(v) - naluTypef = 5 - case naluTypefs == 7: - client.CodecUpdateSPS(v) - case naluTypefs == 8: - client.CodecUpdatePPS(v) - } - } - } - retmap = append(retmap, &av.Packet{ - Data: append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: time.Duration(float32(timestamp-client.PreVideoTS)/90) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluTypef == 5, - Time: time.Duration(timestamp/90) * time.Millisecond, - }) - } - } - default: - //client.Println("Unsupported NAL Type", naluType) - } - } - } - if len(retmap) > 0 { - client.PreVideoTS = timestamp - return retmap, true - } - case client.audioID: - if client.PreAudioTS == 0 { - client.PreAudioTS = timestamp - } - nalRaw, _ := h264parser.SplitNALUs(content[offset:end]) - var retmap []*av.Packet - for _, nal := range nalRaw { - var duration time.Duration - switch client.audioCodec { - case av.PCM_MULAW: - duration = time.Duration(len(nal)) * time.Second / time.Duration(client.AudioTimeScale) - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: nal, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) - case av.PCM_ALAW: - duration = time.Duration(len(nal)) * time.Second / time.Duration(client.AudioTimeScale) - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: nal, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) - case av.OPUS: - duration = time.Duration(20) * time.Millisecond - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: nal, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) - case av.AAC: - auHeadersLength := uint16(0) | (uint16(nal[0]) << 8) | uint16(nal[1]) - auHeadersCount := auHeadersLength >> 4 - framesPayloadOffset := 2 + int(auHeadersCount)<<1 - auHeaders := nal[2:framesPayloadOffset] - framesPayload := nal[framesPayloadOffset:] - for i := 0; i < int(auHeadersCount); i++ { - auHeader := uint16(0) | (uint16(auHeaders[0]) << 8) | uint16(auHeaders[1]) - frameSize := auHeader >> 3 - frame := framesPayload[:frameSize] - auHeaders = auHeaders[2:] - framesPayload = framesPayload[frameSize:] - if _, _, _, _, err := aacparser.ParseADTSHeader(frame); err == nil { - frame = frame[7:] - } - duration = time.Duration((float32(1024)/float32(client.AudioTimeScale))*1000*1000*1000) * time.Nanosecond - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: frame, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) - } - } - } - if len(retmap) > 0 { - client.PreAudioTS = timestamp - return retmap, true - } - default: - //client.Println("Unsuported Intervaled data packet", int(content[1]), content[offset:end]) - } - return nil, false -} - func (client *RTSPClient) CodecUpdateSPS(val []byte) { if client.videoCodec != av.H264 && client.videoCodec != av.H265 { return diff --git a/format/rtspv2/demuxer.go b/format/rtspv2/demuxer.go new file mode 100644 index 0000000..2d74c44 --- /dev/null +++ b/format/rtspv2/demuxer.go @@ -0,0 +1,322 @@ +package rtspv2 + +import ( + "encoding/binary" + "github.com/deepch/vdk/av" + "github.com/deepch/vdk/codec/aacparser" + "github.com/deepch/vdk/codec/h264parser" + "github.com/deepch/vdk/codec/h265parser" + "math" + "time" +) + +func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { + + content := *payloadRAW + firstByte := content[4] + padding := (firstByte>>5)&1 == 1 + extension := (firstByte>>4)&1 == 1 + CSRCCnt := int(firstByte & 0x0f) + client.sequenceNumber = int(binary.BigEndian.Uint16(content[6:8])) + client.timestamp = int64(binary.BigEndian.Uint32(content[8:16])) + + if isRTCPPacket(content) { + client.Println("skipping RTCP packet") + return nil, false + } + + client.offset = RTPHeaderSize + + client.end = len(content) + if client.end-client.offset >= 4*CSRCCnt { + client.offset += 4 * CSRCCnt + } + if extension && len(content) < 4+client.offset+2+2 { + return nil, false + } + if extension && client.end-client.offset >= 4 { + extLen := 4 * int(binary.BigEndian.Uint16(content[4+client.offset+2:])) + client.offset += 4 + if client.end-client.offset >= extLen { + client.offset += extLen + } + } + if padding && client.end-client.offset > 0 { + paddingLen := int(content[client.end-1]) + if client.end-client.offset >= paddingLen { + client.end -= paddingLen + } + } + client.offset += 4 + if len(content) < client.end { + return nil, false + } + + switch int(content[1]) { + case client.videoID: + return client.handleVideo(content) + case client.audioID: + return client.handleAudio(content) + default: + //client.Println("Unsuported Intervaled data packet", int(content[1]), content[offset:end]) + } + return nil, false +} + +func (client *RTSPClient) handleVideo(content []byte) ([]*av.Packet, bool) { + if client.PreVideoTS == 0 { + client.PreVideoTS = client.timestamp + } + if client.timestamp-client.PreVideoTS < 0 { + if math.MaxUint32-client.PreVideoTS < 90*100 { //100 ms + client.PreVideoTS = 0 + client.PreVideoTS -= (math.MaxUint32 - client.PreVideoTS) + } else { + client.PreVideoTS = 0 + } + } + if client.PreSequenceNumber != 0 && client.sequenceNumber-client.PreSequenceNumber != 1 { + client.Println("drop packet", client.sequenceNumber-1) + } + client.PreSequenceNumber = client.sequenceNumber + if client.BufferRtpPacket.Len() > 4048576 { + client.Println("Big Buffer Flush") + client.BufferRtpPacket.Truncate(0) + client.BufferRtpPacket.Reset() + } + nalRaw, _ := h264parser.SplitNALUs(content[client.offset:client.end]) + if len(nalRaw) == 0 || len(nalRaw[0]) == 0 { + return nil, false + } + var retmap []*av.Packet + for _, nal := range nalRaw { + if client.videoCodec == av.H265 { + retmap = client.handleH265Payload(nal, retmap) + } else if client.videoCodec == av.H264 { + retmap = client.handleH264Payload(content, nal, retmap) + } + } + if len(retmap) > 0 { + client.PreVideoTS = client.timestamp + return retmap, true + } + + return nil, false +} + +func (client *RTSPClient) handleH264Payload(content, nal []byte, retmap []*av.Packet) []*av.Packet { + naluType := nal[0] & 0x1f + switch { + case naluType >= 1 && naluType <= 5: + retmap = append(retmap, &av.Packet{ + Data: append(binSize(len(nal)), nal...), + CompositionTime: time.Duration(1) * time.Millisecond, + Idx: client.videoIDX, + IsKeyFrame: naluType == 5, + Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, + Time: time.Duration(client.timestamp/90) * time.Millisecond, + }) + case naluType == 7: + client.CodecUpdateSPS(nal) + case naluType == 8: + client.CodecUpdatePPS(nal) + case naluType == 24: + packet := nal[1:] + for len(packet) >= 2 { + size := int(packet[0])<<8 | int(packet[1]) + if size+2 > len(packet) { + break + } + naluTypefs := packet[2] & 0x1f + switch { + case naluTypefs >= 1 && naluTypefs <= 5: + retmap = append(retmap, &av.Packet{ + Data: append(binSize(len(packet[2:size+2])), packet[2:size+2]...), + CompositionTime: time.Duration(1) * time.Millisecond, + Idx: client.videoIDX, + IsKeyFrame: naluType == 5, + Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, + Time: time.Duration(client.timestamp/90) * time.Millisecond, + }) + case naluTypefs == 7: + client.CodecUpdateSPS(packet[2 : size+2]) + case naluTypefs == 8: + client.CodecUpdatePPS(packet[2 : size+2]) + } + packet = packet[size+2:] + } + case naluType == 28: + fuIndicator := content[client.offset] + fuHeader := content[client.offset+1] + isStart := fuHeader&0x80 != 0 + isEnd := fuHeader&0x40 != 0 + if isStart { + client.fuStarted = true + client.BufferRtpPacket.Truncate(0) + client.BufferRtpPacket.Reset() + client.BufferRtpPacket.Write([]byte{fuIndicator&0xe0 | fuHeader&0x1f}) + } + if client.fuStarted { + client.BufferRtpPacket.Write(content[client.offset+2 : client.end]) + if isEnd { + client.fuStarted = false + naluTypef := client.BufferRtpPacket.Bytes()[0] & 0x1f + if naluTypef == 7 || naluTypef == 9 { + bufered, _ := h264parser.SplitNALUs(append([]byte{0, 0, 0, 1}, client.BufferRtpPacket.Bytes()...)) + for _, v := range bufered { + naluTypefs := v[0] & 0x1f + switch { + case naluTypefs == 5: + client.BufferRtpPacket.Reset() + client.BufferRtpPacket.Write(v) + naluTypef = 5 + case naluTypefs == 7: + client.CodecUpdateSPS(v) + case naluTypefs == 8: + client.CodecUpdatePPS(v) + } + } + } + retmap = append(retmap, &av.Packet{ + Data: append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), + CompositionTime: time.Duration(1) * time.Millisecond, + Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, + Idx: client.videoIDX, + IsKeyFrame: naluTypef == 5, + Time: time.Duration(client.timestamp/90) * time.Millisecond, + }) + } + } + default: + //client.Println("Unsupported NAL Type", naluType) + } + + return retmap +} + +func (client *RTSPClient) handleH265Payload(nal []byte, retmap []*av.Packet) []*av.Packet { + naluType := (nal[0] >> 1) & 0x3f + switch naluType { + case h265parser.NAL_UNIT_CODED_SLICE_TRAIL_R: + retmap = append(retmap, &av.Packet{ + Data: append(binSize(len(nal)), nal...), + CompositionTime: time.Duration(1) * time.Millisecond, + Idx: client.videoIDX, + IsKeyFrame: false, + Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, + Time: time.Duration(client.timestamp/90) * time.Millisecond, + }) + case h265parser.NAL_UNIT_VPS: + client.CodecUpdateVPS(nal) + case h265parser.NAL_UNIT_SPS: + client.CodecUpdateSPS(nal) + case h265parser.NAL_UNIT_PPS: + client.CodecUpdatePPS(nal) + case h265parser.NAL_UNIT_UNSPECIFIED_49: + se := nal[2] >> 6 + naluType := nal[2] & 0x3f + if se == 2 { + client.BufferRtpPacket.Truncate(0) + client.BufferRtpPacket.Reset() + client.BufferRtpPacket.Write([]byte{(nal[0] & 0x81) | (naluType << 1), nal[1]}) + r := make([]byte, 2) + r[1] = nal[1] + r[0] = (nal[0] & 0x81) | (naluType << 1) + client.BufferRtpPacket.Write(nal[3:]) + } else if se == 1 { + client.BufferRtpPacket.Write(nal[3:]) + retmap = append(retmap, &av.Packet{ + Data: append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), + CompositionTime: time.Duration(1) * time.Millisecond, + Idx: client.videoIDX, + IsKeyFrame: naluType == h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL, + Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, + Time: time.Duration(client.timestamp/90) * time.Millisecond, + }) + } else { + client.BufferRtpPacket.Write(nal[3:]) + } + default: + //client.Println("Unsupported Nal", naluType) + } + + return retmap +} + +func (client *RTSPClient) handleAudio(content []byte) ([]*av.Packet, bool) { + if client.PreAudioTS == 0 { + client.PreAudioTS = client.timestamp + } + nalRaw, _ := h264parser.SplitNALUs(content[client.offset:client.end]) + var retmap []*av.Packet + for _, nal := range nalRaw { + var duration time.Duration + switch client.audioCodec { + case av.PCM_MULAW: + duration = time.Duration(len(nal)) * time.Second / time.Duration(client.AudioTimeScale) + client.AudioTimeLine += duration + retmap = append(retmap, &av.Packet{ + Data: nal, + CompositionTime: time.Duration(1) * time.Millisecond, + Duration: duration, + Idx: client.audioIDX, + IsKeyFrame: false, + Time: client.AudioTimeLine, + }) + case av.PCM_ALAW: + duration = time.Duration(len(nal)) * time.Second / time.Duration(client.AudioTimeScale) + client.AudioTimeLine += duration + retmap = append(retmap, &av.Packet{ + Data: nal, + CompositionTime: time.Duration(1) * time.Millisecond, + Duration: duration, + Idx: client.audioIDX, + IsKeyFrame: false, + Time: client.AudioTimeLine, + }) + case av.OPUS: + duration = time.Duration(20) * time.Millisecond + client.AudioTimeLine += duration + retmap = append(retmap, &av.Packet{ + Data: nal, + CompositionTime: time.Duration(1) * time.Millisecond, + Duration: duration, + Idx: client.audioIDX, + IsKeyFrame: false, + Time: client.AudioTimeLine, + }) + case av.AAC: + auHeadersLength := uint16(0) | (uint16(nal[0]) << 8) | uint16(nal[1]) + auHeadersCount := auHeadersLength >> 4 + framesPayloadOffset := 2 + int(auHeadersCount)<<1 + auHeaders := nal[2:framesPayloadOffset] + framesPayload := nal[framesPayloadOffset:] + for i := 0; i < int(auHeadersCount); i++ { + auHeader := uint16(0) | (uint16(auHeaders[0]) << 8) | uint16(auHeaders[1]) + frameSize := auHeader >> 3 + frame := framesPayload[:frameSize] + auHeaders = auHeaders[2:] + framesPayload = framesPayload[frameSize:] + if _, _, _, _, err := aacparser.ParseADTSHeader(frame); err == nil { + frame = frame[7:] + } + duration = time.Duration((float32(1024)/float32(client.AudioTimeScale))*1000*1000*1000) * time.Nanosecond + client.AudioTimeLine += duration + retmap = append(retmap, &av.Packet{ + Data: frame, + CompositionTime: time.Duration(1) * time.Millisecond, + Duration: duration, + Idx: client.audioIDX, + IsKeyFrame: false, + Time: client.AudioTimeLine, + }) + } + } + } + if len(retmap) > 0 { + client.PreAudioTS = client.timestamp + return retmap, true + } + + return nil, false +} From 230b6c6ad185c63da597fea8fd330463e4ae6b42 Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Sat, 10 Feb 2024 23:50:56 +0700 Subject: [PATCH 23/25] style --- format/rtspv2/demuxer.go | 98 ++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 60 deletions(-) diff --git a/format/rtspv2/demuxer.go b/format/rtspv2/demuxer.go index 2d74c44..49911b2 100644 --- a/format/rtspv2/demuxer.go +++ b/format/rtspv2/demuxer.go @@ -194,18 +194,16 @@ func (client *RTSPClient) handleH264Payload(content, nal []byte, retmap []*av.Pa return retmap } +const ( + TimeBaseFactor = 90 + TimeDelay = 1 +) + func (client *RTSPClient) handleH265Payload(nal []byte, retmap []*av.Packet) []*av.Packet { naluType := (nal[0] >> 1) & 0x3f switch naluType { case h265parser.NAL_UNIT_CODED_SLICE_TRAIL_R: - retmap = append(retmap, &av.Packet{ - Data: append(binSize(len(nal)), nal...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: false, - Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(client.timestamp/90) * time.Millisecond, - }) + retmap = client.appendVideoPacket(retmap, nal, false) case h265parser.NAL_UNIT_VPS: client.CodecUpdateVPS(nal) case h265parser.NAL_UNIT_SPS: @@ -215,7 +213,8 @@ func (client *RTSPClient) handleH265Payload(nal []byte, retmap []*av.Packet) []* case h265parser.NAL_UNIT_UNSPECIFIED_49: se := nal[2] >> 6 naluType := nal[2] & 0x3f - if se == 2 { + switch se { + case 2: client.BufferRtpPacket.Truncate(0) client.BufferRtpPacket.Reset() client.BufferRtpPacket.Write([]byte{(nal[0] & 0x81) | (naluType << 1), nal[1]}) @@ -223,23 +222,15 @@ func (client *RTSPClient) handleH265Payload(nal []byte, retmap []*av.Packet) []* r[1] = nal[1] r[0] = (nal[0] & 0x81) | (naluType << 1) client.BufferRtpPacket.Write(nal[3:]) - } else if se == 1 { + case 1: client.BufferRtpPacket.Write(nal[3:]) - retmap = append(retmap, &av.Packet{ - Data: append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluType == h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL, - Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(client.timestamp/90) * time.Millisecond, - }) - } else { + retmap = client.appendVideoPacket(retmap, client.BufferRtpPacket.Bytes(), naluType == h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL) + default: client.BufferRtpPacket.Write(nal[3:]) } default: //client.Println("Unsupported Nal", naluType) } - return retmap } @@ -252,39 +243,12 @@ func (client *RTSPClient) handleAudio(content []byte) ([]*av.Packet, bool) { for _, nal := range nalRaw { var duration time.Duration switch client.audioCodec { - case av.PCM_MULAW: + case av.PCM_MULAW, av.PCM_ALAW: duration = time.Duration(len(nal)) * time.Second / time.Duration(client.AudioTimeScale) - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: nal, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) - case av.PCM_ALAW: - duration = time.Duration(len(nal)) * time.Second / time.Duration(client.AudioTimeScale) - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: nal, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) + retmap = client.appendAudioPacket(retmap, nal, duration) case av.OPUS: duration = time.Duration(20) * time.Millisecond - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: nal, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) + retmap = client.appendAudioPacket(retmap, nal, duration) case av.AAC: auHeadersLength := uint16(0) | (uint16(nal[0]) << 8) | uint16(nal[1]) auHeadersCount := auHeadersLength >> 4 @@ -301,15 +265,7 @@ func (client *RTSPClient) handleAudio(content []byte) ([]*av.Packet, bool) { frame = frame[7:] } duration = time.Duration((float32(1024)/float32(client.AudioTimeScale))*1000*1000*1000) * time.Nanosecond - client.AudioTimeLine += duration - retmap = append(retmap, &av.Packet{ - Data: frame, - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: duration, - Idx: client.audioIDX, - IsKeyFrame: false, - Time: client.AudioTimeLine, - }) + retmap = client.appendAudioPacket(retmap, frame, duration) } } } @@ -317,6 +273,28 @@ func (client *RTSPClient) handleAudio(content []byte) ([]*av.Packet, bool) { client.PreAudioTS = client.timestamp return retmap, true } - return nil, false } + +func (client *RTSPClient) appendAudioPacket(retmap []*av.Packet, nal []byte, duration time.Duration) []*av.Packet { + client.AudioTimeLine += duration + return append(retmap, &av.Packet{ + Data: nal, + CompositionTime: time.Duration(1) * time.Millisecond, + Duration: duration, + Idx: client.audioIDX, + IsKeyFrame: false, + Time: client.AudioTimeLine, + }) +} + +func (client *RTSPClient) appendVideoPacket(retmap []*av.Packet, nal []byte, isKeyFrame bool) []*av.Packet { + return append(retmap, &av.Packet{ + Data: append(binSize(len(nal)), nal...), + CompositionTime: time.Duration(TimeDelay) * time.Millisecond, + Idx: client.videoIDX, + IsKeyFrame: isKeyFrame, + Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/TimeBaseFactor) * time.Millisecond, + Time: time.Duration(client.timestamp/TimeBaseFactor) * time.Millisecond, + }) +} From c6f36a9a8943597dce4e7e33091cf6fa6fe1e8be Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Sun, 11 Feb 2024 00:05:40 +0700 Subject: [PATCH 24/25] style --- format/rtspv2/demuxer.go | 52 +++++++++++----------------------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/format/rtspv2/demuxer.go b/format/rtspv2/demuxer.go index 49911b2..396ca41 100644 --- a/format/rtspv2/demuxer.go +++ b/format/rtspv2/demuxer.go @@ -10,8 +10,12 @@ import ( "time" ) -func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { +const ( + TimeBaseFactor = 90 + TimeDelay = 1 +) +func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { content := *payloadRAW firstByte := content[4] padding := (firstByte>>5)&1 == 1 @@ -57,8 +61,6 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { return client.handleVideo(content) case client.audioID: return client.handleAudio(content) - default: - //client.Println("Unsuported Intervaled data packet", int(content[1]), content[offset:end]) } return nil, false } @@ -108,17 +110,10 @@ func (client *RTSPClient) handleH264Payload(content, nal []byte, retmap []*av.Pa naluType := nal[0] & 0x1f switch { case naluType >= 1 && naluType <= 5: - retmap = append(retmap, &av.Packet{ - Data: append(binSize(len(nal)), nal...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluType == 5, - Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(client.timestamp/90) * time.Millisecond, - }) - case naluType == 7: + retmap = client.appendVideoPacket(retmap, nal, naluType == 5) + case naluType == h264parser.NALU_SPS: client.CodecUpdateSPS(nal) - case naluType == 8: + case naluType == h264parser.NALU_PPS: client.CodecUpdatePPS(nal) case naluType == 24: packet := nal[1:] @@ -130,17 +125,10 @@ func (client *RTSPClient) handleH264Payload(content, nal []byte, retmap []*av.Pa naluTypefs := packet[2] & 0x1f switch { case naluTypefs >= 1 && naluTypefs <= 5: - retmap = append(retmap, &av.Packet{ - Data: append(binSize(len(packet[2:size+2])), packet[2:size+2]...), - CompositionTime: time.Duration(1) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluType == 5, - Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, - Time: time.Duration(client.timestamp/90) * time.Millisecond, - }) - case naluTypefs == 7: + retmap = client.appendVideoPacket(retmap, packet[2:size+2], naluTypefs == 5) + case naluTypefs == h264parser.NALU_SPS: client.CodecUpdateSPS(packet[2 : size+2]) - case naluTypefs == 8: + case naluTypefs == h264parser.NALU_PPS: client.CodecUpdatePPS(packet[2 : size+2]) } packet = packet[size+2:] @@ -170,21 +158,14 @@ func (client *RTSPClient) handleH264Payload(content, nal []byte, retmap []*av.Pa client.BufferRtpPacket.Reset() client.BufferRtpPacket.Write(v) naluTypef = 5 - case naluTypefs == 7: + case naluTypefs == h264parser.NALU_SPS: client.CodecUpdateSPS(v) - case naluTypefs == 8: + case naluTypefs == h264parser.NALU_PPS: client.CodecUpdatePPS(v) } } } - retmap = append(retmap, &av.Packet{ - Data: append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), - CompositionTime: time.Duration(1) * time.Millisecond, - Duration: time.Duration(float32(client.timestamp-client.PreVideoTS)/90) * time.Millisecond, - Idx: client.videoIDX, - IsKeyFrame: naluTypef == 5, - Time: time.Duration(client.timestamp/90) * time.Millisecond, - }) + retmap = client.appendVideoPacket(retmap, client.BufferRtpPacket.Bytes(), naluTypef == 5) } } default: @@ -194,11 +175,6 @@ func (client *RTSPClient) handleH264Payload(content, nal []byte, retmap []*av.Pa return retmap } -const ( - TimeBaseFactor = 90 - TimeDelay = 1 -) - func (client *RTSPClient) handleH265Payload(nal []byte, retmap []*av.Packet) []*av.Packet { naluType := (nal[0] >> 1) & 0x3f switch naluType { From 413b746b2f3d01295cff8bb1d5d2aea5ea1b8e72 Mon Sep 17 00:00:00 2001 From: Andrey Semochkin Date: Tue, 5 Mar 2024 14:52:49 +0300 Subject: [PATCH 25/25] add range header --- format/rtsp/client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/format/rtsp/client.go b/format/rtsp/client.go index 2aa4791..d15c146 100644 --- a/format/rtsp/client.go +++ b/format/rtsp/client.go @@ -1191,6 +1191,7 @@ func (self *Client) Play() (err error) { Method: "PLAY", Uri: self.requestUri, } + req.Header = append(req.Header, "Range: npt=0.000-") req.Header = append(req.Header, "Session: "+self.session) if err = self.WriteRequest(req); err != nil { return