servevideo.bash:
Код: Выделить всё
#!/bin/bash
gst-launch-1.0 v4l2src device=[device-fd] \
! video/x-raw, width=800, height=600, framerate=24/1 \
! jpegenc ! rtpjpegpay ! rtpstreampay \
! udpsink host=[destination-ip] port=12345
Код: Выделить всё
#!/bin/bash
gst-launch-1.0 -e udpsrc port=12344 \
! application/x-rtp-stream,encoding-name=JPEG \
! rtpstreamdepay ! rtpjpegdepay ! jpegdec \
! autovideosink
webcam_passthrough.py:
#!/ usr/bin/python3.6
Код: Выделить всё
import cv2
video_in = cv2.VideoCapture("udpsrc port=12345 ! application/x-rtp-stream,encoding-name=JPEG ! rtpstreamdepay ! rtpjpegdepay ! jpegdec ! videoconvert ! appsink", cv2.CAP_GSTREAMER)
video_out = cv2.VideoWriter("appsrc ! videoconvert ! jpegenc ! rtpjpegpay ! rtpstreampay ! udpsink host=[destination-ip] port=12344", cv2.CAP_GSTREAMER, 0, 24, (800, 600), True)
while True:
ret, frame = video_in.read()
if not ret: break
video_out.write(frame)
cv2.imshow('Original', frame)
key = cv2.waitKey(1) & 0xff
if key == 27: break
cv2.destroyAllWindows()
video_out.release()
video_in.release()
Я также с радостью предоставлю дополнительную информацию, если что-то неясно или отсутствует.
РЕДАКТИРОВАТЬ:
Поэтому кажется, что цель моего минимального примера не была четко выражена.
Три сценария представлены в качестве минимального примера. служат для передачи видео с веб-камеры с моего ноутбука на Jetson AGX Xavier, который затем передает видеосигнал возвращается на ноутбук. Служебноевидео.bash создает на ноутбуке конвейер GStreamer, который использует v4l2 для захвата кадров с камеры и передачи их в сокет UDP. Webcam_passthrough.py запускается на Jetson, где он «подключается» к сокету UDP, созданному конвейером, работающим на ноутбуке. Сценарий Python выполняет транзитную функцию, которая в идеале открывает новый сокет UDP на другом порту и ретранслирует кадры обратно на ноутбук. getvideo.bash создает на ноутбуке еще один конвейер для приема кадров, прошедших через скрипт Python на Jetson. Второй конвейер на ноутбуке используется только для целей визуализации. В идеале этот минимальный пример показывает «необработанный» видеопоток с камеры, подключенной к ноутбуку.
Два bash-скрипта работают изолированно: оба выполняются локально на ноутбуке, а другой — с помощью функции получения видео. bash удаленно на другом компьютере.
Конфигурация cv2.VideoCapture в сценарии Python также работает, поскольку я могу визуализировать кадры (с помощью cv2.imshow< /code>), полученный за UDP-сокет, предоставляемый сценарием servevideo.bash. Это работает как локально, так и удаленно. Часть, которая вызывает у меня некоторую головную боль (я думаю), — это конфигурация cv2.VideoWriter; в идеале это должно открыть сокет UDP, к которому я могу «подключиться» через мой скрипт получения видео.bash. Я тестировал это локально и удаленно, но безрезультатно.
Когда я запускаю getvideo.bash для подключения к UDP-сокету, предоставленному сценарием Python, я получаю следующий вывод:
Код: Выделить всё
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Код: Выделить всё
0:00:06.595120595 8962 0x25b8cf0 WARN rtpjpegpay gstrtpjpegpay.c:596:gst_rtp_jpeg_pay_read_sof: warning: Invalid component
Код: Выделить всё
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
0:00:00.013911480 9078 0x55be0899de80 FIXME videodecoder gstvideodecoder.c:933:gst_video_decoder_drain_out: Sub-class should implement drain()
Setting pipeline to PLAYING ...
New clock: GstSystemClock
РЕДАКТИРОВАНИЕ 2:
Итак, теперь я попытался разделить два конвейера на два отдельных процесса, как это предложено @abysslover. Я до сих пор вижу тот же результат и до сих пор понятия не имею, почему это так. Моя текущая реализация сценария Python указана ниже.
webcam_passthrough.py:
Код: Выделить всё
#!/usr/bin/python3.6
import signal, cv2
from multiprocessing import Process, Pipe
is_running = True
def signal_handler(sig, frame):
global is_running
print("Program was interrupted - terminating ...")
is_running = False
def produce(pipe):
global is_running
video_in = cv2.VideoCapture("udpsrc port=12345 ! application/x-rtp-stream,encoding-name=JPEG ! rtpstreamdepay ! rtpjpegdepay ! jpegdec ! videoconvert ! appsink", cv2.CAP_GSTREAMER)
while is_running:
ret, frame = video_in.read()
if not ret: break
print("Receiving frame ...")
pipe.send(frame)
video_in.release()
if __name__ == "__main__":
consumer_pipe, producer_pipe = Pipe()
signal.signal(signal.SIGINT, signal_handler)
producer = Process(target=produce, args=(producer_pipe,))
video_out = cv2.VideoWriter("appsrc ! videoconvert ! jpegenc ! rtpjpegpay ! rtpstreampay ! udpsink host=[destination-ip] port=12344", cv2.CAP_GSTREAMER, 0, 24, (800, 600), True)
producer.start()
while is_running:
frame = consumer_pipe.recv()
video_out.write(frame)
print("Sending frame ...")
video_out.release()
producer.join()
Подробнее здесь: https://stackoverflow.com/questions/660 ... -gstreamer