def setup_streamer(self, width, height):
        fps = Fraction(FPS)
        fps_str = fraction_to_str(fps)
        caps = f'video/x-raw,format={VIDEO_FORMAT},width={width},height={height},framerate={fps_str}'

        # Converts list of plugins to gst-launch string
        # ['plugin_1', 'plugin_2', 'plugin_3'] => plugin_1 ! plugin_2 ! plugin_3
        default_pipeline = utils.to_gst_string([
            f'appsrc caps={caps}', 'videoscale method=1 add-borders=false',
            'video/x-raw,width=1280,height=720', 'videoconvert',
            'v4l2sink device=/dev/video0 sync=false'
        ])

        self.duration = 10**9 / (fps.numerator / fps.denominator)
        self.appsrc = self.pts = self.pipeline = None

        self.context = GstContext()
        self.context.startup()
        self.pipeline = GstPipeline(default_pipeline)

        def on_pipeline_init(other_self):
            """Setup AppSrc element"""
            self.appsrc = other_self.get_by_cls(GstApp.AppSrc)[0]  # get AppSrc

            # instructs appsrc that we will be dealing with timed buffer
            self.appsrc.set_property("format", Gst.Format.TIME)

            # instructs appsrc to block pushing buffers until ones in queue are preprocessed
            # allows to avoid huge queue internal queue size in appsrc
            self.appsrc.set_property("block", True)
            self.appsrc.set_property("is-live", True)

            # set input format (caps)
            self.appsrc.set_caps(Gst.Caps.from_string(caps))

        # override on_pipeline_init to set specific properties before launching pipeline
        self.pipeline._on_pipeline_init = on_pipeline_init.__get__(
            self.pipeline)  # noqa

        try:
            self.pipeline.startup()
            self.appsrc = self.pipeline.get_by_cls(
                GstApp.AppSrc)[0]  # GstApp.AppSrc

            self.pts = 0  # buffers presentation timestamp
        except Exception as e:
            print("Error: ", e)
Beispiel #2
0
import traceback
import argparse
import typing as typ
import time
import attr

import numpy as np

from gstreamer import GstContext, GstPipeline, GstApp, Gst, GstVideo
import gstreamer.utils as utils

# Converts list of plugins to gst-launch string
# ['plugin_1', 'plugin_2', 'plugin_3'] => plugin_1 ! plugin_2 ! plugin_3
DEFAULT_PIPELINE = utils.to_gst_string([
    "videotestsrc num-buffers=100",
    "capsfilter caps=video/x-raw,format=GRAY16_LE,width=640,height=480",
    "queue",
    "appsink emit-signals=True"
])

ap = argparse.ArgumentParser()
ap.add_argument("-p", "--pipeline", required=False,
                default=DEFAULT_PIPELINE, help="Gstreamer pipeline without gst-launch")

args = vars(ap.parse_args())

command = args["pipeline"]


def extract_buffer(sample: Gst.Sample) -> np.ndarray:
    """Extracts Gst.Buffer from Gst.Sample and converts to np.ndarray"""
Beispiel #3
0
        # typ.List[typ.Tuple[str, str]]
        caps = [
            prop for prop in pipeline.split("!")[0].split(" ")
            if "caps" in prop
        ][0]
        return dict([p.split('=') for p in caps.split(',') if "=" in p])
    except IndexError as err:
        return None


DEFAULT_CAPS = f"video/x-raw,format={VIDEO_FORMAT},width={WIDTH},height={HEIGHT},framerate={fraction_to_str(FPS)}"

# Converts list of plugins to gst-launch string
# ['plugin_1', 'plugin_2', 'plugin_3'] => plugin_1 ! plugin_2 ! plugin_3
DEFAULT_PIPELINE = utils.to_gst_string([
    f"appsrc emit-signals=True is-live=True caps={DEFAULT_CAPS}", "queue",
    "videoconvert", "autovideosink"
])

ap = argparse.ArgumentParser()
ap.add_argument("-p",
                "--pipeline",
                required=False,
                default=DEFAULT_PIPELINE,
                help="Gstreamer pipeline without gst-launch")

ap.add_argument("-n",
                "--num_buffers",
                required=False,
                default=100,
                help="Num buffers to pass")
Beispiel #4
0
    def __init__(self, shared: bool = False):
        # https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPServer.html
        self.server = GstRtspServer.RTSPServer()

        # https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPMediaFactory.html#GstRtspServer.RTSPMediaFactory.set_shared
        # f.set_shared(True)

        # https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPServer.html#GstRtspServer.RTSPServer.get_mount_points
        # https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPMountPoints.html#GstRtspServer.RTSPMountPoints
        m = self.server.get_mount_points()

        # pipeline
        # Launch test buffers streaming
        pipeline = utils.to_gst_string([
            "videotestsrc num-buffers=1000",
            "video/x-raw,format={fmt},width={width},height={height}".format(fmt=VIDEO_FORMAT,
                                                                            width=WIDTH,
                                                                            height=HEIGHT),
            "appsink emit-signals=True"
        ])

        # Launch file streaming
        # pipeline = [
        #     "filesrc location=video.mp4",
        #     "decodebin"
        #     "videoconvert n-threads=0",
        #     "video/x-raw,format=RGB",
        #     "appsink emit-signals=True"
        # ]

        # Buffers streaming from pipeline (Gst)
        generator = functools.partial(
            GstBufferGeneratorFromPipeline, gst_launch=pipeline, loop=True
        )

        # Fake buffers streaming from generator (numpy)
        # generator = functools.partial(FakeGstBufferGenerator, width=WIDTH, height=HEIGHT,
        #                               fps=FPS, video_frmt=GST_VIDEO_FORMAT)

        # https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPMountPoints.html#GstRtspServer.RTSPMountPoints.add_factory
        mount_point = "/stream.rtp"
        factory = RTSPMediaFactoryCustom(generator)

        # Launch Raw Stream
        pipeline = [
            "appsrc emit-signals=True is-live=True",
            "queue max-size-buffers=8",
            "rtpvrawpay name=pay0 pt=96"
        ]

        # Launch H264 Stream
        # pipeline = [
        #     "appsrc emit-signals=True is-live=True",
        #     "queue max-size-buffers=8",
        #     "videoconvert n-threads=0 ! video/x-raw,format=I420",
        #     "264enc tune=zerolatency",  # pass quant
        #     "queue max-size-buffers=8",
        #     "rtph264pay config-interval=1 name=pay0 pt=96"
        # ]

        factory.set_launch(utils.to_gst_string(pipeline))
        factory.set_shared(shared)
        m.add_factory(mount_point, factory)  # adding streams

        port = self.server.get_property("service")
        print(f"rtsp://localhost:{port}/{mount_point}")

        # https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPServer.html#GstRtspServer.RTSPServer.attach
        self.server.attach(None)