/** * Notifies this <tt>Conference</tt> that the ordered list of <tt>Endpoint</tt>s of {@link * #speechActivity} i.e. the dominant speaker history has changed. * * <p>This instance notifies the video <tt>Channel</tt>s about the change so that they may update * their last-n lists and report to this instance which <tt>Endpoint</tt>s are to be asked for * video keyframes. */ private void speechActivityEndpointsChanged() { List<Endpoint> endpoints = null; for (Content content : getContents()) { if (MediaType.VIDEO.equals(content.getMediaType())) { Set<Endpoint> endpointsToAskForKeyframes = null; endpoints = speechActivity.getEndpoints(); for (Channel channel : content.getChannels()) { if (!(channel instanceof RtpChannel)) continue; RtpChannel rtpChannel = (RtpChannel) channel; List<Endpoint> channelEndpointsToAskForKeyframes = rtpChannel.speechActivityEndpointsChanged(endpoints); if ((channelEndpointsToAskForKeyframes != null) && !channelEndpointsToAskForKeyframes.isEmpty()) { if (endpointsToAskForKeyframes == null) { endpointsToAskForKeyframes = new HashSet<>(); } endpointsToAskForKeyframes.addAll(channelEndpointsToAskForKeyframes); } } if ((endpointsToAskForKeyframes != null) && !endpointsToAskForKeyframes.isEmpty()) { content.askForKeyframes(endpointsToAskForKeyframes); } } } }
/** * Expires a specific <tt>Content</tt> of this <tt>Conference</tt> (i.e. if the specified * <tt>content</tt> is not in the list of <tt>Content</tt>s of this <tt>Conference</tt>, does * nothing). * * @param content the <tt>Content</tt> to be expired by this <tt>Conference</tt> */ public void expireContent(Content content) { boolean expireContent; synchronized (contents) { if (contents.contains(content)) { contents.remove(content); expireContent = true; } else expireContent = false; } if (expireContent) content.expire(); }
/** * Gets the <tt>Endpoint</tt>s participating in/contributing to this <tt>Conference</tt>. * * @return the <tt>Endpoint</tt>s participating in/contributing to this <tt>Conference</tt> */ public List<Endpoint> getEndpoints() { List<Endpoint> endpoints; boolean changed = false; synchronized (this.endpoints) { endpoints = new ArrayList<>(this.endpoints.size()); for (Iterator<WeakReference<Endpoint>> i = this.endpoints.iterator(); i.hasNext(); ) { Endpoint endpoint = i.next().get(); if (endpoint == null) { i.remove(); changed = true; } else { endpoints.add(endpoint); } } } if (changed) firePropertyChange(ENDPOINTS_PROPERTY_NAME, null, null); return endpoints; }
/** * Gets a <tt>Content</tt> of this <tt>Conference</tt> which has a specific name. If a * <tt>Content</tt> of this <tt>Conference</tt> with the specified <tt>name</tt> does not exist at * the time the method is invoked, the method initializes a new <tt>Content</tt> instance with the * specified <tt>name</tt> and adds it to the list of <tt>Content</tt>s of this * <tt>Conference</tt>. * * @param name the name of the <tt>Content</tt> which is to be returned * @return a <tt>Content</tt> of this <tt>Conference</tt> which has the specified <tt>name</tt> */ public Content getOrCreateContent(String name) { Content content; synchronized (contents) { for (Content aContent : contents) { if (aContent.getName().equals(name)) { aContent.touch(); // It seems the content is still active. return aContent; } } content = new Content(this, name); if (isRecording()) { content.setRecording(true, getRecordingPath()); } contents.add(content); } if (logger.isInfoEnabled()) { /* * The method Videobridge.getChannelCount() should better be * executed outside synchronized blocks in order to reduce the risks * of causing deadlocks. */ Videobridge videobridge = getVideobridge(); logger.info( "Created content " + name + " of conference " + getID() + ". " + videobridge.getConferenceCountString()); } return content; }
/** * Gets the <tt>Content</tt>s of this <tt>Conference</tt>. * * @return the <tt>Content</tt>s of this <tt>Conference</tt> */ public Content[] getContents() { synchronized (contents) { return contents.toArray(new Content[contents.size()]); } }