/** * 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); } } } }
/** * Finds a <tt>Channel</tt> of this <tt>Conference</tt> which receives a specific SSRC and is with * a specific <tt>MediaType</tt>. * * @param receiveSSRC the SSRC of a received RTP stream whose receiving <tt>Channel</tt> in this * <tt>Conference</tt> is to be found * @param mediaType the <tt>MediaType</tt> of the <tt>Channel</tt> to be found * @return the <tt>Channel</tt> in this <tt>Conference</tt> which receives the specified * <tt>ssrc</tt> and is with the specified <tt>mediaType</tt>; otherwise, <tt>null</tt> */ public Channel findChannelByReceiveSSRC(long receiveSSRC, MediaType mediaType) { for (Content content : getContents()) { if (mediaType.equals(content.getMediaType())) { Channel channel = content.findChannelByReceiveSSRC(receiveSSRC); if (channel != null) return channel; } } return null; }
/** * Checks whether media recording is currently enabled for this <tt>Conference</tt>. * * @return <tt>true</tt> if media recording is currently enabled for this <tt>Conference</tt>, * false otherwise. */ public boolean isRecording() { boolean recording = this.recording; // if one of the contents is not recording, stop all recording if (recording) { synchronized (contents) { for (Content content : contents) { MediaType mediaType = content.getMediaType(); if (!MediaType.VIDEO.equals(mediaType) && !MediaType.AUDIO.equals(mediaType)) continue; if (!content.isRecording()) recording = false; } } } if (this.recording != recording) setRecording(recording); return this.recording; }
/** * Attempts to enable or disable media recording for this <tt>Conference</tt>. * * @param recording whether to enable or disable recording. * @return the state of the media recording for this <tt>Conference</tt> after the attempt to * enable (or disable). */ public boolean setRecording(boolean recording) { if (recording != this.recording) { if (recording) { // try enable recording if (logger.isDebugEnabled()) { logger.debug("Starting recording for conference with id=" + getID()); } String path = getRecordingPath(); boolean failedToStart = !checkRecordingDirectory(path); if (!failedToStart) { RecorderEventHandler handler = getRecorderEventHandler(); if (handler == null) failedToStart = true; } if (!failedToStart) { EndpointRecorder endpointRecorder = getEndpointRecorder(); if (endpointRecorder == null) { failedToStart = true; } else { for (Endpoint endpoint : getEndpoints()) endpointRecorder.updateEndpoint(endpoint); } } /* * The Recorders of the Contents need to share a single * Synchronizer, we take it from the first Recorder. */ boolean first = true; Synchronizer synchronizer = null; for (Content content : contents) { MediaType mediaType = content.getMediaType(); if (!MediaType.VIDEO.equals(mediaType) && !MediaType.AUDIO.equals(mediaType)) { continue; } if (!failedToStart) failedToStart = !content.setRecording(true, path); if (failedToStart) break; if (first) { first = false; synchronizer = content.getRecorder().getSynchronizer(); } else { Recorder recorder = content.getRecorder(); if (recorder != null) recorder.setSynchronizer(synchronizer); } content.feedKnownSsrcsToSynchronizer(); } if (failedToStart) { recording = false; logger.warn("Failed to start media recording for conference " + getID()); } } // either we were asked to disable recording, or we failed to // enable it if (!recording) { if (logger.isDebugEnabled()) { logger.debug("Stopping recording for conference with id=" + getID()); } for (Content content : contents) { MediaType mediaType = content.getMediaType(); if (MediaType.AUDIO.equals(mediaType) || MediaType.VIDEO.equals(mediaType)) { content.setRecording(false, null); } } if (recorderEventHandler != null) recorderEventHandler.close(); recorderEventHandler = null; recordingPath = null; recordingDirectory = null; if (endpointRecorder != null) endpointRecorder.close(); endpointRecorder = null; } this.recording = recording; } return this.recording; }