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)); } }
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 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); }
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; }