pythonopencvvideo-streaminggstreamernvidia-jetson

Capture a video stream from rtsp camera and write it to a file


I am trying to capture a video stream coming from an rtsp camera and write it to a file. Using Jetson Xavier AGX with Jetpack 4.5 [L4T 32.5.0]

I am using below python app to perform the task:

cap = cv2.VideoCapture("rtspsrc location=rtsp://10.34.134.1/Streaming/channels/1/ user-id=myuser user-pw=mypass !  rtph264depay ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw, format=BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink")

w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
print('Src opened, %dx%d @ %d fps' % (w, h, fps))

gst_out = "appsrc ! video/x-raw, format=BGR ! queue ! videoconvert ! video/x-raw,format=BGRx ! nvvidconv ! nvv4l2h264enc ! h264parse ! matroskamux ! filesink location=test.mkv "
out = cv2.VideoWriter(gst_out, cv2.CAP_GSTREAMER, 0, float(fps), (int(w), int(h)))
if not out.isOpened():
   print("Failed to open output")
   exit()

if cap.isOpened():
   while True:
      ret_val, img = cap.read()
      if not ret_val:
         break;
      out.write(img);
      cv2.waitKey(1)
else:
   print ("pipeline open failed")

cap.release()
out.release()

Opening the stream doesn’t work. I get the error below:

[ERROR:0@0.041] global /io/opencv/modules/videoio/src/cap.cpp (164) open VIDEOIO(CV_IMAGES): raised OpenCV exception:

OpenCV(4.6.0) /io/opencv/modules/videoio/src/cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can’t find starting number (in the name of file): rtspsrc location=rtsp://10.34.134.1/Streaming/channels/1/ user-id=myuser user-pw=mypass ! rtph264depay ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw, format=BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink in function ‘icvExtractPattern’

Can I somehow modify the string supplied to cv2.VideoCapture in order to properly read the rtsp stream?


Solution

  • If your OpenCV came with GStreamer support, your VideoCapture() call should have worked. CAP_GSTREAMER would have recognized the pipeline string. That even works without explicitly specifying the backend.

    Whenever OpenCV talks about CAP_IMAGES, that means no other backend felt responsible for the "target" and managed to "open" it. CAP_IMAGES is the lowest priority backend and is tried last.

    When that happens, check the Video I/O section in the output of

    import cv2 as cv
    print(cv.getBuildInformation())
    

    On Windows with an official package, this might look like so:

    ...
      Video I/O:
        DC1394:                      NO
        FFMPEG:                      YES (prebuilt binaries)
          avcodec:                   YES (58.134.100)
          avformat:                  YES (58.76.100)
          avutil:                    YES (56.70.100)
          swscale:                   YES (5.9.100)
          avresample:                YES (4.0.0)
        GStreamer:                   NO
        DirectShow:                  YES
        Media Foundation:            YES
          DXVA:                      YES
    ...
    

    If your build of OpenCV did not come with GStreamer, you can build OpenCV yourself, with support for GStreamer, or you can look around for builds that come with it. Your operating system might have a package manager that provides a third party build of OpenCV with GStreamer support. Official packages don't include this, as far as I'm aware.

    To make sure you are getting a specific backend, pass cv.CAP_GSTREAMER or another identifier for the apiPreference parameter of either VideoCapture() or VideoWriter() constructors.

    cap = cv.VideoCapture(your_gst_pipeline, apiPreference=cv.CAP_GSTREAMER)