Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/glive.py
diff options
context:
space:
mode:
Diffstat (limited to 'glive.py')
-rw-r--r--glive.py110
1 files changed, 66 insertions, 44 deletions
diff --git a/glive.py b/glive.py
index 0747e86..48e28d1 100644
--- a/glive.py
+++ b/glive.py
@@ -39,8 +39,8 @@ import utils
logger = logging.getLogger('glive')
OGG_TRAITS = {
- 0: { 'width': 160, 'height': 120, 'quality': 16 },
- 1: { 'width': 400, 'height': 300, 'quality': 16 } }
+ 0: { 'width': 160, 'height': 120, 'quality': 16 },
+ 1: { 'width': 400, 'height': 300, 'quality': 16 } }
class Glive:
PHOTO_MODE_PHOTO = 0
@@ -50,6 +50,7 @@ class Glive:
self.activity = activity_obj
self.model = model
+
self._eos_cb = None
self._has_camera = False
self._can_limit_framerate = False
@@ -68,6 +69,7 @@ class Glive:
self._detect_camera()
self._pipeline = Gst.Pipeline()
+
self._create_photobin()
self._create_audiobin()
self._create_videobin()
@@ -86,7 +88,7 @@ class Glive:
v4l2src = Gst.ElementFactory.make('v4l2src', 'v4l2src')
- if v4l2src.props.device_name is None:
+ if v4l2src.get_property('device-name') is None:
return
self._has_camera = True
@@ -97,15 +99,25 @@ class Glive:
# can't find a way to do this (at this time, XO-1 cafe camera driver
# doesn't support framerate changes, but gstreamer caps suggest
# otherwise)
+
pipeline = Gst.Pipeline()
+
+ # WARNING **: 0.10-style raw video caps are being created. Should be video/x-raw,format=(string)
caps = Gst.Caps.from_string('video/x-raw-yuv,framerate=10/1')
+ camerafilter = Gst.ElementFactory.make("capsfilter", "capsfilter")
+ camerafilter.set_property("caps", caps)
+
fsink = Gst.ElementFactory.make('fakesink', 'fakesink')
+
pipeline.add(v4l2src)
- # FIXME: TypeError: argument dest: Expected Gst.Element, but got gi.repository.Gst.Caps
- #pipeline.add(caps)
+ pipeline.add(camerafilter)
pipeline.add(fsink)
- v4l2src.link(fsink)
+
+ v4l2src.link(camerafilter)
+ camerafilter.link(fsink)
+
self._can_limit_framerate = pipeline.set_state(Gst.State.PAUSED) != Gst.StateChangeReturn.FAILURE
+
pipeline.set_state(Gst.State.NULL)
def get_has_camera(self):
@@ -115,7 +127,7 @@ class Glive:
def _create_photobin(self):
queue = Gst.ElementFactory.make("queue", "pbqueue")
- queue.set_property("leaky", True)
+ queue.set_property("leaky", 1)
queue.set_property("max-size-buffers", 1)
colorspace = Gst.ElementFactory.make("videoconvert", "pbcolorspace")
@@ -151,8 +163,9 @@ class Glive:
if not hwdev_available:
src.set_property("device", "default")
+ # WARNING **: 0.10-style raw audio caps are being created. Should be audio/x-raw,format=(string)
srccaps = Gst.Caps.from_string("audio/x-raw-int,rate=16000,channels=1,depth=16")
-
+
# guarantee perfect stream, important for A/V sync
rate = Gst.ElementFactory.make("audiorate", 'audiorate')
@@ -161,7 +174,7 @@ class Glive:
# (possibly a gstreamer/ALSA bug -- even if it gets caught up, it
# should be able to resync without problem)
queue = Gst.ElementFactory.make("queue", "audioqueue")
- queue.set_property("leaky", True) # prefer fresh data
+ queue.set_property("leaky", 1) # prefer fresh data
queue.set_property("max-size-time", 5000000000) # 5 seconds
queue.set_property("max-size-buffers", 500)
queue.connect("overrun", self._log_queue_overrun)
@@ -172,13 +185,14 @@ class Glive:
sink.set_property("location", os.path.join(Instance.instancePath, "output.wav"))
self._audiobin = Gst.Bin()
+
self._audiobin.add(src)
self._audiobin.add(rate)
self._audiobin.add(queue)
self._audiobin.add(enc)
self._audiobin.add(sink)
- rate.link(rate)
+ src.link(rate)
rate.link(queue)
queue.link(enc)
enc.link(sink)
@@ -192,9 +206,9 @@ class Glive:
scale = Gst.ElementFactory.make("videoscale", "vbscale")
- scalecapsfilter = Gst.ElementFactory.make("capsfilter", "scalecaps")
-
+ # WARNING **: 0.10-style raw video caps are being created. Should be video/x-raw,format=(string)
scalecaps = Gst.Caps.from_string('video/x-raw-yuv,width=160,height=120')
+ scalecapsfilter = Gst.ElementFactory.make("capsfilter", "scalecaps")
scalecapsfilter.set_property("caps", scalecaps)
colorspace = Gst.ElementFactory.make("videoconvert", "vbcolorspace")
@@ -208,6 +222,7 @@ class Glive:
sink.set_property("location", os.path.join(Instance.instancePath, "output.ogg"))
self._videobin = Gst.Bin()
+
self._videobin.add(queue)
self._videobin.add(scale)
self._videobin.add(scalecapsfilter)
@@ -225,7 +240,7 @@ class Glive:
pad = queue.get_static_pad("sink")
self._videobin.add_pad(Gst.GhostPad.new("sink", pad))
-
+
def _create_xbin(self):
scale = Gst.ElementFactory.make("videoscale", 'videoscale')
@@ -237,6 +252,7 @@ class Glive:
xsink.set_property("sync", False)
self._xbin = Gst.Bin()
+
self._xbin.add(scale)
self._xbin.add(cspace)
self._xbin.add(xsink)
@@ -260,13 +276,6 @@ class Glive:
return
src = Gst.ElementFactory.make("v4l2src", "camsrc")
-
- try:
- # old gst-plugins-good does not have this property
- src.set_property("queue-size", 2)
-
- except:
- pass
# if possible, it is important to place the framerate limit directly
# on the v4l2src so that it gets communicated all the way down to the
@@ -286,23 +295,27 @@ class Glive:
# the FPS value.
rate = Gst.ElementFactory.make("videorate", 'videorate')
ratecaps = Gst.Caps.from_string('video/x-raw-yuv,framerate=10/1')
-
+
tee = Gst.ElementFactory.make("tee", "tee")
queue = Gst.ElementFactory.make("queue", "dispqueue")
# prefer fresh frames
- queue.set_property("leaky", True)
+ queue.set_property("leaky", 1)
queue.set_property("max-size-buffers", 2)
self._pipeline.add(src)
self._pipeline.add(rate)
self._pipeline.add(tee)
self._pipeline.add(queue)
+
src.link(rate)
- # FIXME: TypeError: argument dest: Expected Gst.Element, but got gi.repository.Gst.Caps
+ # FIXME: TypeError: Expected Gst.Element, but got GObjectMeta
#rate.link(srccaps)
+
rate.link(tee)
+ # FIXME: TypeError: Expected Gst.Element, but got GObjectMeta
#tee.link(ratecaps)
+
tee.link(queue)
self._xvsink = Gst.ElementFactory.make("xvimagesink", "xsink")
@@ -406,6 +419,7 @@ class Glive:
return self._pipeline.get_state(0)[1]
def stop_recording_audio(self):
+
# We should be able to simply pause and remove the audiobin, but
# this seems to cause a gstreamer segfault. So we stop the whole
# pipeline while manipulating it.
@@ -423,16 +437,16 @@ class Glive:
self.model.still_ready(self._audio_pixbuf)
line = 'filesrc location=' + audio_path + ' name=audioFilesrc ! wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! filesink name=audioFilesink'
- audioline = gst.parse_launch(line)
+ audioline = Gst.parse_launch(line)
taglist = self._get_tags(constants.TYPE_AUDIO)
if self._audio_pixbuf:
pixbuf_b64 = utils.getStringFromPixbuf(self._audio_pixbuf)
- taglist[Gst.TAG_EXTENDED_COMMENT] = "coverart=" + pixbuf_b64
+ #taglist[Gst.TAG_EXTENDED_COMMENT] = "coverart=" + pixbuf_b64
vorbis_enc = audioline.get_by_name('audioVorbisenc')
- vorbis_enc.merge_tags(taglist, Gst.TAG_MERGE_REPLACE_ALL)
+ #vorbis_enc.merge_tags(taglist, Gst.TagMergeMode.REPLACE_ALL)
audioFilesink = audioline.get_by_name('audioFilesink')
audioOggFilepath = os.path.join(Instance.instancePath, "output.ogg")
@@ -442,11 +456,13 @@ class Glive:
audioBus.add_signal_watch()
self._audio_transcode_handler = audioBus.connect('message', self._onMuxedAudioMessageCb, audioline)
self._transcode_id = GObject.timeout_add(200, self._transcodeUpdateCb, audioline)
+
audioline.set_state(Gst.State.PLAYING)
def _get_tags(self, type):
tl = Gst.TagList()
+ """
tl[Gst.TAG_ARTIST] = self.model.get_nickname()
tl[Gst.TAG_COMMENT] = "olpc"
#this is unfortunately, unreliable
@@ -457,7 +473,7 @@ class Glive:
# Translators: photo by photographer, e.g. "Photo by Mary"
tl[Gst.TAG_TITLE] = _('%(type)s by %(name)s') % {'type': stringType,
- 'name': self.model.get_nickname()}
+ 'name': self.model.get_nickname()}"""
return tl
def _take_photo(self, photo_mode):
@@ -510,10 +526,11 @@ class Glive:
return
self._ogg_quality = quality
+
self._config_videobin(OGG_TRAITS[quality]['quality'],
OGG_TRAITS[quality]['width'],
OGG_TRAITS[quality]['height'])
-
+
# If we use pad blocking and adjust the pipeline on-the-fly, the
# resultant video has bad A/V sync :(
# If we pause the pipeline while adjusting it, the A/V sync is better
@@ -552,7 +569,7 @@ class Glive:
self._eos_cb = self._video_eos
self._pipeline.get_by_name('camsrc').send_event(Gst.Event.new_eos())
self._audiobin.get_by_name('absrc').send_event(Gst.Event.new_eos())
-
+
def _video_eos(self):
self._pipeline.set_state(Gst.State.NULL)
@@ -561,7 +578,7 @@ class Glive:
self._pipeline.remove(self._audiobin)
self.model.shutter_sound()
-
+
if len(self._thumb_pipes) > 0:
thumbline = self._thumb_pipes[-1]
thumbline.get_by_name('thumb_fakesink').disconnect(self._thumb_handoff_handler)
@@ -572,10 +589,12 @@ class Glive:
# FIXME: inform model of failure?
return
- line = 'filesrc location=' + ogg_path + ' name=thumbFilesrc ! oggdemux name=thumbOggdemux ! theoradec name=thumbTheoradec ! tee name=thumb_tee ! queue name=thumb_queue ! ffmpegcolorspace name=thumbFfmpegcolorspace ! jpegenc name=thumbJPegenc ! fakesink name=thumb_fakesink'
+ line = 'filesrc location=' + ogg_path + ' name=thumbFilesrc ! oggdemux name=thumbOggdemux ! theoradec name=thumbTheoradec ! tee name=thumb_tee ! queue name=thumb_queue ! videoconvert name=thumbFfmpegcolorspace ! jpegenc name=thumbJPegenc ! fakesink name=thumb_fakesink'
+
thumbline = Gst.parse_launch(line)
+
thumb_queue = thumbline.get_by_name('thumb_queue')
- thumb_queue.set_property("leaky", True)
+ thumb_queue.set_property("leaky", 1)
thumb_queue.set_property("max-size-buffers", 1)
thumb_tee = thumbline.get_by_name('thumb_tee')
thumb_fakesink = thumbline.get_by_name('thumb_fakesink')
@@ -584,18 +603,19 @@ class Glive:
self._thumb_pipes.append(thumbline)
self._thumb_exposure_open = True
thumbline.set_state(Gst.State.PLAYING)
-
+
def copyThumbPic(self, fsink, buffer, pad, user_data=None):
if not self._thumb_exposure_open:
return
self._thumb_exposure_open = False
- loader = GdkPibuf.PixbufLoader.new_with_mime_type("image/jpeg")
- loader.write(buffer)
- loader.close()
- self.thumbBuf = loader.get_pixbuf()
- self.model.still_ready(self.thumbBuf)
+ #loader = GdkPixbuf.PixbufLoader.new_with_mime_type("image/jpeg")
+ # FIXME: TypeError: Must be sequence, not Buffer
+ #loader.write(buffer)
+ #loader.close()
+ #self.thumbBuf = loader.get_pixbuf()
+ #self.model.still_ready(self.thumbBuf)
self._thumb_element('thumb_tee').unlink(self._thumb_element('thumb_queue'))
@@ -604,9 +624,10 @@ class Glive:
muxFilepath = os.path.join(Instance.instancePath, "mux.ogg")
muxline = Gst.parse_launch('filesrc location=' + str(oggFilepath) + ' name=muxVideoFilesrc ! oggdemux name=muxOggdemux ! theoraparse ! oggmux name=muxOggmux ! filesink location=' + str(muxFilepath) + ' name=muxFilesink filesrc location=' + str(wavFilepath) + ' name=muxAudioFilesrc ! wavparse name=muxWavparse ! audioconvert name=muxAudioconvert ! vorbisenc name=muxVorbisenc ! muxOggmux.')
+
taglist = self._get_tags(constants.TYPE_VIDEO)
vorbis_enc = muxline.get_by_name('muxVorbisenc')
- vorbis_enc.merge_tags(taglist, Gst.TAG_MERGE_REPLACE_ALL)
+ #vorbis_enc.merge_tags(taglist, Gst.TagMergeMode.REPLACE_ALL)
muxBus = muxline.get_bus()
muxBus.add_signal_watch()
@@ -630,13 +651,13 @@ class Glive:
def _query_position(self, pipe):
try:
- position, format = pipe.query_position(Gst.FORMAT_TIME)
+ position, format = pipe.query_position(Gst.Format.TIME)
except:
- position = Gste.CLOCK_TIME_NONE
+ position = Gst.CLOCK_TIME_NONE
try:
- duration, format = pipe.query_duration(Gst.FORMAT_TIME)
+ duration, format = pipe.query_duration(Gst.Format.TIME)
except:
duration = Gst.CLOCK_TIME_NONE
@@ -645,7 +666,7 @@ class Glive:
def _onMuxedVideoMessageCb(self, bus, message, pipe):
- if message.type != Gst.MESSAGE_EOS:
+ if message.type != Gst.MessageType.EOS:
return True
GObject.source_remove(self._video_transcode_handler)
@@ -667,7 +688,7 @@ class Glive:
def _onMuxedAudioMessageCb(self, bus, message, pipe):
- if message.type != Gst.MESSAGE_EOS:
+ if message.type != Gst.MessageType.EOS:
return True
GObject.source_remove(self._audio_transcode_handler)
@@ -682,6 +703,7 @@ class Glive:
oggFilepath = os.path.join(Instance.instancePath, "output.ogg")
os.remove( wavFilepath )
self.model.save_audio(oggFilepath, self._audio_pixbuf)
+
return False
def _bus_message_handler(self, bus, message):