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