Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/.ci.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

PRE_TEST_HOOK=_install_dependencies_hook
PRE_LINT_HOOK=_install_dependencies_hook
GO_MOD_VERSION_EXPECTED=1.24
GO_MOD_VERSION_EXPECTED=1.25
SKIP_i386_TESTS=true
SKIP_WINDOWS_TESTS=true
SKIP_MACOS_TESTS=true
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
uses: pion/.goassets/.github/workflows/test.reusable.yml@main
strategy:
matrix:
go: ["1.25", "1.24"] # auto-update/supported-go-version-list
go: ["1.25"] # auto-update/supported-go-version-list
fail-fast: false
with:
go-version: ${{ matrix.go }}
Expand All @@ -33,7 +33,7 @@ jobs:
uses: pion/.goassets/.github/workflows/test-i386.reusable.yml@main
strategy:
matrix:
go: ["1.25", "1.24"] # auto-update/supported-go-version-list
go: ["1.25"] # auto-update/supported-go-version-list
fail-fast: false
with:
go-version: ${{ matrix.go }}
Expand All @@ -42,7 +42,7 @@ jobs:
uses: pion/.goassets/.github/workflows/test-windows.reusable.yml@main
strategy:
matrix:
go: ["1.25", "1.24"] # auto-update/supported-go-version-list
go: ["1.25"] # auto-update/supported-go-version-list
fail-fast: false
with:
go-version: ${{ matrix.go }}
Expand All @@ -51,7 +51,7 @@ jobs:
uses: pion/.goassets/.github/workflows/test-macos.reusable.yml@main
strategy:
matrix:
go: ["1.25", "1.24"] # auto-update/supported-go-version-list
go: ["1.25"] # auto-update/supported-go-version-list
fail-fast: false
with:
go-version: ${{ matrix.go }}
Expand Down
8 changes: 3 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/pion/example-webrtc-applications/v3

go 1.24.0
go 1.25.0

toolchain go1.26.5

