185 lines
4.6 KiB
C#
185 lines
4.6 KiB
C#
using log4net;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
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
|
|
{
|
|
internal class Salvager
|
|
{
|
|
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
|
|
|
public void Run(string[] args)
|
|
{
|
|
if (args.Length != 3)
|
|
{
|
|
Console.WriteLine("specify the salvaging strategy and the source.");
|
|
return;
|
|
}
|
|
|
|
switch (args[1])
|
|
{
|
|
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.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
FileInfo fi = new FileInfo(args[2]);
|
|
if (fi.Exists)
|
|
{
|
|
InputStream = fi.OpenRead();
|
|
}
|
|
else
|
|
{
|
|
var uri = new Uri("tcp://177.20.20.69:6969", UriKind.Absolute);
|
|
|
|
if (uri.Scheme.Equals("tcp"))
|
|
{
|
|
string host = uri.Host; // "177.20.20.69"
|
|
int port = uri.Port; // 6969
|
|
|
|
TcpClient tcpClient = new TcpClient(host, port);
|
|
InputStream = tcpClient.GetStream();
|
|
InputStream = new BufferedStream(InputStream, 96256 * 2);
|
|
}
|
|
else
|
|
{
|
|
logger.FatalFormat("URI Scheme \"{0}\" is not supported for salvaging.", uri.Scheme);
|
|
return;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (InputStream == null)
|
|
{
|
|
logger.FatalFormat("{0} is not a file that exist, and doesn't fit to any known URL scheme.");
|
|
return;
|
|
}
|
|
|
|
InputStream = new UnseekableInputStream(InputStream);
|
|
|
|
Run();
|
|
}
|
|
|
|
private void Run()
|
|
{
|
|
TsContext mpeg2 = new TsContext();
|
|
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
|
|
{
|
|
IgnorePacketsWithWrongSyncByte,
|
|
PatchSyncByte,
|
|
SeekForSyncByte
|
|
}
|
|
}
|