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 use_audiorate=False) 99 self.addEffect(self.ar) 100 101 self.akuscheduler = kuscheduler.KeyUnitsScheduler('keyunits-scheduler', 102 None, self.pipeline, interval) 103 self.addEffect(self.akuscheduler) 104 self.debug("KeyUnitsScheduler added")
105
106 - def _new_decoded_pad_cb(self, decoder, pad, last):
107 self.log("Decoder %s got new decoded pad %s", decoder, pad) 108 109 new_caps = pad.get_caps() 110 111 # Select a compatible output element 112 for outelem in self.get_output_elements(): 113 output_pad = outelem.get_pad('sink') 114 if output_pad.is_linked(): 115 continue 116 117 pad_caps = output_pad.get_caps() 118 if not new_caps.is_subset(pad_caps): 119 continue 120 121 self.log("Linking decoded pad %s with caps %s to feeder %s", 122 pad, new_caps.to_string(), outelem.get_name()) 123 pad.link(output_pad) 124 self.disconnectedPads = False 125 126 # Plug effects 127 if 'video' in pad_caps.to_string(): 128 self._plug_video_effects(pad) 129 if 'audio' in pad_caps.to_string(): 130 self._plug_audio_effects(pad) 131 return 132 133 self.info("No feeder found for decoded pad %s with caps %s", 134 pad, new_caps.to_string())
135
136 - def _plug_video_effects(self, pad):
137 self.vr.sourcePad = pad 138 self.vr.plug() 139 self.videoscaler.sourcePad = self.vr.effectBin.get_pad("src") 140 self.videoscaler.plug() 141 self.vkuscheduler.sourcePad = self.videoscaler.effectBin.get_pad("src") 142 self.vkuscheduler.plug()
143
144 - def _plug_audio_effects(self, pad):
145 self.ar.sourcePad = pad 146 self.ar.plug() 147 self.akuscheduler.sourcePad = self.ar.effectBin.get_pad("src") 148 self.akuscheduler.plug()
149