Example #1
0
        public override TransportPacket TakePacket()
        {
            if (TransportPackets.Count == 0)
            {
                while ((inputFile.Position < inputFile.Length) && TransportPackets.Count < (10000000 / 188))
                {
                    if (!ReadNextSequence())
                    {
                        if (TransportPackets.Count == 0)
                        {
                            return(null);
                        }
                        break;
                    }

                    Packetize(InitialDTS);
                }
            }

            TransportPacket result = TransportPackets.TakeFirst();

            if (TransportPackets.Count == 0)
            {
                BufferMore();
            }

            return(result);
        }
        public TransportMultiplexer()
        {
            if (FirstInstance == null)
            {
                FirstInstance = this;
            }

            NullPacket = new TransportPacket();
            NullPacket.ConstructNullPacket();
        }
Example #3
0
        public TransportPacket Last()
        {
            if (Count == 0)
            {
                return(null);
            }

            TransportPacket result = packetList[Count - 1];

            return(result);
        }
Example #4
0
        /// <summary>
        /// This function is a hack to remove a padding packet if it's transmitted after a valid
        /// subtitle packet. The correct solution is to go back and properly design the stream buffer
        /// for the subtitle stream
        /// </summary>
        private void KillPacketsAfterTime(ulong time)
        {
            TransportPacket packet = Packets.Last();

            while (packet != null && packet.StreamTime >= (ulong)time)
            {
                Packets.RemoveLast();
                packet = Packets.Last();
                ContinuityCounter--;    // Rolling back the continuity indicator should do the trick
            }
        }
Example #5
0
        public TransportPacket TakeFirst()
        {
            if (Count == 0)
            {
                return(null);
            }

            TransportPacket result = packetList[0];

            Count--;
            packetList.RemoveAt(0);

            return(result);
        }
Example #6
0
 public void AddPacket(TransportPacket packet)
 {
     Count++;
     packetList.Add(packet);
 }
