@marmikshah Thanks for the explanation!
@yuweiw
I am using the repo below to create an RTSP server to stream video frames that I process using openCV.
https://github.com/prabhakar-sivanesan/OpenCV-rtsp-server.git
I noticed it is quite different from Deepstream because the stream only starts when I call it from VLC or within another application.
@marmikshah I added udpsink
to my pipeline and also added :
"( udpsrc name=pay0 port=%d caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)%s )" % (int(5400), "H264")
But I get a segmentation fault.
I appreciate your help I am getting started with gstreamer pipelines.
My code below:
class SensorFactory(GstRtspServer.RTSPMediaFactory):
def __init__(self, **properties):
super(SensorFactory, self).__init__(**properties)
self.cap = cv2.VideoCapture("/path/to/mp4/video.mp4")
self.number_frames = 0
self.fps = 2
self.duration = 1 / self.fps * Gst.SECOND # duration of a frame in nanoseconds
self.launch_string = 'appsrc name=source is-live=true block=true format=GST_FORMAT_TIME ' \
'caps=video/x-raw,format=BGR,width={},height={},framerate={}/1 ' \
'! videoconvert ! video/x-raw,format=I420 ' \
'! x264enc speed-preset=ultrafast tune=zerolatency ' \
'! rtph264pay config-interval=1 name=pay0 pt=96 ! udpsink host=localhost port=5000' \
.format(opt.image_width, opt.image_height, self.fps)
# method to capture the video feed from the camera and push it to the
# streaming buffer.
def on_need_data(self, src, length):
if self.cap.isOpened():
ret, frame = self.cap.read()
if ret:
# It is better to change the resolution of the camera
# instead of changing the image shape as it affects the image quality.
frame = cv2.resize(frame, (opt.image_width, opt.image_height), interpolation = cv2.INTER_LINEAR)
data = frame.tobytes()
buf = Gst.Buffer.new_allocate(None, len(data), None)
buf.fill(0, data)
buf.duration = self.duration
timestamp = self.number_frames * self.duration
buf.pts = buf.dts = int(timestamp)
buf.offset = timestamp
self.number_frames += 1
retval = src.emit('push-buffer', buf)
print('pushed buffer, frame {}, duration {} ns, durations {} s'.format(self.number_frames,
self.duration,
self.duration / Gst.SECOND))
if retval != Gst.FlowReturn.OK:
print(retval)
# attach the launch string to the override method
def do_create_element(self, url):
return Gst.parse_launch(self.launch_string)
# attaching the source element to the rtsp media
def do_configure(self, rtsp_media):
self.number_frames = 0
appsrc = rtsp_media.get_element().get_child_by_name('source')
appsrc.connect('need-data', self.on_need_data)
# Rtsp server implementation where we attach the factory sensor with the stream uri
class GstServer(GstRtspServer.RTSPServer):
def __init__(self, **properties):
super(GstServer, self).__init__(**properties)
self.factory = SensorFactory()
self.factory.set_launch("( udpsrc name=pay0 port=%d caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)%s )" % (int(5400), "H264"))
self.factory.set_shared(True)
self.set_service(str(opt.port))
self.get_mount_points().add_factory(opt.stream_uri, self.factory)
self.attach(None)