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 BufferManager (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; } }
/// <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 StreamManager( 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 BufferManager[Constants.MaxBuffers]; bufferCount = Constants.InitialBuffers; for ( int i = 0; i < bufferCount; i++) { buffers[i] = new BufferManager( 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); }
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 StreamManager::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 BufferManager.DirectWrite(frame, this.streamID); } ++writtenFrames; } }