/// <summary> /// Startet die Anwendung. Dieses Besipiel liest eine TS Datei ein. /// </summary> /// <param name="args">Der Empfangsport und der Name der TS Datei.</param> public static void Main( string[] args ) { // Be safe try { // Create socket to receive RTP stream using (var analyser = new RtpTransportStreamAnalyser()) using (var file = new DoubleBufferedFile( args[1], 1000000 )) using (var socket = new Socket( AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp ) { Blocking = true }) { // Configure socket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, 10000000 ); // Bind it socket.Bind( new IPEndPoint( IPAddress.IPv6Any, ushort.Parse( args[0] ) ) ); // Buffer to use var buffer = new byte[10000]; // First send to file Action<byte[], int, int> sink = file.Write; // Then to analyse sink += analyser.Feed; // Result processor AsyncCallback whenDone = null; // Starter Action asyncRead = () => socket.BeginReceive( buffer, 0, buffer.Length, SocketFlags.None, whenDone, null ); // Define result processor whenDone = result => { // Be safe try { // Finish var bytes = socket.EndReceive( result ); // Try to dispatch RtpPacketDispatcher.DispatchTSPayload( buffer, 0, bytes, sink ); // Fire next asyncRead(); } catch (ObjectDisposedException) { } }; // Process asyncRead(); // Wait for termination Console.WriteLine( "Press ENTER to End" ); Console.ReadLine(); // Terminate connection socket.Close(); } } catch (Exception e) { // Report Console.WriteLine( "Error: {0}", e.Message ); } // Done Console.ReadLine(); }
/// <summary> /// Call <see cref="Flush()"/> and the <see cref="Stream.Close"/> the target /// stream. /// </summary> public void Dispose() { // Forward to all foreach (StreamBase stream in m_Streams) stream.Dispose(); // Forget m_Streams.Clear(); // Cleanup Flush(); // Finish if (null != Target) { // Done Target.Close(); // Forget Target = null; } // Check file targets using (PendingTarget) PendingTarget = null; using (BufferedTarget) BufferedTarget = null; // Release socket SetStreamTarget( "localhost", 0 ); }
/// <summary> /// Erzeugt einen neuen Datenstrom. /// </summary> /// <param name="path">Optional der volle Pfad zu einer Datei.</param> /// <param name="nextPID">Die als nächstes zu verwendende Datenstromkennung.</param> /// <param name="bufferSize">Die Größe des zu verwendenden Zwischenspeichers.</param> /// <exception cref="ArgumentOutOfRangeException">Der Zwischenspeicher muss mindestens 1.000 Bytes groß sein.</exception> public Manager( string path, short nextPID, int bufferSize ) : this( (Stream) null, nextPID ) { // Validate if (bufferSize <= 1000) throw new ArgumentOutOfRangeException( "bufferSize" ); // Remember m_BufferSize = bufferSize; // Open the file if (path != null) BufferedTarget = CreateBuffered( path ); }
/// <summary> /// Send the buffer to the target streams. /// </summary> /// <param name="buf">Full buffer to send.</param> /// <param name="source">The originator of the buffer.</param> /// <returns>Set if buffer is not empty.</returns> internal bool SendBuffer( byte[] buf, Packet source ) { // Validate Debug.Assert( (buf.Length % FullSize) == 0 ); // Count m_Length += buf.Length; // Count sometimes if (source != null) { // Count bytes for audio and video only if (source.IsAudioOrVideo) m_AVLength += buf.Length; // See if PCR is now available if (source.PID == -m_PCRAvailable) m_PCRAvailable = source.PID; } // Has file output if (null != Target) { // Must synchronize WaitDisk(); // Start an asynchronous write operation m_Writer = Target.BeginWrite( buf, 0, buf.Length, null, null ); } // Has buffered output if (null != BufferedTarget) { // See if anyone is interested in PCR reports var pcrReport = OnWritingPCR; // Check mode if (pcrReport != null) if ((buf[3] & 0x20) != 0) if (buf[4] >= 1) if ((buf[5] & 0x10) != 0) pcrReport( BufferedTarget.FilePath, BufferedTarget.TotalBytesWritten, buf ); // Send to file BufferedTarget.Write( buf, 0, buf.Length ); } // See if there is a file switch pending var pendingSwitch = Interlocked.Exchange( ref PendingTarget, null ); // Activate the new one - this will enforce a flush on the previous file and may lead to corruption if (pendingSwitch != null) using (BufferedTarget) BufferedTarget = pendingSwitch; // Nothing to do if (buf.Length < 1) return false; // Forward to optional stream m_UDPStream.Send( buf ); // Read consumer var consumer = InProcessConsumer; // Finally send to in-process consumer if (null != consumer) consumer( buf ); // Found some return true; }