Recording Video unsing the onBoard camera of Jetson TX2

Hello everyone,

I’m working on the Jetson TX2 for my object detection project. I’m trying the whole time to record a video and take pictures using the CSI-onboard camera. For that I’ve found a python script that do this from the following blog : https://jkjung-avt.github.io/tx2-camera-recorder/

but it doesn’t work.

the following script is from the above blog

import sys
import argparse
import cv2

def parse_args():
    # Parse input arguments
    desc = 'Capture and record live camera video on Jetson TX2/TX1'
    parser = argparse.ArgumentParser(description=desc)
    parser.add_argument('--rtsp', dest='use_rtsp',
                        help='use IP CAM (remember to also set --uri)',
                        action='store_true')
    parser.add_argument('--uri', dest='rtsp_uri',
                        help='RTSP URI, e.g. rtsp://192.168.1.64:554',
                        default=None, type=str)
    parser.add_argument('--latency', dest='rtsp_latency',
                        help='latency in ms for RTSP [200]',
                        default=200, type=int)
    parser.add_argument('--usb', dest='use_usb',
                        help='use USB webcam (remember to also set --vid)',
                        action='store_true')
    parser.add_argument('--vid', dest='video_dev',
                        help='device # of USB webcam (/dev/video?) [1]',
                        default=1, type=int)
    parser.add_argument('--width', dest='image_width',
                        help='image width [640]',
                        default=640, type=int)
    parser.add_argument('--height', dest='image_height',
                        help='image height [480]',
                        default=480, type=int)
    parser.add_argument('--ts', dest='ts_file',
                        help='output .ts file name ["output"]',
                        default='output', type=str)
    parser.add_argument('--fps', dest='fps',
                        help='fps of the output .ts video [30]',
                        default=30, type=int)
    parser.add_argument('--rec', dest='rec_sec',
                        help='recording length in seconds [5]',
                        default=5, type=int)
    parser.add_argument('--text', dest='text',
                        help='text overlayed on the video ["TX2 DEMO"]',
                        default='TX2 DEMO', type=str)
    args = parser.parse_args()
    return args

def open_cam_rtsp(uri, width, height, latency):
    gst_str = ('rtspsrc location={} latency={} ! '
               'rtph264depay ! h264parse ! omxh264dec ! '
               'nvvidconv ! '
               'video/x-raw, width=(int){}, height=(int){}, '
               'format=(string)BGRx ! '
               'videoconvert ! appsink').format(uri, latency, width, height)
    return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)

def open_cam_usb(dev, width, height):
    # We want to set width and height here, otherwise we could just do:
    #     return cv2.VideoCapture(dev)
    gst_str = ('v4l2src device=/dev/video{} ! '
               'video/x-raw, width=(int){}, height=(int){} ! '
               'videoconvert ! appsink').format(dev, width, height)
    return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)

def open_cam_onboard(width, height):
    # On versions of L4T prior to 28.1, add 'flip-method=2' into gst_str
    gst_str = ('nvarguscamerasrc ! '
               'video/x-raw(memory:NVMM), '
               'width=(int)2592, height=(int)1458, '
               'format=(string)I420, framerate=(fraction)30/1 ! '
               'nvvidconv ! '
               'video/x-raw, width=(int){}, height=(int){}, '
               'format=(string)BGRx ! '
               'videoconvert ! appsink').format(width, height)
    return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)

def get_video_writer(fname, fps, width, height):
    gst_str = ('appsrc ! videoconvert ! omxh264enc ! mpegtsmux ! '
               'filesink location={}.ts').format(fname)
    return cv2.VideoWriter(gst_str, cv2.CAP_GSTREAMER, 0, fps,
                           (width, height))

def main():
    args = parse_args()
    print('Called with args:')
    print(args)
    print('OpenCV version: {}'.format(cv2.__version__))

    if args.use_rtsp:
        cap = open_cam_rtsp(args.rtsp_uri,
                            args.image_width,
                            args.image_height,
                            args.rtsp_latency)
    elif args.use_usb:
        cap = open_cam_usb(args.video_dev,
                           args.image_width,
                           args.image_height)
    else: # by default, use the Jetson onboard camera
        cap = open_cam_onboard(args.image_width,
                               args.image_height)
    if not cap.isOpened():
        sys.exit('Failed to open camera!')

    writer = get_video_writer(args.ts_file, args.fps,
                              args.image_width, args.image_height)
    if not writer.isOpened():
        cap.release()
        sys.exit('Failed to open "{}.ts"!'.format(args.ts_file))

    for _ in range(args.fps * args.rec_sec): # assuming python3 here...
        _, img = cap.read() # read image
        if img is None:
            print('No more image from camera, exiting...')
            break
        # put watermark on image
        cv2.putText(img, args.text, (10, 60),
                    fontFace=cv2.FONT_HERSHEY_COMPLEX, fontScale=2.0,
                    color=(0, 240, 0), thickness=6, lineType=cv2.LINE_AA)
        cv2.imshow('REC', img)
        if cv2.waitKey(1) == 27: # ESC key: quit program
            break
        writer.write(img) # write current image to the ts file

    writer.release()
    cap.release()

if __name__ == '__main__':
    main()

when i run this code it displays the following error