Expand All @@ -9,7 +9,7 @@ require (
github.com/at-wat/ebml-go v0.18.0
github.com/ebitengine/debugui v0.2.0
github.com/emiago/sipgo v1.4.3
github.com/go-gst/go-gst v1.4.0
github.com/go-gst/go-gst v0.0.1
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/hajimehoshi/ebiten/v2 v2.9.9
Expand All @@ -33,15 +33,14 @@ require (
github.com/ebitengine/gomobile v0.0.0-20260211053922-3d992dae95d1 // indirect
github.com/ebitengine/hideconsole v1.0.0 // indirect
github.com/ebitengine/purego v0.10.1 // indirect
github.com/go-gst/go-glib v1.4.0 // indirect
github.com/go-gst/go-glib v0.0.1 // indirect
github.com/go-text/typesetting v0.3.4 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.4.0 // indirect
github.com/hajimehoshi/bitmapfont/v4 v4.1.1 // indirect
github.com/icholy/digest v1.1.0 // indirect
github.com/jezek/xgb v1.3.1 // indirect
github.com/mattn/go-pointer v0.0.1 // indirect
github.com/pierrec/lz4/v4 v4.1.27 // indirect
github.com/pion/datachannel v1.6.2 // indirect
github.com/pion/dtls/v3 v3.1.5 // indirect
Expand All @@ -57,7 +56,6 @@ require (
github.com/rs/xid v1.6.0 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/exp v0.0.0-20260209203927-2842357ff358 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
Expand Down
12 changes: 4 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ github.com/ebitengine/purego v0.10.1 h1:dewVBCBT2GaMu1SrNTYxQhgQBethzfhiwvZiLGP/
github.com/ebitengine/purego v0.10.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/emiago/sipgo v1.4.3 h1:Ju1Ilp0LhTcSHCyp2jBYAQDQ8TAwuxQHzT1IhO6jSIY=
github.com/emiago/sipgo v1.4.3/go.mod h1:DuwAxBZhKMqIzQFPGZb1MVAGU6Wuxj64oTOhd5dx/FY=
github.com/go-gst/go-glib v1.4.0 h1:FB2uVfB0uqz7/M6EaDdWWlBZRQpvFAbWfL7drdw8lAE=
github.com/go-gst/go-glib v1.4.0/go.mod h1:GUIpWmkxQ1/eL+FYSjKpLDyTZx6Vgd9nNXt8dA31d5M=
github.com/go-gst/go-gst v1.4.0 h1:EikB43u4c3wc8d2RzlFRSfIGIXYzDy6Zls2vJqrG2BU=
github.com/go-gst/go-gst v1.4.0/go.mod h1:p8TLGtOxJLcrp6PCkTPdnanwWBxPZvYiHDbuSuwgO3c=
github.com/go-gst/go-glib v0.0.1 h1:+nHzGo7F0zIM1/VTqzGnr4ckzfn/kk/GCVJWzH1uPgU=
github.com/go-gst/go-glib v0.0.1/go.mod h1:n9WnJ6bNPKRrc7aWKgrsRfNh3LPw5RSz6dfcB1bd0Qk=
github.com/go-gst/go-gst v0.0.1 h1:Xkuv2pY4KyiQxDAbgJqBzpdQHiEex2wqbb8qxzUjSJA=
github.com/go-gst/go-gst v0.0.1/go.mod h1:zzkqr1po9KGciuVBY9hsDeOWsOGllEa1+lZeL7ELNfk=
github.com/go-text/typesetting v0.3.4 h1:YYurUOtEb9kGSOz4uE3k4OpBGsp1dDL8+fjCeaFamAU=
github.com/go-text/typesetting v0.3.4/go.mod h1:4qZCQphq4KSgGTAeI0uMEkVbROgfah8BuyF5LRYr7XY=
github.com/go-text/typesetting-utils v0.0.0-20260223113751-2d88ac90dae3 h1:drBZzMgdYPbmyXqOto4YhhJGrFIQCX94FpR4MzTCsos=
Expand All @@ -46,8 +46,6 @@ github.com/jezek/xgb v1.3.1 h1:NQCAEfQyzN+3RjWUSHBuVIxQcy2YfG3/mNvKfs/0rEg=
github.com/jezek/xgb v1.3.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/kelindar/binary v1.0.19 h1:DNyQCtKjkLhBh9pnP49OWREddLB0Mho+1U/AOt/Qzxw=
github.com/kelindar/binary v1.0.19/go.mod h1:/twdz8gRLNMffx0U4UOgqm1LywPs6nd9YK2TX52MDh8=
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/notedit/janus-go v0.0.0-20210115013133-fdce1b146d0e h1:L1QWI1FyFkgLOLSP/BlbkLiyLyqUuyxCCRJyULDinx8=
github.com/notedit/janus-go v0.0.0-20210115013133-fdce1b146d0e/go.mod h1:BN/Txse3qz8tZOmCm2OfajB2wHVujWmX3o9nVdsI6gE=
github.com/pierrec/lz4/v4 v4.1.27 h1:+PhzhWDrjRj89TH2sw43nE3+4+W8lSxIuQadEHZyjUk=
Expand Down Expand Up @@ -104,8 +102,6 @@ gocv.io/x/gocv v0.43.0 h1:PFNpRUcV8fgBRDbVHHN+4BDZjjPnVveo5N/+e15BTuA=
gocv.io/x/gocv v0.43.0/go.mod h1:zYdWMj29WAEznM3Y8NsU3A0TRq/wR/cy75jeUypThqU=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/exp v0.0.0-20260209203927-2842357ff358 h1:kpfSV7uLwKJbFSEgNhWzGSL47NDSF/5pYYQw1V0ub6c=
golang.org/x/exp v0.0.0-20260209203927-2842357ff358/go.mod h1:R3t0oliuryB5eenPWl3rrQxwnNM3WTwnsRZZiXLAAW8=
golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc=
golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4=
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
Expand Down
47 changes: 36 additions & 11 deletions gstreamer-receive/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ import (
"strings"
"time"

"github.com/go-gst/go-gst/gst"
"github.com/go-gst/go-gst/gst/app"
"github.com/go-gst/go-gst/pkg/gst"
"github.com/go-gst/go-gst/pkg/gstapp"
"github.com/pion/rtcp"
"github.com/pion/webrtc/v4"
)

func main() {
// Initialize GStreamer
gst.Init(nil)
gst.Init()

// Everything below is the Pion WebRTC API! Thanks for using it ❤️.

Expand Down Expand Up @@ -72,7 +72,7 @@ func main() {
panic(err)
}

appSrc.PushBuffer(gst.NewBufferFromBytes(buf[:i]))
appSrc.PushBuffer(bufferFromBytes(buf[:i]))
}
})

Expand Down Expand Up @@ -120,7 +120,7 @@ func main() {
}

// Create the appropriate GStreamer pipeline depending on what codec we are working with.
func pipelineForCodec(track *webrtc.TrackRemote, codecName string) *app.Source {
func pipelineForCodec(track *webrtc.TrackRemote, codecName string) gstapp.AppSrc {
pipelineString := "appsrc format=time is-live=true do-timestamp=true name=src ! application/x-rtp"
switch strings.ToLower(codecName) {
case "vp8":
Expand All @@ -137,21 +137,46 @@ func pipelineForCodec(track *webrtc.TrackRemote, codecName string) *app.Source {
panic("Unhandled codec " + codecName) //nolint
}

pipeline, err := gst.NewPipelineFromString(pipelineString)
pipeline := startPipeline(pipelineString)

appSrc, ok := pipeline.GetByName("src").(gstapp.AppSrc)
if !ok {
panic("failed to find GStreamer appsrc")
}

return appSrc
}

func startPipeline(pipelineString string) gst.Pipeline {
element, err := gst.ParseLaunch(pipelineString)
if err != nil {
panic(err)
}
pipeline, ok := element.(gst.Pipeline)
if !ok {
panic("GStreamer launch description did not produce a pipeline")
}

if err = pipeline.SetState(gst.StatePlaying); err != nil {
panic(err)
if pipeline.SetState(gst.StatePlaying) == gst.StateChangeFailure {
panic("failed to start GStreamer pipeline")
}

appSrc, err := pipeline.GetElementByName("src")
if err != nil {
return pipeline
}

func bufferFromBytes(data []byte) *gst.Buffer {
buffer := gst.NewBufferAllocate(nil, uint(len(data)), nil)
mapped, ok := buffer.Map(gst.MapWrite)
if !ok {
panic("failed to map GStreamer buffer")
}
defer mapped.Unmap()

if _, err := mapped.Write(data); err != nil {
panic(err)
}

return app.SrcFromElement(appSrc)
return buffer
}

// Read from stdin until we get a newline.
Expand Down
77 changes: 46 additions & 31 deletions gstreamer-send-offer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import (
"flag"
"fmt"
"io"
"math"
"net/http"
"strconv"
"time"

"github.com/go-gst/go-gst/gst"
"github.com/go-gst/go-gst/gst/app"
"github.com/go-gst/go-gst/pkg/gst"
"github.com/go-gst/go-gst/pkg/gstapp"
"github.com/pion/webrtc/v4"
"github.com/pion/webrtc/v4/pkg/media"
)
Expand All @@ -30,7 +32,7 @@ func main() {
sdpChan := httpSDPServer(*port)

// Initialize GStreamer
gst.Init(nil)
gst.Init()

// Everything below is the Pion WebRTC API! Thanks for using it ❤️.

Expand Down Expand Up @@ -131,44 +133,57 @@ func pipelineForCodec(codecName string, tracks []*webrtc.TrackLocalStaticSample,
panic("Unhandled codec " + codecName) //nolint
}

pipeline, err := gst.NewPipelineFromString(pipelineStr)
element, err := gst.ParseLaunch(pipelineStr)
if err != nil {
panic(err)
}

if err = pipeline.SetState(gst.StatePlaying); err != nil {
panic(err)
pipeline, ok := element.(gst.Pipeline)
if !ok {
panic("GStreamer launch description did not produce a pipeline")
}

appSink, err := pipeline.GetElementByName("appsink")
if err != nil {
panic(err)
appSink, ok := pipeline.GetByName("appsink").(gstapp.AppSink)
if !ok {
panic("failed to find GStreamer appsink")
}

app.SinkFromElement(appSink).SetCallbacks(&app.SinkCallbacks{
NewSampleFunc: func(sink *app.Sink) gst.FlowReturn {
sample := sink.PullSample()
if sample == nil {
return gst.FlowEOS
}

buffer := sample.GetBuffer()
if buffer == nil {
return gst.FlowError
appSink.SetEmitSignals(true)

appSink.ConnectNewSample(func(sink gstapp.AppSink) gst.FlowReturn {
sample := sink.PullSample()
if sample == nil {
return gst.FlowEOS
}

buffer := sample.GetBuffer()
if buffer == nil {
return gst.FlowError
}

mapped, ok := buffer.Map(gst.MapRead)
if !ok {
return gst.FlowError
}
defer mapped.Unmap()
samples := mapped.Data()

var duration time.Duration
if d := buffer.Duration(); d <= math.MaxInt64 {
duration = time.Duration(d)
}

for _, t := range tracks {
if err := t.WriteSample(media.Sample{Data: samples, Duration: duration}); err != nil {
panic(err) //nolint
}
}

samples := buffer.Map(gst.MapRead).Bytes()
defer buffer.Unmap()

for _, t := range tracks {
if err := t.WriteSample(media.Sample{Data: samples, Duration: *buffer.Duration().AsDuration()}); err != nil {
panic(err) //nolint
}
}

return gst.FlowOK
},
return gst.FlowOK
})

if pipeline.SetState(gst.StatePlaying) == gst.StateChangeFailure {
panic("failed to start GStreamer pipeline")
}
}

// JSON encode + base64 a SessionDescription.
Expand Down
Loading
Loading