skyscraper8/skyscraper8/Mpeg2/TsAdaptionField.cs
feyris-tan ef86554f9a Import
2025-05-12 22:09:16 +02:00

183 lines
6.5 KiB
C#

using System.IO;
using skyscraper5.Dvb;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.IO;
namespace skyscraper5.Mpeg2
{
public class DvbAdaptionField : Validatable
{
public DvbAdaptionField(Stream binaryReader, bool TEI)
{
byte adaptionFieldLength = binaryReader.ReadUInt8();
if (adaptionFieldLength > 183)
{
Valid = false;
return;
}
byte[] adaptionField = binaryReader.ReadBytes(adaptionFieldLength);
binaryReader = new MemoryStream(adaptionField);
this.Length = adaptionFieldLength;
if (adaptionFieldLength == 0)
{
Valid = true;
return; //Seems valid according to ISO 13818-1
}
byte bitmask = binaryReader.ReadUInt8();
Discontinuity = ((bitmask & 0x80) >> 7) != 0;
RandomAccess = ((bitmask & 0x40) >> 6) != 0;
PriorityIndicator = ((bitmask & 0x20) >> 5) != 0;
PcrPresent = ((bitmask & 0x10) >> 4) != 0;
OpcrPresent = ((bitmask & 0x08) >> 3) != 0;
SplicingPointPresent = ((bitmask & 0x04) >> 2) != 0;
TransportPrivateDataPresent = ((bitmask & 0x02) >> 1) != 0;
AdaptionFieldExtensionPresent = ((bitmask & 0x01)) != 0;
if (PcrPresent)
{
if (binaryReader.GetAvailableBytes() < 6)
{
Valid = false;
return;
}
uint pcrA = binaryReader.ReadUInt32BE();
ushort pcrB = binaryReader.ReadUInt16BE();
ulong pcr_base = ((ulong)pcrA << 1) | ((ulong)pcrB >> 15);
ulong pcr_ext = (ulong)pcrB & 0x01ff;
PCR = pcr_base * 300 + pcr_ext;
}
if (OpcrPresent)
{
if (binaryReader.GetAvailableBytes() < 6)
{
Valid = false;
return;
}
uint opcrA = binaryReader.ReadUInt32BE();
ushort opcrB = binaryReader.ReadUInt16BE();
ulong pcr_base = ((ulong)opcrA << 1) | ((ulong)opcrB >> 15);
ulong pcr_ext = (ulong)opcrB & 0x01ff;
OPCR = pcr_base * 300 + pcr_ext;
}
if (SplicingPointPresent)
{
if (binaryReader.GetAvailableBytes() == 0)
{
Valid = false;
return;
}
SplicingPoint = binaryReader.ReadUInt8();
}
if (TransportPrivateDataPresent)
{
if (binaryReader.GetAvailableBytes() == 0)
{
Valid = false;
return;
}
byte TransportPrivateDataLength = binaryReader.ReadUInt8();
long maxLen = binaryReader.Length - binaryReader.Position;
if (TransportPrivateDataLength <= maxLen)
{
TransportPrivateData = binaryReader.ReadBytes(TransportPrivateDataLength);
}
else
{
Valid = false;
return;
}
}
if (AdaptionFieldExtensionPresent)
{
AdaptionFieldExtension = new TsAdaptionFieldExtension();
if (binaryReader.GetAvailableBytes() == 0)
{
Valid = false;
return;
}
byte extensionFlags1 = binaryReader.ReadUInt8();
AdaptionFieldExtension.LtwFlag = (extensionFlags1 & 0x80) != 0;
AdaptionFieldExtension.PiecewiseRateFlag = (extensionFlags1 & 0x40) != 0;
AdaptionFieldExtension.SeamlessSpliceFlag = (extensionFlags1 & 0x20) != 0;
if (AdaptionFieldExtension.LtwFlag)
{
if (binaryReader.GetAvailableBytes() < 2)
{
Valid = false;
return;
}
ushort ltwRaw = binaryReader.ReadUInt16BE();
AdaptionFieldExtension.LtwValidFlag = (ltwRaw & 0x8000) != 0;
AdaptionFieldExtension.LtwOffset = (ltwRaw & 0x7fff);
}
if (AdaptionFieldExtension.PiecewiseRateFlag)
{
if (binaryReader.GetAvailableBytes() < 3)
{
Valid = false;
return;
}
int piecewiseRaw = binaryReader.ReadByte() & 0xff;
piecewiseRaw += (binaryReader.ReadUInt16BE() & 0xffff) >> 8;
piecewiseRaw = piecewiseRaw & 0x3fffff;
AdaptionFieldExtension.PiecewiseRate = piecewiseRaw;
}
if (AdaptionFieldExtension.SeamlessSpliceFlag)
{
if (binaryReader.Length - binaryReader.Position < 5)
{
Valid = false;
return;
}
byte spliceRawA = binaryReader.ReadUInt8();
AdaptionFieldExtension.SpliceType = spliceRawA & 0xf0;
AdaptionFieldExtension.DtsNextAccessUnit = (long)(spliceRawA & 0x0f);
AdaptionFieldExtension.DtsNextAccessUnit += (((long)binaryReader.ReadUInt32BE() & 0xfffefffeL) >> 4);
}
}
Valid = true;
}
public bool PriorityIndicator { get; private set; }
public bool RandomAccess { get; private set; }
public bool Discontinuity { get; private set; }
public TsAdaptionFieldExtension AdaptionFieldExtension { get; private set; }
public bool AdaptionFieldExtensionPresent { get; private set; }
public byte[] TransportPrivateData { get; private set; }
public bool TransportPrivateDataPresent { get; private set; }
public byte SplicingPoint { get; private set; }
public bool SplicingPointPresent { get; private set; }
public ulong OPCR { get; set; }
public bool OpcrPresent { get; private set; }
public ulong PCR { get; private set; }
public bool PcrPresent { get; private set; }
public byte Length { get; private set; }
}
}