Downloads/Tegra-cam$ python3 tegra-cam-rec.py
Called with args:
Namespace(fps=30, image_height=480, image_width=640, rec_sec=5, rtsp_latency=200, rtsp_uri=None, text=‘TX2 DEMO’, ts_file=‘output’, use_rtsp=False, use_usb=False, video_dev=1)
OpenCV version: 4.1.2-dev
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (713) open OpenCV | GStreamer warning: Error opening bin: no element “nvcamerasrc”
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
Failed to open camera!

another script returns the following error:

python3 cam_capture.py
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (1759) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module v4l2src0 reported: Internal data stream error.
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (888) open OpenCV | GStreamer warning: unable to start pipeline
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
select timeout
VIDIOC_DQBUF: Resource temporarily unavailable
Traceback (most recent call last):
File “cam_capture.py”, line 57, in
cv2.imshow(‘frame’,frame)
cv2.error: OpenCV(4.1.2-dev) /home/khaled/opencv/modules/highgui/src/window.cpp:376: error: (-215:Assertion failed) size.width>0 && size.height>0 in function ‘imshow’

So anyone knows how to solve it. Or if anyone has another method of how to record video and capture picture using the on-Board camera of the Jetson TX2., I would be so thankful as i started to lose some hair on this thing.

Thanks in Advance

hello kjbaili,

it’s a combination to composite several plugins into gstreamer pipeline.
you could use “tee” commands to split data into multiple pads.
for example,
below commands to preview stream and also recording simultaneously.

$ gst-launch-1.0 -e nvarguscamerasrc num-buffers=300 ! 'video/x-raw(memory:NVMM), width=2952, height=1944, format=NV12, framerate=30/1' ! tee name=streams streams. ! queue ! nvv4l2h265enc bitrate=8000000 ! h265parse ! qtmux ! filesink location=video0.mp4 streams. ! queue ! nvoverlaysink -e

may I know what’s your expectation of the capturing pictures,
would you like to continuous saving the frames into jpeg files?
thanks

@kjbaili I have updated my gist code to support ‘nvarguscamerasrc’. Could you download the latest code and check if it works for you?

https://gist.github.com/jkjung-avt/1df91d4cedad633cd5b49a4779cb4e32

Hi jkjung13,

Great! Thanks for updating your github to support the ‘nvarguscamerasrc’.

hello @jkjung13 thank you so much it works great

Hello jkjung13,

I just have one more question about your code:

Is it possible to use either of your codes (tegra_cam.py or tegra-cam-rec.py) in order to open an USB camera or record a video using an usb-camra?. if yes, what type of camera is compatible with your code?. For example i have a USB-camera from BASLER company. it is connected to the Jetson via USB port. On the other hand, it has a software supported from BASLER (Pylon Viewer) in order to open it and record Videos or take images,etc. But i’m trying to open it independent from it’s software(pylon viewer), for example using your code or to apply haarcascades face-detection.

I tried your code and it displays the following error:

~/Downloads/Tegra-cam/Tegra_cam$ python tegra-cam.py --usb --vid 0 --width 1280 --height 720
Called with args:
Namespace(image_height=720, image_width=1280, rtsp_latency=200, rtsp_uri=None, use_rtsp=False, use_usb=True, video_dev=0)
OpenCV version: 4.1.2-dev
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (1759) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module v4l2src0 reported: Internal data stream error.
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (888) open OpenCV | GStreamer warning: unable to start pipeline
[ WARN:0] global /home/khaled/opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
Failed to open camera!

the camera that i’m trying to open ( or recording Video) using your codes is connected to usb-of Jetson as show below:

<b>Bus 002 Device 002: ID 2676:ba02 Basler AG ace</b>
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 1a81:1002 Holtek Semiconductor, Inc. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

or here:

T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=5000 MxCh= 0
D:  Ver= 3.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS= 9 #Cfgs=  1
P:  Vendor=2676 ProdID=ba02 Rev=00.00
S:  Manufacturer=Basler
S:  Product=acA1920-40uc
S:  SerialNumber=22697509
C:  #Ifs= 3 Cfg#= 1 Atr=a0 MxPwr=896mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ef(misc ) Sub=05 Prot=00 Driver=(none)
I:  If#= 1 Alt= 0 #EPs= 1 Cls=ef(misc ) Sub=05 Prot=02 Driver=(none)
I:  If#= 2 Alt= 0 #EPs= 1 Cls=ef(misc ) Sub=05 Prot=01 Driver=(none)

Would be grateful if you could help

Thanks in advance

I use GStreamer’s ‘v4l2src’ to access USB webcams, so I should work for most UVC cameras (https://en.wikipedia.org/wiki/USB_video_device_class). For example, I usually test with Logitech C920/C920r and some other lower-end Logitech USB webcams. They all work OK with tegra-cam.py.

I think Basler cameras are not standard UVC devices. You will have to use Basler’s SDK to access them.

Thank you for your answer. This means when I type the following command:

$ python tegra-cam.py --usb --vid 0 --width 1280 --height 720

under assumption that an UVC camera is per USB-port connected, your code should open it, shouldn’t it?

or do i need to modify your code in order to be able to open the UVC camera?

thanks in advance

@kjbaili Yes. Just one additional note. When you use Jetson TX2 DevKit for testing, /dev/video0 is already assigned to the onboard (CSI) camera. As a result, the USB webcam is usually /dev/video1. In that case, you’d use ‘–vid 1’ instead of ‘–vid 0’.