Example #7
0
        private void ReadNextBuffer(long timeDivision)
        {
            long bytesBeforeTime = BytesBeforeEndOfFrame;
            long frames          = 2;

            bytesBeforeTime += frames * FrameSize;

            StreamBufferEvent ev = new StreamBufferEvent(0 - (FrameSize + 14), InitialPTS + (audioSample * TimePerFrame));

            streamBuffer.AddEvent(ev);
            audioSample++;
            for (int currentFrame = 1; currentFrame < frames; currentFrame++)
            {
                ev = new StreamBufferEvent(0 - FrameSize, InitialPTS + (audioSample * TimePerFrame));
                audioSample++;
                streamBuffer.AddEvent(ev);
            }

            // Attempt to compensate for stream ending
            if (bytesBeforeTime > reader.Remaining)
            {
                bytesBeforeTime = reader.Remaining;
            }

            long packets        = 1 + ((bytesBeforeTime - PACKET_PAYLOAD_LENGTH_PES) / PACKET_PAYLOAD_LENGTH);
            long bytesToConsume = PACKET_PAYLOAD_LENGTH_PES + (packets - 1) * PACKET_PAYLOAD_LENGTH;

            BytesBeforeEndOfFrame = bytesBeforeTime - bytesToConsume;

            if (bytesBeforeTime == reader.Remaining)
            {
                BytesBeforeEndOfFrame = 0;
            }

            int padding = 0;

            if (bytesToConsume > bytesBeforeTime)
            {
                padding        = (int)(bytesToConsume - bytesBeforeTime);
                bytesToConsume = bytesBeforeTime;
            }

            long timeToTransfer = 27000000 * bytesToConsume / ((BitRate * 1000) / 8);
            long timePerPacket  = timeToTransfer / packets;

            long packetTime    = timeDivision / packets + 30000;
            long prebufferTime = (packetTime * packets) + 6000000;

            long decoderStamp = (nextTimeStamp * 300);

            //long streamTime = decoderStamp - timeToTransfer;

            for (int i = 0; i < packets; i++)
            {
                ByteArray transportData = new ByteArray();
                transportData.MaxSize = 188;

                //------------------------------
                // Transport Packet Header
                //------------------------------
                // sync_byte = 0x47					(8 bits)
                transportData.Append((byte)0x47);
                transportData.EnterBitMode();
                // transport_error_indicator		(1 bit)
                transportData.AppendBit(0);
                // payload_unit_start_indicator		(1 bit)
                transportData.AppendBit((byte)((i == 0) ? 1 : 0));
                // transport_priority				(1 bit)
                transportData.AppendBit(0);
                // PID								(13 bits)
                transportData.AppendBits(PID, 12, 0);
                // transport_scrambling_code		(2 bits)
                transportData.AppendBits((byte)0x0, 1, 0);
                // adaptation_field_control			(2 bits)
                transportData.AppendBits((byte)((padding > 0) ? 0x3 : 0x1), 1, 0);
                // continuity_counter				(4 bits)
                transportData.AppendBits(ContinuityCounter, 3, 0);
                ContinuityCounter++;
                transportData.LeaveBitMode();

                int used = 4;

                if (padding > 0)
                {
                    transportData.Append((byte)(padding - 1));
                    if (padding > 1)
                    {
                        transportData.Append((byte)0x00);
                    }
                    for (int paddingIndex = 2; paddingIndex < padding; paddingIndex++)
                    {
                        transportData.Append((byte)0xff);
                    }
                    used   += (int)padding;
                    padding = 0;
                }

                if (i == 0)
                {
                    //-------------------------------
                    // PES Packet Header
                    //-------------------------------
                    // packet_start_code_prefix			(24 bits)	(24)
                    transportData.Append((byte)0x00);
                    transportData.Append((byte)0x00);
                    transportData.Append((byte)0x01);
                    // stream_id						(8 bits)	(32)
                    transportData.Append(StreamId);
                    long packetLengthPosition = transportData.length;

                    ushort packetLength = (ushort)(bytesToConsume + 8);
                    // Fill with dummy value
                    transportData.Append(packetLength);

                    // '10'								(2 bits)	(02)	0x8000
                    // PES_scrambling_code				(2 bits)	(04)	0x0000
                    // PES_priority						(1 bit)		(05)	0x0000
                    // data_alignment_indicator			(1 bit)		(06)	0x0000
                    // copyright						(1 bit)		(07)	0x0000
                    // original_or_copy					(1 bit)		(08)	0x0000
                    // PTS_DTS_flags = '10'				(2 bits)	(10)	0x0080
                    // ESCR_flag						(1 bit)		(11)	0x0000
                    // ES_rate_flag						(1 bit)		(12)	0x0000
                    // DSM_trick_mode_flag				(1 bit)		(13)	0x0000
                    // additional_copy_info				(1 bit)		(14)	0x0000
                    // PES_CRC_flag						(1 bit)		(15)	0x0000
                    // PES_extension_flag				(1 bit)		(16)	0x0000
                    //														0x8080
                    transportData.Append((ushort)0x8480);

                    // PES_header_data_length = 0x05	(8 bits)	(08)
                    transportData.Append((byte)0x05);

                    //   '0010'							(4 bits)	(76)
                    //   PTS[32..30]					(3 bits)	(79)
                    //   marker_bit						(1 bit)		(80)
                    //   PTS[29..15]					(15 bits)	(95)
                    //   marker_bit						(1 bit)		(96)
                    //   PTS[14..0]						(15 bits)	(111)
                    //   marker_bit						(1 bit)		(112)
                    transportData.EnterBitMode();
                    transportData.AppendBits((byte)0x2, 3, 0);
                    transportData.AppendBits(nextTimeStamp, 32, 30);
                    transportData.AppendBit(1);
                    transportData.AppendBits(nextTimeStamp, 29, 15);
                    transportData.AppendBit(1);
                    transportData.AppendBits(nextTimeStamp, 14, 0);
                    transportData.AppendBit(1);
                    transportData.LeaveBitMode();

                    nextTimeStamp += Pts * frames;
                    used          += 14;
                }

                int  payloadLength           = PACKET_LENGTH - used;
                long payloadTransmissionTime = (long)27000000 * (long)payloadLength / (((long)BitRate * 1000) / 8);

                for (int k = 0; k < payloadLength; k++)
                {
                    transportData.Append((byte)reader.ReadByte());
                }

                TransportPacket newPacket = new TransportPacket(transportData.buffer);

                long streamTime = (InitialTime - ((long)((TimePerFrame * 2) * 27000000)) + LastStamp);
                streamBuffer.SetTime(streamTime);
                while (!streamBuffer.CanAdd(184))
                {
                    long newStreamTime = streamBuffer.NextEventTime;
                    LastStamp += newStreamTime - streamTime;
                    streamTime = newStreamTime;
                    streamBuffer.SetTime(streamTime);
                }
                streamBuffer.AddEvent(184, (long)streamTime);

                newPacket.StreamTime   = (ulong)streamTime;
                LastStamp             += payloadTransmissionTime;
                newPacket.DecoderStamp = (ulong)decoderStamp;
                decoderStamp          += payloadTransmissionTime;
                Packets.AddPacket(newPacket);

                /*newPacket.StreamTime = (ulong)(InitialTime + LastStamp);
                 * LastStamp += payloadTransmissionTime;
                 * newPacket.DecoderStamp = (ulong)decoderStamp;*/

                //if (newPacket.DecoderStamp < (ulong)(InitialTime - (0.100 * 27000000) + LastStamp))
                //  throw new Exception("Buffer Underrun");

                //Packets.AddPacket(newPacket);
            }

            CurrentStreamTime += timeToTransfer;
        }
        private void ThreadRun()
        {
            if (writer == null)
            {
                Failed = true;
                return;
            }

            double packetsPerSecond = (double)(BitsPerSecond / 8) / 188;
            ulong  packetTime       = 27000000 / (ulong)packetsPerSecond;

            currentTime = 0;

            ulong nextPacketTime = Streams.NextPacketTime;

            while (nextPacketTime != 0xFFFFFFFFFFFFFFFF && currentTime < EndAfter)
            {
                if (currentTime >= ProgramTables.NextPacketTime)
                {
                    // Checking for cancel here means that the mutex on the cancel bool will only be triggered about
                    // 20 times per second of video processed. This theoretically can cause a mutex lock as many as
                    // 1000 times a second if I ever tweak the buffer reader on the MPEG-2 video stream to handle
                    // peeking more efficiently
                    if (Cancelled)
                    {
                        break;
                    }

                    writer.Write(ProgramTables.NextPacket().Packet, 0, 188);
                    currentTime += packetTime;
                }
                else if (currentTime >= nextPacketTime)
                {
                    TransportPacket nextPacket = Streams.TakePacket(currentTime);
                    if (nextPacket.HasPCR)
                    {
                        nextPacket.SetPCR(currentTime);
                    }

                    if (nextPacket.DecoderStamp < currentTime)
                    {
                        throw new Exception(nextPacket.PID.ToString("{0:X4}") + " Decoder Stamp " + nextPacket.DecoderStamp.ToString() + " > current time " + currentTime.ToString());
                    }

                    writer.Write(nextPacket.Packet, 0, 188);

                    nextPacketTime = Streams.NextPacketTime;
                    currentTime   += packetTime;
                }
                else
                {
                    if (PadToConstant)
                    {
                        NullPacket.IncrementContinuityCounter();
                        writer.Write(NullPacket.Packet, 0, 188);
                    }

                    currentTime += packetTime;
                }
            }

            Close();
            Finished = true;
            return;
        }
Example #9
0
        public void GenerateProgramAssociationTable()
        {
            ByteArray output = new ByteArray();

            // sync_byte = 0x47						(8 bits)
            output.Append((byte)0x47);

            output.EnterBitMode();

            // transport_error_indicator = '0b'		(1 bit)
            output.AppendBit(0);

            // payload_unit_start_indicator = '1b'	(1 bit)
            output.AppendBit(1);

            // transport_priority = '0b'			(1 bit)
            output.AppendBit(0);

            // PID									(13 bits)
            output.AppendBits((ushort)0x0000, 12, 0);

            // transport_scrambling_control = '00b'	(2 bits)
            output.AppendBits((byte)0x00, 1, 0);

            // adaptation_field_control = '01b'		(2 bits)
            //output.appendBits((byte) 0x03, 1, 0);
            output.AppendBits((byte)0x01, 1, 0);

            // continuity_counter					(4 bits)
            output.AppendBits((byte)0x00, 3, 0);

            // pointer_field
            output.AppendBits((byte)0x00, 7, 0);

            long packetStart = output.length;

            // table_id = 0x00 (program_association_section)	(8 bits)
            output.AppendBits((byte)0x00, 7, 0);

            // section_syntax_indicator = 1			(1 bit)
            output.AppendBit(1);

            // '0'									(1 bit)
            output.AppendBit(0);

            // Reserved = '11'						(2 bits)
            output.AppendBits((byte)0x3, 1, 0);

            // section_length						(12 bits)
            long sectionLengthPosition = output.length;

            output.AppendBits((ushort)0x000, 11, 0);

            // transport_stream_id					(16 bits)
            output.AppendBits(TransportStreamId, 15, 0);

            // Reserved = '11'						(2 bits)
            output.AppendBits((byte)0x3, 1, 0);

            // version_number = 0x00				(5 bits)
            output.AppendBits((byte)0x00, 4, 0);

            // current_next_indicator = 1			(1 bit)
            output.AppendBit(1);

            // section_number = 0					(8 bits)
            output.AppendBits((byte)0x00, 7, 0);

            // last_section_number = 0				(8 bits)
            output.AppendBits((byte)0x00, 7, 0);

            // Loop here for more than one program, not supported at the moment
            {
                // program_number					(16 bits)
                output.AppendBits(ProgramNumber, 15, 0);

                // reserved							(3 bits)
                output.AppendBits((byte)7, 2, 0);

                // program_map_PID					(13 bits)
                output.AppendBits(ProgramMapPID, 12, 0);
            }

            output.LeaveBitMode();

            ushort sectionLength = (ushort)(output.length - sectionLengthPosition + 2);

            output[sectionLengthPosition]     = (byte)(output[sectionLengthPosition] | ((sectionLength >> 8) & 0xF));
            output[sectionLengthPosition + 1] = (byte)(sectionLength & 0xFF);

            uint crc = CRC.Calculate(output.buffer, packetStart, output.length - packetStart);

            output.Append(crc);

            while (output.length < 188)
            {
                output.Append((byte)0xFF);
            }

            byte [] buffer = new byte[188];
            for (int i = 0; i < 188; i++)
            {
                buffer[i] = output.buffer[i];
            }

            pat = new TransportPacket(buffer);
        }
Example #10
0
        public void GenerateProgramMap(ushort pid, ushort programNumber, InputStreams streams)
        {
            ProgramMapPID = pid;
            ProgramNumber = programNumber;

            ByteArray output = new ByteArray();

            // sync_byte = 0x47						(8 bits)
            output.Append((byte)0x47);

            output.EnterBitMode();

            // transport_error_indicator = '0b'		(1 bit)
            output.AppendBit(0);

            // payload_unit_start_indicator = '1b'	(1 bit)
            output.AppendBit(1);

            // transport_priority = '0b'			(1 bit)
            output.AppendBit(0);

            // PID									(13 bits)
            output.AppendBits(pid, 12, 0);

            // transport_scrambling_control = '00b'	(2 bits)
            output.AppendBits((byte)0x00, 1, 0);

            // adaptation_field_control = '01b'		(2 bits)
            output.AppendBits((byte)0x01, 1, 0);

            // continuity_counter					(4 bits)
            output.AppendBits((byte)0x00, 3, 0);

            // pointer_field
            output.AppendBits((byte)0x00, 7, 0);

            long packetStart = output.length;

            // table_id = 0x02					(8 bits)
            output.AppendBits((byte)0x02, 7, 0);

            // section_syntax_indicator	'1'		(1 bit)
            output.AppendBit(1);

            // '0'								(1 bit)
            output.AppendBit(0);

            // Reserved = '11'					(2 bits)
            output.AppendBits((byte)0x3, 1, 0);

            // section_length (calculate later)	(12 bits)
            long sectionLengthPosition = output.length;

            output.AppendBits((ushort)0x000, 11, 0);

            // program_number					(16 bits)
            output.AppendBits(programNumber, 15, 0);

            // Reserved = '11'					(2 bits)
            output.AppendBits((byte)0x3, 1, 0);

            // version_number = 0x0				(5 bits)
            output.AppendBits((byte)0x00, 4, 0);

            // current_next_indicator = 0x0		(1 bit)
            output.AppendBit(1);

            // section_number = 0x00			(8 bits)
            output.AppendBits((byte)0x00, 7, 0);

            // current_section_number = 0x00	(8 bits)
            output.AppendBits((byte)0x00, 7, 0);

            // Reserved = '111'					(3 bits)
            output.AppendBits((byte)0x7, 2, 0);

            // PCR_ID							(13 bits)
            output.AppendBits(streams.PcrPID, 12, 0);

            // Reserved = '1111'				(4 bits)
            output.AppendBits((byte)0xF, 3, 0);

            // program_info_length = 0x00		(12 bits)
            // - we ignore this field since it doesn't really matter
            output.AppendBits((ushort)0x000, 11, 0);

            for (long i = 0; i < streams.Count; i++)
            {
                streams[i].GenerateProgramMap(output);
            }

            output.LeaveBitMode();

            ushort sectionLength = (ushort)(output.length - sectionLengthPosition + 2);

            output[sectionLengthPosition]     = (byte)(output[sectionLengthPosition] | ((sectionLength >> 8) & 0xF));
            output[sectionLengthPosition + 1] = (byte)(sectionLength & 0xFF);

            uint crc = CRC.Calculate(output.buffer, packetStart, output.length - packetStart);

            output.Append(crc);

            while (output.length < 188)
            {
                output.Append((byte)0xFF);
            }

            byte[] buffer = new byte[188];
            for (int i = 0; i < 188; i++)
            {
                buffer[i] = output.buffer[i];
            }

            pmt = new TransportPacket(buffer);

            GenerateProgramAssociationTable();
        }
Example #11
0
        private TransportPackets PacketizeFile(long InitialPTS, ushort PID, ref int ContinuityCounter)
        {
            TransportPackets result = new TransportPackets();

            FileStream      inputFileStream = new FileStream(SourceFile, FileMode.Open, FileAccess.Read);
            BigEndianReader reader          = new BigEndianReader(inputFileStream);

            long timeStamp = PresentationTimeStamp + InitialPTS;

            long bytesRemaining = ItemLength;

            int i = 0;

            while (bytesRemaining > 0)
            {
                long stuffingBytes = 0;
                int  headerSize    = (i == 0) ? 18 : 4;
                if (bytesRemaining < 188 - headerSize)
                {
                    stuffingBytes = 188 - headerSize - bytesRemaining;
                }

                ByteArray transportData = new ByteArray();
                transportData.MaxSize = 188;

                //------------------------------
                // Transport Packet Header
                //------------------------------
                // sync_byte = 0x47					(8 bits)
                transportData.Append((byte)0x47);
                transportData.EnterBitMode();
                // transport_error_indicator		(1 bit)
                transportData.AppendBit(0);
                // payload_unit_start_indicator		(1 bit)
                transportData.AppendBit((byte)((i == 0) ? 1 : 0));
                // transport_priority				(1 bit)
                transportData.AppendBit(0);
                // PID								(13 bits)
                transportData.AppendBits(PID, 12, 0);
                // transport_scrambling_code		(2 bits)
                transportData.AppendBits((byte)0x0, 1, 0);
                // adaptation_field_control			(2 bits)
                transportData.AppendBits((byte)((stuffingBytes > 0) ? 0x3 : 0x1), 1, 0);
                // continuity_counter				(4 bits)
                transportData.AppendBits(ContinuityCounter, 3, 0);
                ContinuityCounter++;
                transportData.LeaveBitMode();

                long used = 4;
                if (stuffingBytes > 0)
                {
                    // Adaptation field for stuffing
                    stuffingBytes--;
                    used++;
                    transportData.Append((byte)stuffingBytes);
                    if (stuffingBytes > 0)
                    {
                        used += stuffingBytes;
                        stuffingBytes--;
                        transportData.Append((byte)0x00);       // flags field

                        for (int k = 0; k < stuffingBytes; k++)
                        {
                            transportData.Append((byte)0xFF);   // stuffing byte
                        }
                    }
                    //else
                    //    throw new Exception("Adaptation Field length = 0");
                }

                if (i == 0)
                {
                    //-------------------------------
                    // PES Packet Header
                    //-------------------------------
                    // packet_start_code_prefix			(24 bits)	(24)
                    // stream_id						(8 bits)	(32)
                    transportData.Append((uint)0x000001BD);
                    long packetLengthPosition = transportData.length;

                    ushort packetLength = (ushort)(ItemLength + 8);
                    // Fill with dummy value
                    transportData.Append(packetLength);

                    // '10'								(2 bits)	(02)	0x8000
                    // PES_scrambling_code				(2 bits)	(04)	0x0000
                    // PES_priority						(1 bit)		(05)	0x0000
                    // data_alignment_indicator			(1 bit)		(06)	0x0400
                    // copyright						(1 bit)		(07)	0x0000
                    // original_or_copy					(1 bit)		(08)	0x0000
                    // PTS_DTS_flags = '10'				(2 bits)	(10)	0x0080
                    // ESCR_flag						(1 bit)		(11)	0x0000
                    // ES_rate_flag						(1 bit)		(12)	0x0000
                    // DSM_trick_mode_flag				(1 bit)		(13)	0x0000
                    // additional_copy_info				(1 bit)		(14)	0x0000
                    // PES_CRC_flag						(1 bit)		(15)	0x0000
                    // PES_extension_flag				(1 bit)		(16)	0x0000
                    //														0x8480
                    transportData.Append((ushort)0x8480);

                    // PES_header_data_length = 0x05	(8 bits)	(08)
                    transportData.Append((byte)0x05);

                    //   '0010'							(4 bits)	(76)
                    //   PTS[32..30]					(3 bits)	(79)
                    //   marker_bit						(1 bit)		(80)
                    //   PTS[29..15]					(15 bits)	(95)
                    //   marker_bit						(1 bit)		(96)
                    //   PTS[14..0]						(15 bits)	(111)
                    //   marker_bit						(1 bit)		(112)
                    transportData.EnterBitMode();
                    transportData.AppendBits((byte)0x2, 3, 0);
                    transportData.AppendBits(timeStamp, 32, 30);
                    transportData.AppendBit(1);
                    transportData.AppendBits(timeStamp, 29, 15);
                    transportData.AppendBit(1);
                    transportData.AppendBits(timeStamp, 14, 0);
                    transportData.AppendBit(1);
                    transportData.LeaveBitMode();

                    used += 14;
                }

                int payloadLength = TimelineRegionList.PacketSize - (int)used;
                bytesRemaining -= payloadLength;
                for (int k = 0; k < payloadLength; k++)
                {
                    transportData.Append((byte)reader.ReadByte());
                }

                long bytesIntoStream = ((PacketStart - 1) + i) * TimelineRegionList.PacketSize * 27000000 / TimelineRegionList.ByteRate;
                long streamTime      = bytesIntoStream + (InitialPTS * 300);

                TransportPacket newPacket = new TransportPacket(transportData.buffer);
                newPacket.StreamTime   = (ulong)streamTime;
                newPacket.DecoderStamp = (ulong)timeStamp * 300;
                newPacket.PID          = PID;

                if (newPacket.StreamTime >= newPacket.DecoderStamp)
                {
                    throw new Exception("Packet is scheduled for delivery after decoder time");
                }

                result.AddPacket(newPacket);
                i++;
            }
            reader.Close();
            inputFileStream.Close();

            return(result);
        }
Example #12
0
        private TransportPacket GeneratePTSPadding(long InitialPTS, ushort PID, ref int ContinuityCounter)
        {
            // Stuffing bytes = 188 - (packet header length - pes header length - 4 bytes of padding)

            int stuffingBytes = 188 - (TimelineRegionList.PESHeaderSize + TimelineRegionList.PacketHeaderSize + 12);

            long timeStamp = PresentationTimeStamp + InitialPTS;

            ByteArray transportData = new ByteArray();

            transportData.MaxSize = 188;

            //------------------------------
            // Transport Packet Header
            //------------------------------
            // sync_byte = 0x47					(8 bits)
            transportData.Append((byte)0x47);
            transportData.EnterBitMode();
            // transport_error_indicator		(1 bit)
            transportData.AppendBit(0);
            // payload_unit_start_indicator		(1 bit)
            transportData.AppendBit((byte)(1));
            // transport_priority				(1 bit)
            transportData.AppendBit(0);
            // PID								(13 bits)
            transportData.AppendBits(PID, 12, 0);
            // transport_scrambling_code		(2 bits)
            transportData.AppendBits((byte)0x0, 1, 0);
            // adaptation_field_control			(2 bits)
            transportData.AppendBits((byte)((stuffingBytes > 0) ? 0x3 : 0x1), 1, 0);
            // continuity_counter				(4 bits)
            transportData.AppendBits(ContinuityCounter, 3, 0);
            ContinuityCounter++;
            transportData.LeaveBitMode();

            long used = 4;

            if (stuffingBytes > 0)
            {
                // Adaptation field for stuffing
                stuffingBytes--;
                used++;
                transportData.Append((byte)stuffingBytes);      // adaptation_field_length
                if (stuffingBytes > 0)
                {
                    used += stuffingBytes;
                    stuffingBytes--;
                    transportData.Append((byte)0x00);   // flags field

                    for (int k = 0; k < stuffingBytes; k++)
                    {
                        transportData.Append((byte)0xFF);       // stuffing byte
                    }
                }
            }

            //-------------------------------
            // PES Packet Header
            //-------------------------------
            // packet_start_code_prefix			(24 bits)	(24)
            // stream_id						(8 bits)	(32)
            transportData.Append((uint)0x000001BD);
            long packetLengthPosition = transportData.length;

            ushort packetLength = (ushort)(20);

            // Fill with dummy value
            transportData.Append(packetLength);

            // '10'								(2 bits)	(02)	0x8000
            // PES_scrambling_code				(2 bits)	(04)	0x0000
            // PES_priority						(1 bit)		(05)	0x0000
            // data_alignment_indicator			(1 bit)		(06)	0x0400
            // copyright						(1 bit)		(07)	0x0000
            // original_or_copy					(1 bit)		(08)	0x0000
            // PTS_DTS_flags = '10'				(2 bits)	(10)	0x0080
            // ESCR_flag						(1 bit)		(11)	0x0000
            // ES_rate_flag						(1 bit)		(12)	0x0000
            // DSM_trick_mode_flag				(1 bit)		(13)	0x0000
            // additional_copy_info				(1 bit)		(14)	0x0000
            // PES_CRC_flag						(1 bit)		(15)	0x0000
            // PES_extension_flag				(1 bit)		(16)	0x0000
            //														0x8480
            transportData.Append((ushort)0x8480);

            // PES_header_data_length = 0x05	(8 bits)	(08)
            transportData.Append((byte)0x05);

            //   '0010'							(4 bits)	(76)
            //   PTS[32..30]					(3 bits)	(79)
            //   marker_bit						(1 bit)		(80)
            //   PTS[29..15]					(15 bits)	(95)
            //   marker_bit						(1 bit)		(96)
            //   PTS[14..0]						(15 bits)	(111)
            //   marker_bit						(1 bit)		(112)
            transportData.EnterBitMode();
            transportData.AppendBits((byte)0x2, 3, 0);
            transportData.AppendBits(timeStamp, 32, 30);
            transportData.AppendBit(1);
            transportData.AppendBits(timeStamp, 29, 15);
            transportData.AppendBit(1);
            transportData.AppendBits(timeStamp, 14, 0);
            transportData.AppendBit(1);
            transportData.LeaveBitMode();

            used += 14;

            transportData.Append((byte)0x20); // data_identifier
            transportData.Append((byte)0x00); // subtitle_stream_id
            transportData.Append((byte)0x0F); //   sync_byte
            transportData.Append((byte)0xFF); //4        //   segment_type = stuffing
            transportData.Append((byte)0x00); //   page_id = 0x0002
            transportData.Append((byte)0x02);
            transportData.Append((byte)0x00); //   segment_length = 0x0003
            transportData.Append((byte)0x03); //8
            transportData.Append((byte)0xFF); //     stuffing byte 1
            transportData.Append((byte)0xFF); //     stuffing byte 2
            transportData.Append((byte)0xFF); //     stuffing byte 3
            transportData.Append((byte)0xFF); //12       // end_of_PES_data_field_marker

            long decoderStamp = (timeStamp * 300);

            //long insertTime = (long)(27000000 * 0.040);
            //long streamTime = decoderStamp - insertTime;

            long bytesIntoStream = (PacketStart - 1) * TimelineRegionList.PacketSize * 27000000 / TimelineRegionList.ByteRate;
            long streamTime      = bytesIntoStream + (InitialPTS * 300);

            TransportPacket newPacket = new TransportPacket(transportData.buffer);

            newPacket.StreamTime   = (ulong)streamTime;
            newPacket.DecoderStamp = (ulong)decoderStamp;
            newPacket.PID          = PID;
            newPacket.IsPadding    = true;

            return(newPacket);
        }
