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

[DATA-751] Add RTSP model #1653

Merged
merged 36 commits into from
Feb 2, 2023
Merged

Conversation

bhaney
Copy link
Member

@bhaney bhaney commented Dec 8, 2022

  • Uses gortsplib to create an RTSP camera client in RDK

    • model name is rtsp
    • has one required field, rtsp_address
    • ONLY supports H264 MJPEG streams currently!
    • tries to reconnect to server every 5 seconds if connection is lost
  • Uses a fork of simple-rtsp-server to do testing (original package hides server functions in an internal package)

out_rtsp

@bhaney bhaney added the safe to test This pull request is marked safe to test from a trusted zone label Dec 8, 2022
@viambot viambot removed the safe to test This pull request is marked safe to test from a trusted zone label Dec 8, 2022
go.mod Outdated
github.com/aws/aws-sdk-go v1.41.14 // indirect
github.com/bamiaux/iobit v0.0.0-20170418073505-498159a04883 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bhaney/rtsp-simple-server v0.0.0-20221207231808-7a1402c0b840 // indirect
Copy link
Member Author

Choose a reason for hiding this comment

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

This is literally just used for the test. Needed to fork the repo because it did not expose the server as a package, only as a binary.

@bhaney bhaney added the safe to test This pull request is marked safe to test from a trusted zone label Dec 8, 2022
@viambot viambot removed the safe to test This pull request is marked safe to test from a trusted zone label Dec 8, 2022
@bhaney bhaney added the safe to test This pull request is marked safe to test from a trusted zone label Dec 8, 2022
@viambot viambot removed the safe to test This pull request is marked safe to test from a trusted zone label Dec 8, 2022
@bhaney bhaney added the safe to test This pull request is marked safe to test from a trusted zone label Dec 8, 2022
components/camera/rtsp/rtsp.go Outdated Show resolved Hide resolved
@bhaney bhaney requested a review from tessavitabile December 9, 2022 20:05
@tessavitabile
Copy link
Contributor

Thanks for sharing this! I hadn't seen an example of using a codec in go before.

@tessavitabile tessavitabile removed their request for review December 9, 2022 21:13
// #include <libswscale/swscale.h>
import "C"

