118 lines
3.3 KiB
C#
118 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using skyscraper5.Dvb.Descriptors;
|
|
using skyscraper5.Mpeg2;
|
|
using skyscraper5.Skyscraper.IO;
|
|
|
|
namespace skyscraper5.Scorcher
|
|
{
|
|
public class PmtGenerator : PsiGenerator
|
|
{
|
|
public ushort ProgramNumber { get; }
|
|
public ushort PcrPid { get; }
|
|
|
|
public PmtGenerator(uint pid, ushort programNumber, ushort PcrPid) : base(new TimeSpan(0,0,3), pid)
|
|
{
|
|
ProgramNumber = programNumber;
|
|
this.PcrPid = PcrPid;
|
|
descriptors = new List<TsDescriptor>();
|
|
streams = new List<PmtGeneratorStream>();
|
|
}
|
|
|
|
private List<TsDescriptor> descriptors;
|
|
private List<PmtGeneratorStream> streams;
|
|
|
|
private byte[] SerializeDescriptors()
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
foreach (TsDescriptor descriptor in descriptors)
|
|
{
|
|
ms.WriteUInt8(descriptor.GetDescriptorId()); //descriptor_tag
|
|
|
|
byte[] descriptorBytes = descriptor.Serialize();
|
|
ms.WriteUInt8((byte)descriptorBytes.Length); //descriptor_length
|
|
ms.Write(descriptorBytes, 0, descriptorBytes.Length);
|
|
}
|
|
return ms.ToArray();
|
|
}
|
|
|
|
private byte[] SerializeStreams()
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
foreach (PmtGeneratorStream stream in streams)
|
|
{
|
|
ms.WriteUInt8(stream.StreamType);
|
|
ms.WriteUInt16BE((ushort)(stream.ElementaryPid | 0xe000));
|
|
|
|
byte[] descriptorLoop = stream.SerializeDescriptors();
|
|
ms.WriteUInt16BE((ushort)(descriptorLoop.Length | 0xf000)); //ES_Info_length
|
|
ms.Write(descriptorLoop, 0, descriptorLoop.Length);
|
|
}
|
|
|
|
return ms.ToArray();
|
|
}
|
|
|
|
public override byte[] BuildPsi()
|
|
{
|
|
byte[] descriptorBuffer = SerializeDescriptors();
|
|
int programInfoLength = descriptorBuffer.Length;
|
|
byte[] streamBuffer = SerializeStreams();
|
|
int sectionLength = 9 + descriptorBuffer.Length + streamBuffer.Length + 4;
|
|
|
|
//TODO: calculate section length here
|
|
|
|
MemoryStream ms = new MemoryStream();
|
|
ms.WriteUInt8(0x02); //table_id
|
|
|
|
byte byte2 = 0;
|
|
byte2 |= 0x80; //section_syntax_indicator
|
|
//'0'
|
|
byte2 |= 0x30; //reserved
|
|
byte2 += (byte)((sectionLength & 0x0300) >> 8);
|
|
ms.WriteUInt8(byte2); //section length, part 1
|
|
|
|
byte byte3 = (byte)(sectionLength & 0x00ff);
|
|
ms.WriteUInt8(byte3); //section length, part 2
|
|
|
|
ms.WriteUInt16BE(ProgramNumber);
|
|
|
|
byte byte4 = 0;
|
|
byte4 |= 0xc0; //reserved
|
|
byte4 |= (byte)((versionNumber & 0x1f) << 1); //version number
|
|
byte4 |= 0x01; //current next indicator
|
|
ms.WriteUInt8(byte4);
|
|
|
|
ms.WriteUInt8(0); //section number
|
|
ms.WriteUInt8(0); //last section number
|
|
|
|
ms.WriteUInt16BE((ushort)(PcrPid | 0xe000)); //reserved & PCR_PID
|
|
|
|
ms.WriteUInt16BE((ushort)(programInfoLength | 0xf000)); //reserved & program info length
|
|
|
|
ms.Write(descriptorBuffer, 0, descriptorBuffer.Length); //descriptors()
|
|
|
|
ms.Write(streamBuffer, 0, streamBuffer.Length);
|
|
|
|
uint crc = DvbCrc32.CreateCrc(ms, 0, (int)ms.Position);
|
|
ms.WriteUInt32BE(crc);
|
|
|
|
return ms.ToArray();
|
|
}
|
|
|
|
public void AddDescriptor(PrivateDataSpecifierDescriptor privateDataSpecifierDescriptor)
|
|
{
|
|
descriptors.Add(privateDataSpecifierDescriptor);
|
|
versionNumber++;
|
|
}
|
|
|
|
public PmtGeneratorStream AddStream(byte streamType, ushort pid)
|
|
{
|
|
PmtGeneratorStream stream = new PmtGeneratorStream(streamType, pid);
|
|
streams.Add(stream);
|
|
versionNumber++;
|
|
return stream;
|
|
}
|
|
}
|
|
}
|