private static void FileStreamWorkerThread(Stream stream) { var data = new byte[188]; var factory = new TsPacketFactory(); while (stream?.Read(data, 0, 188) > 0) { try { var tsPackets = factory.GetTsPacketsFromData(data); if (tsPackets == null) { break; } _analyser.AnalysePackets(tsPackets); } catch (Exception ex) { LogMessage($@"Unhandled exception within file streamer: {ex.Message}"); } } _pendingExit = true; Thread.Sleep(250); Console.WriteLine("Completed reading of file - hit enter to exit!"); Console.ReadLine(); }
private static void PerformUnalignedDataTest(string filename, int expectedPacketCount, int readFragmentSize) { try { var factory = new TsPacketFactory(); //load some data from test file using (var stream = File.Open(filename, FileMode.Open)) { var packetCounter = 0; var data = new byte[readFragmentSize]; var readCount = stream.Read(data, 0, readFragmentSize); while (readCount > 0) { try { if (readCount < readFragmentSize) { var tmpArr = new byte[readCount]; Buffer.BlockCopy(data, 0, tmpArr, 0, readCount); data = new byte[readCount]; Buffer.BlockCopy(tmpArr, 0, data, 0, readCount); } var tsPackets = factory.GetTsPacketsFromData(data); if (tsPackets == null) { break; } packetCounter += tsPackets.Length; if (stream.Position < stream.Length) { readCount = stream.Read(data, 0, readFragmentSize); } else { break; } } catch (Exception ex) { Assert.Fail($@"Unhandled exception reading sample file: {ex.Message}"); } } if (packetCounter != expectedPacketCount) { Assert.Fail($"Failed to read expected number of packets in sample file - expected {expectedPacketCount}, " + $"got {packetCounter}, blocksize: {readFragmentSize}"); } } } catch (Exception ex) { Assert.Fail(ex.Message); } }
private void ProcessQueueWorkerThread() { var dataBuffer = new byte[12 + (188 * 7)]; while (_pendingExit != true) { try { lock (_ringBuffer) { int dataSize; ulong timestamp; if (_ringBuffer.BufferFullness < 10) { Thread.Sleep(1); continue; } var capacity = _ringBuffer.Remove(ref dataBuffer, out dataSize, out timestamp); if (capacity > 0) { dataBuffer = new byte[capacity]; continue; } if (dataBuffer == null) { continue; } var packets = Factory.GetTsPacketsFromData(dataBuffer, dataSize); //use decoder to register default program (muxing always happens on default program) if (_mainStreamDecoder.GetSelectedPmt() == null) { _mainStreamDecoder.AddPackets(packets); } else { if (_mainStreamTargetPmt == null && _subStreamSourcePmt != null) { _mainStreamTargetPmt = _mainStreamDecoder.GetSelectedPmt(); var pmtSpaceNeeded = 0; foreach (var esinfo in _subStreamSourcePmt.EsStreams) { if (_subPids.Contains(esinfo.ElementaryPid)) { pmtSpaceNeeded += esinfo.SourceData.Length; } } if ((_mainStreamTargetPmt.SectionLength + pmtSpaceNeeded) > (TsPacketSize - 12)) { throw new InvalidDataException( "Cannot add to PMT - no room (packet spanned PMT not supported)"); } } } //check for any PMT packets, and adjust them to reflect the new muxed reality... foreach (var packet in packets) { if (_mainStreamTargetPmt != null && packet.Pid == _mainStreamTargetPmt.Pid) { //this is the PMT for the target program on the target stream - patch in the substream PID entries foreach (var esinfo in _subStreamSourcePmt.EsStreams) { if (_subPids.Contains(esinfo.ElementaryPid)) { //locate current SectionLength bytes in databuffer var pos = packet.SourceBufferIndex + 4; //advance to start of PMT data structure (past TS header) var pointerField = dataBuffer[pos]; pos += pointerField; //advance by pointer field var SectionLength = (short)(((dataBuffer[pos + 2] & 0x3) << 8) + dataBuffer[pos + 3]); //get current length //increase length value by esinfo length var extendedSectionLength = (short)(SectionLength + (short)esinfo.SourceData.Length); //set back new length into databuffer var bytes = BitConverter.GetBytes(extendedSectionLength); dataBuffer[pos + 2] = (byte)((dataBuffer[pos + 2] & 0xFC) + (byte)(bytes[1] & 0x3)); dataBuffer[pos + 3] = bytes[0]; //copy esinfo source data to end of program block in pmt Buffer.BlockCopy(esinfo.SourceData, 0, dataBuffer, packet.SourceBufferIndex + 4 + pointerField + SectionLength, esinfo.SourceData.Length); //correct CRC after each extension var crcBytes = BitConverter.GetBytes(GenerateCRC(ref dataBuffer, pos + 1, extendedSectionLength - 1)); dataBuffer[packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength] = crcBytes[3]; dataBuffer[ packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength + 1] = crcBytes[2]; dataBuffer[ packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength + 2] = crcBytes[1]; dataBuffer[ packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength + 3] = crcBytes[0]; } } } } //insert any queued filtered sub PID packets if (_subPidBuffer.BufferFullness > 0) { foreach (var packet in packets) { if (packet.Pid == (short)PidType.NullPid) { //candidate for wiping with any data queued up for muxing in byte[] subPidPacketBuffer = new byte[TsPacketSize]; int subPidDataSize = 0; ulong subPidTimeStamp = 0; //see if there is any data waiting to get switched into the mux... lock (_subPidBuffer) { if (_subPidBuffer.BufferFullness < 1) { break; //double check here because prior check was not thread safe } var subPidPacketDataReturned = _subPidBuffer.Remove(ref subPidPacketBuffer, out subPidDataSize, out subPidTimeStamp); if (subPidPacketDataReturned != 0 && subPidPacketDataReturned != TsPacketSize) { PrintToConsole("Sub PID data seems to not be size of TS packet!"); return; } } if (packet.SourceBufferIndex % 188 != 0) { PrintToConsole("Misaligned packet"); return; } Buffer.BlockCopy(subPidPacketBuffer, 0, dataBuffer, packet.SourceBufferIndex, TsPacketSize); } } } var packetReadyEventArgs = new PacketReadyEventArgs(); packetReadyEventArgs.UdpPacketData = new byte[dataSize]; Buffer.BlockCopy(dataBuffer, 0, packetReadyEventArgs.UdpPacketData, 0, dataSize); OnPacketReady(packetReadyEventArgs); } } catch (Exception ex) { PrintToConsole($@"Unhandled exception within network receiver: {ex.Message}"); } } //Logger.Log(new TelemetryLogEventInfo { Level = LogLevel.Info, Message = "Stopping analysis thread due to exit request." }); }
private void btnScan_Click(object sender, EventArgs e) { if (lvResult.Items.Count > 0) { lvResult.Items.Clear(); } //StartScanThread(); _decoder.TableChangeDetected += _decoder_TableChangeDetected; var programMapTables = new List <ProgramMapTable>(); _isScanning = true; _stopScanning = false; SetControlPropertyThreadSafe(btnScan, "Text", "Stop Search"); programMapTables.Clear(); patfound = false; pmtsfound = false; nitfound = false; sdtfound = false; SetControlPropertyThreadSafe(lblPat, "BackColor", Color.LightGreen); SetControlPropertyThreadSafe(lblPmt, "BackColor", Color.LightGreen); SetControlPropertyThreadSafe(lblSdt, "BackColor", Color.LightGreen); SetControlPropertyThreadSafe(lblNit, "BackColor", Color.LightGreen); if (_stopScanning) { return; } RtspStatusCode statuscode; if (string.IsNullOrEmpty(_device.RtspSession.SessionID)) { _device.RtspSession.Options(); _device.RtspSession.Setup(_currenttunestring, TransmissionMode.Unicast); _device.RtspSession.Play(_currenttunestring); _udpclient = new UdpClient(_device.RtspSession.RtpPort); _remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); _device.RtspSession.RecieptionInfoChanged += RtspSession_RecieptionInfoChanged; } else { _device.RtspSession.Play(_currenttunestring); } /* Say the Sat>IP server we want Receives the Recieption Details SDP */ statuscode = _device.RtspSession.Describe(); if (_locked) { while (!patfound || !pmtsfound || !sdtfound || !nitfound) { var receivedbytes = _udpclient.Receive(ref _remoteEndPoint); var rtp = RtpPacket.Decode(receivedbytes); if (rtp.HasPayload) { var packets = packetFactory.GetTsPacketsFromData(rtp.Payload); Logger.Write(rtp.Payload.ToHexString()); _decoder.AddData(receivedbytes); } //} lock (_decoder) { programMapTables = _decoder?.ProgramMapTables.OrderBy(p => p.ProgramNumber).ToList(); foreach (var programMapTable in programMapTables) { short videoPid = -1; short audioPid = -1; short ac3pid = -1; short ttxpid = -1; short subpid = -1; var desc = _decoder.GetServiceDescriptorForProgramNumber(programMapTable?.ProgramNumber); if (desc != null) { if (programMapTable?.EsStreams != null) { foreach (var stream in programMapTable.EsStreams) { if (stream != null) { if (stream.Descriptors.OfType <Ac3Descriptor>().Any()) { ac3pid = stream.ElementaryPid; } if (stream.Descriptors.OfType <Eac3Descriptor>().Any()) { ac3pid = stream.ElementaryPid; } if (stream.Descriptors.OfType <SubtitlingDescriptor>().Any()) { subpid = stream.ElementaryPid; } if (stream.Descriptors.OfType <TeletextDescriptor>().Any()) { ttxpid = stream.ElementaryPid; } switch (stream.StreamType) { case 0x01: // ISO/IEC 11172-2 (MPEG-1 video) in a packetized stream case 0x02 : // ITU-T Rec. H.262 and ISO/IEC 13818-2 (MPEG-2 higher rate interlaced video) in a packetized stream case 0x1B : // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video) in a packetized stream case 0x24 : // ITU - T Rec.H.265 and ISO/ IEC 23008 - 2(Ultra HD video) in a packetized stream { videoPid = stream.ElementaryPid; break; } case 0x03: // ISO/IEC 11172-3 (MPEG-1 audio) in a packetized stream case 0x04 : // ISO/IEC 13818-3 (MPEG-2 halved sample rate audio) in a packetized stream { audioPid = stream.ElementaryPid; break; } default: { Console.Write(stream.StreamType.ToString()); break; } } } } } var chan = new Channel { ServiceType = desc.ServiceType, ServiceName = desc.ServiceName.Value, ServiceProvider = desc.ServiceProviderName.Value, ServiceId = programMapTable.ProgramNumber, ProgramClockReferenceId = programMapTable.PcrPid, AudioPid = audioPid, VideoPid = videoPid, AC3Pid = ac3pid, TTXPid = ttxpid, SubTitlePid = subpid }; AddResults(chan); } } } } //Thread.Sleep(55000); _device.RtspSession.TearDown(); SetControlPropertyThreadSafe(pgbSearchResult, "Value", 100); _isScanning = false; SetControlPropertyThreadSafe(btnScan, "Text", "Start Search"); } }