예제 #1
0
        /// <summary>
        /// Create a new PES packet manager.
        /// </summary>
        /// <param name="other">Template manager.</param>
        public Packet( Packet other )
            : this( other.m_Manager, other.PID )
        {
            // Clone the type
            m_Video = other.m_Video;

            // Copy flags
            IgnorePTS = other.IgnorePTS;
        }
예제 #2
0
        /// <summary>
        /// Remove the next complete PES package from the waiting queue
        /// and <see cref="SendTo"/> the transport stream.
        /// </summary>
        /// <remarks>
        /// Only call this method if the queue is not empty.
        /// </remarks>
        /// <param name="packet">First packet already read from the queue.</param>
        /// <returns>Set if anything has been sent.</returns>
        private bool Dequeue( Packet packet )
        {
            // Dequeue
            Pending.RemoveAt( 0 );

            // Send all
            return packet.SendTo();
        }
예제 #3
0
        /// <summary>
        /// Append a complete PES package to the processing queue.
        /// </summary>
        /// <param name="buffer">A complete PES package.</param>
        public void Enqueue( Packet buffer )
        {
            // Count
            m_LastPacket = DateTime.UtcNow;

            // Set flag
            if (!PTSMissing)
                if (IgnorePTS)
                    PTSMissing = true;
                else if (buffer.Count > 0)
                    PTSMissing = (buffer.PTS < 0);

            // Remember
            Pending.Add( buffer );

            // Check
            if (Pending.Count > m_MaxQueue) m_MaxQueue = Pending.Count;
        }
예제 #4
0
        /// <summary>
        /// Create a new transport stream identifier for a new stream
        /// in this transport stream.
        /// </summary>
        /// <param name="type">Type of the stream.</param>
        /// <param name="encoding">Encoding type of the stream.</param>
        /// <param name="isPCR">Set if the stream will be the PCR reference.</param>
        /// <param name="noPTS">Set if the stream should not participate in PTS synchronisation.</param>
        /// <param name="info">Information on the contents of a subtitle stream.</param>
        /// <param name="noPCR">Set to disable PCR from PTS generation.</param>
        /// <returns>A randomly choosen but unique transport stream identifier.</returns>
        private short AddStream( StreamTypes type, byte encoding, bool noPCR, bool noPTS, EPG.SubtitleInfo[] info, out bool isPCR )
        {
            // Create pid
            short pid = NextPID++;

            // Make key
            int keyPID = pid;

            // Forward
            isPCR = ProgramMap.Add( type, encoding, pid, noPCR, info );

            // Reload
            lock (m_Queue)
            {
                // Force PAT change
                PATSent = false;

                // Load
                Packet buffers = (Packet) m_Buffers[keyPID];

                // Create new
                if (null == buffers)
                {
                    // Create new
                    buffers = new Packet( this, keyPID );

                    // Remember
                    m_Buffers[keyPID] = buffers;
                }

                // Set up
                if (StreamTypes.Video == type)
                    buffers.SetAudioVideo( true );
                else if ((StreamTypes.Audio == type) || (StreamTypes.Private == type))
                    buffers.SetAudioVideo( false );

                // May disable PTS synchronisation (e.g. for TeleText streams)
                buffers.IgnorePTS = noPTS;
            }

            // Report
            return pid;
        }
예제 #5
0
        /// <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;
        }
예제 #6
0
        /// <summary>
        /// Send all buffered data to the transport stream. 
        /// </summary>
        /// <param name="pid"></param>
        /// <param name="withPCR">Set to flush PCR, too.</param>
        private void Enqueue( int pid, bool withPCR )
        {
            // Attach to the list
            Packet buffers = (Packet) m_Buffers[pid];

            // Is empty
            if (null == buffers)
                return;

            // Collector packet
            Packet collect = null;

            // Create if not shutting down the stream
            if (!withPCR)
            {
                // Create new
                collect = new Packet( buffers );

                // Clone PTS from PES
                collect.PTS = buffers.PTS;
            }
            else
            {
                // Flush queue
                while (buffers.HasQueue) buffers.Dequeue();
            }

            // Mode
            bool isPCR = false;

            // Process all
            for (int ib = 0, imax = buffers.Count; ib < imax; )
            {
                // Load next
                byte[] buf = buffers[ib++];

                // Switch only
                if (null == buf)
                {
                    // Mark
                    isPCR = true;

                    // Next
                    continue;
                }

                // Last PCR belongs to next PES
                if (isPCR)
                    if (ib == imax)
                        if (!withPCR)
                        {
                            // Reset
                            buffers.Clear();

                            // Append as PCR
                            buffers.Add( null );
                            buffers.Add( buf );

                            // Remember collected data
                            if (collect.Count > 0)
                                buffers.Enqueue( collect );

                            // Finish
                            return;
                        }

                // Reset flag
                isPCR = false;

                // Check mode
                if (null == collect)
                {
                    // Send to file immediately to clenaup all buffers
                    SendBuffer( buf, buffers );
                }
                else
                {
                    // Save for later processing
                    collect.Add( buf );
                }
            }

            // Reset
            buffers.Clear();

            // Remember collected data
            if (null != collect) buffers.Enqueue( collect );
        }