import (
Copy link
Contributor

Choose a reason for hiding this comment

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

Gotta still look through this but I'm curious why we are using this over mediadevices h264 codec

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought it was only encoding in mediadevices? Let me check again...

Copy link
Member Author

Choose a reason for hiding this comment

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

from what I can tell, https://github.com/pion/mediadevices/blob/master/pkg/codec/x264/x264.go is just the encoder, but this is h264 -> image.RGBA decoding.

Copy link
Contributor

Choose a reason for hiding this comment

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

ah. can we not use the x264 c code though so that we have just one dependency?

Copy link
Member Author

@bhaney bhaney Dec 13, 2022

Choose a reason for hiding this comment

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

Rather than changing the library to just the x264 one, what if I changed this PR to allow any codec available from libavcodec (which is from ffmpeg).It will make it more general for many different formats (Prob could have just done that from the beginning)

the available ones are

  • H264
  • HEVC (i.e. H265)
  • MPEG4
  • MPEG2video
  • Theora
  • VC-1 (i.e. SMPTE 421)
  • RAW

Copy link
Contributor

Choose a reason for hiding this comment

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

It almost seems better as a modular resource

Copy link
Member

@Otterverse Otterverse Dec 13, 2022

Choose a reason for hiding this comment

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

So the footprint is pretty significant. Installing JUST those three libraries on a bare-bones debian system brings in 380MB of required other packages/files. Adding them to our AppImage doubles the compressed size from 64MB to 128MB.

As to the two followup questions... I think supporting all the codecs would make a LOT of sense rather than just h264.

Lastly, yeah, due to the size... I think this would be a good candidate as a module. Or we acquire enough new things capable of making use of libavcodec that it becomes worthwhile to put it in the main RDK.

OH, and yeah, hoping that module stuff is done any day now. I'm hoping to be ready for final reviews later today, but i've been saying that since thursday.

Copy link
Member Author

@bhaney bhaney Dec 13, 2022

Choose a reason for hiding this comment

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

Wait, but since these libraries are already included in ffmpeg, which we already have in RDK, would it still add to the overall size of RDK? I don't think this would require adding anything new to RDK.

Or does explictly using cgo (rather than just pointing to the ffmpeg binary like we do in the ffmpeg model) mean having to copy those libraries and repeat them?

This PR passed CI without me having to download/add anything to the canon image.

Copy link
Member Author

Choose a reason for hiding this comment

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

What if we removed the ffmpeg model, and just included these libraries. Would it decrease the size of RDK? Not that we can remove ffmpeg... but if people are only using ffmpeg for the RTSP capability, we maybe could...

Copy link
Member

Choose a reason for hiding this comment

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

We don't include ffmpeg in the actual distribution/packaging, just libx264 and libopus. As far as I know, the ffmpeg camera model only calls an external binary. It never actually links to shared cgo code/libraries. But because we have that model, ffmpeg is needed for testing, and so is in the canon docker images.

The actual list of what gets bundled as true dependencies is here: https://github.com/viamrobotics/rdk/blob/main/etc/packaging/appimages/viam-server-x86_64.yml#L36-L41 (though those few packages pull in a couple more of their own dependencies.)

@bhaney
Copy link
Member Author

bhaney commented Dec 13, 2022

Are they available yet (modular resources?) Is there one I could use as a template?

I can also just delay merging this model into RDK for another time

@edaniels
Copy link
Contributor

edaniels commented Jan 4, 2023

Okay following up on this and understanding a bit more about what is actually needed, we want h264 decoding. We can't just pull in libavcodec due to the conversation we had. Additionally, although we have modular resources, we want this to just work on any appimage install and without a module registry, we aren't quite there yet.

Instead, we need to find a way to lightly include h264 decoding. There does exist https://github.com/ausocean/h264decode but it looks pretty WIP so far. Alternatively, if that proves too cumbersome, mp4 decoding can be found here https://pkg.go.dev/github.com/jfbus/mp4. I would try some quick tests to see if either works more easily and go with that one since ultimately RTSP should provide either h264 or mp4 commonly.

@bhaney
Copy link
Member Author

bhaney commented Jan 4, 2023

Okay following up on this and understanding a bit more about what is actually needed, we want h264 decoding. We can't just pull in libavcodec due to the conversation we had. Additionally, although we have modular resources, we want this to just work on any appimage install and without a module registry, we aren't quite there yet.

Instead, we need to find a way to lightly include h264 decoding. There does exist https://github.com/ausocean/h264decode but it looks pretty WIP so far. Alternatively, if that proves too cumbersome, mp4 decoding can be found here https://pkg.go.dev/github.com/jfbus/mp4. I would try some quick tests to see if either works more easily and go with that one since ultimately RTSP should provide either h264 or mp4 commonly.

This sounds good - I'll work on trying to include both mp4 and h264 decoding (without using avcodec). Talked with Eliot and will hold off on creating a modular resource of RTSP for now

@edaniels
Copy link
Contributor

edaniels commented Jan 4, 2023

To clarify, I'd pick one of the decodings, but sounds good.

@bhaney
Copy link
Member Author

bhaney commented Jan 5, 2023

So, libx264 does not have a decoder. It is only an encoder. Everywhere I look, the recommendation for decoding x264 is "just use ffmpeg", which we've already decided is a no-go. I looked at using MP4, but this would require not using https://github.com/aler9/gortsplib, because it only support MP4Audio, not full MP4 currently. Since the whole RTSP model is built on aler9/gortsplib, one thing I could do is try to create a PR that adds full MP4 support to that library.

I think my course of action right now will be to use/modify https://github.com/ausocean/h264decode/ which is trying to natively decode H264 in golang.

@edaniels
Copy link
Contributor

edaniels commented Jan 5, 2023

@bhaney
Copy link
Member Author

bhaney commented Jan 5, 2023

Did you check out https://pkg.go.dev/github.com/jfbus/mp4#section-readme?

It's the RTSP client that doesn't support MP4. The problem is the conversion from RTP -> MP4, not decoding the MP4 -> image.Image. The Go RTSP client supports MPEG4Audio only right now.

So an option would be to add the RTP->MP4 functions to https://github.com/aler9/gortsplib/, but it would need to be a PR on that repo.

@edaniels
Copy link
Contributor

edaniels commented Jan 5, 2023

We can also full fork (non go mod replace) it if it's an easy path while waiting on a PR.

@bhaney
Copy link
Member Author

bhaney commented Jan 5, 2023

We can also full fork (non go mod replace) it if it's an easy path while waiting on a PR.

OK - I think I was confused, I thought MP4 and H264 were different things. James helpfully explained that MP4 is a container for video, and it can be used to contain the encoded video in H264. So I looked more closely at the mp4 package you sent me, and it looks like it doesn't decode the data? It just stores the packets... it says in the comments "Status: No decoded".

https://github.com/jfbus/mp4/blob/master/mdat.go

It defines the "Box" to store the data in, but it doesn't decode the data.

@edaniels
Copy link
Contributor

edaniels commented Jan 5, 2023

So is the RTSP we're working with sending only h264? is there mjpeg?

@bhaney
Copy link
Member Author

bhaney commented Jan 5, 2023

So is the RTSP we're working with sending only h264? is there mjpeg?

I wrote it for only h264 because I thought that would be the most common encoding, but mjpeg is supported!
If we can use M-JPEG I have this done in a week! Go comes with a native JPEG encoder/decoder. I can rewrite this for only mjpeg

@bhaney bhaney force-pushed the DATA-751-add-rtsp-model branch from 143e429 to 6276a45 Compare January 19, 2023 19:55
@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 Jan 19, 2023
@bhaney bhaney force-pushed the DATA-751-add-rtsp-model branch from b21186e to 363e0df Compare February 2, 2023 00:21
@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 Feb 2, 2023
@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 Feb 2, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2023

Code Coverage

Note: merge base coverage results not available, comparing against closest ac0a9c0~1=(9bce7dc) instead

Package Line Rate Delta Health
go.viam.com/rdk/components/arm 56% 0.00%
go.viam.com/rdk/components/arm/universalrobots 41% 0.00%
go.viam.com/rdk/components/arm/xarm 2% 0.00%
go.viam.com/rdk/components/arm/yahboom 7% 0.00%
go.viam.com/rdk/components/audioinput 55% +0.34%
go.viam.com/rdk/components/base 63% 0.00%
go.viam.com/rdk/components/base/agilex 62% 0.00%
go.viam.com/rdk/components/base/boat 41% 0.00%
go.viam.com/rdk/components/base/wheeled 76% 0.00%
go.viam.com/rdk/components/board 66% 0.00%
go.viam.com/rdk/components/board/arduino 10% 0.00%
go.viam.com/rdk/components/board/commonsysfs 48% 0.00%
go.viam.com/rdk/components/board/fake 38% 0.00%
go.viam.com/rdk/components/board/numato 19% 0.00%
go.viam.com/rdk/components/board/pi 50% 0.00%
go.viam.com/rdk/components/camera 65% 0.00%
go.viam.com/rdk/components/camera/align 64% 0.00%
go.viam.com/rdk/components/camera/fake 64% 0.00%
go.viam.com/rdk/components/camera/ffmpeg 77% 0.00%
go.viam.com/rdk/components/camera/rtsp 61% N/A
go.viam.com/rdk/components/camera/transformpipeline 79% 0.00%
go.viam.com/rdk/components/camera/videosource 45% -0.58%
go.viam.com/rdk/components/encoder 4% 0.00%
go.viam.com/rdk/components/encoder/fake 76% 0.00%
go.viam.com/rdk/components/gantry 60% 0.00%
go.viam.com/rdk/components/gantry/multiaxis 84% 0.00%
go.viam.com/rdk/components/gantry/oneaxis 86% 0.00%
go.viam.com/rdk/components/generic 83% 0.00%
go.viam.com/rdk/components/gripper 68% 0.00%
go.viam.com/rdk/components/input 87% 0.00%
go.viam.com/rdk/components/input/gpio 84% 0.00%
go.viam.com/rdk/components/motor 77% 0.00%
go.viam.com/rdk/components/motor/dimensionengineering 63% 0.00%
go.viam.com/rdk/components/motor/dmc4000 69% 0.00%
go.viam.com/rdk/components/motor/fake 57% 0.00%
go.viam.com/rdk/components/motor/gpio 64% 0.00%
go.viam.com/rdk/components/motor/gpiostepper 57% +0.59%
go.viam.com/rdk/components/motor/tmcstepper 62% 0.00%
go.viam.com/rdk/components/movementsensor 75% 0.00%
go.viam.com/rdk/components/movementsensor/cameramono 46% 0.00%
go.viam.com/rdk/components/movementsensor/gpsnmea 36% 0.00%
go.viam.com/rdk/components/movementsensor/gpsrtk 28% 0.00%
go.viam.com/rdk/components/posetracker 86% 0.00%
go.viam.com/rdk/components/sensor 86% 0.00%
go.viam.com/rdk/components/sensor/ultrasonic 26% 0.00%
go.viam.com/rdk/components/servo 68% 0.00%
go.viam.com/rdk/components/servo/gpio 71% 0.00%
go.viam.com/rdk/config 75% 0.00%
go.viam.com/rdk/control 57% 0.00%
go.viam.com/rdk/data 79% 0.00%
go.viam.com/rdk/examples/customresources/demos/complexmodule 0% 0.00%
go.viam.com/rdk/examples/customresources/demos/remoteserver 0% 0.00%
go.viam.com/rdk/grpc 25% 0.00%
go.viam.com/rdk/ml 67% 0.00%
go.viam.com/rdk/ml/inference 70% 0.00%
go.viam.com/rdk/module 64% 0.00%
go.viam.com/rdk/module/modmanager 79% 0.00%
go.viam.com/rdk/motionplan 69% 0.00%
go.viam.com/rdk/operation 82% 0.00%
go.viam.com/rdk/pointcloud 73% +0.08%
go.viam.com/rdk/protoutils 59% 0.00%
go.viam.com/rdk/referenceframe 72% 0.00%
go.viam.com/rdk/registry 89% 0.00%
go.viam.com/rdk/resource 84% 0.00%
go.viam.com/rdk/rimage 78% 0.00%
go.viam.com/rdk/rimage/depthadapter 94% 0.00%
go.viam.com/rdk/rimage/transform 75% 0.00%
go.viam.com/rdk/rimage/transform/cmd/extrinsic_calibration 67% 0.00%
go.viam.com/rdk/robot 85% 0.00%
go.viam.com/rdk/robot/client 81% 0.00%
go.viam.com/rdk/robot/framesystem 65% 0.00%
go.viam.com/rdk/robot/impl 80% 0.00%
go.viam.com/rdk/robot/server 55% -0.59%
go.viam.com/rdk/robot/web 61% 0.00%
go.viam.com/rdk/robot/web/stream 87% 0.00%
go.viam.com/rdk/services/armremotecontrol 71% 0.00%
go.viam.com/rdk/services/armremotecontrol/builtin 52% 0.00%
go.viam.com/rdk/services/baseremotecontrol 71% 0.00%
go.viam.com/rdk/services/baseremotecontrol/builtin 79% 0.00%
go.viam.com/rdk/services/datamanager 79% 0.00%
go.viam.com/rdk/services/datamanager/builtin 78% 0.00%
go.viam.com/rdk/services/datamanager/datacapture 70% 0.00%
go.viam.com/rdk/services/datamanager/datasync 0% 0.00%
go.viam.com/rdk/services/motion 63% 0.00%
go.viam.com/rdk/services/motion/builtin 88% 0.00%
go.viam.com/rdk/services/navigation 53% 0.00%
go.viam.com/rdk/services/sensors 77% 0.00%
go.viam.com/rdk/services/sensors/builtin 97% 0.00%
go.viam.com/rdk/services/shell 14% 0.00%
go.viam.com/rdk/services/slam 85% 0.00%
go.viam.com/rdk/services/slam/builtin 70% 0.00%
go.viam.com/rdk/services/vision 80% 0.00%
go.viam.com/rdk/services/vision/builtin 74% 0.00%
go.viam.com/rdk/session 97% 0.00%
go.viam.com/rdk/spatialmath 84% 0.00%
go.viam.com/rdk/subtype 92% 0.00%
go.viam.com/rdk/utils 72% 0.00%
go.viam.com/rdk/vision 26% 0.00%
go.viam.com/rdk/vision/chess 80% 0.00%
go.viam.com/rdk/vision/delaunay 87% 0.00%
go.viam.com/rdk/vision/keypoints 92% 0.00%
go.viam.com/rdk/vision/objectdetection 82% 0.00%
go.viam.com/rdk/vision/odometry 60% 0.00%
go.viam.com/rdk/vision/odometry/cmd 0% 0.00%
go.viam.com/rdk/vision/segmentation 49% 0.00%
go.viam.com/rdk/web/server 25% 0.00%
Summary 65% (21679 / 33117) -0.02%

@bhaney bhaney merged commit 292f06a into viamrobotics:main Feb 2, 2023
Comment on lines +226 to +232
case <-cancelCtx.Done():
return nil, nil, cancelCtx.Err()
case <-ctx.Done():
return nil, nil, ctx.Err()
default:
<-rtspCam.gotFirstFrame // block until you get the first frame
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah so this would've had to be (no default)

		select {
 		case <-cancelCtx.Done():
 			return nil, nil, cancelCtx.Err()
 		case <-ctx.Done():
 			return nil, nil, ctx.Err()
 		case <-rtspCam.gotFirstFrame: // block until you get the first frame
 		}

to get rid of the issue. That way the select could block until one of those conditions are true. As of now it could still not see a Done(), fall into the default case, then block indefinitely on <-rtspCam.gotFirstFrame if the goroutine's parent function tried to kill it before sending a frame. Not a big deal though. Just wanted to call it out in the very unlikely chance this gets triggered.

Copy link
Contributor

Choose a reason for hiding this comment

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

we should probably fix this. unlikely is possible

Copy link
Member Author

@bhaney bhaney Feb 2, 2023

Choose a reason for hiding this comment

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

I can change it to a (Wait for Chan or 10s) and then continue after 10s to look for the Done() again

Copy link
Member Author

Choose a reason for hiding this comment

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

bug fix incoming

Copy link
Member Author

Choose a reason for hiding this comment

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

#1653 (comment)

Eric mentioned that the block you propose has its own problems, so I need to create a way to always be listening on the contexts. Essentially the easiest way will actually just putting in the select statement twice - once without the blocking gotFrame, and one with.

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 viam-org Is part of the viamrobotics organization.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants