/// <summary> /// setup the initial buffers and write the basic stream data to the db /// </summary> /// <param name="participant">for this participant</param> /// <param name="stream">using this rtp stream</param> public StreamRecorder(int participantID, RtpStream stream, ConferenceRecorderPC conferencePerfCounter) { this.rtpStream = stream; this.perfCounter = conferencePerfCounter; this.partID = participantID; // We do *not* re-use existing streams if a stream goes away and comes back. This decision was made // becuase it causes the client not to see the Rtcp data die & come back during playback, though it // did during recording. This inconsistency was viewed to cause problems, and was removed. InitStream(); buffers = new BufferRecorder[Constants.MaxBuffers]; bufferCount = Constants.InitialBuffers; for (int i = 0; i < bufferCount; i++) { buffers[i] = new BufferRecorder(i, streamID); buffers[i].Overflowed += new EventHandler(this.OnOverflowException); perfCounter.AddInstanceForCollection(buffers[i]); } curBufIndex = 0; currentBuffer = buffers[curBufIndex]; rtpStream.FrameReceived += new MSR.LST.Net.Rtp.RtpStream.FrameReceivedEventHandler(FrameReceived); }
/// <summary> /// setup the initial buffers and write the basic stream data to the db /// </summary> /// <param name="participant">for this participant</param> /// <param name="stream">using this rtp stream</param> public StreamRecorder( int participantID, RtpStream stream, ConferenceRecorderPC conferencePerfCounter ) { this.rtpStream = stream; this.perfCounter = conferencePerfCounter; this.partID = participantID; // We do *not* re-use existing streams if a stream goes away and comes back. This decision was made // becuase it causes the client not to see the Rtcp data die & come back during playback, though it // did during recording. This inconsistency was viewed to cause problems, and was removed. InitStream(); buffers = new BufferRecorder[Constants.MaxBuffers]; bufferCount = Constants.InitialBuffers; for ( int i = 0; i < bufferCount; i++) { buffers[i] = new BufferRecorder( i, streamID ); buffers[i].Overflowed += new EventHandler(this.OnOverflowException); perfCounter.AddInstanceForCollection(buffers[i]); } curBufIndex = 0; currentBuffer = buffers[curBufIndex]; rtpStream.FrameReceived += new MSR.LST.Net.Rtp.RtpStream.FrameReceivedEventHandler(FrameReceived); }
// // If data is collected from ConferenceRecorder, or some other class, // add an overloaded AddInstanceForCollection method here. // // Note: You could, if you wanted, make AddInstanceForCollection accept an object, // but that would be less performant (and this is a *Performance*Counter... :) // /// <summary> /// Remove an instance from the set of classes on which data is collected. /// </summary> internal void RemoveInstanceForCollection(BufferRecorder bm) { lock (buffers) { if (buffers.Contains(bm)) { buffers.Remove(bm); } } }
/// <summary> /// Accepts an instance of a class on which data is collected for this performance counter category. /// </summary> internal void AddInstanceForCollection(BufferRecorder bm) { lock (buffers) { if (!buffers.Contains(bm)) { buffers.Add(bm); } } }
private bool IncrementBuffer() { // increment the buffer we use.... int bufIndex = (curBufIndex + 1) % bufferCount; while (bufIndex != curBufIndex) { if (buffers[bufIndex].Available == true) { curBufIndex = bufIndex; currentBuffer = buffers[curBufIndex]; return(true); } bufIndex = (bufIndex + 1) % bufferCount; } // no buffers available so grow... if (bufferCount < buffers.Length) { eventLog.WriteEntry("Growing buffers for stream " + streamID + " to " + (bufferCount + 1), EventLogEntryType.Warning, ArchiveServiceEventLog.ID.GrowingBuffers); bufIndex = bufferCount; bufferCount++; buffers[bufIndex] = new BufferRecorder(bufIndex, streamID); buffers[bufIndex].Overflowed += new EventHandler(this.OnOverflowException); perfCounter.AddInstanceForCollection(buffers[bufIndex]); curBufIndex = bufIndex; currentBuffer = buffers[curBufIndex]; return(true); } else { // Uut of buffers logged in return. Also, we return w/o having changed which buffer is the current // one b/c we expect the next buffer to be the first one to become available. return(false); } }
public void StopListening() { if (rtpStream != null) { rtpStream.FrameReceived -= new RtpStream.FrameReceivedEventHandler(FrameReceived); this.rtpStream = null; } int curIndex = curBufIndex; if (buffers != null) { do { BufferRecorder buf = buffers[curBufIndex]; perfCounter.RemoveInstanceForCollection(buf); buf.Dispose(); curBufIndex = (curBufIndex + 1) % bufferCount; }while (curBufIndex != curIndex); this.buffers = null; } }
private void ProcessFrame(object argument) { lock (this) { FrameWithTicks frame = (FrameWithTicks)argument; this.receivedBytes = this.receivedBytes + (long)frame.frame.Length; ++receivedFrames; // Verify the frame fits in a buffer. If not, write it to the database directly. if (frame.frame.Length < Constants.BufferSize) { // if there is no room in the current buffer if (!currentBuffer.HasRoom(frame.frame.Length)) { // With bufferAvailable we try to prevent writing the dropped frame event to the EventLog too often // Incidentally, that means we'll be writing once per every time we use up the buffer pool. If we // have a sudden flood of data, that means it'll only get written once or twice, which helps perf. bool bufferAvailable = false; if (currentBuffer.Available) { currentBuffer.EnableWrite(); ++writtenBuffers; bufferAvailable = true; } if (!IncrementBuffer()) { // Discard the packet by doing nothing with it if (bufferAvailable) { // Warn the user eventLog.WriteEntry("Dropping a frame in StreamRecorder::OnFrameReceived due to no buffers being available.", EventLogEntryType.Error, ArchiveServiceEventLog.ID.FrameDropped); } ++droppedFrames; return; } } currentBuffer.AddFrame(frame); } else { Trace.WriteLine("Writing frame directly to disk. Frame size: " + frame.frame.Length); // Force pending data to be written to disk if (currentBuffer.Available) { currentBuffer.EnableWrite(); ++writtenBuffers; } // Get our new buffer IncrementBuffer(); // And write this frame directly to disk BufferRecorder.DirectWrite(frame, this.streamID); } ++writtenFrames; } }
// // If data is collected from ConferenceRecorder, or some other class, // add an overloaded AddInstanceForCollection method here. // // Note: You could, if you wanted, make AddInstanceForCollection accept an object, // but that would be less performant (and this is a *Performance*Counter... :) // /// <summary> /// Remove an instance from the set of classes on which data is collected. /// </summary> internal void RemoveInstanceForCollection(BufferRecorder bm) { lock(buffers) { if( buffers.Contains(bm) ) buffers.Remove(bm); } }
/// <summary> /// Accepts an instance of a class on which data is collected for this performance counter category. /// </summary> internal void AddInstanceForCollection(BufferRecorder bm) { lock(buffers) { if( !buffers.Contains(bm) ) buffers.Add(bm); } }
private bool IncrementBuffer() { // increment the buffer we use.... int bufIndex = (curBufIndex+1) % bufferCount; while (bufIndex != curBufIndex) { if (buffers[bufIndex].Available == true) { curBufIndex = bufIndex; currentBuffer = buffers[curBufIndex]; return true; } bufIndex = ( bufIndex+1 ) % bufferCount; } // no buffers available so grow... if (bufferCount < buffers.Length) { eventLog.WriteEntry(string.Format(CultureInfo.CurrentCulture, Strings.GrowingBuffers, streamID, (bufferCount + 1)), EventLogEntryType.Warning, ArchiveServiceEventLog.ID.GrowingBuffers ); bufIndex = bufferCount; bufferCount++; buffers[bufIndex] = new BufferRecorder (bufIndex, streamID); buffers[bufIndex].Overflowed += new EventHandler(this.OnOverflowException); perfCounter.AddInstanceForCollection( buffers[bufIndex] ); curBufIndex = bufIndex; currentBuffer = buffers[curBufIndex]; return true; } else { // Uut of buffers logged in return. Also, we return w/o having changed which buffer is the current // one b/c we expect the next buffer to be the first one to become available. return false; } }