update dependencies (#2176)

This commit is contained in:
Alessandro Ros 2023-08-07 20:25:45 +02:00 committed by GitHub
parent bc8dcc4bb9
commit 161a9b54b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 182 additions and 191 deletions

8
go.mod
View File

@ -4,11 +4,11 @@ go 1.20
require (
code.cloudfoundry.org/bytefmt v0.0.0
github.com/abema/go-mp4 v0.11.0
github.com/abema/go-mp4 v0.12.0
github.com/alecthomas/kong v0.8.0
github.com/bluenviron/gohlslib v0.3.1-0.20230806182538-54b835e0ef2c
github.com/bluenviron/gohlslib v0.3.1-0.20230807104729-4e6cc9740504
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806185830-e6e9e8490907
github.com/bluenviron/mediacommon v0.7.1-0.20230806185229-f060a1e5295b
github.com/bluenviron/mediacommon v0.7.1-0.20230807094324-74973d4d50b1
github.com/datarhei/gosrt v0.5.3
github.com/fsnotify/fsnotify v1.6.0
github.com/gin-gonic/gin v1.9.1
@ -31,7 +31,7 @@ require (
)
require (
github.com/aler9/writerseeker v1.0.0 // indirect
github.com/aler9/writerseeker v1.1.0 // indirect
github.com/asticode/go-astikit v0.30.0 // indirect
github.com/asticode/go-astits v1.12.0 // indirect
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c // indirect

17
go.sum
View File

@ -1,25 +1,25 @@
github.com/abema/go-mp4 v0.11.0 h1:XJfpSmEdUBMvWnDKIiNznLGZPpeDxJ/qDdN6Ust1ADk=
github.com/abema/go-mp4 v0.11.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
github.com/abema/go-mp4 v0.12.0 h1:XI9PPt1BpjB3wFl18oFiX6C99uesx7F/X13Z+ga8bYY=
github.com/abema/go-mp4 v0.12.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s=
github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/aler9/gosrt v0.0.0-20230803201410-b26769a3a222 h1:69Oj9CKfxxkTqFtBfBNo7zP4HcxEwjpFnFNHHX2Z06c=
github.com/aler9/gosrt v0.0.0-20230803201410-b26769a3a222/go.mod h1:EryxR+Men7aW67IX2FEo56SU+Pay9OHCw3kZx23qKyQ=
github.com/aler9/writerseeker v1.0.0 h1:3wI/NtI20WqX8iLjrivym5VGXxug3EkRPaLRw6k9f9M=
github.com/aler9/writerseeker v1.0.0/go.mod h1:J5H8yGtvHnTM3DddPusobve1mDTYgdAj7eAwjGj8FXY=
github.com/aler9/writerseeker v1.1.0 h1:t+Sm3tjp8scNlqyoa8obpeqwciMNOvdvsxjxEb3Sx3g=
github.com/aler9/writerseeker v1.1.0/go.mod h1:QNCcjSKnLsYoTfMmXkEEfgbz6nNXWxKSaBY+hGJGWDA=
github.com/asticode/go-astikit v0.30.0 h1:DkBkRQRIxYcknlaU7W7ksNfn4gMFsB0tqMJflxkRsZA=
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
github.com/asticode/go-astits v1.12.0 h1:BiefTgVEyPgEB8nT6J+Sys/uxE4H/a04SW/aedpOpPc=
github.com/asticode/go-astits v1.12.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYhJeJ2aZxADI2tGADS15AzIF8MQ8XAhT4=
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
github.com/bluenviron/gohlslib v0.3.1-0.20230806182538-54b835e0ef2c h1:wztDQy5iTijIZz4v+mkbJkTIHoQ/MHtdMSPirTQy5uQ=
github.com/bluenviron/gohlslib v0.3.1-0.20230806182538-54b835e0ef2c/go.mod h1:SoCWetcOsLi70kcUBBrckYFfmLPJuqmXVGP10OlEc70=
github.com/bluenviron/gohlslib v0.3.1-0.20230807104729-4e6cc9740504 h1:deslGxDQKii0onlMCVOekMvYqhsK+pYbzuAA5QltnMI=
github.com/bluenviron/gohlslib v0.3.1-0.20230807104729-4e6cc9740504/go.mod h1:SoCWetcOsLi70kcUBBrckYFfmLPJuqmXVGP10OlEc70=
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806185830-e6e9e8490907 h1:EPRg+yYqp7eZr9ROvjSvHJf7TIcu31spCGKbjHzpilM=
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806185830-e6e9e8490907/go.mod h1:tK2JtJRkKUIhmZEyRWCd8rtiqbirO4eMXt7fN5Yont4=
github.com/bluenviron/mediacommon v0.7.1-0.20230806185229-f060a1e5295b h1:53WQf0Kam0/Rj4bnTWhpo6n6cCrRE84tjf9xrwq8mWo=
github.com/bluenviron/mediacommon v0.7.1-0.20230806185229-f060a1e5295b/go.mod h1:LR4w8cpvzo2ZcmBwXcentvBj7ZlyF9g9xP4dDbt8uJw=
github.com/bluenviron/mediacommon v0.7.1-0.20230807094324-74973d4d50b1 h1:xj1wSfxUGmvF1QAVgOypMG9Tdj9fF7Ky2o26O83a99Y=
github.com/bluenviron/mediacommon v0.7.1-0.20230807094324-74973d4d50b1/go.mod h1:nt5oKCO0WcZ+AH1oc12gs2ldp67xW2vl88c2StNmPlI=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
@ -217,6 +217,7 @@ 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/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@ -347,7 +347,7 @@ func (m *hlsMuxer) createVideoTrack(stream *stream.Stream) (*media.Media, *gohls
m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitAV1)
if tunit.OBUs == nil {
if tunit.TU == nil {
return nil
}
@ -357,7 +357,7 @@ func (m *hlsMuxer) createVideoTrack(stream *stream.Stream) (*media.Media, *gohls
}
pts := tunit.PTS - startPTS
err := m.muxer.WriteAV1(tunit.NTP, pts, tunit.OBUs)
err := m.muxer.WriteAV1(tunit.NTP, pts, tunit.TU)
if err != nil {
return fmt.Errorf("muxer error: %v", err)
}

View File

@ -48,7 +48,8 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
}
}()
c := &gohlslib.Client{
var c *gohlslib.Client
c = &gohlslib.Client{
URI: cnf.Source,
HTTPClient: &http.Client{
Transport: &http.Transport{
@ -67,146 +68,145 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
OnDecodeError: func(err error) {
s.Log(logger.Warn, err.Error())
},
}
OnTracks: func(tracks []*gohlslib.Track) error {
var medias media.Medias
c.OnTracks(func(tracks []*gohlslib.Track) error {
var medias media.Medias
for _, track := range tracks {
var medi *media.Media
for _, track := range tracks {
var medi *media.Media
switch tcodec := track.Codec.(type) {
case *codecs.AV1:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.AV1{}},
}
switch tcodec := track.Codec.(type) {
case *codecs.AV1:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.AV1{}},
c.OnDataAV1(track, func(pts time.Duration, tu [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitAV1{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
TU: tu,
})
})
case *codecs.VP9:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.VP9{}},
}
c.OnDataVP9(track, func(pts time.Duration, frame []byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitVP9{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
Frame: frame,
})
})
case *codecs.H264:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.H264{
PayloadTyp: 96,
PacketizationMode: 1,
SPS: tcodec.SPS,
PPS: tcodec.PPS,
}},
}
c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH264{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
AU: au,
})
})
case *codecs.H265:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.H265{
PayloadTyp: 96,
VPS: tcodec.VPS,
SPS: tcodec.SPS,
PPS: tcodec.PPS,
}},
}
c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH265{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
AU: au,
})
})
case *codecs.MPEG4Audio:
medi = &media.Media{
Type: media.TypeAudio,
Formats: []formats.Format{&formats.MPEG4Audio{
PayloadTyp: 96,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
Config: &tcodec.Config,
}},
}
c.OnDataMPEG4Audio(track, func(pts time.Duration, aus [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
AUs: aus,
})
})
case *codecs.Opus:
medi = &media.Media{
Type: media.TypeAudio,
Formats: []formats.Format{&formats.Opus{
PayloadTyp: 96,
IsStereo: (tcodec.ChannelCount == 2),
}},
}
c.OnDataOpus(track, func(pts time.Duration, packets [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitOpus{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
Packets: packets,
})
})
}
c.OnDataAV1(track, func(pts time.Duration, obus [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitAV1{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
OBUs: obus,
})
})
case *codecs.VP9:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.VP9{}},
}
c.OnDataVP9(track, func(pts time.Duration, frame []byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitVP9{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
Frame: frame,
})
})
case *codecs.H264:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.H264{
PayloadTyp: 96,
PacketizationMode: 1,
SPS: tcodec.SPS,
PPS: tcodec.PPS,
}},
}
c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH264{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
AU: au,
})
})
case *codecs.H265:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.H265{
PayloadTyp: 96,
VPS: tcodec.VPS,
SPS: tcodec.SPS,
PPS: tcodec.PPS,
}},
}
c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH265{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
AU: au,
})
})
case *codecs.MPEG4Audio:
medi = &media.Media{
Type: media.TypeAudio,
Formats: []formats.Format{&formats.MPEG4Audio{
PayloadTyp: 96,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
Config: &tcodec.Config,
}},
}
c.OnDataMPEG4Audio(track, func(pts time.Duration, aus [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
AUs: aus,
})
})
case *codecs.Opus:
medi = &media.Media{
Type: media.TypeAudio,
Formats: []formats.Format{&formats.Opus{
PayloadTyp: 96,
IsStereo: (tcodec.ChannelCount == 2),
}},
}
c.OnDataOpus(track, func(pts time.Duration, packets [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitOpus{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
Packets: packets,
})
})
medias = append(medias, medi)
}
medias = append(medias, medi)
}
res := s.parent.setReady(pathSourceStaticSetReadyReq{
medias: medias,
generateRTPPackets: true,
})
if res.err != nil {
return res.err
}
res := s.parent.setReady(pathSourceStaticSetReadyReq{
medias: medias,
generateRTPPackets: true,
})
if res.err != nil {
return res.err
}
stream = res.stream
stream = res.stream
return nil
})
return nil
},
}
err := c.Start()
if err != nil {

View File

@ -621,13 +621,13 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
switch videoFormat.(type) {
case *formats.AV1:
r.OnDataAV1(func(pts time.Duration, obus [][]byte) {
r.OnDataAV1(func(pts time.Duration, tu [][]byte) {
stream.WriteUnit(videoMedia, videoFormat, &formatprocessor.UnitAV1{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
OBUs: obus,
PTS: pts,
TU: tu,
})
})

View File

@ -30,17 +30,6 @@ func durationGoToMPEGTS(v time.Duration) int64 {
return int64(v.Seconds() * 90000)
}
func h265RandomAccessPresent(au [][]byte) bool {
for _, nalu := range au {
typ := h265.NALUType((nalu[0] >> 1) & 0b111111)
switch typ {
case h265.NALUType_IDR_W_RADL, h265.NALUType_IDR_N_LP, h265.NALUType_CRA_NUT:
return true
}
}
return false
}
type srtConnState int
const (
@ -454,7 +443,7 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
for _, medi := range res.stream.Medias() {
for _, format := range medi.Formats {
switch format := format.(type) {
case *formats.H265:
case *formats.H265: //nolint:dupl
track := addTrack(medi, &mpegts.CodecH265{})
var startPTS time.Duration
@ -482,10 +471,10 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
startPTSFilled = true
}
randomAccessPresent := h265RandomAccessPresent(tunit.AU)
randomAccess := h265.IsRandomAccess(tunit.AU)
if !randomAccessReceived {
if !randomAccessPresent {
if !randomAccess {
return nil
}
randomAccessReceived = true
@ -510,7 +499,7 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
pts -= leadingTrackStartDTS
sconn.SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
err = w.WriteH26x(track, durationGoToMPEGTS(pts), durationGoToMPEGTS(dts), randomAccessPresent, tunit.AU)
err = w.WriteH26x(track, durationGoToMPEGTS(pts), durationGoToMPEGTS(dts), randomAccess, tunit.AU)
if err != nil {
return err
}
@ -518,7 +507,7 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
})
})
case *formats.H264:
case *formats.H264: //nolint:dupl
track := addTrack(medi, &mpegts.CodecH264{})
var startPTS time.Duration

View File

@ -56,11 +56,11 @@ func newWebRTCOutgoingTrackVideo(medias media.Medias) (*webRTCOutgoingTrack, err
cb: func(unit formatprocessor.Unit) error {
tunit := unit.(*formatprocessor.UnitAV1)
if tunit.OBUs == nil {
if tunit.TU == nil {
return nil
}
packets, err := encoder.Encode(tunit.OBUs, tunit.PTS)
packets, err := encoder.Encode(tunit.TU, tunit.PTS)
if err != nil {
return nil //nolint:nilerr
}

View File

@ -14,8 +14,8 @@ import (
// UnitAV1 is an AV1 data unit.
type UnitAV1 struct {
BaseUnit
PTS time.Duration
OBUs [][]byte
PTS time.Duration
TU [][]byte
}
type formatProcessorAV1 struct {
@ -82,7 +82,7 @@ func (t *formatProcessorAV1) Process(unit Unit, hasNonRTSPReaders bool) error {
}
// DecodeUntilMarker() is necessary, otherwise Encode() generates partial groups
obus, pts, err := t.decoder.DecodeUntilMarker(pkt)
tu, pts, err := t.decoder.DecodeUntilMarker(pkt)
if err != nil {
if err == rtpav1.ErrNonStartingPacketAndNoPrevious || err == rtpav1.ErrMorePacketsNeeded {
return nil
@ -90,7 +90,7 @@ func (t *formatProcessorAV1) Process(unit Unit, hasNonRTSPReaders bool) error {
return err
}
tunit.OBUs = obus
tunit.TU = tu
tunit.PTS = pts
}
@ -99,7 +99,7 @@ func (t *formatProcessorAV1) Process(unit Unit, hasNonRTSPReaders bool) error {
}
// encode into RTP
pkts, err := t.encoder.Encode(tunit.OBUs, tunit.PTS)
pkts, err := t.encoder.Encode(tunit.TU, tunit.PTS)
if err != nil {
return err
}

View File

@ -12,7 +12,6 @@ import (
"github.com/bluenviron/mediacommon/pkg/codecs/h264"
"github.com/bluenviron/mediacommon/pkg/codecs/h265"
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
"github.com/notedit/rtmp/format/flv/flvio"
"github.com/bluenviron/mediamtx/internal/rtmp/h264conf"
@ -20,7 +19,7 @@ import (
)
// OnDataAV1Func is the prototype of the callback passed to OnDataAV1().
type OnDataAV1Func func(pts time.Duration, obus [][]byte)
type OnDataAV1Func func(pts time.Duration, tu [][]byte)
// OnDataH26xFunc is the prototype of the callback passed to OnDataH26x().
type OnDataH26xFunc func(pts time.Duration, au [][]byte)
@ -237,7 +236,7 @@ func tracksFromMetadata(conn *Conn, payload []interface{}) (formats.Format, form
}
case message.FourCCAV1:
var av1c fmp4.Av1C
var av1c mp4.Av1C
_, err := mp4.Unmarshal(bytes.NewReader(tmsg.Config), uint64(len(tmsg.Config)), &av1c, mp4.Context{})
if err != nil {
return nil, nil, fmt.Errorf("invalid AV1 configuration: %v", err)
@ -438,12 +437,12 @@ func (r *Reader) Tracks() (formats.Format, formats.Format) {
func (r *Reader) OnDataAV1(cb OnDataAV1Func) {
r.onDataVideo = func(msg message.Message) error {
if msg, ok := msg.(*message.ExtendedCodedFrames); ok {
obus, err := av1.BitstreamUnmarshal(msg.Payload, true)
tu, err := av1.BitstreamUnmarshal(msg.Payload, true)
if err != nil {
return fmt.Errorf("unable to decode bitstream: %v", err)
}
cb(msg.DTS, obus)
cb(msg.DTS, tu)
}
return nil
}

View File

@ -1,3 +1,5 @@
BINARY_NAME = mediamtx
define DOCKERFILE_BINARIES
FROM $(RPI32_IMAGE) AS rpicamera32
RUN ["cross-build-start"]
@ -26,37 +28,37 @@ RUN mkdir tmp binaries
RUN cp mediamtx.yml LICENSE tmp/
FROM build-base AS build-windows-amd64
RUN GOOS=windows GOARCH=amd64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/mediamtx.exe
RUN cd tmp && zip -q ../binaries/mediamtx_$${VERSION}_windows_amd64.zip mediamtx.exe mediamtx.yml LICENSE
RUN GOOS=windows GOARCH=amd64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/$(BINARY_NAME).exe
RUN cd tmp && zip -q ../binaries/$(BINARY_NAME)_$${VERSION}_windows_amd64.zip $(BINARY_NAME).exe mediamtx.yml LICENSE
FROM build-base AS build-linux-amd64
RUN GOOS=linux GOARCH=amd64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/mediamtx
RUN tar -C tmp -czf binaries/mediamtx_$${VERSION}_linux_amd64.tar.gz --owner=0 --group=0 mediamtx mediamtx.yml LICENSE
RUN GOOS=linux GOARCH=amd64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/$(BINARY_NAME)
RUN tar -C tmp -czf binaries/$(BINARY_NAME)_$${VERSION}_linux_amd64.tar.gz --owner=0 --group=0 $(BINARY_NAME) mediamtx.yml LICENSE
FROM build-base AS build-darwin-amd64
RUN GOOS=darwin GOARCH=amd64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/mediamtx
RUN tar -C tmp -czf binaries/mediamtx_$${VERSION}_darwin_amd64.tar.gz --owner=0 --group=0 mediamtx mediamtx.yml LICENSE
RUN GOOS=darwin GOARCH=amd64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/$(BINARY_NAME)
RUN tar -C tmp -czf binaries/$(BINARY_NAME)_$${VERSION}_darwin_amd64.tar.gz --owner=0 --group=0 $(BINARY_NAME) mediamtx.yml LICENSE
FROM build-base AS build-darwin-arm64
RUN GOOS=darwin GOARCH=arm64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/mediamtx
RUN tar -C tmp -czf binaries/mediamtx_$${VERSION}_darwin_arm64.tar.gz --owner=0 --group=0 mediamtx mediamtx.yml LICENSE
RUN GOOS=darwin GOARCH=arm64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/$(BINARY_NAME)
RUN tar -C tmp -czf binaries/$(BINARY_NAME)_$${VERSION}_darwin_arm64.tar.gz --owner=0 --group=0 $(BINARY_NAME) mediamtx.yml LICENSE
FROM build-base AS build-linux-armv6
COPY --from=rpicamera32 /s/internal/rpicamera/exe/exe internal/rpicamera/exe/
RUN GOOS=linux GOARCH=arm GOARM=6 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/mediamtx -tags rpicamera
RUN tar -C tmp -czf binaries/mediamtx_$${VERSION}_linux_armv6.tar.gz --owner=0 --group=0 mediamtx mediamtx.yml LICENSE
RUN GOOS=linux GOARCH=arm GOARM=6 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/$(BINARY_NAME) -tags rpicamera
RUN tar -C tmp -czf binaries/$(BINARY_NAME)_$${VERSION}_linux_armv6.tar.gz --owner=0 --group=0 $(BINARY_NAME) mediamtx.yml LICENSE
RUN rm internal/rpicamera/exe/exe
FROM build-base AS build-linux-armv7
COPY --from=rpicamera32 /s/internal/rpicamera/exe/exe internal/rpicamera/exe/
RUN GOOS=linux GOARCH=arm GOARM=7 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/mediamtx -tags rpicamera
RUN tar -C tmp -czf binaries/mediamtx_$${VERSION}_linux_armv7.tar.gz --owner=0 --group=0 mediamtx mediamtx.yml LICENSE
RUN GOOS=linux GOARCH=arm GOARM=7 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/$(BINARY_NAME) -tags rpicamera
RUN tar -C tmp -czf binaries/$(BINARY_NAME)_$${VERSION}_linux_armv7.tar.gz --owner=0 --group=0 $(BINARY_NAME) mediamtx.yml LICENSE
RUN rm internal/rpicamera/exe/exe
FROM build-base AS build-linux-arm64
COPY --from=rpicamera64 /s/internal/rpicamera/exe/exe internal/rpicamera/exe/
RUN GOOS=linux GOARCH=arm64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/mediamtx -tags rpicamera
RUN tar -C tmp -czf binaries/mediamtx_$${VERSION}_linux_arm64v8.tar.gz --owner=0 --group=0 mediamtx mediamtx.yml LICENSE
RUN GOOS=linux GOARCH=arm64 go build -ldflags "-X github.com/bluenviron/mediamtx/internal/core.version=$$VERSION" -o tmp/$(BINARY_NAME) -tags rpicamera
RUN tar -C tmp -czf binaries/$(BINARY_NAME)_$${VERSION}_linux_arm64v8.tar.gz --owner=0 --group=0 $(BINARY_NAME) mediamtx.yml LICENSE
RUN rm internal/rpicamera/exe/exe
FROM $(BASE_IMAGE)