Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RSDK-8982, RSDK-9167, RSDK-8979] - Add SetStreamOptions to stream server #4530

Merged
merged 24 commits into from
Nov 26, 2024

Conversation

seanavery
Copy link
Member

@seanavery seanavery commented Nov 5, 2024

Description

RSDK-8982, RSDK-9167 RSDK-8979

This PR adds the SetStreamOptions endpoint to the stream server.

  • Validates the requests and performs a hot swap on the video source with a NewResizeVideoSource.
  • If Resolution is provided, we dispatch a Resize msg to the streamState handler.
    • If in Passthrough mode, the state transitions to gostream.
    • Prevents attempting to use passthrough during Increment and Decrement calls.
  • If Resolution is not provided, we dispatch a Reset msg to the streamState handler.
    • Attempts to restart passthrough if available.
  • In order to unify RTP Sequence Number handling between GoStream and Passthrough paths we now override the Sequence Number header field in the WriteRTP method.

Tests

  • CI Tests:
    • Request Validation ✅
    • GetImage Fake camera resize swap ✅
    • RTPPassthrough fake camera downgrade state transition ✅
    • Video tracks stay alive through resize transition ✅
    • Verifies prevention of RTPPassthrough when resized and peers Increment/Decrement ✅
    • Gostream back Passthrough reset state transition ✅
  • Manual tests (using NewStreamServiceClient script as seen below):
    • GetImage livestreams still work ✅
      • webcam ✅
      • fake cam ✅
      • viamrtsp ✅
    • Passthrough livestreams still work ✅
      • fake cam ✅
      • viamrtsp ✅
    • GetImage resize livestreams ✅
      • webcam ✅
      • fake cam ✅
      • viamrtsp ✅
    • Passthrough->GetImage resize livestream ✅
      • fake cam ✅
      • viamrtsp ✅
    • GetImage->Passthrough reset livestream ✅
      • fake cam ✅
      • viamrtsp ✅

Demos

  • viamrtsp passthrough -> resize getimage stream via SetStreamOptions
Screen.Recording.2024-11-12.at.2.05.18.PM.mov
  • passthrough <-> gostream getimage loop using resize and reset
passthrough_gostream_handoff.mov

TODO:

  • Test that video tracks survive SetSteamOptions swap.
  • Make sure we are safe wrt locking strategy.
  • Resize state transition from passthrough -> get_image.
  • Figure out how to test stream state transition for passthrough -> get_image.
  • Figure out how to prevent passthrough attempts when in resized mode.
  • Make sure resizes are working with viamrtsp camera source.
  • Fix flaky handoff between Gostream and Passthrough RTP sources.

Test Script

package main

import (
	"context"
	"time"

	streampb "go.viam.com/api/stream/v1"
	rgrpc "go.viam.com/rdk/grpc"
	rdklogger "go.viam.com/rdk/logging"
	"go.viam.com/utils/rpc"
)

func main() {
	logger := rdklogger.NewLogger("main")
	addr := "..."
	keyID := "..."
	apiKey := "..."
	camName := "..."
	ctx := context.Background()
	conn, err := rgrpc.Dial(ctx, addr, logger, rpc.WithEntityCredentials(
		keyID,
		rpc.Credentials{
			Type:    rpc.CredentialsTypeAPIKey,
			Payload: apiKey,
		}))
	if err != nil {
		logger.Error("Failed to dial: %v", err)
		return
	}
	livestreamClient := streampb.NewStreamServiceClient(conn)
	if livestreamClient == nil {
		logger.Error("Failed to create stream service client")
		return
	}
	opts, err := livestreamClient.GetStreamOptions(ctx, &streampb.GetStreamOptionsRequest{
		Name: camName,
	})
	if err != nil {
		logger.Error("Failed to get stream options: %v", err)
		return
	}
	logger.Info("Stream options: %v", opts)
	for {
		for _, resolution := range opts.Resolutions {
			logger.Info("Resizing to %v", resolution)
			_, err = livestreamClient.SetStreamOptions(ctx, &streampb.SetStreamOptionsRequest{
				Name:       camName,
				Resolution: resolution,
			})
			if err != nil {
				logger.Error("Failed to set stream options: %v", err)
				return
			}
			time.Sleep(5 * time.Second)
			logger.Info("Resetting to default")
			_, err = livestreamClient.SetStreamOptions(ctx, &streampb.SetStreamOptionsRequest{
				Name: camName,
			})
			if err != nil {
				logger.Error("Failed to set stream options: %v", err)
				return
			}
			time.Sleep(5 * time.Second)
		}
	}
}

