Gstreamer message to signal new frame from video s

2019-06-25 07:44发布

问题:

I am trying to save a stream from webcam as series of image using gstreamer. I have written this code so far...

#!/usr/bin/python
import sys, os
import pygtk, gtk, gobject
import pygst
pygst.require("0.10")
import gst

 def __init__(self):
      #.... 
      # Code to create a gtk Window
      #....
      self.player = gst.Pipeline("player")
      source = gst.element_factory_make("v4l2src", "video-source")
      sink = gst.element_factory_make("xvimagesink", "video-output")
      caps = gst.Caps("video/x-raw-yuv, width=640, height=480")
      filter = gst.element_factory_make("capsfilter", "filter")
      filter.set_property("caps", caps)
      self.player.add(source, filter, sink)
      gst.element_link_many(source, filter, sink)

After this, I am trying to create a signal over the bus to listen for any message from the source or the sink to indicate a new frame has been sent or received, so that it can be saved.

      bus = self.player.get_bus()
      bus.add_signal_watch()
      bus.connect("message::any", self.save_file,"Save file")

where save_file is my callback, where I want to save the file.

def save_file(self, bus, msg):
      print  "SAVED A NEW FILE"

I have two questions,

  1. How do I invoke this callback. The message::any is not working.
  2. When this message is invoked, how do I get access to the image buffer.

UPDATE (4-12-2012):

Couple of links for reference

  1. A python interface for v4l. But it has not been working for me. It seems to crash when i try to grab on 12.04 Ubuntu. http://code.google.com/p/python-video4linux2/

  2. A webcam viewer code for those interested. But this is not what I want since it uses gst-launch and does not provide the level of pipeline control I want to have. http://pygstdocs.berlios.de/pygst-tutorial/webcam-viewer.html

回答1:

Gstreamer Bus is not intended to be used for this purpose. Messages that are put there signal rather some special event like end-of-stream, element state change and so on. Buffers (images) flowing through elements usualy don't generate any messages on the bus.

You may consider several possibilities:

  • make "tee" element before videosink and connect "multifilesink" in parallel to videosink (you may want to see some image encoders like pngenc or jpegenc and put one of them before multifilesink")
  • like before, but use "appsink" that allow you to handle buffers and do whatever-you-want with them
  • if you want to switch dumping on and off, consider using "valve" element

You may want to set "sync" property to false on your additional sink (Which cause buffers to be dumped as soon as possible without syncing to clock). Consider also adding some queues after tee (without this deadlock may occur during ready->paused transition).



回答2:

I am not sure if my response after years will be useful for you. but hope, it will be useful for others.

to receive a message that you have received a buffer, you can use gstreamer probes.

It could be something similar:

def make_pipeline(self):
    CLI2 = [
    'v4l2src ! video/x-raw,format=RGB,width=640,height=480,framerate=30/1 ! ',
    'videoconvert ! x264enc bitrate=128 ! mpegtsmux name="mux" ! hlssink name="sink"',
    ]
    gcmd = ''.join(CLI2)
    self.pipeline = Gst.parse_launch(gcmd)
    self.hlssink = self.pipeline.get_by_name("sink")
    self.hlssink.set_property("target-duration",2)
    self.hlssink_pad = self.hlssink.get_static_pad("sink")
    probe_id = self.hlssink_pad.add_probe(Gst.PadProbeType.EVENT_UPSTREAM,probe_callback)

and then, the probe callback function could be:

def probe_callback(hlssink_pad,info):
    info_event = info.get_event()
    info_structure = info_event.get_structure()
    do_something_with_this_info
    return Gst.PadProbeReturn.PASS

So, every time there is an event on either a source pad or sink pad, the probe callback function will be called in the main thread.

Hope this helps!