Live Streaming over USB on Ubuntu and Linux, NVIDIA Jetson

Detailed instructions are here:

Please post again if you still have questions. We are happy to help.

update Sept 22, 2020

This is in response to your DM about building on x86, Ubuntu 18.04. First, thank you for trying the build and asking your question. It is better if you questions in the public forum as we can leverage the wisdom of the community. Other people are running the software on x86 with Ubuntu 18.04 and ROS. They may be able to help as well.

When you first log into the site, the top video is on building for x86, Ubuntu 20.04. I’ll update the document to make this clearer.

Although the default branch from GitHub is now theta_uvc, make sure that you are using theta_uvc branch. Video shows example of using git branch -a. You need to have the development libraries installed for libusb and libjpeg.

Post the output of cmake .. as well as your build error.

Is it possible that you need to install

libusb-1.0-0-dev - userspace USB programming library development files

Maybe this? libjpeg-dev

If you are building the sample app, you need the gstreamer development libraries installed.

Feel free to respond with more questions if you have problems.

I’m trying to follow this guide to run a Theta V on NVIDIA Xavier. The build works fine, but the sample code doesn’t detect the theta (just says “THETA not found!”). One thing I noticed is that in lsusb, my device shows up as 05ca:0368, which is different than the guides.

I tried changing the product id in thetauvc.c to match, but that still didn’t work. Any advice?

Do you have the THETA V in live streaming mode? the word “LIVE” needs to be shown in blue on the body of the camera. If the camera is in LIVE mode, please check the USB cable.

Are you running the sample theta app?

that error message usually only shows up when it is a camera to connection problem (like USB cable is a little wonky) or the camera is not in live streaming mode.

Also, be aware that for Xavier, the gstreamer plug-in selection isn’t working well, so you need to specify the decoder.

“decodebin ! autovideosink sync=false”
“nvv4l2decoder ! nv3dsink sync=false”

However, your problem is likely the cable or the camera mode.

Please post again.

This is with a THETA V.

Post a screenshot of lsusb and the output of your camera firmware version and info.

This is the information on my device.

$ ptpcam --info

Camera information
  manufacturer: Ricoh Company, Ltd.
  serial number: '00105377'
  device version: 3.40.1
  extension ID: 0x00000006
  extension description: (null)
  extension version: 0x006e

this is the lsusb when it is in still image mode:

this is the lsusb when it is live streaming mode

The program looks for 2712. So, it’s a problem that you have 0368.

I don’t know it would show 0368. I’m hoping a wonky cable or a firmware upgrade might help.


Yes, the camera was not in Live streaming mode, thanks for that tip! I got that working then used the USB interface to keep the camera alive and in Live streaming mode. Next I will modify the libtheta-uvc-sample application to send the h264 stream to a remote computer and then use something like on that remote machine to bring the data into ROS.

My initial thought was to use udpsink, but I wasn’t able to get a pipeline working on my Xavier. I tried an RTSP server which worked momentarily, but was not stable. I am not a gstreamer expert, so I’m probably configuring something wrong there… Have you done anything like this or know someone who has? Any advice would be much appreciated!




Great news about the progress.

Regarding RTSP or a way to get the stream to another server, I believe other people are working on the same problem, but I do not have an answer at the moment. For example, @Yu_You was asking about this. I believe he moved from the RTSP plug-in to the USB cable with libuvc (the technique in this thread). I do not know if he was then able to use something like gst-rtsp-server to get the stream to another computer.

@Hugues is quick far along using the Janus Gateway to get rtp output on IP networks. I don’t know how busy he is, but if your firm is working on a big project, it might be worthwhile to consider trying to hire him as a consultant. He’s using his FOX SEWER ROVER in production and he’s been freely contributing his knowledge to this group.

Another interesting transmission project is the Lockheed Martin Amelia Drone by @Jake_Kenin, @sjm7783 and others.

There is more information on their project here.

As some of them were in undergraduate school before COVID-19 shut down their project, it might be possible to hire some of the team members as interns.

I’m trying to connect people in parallel to sharing whatever I know because there has been a surge of activity around live streaming and USB camera control, likely due to a maturation of technologies and the increase in demand for remote surveillance and analysis.

There seems like many people are working on foundational knowledge such as transmitting data to a remote server running gscam.

I don’t have ros installed.

Are you saying that you can’t get gscam working on the same computer that the THETA is plugged into with a USB cable.? The documentation examples are using /dev/video*. What is the error message?

Are you using ROS Noetic (Ubuntu 20.04) or ROS Melodic (Ubuntu 18.04) or something else? I’m likely gong to install ROS at some point in the future and test basic camera functionality.


Thanks for the information. After trying various approaches, I’ve settled on a setup that I’m happy with. I’ll document it here for posterity.

Firstly, I modified the pipe_proc line in the libuvc-theta-sample program to put the stream into a udpsink:

pipe_proc = " rtph264pay name=pay0 pt=96 ! udpsink host= port=5000 sync=false ";

I then run the test-launch program from the gst-rtsp-server server project with the following pipeline:

./test-launch "( udpsrc port=5000 ! application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264 ! rtph264depay ! h264parse ! rtph264pay name=pay0 pt=96 )"

I tried various other methods of connecting these two gstreamer processes, including shmsink/shmsrc, but ultimately this one worked the best. At some point in the future I may combine the gst_view and test-launch functionality into one executable and do away with some of the needless complexity.

Finally, I used gscam to bring the stream into ROS with the following command:

GSCAM_CONFIG="rtspsrc location=rtspt:// latency=400 drop-on-latency=true ! application/x-rtp, encoding-name=H264 ! rtph264depay ! decodebin ! queue ! videoconvert"  roslaunch gscam_nodelet.launch

Note the “rtspt” protocol, it is not a typo. It forces the RTSP connection to go over TCP. When I used UDP there were too many artifacts and corrupted frames

I actually run this last command on a separate machine, just because of my particular network topology. It could be run on the same machine. In fact, it might be necessary to do so because gscam doesn’t seem to handle udp streams well. I also tried using OpenCV VideoCapture to get the data into ros, but that had a couple issues. There are two APIs for VideoCapture that seemed appropriate: Gstreamer and FFmpeg. It turns out that the OpenCV version packaged with ROS is not built with Gstreamer support, so you would have to build OpenCV yourself to use it. For FFmpeg, the version of OpenCV packaged with ROS melodic is 3.2, which is missing a fairly critical change here: that allows you to set FFmpeg capture options in an environment variable. I got both of these working by upgrading OpenCV to version 3.4.9 and building from source, but Gstreamer had a low framerate (~5fps) and FFmpeg had a lot of corruption and dropped frames (maybe it was stuck using UDP?). So, I decided to stick with gscam for now.

The latency value of 400 worked for me, but should be tuned depending on your network.

Hope this helps you or someone else wanting to use this camera in ros. So far it looks great and should be perfect for my application. The only negative for me is that I can’t control the power state and streaming state programmatically, unless I missed something in the USB API section. For now I’ve disabled sleep so I only have to turn it on once my robot is up and turn it off when done.


Love it!

Thanks so much for sharing this.

See this video, I think is what you want.

More information is here is the camera section.

There is sample code for Jetson Nano as well in that document.

If this is what you are looking for, feel free to ask more questions.

Note that I haven’t tested isolating individual USB ports on the Jetson. I don’t know if it is possible to just reset the USB port that the THETA is attached to. On the Raspberry Pi, all the USB ports are reset when the camera is restarted. If you have other devices attached the USB port of the Xavier that you need, please adjust accordingly. This is not an approved part of the API. If this is something you need for production, we’ll try and test it more.

If your application can live with sleep and wake, it is better as it is part of the official API.

The API supports switching from image to live streaming and to video file.

Note if you need to save video to file, there is a third parameter you must set. It’s documented in on the guide and also on the USB thread of this forum. I think it is something like adding ,0,0,1 to the
end of the hex value for video to file. If you have problems, we can check it.

1 Like

I have live streaming working on Mac and everything is great - but I am trying it on ubuntu and its not working. At all. It doesn’t recognize that the camera is present.

Is there a way to make the Ricoh theta v work on ubuntu?

This was an old question that I merged with this topic to help people using the search feature of this forum. yes, it’s possible. Please review the topic at the topic and ask more question if you have any problems. Hope you’re still using the camera. :slight_smile:

Hi I made a few small modifications to a github entry to transform equirectangular images/frames to perspective images. This can really help when using existing deep learning models or when creating new models based on regular (non 360 camera footage. The Github link can be found here.

Original Images

Transformed image

I will try some of this out on some Mobilenet V2 models later.

Community Ask: Functionalize this in a way that is fast and uses Nvidea GPU on Jetson or Xavier AGX.

1 Like

Nice. This is great. Thanks for sharing it.

I tested it with Python3 on x86 using the standard opencv shipped with Ubuntu 20.04 and Z1 jpeg images. Works great.

sudo apt install python3-opencv

The only sad thing I noticed is that all the test pictures in my camera are of me sitting in front of a computer. :frowning:

Have you tried it on a video stream without applying Mobilenet v2 analysis? I’m wondering how fast the Equirec2Perspec can handle the frames.

I’m still trying to learn more about this new frontier (for me) of GPU acceleration on the Jetson.

Just to clarify the challenge you’re proposing, do you mean to test OpenCV on NVIDIA Jetson with CUDA acceleration?

As my knowledge is weak, I do not know if I need to modify the Python code to load the CV portions into the GPU or if compiling OpenCV with CUDA support somehow automatically does this for me.

Most of the documentation I can find just focuses on compiling CUDA support into OpenCV

I’ve compiled OpenCV from source with CUDA support on the Nvidia Jetson, but I’m not sure if I need to do stuff like cv.cuda…

If you have Equirec2Perspec working on a stream, we can also just test it and see what the latency is. If it’s too slow, then we can try and modify the code with the cv.cuda names.

Thanks to this topic, I was able to run gst_viewer on my Ubuntu laptop and view streaming video of THETA V.

Now,I have a question about THETA video streaming over USB.
This may seem like an odd question, but I would like to ask someone to give me an advice if possible.

I’m trying to view streaming video on ffplay with gst_loopback,v4l2loopback and ffmpeg as well as gst_viewer.
You might think "Why is this guy trying to use ffplay even though gst_viewer is available?”. I know, but it’ll be a long story.So I’ll skip it now.

Anyway, I connected THETA and ran gst_loopback and ran the following command.
("/dev/video1" is a device file created by v4l2loopback.)

ffmpeg -i /dev/video1 -f matroska - | ffplay -

However, as shown in the screenshot, bit rate indicates N/A and no streaming image was displayed.

I changed /dev/video1 to /dev/video0 (the web-camera built into the laptop) and ran the same command and confirmed that the video from the web-camera was correctly displayed.
To further confirm, I ran the following command and saved a 10 second video.

ffmpeg -i /dev/video1 -f matroska output.mp4

The length of the output.mp4 was 0 seconds and only one image was stored.

gst_viewer is working fine, so I think I’m missing some settings or making a mistake on the v4l2loopback, ffmpeg side, but I couldn’t find a good solution.
Does anyone have an advice on this?

camera:THETA V
OS:Ubuntu 18.04 LTS 64bit

1 Like

I do not have a solution, but I can replicate the problem. I will keep trying.

I have the same problem that you do.

The only thing I got working is that ffplay works with THETA on /dev/video0

$ ffplay -f v4l2 /dev/video0
ffplay version 3.4.8-0ubuntu0.2 Copyright (c) 2003-2020 the FFmpeg developers
  built with gcc 7 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04)
  configuration: --prefix=/usr --extra-version=0ubuntu0.2 --toolchain=hardened --libdir=/usr/lib/aarch64-linux-gnu --incdir=/usr/include/aarch64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100

1 Like

I put it into a loop to get the frames from RICOH THETA Z1 to see if it was using the GPU and I don’t think it is.


This screen grab is coming over an X forwarding session to another computer, so it may be faster on a monitor plugged into the Jetson. If I increase the window size, the latency gets worse. The interesting challenge is to get cv2.cuda.remap working, which I don’t have working.


import cv2
import os
import Equirec2Perspec2 as E2P

print(f"OpenCV version {cv2.__version__}")
cap = cv2.VideoCapture(0)

# Check if the webcam is opened correctly
if not cap.isOpened():
    raise IOError("Cannot open webcam")

while True:
    ret, frame =
    equ = E2P.Equirectangular(frame)
    frame = equ.GetPerspective(120, 180, -15, 400, 400)
    cv2.imshow('Input', frame)

    c = cv2.waitKey(1)
    if c == 27:



class Equirectangular:
    def __init__(self, img):
        self._img = img
        [self._height, self._width, _] = img.shape

There’s a guy at the link below trying to use cv2.cuda.remap for the same thing we are.

In the comments, it ends with a happy “it’s working” with a plethora of exclamation points.

I’m not sure what this cv2.fisheye… is doing

map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)#

But, other than that, loading the map looks doable.

        #map1 = map1.astype(np.float32)
        #map2 = map2.astype(np.float32)
        #map1 = cv2.cuda_GpuMat(map1)
        #map2 = cv2.cuda_GpuMat(map2)

then at some point, he’s able to use cv2.cuda.resize with hopefully faster processing…

        #resized = cv2.cuda.resize(img2, (new_w, new_h), interpolation=cv2.INTER_LINEAR)

Another example of using cv.cuda.remap by the same guy, with another “it’s working” at the end

Some friendly guy posted this, which appears to work, according to the original poster.

cuDst = cv.cuda_GpuMat(cuMat.size(),cuMat.type())

We probably just need to read up on cv.cuda and the GpuMat and maybe we’ll get it too, like the happy guy posting on the OpenCV forums. :slight_smile:


The only sad thing I noticed is that all the test pictures in my camera are of me sitting in front of a computer.

Ha, for me it is my basement, time to clean up. No place to hide stuff in a 360 image :slight_smile:

Have you tried it on a video stream without applying Mobilenet v2 analysis? I’m wondering how fast the Equirec2Perspec can handle the frames.

Not yet, doing this on a video stream is my next to do. I will time that process first before applying any NN. My intuition leads me to believe that many NN run fast enough (100 fps + on the AGX Xavier) that a non-linear transformation will form the bottleneck. The good thing is that I don’t need very fast times. Anything around a second would work for me.

Just to clarify the challenge you’re proposing, do you mean to test OpenCV on NVIDIA Jetson with CUDA acceleration?

No Craig, I was referring to this transformation function specifically. I am already worried that this could be a bottleneck in any application. A C++ implementation using some of the Nvidia accelerations could be very helpful.

1 Like

Hello @craig, Were you able to implement this solution?

Got it to work!! it is streaming and correcting in realtime. Let me play around with the code a little.


I can even create a panorama from perspective corrected images.

import cv2
import os
import Equirec2Perspec2 as E2P
import numpy as np

print(f"OpenCV version {cv2.__version__}")
cap = cv2.VideoCapture(1)

# Check if the webcam is opened correctly
if not cap.isOpened():
    raise IOError("Cannot open webcam")

while True:
    ret, frame =
    equ = E2P.Equirectangular(frame)

    frame1 = equ.GetPerspective(90, 0, 0, 400, 400)
    frame2 = equ.GetPerspective(90, 90, 0, 400, 400)
    frame3 = equ.GetPerspective(90, 180, 0, 400, 400)
    frame4 = equ.GetPerspective(90, 270, 0, 400, 400)

    hor_concat_top = np.concatenate((frame1, frame2), axis=1)
    hor_concat_bottom = np.concatenate((frame3, frame4), axis=1)

    all_four_frames = np.concatenate((hor_concat_top, hor_concat_bottom), axis=1)

    cv2.imshow('Input', all_four_frames)

    c = cv2.waitKey(1)
    if c == 27:




Congratulations and great work. :slight_smile:

Are you next going to experiment with some type of object detection on the frames?

The technique would also be useful for human analysis. Selecting portions for humans to inspect.

Sorry, I haven’t tried yet.

The primary algorithm looks like it is feasible to convert to cv2.cuda.remap, but I believe, we need to use cv2.cuda_GpuMat() on each frame and then upload the frame to the GPU.

persp = cv2.remap(self._img, lon.astype(np.float32), lat.astype(np.float32), cv2.INTER_CUBIC, borderMode=cv2.BORDER_WRAP)

This is quite an interesting challenge as I think we can get some big gains on a wide range of frame processing with little effort. We just need to figure the correct sequence of steps for a few common methods such as remap, resize, cvtColor.

Hey, nice going, Jaap!

1 Like

Dear Ricoh Theta V friends,

We got internal data stream error when using gst_loopback even a dummy /dev/video* is created and is assigned by v4l2loopback.
By following this nice tutorial, both ptpcam and gst_viewer works well.

But we stuck on gst_loopback, it outputs below error:

start, hit any key to stop
Error: Internal data stream error.

Seems like we are very close, one step to get it working, were wondering if any one got the same issue.

Our desktop testing environment is Ubuntu 18.04 LTS, with Linux 4.15.0-118-generic, x86-64
Camera is Theta V with the firmware 3.50.1

– Luke