/** * Implements {@link ActiveSpeakerChangedListener#activeSpeakerChanged(long)}. Notifies this * <tt>RecorderRtpImpl</tt> that the audio <tt>ReceiveStream</tt> considered active has changed, * and that the new active stream has SSRC <tt>ssrc</tt>. * * @param ssrc the SSRC of the new active stream. */ @Override public void activeSpeakerChanged(long ssrc) { if (eventHandler != null) { RecorderEvent e = new RecorderEvent(); e.setAudioSsrc(ssrc); // TODO: how do we time this? e.setInstant(System.currentTimeMillis()); e.setType(RecorderEvent.Type.SPEAKER_CHANGED); e.setMediaType(MediaType.VIDEO); eventHandler.handleEvent(e); } }
private void audioRecordingStarted(long ssrc, long timestamp) { ReceiveStreamDesc desc = findReceiveStream(ssrc); if (desc == null) return; RecorderEvent event = new RecorderEvent(); event.setType(RecorderEvent.Type.RECORDING_STARTED); event.setMediaType(MediaType.AUDIO); event.setSsrc(ssrc); event.setRtpTimestamp(timestamp); event.setFilename(desc.filename); if (eventHandler != null) eventHandler.handleEvent(event); }
/** * Expires this <tt>Conference</tt>, its <tt>Content</tt>s and their respective <tt>Channel</tt>s. * Releases the resources acquired by this instance throughout its life time and prepares it to be * garbage collected. */ public void expire() { synchronized (this) { if (expired) return; else expired = true; } EventAdmin eventAdmin = videobridge.getEventAdmin(); if (eventAdmin != null) eventAdmin.sendEvent(EventFactory.conferenceExpired(this)); setRecording(false); if (recorderEventHandler != null) { recorderEventHandler.close(); recorderEventHandler = null; } Videobridge videobridge = getVideobridge(); try { videobridge.expireConference(this); } finally { // Expire the Contents of this Conference. for (Content content : getContents()) { try { content.expire(); } catch (Throwable t) { logger.warn( "Failed to expire content " + content.getName() + " of conference " + getID() + "!", t); if (t instanceof InterruptedException) Thread.currentThread().interrupt(); else if (t instanceof ThreadDeath) throw (ThreadDeath) t; } } // Close the transportManagers of this Conference. Normally, there // will be no TransportManager left to close at this point because // all Channels have expired and the last Channel to be removed from // a TransportManager closes the TransportManager. However, a // Channel may have expired before it has learned of its // TransportManager and then the TransportManager will not close. closeTransportManagers(); if (logger.isInfoEnabled()) { logger.info( "Expired conference " + getID() + ". " + videobridge.getConferenceCountString()); } } }
/** * Notifies this instance that {@link #speechActivity} has identified a speaker switch event in * this multipoint conference and there is now a new dominant speaker. */ private void dominantSpeakerChanged() { Endpoint dominantSpeaker = speechActivity.getDominantEndpoint(); if (logger.isTraceEnabled()) { logger.trace( "The dominant speaker in conference " + getID() + " is now the endpoint " + ((dominantSpeaker == null) ? "(null)" : dominantSpeaker.getID()) + "."); } if (dominantSpeaker != null) { broadcastMessageOnDataChannels(createDominantSpeakerEndpointChangeEvent(dominantSpeaker)); if (isRecording() && (recorderEventHandler != null)) recorderEventHandler.dominantSpeakerChanged(dominantSpeaker); } }
/** * 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; }
private void handleRtcpPacket(RawPacket pkt) { getSynchronizer().addRTCPPacket(pkt); eventHandler.nudge(); }