From e16e63d5e8bb773417bac98ddc5630f8000713d4 Mon Sep 17 00:00:00 2001 From: Michael Tom-Wing Date: Sat, 14 Sep 2013 01:35:13 -0700 Subject: [PATCH 01/16] Changed shebang lines so that they work in a virtualenv This reverts commit 7ddd9c22bc35bed4af067c56db8123b2c0a3aefd. --- src/freeseer-config | 2 +- src/freeseer-record | 2 +- src/freeseer-reporteditor | 2 +- src/freeseer-server | 2 +- src/freeseer-talkeditor | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/freeseer-config b/src/freeseer-config index 85fe17c0..60e86f97 100755 --- a/src/freeseer-config +++ b/src/freeseer-config @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- # freeseer - vga/presentation capture software diff --git a/src/freeseer-record b/src/freeseer-record index 7ea2425a..3c2ae996 100755 --- a/src/freeseer-record +++ b/src/freeseer-record @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- # freeseer - vga/presentation capture software diff --git a/src/freeseer-reporteditor b/src/freeseer-reporteditor index cc7ad817..1c83f9cb 100755 --- a/src/freeseer-reporteditor +++ b/src/freeseer-reporteditor @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- # freeseer - vga/presentation capture software diff --git a/src/freeseer-server b/src/freeseer-server index 01fc2310..18a48b88 100755 --- a/src/freeseer-server +++ b/src/freeseer-server @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- # freeseer - vga/presentation capture software diff --git a/src/freeseer-talkeditor b/src/freeseer-talkeditor index e166fb57..5976f5ef 100755 --- a/src/freeseer-talkeditor +++ b/src/freeseer-talkeditor @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- # freeseer - vga/presentation capture software From 20c5e071d6e6dbb85475c9889d434990f491f47c Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 28 Oct 2013 15:56:12 -0700 Subject: [PATCH 02/16] In flight migration to GStreamer 1.0 - This commit is pretty much so that the project can see this migration in progress. It will is all likeliness be squashed later. - Having limited the functionality of this migration to; working in Linux, and Windows using the test source, I am starting to make so actual progress. - Up to this point the project builds without errors, in Windows, and if you select the test source as the source it will play. Unfortunately currently GStreamer opens its own window for the preview instead of painting it in FreeSeer - I would pretty much assume this will fail Travis --- src/freeseer/framework/multimedia.py | 34 +- .../plugins/audioinput/alsasrc/__init__.py | 14 +- .../audioinput/audiotestsrc/__init__.py | 14 +- .../audioinput/autoaudiosrc/__init__.py | 14 +- .../audioinput/jackaudiosrc/__init__.py | 14 +- .../plugins/audioinput/pulsesrc/__init__.py | 16 +- .../audiomixer/audiopassthrough/__init__.py | 20 +- .../plugins/audiomixer/multiaudio/__init__.py | 22 +- .../plugins/output/audiofeedback/__init__.py | 16 +- .../plugins/output/ogg_icecast/__init__.py | 38 +- .../plugins/output/ogg_output/__init__.py | 44 +- .../plugins/output/rtmp_streaming/__init__.py | 38 +- .../plugins/output/videopreview/__init__.py | 18 +- .../plugins/output/webm_output/__init__.py | 40 +- .../plugins/videoinput/desktop/__init__.py | 21 +- .../videoinput/firewiresrc/__init__.py | 22 +- .../plugins/videoinput/usbsrc/__init__.py | 32 +- .../plugins/videoinput/usbsrc/plugin.py | 515 ++++++++++++++++++ .../videoinput/videotestsrc/__init__.py | 14 +- .../plugins/videomixer/pip/__init__.py | 52 +- .../videomixer/videopassthrough/__init__.py | 32 +- .../videomixer/videopassthrough/widget.py | 4 +- 22 files changed, 784 insertions(+), 250 deletions(-) create mode 100644 src/freeseer/plugins/videoinput/usbsrc/plugin.py diff --git a/src/freeseer/framework/multimedia.py b/src/freeseer/framework/multimedia.py index 325e93bc..1e9087c3 100644 --- a/src/freeseer/framework/multimedia.py +++ b/src/freeseer/framework/multimedia.py @@ -25,12 +25,20 @@ import datetime import logging import os - +""" import gobject gobject.threads_init() import pygst pygst.require("0.10") import gst +""" +#Comment out for now, Nick +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst + +GObject.threads_init() +Gst.init(None) from freeseer.framework.presentation import Presentation from freeseer.framework.plugin import IOutput @@ -58,7 +66,7 @@ def __init__(self, config, plugman, window_id=None, audio_feedback=None, cli=Fal self.current_state = Multimedia.NULL # Initialize Player - self.player = gst.Pipeline('player') + self.player = Gst.Pipeline() bus = self.player.get_bus() bus.add_signal_watch() bus.enable_sync_message_emission() @@ -66,8 +74,8 @@ def __init__(self, config, plugman, window_id=None, audio_feedback=None, cli=Fal bus.connect('sync-message::element', self.on_sync_message) # Initialize Entry Points - self.audio_tee = gst.element_factory_make('tee', 'audio_tee') - self.video_tee = gst.element_factory_make('tee', 'video_tee') + self.audio_tee = Gst.ElementFactory.make('tee', 'audio_tee') + self.video_tee = Gst.ElementFactory.make('tee', 'video_tee') self.player.add(self.audio_tee) self.player.add(self.video_tee) @@ -79,10 +87,10 @@ def __init__(self, config, plugman, window_id=None, audio_feedback=None, cli=Fal def on_message(self, bus, message): t = message.type - if t == gst.MESSAGE_EOS: + if t == Gst.MESSAGE_EOS: self.stop() - elif t == gst.MESSAGE_ERROR: + elif t == Gst.MESSAGE_ERROR: err, debug = message.parse_error() log.error(str(err) + str(debug)) @@ -102,13 +110,15 @@ def on_message(self, bus, message): self.audio_feedback_event(percent) def on_sync_message(self, bus, message): - if message.structure is None: + if message.get_structure() is None: return - message_name = message.structure.get_name() - if message_name == 'prepare-xwindow-id' and self.window_id is not None: + message_name = message.get_structure().get_name() + if message_name == 'prepare-window-handle' and self.window_id is not None: imagesink = message.src imagesink.set_property('force-aspect-ratio', True) + #imagesink.set_window_handle(int(self.window_id)) imagesink.set_xwindow_id(int(self.window_id)) + log.debug("Preview loaded into window.") def set_window_id(self, window_id): @@ -126,7 +136,7 @@ def record(self): """ Start recording. """ - self.player.set_state(gst.STATE_PLAYING) + self.player.set_state(Gst.State.PLAYING) self.current_state = Multimedia.RECORD log.debug("Recording started.") @@ -134,7 +144,7 @@ def pause(self): """ Pause recording. """ - self.player.set_state(gst.STATE_PAUSED) + self.player.set_state(Gst.State.PAUSED) self.current_state = Multimedia.PAUSE log.debug("Gstreamer paused.") @@ -143,7 +153,7 @@ def stop(self): Stop recording. """ if self.current_state != Multimedia.NULL and self.current_state != Multimedia.STOP: - self.player.set_state(gst.STATE_NULL) + self.player.set_state(Gst.State.NULL) self.unload_audiomixer() self.unload_videomixer() diff --git a/src/freeseer/plugins/audioinput/alsasrc/__init__.py b/src/freeseer/plugins/audioinput/alsasrc/__init__.py index f2cfb3c2..737ddfc6 100644 --- a/src/freeseer/plugins/audioinput/alsasrc/__init__.py +++ b/src/freeseer/plugins/audioinput/alsasrc/__init__.py @@ -28,9 +28,9 @@ @author: Thanh Ha ''' -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst from freeseer.framework.plugin import IAudioInput @@ -40,14 +40,14 @@ class ALSASrc(IAudioInput): os = ["linux", "linux2"] def get_audioinput_bin(self): - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - audiosrc = gst.element_factory_make("alsasrc", "audiosrc") + audiosrc = Gst.ElementFactory.make("alsasrc", "audiosrc") bin.add(audiosrc) # Setup ghost pad - pad = audiosrc.get_pad("src") - ghostpad = gst.GhostPad("audiosrc", pad) + pad = audiosrc.get_static_pad("src") + ghostpad = Gst.GhostPad.new("audiosrc", pad) bin.add_pad(ghostpad) return bin diff --git a/src/freeseer/plugins/audioinput/audiotestsrc/__init__.py b/src/freeseer/plugins/audioinput/audiotestsrc/__init__.py index e210ea95..27123e15 100644 --- a/src/freeseer/plugins/audioinput/audiotestsrc/__init__.py +++ b/src/freeseer/plugins/audioinput/audiotestsrc/__init__.py @@ -29,9 +29,9 @@ @author: Thanh Ha ''' -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst from freeseer.framework.plugin import IAudioInput @@ -41,14 +41,14 @@ class AudioTestSrc(IAudioInput): os = ["linux", "linux2", "win32", "cygwin", "darwin"] def get_audioinput_bin(self): - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - audiosrc = gst.element_factory_make("audiotestsrc", "audiosrc") + audiosrc = Gst.ElementFactory.make("audiotestsrc", "audiosrc") bin.add(audiosrc) # Setup ghost pad - pad = audiosrc.get_pad("src") - ghostpad = gst.GhostPad("audiosrc", pad) + pad = audiosrc.get_static_pad("src") + ghostpad = Gst.GhostPad.new("audiosrc", pad) bin.add_pad(ghostpad) return bin diff --git a/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py b/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py index 0251ba59..dbfe58e0 100644 --- a/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py +++ b/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py @@ -29,9 +29,9 @@ @author: Thanh Ha ''' -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst from freeseer.framework.plugin import IAudioInput @@ -41,14 +41,14 @@ class AutoAudioSrc(IAudioInput): os = ["linux", "linux2", "win32", "cygwin", "darwin"] def get_audioinput_bin(self): - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - audiosrc = gst.element_factory_make("autoaudiosrc", "audiosrc") + audiosrc = Gst.ElementFactory.make("autoaudiosrc", "audiosrc") bin.add(audiosrc) # Setup ghost pad - pad = audiosrc.get_pad("src") - ghostpad = gst.GhostPad("audiosrc", pad) + pad = audiosrc.get_static_pad("src") + ghostpad = Gst.GhostPad.new("audiosrc", pad) bin.add_pad(ghostpad) return bin diff --git a/src/freeseer/plugins/audioinput/jackaudiosrc/__init__.py b/src/freeseer/plugins/audioinput/jackaudiosrc/__init__.py index 49334cb9..e9a8440b 100644 --- a/src/freeseer/plugins/audioinput/jackaudiosrc/__init__.py +++ b/src/freeseer/plugins/audioinput/jackaudiosrc/__init__.py @@ -32,9 +32,9 @@ import ConfigParser # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt from PyQt4.QtCore import SIGNAL @@ -57,14 +57,14 @@ class JackAudioSrc(IAudioInput): clientname = "" def get_audioinput_bin(self): - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - audiosrc = gst.element_factory_make("jackaudiosrc", "audiosrc") + audiosrc = Gst.ElementFactory.make("jackaudiosrc", "audiosrc") bin.add(audiosrc) # Setup ghost pad - pad = audiosrc.get_pad("src") - ghostpad = gst.GhostPad("audiosrc", pad) + pad = audiosrc.get_static_pad("src") + ghostpad = Gst.GhostPad.new("audiosrc", pad) bin.add_pad(ghostpad) return bin diff --git a/src/freeseer/plugins/audioinput/pulsesrc/__init__.py b/src/freeseer/plugins/audioinput/pulsesrc/__init__.py index 5c5b40ab..19d7a7bb 100644 --- a/src/freeseer/plugins/audioinput/pulsesrc/__init__.py +++ b/src/freeseer/plugins/audioinput/pulsesrc/__init__.py @@ -33,9 +33,9 @@ import logging # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt from PyQt4.QtCore import SIGNAL @@ -57,17 +57,17 @@ class PulseSrc(IAudioInput): source = '' def get_audioinput_bin(self): - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - audiosrc = gst.element_factory_make("pulsesrc", "audiosrc") + audiosrc = Gst.ElementFactory.make("pulsesrc", "audiosrc") if self.source != '': audiosrc.set_property('device', self.source) log.debug('Pulseaudio source is set to %s' % str(audiosrc.get_property('device'))) bin.add(audiosrc) # Setup ghost pad - pad = audiosrc.get_pad("src") - ghostpad = gst.GhostPad("audiosrc", pad) + pad = audiosrc.get_static_pad("src") + ghostpad = Gst.GhostPad.new("audiosrc", pad) bin.add_pad(ghostpad) return bin @@ -77,7 +77,7 @@ def __get_sources(self): Get a list of pairs in the form (name, description) for each pulseaudio source. """ result = [] - audiosrc = gst.element_factory_make("pulsesrc", "audiosrc") + audiosrc = Gst.ElementFactory.make("pulsesrc", "audiosrc") audiosrc.probe_property_name('device') names = audiosrc.probe_get_values_name('device') #should be getting actual device description, but .get_property('device-name') does not work diff --git a/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py b/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py index 375bfbad..ca4c2492 100644 --- a/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py +++ b/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py @@ -34,9 +34,9 @@ import ConfigParser # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt from PyQt4.QtCore import SIGNAL @@ -55,18 +55,20 @@ class AudioPassthrough(IAudioMixer): widget = None def get_audiomixer_bin(self): - bin = gst.Bin() + bin = Gst.Bin() - audiomixer = gst.element_factory_make("adder", "audiomixer") + audiomixer = Gst.ElementFactory.make("adder", "audiomixer") bin.add(audiomixer) # Setup ghost pad - sinkpad = audiomixer.get_pad("sink%d") - sink_ghostpad = gst.GhostPad("sink", sinkpad) + sinkpad = audiomixer.get_request_pad("sink_%u") + print "DOOM CHICKEN!!!" + print sinkpad + sink_ghostpad = Gst.GhostPad.new("sink", sinkpad) bin.add_pad(sink_ghostpad) - srcpad = audiomixer.get_pad("src") - src_ghostpad = gst.GhostPad("src", srcpad) + srcpad = audiomixer.get_static_pad("src") + src_ghostpad = Gst.GhostPad.new("src", srcpad) bin.add_pad(src_ghostpad) return bin diff --git a/src/freeseer/plugins/audiomixer/multiaudio/__init__.py b/src/freeseer/plugins/audiomixer/multiaudio/__init__.py index 780c86dd..b0736192 100644 --- a/src/freeseer/plugins/audiomixer/multiaudio/__init__.py +++ b/src/freeseer/plugins/audiomixer/multiaudio/__init__.py @@ -32,9 +32,9 @@ import ConfigParser # GStreamer -import pygst -pygst.require('0.10') -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt from PyQt4.QtCore import SIGNAL @@ -54,22 +54,22 @@ class MultiAudio(IAudioMixer): widget = None def get_audiomixer_bin(self): - mixerbin = gst.Bin() + mixerbin = Gst.Bin() - audiomixer = gst.element_factory_make('adder', 'audiomixer') + audiomixer = Gst.ElementFactory.make('adder', 'audiomixer') mixerbin.add(audiomixer) # ghost pads - sinkpad1 = audiomixer.get_pad('sink%d') - sink_ghostpad1 = gst.GhostPad('sink1', sinkpad1) + sinkpad1 = audiomixer.get_static_pad('sink%d') + sink_ghostpad1 = Gst.GhostPad.new('sink1', sinkpad1) mixerbin.add_pad(sink_ghostpad1) - sinkpad2 = audiomixer.get_pad('sink%d') - sink_ghostpad2 = gst.GhostPad('sink2', sinkpad2) + sinkpad2 = audiomixer.get_static_pad('sink%d') + sink_ghostpad2 = Gst.GhostPad.new('sink2', sinkpad2) mixerbin.add_pad(sink_ghostpad2) - srcpad = audiomixer.get_pad('src') - src_ghostpad = gst.GhostPad('src', srcpad) + srcpad = audiomixer.get_static_pad('src') + src_ghostpad = Gst.GhostPad.new('src', srcpad) mixerbin.add_pad(src_ghostpad) return mixerbin diff --git a/src/freeseer/plugins/output/audiofeedback/__init__.py b/src/freeseer/plugins/output/audiofeedback/__init__.py index 3fd50cd5..79bcbcac 100644 --- a/src/freeseer/plugins/output/audiofeedback/__init__.py +++ b/src/freeseer/plugins/output/audiofeedback/__init__.py @@ -33,9 +33,9 @@ import ConfigParser # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt from PyQt4.QtCore import SIGNAL @@ -57,17 +57,17 @@ class AudioFeedback(IOutput): feedbacksink = "autoaudiosink" def get_output_bin(self, audio=True, video=False, metadata=None): - bin = gst.Bin() + bin = Gst.Bin() - audioqueue = gst.element_factory_make("queue", "audioqueue") + audioqueue = Gst.ElementFactory.make("queue", "audioqueue") bin.add(audioqueue) - audiosink = gst.element_factory_make(self.feedbacksink, "audiosink") + audiosink = Gst.ElementFactory.make(self.feedbacksink, "audiosink") bin.add(audiosink) # Setup ghost pad - pad = audioqueue.get_pad("sink") - ghostpad = gst.GhostPad("sink", pad) + pad = audioqueue.get_static_pad("sink") + ghostpad = Gst.GhostPad.new("sink", pad) bin.add_pad(ghostpad) audioqueue.link(audiosink) diff --git a/src/freeseer/plugins/output/ogg_icecast/__init__.py b/src/freeseer/plugins/output/ogg_icecast/__init__.py index 35f8b794..334d01ad 100644 --- a/src/freeseer/plugins/output/ogg_icecast/__init__.py +++ b/src/freeseer/plugins/output/ogg_icecast/__init__.py @@ -32,9 +32,9 @@ import ConfigParser # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt from PyQt4.QtCore import SIGNAL @@ -61,16 +61,16 @@ class OggIcecast(IOutput): mount = "stream.ogg" def get_output_bin(self, audio=True, video=True, metadata=None): - bin = gst.Bin() + bin = Gst.Bin() if metadata is not None: self.set_metadata(metadata) # Muxer - muxer = gst.element_factory_make("oggmux", "muxer") + muxer = Gst.ElementFactory.make("oggmux", "muxer") bin.add(muxer) - icecast = gst.element_factory_make("shout2send", "icecast") + icecast = Gst.ElementFactory.make("shout2send", "icecast") icecast.set_property("ip", self.ip) icecast.set_property("port", self.port) icecast.set_property("password", self.password) @@ -81,19 +81,19 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Audio Pipeline # if audio: - audioqueue = gst.element_factory_make("queue", "audioqueue") + audioqueue = Gst.ElementFactory.make("queue", "audioqueue") bin.add(audioqueue) - audioconvert = gst.element_factory_make("audioconvert", "audioconvert") + audioconvert = Gst.ElementFactory.make("audioconvert", "audioconvert") bin.add(audioconvert) - audiocodec = gst.element_factory_make("vorbisenc", "audiocodec") + audiocodec = Gst.ElementFactory.make("vorbisenc", "audiocodec") bin.add(audiocodec) # Setup metadata - vorbistag = gst.element_factory_make("vorbistag", "vorbistag") + vorbistag = Gst.ElementFactory.make("vorbistag", "vorbistag") # set tag merge mode to GST_TAG_MERGE_REPLACE - merge_mode = gst.TagMergeMode.__enum_values__[2] + merge_mode = Gst.TagMergeMode.__enum_values__[2] if metadata is not None: # Only set tag if metadata is set @@ -102,8 +102,8 @@ def get_output_bin(self, audio=True, video=True, metadata=None): bin.add(vorbistag) # Setup ghost pads - audiopad = audioqueue.get_pad("sink") - audio_ghostpad = gst.GhostPad("audiosink", audiopad) + audiopad = audioqueue.get_static_pad("sink") + audio_ghostpad = Gst.GhostPad.new("audiosink", audiopad) bin.add_pad(audio_ghostpad) # Link elements @@ -116,14 +116,14 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Video Pipeline # if video: - videoqueue = gst.element_factory_make("queue", "videoqueue") + videoqueue = Gst.ElementFactory.make("queue", "videoqueue") bin.add(videoqueue) - videocodec = gst.element_factory_make("theoraenc", "videocodec") + videocodec = Gst.ElementFactory.make("theoraenc", "videocodec") bin.add(videocodec) - videopad = videoqueue.get_pad("sink") - video_ghostpad = gst.GhostPad("videosink", videopad) + videopad = videoqueue.get_static_pad("sink") + video_ghostpad = Gst.GhostPad.new("videosink", videopad) bin.add_pad(video_ghostpad) videoqueue.link(videocodec) @@ -141,10 +141,10 @@ def set_metadata(self, data): Populate global tag list variable with file metadata for vorbistag audio element ''' - self.tags = gst.TagList() + self.tags = Gst.TagList() for tag in data.keys(): - if(gst.tag_exists(tag)): + if(Gst.tag_exists(tag)): self.tags[tag] = data[tag] else: #self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") diff --git a/src/freeseer/plugins/output/ogg_output/__init__.py b/src/freeseer/plugins/output/ogg_output/__init__.py index 3b6b8fe0..dc9919ce 100644 --- a/src/freeseer/plugins/output/ogg_output/__init__.py +++ b/src/freeseer/plugins/output/ogg_output/__init__.py @@ -33,9 +33,9 @@ import ConfigParser # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt from PyQt4.QtCore import SIGNAL @@ -61,7 +61,7 @@ class OggOutput(IOutput): video_bitrate = 2400 def get_output_bin(self, audio=True, video=True, metadata=None): - bin = gst.Bin() + bin = Gst.Bin() if metadata is not None: self.set_metadata(metadata) @@ -69,11 +69,11 @@ def get_output_bin(self, audio=True, video=True, metadata=None): self.generate_xml_metadata(metadata).write(self.location + ".xml") # Muxer - muxer = gst.element_factory_make("oggmux", "muxer") + muxer = Gst.ElementFactory.make("oggmux", "muxer") bin.add(muxer) # File sink - filesink = gst.element_factory_make('filesink', 'filesink') + filesink = Gst.ElementFactory.make('filesink', 'filesink') filesink.set_property('location', self.location) bin.add(filesink) @@ -81,24 +81,24 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Audio Pipeline if Audio Recording is Enabled # if audio: - audioqueue = gst.element_factory_make("queue", "audioqueue") + audioqueue = Gst.ElementFactory.make("queue", "audioqueue") bin.add(audioqueue) - audioconvert = gst.element_factory_make("audioconvert", "audioconvert") + audioconvert = Gst.ElementFactory.make("audioconvert", "audioconvert") bin.add(audioconvert) - audiolevel = gst.element_factory_make('level', 'audiolevel') + audiolevel = Gst.ElementFactory.make('level', 'audiolevel') audiolevel.set_property('interval', 20000000) bin.add(audiolevel) - audiocodec = gst.element_factory_make("vorbisenc", "audiocodec") + audiocodec = Gst.ElementFactory.make("vorbisenc", "audiocodec") audiocodec.set_property("quality", float(self.audio_quality)) bin.add(audiocodec) # Setup metadata - vorbistag = gst.element_factory_make("vorbistag", "vorbistag") + vorbistag = Gst.ElementFactory.make("vorbistag", "vorbistag") # set tag merge mode to GST_TAG_MERGE_REPLACE - merge_mode = gst.TagMergeMode.__enum_values__[2] + merge_mode = Gst.TagMergeMode.__enum_values__[2] if metadata is not None: # Only set tag if metadata is set @@ -107,8 +107,8 @@ def get_output_bin(self, audio=True, video=True, metadata=None): bin.add(vorbistag) # Setup ghost pads - audiopad = audioqueue.get_pad("sink") - audio_ghostpad = gst.GhostPad("audiosink", audiopad) + audiopad = audioqueue.get_static_pad("sink") + audio_ghostpad = Gst.GhostPad.new("audiosink", audiopad) bin.add_pad(audio_ghostpad) # Link Elements @@ -122,16 +122,16 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Video Pipeline # if video: - videoqueue = gst.element_factory_make("queue", "videoqueue") + videoqueue = Gst.ElementFactory.make("queue", "videoqueue") bin.add(videoqueue) - videocodec = gst.element_factory_make("theoraenc", "videocodec") + videocodec = Gst.ElementFactory.make("theoraenc", "videocodec") videocodec.set_property("bitrate", int(self.video_bitrate)) bin.add(videocodec) # Setup ghost pads - videopad = videoqueue.get_pad("sink") - video_ghostpad = gst.GhostPad("videosink", videopad) + videopad = videoqueue.get_static_pad("sink") + video_ghostpad = Gst.GhostPad.new("videosink", videopad) bin.add_pad(video_ghostpad) # Link Elements @@ -150,11 +150,13 @@ def set_metadata(self, data): Populate global tag list variable with file metadata for vorbistag audio element ''' - self.tags = gst.TagList() + self.tags = Gst.TagList() for tag in data.keys(): - if(gst.tag_exists(tag)): - self.tags[tag] = data[tag] + if(Gst.tag_exists(tag)): + #self.tags[tag] = data[tag] + #Tag stuff seems broken, commenting out for now. Nick + print "I should be tagging meta data" else: #self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") pass diff --git a/src/freeseer/plugins/output/rtmp_streaming/__init__.py b/src/freeseer/plugins/output/rtmp_streaming/__init__.py index 543fadd4..4d3369b7 100644 --- a/src/freeseer/plugins/output/rtmp_streaming/__init__.py +++ b/src/freeseer/plugins/output/rtmp_streaming/__init__.py @@ -85,9 +85,9 @@ import webbrowser # GStreamer libs -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # Qt libs from PyQt4 import QtGui, QtCore @@ -161,17 +161,17 @@ class RTMPOutput(IOutput): # Streams flv content to [self.url] # TODO - Error handling - verify pad setup def get_output_bin(self, audio=True, video=True, metadata=None): - bin = gst.Bin() + bin = Gst.Bin() if metadata is not None: self.set_metadata(metadata) # Muxer - muxer = gst.element_factory_make("flvmux", "muxer") + muxer = Gst.ElementFactory.make("flvmux", "muxer") # Setup metadata # set tag merge mode to GST_TAG_MERGE_REPLACE - merge_mode = gst.TagMergeMode.__enum_values__[2] + merge_mode = Gst.TagMergeMode.__enum_values__[2] if metadata is not None: # Only set tag if metadata is set @@ -184,7 +184,7 @@ def get_output_bin(self, audio=True, video=True, metadata=None): audio_codec = self.audio_codec # RTMP sink - rtmpsink = gst.element_factory_make('rtmpsink', 'rtmpsink') + rtmpsink = Gst.ElementFactory.make('rtmpsink', 'rtmpsink') rtmpsink.set_property('location', url) bin.add(rtmpsink) @@ -192,17 +192,17 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Audio Pipeline if Audio Recording is Enabled # if audio: - audioqueue = gst.element_factory_make("queue", "audioqueue") + audioqueue = Gst.ElementFactory.make("queue", "audioqueue") bin.add(audioqueue) - audioconvert = gst.element_factory_make("audioconvert", "audioconvert") + audioconvert = Gst.ElementFactory.make("audioconvert", "audioconvert") bin.add(audioconvert) - audiolevel = gst.element_factory_make('level', 'audiolevel') + audiolevel = Gst.ElementFactory.make('level', 'audiolevel') audiolevel.set_property('interval', 20000000) bin.add(audiolevel) - audiocodec = gst.element_factory_make(audio_codec, "audiocodec") + audiocodec = Gst.ElementFactory.make(audio_codec, "audiocodec") if 'quality' in audiocodec.get_property_names(): audiocodec.set_property("quality", int(self.audio_quality)) @@ -212,8 +212,8 @@ def get_output_bin(self, audio=True, video=True, metadata=None): bin.add(audiocodec) # Setup ghost pads - audiopad = audioqueue.get_pad("sink") - audio_ghostpad = gst.GhostPad("audiosink", audiopad) + audiopad = audioqueue.get_static_pad("sink") + audio_ghostpad = Gst.GhostPad.new("audiosink", audiopad) bin.add_pad(audio_ghostpad) # Link Elements @@ -226,18 +226,18 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Video Pipeline # if video: - videoqueue = gst.element_factory_make("queue", "videoqueue") + videoqueue = Gst.ElementFactory.make("queue", "videoqueue") bin.add(videoqueue) - videocodec = gst.element_factory_make("x264enc", "videocodec") + videocodec = Gst.ElementFactory.make("x264enc", "videocodec") videocodec.set_property("bitrate", int(self.video_bitrate)) if self.video_tune != 'none': videocodec.set_property('tune', self.video_tune) bin.add(videocodec) # Setup ghost pads - videopad = videoqueue.get_pad("sink") - video_ghostpad = gst.GhostPad("videosink", videopad) + videopad = videoqueue.get_static_pad("sink") + video_ghostpad = Gst.GhostPad.new("videosink", videopad) bin.add_pad(video_ghostpad) # Link Elements @@ -270,10 +270,10 @@ def set_metadata(self, data): Populate global tag list variable with file metadata for vorbistag audio element ''' - self.tags = gst.TagList() + self.tags = Gst.TagList() for tag in data.keys(): - if(gst.tag_exists(tag)): + if(Gst.tag_exists(tag)): self.tags[tag] = data[tag] else: #self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") diff --git a/src/freeseer/plugins/output/videopreview/__init__.py b/src/freeseer/plugins/output/videopreview/__init__.py index 09965344..1095c125 100644 --- a/src/freeseer/plugins/output/videopreview/__init__.py +++ b/src/freeseer/plugins/output/videopreview/__init__.py @@ -33,9 +33,9 @@ import ConfigParser # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQT from PyQt4.QtCore import SIGNAL @@ -61,22 +61,22 @@ class VideoPreview(IOutput): LEAKY_VALUES = ["no", "upstream", "downstream"] def get_output_bin(self, audio=False, video=True, metadata=None): - bin = gst.Bin() + bin = Gst.Bin() # Leaky queue necessary to work with rtmp streaming - videoqueue = gst.element_factory_make("queue", "videoqueue") + videoqueue = Gst.ElementFactory.make("queue", "videoqueue") videoqueue.set_property("leaky", self.leakyqueue) bin.add(videoqueue) - cspace = gst.element_factory_make("ffmpegcolorspace", "cspace") + cspace = Gst.ElementFactory.make("videoconvert", "cspace") bin.add(cspace) - videosink = gst.element_factory_make(self.previewsink, "videosink") + videosink = Gst.ElementFactory.make(self.previewsink, "videosink") bin.add(videosink) # Setup ghost pad - pad = videoqueue.get_pad("sink") - ghostpad = gst.GhostPad("sink", pad) + pad = videoqueue.get_static_pad("sink") + ghostpad = Gst.GhostPad.new("sink", pad) bin.add_pad(ghostpad) # Link Elements diff --git a/src/freeseer/plugins/output/webm_output/__init__.py b/src/freeseer/plugins/output/webm_output/__init__.py index 63e0b847..60929393 100644 --- a/src/freeseer/plugins/output/webm_output/__init__.py +++ b/src/freeseer/plugins/output/webm_output/__init__.py @@ -30,9 +30,9 @@ ''' # GStreamer -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # Freeseer from freeseer.framework.plugin import IOutput @@ -47,16 +47,16 @@ class WebMOutput(IOutput): tags = None def get_output_bin(self, audio=True, video=True, metadata=None): - bin = gst.Bin() + bin = Gst.Bin() if metadata is not None: self.set_metadata(metadata) # Muxer - muxer = gst.element_factory_make("webmmux", "muxer") + muxer = Gst.ElementFactory.make("webmmux", "muxer") bin.add(muxer) - filesink = gst.element_factory_make('filesink', 'filesink') + filesink = Gst.ElementFactory.make('filesink', 'filesink') filesink.set_property('location', self.location) bin.add(filesink) @@ -64,23 +64,23 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Audio Pipeline # if audio: - audioqueue = gst.element_factory_make("queue", "audioqueue") + audioqueue = Gst.ElementFactory.make("queue", "audioqueue") bin.add(audioqueue) - audioconvert = gst.element_factory_make("audioconvert", "audioconvert") + audioconvert = Gst.ElementFactory.make("audioconvert", "audioconvert") bin.add(audioconvert) - audiolevel = gst.element_factory_make('level', 'audiolevel') + audiolevel = Gst.ElementFactory.make('level', 'audiolevel') audiolevel.set_property('interval', 20000000) bin.add(audiolevel) - audiocodec = gst.element_factory_make("vorbisenc", "audiocodec") + audiocodec = Gst.ElementFactory.make("vorbisenc", "audiocodec") bin.add(audiocodec) # Setup metadata - vorbistag = gst.element_factory_make("vorbistag", "vorbistag") + vorbistag = Gst.ElementFactory.make("vorbistag", "vorbistag") # set tag merge mode to GST_TAG_MERGE_REPLACE - merge_mode = gst.TagMergeMode.__enum_values__[2] + merge_mode = Gst.TagMergeMode.__enum_values__[2] if metadata is not None: # Only set tag if metadata is set @@ -89,8 +89,8 @@ def get_output_bin(self, audio=True, video=True, metadata=None): bin.add(vorbistag) # Setup ghost pads - audiopad = audioqueue.get_pad("sink") - audio_ghostpad = gst.GhostPad("audiosink", audiopad) + audiopad = audioqueue.get_static_pad("sink") + audio_ghostpad = Gst.GhostPad.new("audiosink", audiopad) bin.add_pad(audio_ghostpad) # Link Elements @@ -104,14 +104,14 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Video Pipeline # if video: - videoqueue = gst.element_factory_make("queue", "videoqueue") + videoqueue = Gst.ElementFactory.make("queue", "videoqueue") bin.add(videoqueue) - videocodec = gst.element_factory_make("vp8enc", "videocodec") + videocodec = Gst.ElementFactory.make("vp8enc", "videocodec") bin.add(videocodec) - videopad = videoqueue.get_pad("sink") - video_ghostpad = gst.GhostPad("videosink", videopad) + videopad = videoqueue.get_static_pad("sink") + video_ghostpad = Gst.GhostPad.new("videosink", videopad) bin.add_pad(video_ghostpad) # Link Elements @@ -130,10 +130,10 @@ def set_metadata(self, data): Populate global tag list variable with file metadata for vorbistag audio element ''' - self.tags = gst.TagList() + self.tags = Gst.TagList() for tag in data.keys(): - if(gst.tag_exists(tag)): + if(Gst.tag_exists(tag)): self.tags[tag] = data[tag] else: #self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") diff --git a/src/freeseer/plugins/videoinput/desktop/__init__.py b/src/freeseer/plugins/videoinput/desktop/__init__.py index af2267a8..cf512d17 100644 --- a/src/freeseer/plugins/videoinput/desktop/__init__.py +++ b/src/freeseer/plugins/videoinput/desktop/__init__.py @@ -34,9 +34,9 @@ import sys # GStreamer modules -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt4 modules from PyQt4.QtCore import SIGNAL @@ -71,11 +71,11 @@ def get_videoinput_bin(self): """ Return the video input object in gstreamer bin format. """ - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. videosrc = None if sys.platform.startswith("linux"): - videosrc = gst.element_factory_make("ximagesrc", "videosrc") + videosrc = Gst.ElementFactory.make("ximagesrc", "videosrc") # Configure coordinates if we're not recording full desktop if self.desktop == "Area": @@ -89,7 +89,10 @@ def get_videoinput_bin(self): videosrc.set_property("xname", self.window) elif sys.platform in ["win32", "cygwin"]: - videosrc = gst.element_factory_make("dx9screencapsrc", "videosrc") + #videosrc = Gst.ElementFactory.make("dx9screencapsrc", "videosrc") + #This is being replaced with the test source as dx9screencaosrc has not been + #ported to GStreamer 1.0.5 + videosrc = Gst.ElementFactory.make("videotestsrc", "videosrc") # Configure coordinates if we're not recording full desktop if self.desktop == "Area": @@ -101,13 +104,13 @@ def get_videoinput_bin(self): bin.add(videosrc) - colorspace = gst.element_factory_make("ffmpegcolorspace", "colorspace") + colorspace = Gst.ElementFactory.make("videoconvert", "colorspace") bin.add(colorspace) videosrc.link(colorspace) # Setup ghost pad - pad = colorspace.get_pad("src") - ghostpad = gst.GhostPad("videosrc", pad) + pad = colorspace.get_static_pad("src") + ghostpad = Gst.GhostPad.new("videosrc", pad) bin.add_pad(ghostpad) return bin diff --git a/src/freeseer/plugins/videoinput/firewiresrc/__init__.py b/src/freeseer/plugins/videoinput/firewiresrc/__init__.py index cd639412..156677ae 100644 --- a/src/freeseer/plugins/videoinput/firewiresrc/__init__.py +++ b/src/freeseer/plugins/videoinput/firewiresrc/__init__.py @@ -34,9 +34,9 @@ import os # GStreamer modules -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt4 modules from PyQt4.QtCore import SIGNAL @@ -70,13 +70,13 @@ def __init__(self): devpath = path + str(i) def get_videoinput_bin(self): - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - videosrc = gst.element_factory_make("dv1394src", "videosrc") - dv1394q1 = gst.element_factory_make('queue', 'dv1394q1') - dv1394dvdemux = gst.element_factory_make('dvdemux', 'dv1394dvdemux') - dv1394q2 = gst.element_factory_make('queue', 'dv1394q2') - dv1394dvdec = gst.element_factory_make('dvdec', 'dv1394dvdec') + videosrc = Gst.ElementFactory.make("dv1394src", "videosrc") + dv1394q1 = Gst.ElementFactory.make('queue', 'dv1394q1') + dv1394dvdemux = Gst.ElementFactory.make('dvdemux', 'dv1394dvdemux') + dv1394q2 = Gst.ElementFactory.make('queue', 'dv1394q2') + dv1394dvdec = Gst.ElementFactory.make('dvdec', 'dv1394dvdec') # Add Elements bin.add(videosrc) @@ -92,8 +92,8 @@ def get_videoinput_bin(self): dv1394q2.link(dv1394dvdec) # Setup ghost pad - pad = dv1394dvdec.get_pad("src") - ghostpad = gst.GhostPad("videosrc", pad) + pad = dv1394dvdec.get_static_pad("src") + ghostpad = Gst.GhostPad.new("videosrc", pad) bin.add_pad(ghostpad) return bin diff --git a/src/freeseer/plugins/videoinput/usbsrc/__init__.py b/src/freeseer/plugins/videoinput/usbsrc/__init__.py index 30aeae18..51ed8d0e 100644 --- a/src/freeseer/plugins/videoinput/usbsrc/__init__.py +++ b/src/freeseer/plugins/videoinput/usbsrc/__init__.py @@ -36,9 +36,9 @@ import sys # GStreamer modules -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt modules from PyQt4.QtCore import SIGNAL @@ -67,24 +67,24 @@ def get_videoinput_bin(self): """ Return the video input object in gstreamer bin format. """ - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. videosrc = None if sys.platform.startswith("linux"): - videosrc = gst.element_factory_make("v4l2src", "videosrc") + videosrc = Gst.ElementFactory.make("v4l2src", "videosrc") videosrc.set_property("device", self.device) elif sys.platform in ["win32", "cygwin"]: - videosrc = gst.element_factory_make("dshowvideosrc", "videosrc") + videosrc = Gst.ElementFactory.make("dshowvideosrc", "videosrc") videosrc.set_property("device-name", self.device) bin.add(videosrc) - colorspace = gst.element_factory_make("ffmpegcolorspace", "colorspace") + colorspace = Gst.ElementFactory.make("ffmpegcolorspace", "colorspace") bin.add(colorspace) videosrc.link(colorspace) # Setup ghost pad - pad = colorspace.get_pad("src") - ghostpad = gst.GhostPad("videosrc", pad) + pad = colorspace.get_static_pad("src") + ghostpad = Gst.GhostPad.new("videosrc", pad) bin.add_pad(ghostpad) return bin @@ -149,12 +149,14 @@ def get_devices(self): devicemap[videosrc.get_property('device-name')] = device elif sys.platform in ["win32", "cygwin"]: - videosrc = gst.element_factory_make("dshowvideosrc", "videosrc") - videosrc.probe_property_name('device-name') - devices = videosrc.probe_get_values_name('device-name') - - for device in devices: - devicemap[device] = device + #videosrc = gst.element_factory_make("dshowvideosrc", "videosrc") + #Video source has to be test source as dshowvideosrc is not implemented + videosrc = Gst.ElementFactory.make('videotestsrc', "videosrc") + #videosrc.probe_property_name('device-name') + #devices = videosrc.probe_get_values_name('device-name') + + #for device in devices: + # devicemap[device] = device return devicemap diff --git a/src/freeseer/plugins/videoinput/usbsrc/plugin.py b/src/freeseer/plugins/videoinput/usbsrc/plugin.py new file mode 100644 index 00000000..378715d3 --- /dev/null +++ b/src/freeseer/plugins/videoinput/usbsrc/plugin.py @@ -0,0 +1,515 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# freeseer - vga/presentation capture software +# +# Copyright (C) 2011, 2013 Free and Open Source Software Learning Centre +# http://fosslc.org +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# For support, questions, suggestions or any other inquiries, visit: +# http://wiki.github.com/Freeseer/freeseer/ + +import ConfigParser +import logging +import os +import sys + +import xml.etree.ElementTree as ET + +from yapsy.PluginManager import PluginManagerSingleton +from yapsy.ConfigurablePluginManager import ConfigurablePluginManager +from yapsy.IPlugin import IPlugin +from PyQt4 import QtCore + +log = logging.getLogger(__name__) + + +class PluginManager(QtCore.QObject): + ''' + Plugin Manager for Freeseer + + Provides the core functionality which enables plugin support in. + ''' + + def __init__(self, configdir, profile=None): + QtCore.QObject.__init__(self) + + self.firstrun = False + PluginManagerSingleton.setBehaviour([ConfigurablePluginManager]) + self.plugmanc = PluginManagerSingleton.get() + locator = self.plugmanc.getPluginLocator() + locator.setPluginInfoExtension("freeseer-plugin") + + self.configdir = configdir + + if profile: + # Use profile if specified + self.configfile = os.path.abspath(os.path.join(self.configdir, "profiles", profile, "plugin.conf")) + else: + self.configfile = os.path.abspath(os.path.join(self.configdir, "plugin.conf")) + + self.config = ConfigParser.ConfigParser() + self.load() + self.plugmanc.setConfigParser(self.config, self.save) + + # Get the path where the installed plugins are located on systems where + # freeseer is installed. + pluginpath = "%s/../plugins" % os.path.dirname(os.path.abspath(__file__)) + + self.plugmanc.setPluginPlaces([pluginpath, + os.path.expanduser("~/.freeseer/plugins"), + "freeseer/plugins"]) + self.plugmanc.setCategoriesFilter({ + "AudioInput": IAudioInput, + "AudioMixer": IAudioMixer, + "VideoInput": IVideoInput, + "VideoMixer": IVideoMixer, + "Output": IOutput}) + self.plugmanc.collectPlugins() + + # If config was corrupt or did not exist, reset default plugins. + if self.firstrun: + self.set_default_plugins() + + for plugin in self.plugmanc.getAllPlugins(): + plugin.plugin_object.set_plugman(self) + + log.debug("Plugin manager initialized.") + + def __call__(self): + pass + + def load(self): + try: + self.config.readfp(open(self.configfile)) + # Config file does not exist, create a default + except IOError: + log.debug("First run scenario detected. Creating new configuration files.") + self.firstrun = True # If config was corrupt or did not exist, reset defaults. + self.save() + return + + def save(self): + with open(self.configfile, 'w') as configfile: + self.config.write(configfile) + + def set_default_plugins(self): + """ + Default the passthrough mixers and ogg output plugins. + """ + self.set_plugin_option("AudioMixer", "Audio Passthrough-0", "Audio Input", "Audio Test Source") + self.set_plugin_option("VideoMixer", "Video Passthrough-0", "Video Input", "Video Test Source") + self.save() + log.info("Default plugins enabled.") + + def get_plugin_option(self, category, name, option): + """ + Returns the value stored in the config for a plugin option + + Parameters: + category - category to check + name - name of the plugin + option - plugin option to retrieve + Returns: + value of plugin option + """ + return self.plugmanc.readOptionFromPlugin(category, name, option) + + def set_plugin_option(self, category, name, option, value): + """ + Stores a value to the config for a plugin option + + Parameters: + category - category to check + name - name of the plugin + option - plugin option to retrieve + value - value to store + Returns: + none + """ + self.plugmanc.registerOptionFromPlugin(category, name, option, value) + + ## + ## Functions related to getting plugins supported by user's OS + ## + + def _os_supported(self, plugin): + """ + Determines if the user's OS as detected by sys.platform is supported by + the plugin. + + Parameters: plugin - a plugin object + Returns: true/false + """ + return sys.platform in plugin.plugin_object.get_supported_os() + + def _get_supported_plugins(self, unfiltered_plugins): + """ + Returns a list of plugins supported by the users OS as detected by + python's sys.platform library. + + Parameters: + unfiltered plugins - list of plugins to filter + Returns: + list of supported plugins + """ + plugins = [] + + for plugin in unfiltered_plugins: + if self._os_supported(plugin): + plugins.append(plugin) + + return plugins + + def get_plugin_by_name(self, name, category): + """ + Takes a name & category and returns the plugin with that name. + + Parameters: + name - name of the plugin + category - category to search + Returns: + plugin + """ + return self.plugmanc.getPluginByName(name, category) + + def get_all_plugins(self): + """ + Returns a list of all plugins supported by the users OS as detected by + python's sys.platform library. + + Parameters: + none + Returns: + list of all supported plugins + """ + unfiltered_plugins = self.plugmanc.getAllPlugins() + return self._get_supported_plugins(unfiltered_plugins) + + def get_plugins_of_category(self, category): + """ + Returns a list of all plugins in category supported by the users OS as + detected by python's sys.platform library. + + Parameters: + none + Returns: + list of all supported plugins + """ + unfiltered_plugins = self.plugmanc.getPluginsOfCategory(category) + return self._get_supported_plugins(unfiltered_plugins) + + def get_audioinput_plugins(self): + """ + Returns a list of plugins that are supported by the users OS as + detected by python's sys.platform library. + + Parameters: + none + Returns: + list of supported AudioInput plugins + """ + unfiltered_plugins = self.plugmanc.getPluginsOfCategory("AudioInput") + return self._get_supported_plugins(unfiltered_plugins) + + def get_audiomixer_plugins(self): + """ + Returns a list of plugins that are supported by the users OS as + detected by python's sys.platform library. + + Parameters: + none + Returns: + list of supported AudioMixer plugins + """ + unfiltered_plugins = self.plugmanc.getPluginsOfCategory("AudioMixer") + return self._get_supported_plugins(unfiltered_plugins) + + def get_videoinput_plugins(self): + """ + Returns a list of plugins that are supported by the users OS as + detected by python's sys.platform library. + + Parameters: + none + Returns: + list of supported VideoInput plugins + """ + unfiltered_plugins = self.plugmanc.getPluginsOfCategory("VideoInput") + return self._get_supported_plugins(unfiltered_plugins) + + def get_videomixer_plugins(self): + """ + Returns a list of plugins that are supported by the users OS as + detected by python's sys.platform library. + + Parameters: + none + Returns: + list of supported VideoMixer plugins + """ + unfiltered_plugins = self.plugmanc.getPluginsOfCategory("VideoMixer") + return self._get_supported_plugins(unfiltered_plugins) + + def get_output_plugins(self): + """ + Returns a list of plugins that are supported by the users OS as + detected by python's sys.platform library. + + Parameters: + none + Returns: + list of supported Output plugins + """ + unfiltered_plugins = self.plugmanc.getPluginsOfCategory("Output") + return self._get_supported_plugins(unfiltered_plugins) + + +class IBackendPlugin(IPlugin): + instance = 0 + name = None + widget = None + CATEGORY = "Undefined" + + # list of supported OSes per: + # http://docs.python.org/2/library/sys.html#sys.platform + os = [] + + config_loaded = False + + def __init__(self): + IPlugin.__init__(self) + + def get_name(self): + return self.name + + def get_supported_os(self): + """ + Returns a list of OSes supported by the plugin + """ + return self.os + + def get_config_name(self): + return "%s-%s" % (self.name, self.instance) + + def load_config(self, plugman): + pass + + def set_plugman(self, plugman): + self.plugman = plugman + + def set_instance(self, instance=0): + self.instance = instance + + def set_gui(self, gui): + self.gui = gui + + def get_dialog(self): + widget = self.get_widget() + self.retranslate() # Translate the UI + + # Only load configuration the first time the user opens widget + if not self.config_loaded: + log.debug(self.name + " loading configuration into widget.") + self.config_loaded = True + self.widget_load_config(self.plugman) + + if widget is not None: + self.gui.show_plugin_widget_dialog(widget) + + def get_widget(self): + """ + Implement this method to return the settings widget (Qt based). + Used by Freeseer configtool + """ + return None + + def __enable_connections(self): + """ + Implement this method to setup Qt SIGNALs/SLOTS. + + This should be enabled after loading the widget config. + """ + pass + + def widget_load_config(self, plugman): + """ + Implement this when using a plugin widget. This function should be used + to load any required configurations for the plugin widget. + """ + pass + + def retranslate(self): + """Implement this function to allow translation of UI components in the widget""" + pass + + +class IAudioInput(IBackendPlugin): + CATEGORY = "AudioInput" + + def __init__(self): + IBackendPlugin.__init__(self) + + def get_audioinput_bin(self): + raise NotImplementedError + + +class IAudioMixer(IBackendPlugin): + CATEGORY = "AudioMixer" + + def __init__(self): + IBackendPlugin.__init__(self) + + def get_audiomixer_bin(self): + raise NotImplementedError + + def get_inputs(self): + """ + Returns a list of tuples containing the input name and instance number that the audio mixer needs + in order to initialize it's pipelines. + + This should be used so that the code that calls it can + gather the required inputs before calling load_inputs(). + """ + raise NotImplementedError + + def load_inputs(self, player, mixer, inputs): + """ + This method is responsible for loading the inputs needed + by the mixer. + """ + raise NotImplementedError + + +class IVideoInput(IBackendPlugin): + CATEGORY = "VideoInput" + + def __init__(self): + IBackendPlugin.__init__(self) + + def get_videoinput_bin(self): + """ + Returns the Gstreamer Bin for the video input plugin. + MUST be overridded when creating a video input plugin. + """ + raise NotImplementedError + + +class IVideoMixer(IBackendPlugin): + CATEGORY = "VideoMixer" + + def __init__(self): + IBackendPlugin.__init__(self) + + def get_videomixer_bin(self): + """ + Returns the Gstreamer Bin for the video mixer plugin. + MUST be overridded when creating a video mixer plugin. + """ + raise NotImplementedError + + def get_inputs(self): + """ + Returns a list of tuples containing the input name and instance number that the video mixer needs + in order to initialize it's pipelines. + + This should be used so that the code that calls it can + gather the required inputs before calling load_inputs(). + """ + raise NotImplementedError + + def load_inputs(self, player, mixer, inputs): + """ + This method is responsible for loading the inputs needed + by the mixer. + """ + raise NotImplementedError + + +class IOutput(IBackendPlugin): + # + # static variables + # + CATEGORY = "Output" + + # recordto + FILE = 0 + STREAM = 1 + OTHER = 2 + + # type + AUDIO = 0 + VIDEO = 1 + BOTH = 2 + + # + # variables + # + recordto = None # recordto: FILE, STREAM, OTHER + type = None # Types: AUDIO, VIDEO, BOTH + extension = None + location = None + + metadata_order = [ + "title", + "artist", + "performer", + "album", + "location", + "date", + "comment"] + + def __init__(self): + IBackendPlugin.__init__(self) + + def get_recordto(self): + return self.recordto + + def get_type(self): + return self.type + + def get_output_bin(self, audio=True, video=True, metadata=None): + """ + Returns the Gstreamer Bin for the output plugin. + MUST be overridded when creating an output plugin. + """ + raise NotImplementedError + + def get_extension(self): + return self.extension + + def set_recording_location(self, location): + self.location = location + + def set_metadata(self, data): + """ + Set the metadata if supported by Output plugin. + """ + pass + + def generate_xml_metadata(self, metadata): + root = ET.Element('metadata') + + for key in self.metadata_order: + node = ET.SubElement(root, key) + node.text = metadata[key] + + return ET.ElementTree(root) + + +class PluginError(Exception): + def __init__(self, message): + self.message = message diff --git a/src/freeseer/plugins/videoinput/videotestsrc/__init__.py b/src/freeseer/plugins/videoinput/videotestsrc/__init__.py index 8f1d8162..5a6465c5 100644 --- a/src/freeseer/plugins/videoinput/videotestsrc/__init__.py +++ b/src/freeseer/plugins/videoinput/videotestsrc/__init__.py @@ -33,9 +33,9 @@ import ConfigParser # GStreamer modules -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt4 modules from PyQt4.QtCore import SIGNAL @@ -61,16 +61,16 @@ class VideoTestSrc(IVideoInput): "chroma-zone-plate", "ball", "smpte100", "bar"] def get_videoinput_bin(self): - bin = gst.Bin() # Do not pass a name so that we can load this input more than once. + bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - videosrc = gst.element_factory_make("videotestsrc", "videosrc") + videosrc = Gst.ElementFactory.make("videotestsrc", "videosrc") videosrc.set_property("pattern", self.pattern) videosrc.set_property("is-live", self.live) bin.add(videosrc) # Setup ghost pad - pad = videosrc.get_pad("src") - ghostpad = gst.GhostPad("videosrc", pad) + pad = videosrc.get_static_pad("src") + ghostpad = Gst.GhostPad.new("videosrc", pad) bin.add_pad(ghostpad) return bin diff --git a/src/freeseer/plugins/videomixer/pip/__init__.py b/src/freeseer/plugins/videomixer/pip/__init__.py index 807a6297..1a1db876 100644 --- a/src/freeseer/plugins/videomixer/pip/__init__.py +++ b/src/freeseer/plugins/videomixer/pip/__init__.py @@ -33,9 +33,9 @@ import ConfigParser # GStreamer modules -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt modules from PyQt4.QtCore import SIGNAL @@ -55,22 +55,22 @@ class PictureInPicture(IVideoMixer): widget = None def get_videomixer_bin(self): - bin = gst.Bin() + bin = Gst.Bin() - videomixer = gst.element_factory_make("videomixer", "videomixer") + videomixer = Gst.ElementFactory.make("videomixer", "videomixer") bin.add(videomixer) - colorspace = gst.element_factory_make("ffmpegcolorspace", "colorspace") + colorspace = Gst.ElementFactory.make("videoconvert", "colorspace") bin.add(colorspace) videomixer.link(colorspace) # Picture-In-Picture - videobox = gst.element_factory_make("videobox", "videobox") + videobox = Gst.ElementFactory.make("videobox", "videobox") bin.add(videobox) videobox.link(videomixer) - videobox2 = gst.element_factory_make("videobox", "videobox2") + videobox2 = Gst.ElementFactory.make("videobox", "videobox2") bin.add(videobox2) videobox2.set_property("alpha", 0.6) @@ -81,16 +81,16 @@ def get_videomixer_bin(self): videobox2.link(videomixer) # Setup ghost pad - sinkpad = videobox.get_pad("sink") - sink_ghostpad = gst.GhostPad("sink_main", sinkpad) + sinkpad = videobox.get_static_pad("sink") + sink_ghostpad = Gst.GhostPad.new("sink_main", sinkpad) bin.add_pad(sink_ghostpad) - pip_sinkpad = videobox2.get_pad("sink") - pip_ghostpad = gst.GhostPad("sink_pip", pip_sinkpad) + pip_sinkpad = videobox2.get_static_pad("sink") + pip_ghostpad = Gst.GhostPad.new("sink_pip", pip_sinkpad) bin.add_pad(pip_ghostpad) - srcpad = colorspace.get_pad("src") - src_ghostpad = gst.GhostPad("src", srcpad) + srcpad = colorspace.get_static_pad("src") + src_ghostpad = Gst.GhostPad.new("src", srcpad) bin.add_pad(src_ghostpad) return bin @@ -104,15 +104,15 @@ def load_inputs(self, player, mixer, inputs): input1 = inputs[0] # Create videoscale element in order to scale to dimensions not supported by camera - mainsrc_scale = gst.element_factory_make("videoscale", "mainsrc_scale") + mainsrc_scale = Gst.ElementFactory.make("videoscale", "mainsrc_scale") # Create ffmpegcolorspace element to convert from what camera supports to rgb - mainsrc_colorspace = gst.element_factory_make("ffmpegcolorspace", "mainsrc_colorspace") + mainsrc_colorspace = Gst.ElementFactory.make("ffmpegcolorspace", "mainsrc_colorspace") # Create capsfilter for limiting to x-raw-rgb pixel video format and setting dimensions - mainsrc_capsfilter = gst.element_factory_make("capsfilter", "mainsrc_capsfilter") + mainsrc_capsfilter = Gst.ElementFactory.make("capsfilter", "mainsrc_capsfilter") mainsrc_capsfilter.set_property('caps', - gst.caps_from_string('video/x-raw-rgb, width=640, height=480')) + Gst.caps_from_string('video/x-raw, format=Y444, width=640, height=480')) mainsrc_elements = [input1, mainsrc_scale, mainsrc_capsfilter, mainsrc_colorspace] @@ -125,19 +125,19 @@ def load_inputs(self, player, mixer, inputs): mainsrc_capsfilter.link(mainsrc_colorspace) # Link colorspace element to sink pad for pixel format conversion - srcpad = mainsrc_colorspace.get_pad("src") - sinkpad = mixer.get_pad("sink_main") + srcpad = mainsrc_colorspace.get_static_pad("src") + sinkpad = mixer.get_static_pad("sink_main") srcpad.link(sinkpad) # Load the secondary source input2 = inputs[1] # Create gst elements as above, but set smaller dimensions - pipsrc_scale = gst.element_factory_make("videoscale", "pipsrc_scale") - pipsrc_colorspace = gst.element_factory_make("ffmpegcolorspace", "pipsrc_colorspace") - pipsrc_capsfilter = gst.element_factory_make("capsfilter", "pipsrc_capsfilter") + pipsrc_scale = Gst.ElementFactory.make("videoscale", "pipsrc_scale") + pipsrc_colorspace = Gst.ElementFactory.make("ffmpegcolorspace", "pipsrc_colorspace") + pipsrc_capsfilter = gst.ElementFactory.make("capsfilter", "pipsrc_capsfilter") pipsrc_capsfilter.set_property('caps', - gst.caps_from_string('video/x-raw-rgb, width=200, height=150')) + Gst.caps_from_string('video/x-raw, format=Y444, width=200, height=150')) pipsrc_elements = [input2, pipsrc_scale, pipsrc_capsfilter, pipsrc_colorspace] @@ -150,8 +150,8 @@ def load_inputs(self, player, mixer, inputs): pipsrc_capsfilter.link(pipsrc_colorspace) # Link colorspace element to sink pad for pixel format conversion - srcpad = pipsrc_colorspace.get_pad("src") - sinkpad = mixer.get_pad("sink_pip") + srcpad = pipsrc_colorspace.get_static_pad("src") + sinkpad = mixer.get_static_pad("sink_pip") srcpad.link(sinkpad) def load_config(self, plugman): diff --git a/src/freeseer/plugins/videomixer/videopassthrough/__init__.py b/src/freeseer/plugins/videomixer/videopassthrough/__init__.py index fe059e73..739d13e1 100644 --- a/src/freeseer/plugins/videomixer/videopassthrough/__init__.py +++ b/src/freeseer/plugins/videomixer/videopassthrough/__init__.py @@ -34,9 +34,9 @@ import ConfigParser # GStreamer modules -import pygst -pygst.require("0.10") -import gst +import gi +gi.require_version('Gst', '1.0') +from gi.repository import GObject, Gst # PyQt modules from PyQt4.QtCore import SIGNAL @@ -55,35 +55,35 @@ class VideoPassthrough(IVideoMixer): widget = None # VideoPassthrough variables - input_type = "video/x-raw-rgb" + input_type = "video/x-raw" framerate = 30 resolution = "NOSCALE" def get_videomixer_bin(self): - bin = gst.Bin() + bin = Gst.Bin() # Video Rate - videorate = gst.element_factory_make("videorate", "videorate") + videorate = Gst.ElementFactory.make("videorate", "videorate") bin.add(videorate) - videorate_cap = gst.element_factory_make("capsfilter", + videorate_cap = Gst.ElementFactory.make("capsfilter", "video_rate_cap") videorate_cap.set_property("caps", - gst.caps_from_string("%s, framerate=%d/1" % (self.input_type, self.framerate))) + Gst.caps_from_string("%s, framerate=%d/1, format=Y444" % (self.input_type, self.framerate))) bin.add(videorate_cap) # --- End Video Rate # Video Scaler (Resolution) - videoscale = gst.element_factory_make("videoscale", "videoscale") + videoscale = Gst.ElementFactory.make("videoscale", "videoscale") bin.add(videoscale) - videoscale_cap = gst.element_factory_make("capsfilter", + videoscale_cap = Gst.ElementFactory.make("capsfilter", "videoscale_cap") if self.resolution != "NOSCALE": videoscale_cap.set_property('caps', - gst.caps_from_string('%s, width=640, height=480' % (self.input_type))) + Gst.caps_from_string('%s, width=640, height=480, format=Y444' % (self.input_type))) bin.add(videoscale_cap) # --- End Video Scaler - colorspace = gst.element_factory_make("ffmpegcolorspace", "colorspace") + colorspace = Gst.ElementFactory.make("videoconvert", "colorspace") bin.add(colorspace) # Link Elements @@ -93,12 +93,12 @@ def get_videomixer_bin(self): videoscale_cap.link(colorspace) # Setup ghost pad - sinkpad = videorate.get_pad("sink") - sink_ghostpad = gst.GhostPad("sink", sinkpad) + sinkpad = videorate.get_static_pad("sink") + sink_ghostpad = Gst.GhostPad.new("sink", sinkpad) bin.add_pad(sink_ghostpad) - srcpad = colorspace.get_pad("src") - src_ghostpad = gst.GhostPad("src", srcpad) + srcpad = colorspace.get_static_pad("src") + src_ghostpad = Gst.GhostPad.new("src", srcpad) bin.add_pad(src_ghostpad) return bin diff --git a/src/freeseer/plugins/videomixer/videopassthrough/widget.py b/src/freeseer/plugins/videomixer/videopassthrough/widget.py index 51d599b7..fc142e82 100644 --- a/src/freeseer/plugins/videomixer/videopassthrough/widget.py +++ b/src/freeseer/plugins/videomixer/videopassthrough/widget.py @@ -67,8 +67,8 @@ def __init__(self, parent=None): self.videocolourLabel = QLabel(self.tr("Colour Format")) self.videocolourComboBox = QComboBox() - self.videocolourComboBox.addItem("video/x-raw-rgb") - self.videocolourComboBox.addItem("video/x-raw-yuv") + self.videocolourComboBox.addItem("video/x-raw") + self.videocolourComboBox.addItem("video/x-raw") self.videocolourComboBox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) layout.addRow(self.videocolourLabel, self.videocolourComboBox) From cd00f990d478adebd53f65dda0ee013f483ad79d Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 5 Nov 2013 14:43:31 -0800 Subject: [PATCH 03/16] Test source now plays and records -In windows anyway, linux is still not tested -I didn't think multimedia.py line 310-318 were being called. So having replaced every single part of the pipe line (and then put them back) this road block came down to the .link_pads call. It caused the pipe to freeze. - I accidently copied plugin.py into the usbsrc last commit, I am deleting in this commit. --- src/freeseer/framework/multimedia.py | 14 +- .../plugins/output/ogg_output/__init__.py | 23 +- .../plugins/output/webm_output/__init__.py | 10 +- .../plugins/videoinput/usbsrc/plugin.py | 515 ------------------ 4 files changed, 28 insertions(+), 534 deletions(-) delete mode 100644 src/freeseer/plugins/videoinput/usbsrc/plugin.py diff --git a/src/freeseer/framework/multimedia.py b/src/freeseer/framework/multimedia.py index 1e9087c3..e1070b91 100644 --- a/src/freeseer/framework/multimedia.py +++ b/src/freeseer/framework/multimedia.py @@ -74,8 +74,8 @@ def __init__(self, config, plugman, window_id=None, audio_feedback=None, cli=Fal bus.connect('sync-message::element', self.on_sync_message) # Initialize Entry Points - self.audio_tee = Gst.ElementFactory.make('tee', 'audio_tee') - self.video_tee = Gst.ElementFactory.make('tee', 'video_tee') + self.audio_tee = Gst.ElementFactory.make('tee', None) + self.video_tee = Gst.ElementFactory.make('tee', None) self.player.add(self.audio_tee) self.player.add(self.video_tee) @@ -117,7 +117,8 @@ def on_sync_message(self, bus, message): imagesink = message.src imagesink.set_property('force-aspect-ratio', True) #imagesink.set_window_handle(int(self.window_id)) - imagesink.set_xwindow_id(int(self.window_id)) + #The window currently will appear outside of FreeSeer + #imagesink.set_xwindow_id(int(self.window_id)) log.debug("Preview loaded into window.") @@ -308,10 +309,13 @@ def load_output_plugins(self, plugins, record_audio, record_video, metadata): self.output_plugins.append(bin) elif type == IOutput.BOTH: self.player.add(bin) + #I think pads can't be linked like this in GST 1.0, Nick if record_audio: - self.audio_tee.link_pads("src%d", bin, "audiosink") + #self.audio_tee.link_pads("src%d", bin, "audiosink") + self.audio_tee.link(bin) if record_video: - self.video_tee.link_pads("src%d", bin, "videosink") + #self.video_tee.link_pads("src%d", bin, "videosink") + self.video_tee.link(bin) self.output_plugins.append(bin) return True diff --git a/src/freeseer/plugins/output/ogg_output/__init__.py b/src/freeseer/plugins/output/ogg_output/__init__.py index dc9919ce..e1f94d0d 100644 --- a/src/freeseer/plugins/output/ogg_output/__init__.py +++ b/src/freeseer/plugins/output/ogg_output/__init__.py @@ -69,11 +69,11 @@ def get_output_bin(self, audio=True, video=True, metadata=None): self.generate_xml_metadata(metadata).write(self.location + ".xml") # Muxer - muxer = Gst.ElementFactory.make("oggmux", "muxer") + muxer = Gst.ElementFactory.make("oggmux", None) bin.add(muxer) # File sink - filesink = Gst.ElementFactory.make('filesink', 'filesink') + filesink = Gst.ElementFactory.make('filesink', None) filesink.set_property('location', self.location) bin.add(filesink) @@ -81,22 +81,22 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Audio Pipeline if Audio Recording is Enabled # if audio: - audioqueue = Gst.ElementFactory.make("queue", "audioqueue") + audioqueue = Gst.ElementFactory.make("queue", None) bin.add(audioqueue) - audioconvert = Gst.ElementFactory.make("audioconvert", "audioconvert") + audioconvert = Gst.ElementFactory.make("audioconvert", None) bin.add(audioconvert) - audiolevel = Gst.ElementFactory.make('level', 'audiolevel') + audiolevel = Gst.ElementFactory.make('level', None) audiolevel.set_property('interval', 20000000) bin.add(audiolevel) - audiocodec = Gst.ElementFactory.make("vorbisenc", "audiocodec") + audiocodec = Gst.ElementFactory.make("vorbisenc", None) audiocodec.set_property("quality", float(self.audio_quality)) bin.add(audiocodec) # Setup metadata - vorbistag = Gst.ElementFactory.make("vorbistag", "vorbistag") + vorbistag = Gst.ElementFactory.make("vorbistag", None) # set tag merge mode to GST_TAG_MERGE_REPLACE merge_mode = Gst.TagMergeMode.__enum_values__[2] @@ -122,16 +122,16 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Video Pipeline # if video: - videoqueue = Gst.ElementFactory.make("queue", "videoqueue") + videoqueue = Gst.ElementFactory.make("queue", None) bin.add(videoqueue) - videocodec = Gst.ElementFactory.make("theoraenc", "videocodec") - videocodec.set_property("bitrate", int(self.video_bitrate)) + videocodec = Gst.ElementFactory.make("theoraenc", None) + #videocodec.set_property("bitrate", int(self.video_bitrate)) bin.add(videocodec) # Setup ghost pads videopad = videoqueue.get_static_pad("sink") - video_ghostpad = Gst.GhostPad.new("videosink", videopad) + video_ghostpad = Gst.GhostPad.new("sink", videopad) bin.add_pad(video_ghostpad) # Link Elements @@ -142,7 +142,6 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Link muxer to filesink # muxer.link(filesink) - return bin def set_metadata(self, data): diff --git a/src/freeseer/plugins/output/webm_output/__init__.py b/src/freeseer/plugins/output/webm_output/__init__.py index 60929393..c0e9150e 100644 --- a/src/freeseer/plugins/output/webm_output/__init__.py +++ b/src/freeseer/plugins/output/webm_output/__init__.py @@ -131,10 +131,16 @@ def set_metadata(self, data): vorbistag audio element ''' self.tags = Gst.TagList() - for tag in data.keys(): if(Gst.tag_exists(tag)): - self.tags[tag] = data[tag] + #self.tags[tag] = data[tag] + #self.tags.add_value(Gst.TagMergeMode.__enum_values__[4], tag, data[tag]) + Gst.TagList_Add_Value() + #Gst.tag_list_add_value() + #print tag + #print data[tag] + #Tag stuff seems broken, commenting out for now. Nick + print "I should be tagging meta data" else: #self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") pass diff --git a/src/freeseer/plugins/videoinput/usbsrc/plugin.py b/src/freeseer/plugins/videoinput/usbsrc/plugin.py deleted file mode 100644 index 378715d3..00000000 --- a/src/freeseer/plugins/videoinput/usbsrc/plugin.py +++ /dev/null @@ -1,515 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# freeseer - vga/presentation capture software -# -# Copyright (C) 2011, 2013 Free and Open Source Software Learning Centre -# http://fosslc.org -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# For support, questions, suggestions or any other inquiries, visit: -# http://wiki.github.com/Freeseer/freeseer/ - -import ConfigParser -import logging -import os -import sys - -import xml.etree.ElementTree as ET - -from yapsy.PluginManager import PluginManagerSingleton -from yapsy.ConfigurablePluginManager import ConfigurablePluginManager -from yapsy.IPlugin import IPlugin -from PyQt4 import QtCore - -log = logging.getLogger(__name__) - - -class PluginManager(QtCore.QObject): - ''' - Plugin Manager for Freeseer - - Provides the core functionality which enables plugin support in. - ''' - - def __init__(self, configdir, profile=None): - QtCore.QObject.__init__(self) - - self.firstrun = False - PluginManagerSingleton.setBehaviour([ConfigurablePluginManager]) - self.plugmanc = PluginManagerSingleton.get() - locator = self.plugmanc.getPluginLocator() - locator.setPluginInfoExtension("freeseer-plugin") - - self.configdir = configdir - - if profile: - # Use profile if specified - self.configfile = os.path.abspath(os.path.join(self.configdir, "profiles", profile, "plugin.conf")) - else: - self.configfile = os.path.abspath(os.path.join(self.configdir, "plugin.conf")) - - self.config = ConfigParser.ConfigParser() - self.load() - self.plugmanc.setConfigParser(self.config, self.save) - - # Get the path where the installed plugins are located on systems where - # freeseer is installed. - pluginpath = "%s/../plugins" % os.path.dirname(os.path.abspath(__file__)) - - self.plugmanc.setPluginPlaces([pluginpath, - os.path.expanduser("~/.freeseer/plugins"), - "freeseer/plugins"]) - self.plugmanc.setCategoriesFilter({ - "AudioInput": IAudioInput, - "AudioMixer": IAudioMixer, - "VideoInput": IVideoInput, - "VideoMixer": IVideoMixer, - "Output": IOutput}) - self.plugmanc.collectPlugins() - - # If config was corrupt or did not exist, reset default plugins. - if self.firstrun: - self.set_default_plugins() - - for plugin in self.plugmanc.getAllPlugins(): - plugin.plugin_object.set_plugman(self) - - log.debug("Plugin manager initialized.") - - def __call__(self): - pass - - def load(self): - try: - self.config.readfp(open(self.configfile)) - # Config file does not exist, create a default - except IOError: - log.debug("First run scenario detected. Creating new configuration files.") - self.firstrun = True # If config was corrupt or did not exist, reset defaults. - self.save() - return - - def save(self): - with open(self.configfile, 'w') as configfile: - self.config.write(configfile) - - def set_default_plugins(self): - """ - Default the passthrough mixers and ogg output plugins. - """ - self.set_plugin_option("AudioMixer", "Audio Passthrough-0", "Audio Input", "Audio Test Source") - self.set_plugin_option("VideoMixer", "Video Passthrough-0", "Video Input", "Video Test Source") - self.save() - log.info("Default plugins enabled.") - - def get_plugin_option(self, category, name, option): - """ - Returns the value stored in the config for a plugin option - - Parameters: - category - category to check - name - name of the plugin - option - plugin option to retrieve - Returns: - value of plugin option - """ - return self.plugmanc.readOptionFromPlugin(category, name, option) - - def set_plugin_option(self, category, name, option, value): - """ - Stores a value to the config for a plugin option - - Parameters: - category - category to check - name - name of the plugin - option - plugin option to retrieve - value - value to store - Returns: - none - """ - self.plugmanc.registerOptionFromPlugin(category, name, option, value) - - ## - ## Functions related to getting plugins supported by user's OS - ## - - def _os_supported(self, plugin): - """ - Determines if the user's OS as detected by sys.platform is supported by - the plugin. - - Parameters: plugin - a plugin object - Returns: true/false - """ - return sys.platform in plugin.plugin_object.get_supported_os() - - def _get_supported_plugins(self, unfiltered_plugins): - """ - Returns a list of plugins supported by the users OS as detected by - python's sys.platform library. - - Parameters: - unfiltered plugins - list of plugins to filter - Returns: - list of supported plugins - """ - plugins = [] - - for plugin in unfiltered_plugins: - if self._os_supported(plugin): - plugins.append(plugin) - - return plugins - - def get_plugin_by_name(self, name, category): - """ - Takes a name & category and returns the plugin with that name. - - Parameters: - name - name of the plugin - category - category to search - Returns: - plugin - """ - return self.plugmanc.getPluginByName(name, category) - - def get_all_plugins(self): - """ - Returns a list of all plugins supported by the users OS as detected by - python's sys.platform library. - - Parameters: - none - Returns: - list of all supported plugins - """ - unfiltered_plugins = self.plugmanc.getAllPlugins() - return self._get_supported_plugins(unfiltered_plugins) - - def get_plugins_of_category(self, category): - """ - Returns a list of all plugins in category supported by the users OS as - detected by python's sys.platform library. - - Parameters: - none - Returns: - list of all supported plugins - """ - unfiltered_plugins = self.plugmanc.getPluginsOfCategory(category) - return self._get_supported_plugins(unfiltered_plugins) - - def get_audioinput_plugins(self): - """ - Returns a list of plugins that are supported by the users OS as - detected by python's sys.platform library. - - Parameters: - none - Returns: - list of supported AudioInput plugins - """ - unfiltered_plugins = self.plugmanc.getPluginsOfCategory("AudioInput") - return self._get_supported_plugins(unfiltered_plugins) - - def get_audiomixer_plugins(self): - """ - Returns a list of plugins that are supported by the users OS as - detected by python's sys.platform library. - - Parameters: - none - Returns: - list of supported AudioMixer plugins - """ - unfiltered_plugins = self.plugmanc.getPluginsOfCategory("AudioMixer") - return self._get_supported_plugins(unfiltered_plugins) - - def get_videoinput_plugins(self): - """ - Returns a list of plugins that are supported by the users OS as - detected by python's sys.platform library. - - Parameters: - none - Returns: - list of supported VideoInput plugins - """ - unfiltered_plugins = self.plugmanc.getPluginsOfCategory("VideoInput") - return self._get_supported_plugins(unfiltered_plugins) - - def get_videomixer_plugins(self): - """ - Returns a list of plugins that are supported by the users OS as - detected by python's sys.platform library. - - Parameters: - none - Returns: - list of supported VideoMixer plugins - """ - unfiltered_plugins = self.plugmanc.getPluginsOfCategory("VideoMixer") - return self._get_supported_plugins(unfiltered_plugins) - - def get_output_plugins(self): - """ - Returns a list of plugins that are supported by the users OS as - detected by python's sys.platform library. - - Parameters: - none - Returns: - list of supported Output plugins - """ - unfiltered_plugins = self.plugmanc.getPluginsOfCategory("Output") - return self._get_supported_plugins(unfiltered_plugins) - - -class IBackendPlugin(IPlugin): - instance = 0 - name = None - widget = None - CATEGORY = "Undefined" - - # list of supported OSes per: - # http://docs.python.org/2/library/sys.html#sys.platform - os = [] - - config_loaded = False - - def __init__(self): - IPlugin.__init__(self) - - def get_name(self): - return self.name - - def get_supported_os(self): - """ - Returns a list of OSes supported by the plugin - """ - return self.os - - def get_config_name(self): - return "%s-%s" % (self.name, self.instance) - - def load_config(self, plugman): - pass - - def set_plugman(self, plugman): - self.plugman = plugman - - def set_instance(self, instance=0): - self.instance = instance - - def set_gui(self, gui): - self.gui = gui - - def get_dialog(self): - widget = self.get_widget() - self.retranslate() # Translate the UI - - # Only load configuration the first time the user opens widget - if not self.config_loaded: - log.debug(self.name + " loading configuration into widget.") - self.config_loaded = True - self.widget_load_config(self.plugman) - - if widget is not None: - self.gui.show_plugin_widget_dialog(widget) - - def get_widget(self): - """ - Implement this method to return the settings widget (Qt based). - Used by Freeseer configtool - """ - return None - - def __enable_connections(self): - """ - Implement this method to setup Qt SIGNALs/SLOTS. - - This should be enabled after loading the widget config. - """ - pass - - def widget_load_config(self, plugman): - """ - Implement this when using a plugin widget. This function should be used - to load any required configurations for the plugin widget. - """ - pass - - def retranslate(self): - """Implement this function to allow translation of UI components in the widget""" - pass - - -class IAudioInput(IBackendPlugin): - CATEGORY = "AudioInput" - - def __init__(self): - IBackendPlugin.__init__(self) - - def get_audioinput_bin(self): - raise NotImplementedError - - -class IAudioMixer(IBackendPlugin): - CATEGORY = "AudioMixer" - - def __init__(self): - IBackendPlugin.__init__(self) - - def get_audiomixer_bin(self): - raise NotImplementedError - - def get_inputs(self): - """ - Returns a list of tuples containing the input name and instance number that the audio mixer needs - in order to initialize it's pipelines. - - This should be used so that the code that calls it can - gather the required inputs before calling load_inputs(). - """ - raise NotImplementedError - - def load_inputs(self, player, mixer, inputs): - """ - This method is responsible for loading the inputs needed - by the mixer. - """ - raise NotImplementedError - - -class IVideoInput(IBackendPlugin): - CATEGORY = "VideoInput" - - def __init__(self): - IBackendPlugin.__init__(self) - - def get_videoinput_bin(self): - """ - Returns the Gstreamer Bin for the video input plugin. - MUST be overridded when creating a video input plugin. - """ - raise NotImplementedError - - -class IVideoMixer(IBackendPlugin): - CATEGORY = "VideoMixer" - - def __init__(self): - IBackendPlugin.__init__(self) - - def get_videomixer_bin(self): - """ - Returns the Gstreamer Bin for the video mixer plugin. - MUST be overridded when creating a video mixer plugin. - """ - raise NotImplementedError - - def get_inputs(self): - """ - Returns a list of tuples containing the input name and instance number that the video mixer needs - in order to initialize it's pipelines. - - This should be used so that the code that calls it can - gather the required inputs before calling load_inputs(). - """ - raise NotImplementedError - - def load_inputs(self, player, mixer, inputs): - """ - This method is responsible for loading the inputs needed - by the mixer. - """ - raise NotImplementedError - - -class IOutput(IBackendPlugin): - # - # static variables - # - CATEGORY = "Output" - - # recordto - FILE = 0 - STREAM = 1 - OTHER = 2 - - # type - AUDIO = 0 - VIDEO = 1 - BOTH = 2 - - # - # variables - # - recordto = None # recordto: FILE, STREAM, OTHER - type = None # Types: AUDIO, VIDEO, BOTH - extension = None - location = None - - metadata_order = [ - "title", - "artist", - "performer", - "album", - "location", - "date", - "comment"] - - def __init__(self): - IBackendPlugin.__init__(self) - - def get_recordto(self): - return self.recordto - - def get_type(self): - return self.type - - def get_output_bin(self, audio=True, video=True, metadata=None): - """ - Returns the Gstreamer Bin for the output plugin. - MUST be overridded when creating an output plugin. - """ - raise NotImplementedError - - def get_extension(self): - return self.extension - - def set_recording_location(self, location): - self.location = location - - def set_metadata(self, data): - """ - Set the metadata if supported by Output plugin. - """ - pass - - def generate_xml_metadata(self, metadata): - root = ET.Element('metadata') - - for key in self.metadata_order: - node = ET.SubElement(root, key) - node.text = metadata[key] - - return ET.ElementTree(root) - - -class PluginError(Exception): - def __init__(self, message): - self.message = message From 263a6218044e84f3f0e87c2500950668a373fe52 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 5 Nov 2013 18:55:38 -0800 Subject: [PATCH 04/16] Audio now "works" - The audio test signal is now combined and recorded to ogg - FYI the name of the source from a tee element has change from "src%d" to "src_%u" - The audio portion now has 2 queues, one on its input and one on its output - All meta tagging is still commented out - Linux is still on the todo list --- src/freeseer/framework/multimedia.py | 7 +-- .../audiomixer/audiopassthrough/__init__.py | 2 - .../plugins/output/ogg_output/__init__.py | 60 +++++++++++-------- .../plugins/videoinput/desktop/__init__.py | 1 + 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/freeseer/framework/multimedia.py b/src/freeseer/framework/multimedia.py index e1070b91..34a43368 100644 --- a/src/freeseer/framework/multimedia.py +++ b/src/freeseer/framework/multimedia.py @@ -309,13 +309,10 @@ def load_output_plugins(self, plugins, record_audio, record_video, metadata): self.output_plugins.append(bin) elif type == IOutput.BOTH: self.player.add(bin) - #I think pads can't be linked like this in GST 1.0, Nick if record_audio: - #self.audio_tee.link_pads("src%d", bin, "audiosink") - self.audio_tee.link(bin) + self.audio_tee.link_pads("src_%u", bin, "audiosink") if record_video: - #self.video_tee.link_pads("src%d", bin, "videosink") - self.video_tee.link(bin) + self.video_tee.link_pads("src_%u", bin, "videosink") self.output_plugins.append(bin) return True diff --git a/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py b/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py index ca4c2492..9b38b6bb 100644 --- a/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py +++ b/src/freeseer/plugins/audiomixer/audiopassthrough/__init__.py @@ -62,8 +62,6 @@ def get_audiomixer_bin(self): # Setup ghost pad sinkpad = audiomixer.get_request_pad("sink_%u") - print "DOOM CHICKEN!!!" - print sinkpad sink_ghostpad = Gst.GhostPad.new("sink", sinkpad) bin.add_pad(sink_ghostpad) diff --git a/src/freeseer/plugins/output/ogg_output/__init__.py b/src/freeseer/plugins/output/ogg_output/__init__.py index e1f94d0d..c4a3a01d 100644 --- a/src/freeseer/plugins/output/ogg_output/__init__.py +++ b/src/freeseer/plugins/output/ogg_output/__init__.py @@ -81,43 +81,50 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Audio Pipeline if Audio Recording is Enabled # if audio: - audioqueue = Gst.ElementFactory.make("queue", None) - bin.add(audioqueue) - + + #Create audio elements + q1 = Gst.ElementFactory.make('queue', None) + enc = Gst.ElementFactory.make('vorbisenc', None) + enc.set_property("quality", float(self.audio_quality)) + q2 = Gst.ElementFactory.make('queue', None) audioconvert = Gst.ElementFactory.make("audioconvert", None) - bin.add(audioconvert) - audiolevel = Gst.ElementFactory.make('level', None) audiolevel.set_property('interval', 20000000) + + + #Add the audio elements to the bin + bin.add(q1) bin.add(audiolevel) + bin.add(audioconvert) + bin.add(enc) + bin.add(q2) - audiocodec = Gst.ElementFactory.make("vorbisenc", None) - audiocodec.set_property("quality", float(self.audio_quality)) - bin.add(audiocodec) + #link the audio elements + q1.link(audiolevel) + audiolevel.link(audioconvert) + audioconvert.link(enc) + enc.link(q2) + q2.link(muxer) - # Setup metadata - vorbistag = Gst.ElementFactory.make("vorbistag", None) - # set tag merge mode to GST_TAG_MERGE_REPLACE - merge_mode = Gst.TagMergeMode.__enum_values__[2] - if metadata is not None: - # Only set tag if metadata is set - vorbistag.merge_tags(self.tags, merge_mode) - vorbistag.set_tag_merge_mode(merge_mode) - bin.add(vorbistag) + #Currently tagging is broken and will need to be moved up in the code + + # # Setup metadata + # #vorbistag = Gst.ElementFactory.make("vorbistag", None) + # # set tag merge mode to GST_TAG_MERGE_REPLACE + # #merge_mode = Gst.TagMergeMode.__enum_values__[2] + + # # if metadata is not None: + # # # Only set tag if metadata is set + # # vorbistag.merge_tags(self.tags, merge_mode) + # # vorbistag.set_tag_merge_mode(merge_mode) + # # bin.add(vorbistag) # Setup ghost pads - audiopad = audioqueue.get_static_pad("sink") + audiopad = q1.get_static_pad("sink") audio_ghostpad = Gst.GhostPad.new("audiosink", audiopad) bin.add_pad(audio_ghostpad) - # Link Elements - audioqueue.link(audioconvert) - audioconvert.link(audiolevel) - audiolevel.link(audiocodec) - audiocodec.link(vorbistag) - vorbistag.link(muxer) - # # Setup Video Pipeline # @@ -126,12 +133,13 @@ def get_output_bin(self, audio=True, video=True, metadata=None): bin.add(videoqueue) videocodec = Gst.ElementFactory.make("theoraenc", None) + #Setting the bit rate like this will cause this plugin not to work, currently #videocodec.set_property("bitrate", int(self.video_bitrate)) bin.add(videocodec) # Setup ghost pads videopad = videoqueue.get_static_pad("sink") - video_ghostpad = Gst.GhostPad.new("sink", videopad) + video_ghostpad = Gst.GhostPad.new("videosink", videopad) bin.add_pad(video_ghostpad) # Link Elements diff --git a/src/freeseer/plugins/videoinput/desktop/__init__.py b/src/freeseer/plugins/videoinput/desktop/__init__.py index cf512d17..2f24e095 100644 --- a/src/freeseer/plugins/videoinput/desktop/__init__.py +++ b/src/freeseer/plugins/videoinput/desktop/__init__.py @@ -93,6 +93,7 @@ def get_videoinput_bin(self): #This is being replaced with the test source as dx9screencaosrc has not been #ported to GStreamer 1.0.5 videosrc = Gst.ElementFactory.make("videotestsrc", "videosrc") + print "test source in place of desktop" # Configure coordinates if we're not recording full desktop if self.desktop == "Area": From e83f10f2d95077a698fe3fdc0cab2d8bb6450f37 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 5 Nov 2013 19:09:54 -0800 Subject: [PATCH 05/16] Autoaudiosource != Windows friendly - Using the auto audio source causes python in Windows to lock up - I've used a system detection guard, if you're in Windows it will just sub in the autiotestsrc -Autoaudiosource is in the current version of GST for Windows so I don't know why it locks up -This has not been tested in Linux --- src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py b/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py index dbfe58e0..ac1c580f 100644 --- a/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py +++ b/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py @@ -43,7 +43,9 @@ class AutoAudioSrc(IAudioInput): def get_audioinput_bin(self): bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. - audiosrc = Gst.ElementFactory.make("autoaudiosrc", "audiosrc") + # audiosrc = Gst.ElementFactory.make("autoaudiosrc", None) + # autoaudiosrc causes python to lock up in Windows + audiosrc = Gst.ElementFactory.make("audiotestsrc", None) bin.add(audiosrc) # Setup ghost pad From ff002f3538e75e7f99431fc4388d8b32a21b908a Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 5 Nov 2013 19:15:18 -0800 Subject: [PATCH 06/16] Autoaudiosource take 2 -I jumped the gun and hadn't saved my changes for the OS guard --- .../plugins/audioinput/autoaudiosrc/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py b/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py index ac1c580f..3d869230 100644 --- a/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py +++ b/src/freeseer/plugins/audioinput/autoaudiosrc/__init__.py @@ -28,6 +28,7 @@ @author: Thanh Ha ''' +import sys import gi gi.require_version('Gst', '1.0') @@ -42,10 +43,14 @@ class AutoAudioSrc(IAudioInput): def get_audioinput_bin(self): bin = Gst.Bin() # Do not pass a name so that we can load this input more than once. + if sys.platform.startswith("linux"): + audiosrc = Gst.ElementFactory.make("autoaudiosrc", None) - # audiosrc = Gst.ElementFactory.make("autoaudiosrc", None) - # autoaudiosrc causes python to lock up in Windows - audiosrc = Gst.ElementFactory.make("audiotestsrc", None) + elif sys.platform in ["win32", "cygwin"]: + # autoaudiosrc causes python to lock up in Windows + audiosrc = Gst.ElementFactory.make("audiotestsrc", None) + + bin.add(audiosrc) # Setup ghost pad From b29e8ccbceb3855b4140b45fdb0eaad655095074 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 5 Nov 2013 19:33:39 -0800 Subject: [PATCH 07/16] WebM not records -The code for creating the audio elements is taken from the Ogg plugin, it was mostly the same anyway. -Not tested on Linux --- .../plugins/output/webm_output/__init__.py | 61 +++++++++++-------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/freeseer/plugins/output/webm_output/__init__.py b/src/freeseer/plugins/output/webm_output/__init__.py index c0e9150e..57357ef5 100644 --- a/src/freeseer/plugins/output/webm_output/__init__.py +++ b/src/freeseer/plugins/output/webm_output/__init__.py @@ -64,41 +64,49 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Setup Audio Pipeline # if audio: - audioqueue = Gst.ElementFactory.make("queue", "audioqueue") - bin.add(audioqueue) - audioconvert = Gst.ElementFactory.make("audioconvert", "audioconvert") - bin.add(audioconvert) - - audiolevel = Gst.ElementFactory.make('level', 'audiolevel') + #Create audio elements + q1 = Gst.ElementFactory.make('queue', None) + enc = Gst.ElementFactory.make('vorbisenc', None) + q2 = Gst.ElementFactory.make('queue', None) + audioconvert = Gst.ElementFactory.make("audioconvert", None) + audiolevel = Gst.ElementFactory.make('level', None) audiolevel.set_property('interval', 20000000) - bin.add(audiolevel) - audiocodec = Gst.ElementFactory.make("vorbisenc", "audiocodec") - bin.add(audiocodec) + #Currently tagging is broken and will need to be moved up in the code - # Setup metadata - vorbistag = Gst.ElementFactory.make("vorbistag", "vorbistag") - # set tag merge mode to GST_TAG_MERGE_REPLACE - merge_mode = Gst.TagMergeMode.__enum_values__[2] + # # Setup metadata + # #vorbistag = Gst.ElementFactory.make("vorbistag", "vorbistag") + # # set tag merge mode to GST_TAG_MERGE_REPLACE + # #merge_mode = Gst.TagMergeMode.__enum_values__[2] - if metadata is not None: - # Only set tag if metadata is set - vorbistag.merge_tags(self.tags, merge_mode) - vorbistag.set_tag_merge_mode(merge_mode) - bin.add(vorbistag) + # #if metadata is not None: + # # Only set tag if metadata is set + # #vorbistag.merge_tags(self.tags, merge_mode) + # #vorbistag.set_tag_merge_mode(merge_mode) + # #bin.add(vorbistag) + + + + #Add the audio elements to the bin + bin.add(q1) + bin.add(audiolevel) + bin.add(audioconvert) + bin.add(enc) + bin.add(q2) + + #link the audio elements + q1.link(audiolevel) + audiolevel.link(audioconvert) + audioconvert.link(enc) + enc.link(q2) + q2.link(muxer) # Setup ghost pads - audiopad = audioqueue.get_static_pad("sink") + audiopad = q1.get_static_pad("sink") audio_ghostpad = Gst.GhostPad.new("audiosink", audiopad) bin.add_pad(audio_ghostpad) - # Link Elements - audioqueue.link(audioconvert) - audioconvert.link(audiolevel) - audiolevel.link(audiocodec) - audiocodec.link(vorbistag) - vorbistag.link(muxer) # # Setup Video Pipeline @@ -133,9 +141,10 @@ def set_metadata(self, data): self.tags = Gst.TagList() for tag in data.keys(): if(Gst.tag_exists(tag)): + #tagging is not currently working #self.tags[tag] = data[tag] #self.tags.add_value(Gst.TagMergeMode.__enum_values__[4], tag, data[tag]) - Gst.TagList_Add_Value() + #Gst.TagList_Add_Value() #Gst.tag_list_add_value() #print tag #print data[tag] From f704c70ebbb1bd9e951216f2d406e2e2754239e2 Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 7 Nov 2013 16:30:40 -0500 Subject: [PATCH 08/16] Linux now works --- src/freeseer/framework/multimedia.py | 10 +++++----- .../plugins/videoinput/usbsrc/__init__.py | 20 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/freeseer/framework/multimedia.py b/src/freeseer/framework/multimedia.py index 34a43368..1d8ff5d5 100644 --- a/src/freeseer/framework/multimedia.py +++ b/src/freeseer/framework/multimedia.py @@ -87,18 +87,18 @@ def __init__(self, config, plugman, window_id=None, audio_feedback=None, cli=Fal def on_message(self, bus, message): t = message.type - if t == Gst.MESSAGE_EOS: + if t == Gst.MessageType.EOS: self.stop() - elif t == Gst.MESSAGE_ERROR: + elif t == Gst.MessageType.ERROR: err, debug = message.parse_error() log.error(str(err) + str(debug)) - elif message.structure is not None: - s = message.structure.get_name() + elif message.get_structure() is not None: + s = message.get_structure().get_name() if s == 'level' and self.audio_feedback_event is not None: - msg = message.structure.to_string() + msg = message.get_structure().get_name().to_string() rms_dB = float(msg.split(',')[6].split('{')[1].rstrip('}')) # This is an inaccurate representation of decibels into percent diff --git a/src/freeseer/plugins/videoinput/usbsrc/__init__.py b/src/freeseer/plugins/videoinput/usbsrc/__init__.py index 51ed8d0e..6d3ec438 100644 --- a/src/freeseer/plugins/videoinput/usbsrc/__init__.py +++ b/src/freeseer/plugins/videoinput/usbsrc/__init__.py @@ -71,14 +71,14 @@ def get_videoinput_bin(self): videosrc = None if sys.platform.startswith("linux"): - videosrc = Gst.ElementFactory.make("v4l2src", "videosrc") - videosrc.set_property("device", self.device) + videosrc = Gst.ElementFactory.make("autovideosrc", "videosrc") + #videosrc.set_property("device", self.device) elif sys.platform in ["win32", "cygwin"]: videosrc = Gst.ElementFactory.make("dshowvideosrc", "videosrc") - videosrc.set_property("device-name", self.device) + #videosrc.set_property("device-name", self.device) bin.add(videosrc) - colorspace = Gst.ElementFactory.make("ffmpegcolorspace", "colorspace") + colorspace = Gst.ElementFactory.make("videoconvert", "colorspace") bin.add(colorspace) videosrc.link(colorspace) @@ -140,13 +140,13 @@ def get_devices(self): devicemap = {} if sys.platform.startswith("linux"): - videosrc = gst.element_factory_make("v4l2src", "videosrc") - videosrc.probe_property_name('device') - devices = videosrc.probe_get_values_name('device') + videosrc = Gst.ElementFactory.make("v4l2src", "videosrc") + #videosrc.probe_property_name('device') + #devices = videosrc.probe_get_values_name('device') - for device in devices: - videosrc.set_property('device', device) - devicemap[videosrc.get_property('device-name')] = device + # for device in devices: + # videosrc.set_property('device', device) + # devicemap[videosrc.get_property('device-name')] = device elif sys.platform in ["win32", "cygwin"]: #videosrc = gst.element_factory_make("dshowvideosrc", "videosrc") From 3f68df030e4b0ca9f9b4ca6f830276995c9b9625 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 8 Nov 2013 18:11:23 -0800 Subject: [PATCH 09/16] PIP Video mixer works, in Windows --- src/freeseer/plugins/videomixer/pip/__init__.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/freeseer/plugins/videomixer/pip/__init__.py b/src/freeseer/plugins/videomixer/pip/__init__.py index 1a1db876..4e022741 100644 --- a/src/freeseer/plugins/videomixer/pip/__init__.py +++ b/src/freeseer/plugins/videomixer/pip/__init__.py @@ -102,22 +102,29 @@ def get_inputs(self): def load_inputs(self, player, mixer, inputs): # Load main source input1 = inputs[0] + player.add(input1) # Create videoscale element in order to scale to dimensions not supported by camera mainsrc_scale = Gst.ElementFactory.make("videoscale", "mainsrc_scale") + player.add(mainsrc_scale) # Create ffmpegcolorspace element to convert from what camera supports to rgb - mainsrc_colorspace = Gst.ElementFactory.make("ffmpegcolorspace", "mainsrc_colorspace") + mainsrc_colorspace = Gst.ElementFactory.make("videoconvert", "mainsrc_colorspace") + player.add(mainsrc_colorspace) # Create capsfilter for limiting to x-raw-rgb pixel video format and setting dimensions mainsrc_capsfilter = Gst.ElementFactory.make("capsfilter", "mainsrc_capsfilter") mainsrc_capsfilter.set_property('caps', Gst.caps_from_string('video/x-raw, format=Y444, width=640, height=480')) + player.add(mainsrc_capsfilter) - mainsrc_elements = [input1, mainsrc_scale, mainsrc_capsfilter, mainsrc_colorspace] + #This lambda function causes errors in Windows. Which makes not sense as the second one + #on line 152 works + + #mainsrc_elements = [input1, mainsrc_scale, mainsrc_capsfilter, mainsrc_colorspace] # Add elements to player in list order - map(lambda element: player.add(element), mainsrc_elements) + #map(lambda element: player.add(element), mainsrc_elements) # Link elements in a specific order input1.link(mainsrc_scale) @@ -134,8 +141,8 @@ def load_inputs(self, player, mixer, inputs): # Create gst elements as above, but set smaller dimensions pipsrc_scale = Gst.ElementFactory.make("videoscale", "pipsrc_scale") - pipsrc_colorspace = Gst.ElementFactory.make("ffmpegcolorspace", "pipsrc_colorspace") - pipsrc_capsfilter = gst.ElementFactory.make("capsfilter", "pipsrc_capsfilter") + pipsrc_colorspace = Gst.ElementFactory.make("videoconvert", "pipsrc_colorspace") + pipsrc_capsfilter = Gst.ElementFactory.make("capsfilter", "pipsrc_capsfilter") pipsrc_capsfilter.set_property('caps', Gst.caps_from_string('video/x-raw, format=Y444, width=200, height=150')) From 60cfc08d01513fda41a33c5e2d5fb0cb90c2a819 Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 14 Nov 2013 12:12:45 -0800 Subject: [PATCH 10/16] Video preview now places the video in the Window - This works in both Linux and Windows --- src/freeseer/framework/multimedia.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/freeseer/framework/multimedia.py b/src/freeseer/framework/multimedia.py index 1d8ff5d5..8284acff 100644 --- a/src/freeseer/framework/multimedia.py +++ b/src/freeseer/framework/multimedia.py @@ -25,17 +25,11 @@ import datetime import logging import os -""" -import gobject -gobject.threads_init() -import pygst -pygst.require("0.10") -import gst -""" -#Comment out for now, Nick +import sys + import gi gi.require_version('Gst', '1.0') -from gi.repository import GObject, Gst +from gi.repository import GObject, Gst, GstVideo GObject.threads_init() Gst.init(None) @@ -116,10 +110,7 @@ def on_sync_message(self, bus, message): if message_name == 'prepare-window-handle' and self.window_id is not None: imagesink = message.src imagesink.set_property('force-aspect-ratio', True) - #imagesink.set_window_handle(int(self.window_id)) - #The window currently will appear outside of FreeSeer - #imagesink.set_xwindow_id(int(self.window_id)) - + imagesink.set_window_handle(int(self.window_id)) log.debug("Preview loaded into window.") def set_window_id(self, window_id): From fa3ad182b7537ff53c53e9e289fdce9c9bbf22a9 Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 14 Nov 2013 13:10:46 -0800 Subject: [PATCH 11/16] Audio test source now works in Linux - The test source can be combined with either the USB or test video source. - The USB source seems to stall on recording for both the audio and the video, it seems like it is buffering somewhere. I do not know if this is an actual problem, or a "feature" of the virtual machine I am running linux in. --- src/freeseer/framework/multimedia.py | 30 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/freeseer/framework/multimedia.py b/src/freeseer/framework/multimedia.py index 8284acff..8c9437d5 100644 --- a/src/freeseer/framework/multimedia.py +++ b/src/freeseer/framework/multimedia.py @@ -79,8 +79,10 @@ def __init__(self, config, plugman, window_id=None, audio_feedback=None, cli=Fal ## GST Player Functions ## def on_message(self, bus, message): + # This mothod never seems to be run in Windows + # print "This message came from on_message" + # print t t = message.type - if t == Gst.MessageType.EOS: self.stop() @@ -90,23 +92,25 @@ def on_message(self, bus, message): elif message.get_structure() is not None: s = message.get_structure().get_name() - if s == 'level' and self.audio_feedback_event is not None: - msg = message.get_structure().get_name().to_string() - rms_dB = float(msg.split(',')[6].split('{')[1].rstrip('}')) - - # This is an inaccurate representation of decibels into percent - # conversion, this code should be revisited. - try: - percent = (int(round(rms_dB)) + 50) * 2 - except OverflowError: - percent = 0 - self.audio_feedback_event(percent) + msg = message.get_structure().get_name() + #This code causes Linux to throw errors + # rms_dB = float(msg.split(',')[6].split('{')[1].rstrip('}')) + + # # This is an inaccurate representation of decibels into percent + # # conversion, this code should be revisited. + # try: + # percent = (int(round(rms_dB)) + 50) * 2 + # except OverflowError: + # percent = 0 + # self.audio_feedback_event(percent) def on_sync_message(self, bus, message): if message.get_structure() is None: return message_name = message.get_structure().get_name() + # print "This message came from on_sync_message" + # print message_name if message_name == 'prepare-window-handle' and self.window_id is not None: imagesink = message.src imagesink.set_property('force-aspect-ratio', True) @@ -364,4 +368,4 @@ def unload_videomixer(self): self.player.remove(plugin) self.videomixer.unlink(self.video_tee) - self.player.remove(self.videomixer) + self.player.remove(self.videomixer) \ No newline at end of file From ed5c277d8696f9ec3c9a92f062a61058ca086e6c Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 18 Nov 2013 15:34:32 -0800 Subject: [PATCH 12/16] Ogg meta tagging works - Currently there is only two types of tag that we are using, gchararrays and one gdate. - Tagging is very different in GST 1.0 than under 0.1. There are no examples I can find of anyone using it in Python yet. - This has been tested in Windows, not Linux yet --- .../plugins/output/ogg_output/__init__.py | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/freeseer/plugins/output/ogg_output/__init__.py b/src/freeseer/plugins/output/ogg_output/__init__.py index c4a3a01d..d3f21551 100644 --- a/src/freeseer/plugins/output/ogg_output/__init__.py +++ b/src/freeseer/plugins/output/ogg_output/__init__.py @@ -32,10 +32,12 @@ # python-libs import ConfigParser + # GStreamer import gi gi.require_version('Gst', '1.0') -from gi.repository import GObject, Gst +from gi.repository import GObject, Gst, GstTag +from gi.repository import GLib # PyQt from PyQt4.QtCore import SIGNAL @@ -91,7 +93,17 @@ def get_output_bin(self, audio=True, video=True, metadata=None): audiolevel = Gst.ElementFactory.make('level', None) audiolevel.set_property('interval', 20000000) - + # # Setup metadata + vorbistag = Gst.ElementFactory.make("vorbistag", None) + #set tag merge mode to GST_TAG_MERGE_REPLACE + merge_mode = Gst.TagMergeMode.__enum_values__[2] + + if metadata is not None: + # Only set tag if metadata is set + vorbistag.merge_tags(self.tags, merge_mode) + vorbistag.set_tag_merge_mode(merge_mode) + bin.add(vorbistag) + #Add the audio elements to the bin bin.add(q1) bin.add(audiolevel) @@ -103,22 +115,16 @@ def get_output_bin(self, audio=True, video=True, metadata=None): q1.link(audiolevel) audiolevel.link(audioconvert) audioconvert.link(enc) - enc.link(q2) + enc.link(vorbistag) + vorbistag.link(q2) q2.link(muxer) #Currently tagging is broken and will need to be moved up in the code - # # Setup metadata - # #vorbistag = Gst.ElementFactory.make("vorbistag", None) - # # set tag merge mode to GST_TAG_MERGE_REPLACE - # #merge_mode = Gst.TagMergeMode.__enum_values__[2] - # # if metadata is not None: - # # # Only set tag if metadata is set - # # vorbistag.merge_tags(self.tags, merge_mode) - # # vorbistag.set_tag_merge_mode(merge_mode) - # # bin.add(vorbistag) + + # Setup ghost pads audiopad = q1.get_static_pad("sink") @@ -157,15 +163,24 @@ def set_metadata(self, data): Populate global tag list variable with file metadata for vorbistag audio element ''' - self.tags = Gst.TagList() + self.tags = Gst.TagList.new_empty() + print self.tags + #Set merge mode, pull to top of file if this works + merge_mode = Gst.TagMergeMode.__enum_values__[2] for tag in data.keys(): if(Gst.tag_exists(tag)): - #self.tags[tag] = data[tag] - #Tag stuff seems broken, commenting out for now. Nick - print "I should be tagging meta data" + if tag == "date": + s_date = data[tag].split("-") + Tag_date = GLib.Date() + Tag_date.set_day(int(s_date[2])) + Tag_date.set_month(s_date[1]) + Tag_date.set_year(int(s_date[0])) + self.tags.add_value(merge_mode, tag, Tag_date) + else: + self.tags.add_value(merge_mode, tag, str(data[tag])) else: - #self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") + self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") pass def load_config(self, plugman): From 8b33802e775deb8c593c283ad1648add80fc15bb Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 18 Nov 2013 17:12:07 -0800 Subject: [PATCH 13/16] WebM meta tagging is implemented, but does not work -I am not sure that the WebM format can take tagging? -I tested a clean version of FreeSeer, aka one I have not been editing, and did not get any meta tags when recording to webM --- .../plugins/output/ogg_output/__init__.py | 2 - .../plugins/output/webm_output/__init__.py | 49 ++++++++++--------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/freeseer/plugins/output/ogg_output/__init__.py b/src/freeseer/plugins/output/ogg_output/__init__.py index d3f21551..01152f83 100644 --- a/src/freeseer/plugins/output/ogg_output/__init__.py +++ b/src/freeseer/plugins/output/ogg_output/__init__.py @@ -164,8 +164,6 @@ def set_metadata(self, data): vorbistag audio element ''' self.tags = Gst.TagList.new_empty() - print self.tags - #Set merge mode, pull to top of file if this works merge_mode = Gst.TagMergeMode.__enum_values__[2] for tag in data.keys(): diff --git a/src/freeseer/plugins/output/webm_output/__init__.py b/src/freeseer/plugins/output/webm_output/__init__.py index 57357ef5..c9912505 100644 --- a/src/freeseer/plugins/output/webm_output/__init__.py +++ b/src/freeseer/plugins/output/webm_output/__init__.py @@ -32,7 +32,7 @@ # GStreamer import gi gi.require_version('Gst', '1.0') -from gi.repository import GObject, Gst +from gi.repository import GObject, Gst, GLib # Freeseer from freeseer.framework.plugin import IOutput @@ -73,18 +73,16 @@ def get_output_bin(self, audio=True, video=True, metadata=None): audiolevel = Gst.ElementFactory.make('level', None) audiolevel.set_property('interval', 20000000) - #Currently tagging is broken and will need to be moved up in the code + #Setup metadata + vorbistag = Gst.ElementFactory.make("vorbistag", None) + #set tag merge mode to GST_TAG_MERGE_REPLACE + merge_mode = Gst.TagMergeMode.__enum_values__[2] - # # Setup metadata - # #vorbistag = Gst.ElementFactory.make("vorbistag", "vorbistag") - # # set tag merge mode to GST_TAG_MERGE_REPLACE - # #merge_mode = Gst.TagMergeMode.__enum_values__[2] - - # #if metadata is not None: - # # Only set tag if metadata is set - # #vorbistag.merge_tags(self.tags, merge_mode) - # #vorbistag.set_tag_merge_mode(merge_mode) - # #bin.add(vorbistag) + if metadata is not None: + # Only set tag if metadata is set + vorbistag.merge_tags(self.tags, merge_mode) + vorbistag.set_tag_merge_mode(merge_mode) + @@ -93,13 +91,15 @@ def get_output_bin(self, audio=True, video=True, metadata=None): bin.add(audiolevel) bin.add(audioconvert) bin.add(enc) + bin.add(vorbistag) bin.add(q2) #link the audio elements q1.link(audiolevel) audiolevel.link(audioconvert) audioconvert.link(enc) - enc.link(q2) + enc.link(vorbistag) + vorbistag.link(q2) q2.link(muxer) # Setup ghost pads @@ -138,18 +138,19 @@ def set_metadata(self, data): Populate global tag list variable with file metadata for vorbistag audio element ''' - self.tags = Gst.TagList() + self.tags = Gst.TagList.new_empty() + merge_mode = Gst.TagMergeMode.__enum_values__[2] for tag in data.keys(): if(Gst.tag_exists(tag)): - #tagging is not currently working - #self.tags[tag] = data[tag] - #self.tags.add_value(Gst.TagMergeMode.__enum_values__[4], tag, data[tag]) - #Gst.TagList_Add_Value() - #Gst.tag_list_add_value() - #print tag - #print data[tag] - #Tag stuff seems broken, commenting out for now. Nick - print "I should be tagging meta data" + if tag == "date": + s_date = data[tag].split("-") + Tag_date = GLib.Date() + Tag_date.set_day(int(s_date[2])) + Tag_date.set_month(s_date[1]) + Tag_date.set_year(int(s_date[0])) + self.tags.add_value(merge_mode, tag, Tag_date) + else: + self.tags.add_value(merge_mode, tag, str(data[tag])) else: - #self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") + self.core.logger.log.debug("WARNING: Tag \"" + str(tag) + "\" is not registered with gstreamer.") pass From 942b1385a974ccdfa15c21b2d8af58206f94f6d6 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 19 Nov 2013 12:29:26 -0800 Subject: [PATCH 14/16] Ogg video - Can set bitrate - Also some minor code clean up -Works in Windows and Linux --- src/freeseer/plugins/output/ogg_output/__init__.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/freeseer/plugins/output/ogg_output/__init__.py b/src/freeseer/plugins/output/ogg_output/__init__.py index 01152f83..e41102b4 100644 --- a/src/freeseer/plugins/output/ogg_output/__init__.py +++ b/src/freeseer/plugins/output/ogg_output/__init__.py @@ -102,13 +102,13 @@ def get_output_bin(self, audio=True, video=True, metadata=None): # Only set tag if metadata is set vorbistag.merge_tags(self.tags, merge_mode) vorbistag.set_tag_merge_mode(merge_mode) - bin.add(vorbistag) - + #Add the audio elements to the bin bin.add(q1) bin.add(audiolevel) bin.add(audioconvert) bin.add(enc) + bin.add(vorbistag) bin.add(q2) #link the audio elements @@ -119,13 +119,6 @@ def get_output_bin(self, audio=True, video=True, metadata=None): vorbistag.link(q2) q2.link(muxer) - - #Currently tagging is broken and will need to be moved up in the code - - - - - # Setup ghost pads audiopad = q1.get_static_pad("sink") audio_ghostpad = Gst.GhostPad.new("audiosink", audiopad) @@ -139,8 +132,7 @@ def get_output_bin(self, audio=True, video=True, metadata=None): bin.add(videoqueue) videocodec = Gst.ElementFactory.make("theoraenc", None) - #Setting the bit rate like this will cause this plugin not to work, currently - #videocodec.set_property("bitrate", int(self.video_bitrate)) + videocodec.set_property("bitrate", int(self.video_bitrate)) bin.add(videocodec) # Setup ghost pads From 0fad019e9a3d5d6707312343a145ca6af90a03a5 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Nov 2013 19:17:38 -0800 Subject: [PATCH 15/16] Desktop capture update, does not work -I am not sure what the error is caused by but I've added a pipeline and comments in the code that explain the problem. --- .../plugins/videoinput/desktop/__init__.py | 16 ++++++++++++---- .../plugins/videoinput/usbsrc/__init__.py | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/freeseer/plugins/videoinput/desktop/__init__.py b/src/freeseer/plugins/videoinput/desktop/__init__.py index 2f24e095..cb9c4859 100644 --- a/src/freeseer/plugins/videoinput/desktop/__init__.py +++ b/src/freeseer/plugins/videoinput/desktop/__init__.py @@ -105,12 +105,20 @@ def get_videoinput_bin(self): bin.add(videosrc) - colorspace = Gst.ElementFactory.make("videoconvert", "colorspace") - bin.add(colorspace) - videosrc.link(colorspace) + #Adding a queue before the video ends up in the Videorate Gst element in the + #video processing stage should make this work but does not. + #gst-launch-1.0 -e ximagesrc ! queue ! videorate ! video/x-raw,framerate=4/1 ! videoconvert ! theoraenc ! oggmux ! / + # queue ! filesink location="test-videorate.ogg" + #That pipeline works, which this should replicate. + #If you sub in videotestsrc in place of ximagesrc this this works, if you leave it as it + #then you end up with an "internal data flow error" + q1 = Gst.ElementFactory.make("queue", "q1") + bin.add(q1) + + videosrc.link(q1) # Setup ghost pad - pad = colorspace.get_static_pad("src") + pad = q1.get_static_pad("src") ghostpad = Gst.GhostPad.new("videosrc", pad) bin.add_pad(ghostpad) diff --git a/src/freeseer/plugins/videoinput/usbsrc/__init__.py b/src/freeseer/plugins/videoinput/usbsrc/__init__.py index 6d3ec438..6b2fb8ee 100644 --- a/src/freeseer/plugins/videoinput/usbsrc/__init__.py +++ b/src/freeseer/plugins/videoinput/usbsrc/__init__.py @@ -71,7 +71,7 @@ def get_videoinput_bin(self): videosrc = None if sys.platform.startswith("linux"): - videosrc = Gst.ElementFactory.make("autovideosrc", "videosrc") + videosrc = Gst.ElementFactory.make("v4l2src", "videosrc") #videosrc.set_property("device", self.device) elif sys.platform in ["win32", "cygwin"]: videosrc = Gst.ElementFactory.make("dshowvideosrc", "videosrc") From 4ae3586c622f6901eb6c1dde60101701d057302c Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 2 Dec 2013 10:48:35 -0800 Subject: [PATCH 16/16] Changed the color format box - As per the comments related to this feature I have changed the drop down box in the GUI to give you the option of selecting the, Y444, RGBx, or YVYU, color formats. It does not make much sense to have a drop box with two options that are the same. - I had originally selected Y444 because it was the format used in an example from Novacut (http://bazaar.launchpad.net/~jderose/+junk/gst-examples/view/head:/transcoder-1.0) - There is a long list of possible video formats that I found here: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/gst-plugins-base-plugins-videotestsrc.html - It is a simple process to change the color format and if the desired format is not implemented it just needs to be added in widget.py - The 3 I have coded work with the test source in Windows --- src/freeseer/plugins/videomixer/videopassthrough/__init__.py | 4 ++-- src/freeseer/plugins/videomixer/videopassthrough/widget.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/freeseer/plugins/videomixer/videopassthrough/__init__.py b/src/freeseer/plugins/videomixer/videopassthrough/__init__.py index 739d13e1..b6d9b42b 100644 --- a/src/freeseer/plugins/videomixer/videopassthrough/__init__.py +++ b/src/freeseer/plugins/videomixer/videopassthrough/__init__.py @@ -55,7 +55,7 @@ class VideoPassthrough(IVideoMixer): widget = None # VideoPassthrough variables - input_type = "video/x-raw" + input_type = "Y444" framerate = 30 resolution = "NOSCALE" @@ -68,7 +68,7 @@ def get_videomixer_bin(self): videorate_cap = Gst.ElementFactory.make("capsfilter", "video_rate_cap") videorate_cap.set_property("caps", - Gst.caps_from_string("%s, framerate=%d/1, format=Y444" % (self.input_type, self.framerate))) + Gst.caps_from_string("video/x-raw, framerate=%d/1, format=%s" % (self.framerate, self.input_type))) bin.add(videorate_cap) # --- End Video Rate diff --git a/src/freeseer/plugins/videomixer/videopassthrough/widget.py b/src/freeseer/plugins/videomixer/videopassthrough/widget.py index fc142e82..6e3455df 100644 --- a/src/freeseer/plugins/videomixer/videopassthrough/widget.py +++ b/src/freeseer/plugins/videomixer/videopassthrough/widget.py @@ -67,8 +67,9 @@ def __init__(self, parent=None): self.videocolourLabel = QLabel(self.tr("Colour Format")) self.videocolourComboBox = QComboBox() - self.videocolourComboBox.addItem("video/x-raw") - self.videocolourComboBox.addItem("video/x-raw") + self.videocolourComboBox.addItem("Y444") + self.videocolourComboBox.addItem("RGBx") + self.videocolourComboBox.addItem("YVYU") self.videocolourComboBox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) layout.addRow(self.videocolourLabel, self.videocolourComboBox)