public void AddEvent(StreamBufferEvent bufferEvent) { if (bufferEvent.ProcessAt <= Clock) { bufferLength += bufferEvent.Amount; } else { if (buffer.Count == 0) { buffer.Add(bufferEvent); } else { int index = buffer.Count - 1; while (index > 0 && buffer[index].ProcessAt > bufferEvent.ProcessAt) { index--; } if (index == buffer.Count - 1) { buffer.Add(bufferEvent); } else { if (buffer[index].ProcessAt < bufferEvent.ProcessAt) { index++; } buffer.Insert(index, bufferEvent); } } } }
public void AddEvent(int Amount, long ProcessAt) { if (ProcessAt <= Clock) { StreamBufferEvent bevent = new StreamBufferEvent(Amount, ProcessAt); bufferLength += Amount; } else { AddEvent(new StreamBufferEvent(Amount, ProcessAt)); } }
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; }