/** {@inheritDoc} */ public long getLocalTime(long ssrc, long rtp0) { // don't use getSSRCDesc, because we don't want to create an instance SSRCDesc ssrcDesc = ssrcs.get(ssrc); if (ssrcDesc == null) { return -1; } // get all required times long clockRate; // the clock rate for the RTP clock for the given SSRC long rtp1; // some time X in the RTP clock for the given SSRC double ntp1; // the same time X in the source's wallclock String endpointId; synchronized (ssrcDesc) { clockRate = ssrcDesc.clockRate; rtp1 = ssrcDesc.rtpTime; ntp1 = ssrcDesc.ntpTime; endpointId = ssrcDesc.endpointId; } // if something is missing, we can't calculate the time if (clockRate == -1 || rtp1 == -1 || ntp1 == -1.0 || endpointId == null) { return -1; } Endpoint endpoint = endpoints.get(ssrcDesc.endpointId); if (endpoint == null) { return -1; } double ntp2; // some time Y in the source's wallclock (same clock as for ntp1) long local2; // the same time Y in the local clock synchronized (endpoint) { ntp2 = endpoint.ntpTime; local2 = endpoint.localTime; } if (ntp2 == -1.0 || local2 == -1) { return -1; } // crunch the numbers. we're looking for 'local0', // the local time corresponding to 'rtp0' long local0; double diff1S = ntp1 - ntp2; double diff2S = ((double) TimeUtils.rtpDiff(rtp0, rtp1)) / clockRate; long diffMs = Math.round((diff1S + diff2S) * 1000); local0 = local2 + diffMs; return local0; }
/** * Removes the RTP-NTP mapping for a given SSRC. * * @param ssrc the SSRC for which to remove the RTP-NTP mapping */ void removeMapping(long ssrc) { if (ssrcs.containsKey(ssrc)) { synchronized (ssrcs) { SSRCDesc ssrcDesc = ssrcs.get(ssrc); if (ssrcDesc != null) { synchronized (ssrcDesc) { ssrcDesc.ntpTime = -1.0; ssrcDesc.rtpTime = -1; } } } } }
/** * Returns the <tt>SSRCDesc</tt> instance mapped to the SSRC <tt>ssrc</tt>. If no instance is * mapped to <tt>ssrc</tt>, create one and inserts it in the map. Always returns non-null. * * @param ssrc the ssrc to get the <tt>SSRCDesc</tt> for. * @return the <tt>SSRCDesc</tt> instance mapped to the SSRC <tt>ssrc</tt>. */ private SSRCDesc getSSRCDesc(long ssrc) { SSRCDesc ssrcDesc = ssrcs.get(ssrc); if (ssrcDesc == null) { synchronized (ssrcs) { ssrcDesc = ssrcs.get(ssrc); if (ssrcDesc == null) { ssrcDesc = new SSRCDesc(); ssrcs.put(ssrc, ssrcDesc); } } } return ssrcDesc; }
/** * Returns the <tt>Endpoint</tt> with id <tt>endpointId</tt>. Creates an <tt>Endpoint</tt> if * necessary. Always returns non-null. * * @param endpointId the string identifying the endpoint. * @return the <tt>Endpoint</tt> with id <tt>endpointId</tt>. Creates an <tt>Endpoint</tt> if * necessary. */ private Endpoint getEndpoint(String endpointId) { Endpoint endpoint = endpoints.get(endpointId); if (endpoint == null) { synchronized (endpoints) { endpoint = endpoints.get(endpointId); if (endpoint == null) { endpoint = new Endpoint(); endpoints.put(endpointId, endpoint); } } } return endpoint; }
/** * Closes given {@link #transportManagers} of this <tt>Conference</tt> and removes corresponding * channel bundle. */ void closeTransportManager(TransportManager transportManager) { synchronized (transportManagers) { for (Iterator<IceUdpTransportManager> i = transportManagers.values().iterator(); i.hasNext(); ) { if (i.next() == transportManager) { i.remove(); // Presumably, we have a single association for // transportManager. break; } } // Close manager try { transportManager.close(); } catch (Throwable t) { logger.warn( "Failed to close an IceUdpTransportManager of" + " conference " + getID() + "!", t); // The whole point of explicitly closing the // transportManagers of this Conference is to prevent memory // leaks. Hence, it does not make sense to possibly leave // TransportManagers open because a TransportManager has // failed to close. if (t instanceof InterruptedException) Thread.currentThread().interrupt(); else if (t instanceof ThreadDeath) throw (ThreadDeath) t; } } }
/** * Returns, the <tt>TransportManager</tt> instance for the channel-bundle with ID * <tt>channelBundleId</tt>. If no instance exists and <tt>create</tt> is <tt>true</tt>, one will * be created. * * @param channelBundleId the ID of the channel-bundle for which to return the * <tt>TransportManager</tt>. * @param create whether to create a new instance, if one doesn't exist. * @return the <tt>TransportManager</tt> instance for the channel-bundle with ID * <tt>channelBundleId</tt>. */ IceUdpTransportManager getTransportManager(String channelBundleId, boolean create) { IceUdpTransportManager transportManager; synchronized (transportManagers) { transportManager = transportManagers.get(channelBundleId); if (transportManager == null && create && !isExpired()) { try { // FIXME: the initiator is hard-coded // We assume rtcp-mux when bundle is used, so we make only // one component. transportManager = new IceUdpTransportManager(this, true, 1); } catch (IOException ioe) { throw new UndeclaredThrowableException(ioe); } transportManagers.put(channelBundleId, transportManager); } } return transportManager; }
/** * Adds the channel-bundles of this <tt>Conference</tt> as * <tt>ColibriConferenceIQ.ChannelBundle</tt> instances in <tt>iq</tt>. * * @param iq the <tt>ColibriConferenceIQ</tt> in which to describe. */ void describeChannelBundles(ColibriConferenceIQ iq) { synchronized (transportManagers) { for (Map.Entry<String, IceUdpTransportManager> entry : transportManagers.entrySet()) { ColibriConferenceIQ.ChannelBundle responseBundleIQ = new ColibriConferenceIQ.ChannelBundle(entry.getKey()); entry.getValue().describe(responseBundleIQ); iq.addChannelBundle(responseBundleIQ); } } }
/** Closes the {@link #transportManagers} of this <tt>Conference</tt>. */ private void closeTransportManagers() { synchronized (transportManagers) { for (Iterator<IceUdpTransportManager> i = transportManagers.values().iterator(); i.hasNext(); ) { IceUdpTransportManager transportManager = i.next(); i.remove(); closeTransportManager(transportManager); } } }