Example #13
0
        private void PacketizeFile(string fileName, long timeStamp)
        {
            FileStream      inputFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            BigEndianReader reader          = new BigEndianReader(inputFileStream);

            long dataLength = inputFileStream.Length;

            /*int expectedAdaptationFieldLength = 0; // (int)((dataLength + PES_HEADER_LENGTH_PTS) % 184);
             *
             * int endStuffing = (expectedAdaptationFieldLength == 1) ? 12 : 0;
             *
             * byte [] readBuffer = new byte[dataLength + endStuffing];
             * reader.Read(readBuffer, 0, (int) dataLength);
             * if (expectedAdaptationFieldLength == 1)
             * {
             *  readBuffer[dataLength++] = 0x20;
             *  readBuffer[dataLength++] = 0x00;
             *  readBuffer[dataLength++] = 0x0F;
             *  readBuffer[dataLength++] = 0xFF;//4
             *  readBuffer[dataLength++] = 0x00;
             *  readBuffer[dataLength++] = 0x02;
             *  readBuffer[dataLength++] = 0x00;
             *  readBuffer[dataLength++] = 0x03;//8
             *  readBuffer[dataLength++] = 0xFF;
             *  readBuffer[dataLength++] = 0xFF;
             *  readBuffer[dataLength++] = 0xFF;
             *  readBuffer[dataLength++] = 0xFF;//12
             * }
             * int readIndex = 0;*/

            long lengthAfterPESHeader = dataLength - 14;
            long packets = (lengthAfterPESHeader / 184) + (((lengthAfterPESHeader % 184) == 0) ? 0 : 1);

            timeStamp *= 90;
            timeStamp += InitialPtsInt;
            long decoderStamp = (timeStamp * 300);

            long insertTime        = 27000000 * dataLength / MultiplexByteRate;
            long packetSpacingTime = insertTime / packets;

            insertTime += packetSpacingTime;
            long streamTime = decoderStamp - insertTime;

            long bytesRemaining = dataLength;

            int i = 0;

            while (bytesRemaining > 0)
            {
                long stuffingBytes = 0;
                int  headerSize    = (i == 0) ? 18 : 4;
                if (bytesRemaining < 188 - headerSize)
                {
                    stuffingBytes = 188 - headerSize - bytesRemaining;
                }

                ByteArray transportData = new ByteArray();
                transportData.MaxSize = 188;

                //------------------------------
                // Transport Packet Header
                //------------------------------
                // sync_byte = 0x47					(8 bits)
                transportData.Append((byte)0x47);
                transportData.EnterBitMode();
                // transport_error_indicator		(1 bit)
                transportData.AppendBit(0);
                // payload_unit_start_indicator		(1 bit)
                transportData.AppendBit((byte)((i == 0) ? 1 : 0));
                // transport_priority				(1 bit)
                transportData.AppendBit(0);
                // PID								(13 bits)
                transportData.AppendBits(PID, 12, 0);
                // transport_scrambling_code		(2 bits)
                transportData.AppendBits((byte)0x0, 1, 0);
                // adaptation_field_control			(2 bits)
                transportData.AppendBits((byte)((stuffingBytes > 0) ? 0x3 : 0x1), 1, 0);
                // continuity_counter				(4 bits)
                transportData.AppendBits(ContinuityCounter, 3, 0);
                ContinuityCounter++;
                transportData.LeaveBitMode();

                long used = 4;
                if (stuffingBytes > 0)
                {
                    // Adaptation field for stuffing
                    stuffingBytes--;
                    used++;
                    transportData.Append((byte)stuffingBytes);
                    if (stuffingBytes > 0)
                    {
                        used += stuffingBytes;
                        stuffingBytes--;
                        transportData.Append((byte)0x00);       // flags field

                        for (int k = 0; k < stuffingBytes; k++)
                        {
                            transportData.Append((byte)0xFF);   // stuffing byte
                        }
                    }
                    //else
                    //    throw new Exception("Adaptation Field length = 0");
                }

                if (i == 0)
                {
                    //-------------------------------
                    // PES Packet Header
                    //-------------------------------
                    // packet_start_code_prefix			(24 bits)	(24)
                    // stream_id						(8 bits)	(32)
                    transportData.Append((uint)0x000001BD);
                    long packetLengthPosition = transportData.length;

                    ushort packetLength = (ushort)(dataLength + 8);
                    // Fill with dummy value
                    transportData.Append(packetLength);

                    // '10'								(2 bits)	(02)	0x8000
                    // PES_scrambling_code				(2 bits)	(04)	0x0000
                    // PES_priority						(1 bit)		(05)	0x0000
                    // data_alignment_indicator			(1 bit)		(06)	0x0400
                    // copyright						(1 bit)		(07)	0x0000
                    // original_or_copy					(1 bit)		(08)	0x0000
                    // PTS_DTS_flags = '10'				(2 bits)	(10)	0x0080
                    // ESCR_flag						(1 bit)		(11)	0x0000
                    // ES_rate_flag						(1 bit)		(12)	0x0000
                    // DSM_trick_mode_flag				(1 bit)		(13)	0x0000
                    // additional_copy_info				(1 bit)		(14)	0x0000
                    // PES_CRC_flag						(1 bit)		(15)	0x0000
                    // PES_extension_flag				(1 bit)		(16)	0x0000
                    //														0x8480
                    transportData.Append((ushort)0x8480);

                    // PES_header_data_length = 0x05	(8 bits)	(08)
                    transportData.Append((byte)0x05);

                    //   '0010'							(4 bits)	(76)
                    //   PTS[32..30]					(3 bits)	(79)
                    //   marker_bit						(1 bit)		(80)
                    //   PTS[29..15]					(15 bits)	(95)
                    //   marker_bit						(1 bit)		(96)
                    //   PTS[14..0]						(15 bits)	(111)
                    //   marker_bit						(1 bit)		(112)
                    transportData.EnterBitMode();
                    transportData.AppendBits((byte)0x2, 3, 0);
                    transportData.AppendBits(timeStamp, 32, 30);
                    transportData.AppendBit(1);
                    transportData.AppendBits(timeStamp, 29, 15);
                    transportData.AppendBit(1);
                    transportData.AppendBits(timeStamp, 14, 0);
                    transportData.AppendBit(1);
                    transportData.LeaveBitMode();

                    used += 14;
                }

                int payloadLength = PACKET_LENGTH - (int)used;
                bytesRemaining -= payloadLength;
                for (int k = 0; k < payloadLength; k++)
                {
                    transportData.Append((byte)reader.ReadByte());
                }

                TransportPacket newPacket = new TransportPacket(transportData.buffer);
                newPacket.StreamTime   = (ulong)streamTime + (ulong)(i * packetSpacingTime);
                newPacket.DecoderStamp = (ulong)decoderStamp;
                newPacket.PID          = PID;

                if (newPacket.StreamTime >= newPacket.DecoderStamp)
                {
                    throw new Exception("Packet is scheduled for delivery after decoder time");
                }

                KillPacketsAfterTime(newPacket.StreamTime);
                Packets.AddPacket(newPacket);
                i++;
            }
            reader.Close();
            inputFileStream.Close();
        }
