Package flumotion :: Package component :: Package producers :: Package firewire :: Module firewire
[hide private]

Source Code for Module flumotion.component.producers.firewire.firewire

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  import gst 
 23  from twisted.internet import defer 
 24   
 25  from flumotion.common import errors, messages, gstreamer 
 26  from flumotion.common.i18n import N_, gettexter 
 27  from flumotion.component import feedcomponent 
 28  from flumotion.component.effects.deinterlace import deinterlace 
 29  from flumotion.component.effects.videorate import videorate 
 30  from flumotion.component.effects.videoscale import videoscale 
 31  from flumotion.component.effects.audiorate import audiorate 
 32   
 33  __version__ = "$Rev$" 
 34  T_ = gettexter() 
 35   
 36   
 37  # See comments in gstdvdec.c for details on the dv format. 
 38   
 39   
40 -class Firewire(feedcomponent.ParseLaunchComponent):
41
42 - def do_check(self):
43 self.debug('running PyGTK/PyGST and configuration checks') 44 from flumotion.component.producers import checks 45 d1 = checks.checkTicket347() 46 d2 = checks.checkTicket348() 47 dl = defer.DeferredList([d1, d2]) 48 dl.addCallback(self._checkCallback) 49 return dl
50
51 - def check_properties(self, props, addMessage):
52 deintMode = props.get('deinterlace-mode', 'auto') 53 deintMethod = props.get('deinterlace-method', 'ffmpeg') 54 55 if deintMode not in deinterlace.DEINTERLACE_MODE: 56 msg = messages.Error(T_(N_("Configuration error: '%s' " \ 57 "is not a valid deinterlace mode." % deintMode))) 58 addMessage(msg) 59 raise errors.ConfigError(msg) 60 61 if deintMethod not in deinterlace.DEINTERLACE_METHOD: 62 msg = messages.Error(T_(N_("Configuration error: '%s' " \ 63 "is not a valid deinterlace method." % deintMethod))) 64 self.debug("'%s' is not a valid deinterlace method", 65 deintMethod) 66 addMessage(msg) 67 raise errors.ConfigError(msg)
68
69 - def _checkCallback(self, results):
70 for (state, result) in results: 71 for m in result.messages: 72 self.addMessage(m)
73
74 - def get_pipeline_string(self, props):
75 if props.get('scaled-width', None) is not None: 76 self.warnDeprecatedProperties(['scaled-width']) 77 78 self.is_square = props.get('is-square', False) 79 self.width = props.get('width', 0) 80 self.height = props.get('height', 0) 81 decoder = props.get('decoder', 'dvdec') 82 if not self.is_square and not self.height: 83 self.height = int(576 * self.width/720.) # assuming PAL 84 self.add_borders = props.get('add-borders', True) 85 guid = "guid=%s" % props.get('guid', 0) 86 self.deintMode = props.get('deinterlace-mode', 'auto') 87 self.deintMethod = props.get('deinterlace-method', 'ffmpeg') 88 89 fr = props.get('framerate', None) 90 if fr is not None: 91 self.framerate = gst.Fraction(fr[0], fr[1]) 92 else: 93 self.framerate = None 94 95 # FIXME: might be nice to factor out dv1394src ! dvdec so we can 96 # replace it with videotestsrc of the same size and PAR, so we can 97 # unittest the pipeline 98 # need a queue in case tcpserversink blocks somehow 99 template = ('dv1394src %s' 100 ' ! tee name=t' 101 ' ! queue leaky=2 max-size-time=1000000000' 102 ' ! dvdemux name=demux' 103 ' demux. ! queue ! %s name=decoder' 104 ' ! @feeder:video@' 105 ' demux. ! queue ! audio/x-raw-int ' 106 ' ! volume name=setvolume' 107 ' ! level name=volumelevel message=true ' 108 ' ! @feeder:audio@' 109 ' t. ! queue ! @feeder:dv@' % (guid, decoder)) 110 111 return template
112
113 - def configure_pipeline(self, pipeline, properties):
114 self.volume = pipeline.get_by_name("setvolume") 115 from flumotion.component.effects.volume import volume 116 comp_level = pipeline.get_by_name('volumelevel') 117 vol = volume.Volume('inputVolume', comp_level, pipeline) 118 # catch bus message for when camera disappears 119 bus = pipeline.get_bus() 120 bus.add_signal_watch() 121 bus.connect('message::element', self._bus_message_received_cb) 122 self.addEffect(vol) 123 124 decoder = pipeline.get_by_name("decoder") 125 if gstreamer.element_has_property(decoder, 'drop-factor'): 126 if self.framerate: 127 framerate = float(self.framerate.num / self.framerate.denom) 128 if 12.5 < framerate: 129 drop_factor = 1 130 elif 6.3 < framerate <= 12.5: 131 drop_factor = 2 132 elif 3.2 < framerate <= 6.3: 133 drop_factor = 4 134 elif framerate <= 3.2: 135 drop_factor = 8 136 else: 137 drop_factor = 1 138 decoder.set_property('drop-factor', drop_factor) 139 140 vr = videorate.Videorate('videorate', 141 decoder.get_pad("src"), pipeline, self.framerate) 142 self.addEffect(vr) 143 vr.plug() 144 145 deinterlacer = deinterlace.Deinterlace('deinterlace', 146 vr.effectBin.get_pad("src"), pipeline, 147 self.deintMode, self.deintMethod) 148 self.addEffect(deinterlacer) 149 deinterlacer.plug() 150 151 videoscaler = videoscale.Videoscale('videoscale', self, 152 deinterlacer.effectBin.get_pad("src"), pipeline, 153 self.width, self.height, self.is_square, self.add_borders) 154 self.addEffect(videoscaler) 155 videoscaler.plug() 156 157 # Setting a tolerance of 20ms should be enough (1/2 frame), but 158 # we set it to 40ms to be more conservatives 159 ar = audiorate.Audiorate('audiorate', comp_level.get_pad("src"), 160 pipeline, tolerance=40 * gst.MSECOND) 161 self.addEffect(ar) 162 ar.plug()
163
164 - def getVolume(self):
165 return self.volume.get_property('volume')
166
167 - def setVolume(self, value):
168 """ 169 @param value: float between 0.0 and 4.0 170 """ 171 self.debug("Setting volume to %f" % (value)) 172 self.volume.set_property('volume', value)
173 174 # detect camera unplugging or other cause of firewire bus reset 175
176 - def _bus_message_received_cb(self, bus, message):
177 """ 178 @param bus: the message bus sending the message 179 @param message: the message received 180 """ 181 if message.structure.get_name() == "ieee1394-bus-reset": 182 # we have a firewire bus reset 183 s = message.structure 184 # current-device-change is only in gst-plugins-good >= 0.10.3 185 if 'current-device-change' in s.keys(): 186 if s['current-device-change'] != 0: 187 # we actually have a connect or disconnect of the camera 188 # so first remove all the previous messages warning about a 189 # firewire-bus-reset 190 191 for m in self.state.get('messages'): 192 if m.id.startswith('firewire-bus-reset'): 193 self.state.remove('messages', m) 194 195 if s['current-device-change'] == 1: 196 # connected 197 m = messages.Info(T_(N_( 198 "The camera has now been reconnected.")), 199 mid="firewire-bus-reset-%d" % s['nodecount'], 200 priority=40) 201 self.state.append('messages', m) 202 elif s['current-device-change'] == -1: 203 # disconnected 204 m = messages.Warning(T_(N_( 205 "The camera has been disconnected.")), 206 mid="firewire-bus-reset-%d" % s['nodecount'], 207 priority=40) 208 self.state.append('messages', m)
209