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 
 26  from flumotion.common.i18n import N_, gettexter 
 27  from flumotion.component import feedcomponent 
 28   
 29  __version__ = "$Rev: 7769 $" 
 30  T_ = gettexter() 
 31   
 32   
 33  # See comments in gstdvdec.c for details on the dv format. 
 34   
 35   
36 -class Firewire(feedcomponent.ParseLaunchComponent):
37
38 - def do_check(self):
39 self.debug('running PyGTK/PyGST checks') 40 from flumotion.component.producers import checks 41 d1 = checks.checkTicket347() 42 d2 = checks.checkTicket348() 43 dl = defer.DeferredList([d1, d2]) 44 dl.addCallback(self._checkCallback) 45 return dl
46
47 - def _checkCallback(self, results):
48 for (state, result) in results: 49 for m in result.messages: 50 self.addMessage(m)
51
52 - def get_pipeline_string(self, props):
53 width = props.get('width', 240) 54 height = props.get('height', int(576 * width/720.)) # assuming PAL :-/ 55 guid = props.get('guid', None) 56 57 # F0.6: remove backwards-compatible properties 58 self.fixRenamedProperties(props, [ 59 ('scaled_width', 'scaled-width'), 60 ('is_square', 'is-square'), 61 ]) 62 scaled_width = props.get('scaled-width', width) 63 is_square = props.get('is-square', False) 64 framerate = props.get('framerate', (30, 2)) 65 framerate_float = float(framerate[0]) / framerate[1] 66 67 scale_correction = width - scaled_width 68 69 if 12.5 < framerate_float <= 25: 70 drop_factor = 1 71 elif 6.3 < framerate_float <= 12.5: 72 drop_factor = 2 73 elif 3.2 < framerate_float <= 6.3: 74 drop_factor = 4 75 else: 76 drop_factor = 8 77 78 if is_square: 79 square_pipe = ',pixel-aspect-ratio=(fraction)1/1' 80 else: 81 square_pipe = '' 82 83 # the point of width correction is to get to a multiple of 8 for width 84 # so codecs are happy; it's unrelated to the aspect ratio correction 85 # to get to 4:3 or 16:9 86 if scale_correction > 0: 87 # videobox in 0.8.8 has a stride problem outputting AYUV with odd 88 # width I420 works fine, but is slower when overlay is used 89 90 pad_pipe = ('! ffmpegcolorspace ! videobox right=-%d ! ' 91 'video/x-raw-yuv,format=(fourcc)I420 ' % 92 (scale_correction, )) 93 else: 94 pad_pipe = '' 95 96 # Always scale down to half size to lose interlacing artifacts. 97 # FIXME: handle this better when GStreamer provides facilities for it. 98 interlaced_height = 288 99 100 # FIXME: might be nice to factor out dv1394src ! dvdec so we can 101 # replace it with videotestsrc of the same size and PAR, so we can 102 # unittest the pipeline 103 # need a queue in case tcpserversink blocks somehow 104 template = ('dv1394src %(guid)s' 105 ' ! tee name=t' 106 ' ! queue leaky=2 max-size-time=1000000000' 107 ' ! dvdemux name=demux' 108 ' demux. ! queue ! dvdec drop-factor=%(df)d' 109 ' ! video/x-raw-yuv,format=(fourcc)YUY2' 110 ' ! videorate ! videoscale' 111 ' ! video/x-raw-yuv,width=%(sw)s,height=%(ih)s%(sq)s' 112 ' ! videoscale' 113 ' ! video/x-raw-yuv,width=%(sw)s,height=%(h)s,' 114 ' framerate=%(fr)s,format=(fourcc)YUY2' 115 ' %(pp)s' 116 ' ! @feeder:video@' 117 ' demux. ! queue ! audio/x-raw-int ' 118 ' ! volume name=setvolume' 119 ' ! level name=volumelevel message=true ! audiorate' 120 ' ! @feeder:audio@' 121 ' t. ! queue ! @feeder:dv@' 122 % dict(df=drop_factor, ih=interlaced_height, 123 sq=square_pipe, pp=pad_pipe, 124 sw=scaled_width, h=height, 125 guid=(guid and ('guid=%s' % guid) or ''), 126 fr=('%d/%d' % (framerate[0], framerate[1])))) 127 128 return template
129
130 - def configure_pipeline(self, pipeline, properties):
131 self.volume = pipeline.get_by_name("setvolume") 132 from flumotion.component.effects.volume import volume 133 comp_level = pipeline.get_by_name('volumelevel') 134 vol = volume.Volume('inputVolume', comp_level, pipeline) 135 # catch bus message for when camera disappears 136 bus = pipeline.get_bus() 137 bus.add_signal_watch() 138 bus.connect('message::element', self._bus_message_received_cb) 139 140 self.addEffect(vol)
141
142 - def getVolume(self):
143 return self.volume.get_property('volume')
144
145 - def setVolume(self, value):
146 """ 147 @param value: float between 0.0 and 4.0 148 """ 149 self.debug("Setting volume to %f" % (value)) 150 self.volume.set_property('volume', value)
151 152 # detect camera unplugging or other cause of firewire bus reset 153
154 - def _bus_message_received_cb(self, bus, message):
155 """ 156 @param bus: the message bus sending the message 157 @param message: the message received 158 """ 159 if message.structure.get_name() == "ieee1394-bus-reset": 160 # we have a firewire bus reset 161 s = message.structure 162 # current-device-change is only in gst-plugins-good >= 0.10.3 163 if 'current-device-change' in s.keys(): 164 if s['current-device-change'] != 0: 165 # we actually have a connect or disconnect of the camera 166 # so first remove all the previous messages warning about a 167 # firewire-bus-reset 168 169 for m in self.state.get('messages'): 170 if m.id.startswith('firewire-bus-reset'): 171 self.state.remove('messages', m) 172 173 if s['current-device-change'] == 1: 174 # connected 175 m = messages.Info(T_(N_( 176 "The camera has now been reconnected.")), 177 mid="firewire-bus-reset-%d" % s['nodecount'], 178 priority=40) 179 self.state.append('messages', m) 180 elif s['current-device-change'] == -1: 181 # disconnected 182 m = messages.Warning(T_(N_( 183 "The camera has been disconnected.")), 184 mid="firewire-bus-reset-%d" % s['nodecount'], 185 priority=40) 186 self.state.append('messages', m)
187