Part program in two logical units: ingest and storage.
This commit is contained in:
parent
c47438f2b1
commit
489b60b11e
@ -12,13 +12,13 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// Parse camera links from YAML file into struct Cameras.
|
// Parse camera links from YAML file into struct Cameras.
|
||||||
c, err := config.ParseCamerasYAML(*directory)
|
cams, err := config.ParseCamerasYAML(*directory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to each camera.
|
// Connect to each camera.
|
||||||
for _, link := range c {
|
for _, link := range cams {
|
||||||
log.Printf("process camera:\n %s\n", link)
|
log.Printf("process camera:\n %s\n", link)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -3,14 +3,14 @@ module git.insit.tech/psa/rtsp_reader-writer/writer
|
|||||||
go 1.24.1
|
go 1.24.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.insit.tech/sas/rtsp_proxy v0.0.0-20250310124520-82fa76149f4e
|
git.insit.tech/sas/rtsp_proxy v0.0.0-20250325071536-7b97f96d64e6
|
||||||
github.com/Eyevinn/mp4ff v0.47.0
|
github.com/Eyevinn/mp4ff v0.47.0
|
||||||
github.com/bluenviron/gortsplib/v4 v4.12.3
|
github.com/bluenviron/gortsplib/v4 v4.12.3
|
||||||
github.com/bluenviron/mediacommon v1.14.0
|
github.com/bluenviron/mediacommon v1.14.0
|
||||||
github.com/bluenviron/mediacommon/v2 v2.0.0
|
github.com/bluenviron/mediacommon/v2 v2.0.0
|
||||||
github.com/gen2brain/aac-go v0.0.0-20230119102159-ef1e76509d21
|
github.com/gen2brain/aac-go v0.0.0-20230119102159-ef1e76509d21
|
||||||
github.com/golang/snappy v1.0.0
|
github.com/golang/snappy v1.0.0
|
||||||
github.com/pion/rtp v1.8.12
|
github.com/pion/rtp v1.8.13
|
||||||
github.com/zaf/g711 v1.4.0
|
github.com/zaf/g711 v1.4.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
@ -18,12 +18,15 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/asticode/go-astikit v0.52.0 // indirect
|
github.com/asticode/go-astikit v0.52.0 // indirect
|
||||||
github.com/asticode/go-astits v1.13.0 // indirect
|
github.com/asticode/go-astits v1.13.0 // indirect
|
||||||
github.com/cyub/ringbuffer v0.0.0-20221202135829-35445cc89929 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/grafov/m3u8 v0.12.1 // indirect
|
github.com/grafov/m3u8 v0.12.1 // indirect
|
||||||
github.com/pion/randutil v0.1.0 // indirect
|
github.com/pion/randutil v0.1.0 // indirect
|
||||||
github.com/pion/rtcp v1.2.15 // indirect
|
github.com/pion/rtcp v1.2.15 // indirect
|
||||||
github.com/pion/sdp/v3 v3.0.10 // indirect
|
github.com/pion/sdp/v3 v3.0.11 // indirect
|
||||||
|
github.com/zencoder/go-dash v0.0.0-20201006100653-2f93b14912b2 // indirect
|
||||||
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/net v0.37.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
git.insit.tech/sas/rtsp_proxy v0.0.0-20250310124520-82fa76149f4e h1:JeOZvcZA4JHfoBG5ES9tpSHrhOj1jmjFzSJAyKIjApU=
|
git.insit.tech/sas/rtsp_proxy v0.0.0-20250325071536-7b97f96d64e6 h1:9WyrbPswZtjr3sqoCYaqus22j5st2HuVjWMiBTAorsM=
|
||||||
git.insit.tech/sas/rtsp_proxy v0.0.0-20250310124520-82fa76149f4e/go.mod h1:9Yw6g7jcG9fIkWh6FGXSWTyZs4d7EQWaRhdKnnH2TvA=
|
git.insit.tech/sas/rtsp_proxy v0.0.0-20250325071536-7b97f96d64e6/go.mod h1:/AHWd1Otr+ikOLWzpXtoozzifEx9ZKou+R6DgwaEzr0=
|
||||||
github.com/Eyevinn/mp4ff v0.47.0 h1:XSSHYt5+I0fyOnHWoNwM72DtivlmHFR0V9azgIi+ZVU=
|
github.com/Eyevinn/mp4ff v0.47.0 h1:XSSHYt5+I0fyOnHWoNwM72DtivlmHFR0V9azgIi+ZVU=
|
||||||
github.com/Eyevinn/mp4ff v0.47.0/go.mod h1:hJNUUqOBryLAzUW9wpCJyw2HaI+TCd2rUPhafoS5lgg=
|
github.com/Eyevinn/mp4ff v0.47.0/go.mod h1:hJNUUqOBryLAzUW9wpCJyw2HaI+TCd2rUPhafoS5lgg=
|
||||||
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
|
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
|
||||||
@ -13,11 +13,9 @@ github.com/bluenviron/mediacommon v1.14.0 h1:lWCwOBKNKgqmspRpwpvvg3CidYm+XOc2+z/
|
|||||||
github.com/bluenviron/mediacommon v1.14.0/go.mod h1:z5LP9Tm1ZNfQV5Co54PyOzaIhGMusDfRKmh42nQSnyo=
|
github.com/bluenviron/mediacommon v1.14.0/go.mod h1:z5LP9Tm1ZNfQV5Co54PyOzaIhGMusDfRKmh42nQSnyo=
|
||||||
github.com/bluenviron/mediacommon/v2 v2.0.0 h1:JinZ9v2x6QeAOzA0cDA6aFe8vQuCrU8OyWEhG2iNzwY=
|
github.com/bluenviron/mediacommon/v2 v2.0.0 h1:JinZ9v2x6QeAOzA0cDA6aFe8vQuCrU8OyWEhG2iNzwY=
|
||||||
github.com/bluenviron/mediacommon/v2 v2.0.0/go.mod h1:iHEz1SFIet6zBwAQoh1a92vTQ3dV3LpVFbom6/SLz3k=
|
github.com/bluenviron/mediacommon/v2 v2.0.0/go.mod h1:iHEz1SFIet6zBwAQoh1a92vTQ3dV3LpVFbom6/SLz3k=
|
||||||
github.com/cyub/ringbuffer v0.0.0-20221202135829-35445cc89929 h1:ZPgY61C6ZvVsr4YIBOOcXZ2lw/FuJ4GcoTRPDkHQ3Zg=
|
|
||||||
github.com/cyub/ringbuffer v0.0.0-20221202135829-35445cc89929/go.mod h1:049xI0W4vQexZfPJl70HOMs0eJ7FAZxTtm4iPp1cEDY=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gen2brain/aac-go v0.0.0-20230119102159-ef1e76509d21 h1:yfrARW/aVlqKORCdKrYdU0PZUKPqQvYEUQBKfVlNa9Q=
|
github.com/gen2brain/aac-go v0.0.0-20230119102159-ef1e76509d21 h1:yfrARW/aVlqKORCdKrYdU0PZUKPqQvYEUQBKfVlNa9Q=
|
||||||
github.com/gen2brain/aac-go v0.0.0-20230119102159-ef1e76509d21/go.mod h1:HZqGD/LXHB1VCGUGNzuyxSsD12f3KjbJbvImAmoK/mM=
|
github.com/gen2brain/aac-go v0.0.0-20230119102159-ef1e76509d21/go.mod h1:HZqGD/LXHB1VCGUGNzuyxSsD12f3KjbJbvImAmoK/mM=
|
||||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||||
@ -32,20 +30,16 @@ 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/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||||
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
||||||
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
||||||
github.com/pion/rtp v1.8.12 h1:nsKs8Wi0jQyBFHU3qmn/OvtZrhktVfJY0vRxwACsL5U=
|
github.com/pion/rtp v1.8.13 h1:8uSUPpjSL4OlwZI8Ygqu7+h2p9NPFB+yAZ461Xn5sNg=
|
||||||
github.com/pion/rtp v1.8.12/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
|
github.com/pion/rtp v1.8.13/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
|
||||||
github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
|
github.com/pion/sdp/v3 v3.0.11 h1:VhgVSopdsBKwhCFoyyPmT1fKMeV9nLMrEKxNOdy3IVI=
|
||||||
github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
github.com/pion/sdp/v3 v3.0.11/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
||||||
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
|
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
|
||||||
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/youpy/go-riff v0.1.0 h1:vZO/37nI4tIET8tQI0Qn0Y79qQh99aEpponTPiPut7k=
|
github.com/youpy/go-riff v0.1.0 h1:vZO/37nI4tIET8tQI0Qn0Y79qQh99aEpponTPiPut7k=
|
||||||
@ -54,13 +48,22 @@ github.com/youpy/go-wav v0.3.2 h1:NLM8L/7yZ0Bntadw/0h95OyUsen+DQIVf9gay+SUsMU=
|
|||||||
github.com/youpy/go-wav v0.3.2/go.mod h1:0FCieAXAeSdcxFfwLpRuEo0PFmAoc+8NU34h7TUvk50=
|
github.com/youpy/go-wav v0.3.2/go.mod h1:0FCieAXAeSdcxFfwLpRuEo0PFmAoc+8NU34h7TUvk50=
|
||||||
github.com/zaf/g711 v1.4.0 h1:XZYkjjiAg9QTBnHqEg37m2I9q3IIDv5JRYXs2N8ma7c=
|
github.com/zaf/g711 v1.4.0 h1:XZYkjjiAg9QTBnHqEg37m2I9q3IIDv5JRYXs2N8ma7c=
|
||||||
github.com/zaf/g711 v1.4.0/go.mod h1:eCDXt3dSp/kYYAoooba7ukD/Q75jvAaS4WOMr0l1Roo=
|
github.com/zaf/g711 v1.4.0/go.mod h1:eCDXt3dSp/kYYAoooba7ukD/Q75jvAaS4WOMr0l1Roo=
|
||||||
|
github.com/zencoder/go-dash v0.0.0-20201006100653-2f93b14912b2 h1:0iAY2pL6yYhNYpdc1DbFq0p7ocyu5MlgKmkealhz3nk=
|
||||||
|
github.com/zencoder/go-dash v0.0.0-20201006100653-2f93b14912b2/go.mod h1:c8Gxxfmh0jmZ6G+ISlpa315WBVkzd8mEhu6gN9mn5Qg=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
@ -1,33 +1,19 @@
|
|||||||
package storage
|
package rtsp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.insit.tech/sas/rtsp_proxy/protos"
|
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CutURI returns the last part of the URI after "/".
|
// cutURI returns the last part of the URI after "/".
|
||||||
func CutURI(URI string) (CutterURI string) {
|
func cutURI(URI string) (CutURI string) {
|
||||||
splitted := strings.Split(URI, "/")
|
splitted := strings.Split(URI, "/")
|
||||||
return splitted[len(splitted)-1]
|
return splitted[len(splitted)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFileName creates FileName structure.
|
// waitPeriod waits for the next period.
|
||||||
func CreateFileName(dir string, resolutions []string, cuttedURI string, period int) *protos.FileName {
|
func waitPeriod(period int) {
|
||||||
fn := protos.FileName{
|
|
||||||
Path: dir + "/data/" + cuttedURI + "/" + resolutions[0],
|
|
||||||
TimeNow: time.Now().Format("15-04-05_02-01-2006"),
|
|
||||||
Name: "videoFragment",
|
|
||||||
Number: -1,
|
|
||||||
Duration: float64(period),
|
|
||||||
}
|
|
||||||
|
|
||||||
return &fn
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitPeriod waits for the next period.
|
|
||||||
func WaitPeriod(period int) {
|
|
||||||
periodTD := time.Duration(period) * time.Second
|
periodTD := time.Duration(period) * time.Second
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@ -37,7 +23,8 @@ func WaitPeriod(period int) {
|
|||||||
time.Sleep(waitDuration)
|
time.Sleep(waitDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindResolution(Body []byte) string {
|
// findResolution finds resolution in SDP.
|
||||||
|
func findResolution(Body []byte) string {
|
||||||
split := strings.Split(string(Body), "\r\n")
|
split := strings.Split(string(Body), "\r\n")
|
||||||
for _, line := range split {
|
for _, line := range split {
|
||||||
if strings.Contains(line, "a=x-dimensions:") {
|
if strings.Contains(line, "a=x-dimensions:") {
|
File diff suppressed because it is too large
Load Diff
@ -1,23 +1,126 @@
|
|||||||
package storage
|
package storage
|
||||||
|
|
||||||
const (
|
import (
|
||||||
PacketTypeH264 = 1
|
"bytes"
|
||||||
PacketTypeLPCM = 2
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InterleavedPacket представляет пакет, который может быть либо H264, либо G711.
|
// Constants for detection video and audio types.
|
||||||
|
const (
|
||||||
|
PacketTypeAV1 = 1
|
||||||
|
PacketTypeH264 = 2
|
||||||
|
PacketTypeH265 = 3
|
||||||
|
PacketTypeMJPEG = 4
|
||||||
|
PacketTypeVP8 = 5
|
||||||
|
PacketTypeVP9 = 6
|
||||||
|
|
||||||
|
PacketTypeG711 = 21
|
||||||
|
PacketTypeAAC = 22
|
||||||
|
PacketTypeLPCM = 23
|
||||||
|
PacketTypeOPUS = 24
|
||||||
|
)
|
||||||
|
|
||||||
|
// InterleavedPacket is the structure of each inner packet.
|
||||||
type InterleavedPacket struct {
|
type InterleavedPacket struct {
|
||||||
// Type: 1 для H264, 2 для G711.
|
|
||||||
Type byte
|
Type byte
|
||||||
Pts int64
|
Pts int64
|
||||||
|
// Для H264 – access units как [][]byte.
|
||||||
H264AUs [][]byte
|
H264AUs [][]byte
|
||||||
|
// Для LPCM (из G711) – samples.
|
||||||
LPCMSamples []byte
|
LPCMSamples []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Segment содержит строковые поля Start и Duration, а также набор interleaved пакетов.
|
// Segment is overall structure according to each period.
|
||||||
type Segment struct {
|
type Segment struct {
|
||||||
Start string
|
Date string
|
||||||
Duration string
|
Duration string
|
||||||
Packets InterleavedPacket
|
Packets InterleavedPacket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeString записывает строку: сначала int32 длина, затем данные.
|
||||||
|
func writeString(w io.Writer, s string) error {
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, int32(len(s))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := w.Write([]byte(s))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePacket записывает один interleaved пакет.
|
||||||
|
func WritePacket(w io.Writer, pkt InterleavedPacket) error {
|
||||||
|
// Записываем тип пакета (1 байт)
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, pkt.Type); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Записываем pts (int64)
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, pkt.Pts); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkt.Type == PacketTypeH264 {
|
||||||
|
// Для H264 – AU как [][]byte.
|
||||||
|
numAUs := int32(len(pkt.H264AUs))
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, numAUs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, au := range pkt.H264AUs {
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, int32(len(au))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(au); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if pkt.Type == PacketTypeLPCM {
|
||||||
|
// Для LPCM – просто длина и данные.
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, int32(len(pkt.LPCMSamples))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(pkt.LPCMSamples); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("неизвестный тип пакета: %d", pkt.Type)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteHeader записывает заголовок сегмента (Start и Duration).
|
||||||
|
func WriteHeader(w io.Writer, seg Segment) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := writeString(&buf, seg.Date); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writeString(&buf, seg.Duration); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
segData := buf.Bytes()
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, int32(len(segData))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := w.Write(segData)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteInterleavedPacket записывает сегмент с пакетами.
|
||||||
|
// Теперь количество пакетов определяется динамически.
|
||||||
|
func WriteInterleavedPacket(w io.Writer, seg Segment) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
if err := binary.Write(&buf, binary.LittleEndian, int32(1)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Записываем каждый пакет.
|
||||||
|
if err := WritePacket(&buf, seg.Packets); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
segData := buf.Bytes()
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, int32(len(segData))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := w.Write(segData)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
19
writer/internal/storage/file_manager.go
Normal file
19
writer/internal/storage/file_manager.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.insit.tech/sas/rtsp_proxy/proto/common"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateFileName creates FileName structure.
|
||||||
|
func CreateFileName(dir string, resolutions []string, cuttedURI string, period int) *common.FileName {
|
||||||
|
fn := common.FileName{
|
||||||
|
Path: dir + "/data/" + cuttedURI + "/" + resolutions[0],
|
||||||
|
TimeNow: time.Now().Format("15-04-05_02-01-2006"),
|
||||||
|
Name: "videoFragment",
|
||||||
|
Number: -1,
|
||||||
|
Duration: float64(period),
|
||||||
|
}
|
||||||
|
|
||||||
|
return &fn
|
||||||
|
}
|
@ -1,162 +0,0 @@
|
|||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/golang/snappy"
|
|
||||||
)
|
|
||||||
|
|
||||||
// writeString записывает строку: сначала длину (int32), затем байты строки.
|
|
||||||
func writeString(w io.Writer, s string) error {
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, int32(len(s))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err := w.Write([]byte(s))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// WritePacket записывает один interleaved пакет в writer.
|
|
||||||
func WritePacket(w io.Writer, pkt InterleavedPacket) error {
|
|
||||||
// Записываем тип пакета (1 байт).
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, pkt.Type); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Записываем pts.
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, pkt.Pts); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// В зависимости от типа пакета записываем данные access unit.
|
|
||||||
if pkt.Type == PacketTypeH264 {
|
|
||||||
// Для H264 AU — [][]byte.
|
|
||||||
numAUs := int32(len(pkt.H264AUs))
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, numAUs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, au := range pkt.H264AUs {
|
|
||||||
// Сначала длина AU.
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, int32(len(au))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Затем сами данные.
|
|
||||||
if _, err := w.Write(au); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if pkt.Type == PacketTypeLPCM {
|
|
||||||
// Для G711 AU — []byte.
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, int32(len(pkt.LPCMSamples))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write(pkt.LPCMSamples); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("неизвестный тип пакета: %d", pkt.Type)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteHeader writes header to a file.
|
|
||||||
func WriteHeader(w io.Writer, seg Segment) error {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
// Записываем строки Start и Duration.
|
|
||||||
if err := writeString(&buf, seg.Start); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := writeString(&buf, seg.Duration); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сначала записываем длину сегмента, затем данные сегмента.
|
|
||||||
segData := buf.Bytes()
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, int32(len(segData))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err := w.Write(segData)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteInterleavedPacket записывает один сегмент в writer. Сначала собирается содержимое сегмента в буфер,
|
|
||||||
// затем записывается его длина (int32) и данные.
|
|
||||||
func WriteInterleavedPacket(w io.Writer, seg Segment) error {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
// Записываем количество пакетов.
|
|
||||||
if err := binary.Write(&buf, binary.LittleEndian, int32(1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Для каждого пакета записываем данные.
|
|
||||||
if err := WritePacket(&buf, seg.Packets); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сначала записываем длину сегмента, затем данные сегмента.
|
|
||||||
segData := buf.Bytes()
|
|
||||||
if err := binary.Write(w, binary.LittleEndian, int32(len(segData))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err := w.Write(segData)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
now := time.Now()
|
|
||||||
// Пример сегмента с interleaved пакетами.
|
|
||||||
seg := Segment{
|
|
||||||
Start: now.Format(time.RFC3339),
|
|
||||||
Duration: "1m", // длительность сегмента в виде строки
|
|
||||||
Packets: InterleavedPacket{
|
|
||||||
|
|
||||||
Type: PacketTypeH264,
|
|
||||||
Pts: now.UnixNano(),
|
|
||||||
H264AUs: [][]byte{
|
|
||||||
[]byte{0x00, 0x01, 0x02},
|
|
||||||
[]byte{0x03, 0x04},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Открываем файл для записи.
|
|
||||||
f, err := os.Create("stream_interleaved.bin")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Ошибка создания файла:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
// Оборачиваем writer через snappy для быстрой компрессии (если требуется).
|
|
||||||
writer := snappy.NewBufferedWriter(f)
|
|
||||||
defer writer.Close()
|
|
||||||
|
|
||||||
// Записываем заголовок файла (например, streamID).
|
|
||||||
streamID := "example_stream"
|
|
||||||
if err := binary.Write(writer, binary.LittleEndian, int32(len(streamID))); err != nil {
|
|
||||||
fmt.Println("Ошибка записи заголовка:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err := writer.Write([]byte(streamID)); err != nil {
|
|
||||||
fmt.Println("Ошибка записи streamID:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Записываем сегмент с interleaved пакетами.
|
|
||||||
if err := WriteInterleavedPacket(writer, seg); err != nil {
|
|
||||||
fmt.Println("Ошибка записи сегмента:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обязательно делаем Flush, чтобы данные точно записались.
|
|
||||||
if err := writer.Flush(); err != nil {
|
|
||||||
fmt.Println("Ошибка при сбросе данных:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Сегмент с interleaved пакетами успешно записан.")
|
|
||||||
}
|
|
67
writer/internal/storage/temp.go
Normal file
67
writer/internal/storage/temp.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/snappy"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
now := time.Now()
|
||||||
|
// Обратите внимание: Packets – срез, поэтому оборачиваем пакет в литерал среза.
|
||||||
|
seg := Segment{
|
||||||
|
Date: now.Format(time.RFC3339),
|
||||||
|
Duration: "1m",
|
||||||
|
Packets: InterleavedPacket{
|
||||||
|
|
||||||
|
Type: PacketTypeH264,
|
||||||
|
Pts: now.UnixNano(),
|
||||||
|
H264AUs: [][]byte{
|
||||||
|
[]byte{0x00, 0x01, 0x02},
|
||||||
|
[]byte{0x03, 0x04},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create("stream_interleaved.bin")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Ошибка создания файла:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
writer := snappy.NewBufferedWriter(f)
|
||||||
|
defer writer.Close()
|
||||||
|
|
||||||
|
streamID := "example_stream"
|
||||||
|
if err := binary.Write(writer, binary.LittleEndian, int32(len(streamID))); err != nil {
|
||||||
|
fmt.Println("Ошибка записи заголовка:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := writer.Write([]byte(streamID)); err != nil {
|
||||||
|
fmt.Println("Ошибка записи streamID:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Здесь можно записывать сначала заголовочный сегмент, затем сегменты с пакетами.
|
||||||
|
// Например, если заголовочный сегмент содержит только Start и Duration:
|
||||||
|
if err := WriteHeader(writer, seg); err != nil {
|
||||||
|
fmt.Println("Ошибка записи заголовочного сегмента:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// А затем записываем сегмент с пакетами:
|
||||||
|
if err := WriteInterleavedPacket(writer, seg); err != nil {
|
||||||
|
fmt.Println("Ошибка записи сегмента пакетов:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writer.Flush(); err != nil {
|
||||||
|
fmt.Println("Ошибка при сбросе данных:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Сегмент с interleaved пакетами успешно записан.")
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user