Package flumotion :: Package component :: Module decodercomponent
[hide private]

Source Code for Module flumotion.component.decodercomponent

  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,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  """ 
 19  Decoder component, participating in the stream 
 20  """ 
 21   
 22  import gst 
 23  import gst.interfaces 
 24   
 25  from flumotion.common.i18n import N_, gettexter 
 26  from flumotion.common import errors, messages, gstreamer 
 27  from flumotion.component.effects.audioconvert import audioconvert 
 28  from flumotion.component.effects.kuscheduler import kuscheduler 
 29  from flumotion.component.effects.videorate import videorate 
 30  from flumotion.component.effects.videoscale import videoscale 
 31  from flumotion.component import feedcomponent as fc 
 32   
 33  __version__ = "$Rev$" 
 34  T_ = gettexter() 
 35   
 36   
37 -class DecoderComponent(fc.ReconfigurableComponent):
38 39 swallowNewSegment = False 40 disconnectedPads = True 41 42 _feeders_info = [] 43
44 - def configure_pipeline(self, pipeline, properties):
45 # Handle decoder dynamic pads 46 decoder = self.pipeline.get_by_name("decoder") 47 decoder.connect('new-decoded-pad', self._new_decoded_pad_cb) 48 49 self._add_video_effects() 50 self._add_audio_effects()
51
52 - def get_output_elements(self):
53 return [self.get_element(i.name + '-output') 54 for i in self._feeders_info.values()]
55
56 - def _add_video_effects(self):
57 # Add the effects to the component but don't plug them until we have a 58 # valid video pad 59 props = self.config['properties'] 60 is_square = props.get('is-square', False) 61 add_borders = props.get('add-borders', False) 62 width = props.get('width', None) 63 height = props.get('height', None) 64 # Expressed in ms 65 interval = props.get('keyunits-interval', 10000) * gst.MSECOND 66 fr = props.get('framerate', (25, 2)) 67 framerate = gst.Fraction(fr[0], fr[1]) 68 69 self.vr = videorate.Videorate('videorate', None, 70 self.pipeline, framerate) 71 self.addEffect(self.vr) 72 #self.vr.effectBin.set_state(gst.STATE_PLAYING) 73 self.debug("Videorate added") 74 75 self.videoscaler = videoscale.Videoscale('videoscale', self, 76 None, self.pipeline, 77 width, height, is_square, add_borders) 78 self.addEffect(self.videoscaler) 79 #self.videoscaler.effectBin.set_state(gst.STATE_PLAYING) 80 self.debug("Videoscaler added") 81 82 self.vkuscheduler = kuscheduler.KeyUnitsScheduler('keyunits-scheduler', 83 None, self.pipeline, interval) 84 self.addEffect(self.vkuscheduler) 85 self.debug("KeyUnitsScheduler added")
86
87 - def _add_audio_effects(self):
88 # Add the effects to the component but don't plug them until we have a 89 # valid video pad 90 props = self.config['properties'] 91 samplerate = props.get('samplerate', 44100) 92 channels = props.get('channels', 2) 93 interval = props.get('keyunits-interval', 10000) * gst.MSECOND 94 95 self.ar = audioconvert.Audioconvert('audioconvert', None, 96 self.pipeline, channels=channels, 97 samplerate=samplerate) 98 self.addEffect(self.ar) 99 100 self.akuscheduler = kuscheduler.KeyUnitsScheduler('keyunits-scheduler', 101 None, self.pipeline, interval) 102 self.addEffect(self.akuscheduler) 103 self.debug("KeyUnitsScheduler added")
104
105 - def _new_decoded_pad_cb(self, decoder, pad, last):
106 self.log("Decoder %s got new decoded pad %s", decoder, pad) 107 108 new_caps = pad.get_caps() 109 110 # Select a compatible output element 111 for outelem in self.get_output_elements(): 112 output_pad = outelem.get_pad('sink') 113 if output_pad.is_linked(): 114 continue 115 116 pad_caps = output_pad.get_caps() 117 if not new_caps.is_subset(pad_caps): 118 continue 119 120 self.log("Linking decoded pad %s with caps %s to feeder %s", 121 pad, new_caps.to_string(), outelem.get_name()) 122 pad.link(output_pad) 123 self.disconnectedPads = False 124 125 # Plug effects 126 if 'video' in pad_caps.to_string(): 127 self._plug_video_effects(pad) 128 if 'audio' in pad_caps.to_string(): 129 self._plug_audio_effects(pad) 130 return 131 132 self.info("No feeder found for decoded pad %s with caps %s", 133 pad, new_caps.to_string())
134
135 - def _plug_video_effects(self, pad):
136 self.vr.sourcePad = pad 137 self.vr.plug() 138 self.videoscaler.sourcePad = self.vr.effectBin.get_pad("src") 139 self.videoscaler.plug() 140 self.vkuscheduler.sourcePad = self.videoscaler.effectBin.get_pad("src") 141 self.vkuscheduler.plug()
142
143 - def _plug_audio_effects(self, pad):
144 self.ar.sourcePad = pad 145 self.ar.plug() 146 self.akuscheduler.sourcePad = self.ar.effectBin.get_pad("src") 147 self.akuscheduler.plug()
148