/// <summary> /// get details of the stream...raw data and start tiume etc /// set up the stream senders associated with us. we have n, one active and the rest acting as buffers /// </summary> public StreamPlayer(RtpSession session, int newStreamID, ConferencePlayerPC cppc) { int maxFrameSize, maxFrameCount, maxBufferSize; // This occasionally throws due to bad data. Let ConferencePlayer handle it. DBHelper.GetStreamStatistics(newStreamID, out this.firstStreamTicks, out maxFrameSize, out maxFrameCount, out maxBufferSize); streamID = newStreamID; totalFramesSent = 0; totalBytesSent = 0; totalLateness = 0; buffers = new BufferPlayer[Constants.BuffersPerStream]; perfCounter = cppc; string payload; DBHelper.GetStreamAndParticipantDetails(streamID, out name, out payload, out cname, out privExtns); streamPayload = (PayloadType)Enum.Parse(typeof(PayloadType), payload, true); // for delayed buffers (late joiners), we create the rtpSender later this.rtpSession = session; Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Playing back stream: {0}; payload: {1}; name: {2} : {3}", streamID, streamPayload, cname, name)); // buffer n buffers worth of data long startingTick = this.firstStreamTicks; for (int i = 0; i < buffers.Length; i++) { buffers[i] = new BufferPlayer(streamID, maxFrameSize, maxFrameCount, maxBufferSize); buffers[i].Populate(startingTick); startingTick = buffers[i].LastTick + 1; perfCounter.AddInstanceForCollection(buffers[i]); } // first stream is initially active activeBufferIndex = 0; activeBuffer = buffers[activeBufferIndex]; }
/// <summary> /// get details of the stream...raw data and start tiume etc /// set up the stream senders associated with us. we have n, one active and the rest acting as buffers /// </summary> public StreamPlayer( RtpSession session, int newStreamID, ConferencePlayerPC cppc) { int maxFrameSize, maxFrameCount, maxBufferSize; // This occasionally throws due to bad data. Let ConferencePlayer handle it. DBHelper.GetStreamStatistics( newStreamID, out this.firstStreamTicks, out maxFrameSize, out maxFrameCount, out maxBufferSize); streamID = newStreamID; totalFramesSent = 0; totalBytesSent = 0; totalLateness = 0; buffers = new BufferPlayer[Constants.BuffersPerStream]; perfCounter = cppc; string payload; DBHelper.GetStreamAndParticipantDetails( streamID, out name, out payload, out cname, out privExtns ); streamPayload = (PayloadType)Enum.Parse( typeof(PayloadType), payload, true ); // for delayed buffers (late joiners), we create the rtpSender later this.rtpSession = session; Trace.WriteLine("Playing back stream: "+streamID+"; payload: "+streamPayload+"; name: "+ (cname + " : " +name)); // buffer n buffers worth of data long startingTick = this.firstStreamTicks; for ( int i = 0; i < buffers.Length; i++) { buffers[i] = new BufferPlayer( streamID, maxFrameSize, maxFrameCount, maxBufferSize); buffers[i].Populate( startingTick ); startingTick = buffers[i].LastTick + 1; perfCounter.AddInstanceForCollection(buffers[i]); } // first stream is initially active activeBufferIndex = 0; activeBuffer = buffers[activeBufferIndex]; }
public void Play( IPEndPoint venue, int[] streams, bool receiveData ) { if( this.playing ) throw new InvalidOperationException("ConferencePlayer::Play called when the player is already playing."); if( streams == null ) throw new ArgumentNullException("streams cannot be null"); venueIPE = venue; // Create an RtpSession RtpParticipant me = new RtpParticipant(Constants.PersistenceCName, Constants.PersistenceName + " (Playing)"); rtpSession = new RtpSession(venue, me, true, receiveData); // Hook the static stream-ended event StreamPlayer.EndOfStreamReached += new EventHandler(EndOfStreamReached); // Create a new perf counter for this ConferencePlayer instance this.perfCounter = new ConferencePlayerPC(venue.ToString()); // Keep track of the streamPlayers ArrayList avStreams = new ArrayList(); ArrayList otherStreams = new ArrayList(); // Find the first stored ticks of all the streams while creating them... this.firstStoredTick = long.MaxValue; // Create all of our StreamPlayers (one per stream...) for ( int i = 0; i < streams.Length; i++) { StreamPlayer newStream = null; try { newStream = new StreamPlayer(rtpSession, streams[i], perfCounter); } catch( Exception ex ) { eventLog.WriteEntry(String.Format("Stream with bad data reached. Continuing playback of all other streams." + " Stream ID: {0}. Exception: \n {1}", streams[i], ex.ToString()), EventLogEntryType.Warning, ArchiveServiceEventLog.ID.BadStreamInDB); } if( newStream != null ) { perfCounter.AddInstanceForCollection( newStream ); if( newStream.FirstStreamsTicks < this.firstStoredTick ) this.firstStoredTick = newStream.FirstStreamsTicks; // Add the new StreamPlayer to the right collection // Pri3: Consider other methods here. Maybe a smarter detection of large frame sizes, // or initializing the stream so it has enough packets ahead of time? if( newStream.Payload == PayloadType.dynamicAudio || newStream.Payload == PayloadType.dynamicVideo ) avStreams.Add(newStream); else // RTDocs stream or other large-payload stream, most likely otherStreams.Add(newStream); } } // Start the StreamsGroupPlayers // Pri2: Change this to be compatable with use of the "playback speed" feature. long startTime = DateTime.Now.Ticks + 1500*Constants.TicksPerMs; // we'll start in 1.5 seconds (for init time) // Create the StreamsGroupPlayer(s) avPlayer = new StreamsGroupPlayer(avStreams, this.firstStoredTick, startTime); otherPlayer = new StreamsGroupPlayer(otherStreams, this.firstStoredTick, startTime); this.playing = true; }
public void Play(IPEndPoint venue, int[] streams, bool receiveData) { if (this.playing) { throw new InvalidOperationException(Strings.PlayerAlreadyPlayingError); } if (streams == null) { throw new ArgumentNullException(Strings.StreamsCannotBeNull); } venueIPE = venue; // Create an RtpSession RtpParticipant me = new RtpParticipant(Constants.PersistenceCName, string.Format(CultureInfo.CurrentCulture, Strings.Playing, Constants.PersistenceName)); rtpSession = new RtpSession(venue, me, true, receiveData); // andrew: connect to diagnostic server rtpSession.VenueName = "Archived: " + venue.ToString(); // Hook the static stream-ended event StreamPlayer.EndOfStreamReached += new EventHandler(EndOfStreamReached); // Create a new perf counter for this ConferencePlayer instance this.perfCounter = new ConferencePlayerPC(venue.ToString()); // Keep track of the streamPlayers ArrayList avStreams = new ArrayList(); ArrayList otherStreams = new ArrayList(); // Find the first stored ticks of all the streams while creating them... this.firstStoredTick = long.MaxValue; // Create all of our StreamPlayers (one per stream...) for (int i = 0; i < streams.Length; i++) { StreamPlayer newStream = null; try { newStream = new StreamPlayer(rtpSession, streams[i], perfCounter); } catch (Exception ex) { eventLog.WriteEntry(String.Format(CultureInfo.CurrentCulture, Strings.StreamWithBadDataReached, streams[i], ex.ToString()), EventLogEntryType.Warning, ArchiveServiceEventLog.ID.BadStreamInDB); } if (newStream != null) { perfCounter.AddInstanceForCollection(newStream); if (newStream.FirstStreamsTicks < this.firstStoredTick) { this.firstStoredTick = newStream.FirstStreamsTicks; } // Add the new StreamPlayer to the right collection // Pri3: Consider other methods here. Maybe a smarter detection of large frame sizes, // or initializing the stream so it has enough packets ahead of time? if (newStream.Payload == PayloadType.dynamicAudio || newStream.Payload == PayloadType.dynamicVideo) { avStreams.Add(newStream); } else // RTDocs stream or other large-payload stream, most likely { otherStreams.Add(newStream); } } } // Start the StreamsGroupPlayers // Pri2: Change this to be compatable with use of the "playback speed" feature. long startTime = DateTime.Now.Ticks + 1500 * Constants.TicksPerMs; // we'll start in 1.5 seconds (for init time) // Create the StreamsGroupPlayer(s) avPlayer = new StreamsGroupPlayer(avStreams, this.firstStoredTick, startTime); otherPlayer = new StreamsGroupPlayer(otherStreams, this.firstStoredTick, startTime); this.playing = true; }