Example #14
0
        private void PacketizePadding(long timeStamp)
        {
            // Stuffing bytes = 188 - (packet header length - pes header length - 4 bytes of padding)

            int stuffingBytes = 188 - (PES_HEADER_LENGTH_PTS + PACKET_HEADER_LENGTH + 12);

            timeStamp *= 90;            // Correct for 90Khz clock
            timeStamp += InitialPtsInt; // Increase spacing for initial PTS

            ByteArray transportData = new ByteArray();

            transportData.MaxSize = 188;

            //------------------------------
            // Transport Packet Header
            //------------------------------
            // sync_byte = 0x47					(8 bits)
            transportData.Append((byte)0x47);
            transportData.EnterBitMode();
            // transport_error_indicator		(1 bit)
            transportData.AppendBit(0);
            // payload_unit_start_indicator		(1 bit)
            transportData.AppendBit((byte)(1));
            // transport_priority				(1 bit)
            transportData.AppendBit(0);
            // PID								(13 bits)
            transportData.AppendBits(PID, 12, 0);
            // transport_scrambling_code		(2 bits)
            transportData.AppendBits((byte)0x0, 1, 0);
            // adaptation_field_control			(2 bits)
            transportData.AppendBits((byte)((stuffingBytes > 0) ? 0x3 : 0x1), 1, 0);
            // continuity_counter				(4 bits)
            transportData.AppendBits(ContinuityCounter, 3, 0);
            ContinuityCounter++;
            transportData.LeaveBitMode();

            long used = 4;

            if (stuffingBytes > 0)
            {
                // Adaptation field for stuffing
                stuffingBytes--;
                used++;
                transportData.Append((byte)stuffingBytes);              // adaptation_field_length
                if (stuffingBytes > 0)
                {
                    used += stuffingBytes;
                    stuffingBytes--;
                    transportData.Append((byte)0x00);                   // flags field

                    for (int k = 0; k < stuffingBytes; k++)
                    {
                        transportData.Append((byte)0xFF);                       // stuffing byte
                    }
                }
            }

            //-------------------------------
            // PES Packet Header
            //-------------------------------
            // packet_start_code_prefix			(24 bits)	(24)
            // stream_id						(8 bits)	(32)
            transportData.Append((uint)0x000001BD);
            long packetLengthPosition = transportData.length;

            ushort packetLength = (ushort)(20);

            // Fill with dummy value
            transportData.Append(packetLength);

            // '10'								(2 bits)	(02)	0x8000
            // PES_scrambling_code				(2 bits)	(04)	0x0000
            // PES_priority						(1 bit)		(05)	0x0000
            // data_alignment_indicator			(1 bit)		(06)	0x0400
            // copyright						(1 bit)		(07)	0x0000
            // original_or_copy					(1 bit)		(08)	0x0000
            // PTS_DTS_flags = '10'				(2 bits)	(10)	0x0080
            // ESCR_flag						(1 bit)		(11)	0x0000
            // ES_rate_flag						(1 bit)		(12)	0x0000
            // DSM_trick_mode_flag				(1 bit)		(13)	0x0000
            // additional_copy_info				(1 bit)		(14)	0x0000
            // PES_CRC_flag						(1 bit)		(15)	0x0000
            // PES_extension_flag				(1 bit)		(16)	0x0000
            //														0x8480
            transportData.Append((ushort)0x8480);

            // PES_header_data_length = 0x05	(8 bits)	(08)
            transportData.Append((byte)0x05);

            //   '0010'							(4 bits)	(76)
            //   PTS[32..30]					(3 bits)	(79)
            //   marker_bit						(1 bit)		(80)
            //   PTS[29..15]					(15 bits)	(95)
            //   marker_bit						(1 bit)		(96)
            //   PTS[14..0]						(15 bits)	(111)
            //   marker_bit						(1 bit)		(112)
            transportData.EnterBitMode();
            transportData.AppendBits((byte)0x2, 3, 0);
            transportData.AppendBits(timeStamp, 32, 30);
            transportData.AppendBit(1);
            transportData.AppendBits(timeStamp, 29, 15);
            transportData.AppendBit(1);
            transportData.AppendBits(timeStamp, 14, 0);
            transportData.AppendBit(1);
            transportData.LeaveBitMode();

            used += 14;

            transportData.Append((byte)0x20);
            transportData.Append((byte)0x00);
            transportData.Append((byte)0x0F);
            transportData.Append((byte)0xFF);//4
            transportData.Append((byte)0x00);
            transportData.Append((byte)0x02);
            transportData.Append((byte)0x00);
            transportData.Append((byte)0x03);//8
            transportData.Append((byte)0xFF);
            transportData.Append((byte)0xFF);
            transportData.Append((byte)0xFF);
            transportData.Append((byte)0xFF);//12

            long decoderStamp = (timeStamp * 300);

            long insertTime = (long)(27000000 * 0.040);
            long streamTime = decoderStamp - insertTime;

            TransportPacket newPacket = new TransportPacket(transportData.buffer);

            newPacket.StreamTime   = (ulong)streamTime;
            newPacket.DecoderStamp = (ulong)decoderStamp;
            newPacket.PID          = PID;
            newPacket.IsPadding    = true;

            Packets.AddPacket(newPacket);
        }
