简体   繁体   中英

The filesink creates empty file

I'd like to create a stream over network where on main computer I'd like to have a window with stream and button that allows me to record the stream and save it to a file.

As a source I have following(testing purpose):

gst-launch-1.0 -e -vvvv videotestsrc ! video/x-raw, width=1280, height=1024  ! x264enc ! rtph264pay pt=96 config-interval=1 ! udpsink host=127.0.0.1 port=5000

And on the other side I have a small window in Gtk and I made a widget: (the input method is _on_realize())

import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
gi.require_version('Gtk', '3.0')
from gi.repository import   (Gst, Gtk, GObject)

class GstWidget(Gtk.Box):
    def __init__(self, pipeline):
        super().__init__()
        # Only setup the widget after the window is shown
        self.connect('realize', self._on_realize)
        
    def on_message(self, bus: Gst.Bus, message: Gst.Message, loop: GObject.MainLoop):
        mtype = message.type
        """
            Gstreamer Message Types and how to parse
        """
        if mtype == Gst.MessageType.EOS:
            print("End-of-stream\n")
            loop.quit()

        elif mtype == Gst.MessageType.ERROR:
            err, debug = message.parse_error()
            print("Warning: %s: %s\n" % (err, debug))
            loop.quit()

        elif mtype == Gst.MessageType.WARNING:
            err, debug = message.parse_warning()
            print("Error: %s: %s\n" % (err, debug))

        return True

    def send_eos(self):
        current_state = self.file_valve.get_property("drop")
        new_state = not current_state
        self.file_valve.set_property("drop" , new_state)
        print("Valve set from {} to {}".format(current_state, new_state))
        
    def create_pipeline(self):
        # Create elements
        udpsrc = Gst.ElementFactory.make("udpsrc","udp_src")
        rtph264depay = Gst.ElementFactory.make("rtph264depay", "rtph264depay")
        avdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264")
        self.textoverlay = Gst.ElementFactory.make("textoverlay","textoverlay")
        
        tee = Gst.ElementFactory.make("tee", "tee")

        stream_queue = Gst.ElementFactory.make("queue")
        stream_videoconvert = Gst.ElementFactory.make("videoconvert","videoconvert")
        stream_gtksink = Gst.ElementFactory.make("gtksink","gtksink")

        file_queue = Gst.ElementFactory.make("queue")
        self.file_valve = Gst.ElementFactory.make("valve", "valve")
        file_x264enc = Gst.ElementFactory.make("x264enc", "x264enc")
        file_avimux = Gst.ElementFactory.make("avimux","avimux")
        self.file_filesink = Gst.ElementFactory.make("filesink","filesink")
        
        # Make sure every element is created
        if (not udpsrc or
            not rtph264depay or
            not avdec_h264 or
            not self.textoverlay or
            not tee or
            not stream_queue or
            not stream_videoconvert or
            not stream_gtksink or
            not file_queue or
            not self.file_valve or
            not file_x264enc or
            not file_avimux or
            not self.file_filesink):
            return None, None

        # Configure elements
        udpsrc.set_property("port", 5000)
        caps = Gst.caps_from_string("application/x-rtp, payload=96, media=video, clock-rate=90000")
        udpsrc.set_property("caps", caps)
        self.file_valve.set_property("drop", "false")
        self.file_filesink.set_property("location", "default.avi")
        self.file_filesink.set_property("sync", 1)
        self.file_filesink.set_property("async", 0)
        self.textoverlay.set_property("text",'Hello!')

        # Add elements to bin(pipeline)
        pipeline = Gst.Pipeline()
        pipeline.add(udpsrc)
        pipeline.add(rtph264depay)
        pipeline.add(avdec_h264)
        pipeline.add(self.textoverlay)
        pipeline.add(tee)
        pipeline.add(stream_queue)
        pipeline.add(stream_videoconvert)
        pipeline.add(stream_gtksink)
        pipeline.add(file_queue)        
        pipeline.add(self.file_valve)
        pipeline.add(file_x264enc)
        pipeline.add(file_avimux)
        pipeline.add(self.file_filesink)

        # Link elements together
        # First part
        ret = udpsrc.link(rtph264depay)
        ret = ret and rtph264depay.link(avdec_h264)
        ret = ret and avdec_h264.link(self.textoverlay)
        ret = ret and self.textoverlay.link(tee)

        # Stream part
        ret = ret and stream_queue.link(stream_videoconvert)
        ret = ret and stream_videoconvert.link(stream_gtksink)

        # # File part
        ret = ret and file_queue.link(self.file_valve)
        ret = ret and self.file_valve.link(file_x264enc)
        ret = ret and file_x264enc.link(file_avimux)
        ret = ret and file_x264enc.link(self.file_filesink)

        # Request pads from Tee & get pads from Queues
        tee_pad_stream = tee.get_request_pad("src_%u")
        tee_pad_file = tee.get_request_pad("src_%u")
        stream_queue_pad = stream_queue.get_static_pad("sink")
        file_queue_pad = file_queue.get_static_pad("sink")

        # # Link pads
        tee_pad_stream.link(stream_queue_pad)
        tee_pad_file.link(file_queue_pad)
        
        
        bus = pipeline.get_bus()
        bus.add_signal_watch()

        loop = GObject.MainLoop()
        bus.connect("message", self.on_message, loop)

        return pipeline, stream_gtksink

    def render_text(self, text):
        self.textoverlay.set_property("text", text)

    def _on_realize(self, widget):
        self.pipeline, self.gtksink = self.create_pipeline()
        if self.pipeline is None:
            return
    
        self.pack_start(self.gtksink.props.widget, True, True, 0)
        self.gtksink.props.widget.show()

        # Start the video
        self.pipeline.set_state(Gst.State.PLAYING)

I can see the stream with text ("Hello,"). file is create but it's empty. I can't figure out what I'm doing wrong. I tried

gst-launch-1.0 -e -vvvv udpsrc port=5000 ! application/x-rtp, payload=96, media=video, clock-rate=90000 ! rtph264depay ! avdec_h264 ! textoverlay text="Hello!" ! queue ! valve ! x264enc ! avimux ! filesink location="default.avi"

When I tried the same command from Python it didn't work, what I did: Instead of linking the tee I put there directly the queue(file_queue) but still not output.

After a searching for many hours I found quite nice solution which worked for me. I just added start/stop recording. I still use different sink for the stream I also kept most of my code. For those who wants to stream and save to file once button is pressed: https://gist.github.com/NBonaparte/89fb1b645c99470bc0f6

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM