~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/tcl/psvp/synch-switch.tcl

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 # synch-switch.tcl --
  2 #
  3 #       FIXME: This file needs a description here.
  4 #
  5 # Copyright (c) 1999-2002 The Regents of the University of California.
  6 # All rights reserved.
  7 #
  8 # Redistribution and use in source and binary forms, with or without
  9 # modification, are permitted provided that the following conditions are met:
 10 #
 11 # A. Redistributions of source code must retain the above copyright notice,
 12 #    this list of conditions and the following disclaimer.
 13 # B. Redistributions in binary form must reproduce the above copyright notice,
 14 #    this list of conditions and the following disclaimer in the documentation
 15 #    and/or other materials provided with the distribution.
 16 # C. Neither the names of the copyright holders nor the names of its
 17 #    contributors may be used to endorse or promote products derived from this
 18 #    software without specific prior written permission.
 19 #
 20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 23 # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 24 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 30 
 31 import Observer
 32 import SynchSrcVideoAgent
 33 import VideoAgent
 34 
 35 Class SynchSwitch;
 36 
 37 SynchSwitch instproc init {app} {
 38     $self next;
 39 
 40     $self instvar sources_ synch_transmitters_ source_sessions_
 41     $self instvar master_lts_;
 42     $self instvar app_;
 43     $self instvar new_source_cmd_;
 44 
 45     set app_ $app;
 46 
 47     set sources_ "";
 48     set source_sessions_ "";
 49     set synch_transmitters_ "";
 50 
 51     set master_lts_ [new SynchLTS];
 52     $master_lts_ speed 1.0;
 53     $master_lts_ set_reference 0 0;
 54 
 55     set new_source_cmd_ "";
 56 
 57     $self instvar expansion_speed_ compression_speed_;
 58 
 59     set expansion_speed_ 0.9;
 60     set compression_speed_ 1.1;
 61 }
 62 
 63 SynchSwitch instproc register_source {sess src} {
 64     $self instvar sources_ master_lts_
 65 
 66     set new_src [new SynchSource $sess $src $master_lts_];
 67     lappend sources_ $new_src;
 68 
 69     $self instvar new_source_cmd_;
 70 
 71     if {$new_source_cmd_ != ""} {
 72         eval $new_source_cmd_ $new_src
 73     }
 74 
 75     return $new_src
 76 }
 77 
 78 SynchSwitch instproc unregister_source {src} {
 79     $self instvar sources_;
 80 
 81     set k [lsearch -exact $sources_ $src];
 82     set sources_ [lreplace $sources_ $k $k];
 83 
 84     delete $src;
 85 }
 86 
 87 Class SynchTransmitAgent -superclass VideoAgent
 88 
 89 SynchTransmitAgent instproc create_decoder {src} {
 90     set decoder [new Module/VideoDecoder/Null];
 91     $decoder set src_ $src;
 92     $decoder set agent_ $self;
 93     return $decoder;
 94 }
 95 
 96 SynchTransmitter instproc init {switch spec} {
 97     $self instvar sess_ switch_ src_ srcid_ cur_src_ spec_;
 98 
 99     set spec_ $spec;
100     set sess_ [new SynchTransmitAgent [$switch set app_] $spec];
101 
102     # This is a call to RTPAgent::get_transmitter{}. It returns a handler to 
103     # the Session/RTP/Video object handler created by 
104     # VideoAgent::create_session{} 
105     [$sess_ get_transmitter] set loopback_ 0;
106 
107     # SynchTransmitAgent::local_ is the Source/RTP object that contains the 
108     # information of our own Source object
109     set src_ [$sess_ set local_];
110     set srcid_ [$sess_ get_local_srcid];
111     set cur_src_ "";
112 
113     $self target [$sess_ get_transmitter];
114     $self reset;
115 }
116 
117 Class SynchSource -superclass Observer
118 
119 SynchSource instproc init {sess src master} {
120     $self next;
121 
122     $self instvar sess_ src_ master_;
123 
124     set sess_ $sess;
125     set src_ $src;
126     set master_ $master;
127 
128     $self instvar synch_buffer_ lts_;
129 
130     set synch_buffer_ [new SynchBuffer];
131     $synch_buffer_ set synch_src_ $self;
132 
133     set lts_ [new SynchLTS];
134 
135     $synch_buffer_ lts $lts_;
136     $lts_ lts $master;
137     $lts_ speed 1.0;
138     $synch_buffer_ reset_reference;
139     $sess_ attach $self
140 }
141 
142 SynchSource public trigger_sr {src} {
143     $self instvar src_;
144 
145     if {$src == $src_} {
146         $self instvar synch_buffer_;
147 
148         $synch_buffer_ synch_to_source $src_;
149     }
150 }
151 
152 SynchSource instproc synch_buffer {} {
153     $self instvar synch_buffer_;
154 
155     return $synch_buffer_;
156 }
157 
158 SynchSource instproc buffer_latency {} {
159     $self instvar synch_buffer_;
160     return [$synch_buffer_ buffer_latency];
161 }
162 
163 SynchSource instproc num_frames {} {
164     $self instvar synch_buffer_;
165     return [$synch_buffer_ num_frames];
166 }
167 
168 SynchSource instproc destroy {} {
169     $self instvar synch_buffer_ lts_;
170     $lts_ lts "";
171     $synch_buffer_ lts "";
172     delete $lts_;
173     delete $synch_buffer_;
174 
175     $self instvar sess_;
176     $sess_ detach $self;
177 
178     $self next;
179 }
180 
181 #################
182 # Below is API for Synch Switch although
183 # this is not strictly enforced (i.e.,
184 # procedures defined above are accessible).
185 ################
186 
187 # add_source_session
188 #    Add session for possible sources
189 
190 SynchSwitch instproc add_source_session {spec} {
191     $self instvar app_ source_sessions_;
192 
193     set new_sess [new SynchSrcVideoAgent $app_ $self $spec];
194     lappend source_sessions_ $new_sess;
195 }
196 
197 # new_source_command
198 #    Set callback for when new source is heard
199 
200 SynchSwitch instproc new_source_command {args} {
201     $self instvar new_source_cmd_;
202 
203     if {[llength $args] == 0} {
204         return $new_source_cmd_;
205     } else {
206         set new_source_cmd_ [lindex $args 0];
207     }
208 }
209 
210 # sources
211 #    Return list of sources we know about.
212 
213 SynchSwitch instproc sources {} {
214     $self instvar sources_;
215 
216     return $sources_;
217 }
218 
219 # create_synch_transmitter
220 #    Create a new source for transmission
221 
222 SynchSwitch instproc create_synch_transmitter {spec} {
223     $self instvar synch_transmitters_
224 
225     set tsrc [new SynchTransmitter $self $spec];
226 
227     lappend synch_transmitters_ $tsrc;
228     return $tsrc;
229 }
230 
231 # buffer_latency
232 #    Query current estimated buffer latency for a source.
233 #    If <src> is "", returns a list of source/latency pairs
234 #    for all known sources.
235 
236 SynchSwitch instproc buffer_latency {{src ""}} {
237     if {$src != ""} {
238         return [$src buffer_latency];
239     } else {
240         $self instvar sources_;
241         set res "";
242         foreach s $sources_ {
243             lappend res [list $s [$s buffer_latency]];
244         }
245         return $res;
246     }
247 }
248 
249 # master_speed
250 #    Set/query master LTS speed
251 
252 SynchSwitch instproc master_speed {{speed ""}} {
253     $self instvar master_lts_;
254 
255     if {$speed == ""} {
256         return [$master_lts_ speed];
257     } else {
258         $master_lts_ speed $speed;
259     }
260 }
261 
262 # master_offset_adjust
263 #    Adjust master logical offset by <delta>
264 
265 SynchSwitch instproc master_offset_adjust {delta} {
266     $self instvar master_lts_;
267 
268     $master_lts_ adjust $delta;
269 }
270 
271 # master_time_expansion_speed
272 #    Set/query speed used for time expansion
273 
274 SynchSwitch instproc master_time_expansion_speed {{speed ""}} {
275     $self instvar expansion_speed_;
276 
277     if {$speed == ""} {
278         return $expansion_speed_;
279     } else {
280         set expansion_speed_ $speed;
281     }
282 }
283 
284 # master_time_compression_speed
285 #    Set/query speed used for time compression
286 
287 SynchSwitch instproc master_time_compression_speed {{speed ""}} {
288     $self instvar compression_speed_;
289 
290     if {$speed == ""} {
291         return $compression_speed_;
292     } else {
293         set compression_speed_ $speed;
294     }
295 }
296 
297 # prep_switch
298 #    Switch transmission to specified source after
299 #    eliminating negative latency. Positive latencies
300 #    eliminated after switch only if <no_positive> flag
301 #    set.
302 
303 SynchSwitch instproc prep_switch {src transmitter {no_positive 0}} {
304     $self instvar pending_action_ expansion_speed_ compression_speed_;
305 
306     if {[info exists pending_action_]} {
307         after cancel $pending_action_;
308         unset pending_action_;
309         $self master_speed 1.0;
310     }
311 
312     set sb [$src set synch_buffer_];
313     set lat [$sb buffer_latency];
314     if {$lat < -0.030} {
315         $self master_speed $expansion_speed_;
316         set delta [expr int((($lat * -1.0)/(1.0 - $expansion_speed_)) * 1000.0)];
317 
318         set pending_action_ [after $delta "$self straight_switch $src $transmitter"];
319     } else {
320         $self straight_switch $src $transmitter;
321         if {($lat > 0.030) && $no_positive} {
322             $self master_speed $compression_speed_;
323             set delta [expr int(($lat / ($compression_speed_ - 1.0)) * 1000.0)];
324             set pending_action_ [after $delta "$self straight_switch $src $transmitter"];
325         }
326     }
327 }
328 
329 # switch_prep
330 #    Switch transmission to specified source immediately,
331 #    eliminate negative latency after switch. Positive
332 #    latencies eliminated after switch only if <no_positive>
333 #    flag set.
334 
335 SynchSwitch instproc switch_prep {src transmitter {no_positive 0}} {
336     $self instvar pending_action_ expansion_speed_ compression_speed_;
337 
338     if {[info exists pending_action_]} {
339         after cancel $pending_action_;
340         unset pending_action_;
341         $self master_speed 1.0;
342     }
343 
344     $self straight_switch $src $transmitter;
345 
346     set sb [$src set synch_buffer_];
347     set lat [$sb buffer_latency];
348     if {$lat < -0.030} {
349         $self master_speed $expansion_speed_;
350         set delta [expr int((($lat * -1.0)/(1.0 - $expansion_speed_)) * 1000.0)];
351         set pending_action_ [after $delta "$self straight_switch $src $transmitter"];
352     } else {
353         if {($lat > 0.030) && $no_positive} {
354             $self master_speed $compression_speed_;
355             set delta [expr int(($lat / ($compression_speed_ - 1.0)) * 1000.0)];
356             set pending_action_ [after $delta "$self straight_switch $src $transmitter"];
357         }
358     }
359 }
360 
361 # straight_switch
362 #    Switch transmission without adjusting for latencies
363 
364 SynchSwitch instproc straight_switch {src transmitter} {
365     $self instvar sources_ pending_action_;
366 
367     if {[info exists pending_action_]} {
368         after cancel $pending_action_;
369         unset pending_action_;
370         $self master_speed 1.0;
371     }
372 
373     if {[$transmitter set cur_src_] == $src} {
374         return;
375     }
376 
377     set sb [$src set synch_buffer_];
378 
379     if {[lsearch -exact $sources_ [$transmitter set cur_src_]] != -1} {
380         set old_sb [[$transmitter set cur_src_] set synch_buffer_];
381         if {[$old_sb target] == $transmitter} {
382             $old_sb target "";
383         }
384         $transmitter set cur_src_ "";
385     }
386     $transmitter reset;
387     $transmitter set cur_src_ $src;
388     $sb target $transmitter;
389 }
390 
391 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.