110 lines
3.1 KiB
C#
110 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using skyscraper5.Dvb.Psi.Model;
|
|
using skyscraper5.Mpeg2;
|
|
using skyscraper5.Skyscraper.IO;
|
|
|
|
namespace skyscraper5.Scorcher
|
|
{
|
|
internal class SdtGenerator : PsiGenerator
|
|
{
|
|
public ushort TransportStreamId { get; }
|
|
public ushort OriginalNetworkId { get; }
|
|
|
|
public SdtGenerator(ushort transportStreamId, ushort originalNetworkId) : base(new TimeSpan(0, 0, 4), 0x0011)
|
|
{
|
|
TransportStreamId = transportStreamId;
|
|
OriginalNetworkId = originalNetworkId;
|
|
services = new List<SdtGeneratorService>();
|
|
}
|
|
|
|
public SdtGeneratorService CreateService(ushort serviceId, bool eitScheduleFlag = false,
|
|
bool eitPresentFollowingFlag = false, RunningStatus runningStatus = RunningStatus.Running,
|
|
bool freeCaMode = false)
|
|
{
|
|
SdtGeneratorService result = new SdtGeneratorService(serviceId, eitScheduleFlag, eitPresentFollowingFlag, runningStatus, freeCaMode);
|
|
services.Add(result);
|
|
return result;
|
|
}
|
|
|
|
private List<SdtGeneratorService> services;
|
|
|
|
private byte[] SerializeServices()
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
foreach (SdtGeneratorService service in services)
|
|
{
|
|
byte[] descriptorBuffer = service.SerializeDescriptors();
|
|
ushort descriptorLength = (ushort)descriptorBuffer.Length;
|
|
|
|
ms.WriteUInt16BE(service.ServiceId);
|
|
|
|
byte byteA = 0;
|
|
byteA |= 0xfc; //reserved
|
|
if (service.EitScheduleFlag)
|
|
byteA |= 0x02;
|
|
if (service.EitPresentFollowingFlag)
|
|
byteA |= 0x01;
|
|
ms.WriteUInt8(byteA);
|
|
|
|
byte byteB = 0;
|
|
byteB |= (byte)((int)service.RunningStatus << 5);
|
|
if (service.FreeCaMode)
|
|
byteB |= 0x10;
|
|
byteB |= (byte)((descriptorLength & 0x0f00) >> 8);
|
|
ms.WriteUInt8(byteB);
|
|
|
|
ms.WriteUInt8((byte)(descriptorLength & 0x00ff));
|
|
ms.Write(descriptorBuffer, 0, descriptorBuffer.Length);
|
|
}
|
|
|
|
return ms.ToArray();
|
|
}
|
|
|
|
public override byte[] BuildPsi()
|
|
{
|
|
byte[] serializedServices = SerializeServices();
|
|
|
|
ushort sectionLength = (ushort)(2 + 3 + 2 + 1 + serializedServices.Length + 4); //TODO: calculate section length
|
|
if (sectionLength > 1021)
|
|
throw new Exception("section too long");
|
|
sectionLength &= 0x3fff;
|
|
|
|
MemoryStream ms = new MemoryStream();
|
|
ms.WriteUInt8(0x42);
|
|
|
|
byte byteA = 0;
|
|
byteA |= 0x80; //section_syntax_indicator
|
|
byteA |= 0x40; //reserved_future_use
|
|
byteA |= 0x30; //reserved
|
|
byteA |= (byte)(sectionLength >> 8);
|
|
ms.WriteUInt8(byteA);
|
|
|
|
byte byteB = (byte)(sectionLength & 0x00ff);
|
|
ms.WriteUInt8(byteB);
|
|
|
|
ms.WriteUInt16BE(TransportStreamId);
|
|
|
|
byte byteC = 0;
|
|
byteC |= 0xc0; //reserved
|
|
byteC |= (byte)(versionNumber << 1); //version_number
|
|
byteC |= 0x01; //current_next_indicator
|
|
ms.WriteUInt8(byteC);
|
|
|
|
ms.WriteUInt8(0x00); //section number
|
|
ms.WriteUInt8(0x00); //last section number
|
|
|
|
ms.WriteUInt16BE(OriginalNetworkId); //original network id
|
|
ms.WriteUInt8(0xff); //reserved future use
|
|
|
|
ms.Write(serializedServices, 0, serializedServices.Length);
|
|
|
|
uint crc = DvbCrc32.CreateCrc(ms, 0, (int)ms.Position);
|
|
ms.WriteUInt32BE(crc);
|
|
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
}
|