How To : Create Video chat using gst and python and show initiators and accepter's video, in single gtk window

1.8k Views Asked by At

I am developing video chat using gst and python. where, I would like to view end user's webcam and also want to view my own webcam in one gtk window (similar to empathy video chat).

for that, I have used gst.Tee object and created 2 queues, one would link result to local gtk window and second queue would link same video stream to session object.

gst.Tee have done the task but also decrease the speed of video chat and Video comes later than Audio. (I have used different stream for Audio session)

here, the code snippet :

self.pipeline = gst.Pipeline()

bus = self.pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', self._on_gst_message)

self.src_bin = gst.element_factory_make("autovideosrc", "src")
autovideosinkLocal = gst.element_factory_make("autovideosink", "autovideosinkLocal")
tee = gst.element_factory_make('tee', "tee")
queueLocal = gst.element_factory_make("queue", "queueLocal")
queueSend = gst.element_factory_make("queue", "queueSend")
self.pipeline.add(self.src_bin, tee, queueLocal, autovideosinkLocal, queueSend)
gst.element_link_many(self.src_bin, tee)
tee.link(queueLocal)
queueLocal.link(autovideosinkLocal)
tee.link(queueSend)
queueSend.get_pad('src').link(self.p2psession.get_property('sink-pad'))
self.pipeline.set_state(gst.STATE_PLAYING)

How would I speedup the video chat (like, If I would use single sink and display only accepter's video it works great)?

Is there any other way to do the same?

Thanks!

1

There are 1 best solutions below

2
On

I was holding off on answering, but as no one else has weighed in, I'll take a shot at it.

I'm not sure if this would tie in with webcam (though it probably would), but you could create two drawing areas (gtk.DrawingArea) in PyGTK for your two screens. Then, you can hook your video up to those.

I'm doing something similar in my code for playing video. This may require you to create two separate sinks, but frankly, I'm not sure. (If anyone can further expand on this idea, please feel free to do so in comments.)

Here's the piece of code I'm using right now (taken from def __ init __. I am dealing with a small glitch with it in Ubuntu (it has to do with JACK I think), but I'm pretty sure that's computer specific. Note, I have a predefined path.

def __init__(self):

        def on_message(bus, message): 
            if message.type == gst.MESSAGE_EOS: 
                # End of Stream 
                player.set_state(gst.STATE_NULL) 
            elif message.type == gst.MESSAGE_ERROR: 
                player.set_state(gst.STATE_NULL) 
                (err, debug) = message.parse_error() 
                print "Error: %s" % err, debug

        def on_sync_message(bus, message):
            if message.structure is None: 
                return False 
            if message.structure.get_name() == "prepare-xwindow-id":
                if sys.platform == "win32":
                    win_id = videowidget.window.handle
                else:
                    win_id = videowidget.window.xid
                assert win_id
                imagesink = message.src 
                imagesink.set_property("force-aspect-ratio", True)
                imagesink.set_xwindow_id(win_id) 

        win = gtk.Window()
        win.set_resizable(False)
        win.set_has_frame(False)
        win.set_position(gtk.WIN_POS_CENTER)

        fixed = gtk.Fixed()
        win.add(fixed)
        fixed.show()

        videowidget = gtk.DrawingArea()
        fixed.put(videowidget, 0, 0)
        videowidget.set_size_request(640, 480)
        videowidget.show()

        # Setup GStreamer 
        player = gst.element_factory_make("playbin", "MultimediaPlayer")
        bus = player.get_bus() 
        bus.add_signal_watch() 
        bus.enable_sync_message_emission() 
        #used to get messages that GStreamer emits 
        bus.connect("message", on_message) 
        #used for connecting video to your application 
        bus.connect("sync-message::element", on_sync_message)
        player.set_property("uri", "file://" + os.getcwd() + "/VID/SEQ-GAME-OPEN.ogv") 
        player.set_state(gst.STATE_PLAYING)

        win.show()

Here's hoping that helps you out, some.