1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import gst
23 import gobject
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
36
39
41 return self.comp.nbiterations
42
45
46
47
48
49
50
51
52
53
54
55
56
57 -class Looper(feedcomponent.ParseLaunchComponent):
58
59 componentMediumClass = LooperMedium
60
62 self.initial_seek = False
63 self.nbiterations = 0
64 self.fileinformation = None
65 self.timeoutid = 0
66 self.pads_awaiting_block = []
67 self.pads_to_link = []
68 self.bus = None
69 self.uiState.addKey('info-location', '')
70 self.uiState.addKey('info-duration', 0)
71 self.uiState.addKey('info-audio', None)
72 self.uiState.addKey('info-video', None)
73 self.uiState.addKey('num-iterations', 0)
74 self.uiState.addKey('position', 0)
75
80
81 from flumotion.component.producers import checks
82 d = checks.checkTicket349()
83 d.addCallback(on_result)
84 return d
85
87
88 self.bus = None
89 self.videowidth = properties.get('width', 240)
90 self.videoheight = properties.get('height', int(576 * self.videowidth/720.))
91 self.videoframerate = properties.get('framerate', (25, 2))
92 self.filelocation = properties.get('location')
93
94 vstruct = gst.structure_from_string("video/x-raw-yuv,width=%(width)d,height=%(height)d" %
95 dict (width=self.videowidth, height=self.videoheight))
96 vstruct['framerate'] = gst.Fraction(self.videoframerate[0],
97 self.videoframerate[1])
98
99 vcaps = gst.Caps(vstruct)
100
101 self.run_discoverer()
102
103 template = (
104 'filesrc location=%(location)s'
105 ' ! oggdemux name=demux'
106 ' demux. ! queue ! theoradec name=theoradec'
107 ' ! identity name=videolive single-segment=true silent=true'
108 ' ! videorate name=videorate'
109 ' ! videoscale'
110 ' ! %(vcaps)s'
111 ' ! identity name=vident sync=true silent=true ! @feeder:video@'
112 ' demux. ! queue ! vorbisdec name=vorbisdec'
113 ' ! identity name=audiolive single-segment=true silent=true'
114 ' ! audioconvert'
115 ' ! audio/x-raw-int,width=16,depth=16,signed=(boolean)true'
116 ' ! identity name=aident sync=true silent=true ! @feeder:audio@'
117 % dict(location=self.filelocation, vcaps=vcaps))
118
119 return template
120
129
131 def discovered(d, ismedia):
132 self.uiState.set('info-location', self.filelocation)
133 self.uiState.set('info-duration',
134 max(d.audiolength, d.videolength))
135 if d.is_audio:
136 self.uiState.set('info-audio',
137 "%d channel(s) %dHz" % (d.audiochannels,
138 d.audiorate))
139 if d.is_video:
140 self.uiState.set('info-video',
141 "%d x %d at %d/%d fps" % (d.videowidth,
142 d.videoheight,
143 d.videorate.num,
144 d.videorate.denom))
145
146 from gst.extend import discoverer
147 d = discoverer.Discoverer(self.filelocation)
148 d.connect('discovered', discovered)
149 d.discover()
150
152 self.do_seek(False)
153 self.nbiterations += 1
154 self.uiState.set('num-iterations', self.nbiterations)
155
157 for src, sink in self.pads_to_link:
158 src.link(sink)
159 self.do_seek(True)
160 for src, sink in self.pads_to_link:
161 src.set_blocked_async(False, lambda *x: None)
162 self.pads_to_link = []
163 self.nbiterations = 0
164 self.uiState.set('num-iterations', self.nbiterations)
165
175
176 self.oggdemux = pipeline.get_by_name("demux")
177
178 for name in 'aident', 'vident':
179 def blocked(x, is_blocked):
180 if not x in self.pads_awaiting_block:
181 return
182 self.pads_awaiting_block.remove(x)
183 if not self.pads_awaiting_block:
184 s = gst.Structure('pads-blocked')
185 m = gst.message_new_application(pipeline, s)
186
187 pipeline.post_message(m)
188
189 e = pipeline.get_by_name(name)
190 src = e.get_pad('src')
191 sink = src.get_peer()
192 src.unlink(sink)
193 src.set_blocked_async(True, blocked)
194 self.pads_awaiting_block.append(src)
195 self.pads_to_link.append((src, sink))
196
197 self.bus = pipeline.get_bus()
198 self.bus.add_signal_watch()
199
200 self.bus.connect('message', on_message)
201
203 """
204 Restarts the looping.
205
206 Returns True if the seeking was accepted,
207 Returns False otherwiser
208 """
209 self.debug("restarting looping")
210 flags = gst.SEEK_FLAG_SEGMENT | (flushing and gst.SEEK_FLAG_FLUSH or 0)
211 return self.oggdemux.seek(1.0, gst.FORMAT_TIME, flags,
212 gst.SEEK_TYPE_SET, 0, gst.SEEK_TYPE_END, 0)
213
215 def check_time():
216 self.log("checking position")
217 try:
218 pos, format = self.pipeline.query_position(gst.FORMAT_TIME)
219 except:
220 self.debug("position query didn't succeed")
221 else:
222 self.uiState.set('position', pos)
223 return True
224
225 if not self.timeoutid:
226 self.timeoutid = gobject.timeout_add(500, check_time)
227
229 if self.bus:
230 self.bus.remove_signal_watch()
231 self.bus = None
232
233 if self.timeoutid:
234 gobject.source_remove(self.timeoutid)
235 self.timeoutid = 0
236
237 self.nbiterations = 0
238