Beispiel #1
0
 public TransportPackets Packetize(long initialPTS, ushort PID, ref int ContinuityCounter)
 {
     if (GeneratePTSPacket)
     {
         TransportPackets result = new TransportPackets();
         result.AddPacket(GeneratePTSPadding(initialPTS, PID, ref ContinuityCounter));
         return(result);
     }
     else
     {
         return(PacketizeFile(initialPTS, PID, ref ContinuityCounter));
     }
 }
Beispiel #2
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;
        }
Beispiel #3
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);
        }
Beispiel #4
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);
        }
        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;
        }