@seanavery seanavery marked this pull request as draft November 5, 2024 21:12
@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label Nov 5, 2024
@seanavery seanavery changed the title RSDK-8982 - Add basic set stream options RSDK-8982 - Add SetStreamOptions to stream server Nov 5, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 6, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 7, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 7, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 7, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 8, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 8, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 8, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 11, 2024
@viambot viambot removed the safe to test This pull request is marked safe to test from a trusted zone label Nov 11, 2024
Comment on lines +766 to +767
t.Run("when in rtppassthrough mode and a resize occurs test downgrade path to gostream", func(t *testing.T) {
var startCount atomic.Int64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of your tests are time based and waiting for assertions, can you run with -race and -failfast in canon to verify that they're not flaky.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go test -timeout 30s -race -failfast -run ^TestSetStreamOptions$ go.viam.com/rdk/robot/web/stream
ok go.viam.com/rdk/robot/web/stream 3.255s


go test -timeout 30s -race -failfast -run ^TestStreamState$/^when_in_rtppassthrough_mode_and_a_resize_occurs_test_downgrade_path_to_gostream$ go.viam.com/rdk/robot/web/stream/state
ok go.viam.com/rdk/robot/web/stream/state 3.056s

robot/web/stream/server.go Outdated Show resolved Hide resolved
@@ -271,7 +302,7 @@ func (state *StreamState) tick() {
case state.streamSource == streamSourcePassthrough:
// no op if we are using passthrough & are healthy
state.logger.Debug("still healthy and using h264 passthrough")
case state.streamSource == streamSourceGoStream:
case state.streamSource == streamSourceGoStream && !state.isResized:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does a user do to hit this state after they've selected a resolution in the UI?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented the Reset path for this. Not exactly sure how to handle this from a UI perspective -- may need to update the wire-diagram in the scope doc to include a Reset button.

@seanavery seanavery changed the title RSDK-8982 - Add SetStreamOptions to stream server [RSDK-8982, RSDK-9167, RSDK-8979]- Add SetStreamOptions to stream server Nov 14, 2024
@seanavery seanavery changed the title [RSDK-8982, RSDK-9167, RSDK-8979]- Add SetStreamOptions to stream server [RSDK-8982, RSDK-9167, RSDK-8979] - Add SetStreamOptions to stream server Nov 14, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 14, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 14, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 14, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 15, 2024
Comment on lines 764 to 781

// validateSetStreamOptionsRequest validates the request to set the stream options.
func validateSetStreamOptionsRequest(req *streampb.SetStreamOptionsRequest) (int, error) {
if req.Name == "" {
return optionsCommandUnknown, errors.New("stream name is required in request")
}
if req.Resolution == nil {
return optionsCommandReset, nil
}
if req.Resolution.Width <= 0 || req.Resolution.Height <= 0 {
return optionsCommandUnknown,
fmt.Errorf(
"invalid resolution to resize stream %q: width (%d) and height (%d) must be greater than 0",
req.Name, req.Resolution.Width, req.Resolution.Height,
)
}
return optionsCommandResize, nil
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: put this above where it's used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, moved.

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 20, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 20, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Nov 21, 2024
@seanavery seanavery merged commit 3225263 into viamrobotics:main Nov 26, 2024
16 checks passed
randhid pushed a commit to randhid/rdk that referenced this pull request Nov 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
safe to test This pull request is marked safe to test from a trusted zone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants