fix: update WebRTC SDP handling and logging for offer/answer exchange
This commit is contained in:
parent
3d88b76c0d
commit
4419e31503
1 changed files with 24 additions and 20 deletions
|
@ -5,6 +5,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-gst/go-glib/glib"
|
"github.com/go-gst/go-glib/glib"
|
||||||
"github.com/go-gst/go-gst/gst"
|
"github.com/go-gst/go-gst/gst"
|
||||||
|
"github.com/go-gst/go-gst/gst/gstsdp"
|
||||||
|
"github.com/go-gst/go-gst/gst/gstwebrtc"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
@ -94,7 +96,7 @@ func (api *API) previewHandler(c echo.Context) error {
|
||||||
// on-negotiation-needed: Triggered when webrtcbin needs to create an offer or answer.
|
// on-negotiation-needed: Triggered when webrtcbin needs to create an offer or answer.
|
||||||
// In our case (server receiving an offer), this fires after the remote description is set.
|
// In our case (server receiving an offer), this fires after the remote description is set.
|
||||||
previewPipeline.webrtcbin.Connect("on-negotiation-needed", func(self *gst.Element) {
|
previewPipeline.webrtcbin.Connect("on-negotiation-needed", func(self *gst.Element) {
|
||||||
log.Info().Msg("🧠 Negotiation needed, creating answer...")
|
log.Info().Msg("Negotiation needed, creating answer")
|
||||||
|
|
||||||
// Create Answer
|
// Create Answer
|
||||||
promise, err := self.Emit("create-answer")
|
promise, err := self.Emit("create-answer")
|
||||||
|
@ -108,26 +110,26 @@ func (api *API) previewHandler(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the promise result (asynchronously)
|
// Handle the promise result (asynchronously)
|
||||||
promise.(*gst.Promise).Interrupt() // Interrupt any previous waits
|
promise.(*gst.Promise).Interrupt() // Interrupt any previous waits
|
||||||
promise.(*gst.Promise).Wait() // Wait for the answer to be created
|
promise.(*gst.Promise).Await(c.Request().Context()) // Wait for the answer to be created
|
||||||
reply := promise.(*gst.Promise).GetReply()
|
reply := promise.(*gst.Promise).GetReply()
|
||||||
if reply == nil {
|
if reply == nil {
|
||||||
log.Error().Msg("Promise reply for create-answer was nil")
|
log.Error().Msg("Promise reply for create-answer was nil")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
answerValue, ok := reply.GetValue("answer")
|
answerValue, err := reply.GetValue("answer")
|
||||||
if !ok || answerValue == nil {
|
if err != nil || answerValue == nil {
|
||||||
log.Error().Msg("Failed to get answer from promise reply")
|
log.Error().Msg("Failed to get answer from promise reply")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
answer, ok := answerValue.(*gst.WebRTCSessionDescription)
|
answer, ok := answerValue.(*gstwebrtc.SessionDescription)
|
||||||
if !ok || answer == nil {
|
if !ok || answer == nil {
|
||||||
log.Error().Msg("Answer value is not a WebRTCSessionDescription")
|
log.Error().Msg("Answer value is not a WebRTCSessionDescription")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Str("sdp", answer.GetSDP().String()).Msg("✅ Answer created")
|
log.Debug().Str("sdp", answer.SDP().String()).Msg("Answer created")
|
||||||
|
|
||||||
// Set Local Description
|
// Set Local Description
|
||||||
promise, err = self.Emit("set-local-description", answer)
|
promise, err = self.Emit("set-local-description", answer)
|
||||||
|
@ -141,13 +143,13 @@ func (api *API) previewHandler(c echo.Context) error {
|
||||||
}
|
}
|
||||||
promise.(*gst.Promise).Interrupt() // Interrupt any previous waits
|
promise.(*gst.Promise).Interrupt() // Interrupt any previous waits
|
||||||
|
|
||||||
log.Info().Msg("➡️ Set local description (answer)")
|
log.Info().Msg("Set local description (answer)")
|
||||||
|
|
||||||
// Send Answer back to the client
|
// Send Answer back to the client
|
||||||
log.Info().Msg("📨 Sending SDP answer back to browser")
|
log.Info().Msg("Sending SDP answer back to browser")
|
||||||
response := SignalMessage{
|
response := SignalMessage{
|
||||||
Type: "answer",
|
Type: "answer",
|
||||||
SDP: answer.GetSDP().String(),
|
SDP: answer.SDP().String(),
|
||||||
}
|
}
|
||||||
msg, err := json.Marshal(response)
|
msg, err := json.Marshal(response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -185,7 +187,7 @@ func (api *API) previewHandler(c echo.Context) error {
|
||||||
|
|
||||||
// --- WebSocket Message Loop ---
|
// --- WebSocket Message Loop ---
|
||||||
for {
|
for {
|
||||||
messageType, message, err := conn.ReadMessage()
|
_, message, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("WebSocket read error")
|
log.Error().Err(err).Msg("WebSocket read error")
|
||||||
break
|
break
|
||||||
|
@ -199,20 +201,21 @@ func (api *API) previewHandler(c echo.Context) error {
|
||||||
|
|
||||||
switch signal.Type {
|
switch signal.Type {
|
||||||
case "offer":
|
case "offer":
|
||||||
log.Info().Msg("📥 Received SDP offer from browser")
|
log.Info().Msg("Received SDP offer from browser")
|
||||||
log.Debug().Str("sdp", signal.SDP).Msg("Offer SDP")
|
//log.Debug().Str("sdp", signal.SDP).Msg("Offer SDP")
|
||||||
|
|
||||||
// Create WebRTCSessionDescription for the offer
|
// Create WebRTCSessionDescription for the offer
|
||||||
offerDesc, err := gst.NewWebRTCSessionDescription(gst.WebRTCSDPTypeOffer, gst.NewSDPMessageFromString(signal.SDP))
|
offerMsg, err := gstsdp.ParseSDPMessage(signal.SDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Failed to create offer description from SDP")
|
log.Error().Err(err).Msg("Failed to parse SDP message")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
offerDesc := gstwebrtc.NewSessionDescription(gstwebrtc.SDP_TYPE_OFFER, offerMsg)
|
||||||
|
|
||||||
|
promise := gst.NewPromise()
|
||||||
// Set Remote Description
|
// Set Remote Description
|
||||||
// This will trigger on-negotiation-needed if successful and state allows
|
// This will trigger on-negotiation-needed if successful and state allows
|
||||||
promise, err := previewPipeline.webrtcbin.Emit("set-remote-description", offerDesc)
|
if _, err := previewPipeline.webrtcbin.Emit("set-remote-description", offerDesc, promise); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("Failed to emit set-remote-description")
|
log.Error().Err(err).Msg("Failed to emit set-remote-description")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -220,9 +223,10 @@ func (api *API) previewHandler(c echo.Context) error {
|
||||||
log.Error().Msg("Emit set-remote-description returned nil promise")
|
log.Error().Msg("Emit set-remote-description returned nil promise")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
promise.(*gst.Promise).Interrupt() // Interrupt previous waits if any
|
//promise.Interrupt() // Interrupt previous waits if any
|
||||||
|
promise.Await(c.Request().Context()) // Wait for the remote description to be set
|
||||||
|
|
||||||
log.Info().Msg("➡️ Set remote description (offer)")
|
log.Info().Msg("Set remote description (offer)")
|
||||||
// Answer creation is now handled in on-negotiation-needed
|
// Answer creation is now handled in on-negotiation-needed
|
||||||
|
|
||||||
case "ice":
|
case "ice":
|
||||||
|
@ -230,7 +234,7 @@ func (api *API) previewHandler(c echo.Context) error {
|
||||||
log.Warn().Msg("Received ICE signal with nil ICE field")
|
log.Warn().Msg("Received ICE signal with nil ICE field")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Debug().Str("candidate", signal.ICE.Candidate).Uint16("mlineindex", signal.ICE.SDPMLineIndex).Str("sdpMid", signal.ICE.SDPMid).Msg("➕ Received ICE candidate from browser")
|
log.Debug().Str("candidate", signal.ICE.Candidate).Uint16("mlineindex", signal.ICE.SDPMLineIndex).Str("sdpMid", signal.ICE.SDPMid).Msg("Received ICE candidate from browser")
|
||||||
|
|
||||||
// Add ICE Candidate
|
// Add ICE Candidate
|
||||||
// Note: The signal takes mlineindex (uint) and candidate (string).
|
// Note: The signal takes mlineindex (uint) and candidate (string).
|
||||||
|
|
Loading…
Add table
Reference in a new issue