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 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  """ 
 23  Decoder component, participating in the stream 
 24  """ 
 25   
 26  import gst 
 27  import gst.interfaces 
 28   
 29  from flumotion.common.i18n import N_, gettexter 
 30  from flumotion.common import errors, messages 
 31  from flumotion.component.effects.audiorate import audiorate 
 32  from flumotion.component.effects.videorate import videorate 
 33  from flumotion.component.effects.videoscale import videoscale 
 34  from flumotion.component import feedcomponent as fc 
 35   
 36  __version__ = "$Rev$" 
 37  T_ = gettexter() 
 38   
 39   
40 -class DecoderComponent(fc.ReconfigurableComponent):
41 42 disconnectedPads = True 43 keepStreamheaderForLater = True 44 swallowNewSegment = False 45 46 _feeders_info = [] 47
48 - def configure_pipeline(self, pipeline, properties):
49 # Handle decoder dynamic pads 50 eater = self.eaters.values()[0] 51 depay = self.get_element(eater.depayName) 52 depay.get_pad("src").add_event_probe(self._depay_reset_event, eater) 53 54 decoder = self.pipeline.get_by_name("decoder") 55 decoder.connect('new-decoded-pad', self._new_decoded_pad_cb) 56 57 self._add_video_effects() 58 self._add_audio_effects()
59
60 - def get_output_elements(self):
61 return [self.get_element(i.name + '-output') 62 for i in self._feeders_info.values()]
63
64 - def _depay_reset_event(self, pad, event, eater):
65 if event.type != gst.EVENT_CUSTOM_DOWNSTREAM: 66 return True 67 if event.get_structure().get_name() != 'flumotion-reset': 68 return True 69 self.info("Received flumotion-reset, not droping buffers anymore") 70 71 self.dropStreamHeaders = False 72 if self.disconnectedPads: 73 return False 74 return True
75
76 - def _add_video_effects(self):
77 # Add the effects to the component but don't plug them until we have a 78 # valid video pad 79 props = self.config['properties'] 80 is_square = props.get('is-square', False) 81 add_borders = props.get('add-borders', False) 82 width = props.get('width', None) 83 height = props.get('height', None) 84 fr = props.get('framerate', (25, 2)) 85 framerate = gst.Fraction(fr[0], fr[1]) 86 87 self.vr = videorate.Videorate('videorate', None, 88 self.pipeline, framerate) 89 self.addEffect(self.vr) 90 #self.vr.effectBin.set_state(gst.STATE_PLAYING) 91 self.debug("Videorate added") 92 93 self.videoscaler = videoscale.Videoscale('videoscale', self, 94 None, self.pipeline, 95 width, height, is_square, add_borders) 96 self.addEffect(self.videoscaler) 97 #self.videoscaler.effectBin.set_state(gst.STATE_PLAYING) 98 self.debug("Videoscaler added")
99
100 - def _add_audio_effects(self):
101 # Add the effects to the component but don't plug them until we have a 102 # valid video pad 103 props = self.config['properties'] 104 samplerate = props.get('samplerate', 44100) 105 106 self.ar = audiorate.Audiorate('audiorate', None, 107 self.pipeline, samplerate) 108 self.addEffect(self.ar)
109
110 - def _new_decoded_pad_cb(self, decoder, pad, last):
111 self.log("Decoder %s got new decoded pad %s", decoder, pad) 112 113 self.dropStreamHeaders = True 114 new_caps = pad.get_caps() 115 116 # Select a compatible output element 117 for outelem in self.get_output_elements(): 118 output_pad = outelem.get_pad('sink') 119 if output_pad.is_linked(): 120 continue 121 122 pad_caps = output_pad.get_caps() 123 if not new_caps.is_subset(pad_caps): 124 continue 125 126 self.log("Linking decoded pad %s with caps %s to feeder %s", 127 pad, new_caps.to_string(), outelem.get_name()) 128 pad.link(output_pad) 129 self.disconnectedPads = False 130 131 # Plug effects 132 if 'video' in pad_caps.to_string(): 133 self._plug_video_effects(pad) 134 if 'audio' in pad_caps.to_string(): 135 self._plug_audio_effects(pad) 136 return 137 138 self.info("No feeder found for decoded pad %s with caps %s", 139 pad, new_caps.to_string())
140
141 - def _plug_video_effects(self, pad):
142 self.vr.sourcePad = pad 143 self.vr.plug() 144 self.videoscaler.sourcePad = self.vr.effectBin.get_pad("src") 145 self.videoscaler.plug()
146
147 - def _plug_audio_effects(self, pad):
148 self.ar.sourcePad = pad 149 self.ar.plug()
150