Example #15
0
        private void Packetize(double initialDTS)
        {
            int added = 0;

            for (int i = 0; i < Frames.Count; i++)
            {
                ByteArray pesData = PesForFrame(0, i, initialDTS);
                byte[]    pes     = pesData.buffer;

                double time = Frames[i].DTS - AdjustedVBVDelay;
                if (Frames[i].VBVDelay != 0)
                {
                    time = Frames[i].DTS - Frames[i].VBVDelay;
                }

                if (time < 0)
                {
                    time = 0;
                }

                ulong streamTime   = (ulong)(27000000.0 * time);
                ulong decoderStamp = (ulong)(27000000.0 * Frames[i].DTS);

                long frameTransmissionTime = (long)27000000 * (long)(pesData.length) / (long)(ByteRate * 100 / 100); // * 112 / 100);
                long timeIncrement         = frameTransmissionTime / ((pesData.length / 184) + 1);

                long lastPCR      = 0;
                long index        = 0;
                int  packetNumber = 0;
                while (index < pesData.length)
                {
                    TransportPacket newPacket = new TransportPacket();
                    newPacket.PID = PID;
                    newPacket.ContinuityIndicator = ContinuityIndicator;
                    ContinuityIndicator++;

                    if (index == 0)
                    {
                        newPacket.IsAligned     = true;
                        newPacket.HasAdaptation = true;
                        newPacket.HasPCR        = true;

                        if (firstPacket)
                        {
                            // MD-SP-VOD-CEP-I01040107 - Part 4.6 Transport Stream Requirements
                            // The first PCR packet of the stream must have the transport discontinuity_indicator flag set to 1.
                            newPacket.DiscontinuityIndicator = true;
                            firstPacket = false;
                        }

                        if (Frames[i].StartOfGOP)
                        {
                            // MD-SP-VOD-CEP-I01040107 - Part 4.6 Transport Stream Requirements
                            // Transport packet at the start of a GOP must have random_access_indicator set to 1.
                            newPacket.RandomAccess = true;
                        }
                    }

                    // This section forces a PCR stamp if the current frame is just so big that it will take longer than
                    // the maximum PCR interval to transmit.
                    if ((index - lastPCR) > BytesPerPCRMax)
                    {
                        newPacket.HasAdaptation = true;
                        newPacket.HasPCR        = true;
                        lastPCR = index;
                    }

                    newPacket.DecoderStamp = decoderStamp;
                    newPacket.StreamTime   = streamTime + ((ulong)timeIncrement * (ulong)packetNumber);
                    if (newPacket.StreamTime > decoderStamp)
                    {
                        throw new Exception("Buffer Overflow");
                    }

                    packetNumber++;

                    index += newPacket.Construct(pes, index, pesData.length);
                    added++;

                    TransportPackets.AddPacket(newPacket);
                }
            }

            return;
        }