From a940ef3a458a195adf86e64e4e695fb15e25cdac Mon Sep 17 00:00:00 2001 From: feyris-tan <4116042+feyris-tan@users.noreply.github.com> Date: Sun, 17 May 2026 12:18:39 +0200 Subject: [PATCH] Implemented Salvaging strategies 1 & 2. --- skyscraper8/Program.cs | 6 +- skyscraper8/Properties/launchSettings.json | 2 +- skyscraper8/Skyscraper/Salvager.cs | 90 +++++++++++++++++++++- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/skyscraper8/Program.cs b/skyscraper8/Program.cs index 587accc..ef97b7c 100644 --- a/skyscraper8/Program.cs +++ b/skyscraper8/Program.cs @@ -445,9 +445,9 @@ namespace skyscraper5 Console.WriteLine(".\\skyscraper8.exe salvage strategyName \"C:\\path\\to\\file.ts\\\" - attempts to salvage a corrupted TS.)"); Console.WriteLine(); Console.WriteLine("Salvaging strategy names:"); - Console.WriteLine(" s1 - Stay aligned with 188-bytes, but skip blocks which do not feature the 0x49 sync byte."); - Console.WriteLine(" s2 - Stay aligned with 188-bytes, but pretends the sync byte is valid even if it isn't."); - Console.WriteLine(" s3 - Ignore 188-byte alignment. When the sync-byte is not found after a packet, seek the stream forward until something is found that *might* sync."); + Console.WriteLine(" strat1 - Stay aligned with 188-bytes, but skip blocks which do not feature the 0x49 sync byte."); + Console.WriteLine(" strat2 - Stay aligned with 188-bytes, but pretends the sync byte is valid even if it isn't."); + Console.WriteLine(" strat3 - Ignore 188-byte alignment. When the sync-byte is not found after a packet, seek the stream forward until something is found that *might* sync."); Console.WriteLine(" Note that the salvaging feature needs the first packet to be valid."); } diff --git a/skyscraper8/Properties/launchSettings.json b/skyscraper8/Properties/launchSettings.json index 29e21ca..b2d6d50 100644 --- a/skyscraper8/Properties/launchSettings.json +++ b/skyscraper8/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "skyscraper8": { "commandName": "Project", - "commandLineArgs": "salvage s1 \"C:\\devel\\skyscraper8-testsuite\\105.5E_4169.263_H_5237_(2026-04-24 12.36.13)_dump.ts\"", + "commandLineArgs": "salvage strat3 \"C:\\devel\\skyscraper8-testsuite\\105.5E_4169.263_H_5237_(2026-04-24 12.36.13)_dump.ts\"", "remoteDebugEnabled": false }, "Container (Dockerfile)": { diff --git a/skyscraper8/Skyscraper/Salvager.cs b/skyscraper8/Skyscraper/Salvager.cs index f95bcc8..6862ed2 100644 --- a/skyscraper8/Skyscraper/Salvager.cs +++ b/skyscraper8/Skyscraper/Salvager.cs @@ -9,6 +9,7 @@ using skyscraper5.Mpeg2; using skyscraper5.Skyscraper.Scraper; using skyscraper5.Skyscraper.Scraper.Storage.Filesystem; using skyscraper5.Skyscraper.Scraper.Storage.InMemory; +using skyscraper8.Skyscraper.IO; using skyscraper8.Skyscraper.Scraper.Storage; namespace skyscraper8.Skyscraper @@ -27,9 +28,9 @@ namespace skyscraper8.Skyscraper switch (args[1]) { - case "s1": Strategy = SalvagingStrategy.IgnorePacketsWithWrongSyncByte; break; - case "s2": Strategy = SalvagingStrategy.PatchSyncByte; break; - case "s3": Strategy = SalvagingStrategy.SeekForSyncByte; break; + case "strat1": Strategy = SalvagingStrategy.IgnorePacketsWithWrongSyncByte; break; + case "strat2": Strategy = SalvagingStrategy.PatchSyncByte; break; + case "strat3": Strategy = SalvagingStrategy.SeekForSyncByte; break; default: { logger.Fatal("\"{0}\" is not a known salvaging strategy."); @@ -53,6 +54,7 @@ namespace skyscraper8.Skyscraper TcpClient tcpClient = new TcpClient(host, port); InputStream = tcpClient.GetStream(); + InputStream = new BufferedStream(InputStream, 96256 * 2); } else { @@ -69,6 +71,8 @@ namespace skyscraper8.Skyscraper return; } + InputStream = new UnseekableInputStream(InputStream); + Run(); } @@ -78,17 +82,97 @@ namespace skyscraper8.Skyscraper InMemoryScraperStorage dataStorage = new InMemoryScraperStorage(); FilesystemStorage objectStorage = new FilesystemStorage(new DirectoryInfo(".")); Context = new SkyscraperContext(mpeg2, dataStorage, objectStorage); + Context.InitalizeFilterChain(); + + logger.InfoFormat("Trying to read the initial packet..."); + readBuffer = new byte[188]; + readLength = InputStream.Read(readBuffer, 0, 188); + if (readLength != 188) + { + logger.FatalFormat("Could not read the initial packet. The read was cut too short to include a full TS packet."); + return; + } + + if (readBuffer[0] != 'G') + { + logger.FatalFormat("I'm sorry, but I can't salvage this stream. The initial packet is broken already."); + return; + } + + + Context.IngestSinglePacket(readBuffer); + switch (Strategy) { + case SalvagingStrategy.IgnorePacketsWithWrongSyncByte: + RunWithIgnoringPacketsWithWrongSyncByte(); + break; + case SalvagingStrategy.PatchSyncByte: + RunWithPatchingSyncByte(); + break; default: logger.ErrorFormat("I'm sorry, but the strategy \"{0}\" is not yet fully implemented.",Strategy); return; } } + private void RunWithPatchingSyncByte() + { + while (readLength == 188) + { + long currentOffset = InputStream.Position; + Array.Clear(readBuffer); + readLength = InputStream.Read(readBuffer, 0, 188); + if (readBuffer[0] != 'G') + { + logger.WarnFormat("Patching sync byte and setting TEI flag for packet #{0}", currentOffset / 188); + readBuffer[0] = (byte)'G'; + readBuffer[1] |= 0x80; + } + + SalvagedOutput?.Write(readBuffer, 0, 188); + Context.IngestSinglePacket(readBuffer); + } + } + + private void RunWithIgnoringPacketsWithWrongSyncByte() + { + bool justBroken = false; + + while (readLength == 188) + { + long currentOffset = InputStream.Position; + Array.Clear(readBuffer); + readLength = InputStream.Read(readBuffer, 0, 188); + if (readBuffer[0] == 'G') + { + if (justBroken) + { + logger.InfoFormat("Resynced at packet #{0}", currentOffset / 188); + } + Context.IngestSinglePacket(readBuffer); + justBroken = false; + SalvagedOutput?.Write(readBuffer, 0, 188); + } + else + { + if (!justBroken) + { + logger.WarnFormat("Lost TS sync at packet #{0}", currentOffset / 188); + justBroken = true; + } + } + } + } + + private byte[] readBuffer; + private int readLength; + public SalvagingStrategy Strategy { get; set; } public Stream InputStream { get; set; } public SkyscraperContext Context { get; set; } + + public Stream SalvagedOutput { get; set; } } public enum SalvagingStrategy