Merge pull request #7 from Shadowghost/upstream-merge

Merge upstream changes
This commit is contained in:
Tim Eisele 2024-03-13 11:55:12 +01:00 committed by GitHub
commit 40d2c5be76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 1874 additions and 930 deletions

View File

@ -2,11 +2,11 @@
<PropertyGroup>
<TargetFrameworks>netstandard2.1;net6.0</TargetFrameworks>
<Version>0.7.6.2</Version>
<Version>0.8.0.0</Version>
<Authors>UniqProject, cinemasquid, stanionascu, jellyfin</Authors>
<Description>Library for analysis of the Bluray disc and folder stuctures.</Description>
<AssemblyVersion>0.7.6.2</AssemblyVersion>
<FileVersion>0.7.6.2</FileVersion>
<AssemblyVersion>0.8.0.0</AssemblyVersion>
<FileVersion>0.8.0.0</FileVersion>
<PackageLicenseExpression>LGPL-2.1-only</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/jellyfin/BDInfo</PackageProjectUrl>
<RepositoryUrl>https://github.com/jellyfin/BDInfo</RepositoryUrl>

View File

@ -234,17 +234,26 @@ namespace BDInfo
private void ReadDiscTitle(StreamReader fileStream)
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load(fileStream);
var xNsMgr = new XmlNamespaceManager(xDoc.NameTable);
xNsMgr.AddNamespace("di", "urn:BDA:bdmv;discinfo");
var xNode = xDoc.DocumentElement?.SelectSingleNode("di:discinfo/di:title/di:name", xNsMgr);
DiscTitle = xNode?.InnerText;
try
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load(fileStream);
var xNsMgr = new XmlNamespaceManager(xDoc.NameTable);
xNsMgr.AddNamespace("di", "urn:BDA:bdmv;discinfo");
var xNode = xDoc.DocumentElement?.SelectSingleNode("di:discinfo/di:title/di:name", xNsMgr);
DiscTitle = xNode?.InnerText;
if (!string.IsNullOrEmpty(DiscTitle) && DiscTitle.ToLowerInvariant() == "blu-ray")
if (!string.IsNullOrEmpty(DiscTitle) && DiscTitle.ToLowerInvariant() == "blu-ray")
DiscTitle = null;
}
catch (Exception)
{
DiscTitle = null;
fileStream.Close();
}
finally
{
fileStream.Close();
}
}
public void Scan()
@ -456,7 +465,7 @@ namespace BDInfo
try
{
long result = GetVolumeInformation(
dir.Name,
dir.FullName,
volumeLabel,
(uint)volumeLabel.Capacity,
ref serialNumber,
@ -487,7 +496,7 @@ namespace BDInfo
{
return 0;
}
else if ((x == null || x.FileInfo == null) && (y != null && y.FileInfo != null))
else if ((x == null || x.FileInfo == null) && y != null && y.FileInfo != null)
{
return 1;
}
@ -524,7 +533,7 @@ namespace BDInfo
}
}
[DllImport("kernel32.dll")]
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern long GetVolumeInformation(
string PathName,
StringBuilder VolumeNameBuffer,

121
src/BDInfo/TSCodecAAC.cs Normal file
View File

@ -0,0 +1,121 @@
//============================================================================
// BDInfo - Blu-ray Video and Audio Analysis Tool
// Copyright © 2010 Cinema Squid
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================
#undef DEBUG
namespace BDInfo
{
public abstract class TSCodecAAC
{
private static readonly string[] AACID =
{
"MPEG-4",
"MPEG-2",
};
private static string GetAACProfile(int profileType)
{
switch (profileType)
{
case 0: return "AAC Main";
case 1: return "AAC LC";
case 2: return "AAC SSR";
case 3: return "AAC LTP";
case 16: return "ER AAC LC";
case 18: return "ER AAC LTP";
case 36: return "SLS";
default: return "";
}
}
public static int[] AACSampleRates =
{
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000, 7350, 0, 0, 57600,
51200, 40000, 38400, 34150, 28800, 25600, 20000, 19200,
17075, 14400, 12800, 9600, 0, 0, 0
};
private const int AACChannelsSize = 8;
public static int[] AACChannels = { 0, 1, 2, 3, 4, 5, 6, 8 };
private static readonly byte[] AACChannelModes =
{
(byte)TSAudioMode.Unknown,
(byte)TSAudioMode.Mono,
(byte)TSAudioMode.Stereo,
(byte)TSAudioMode.Extended,
(byte)TSAudioMode.Surround,
(byte)TSAudioMode.Surround,
(byte)TSAudioMode.Surround,
(byte)TSAudioMode.Surround,
};
public static void Scan(TSAudioStream stream, TSStreamBuffer buffer, ref string tag)
{
if (stream.IsInitialized) return;
int syncWord = buffer.ReadBits2(12);
if (syncWord != 0b1111_1111_1111) return;
// fixed header
int audioVersionID = buffer.ReadBits2(1);
_ = buffer.ReadBits2(2); // Layer Index
_ = buffer.ReadBool(); // Protection Absent
int profileObjectType = buffer.ReadBits2(2);
int samplingRateIndex = buffer.ReadBits2(4);
_ = buffer.ReadBool(); // Private Bit
int channelMode = buffer.ReadBits2(3);
_ = buffer.ReadBool(); // Original Bit
_ = buffer.ReadBool(); // Home
if (samplingRateIndex <= 13)
stream.SampleRate = AACSampleRates[samplingRateIndex];
else
stream.SampleRate = 0;
if (channelMode <= AACChannelsSize)
{
stream.AudioMode = (TSAudioMode)AACChannelModes[channelMode];
stream.ChannelCount = AACChannels[channelMode];
}
else
{
stream.ChannelCount = 0;
stream.AudioMode = TSAudioMode.Unknown;
}
if (channelMode >= 7 && channelMode <= 8)
{
stream.ChannelCount--;
stream.LFE = 1;
}
else
stream.LFE = 0;
stream.ExtendedData = $"{AACID[audioVersionID]} {GetAACProfile(profileObjectType)}";
stream.IsVBR = true;
stream.IsInitialized = true;
}
}
}

View File

@ -205,12 +205,12 @@ namespace BDInfo
buffer.BSSkipBits(8);
}
}
if (frameType == 1) //dependent stream
if (frameType == 1) // Dependent Stream
{
stream.CoreStream = (TSAudioStream)stream.Clone();
stream.CoreStream.StreamType = TSStreamType.AC3_AUDIO;
if (buffer.ReadBool()) //channel remapping
if (buffer.ReadBool()) // channel_remapping
{
uint chanmap = buffer.ReadBits4(16);
@ -224,52 +224,52 @@ namespace BDInfo
do
{
uint emdfSync = (buffer.ReadBits4(16));
if ((emdfSync) == 0x5838)
uint emdfSync = buffer.ReadBits4(16);
if (emdfSync == 0x5838)
{
emdfFound = true;
break;
}
buffer.Seek(-2, SeekOrigin.Current);
buffer.BSSkipBits(1); // skip 1 bit
buffer.BSSkipBits(1); // Skip 1 bit
} while (buffer.Position < buffer.Length);
if (emdfFound)
{
uint emdfContainerSize = buffer.ReadBits4(16);
var remainAfterEmdf = buffer.DataBitStreamRemain() - emdfContainerSize*8;
var remainAfterEmdf = buffer.DataBitStreamRemain() - emdfContainerSize * 8;
uint emdfVersion = buffer.ReadBits2(2); //emdf_version
uint emdfVersion = buffer.ReadBits2(2); // emdf_version
if (emdfVersion == 3)
emdfVersion += buffer.ReadBits2(2);
if (emdfVersion > 0)
{
buffer.BSSkipBits((int) (buffer.DataBitStreamRemain() - remainAfterEmdf));
buffer.BSSkipBits((int)(buffer.DataBitStreamRemain() - remainAfterEmdf));
}
else
{
var temp = buffer.ReadBits2(3);
if (temp == 0x7)
buffer.BSSkipBits(2); //skip 3 bits
buffer.BSSkipBits(2); // Skip 3 bits
var emdfPayloadID = buffer.ReadBits2(5);
if (emdfPayloadID > 0 && emdfPayloadID < 16)
{
if (emdfPayloadID == 0x1F)
buffer.BSSkipBits(5); //skip 5 bits
buffer.BSSkipBits(5); // Skip 5 bits
EmdfPayloadConfig(buffer);
int emdfPayloadSize = buffer.ReadBits2(8)*8;
int emdfPayloadSize = buffer.ReadBits2(8) * 8;
buffer.BSSkipBits(emdfPayloadSize + 1);
}
while ((emdfPayloadID = buffer.ReadBits2(5)) != 14 && buffer.Position < buffer.Length)
{
if (emdfPayloadID == 0x1F)
buffer.BSSkipBits(5); //skip 5 bits
buffer.BSSkipBits(5); // Skip 5 bits
EmdfPayloadConfig(buffer);
@ -366,22 +366,22 @@ namespace BDInfo
if (sampleOffsetE)
buffer.BSSkipBits(12);
if (buffer.ReadBool()) //duratione
buffer.BSSkipBits(11); //duration
if (buffer.ReadBool()) // duratione
buffer.BSSkipBits(11); // duration
if (buffer.ReadBool()) //groupide
buffer.BSSkipBits(2); //groupid
if (buffer.ReadBool()) // groupide
buffer.BSSkipBits(2); // groupid
if (buffer.ReadBool())
buffer.BSSkipBits(8); // reserved
buffer.BSSkipBits(8); // Reserved
if (!buffer.ReadBool()) //discard_unknown_payload
if (!buffer.ReadBool()) // discard_unknown_payload
{
buffer.BSSkipBits(1);
if (!sampleOffsetE)
{
if (buffer.ReadBool()) //payload_frame_aligned
if (buffer.ReadBool()) // payload_frame_aligned
buffer.BSSkipBits(9);
}
}

View File

@ -17,7 +17,6 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================
using System.Globalization;
namespace BDInfo
{
@ -32,10 +31,6 @@ namespace BDInfo
byte accessUnitDelimiterParse = 0;
byte sequenceParameterSetParse = 0;
string profile = null;
string level = null;
byte constraintSet0Flag = 0;
byte constraintSet1Flag = 0;
byte constraintSet2Flag = 0;
byte constraintSet3Flag = 0;
for (int i = 0; i < buffer.Length; i++)
@ -80,67 +75,69 @@ namespace BDInfo
else if (sequenceParameterSetParse > 0)
{
--sequenceParameterSetParse;
switch (sequenceParameterSetParse)
{
case 2:
switch (parse & 0xFF)
{
case 66:
profile = "Baseline Profile";
break;
case 77:
profile = "Main Profile";
break;
case 88:
profile = "Extended Profile";
break;
case 100:
profile = "High Profile";
break;
case 110:
profile = "High 10 Profile";
break;
case 122:
profile = "High 4:2:2 Profile";
break;
case 144:
profile = "High 4:4:4 Profile";
break;
default:
profile = "Unknown Profile";
break;
}
break;
if (!stream.IsInitialized)
switch (sequenceParameterSetParse)
{
case 2:
switch (parse & 0xFF)
{
case 66:
profile = "Baseline Profile";
break;
case 77:
profile = "Main Profile";
break;
case 88:
profile = "Extended Profile";
break;
case 100:
profile = "High Profile";
break;
case 110:
profile = "High 10 Profile";
break;
case 122:
profile = "High 4:2:2 Profile";
break;
case 144:
profile = "High 4:4:4 Profile";
break;
default:
profile = "Unknown Profile";
break;
}
break;
case 1:
constraintSet0Flag = (byte)
((parse & 0x80) >> 7);
constraintSet1Flag = (byte)
((parse & 0x40) >> 6);
constraintSet2Flag = (byte)
((parse & 0x20) >> 5);
constraintSet3Flag = (byte)
((parse & 0x10) >> 4);
break;
case 1:
_ = (byte) // Constraint Set 0 Flag
((parse & 0x80) >> 7);
_ = (byte) // Constraint Set 1 Flag
((parse & 0x40) >> 6);
_ = (byte) // Constraint Set 2 Flag
((parse & 0x20) >> 5);
constraintSet3Flag = (byte)
((parse & 0x10) >> 4);
break;
case 0:
byte b = (byte)(parse & 0xFF);
if (b == 11 && constraintSet3Flag == 1)
{
level = "1b";
}
else
{
level = string.Format(CultureInfo.InvariantCulture,
"{0:D}.{1:D}",
b / 10, (b - ((b / 10) * 10)));
}
stream.EncodingProfile = string.Format(
"{0} {1}", profile, level);
stream.IsVBR = true;
stream.IsInitialized = true;
break;
}
case 0:
byte b = (byte)(parse & 0xFF);
string level;
if (b == 11 && constraintSet3Flag == 1)
{
level = "1b";
}
else
{
level = string.Format(
"{0:D}.{1:D}",
b / 10, b - (b / 10 * 10));
}
stream.EncodingProfile = string.Format(
"{0} {1}", profile, level);
stream.IsVBR = true;
stream.IsInitialized = true;
break;
}
}
}
return;

View File

@ -103,10 +103,10 @@ namespace BDInfo
uint totalChannels = buffer.ReadBits4(3) + 1 + extCoding;
stream.SampleRate = DcaSampleRates[sampleRate];
stream.ChannelCount = (int) totalChannels;
stream.LFE = (lfe > 0 ? 1 : 0);
stream.ChannelCount = (int)totalChannels;
stream.LFE = lfe > 0 ? 1 : 0;
stream.BitDepth = DcaBitsPerSample[sourcePcmRes];
stream.DialNorm = (int) -dialogNorm;
stream.DialNorm = (int)-dialogNorm;
if ((sourcePcmRes & 0x1) == 0x1)
{
stream.AudioMode = TSAudioMode.Extended;

View File

@ -17,8 +17,6 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================
using System.IO;
namespace BDInfo
{
public abstract class TSCodecDTSHD
@ -47,10 +45,7 @@ namespace BDInfo
if (!syncFound)
{
tag = "CORE";
if (stream.CoreStream == null)
{
stream.CoreStream = new TSAudioStream {StreamType = TSStreamType.DTS_AUDIO};
}
stream.CoreStream ??= new TSAudioStream { StreamType = TSStreamType.DTS_AUDIO };
if (!stream.CoreStream.IsInitialized)
{
buffer.BeginRead();
@ -81,7 +76,7 @@ namespace BDInfo
var nuActiveExSsMask = new uint[nuNumAudioPresent];
for (var i = 0; i < nuNumAudioPresent; i++)
{
nuActiveExSsMask[i] = buffer.ReadBits4((int) (nuSubStreamIndex + 1)); //?
nuActiveExSsMask[i] = buffer.ReadBits4((int)(nuSubStreamIndex + 1)); // ?
}
for (var i = 0; i < nuNumAudioPresent; i++)
{
@ -200,7 +195,7 @@ namespace BDInfo
{
temp3 = (temp3 << 8) + buffer.ReadByte();
if (temp3 == 0x02000850) //DTS:X Pattern
if (temp3 == 0x02000850) // DTS:X Pattern
{
stream.HasExtensions = true;
break;
@ -215,7 +210,7 @@ namespace BDInfo
// TODO
if (stream.CoreStream != null)
{
var coreStream = (TSAudioStream)stream.CoreStream;
var coreStream = stream.CoreStream;
if (coreStream.AudioMode == TSAudioMode.Extended &&
stream.ChannelCount == 5)
{
@ -243,7 +238,7 @@ namespace BDInfo
stream.BitRate += stream.CoreStream.BitRate;
stream.IsInitialized = true;
}
stream.IsInitialized = (stream.BitRate > 0);
stream.IsInitialized = stream.BitRate > 0;
}
}
}

File diff suppressed because it is too large Load Diff

157
src/BDInfo/TSCodecMPA.cs Normal file
View File

@ -0,0 +1,157 @@
//============================================================================
// BDInfo - Blu-ray Video and Audio Analysis Tool
// Copyright © 2010 Cinema Squid
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================
#undef DEBUG
namespace BDInfo
{
public abstract class TSCodecMPA
{
private static readonly int[][][] MPABitrate =
{
/*
* Audio version ID (see table 3.2 also)
00 - MPEG Version 2.5 (unofficial extension of MPEG 2)
01 - reserved
10 - MPEG Version 2 (ISO/IEC 13818-3)
11 - MPEG Version 1 (ISO/IEC 11172-3)
-------------
Layer index
00 - reserved
01 - Layer III
10 - Layer II
11 - Layer I
-----
* // Bitrate Index MPEG 1 MPEG 2, 2.5 (LSF)
Layer I Layer II Layer III Layer I Layer II & III
0000 free
0001 32 32 32 32 8
0010 64 48 40 48 16
0011 96 56 48 56 24
0100 128 64 56 64 32
0101 160 80 64 80 40
0110 192 96 80 96 48
0111 224 112 96 112 56
1000 256 128 112 128 64
1001 288 160 128 144 80
1010 320 192 160 160 96
1011 352 224 192 176 112
1100 384 256 224 192 128
1101 416 320 256 224 144
1110 448 384 320 256 160
1111 reserved
*/
new [] // MPEG Version 2.5
{
new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // MPEG Version 2.5 Layer 0
new int[] {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, // MPEG Version 2.5 Layer III
new int[] {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, // MPEG Version 2.5 Layer II
new int[] {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}, // MPEG Version 2.5 Layer I
},
new [] // reserved
{
new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // reserved
new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // reserved
new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // reserved
new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // reserved
},
new [] // MPEG Version 2
{
new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // MPEG Version 2 Layer 0
new int[] {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, // MPEG Version 2 Layer III
new int[] {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, // MPEG Version 2 Layer II
new int[] {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}, // MPEG Version 2 Layer I
},
new [] // MPEG Version 1
{
new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // MPEG Version 1 Layer 0
new int[] {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, // MPEG Version 1 Layer III
new int[] {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, // MPEG Version 1 Layer II
new int[] {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}, // MPEG Version 1 Layer I
}
};
private static readonly int[][] MPASampleRate =
{
new int[] {11025, 12000, 8000, 0}, // MPEG Version 2.5
new int[] { 0, 0, 0, 0}, // reserved
new int[] {22050, 24000, 16000, 0}, // MPEG Version 2
new int[] {44100, 48000, 32000, 0} // MPEG Version 1
};
private static readonly byte[] MPAChannelModes =
{
(byte)TSAudioMode.Stereo,
(byte)TSAudioMode.JointStereo,
(byte)TSAudioMode.DualMono,
(byte)TSAudioMode.Mono
};
private static readonly string[] MPAVersion =
{
"MPEG 2.5",
"Unknown MPEG",
"MPEG 2",
"MPEG 1"
};
private static readonly string[] MPALayer =
{
"Unknown Layer",
"Layer III",
"Layer II",
"Layer I"
};
private static readonly byte[] MPAChannels = { 2, 2, 2, 1 };
public static void Scan(TSAudioStream stream, TSStreamBuffer buffer, ref string tag)
{
if (stream.IsInitialized) return;
int syncWord = buffer.ReadBits2(11) << 5;
if (syncWord != 0b1111_1111_1110_0000) return;
int audioVersionID = buffer.ReadBits2(2);
int layerIndex = buffer.ReadBits2(2);
_ = buffer.ReadBool(); // Protected Bit
int bitrateIndex = buffer.ReadBits2(4);
int samplingRateIndex = buffer.ReadBits2(2);
_ = buffer.ReadBool(); // Padding
_ = buffer.ReadBool(); // Private Bit
int channelMode = buffer.ReadBits2(2);
_ = buffer.ReadBits2(2); // Mode Extension
_ = buffer.ReadBool(); // Copyright Bit
_ = buffer.ReadBool(); // Original Bit
_ = buffer.ReadBits2(2); // EMphasis
stream.BitRate = MPABitrate[audioVersionID][layerIndex][bitrateIndex] * 1000;
stream.SampleRate = MPASampleRate[audioVersionID][samplingRateIndex];
stream.AudioMode = (TSAudioMode)MPAChannelModes[channelMode];
stream.ChannelCount = MPAChannels[channelMode];
stream.LFE = 0;
stream.ExtendedData = $"{MPAVersion[audioVersionID]} {MPALayer[layerIndex]}";
stream.IsVBR = false;
stream.IsInitialized = true;
}
}
}

123
src/BDInfo/TSCodecPGS.cs Normal file
View File

@ -0,0 +1,123 @@
//============================================================================
// BDInfo - Blu-ray Video and Audio Analysis Tool
// Copyright © 2010 Cinema Squid
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================
namespace BDInfo
{
public abstract class TSCodecPGS
{
public struct Frame
{
public bool Started;
public bool Forced;
public bool Finished;
}
public static void Scan(
TSGraphicsStream stream,
TSStreamBuffer buffer,
ref string tag)
{
byte SegmentType = buffer.ReadByte(false);
switch (SegmentType)
{
case 0x15: // ODS: Object Definition Segment
tag = ReadODS(stream, buffer);
break;
case 0x16: // PCS: Presentation Composition Segment
ReadPCS(stream, buffer);
break;
case 0x80:
if (!stream.LastFrame.Finished)
stream.LastFrame.Finished = true;
break;
default:
break;
}
stream.IsVBR = true;
}
private static string ReadODS(TSGraphicsStream stream, TSStreamBuffer buffer)
{
string tag = string.Empty;
_ = buffer.ReadBits2(16, false); // Segment Size
_ = buffer.ReadBits2(16, false); // Object ID
if (!stream.LastFrame.Finished)
{
if (stream.LastFrame.Forced)
{
stream.ForcedCaptions++;
tag = "F";
}
else
{
stream.Captions++;
tag = "N";
}
}
return tag;
}
private static void ReadPCS(TSGraphicsStream stream, TSStreamBuffer buffer)
{
_ = buffer.ReadBits2(16, false); // Segment Size
if (!stream.IsInitialized)
{
stream.Width = buffer.ReadBits2(16, false);
stream.Height = buffer.ReadBits2(16, false);
stream.IsInitialized = true;
}
else
{
_ = buffer.ReadBits2(16, false);
_ = buffer.ReadBits2(16, false);
}
_ = buffer.ReadByte();
int compositionNumber = buffer.ReadBits2(16, false);
_ = buffer.ReadByte(false); // Composition State
_ = buffer.ReadBits2(16, false);
int numCompositionObjects = buffer.ReadByte(false);
for (int i = 0; i < numCompositionObjects; i++)
{
_ = buffer.ReadBits2(16, false); // Object ID
_ = buffer.ReadByte(false); // Window ID
var forced = buffer.ReadByte(false); // Object Cropped Flag
_ = buffer.ReadBits2(16, false); // Object Horizontal Position
_ = buffer.ReadBits2(16, false); // Object Vertical Position
_ = buffer.ReadBits2(16, false); // Object Cropping Horizontal Position
_ = buffer.ReadBits2(16, false); // Object Cropping Vertical Position
_ = buffer.ReadBits2(16, false); // Object Cropping Width
_ = buffer.ReadBits2(16, false); // Object Cropping Height Position
stream.LastFrame = new Frame { Started = true, Forced = (forced & 0x40) == 0x40, Finished = false };
if (!stream.CaptionIDs.ContainsKey(compositionNumber))
{
stream.CaptionIDs[compositionNumber] = stream.LastFrame;
}
}
}
}
}

View File

@ -44,10 +44,7 @@ namespace BDInfo
if (!syncFound)
{
tag = "CORE";
if (stream.CoreStream == null)
{
stream.CoreStream = new TSAudioStream {StreamType = TSStreamType.AC3_AUDIO};
}
stream.CoreStream ??= new TSAudioStream { StreamType = TSStreamType.AC3_AUDIO };
if (!stream.CoreStream.IsInitialized)
{
buffer.BeginRead();
@ -61,7 +58,7 @@ namespace BDInfo
if (ratebits != 0xF)
{
stream.SampleRate =
(((ratebits & 8) > 0 ? 44100 : 48000) << (ratebits & 7));
((ratebits & 8) > 0 ? 44100 : 48000) << (ratebits & 7);
}
buffer.BSSkipBits(15);
@ -123,16 +120,16 @@ namespace BDInfo
buffer.BSSkipBits(49);
var peakBitrate = buffer.ReadBits4(15);
peakBitrate = (uint) ((peakBitrate * stream.SampleRate) >> 4);
peakBitrate = (uint)((peakBitrate * stream.SampleRate) >> 4);
var peakBitdepth = (double)peakBitrate / (stream.ChannelCount + stream.LFE) / stream.SampleRate;
var peakBitdepth = (double)peakBitrate / (stream.ChannelCount + stream.LFE) / stream.SampleRate;
stream.BitDepth = peakBitdepth > 14 ? 24 : 16;
buffer.BSSkipBits(79);
var hasExtensions = buffer.ReadBool();
int numExtensions = (buffer.ReadBits2(4)*2) + 1;
int numExtensions = (buffer.ReadBits2(4) * 2) + 1;
var hasContent = Convert.ToBoolean(buffer.ReadBits4(4));
if (hasExtensions)

View File

@ -44,7 +44,7 @@ namespace BDInfo
--frameHeaderParse;
if (frameHeaderParse == 0)
{
uint pictureType = 0;
uint pictureType;
if (isInterlaced)
{
if ((parse & 0x80000000) == 0)
@ -97,7 +97,7 @@ namespace BDInfo
switch (sequenceHeaderParse)
{
case 5:
int profileLevel = ((parse & 0x38) >> 3);
int profileLevel = (parse & 0x38) >> 3;
if (((parse & 0xC0) >> 6) == 3)
{
stream.EncodingProfile = string.Format(

View File

@ -19,7 +19,6 @@
#undef DEBUG
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@ -39,7 +38,7 @@ namespace BDInfo
public bool HasLoops = false;
public bool IsCustom = false;
public bool MVCBaseViewR = false;
public bool MVCBaseViewR = false;
public List<double> Chapters = new List<double>();
@ -86,11 +85,13 @@ namespace BDInfo
foreach (TSStreamClip clip in clips)
{
TSStreamClip newClip = new TSStreamClip(
clip.StreamFile, clip.StreamClipFile);
clip.StreamFile, clip.StreamClipFile)
{
Name = clip.Name,
TimeIn = clip.TimeIn,
TimeOut = clip.TimeOut
};
newClip.Name = clip.Name;
newClip.TimeIn = clip.TimeIn;
newClip.TimeOut = clip.TimeOut;
newClip.Length = newClip.TimeOut - newClip.TimeIn;
newClip.RelativeTimeIn = TotalLength;
newClip.RelativeTimeOut = newClip.RelativeTimeIn + newClip.Length;
@ -204,7 +205,7 @@ namespace BDInfo
{
if (TotalLength > 0)
{
return (ulong)Math.Round((TotalSize * 8.0) / TotalLength);
return (ulong)Math.Round(TotalSize * 8.0 / TotalLength);
}
return 0;
}
@ -216,7 +217,7 @@ namespace BDInfo
{
if (TotalAngleLength > 0)
{
return (ulong)Math.Round((TotalAngleSize * 8.0) / TotalAngleLength);
return (ulong)Math.Round(TotalAngleSize * 8.0 / TotalAngleLength);
}
return 0;
}
@ -269,7 +270,7 @@ namespace BDInfo
// misc flags
pos = 0x38;
byte miscFlags = data[pos++];
byte miscFlags = ReadByte(data, ref pos);
// MVC_Base_view_R_flag is stored in 4th bit
MVCBaseViewR = (miscFlags & 0x10) != 0;
@ -331,14 +332,17 @@ namespace BDInfo
double timeOut = (double)outTime / 45000;
TSStreamClip streamClip = new TSStreamClip(
streamFile, streamClipFile);
streamFile, streamClipFile)
{
Name = streamFileName, //TODO
TimeIn = timeIn,
TimeOut = timeOut
};
streamClip.Name = streamFileName; //TODO
streamClip.TimeIn = timeIn;
streamClip.TimeOut = timeOut;
streamClip.Length = streamClip.TimeOut - streamClip.TimeIn;
streamClip.RelativeTimeIn = TotalLength;
streamClip.RelativeTimeOut = streamClip.RelativeTimeIn + streamClip.Length;
streamClip.RelativeLength = streamClip.Length / TotalLength;
StreamClips.Add(streamClip);
chapterClips.Add(streamClip);
@ -382,13 +386,16 @@ namespace BDInfo
}
TSStreamClip angleClip =
new TSStreamClip(angleFile, angleClipFile);
angleClip.AngleIndex = angle + 1;
angleClip.TimeIn = streamClip.TimeIn;
angleClip.TimeOut = streamClip.TimeOut;
angleClip.RelativeTimeIn = streamClip.RelativeTimeIn;
angleClip.RelativeTimeOut = streamClip.RelativeTimeOut;
angleClip.Length = streamClip.Length;
new TSStreamClip(angleFile, angleClipFile)
{
AngleIndex = angle + 1,
TimeIn = streamClip.TimeIn,
TimeOut = streamClip.TimeOut,
RelativeTimeIn = streamClip.RelativeTimeIn,
RelativeTimeOut = streamClip.RelativeTimeOut,
Length = streamClip.Length
};
StreamClips.Add(angleClip);
}
if (angles - 1 > AngleCount) AngleCount = angles - 1;
@ -407,47 +414,73 @@ namespace BDInfo
#if DEBUG
Debug.WriteLine(string.Format(
"{0} : {1} -> V:{2} A:{3} PG:{4} IG:{5} 2A:{6} 2V:{7} PIP:{8}",
CultureInfo.InvariantCulture,
"{0} : {1} -> V:{2} A:{3} PG:{4} IG:{5} 2A:{6} 2V:{7} PIP:{8}",
Name, streamFileName, streamCountVideo, streamCountAudio, streamCountPG, streamCountIG,
Name, streamFileName, streamCountVideo, streamCountAudio, streamCountPG, streamCountIG,
streamCountSecondaryAudio, streamCountSecondaryVideo, streamCountPIP));
#endif
for (int i = 0; i < streamCountVideo; i++)
{
TSStream stream = CreatePlaylistStream(data, ref pos);
if (stream != null) PlaylistStreams[stream.PID] = stream;
if (stream != null)
{
if (!PlaylistStreams.ContainsKey(stream.PID) || streamClip.RelativeLength > 0.01)
PlaylistStreams[stream.PID] = stream;
}
}
for (int i = 0; i < streamCountAudio; i++)
{
TSStream stream = CreatePlaylistStream(data, ref pos);
if (stream != null) PlaylistStreams[stream.PID] = stream;
if (stream != null)
{
if (!PlaylistStreams.ContainsKey(stream.PID) || streamClip.RelativeLength > 0.01)
PlaylistStreams[stream.PID] = stream;
}
}
for (int i = 0; i < streamCountPG; i++)
{
TSStream stream = CreatePlaylistStream(data, ref pos);
if (stream != null) PlaylistStreams[stream.PID] = stream;
if (stream != null)
{
if (!PlaylistStreams.ContainsKey(stream.PID) || streamClip.RelativeLength > 0.01)
PlaylistStreams[stream.PID] = stream;
}
}
for (int i = 0; i < streamCountIG; i++)
{
TSStream stream = CreatePlaylistStream(data, ref pos);
if (stream != null) PlaylistStreams[stream.PID] = stream;
if (stream != null)
{
if (!PlaylistStreams.ContainsKey(stream.PID) || streamClip.RelativeLength > 0.01)
PlaylistStreams[stream.PID] = stream;
}
}
for (int i = 0; i < streamCountSecondaryAudio; i++)
{
TSStream stream = CreatePlaylistStream(data, ref pos);
if (stream != null) PlaylistStreams[stream.PID] = stream;
if (stream != null)
{
if (!PlaylistStreams.ContainsKey(stream.PID) || streamClip.RelativeLength > 0.01)
PlaylistStreams[stream.PID] = stream;
}
pos += 2;
}
for (int i = 0; i < streamCountSecondaryVideo; i++)
{
TSStream stream = CreatePlaylistStream(data, ref pos);
if (stream != null) PlaylistStreams[stream.PID] = stream;
if (stream != null)
{
if (!PlaylistStreams.ContainsKey(stream.PID) || streamClip.RelativeLength > 0.01)
PlaylistStreams[stream.PID] = stream;
}
pos += 6;
}
/*
* TODO
*
*
for (int i = 0; i < streamCountPIP; i++)
{
TSStream stream = CreatePlaylistStream(data, ref pos);
@ -466,13 +499,18 @@ namespace BDInfo
chapterIndex < chapterCount;
chapterIndex++)
{
int chapterType = data[pos+1];
int chapterType = data[pos + 1];
if (chapterType == 1)
{
int streamFileIndex = BinaryPrimitives.ReadUInt16BigEndian(data.AsSpan(pos + 2));
int streamFileIndex =
(data[pos + 2] << 8) + data[pos + 3];
uint chapterTime = BinaryPrimitives.ReadUInt32BigEndian(data.AsSpan(pos + 4));
long chapterTime =
((long)data[pos + 4] << 24) +
((long)data[pos + 5] << 16) +
((long)data[pos + 6] << 8) +
data[pos + 7];
TSStreamClip streamClip = chapterClips[streamFileIndex];
@ -499,14 +537,8 @@ namespace BDInfo
}
finally
{
if (fileReader != null)
{
fileReader.Close();
}
if (fileStream != null)
{
fileStream.Close();
}
fileReader?.Close();
fileStream?.Close();
}
}
@ -610,7 +642,6 @@ namespace BDInfo
#if DEBUG
Debug.WriteLine(string.Format(
CultureInfo.InvariantCulture,
"\t{0} {1} {2} {3} {4}",
pid,
streamType,
@ -632,8 +663,10 @@ namespace BDInfo
case TSStreamType.LPCM_AUDIO:
case TSStreamType.MPEG1_AUDIO:
case TSStreamType.MPEG2_AUDIO:
case TSStreamType.MPEG2_AAC_AUDIO:
case TSStreamType.MPEG4_AAC_AUDIO:
int audioFormat = data[pos++];
int audioFormat = ReadByte(data, ref pos);
TSChannelLayout channelLayout = (TSChannelLayout)
(audioFormat >> 4);
@ -649,7 +682,6 @@ namespace BDInfo
#if DEBUG
Debug.WriteLine(string.Format(
CultureInfo.InvariantCulture,
"\t{0} {1} {2} {3} {4}",
pid,
streamType,
@ -674,7 +706,6 @@ namespace BDInfo
#if DEBUG
Debug.WriteLine(string.Format(
CultureInfo.InvariantCulture,
"\t{0} {1} {2}",
pid,
streamType,
@ -685,7 +716,7 @@ namespace BDInfo
case TSStreamType.SUBTITLE:
int code = data[pos++]; // TODO
int code = ReadByte(data, ref pos); // TODO
string textLanguage = ToolBox.ReadString(data, 3, ref pos);
stream = new TSTextStream();
@ -693,7 +724,6 @@ namespace BDInfo
#if DEBUG
Debug.WriteLine(string.Format(
CultureInfo.InvariantCulture,
"\t{0} {1} {2}",
pid,
streamType,
@ -735,11 +765,14 @@ namespace BDInfo
}
foreach (TSStreamClip clip in StreamClips)
{
if (clip.StreamClipFile.Streams.Count > referenceClip.StreamClipFile.Streams.Count)
if (referenceClip.StreamFile == null && clip.StreamFile != null)
referenceClip = clip;
if (clip.StreamClipFile.Streams.Count > referenceClip.StreamClipFile.Streams.Count && clip.RelativeLength > 0.01)
{
referenceClip = clip;
}
else if (clip.Length > referenceClip.Length)
else if (clip.Length > referenceClip.Length && clip.StreamFile != null)
{
referenceClip = clip;
}
@ -759,6 +792,8 @@ namespace BDInfo
}
}
if (referenceClip == null) return;
foreach (TSStream clipStream
in referenceClip.StreamClipFile.Streams.Values)
{
@ -828,11 +863,11 @@ namespace BDInfo
{
((TSVideoStream)stream).EncodingProfile =
((TSVideoStream)clipStream).EncodingProfile;
((TSVideoStream) stream).ExtendedData =
((TSVideoStream) clipStream).ExtendedData;
((TSVideoStream)stream).ExtendedData =
((TSVideoStream)clipStream).ExtendedData;
}
else if (stream.IsAudioStream &&
clipStream.IsAudioStream)
clipStream.IsAudioStream)
{
TSAudioStream audioStream = (TSAudioStream)stream;
TSAudioStream clipAudioStream = (TSAudioStream)clipStream;
@ -865,6 +900,10 @@ namespace BDInfo
{
audioStream.HasExtensions = clipAudioStream.HasExtensions;
}
if (clipAudioStream.ExtendedData != audioStream.ExtendedData)
{
audioStream.ExtendedData = clipAudioStream.ExtendedData;
}
if (clipAudioStream.CoreStream != null &&
audioStream.CoreStream == null)
{
@ -872,6 +911,18 @@ namespace BDInfo
clipAudioStream.CoreStream.Clone();
}
}
else if (stream.IsGraphicsStream &&
clipStream.IsGraphicsStream)
{
TSGraphicsStream graphicsStream = (TSGraphicsStream)stream;
TSGraphicsStream clipGraphicsStream = (TSGraphicsStream)clipStream;
graphicsStream.Captions = clipGraphicsStream.Captions;
graphicsStream.ForcedCaptions = clipGraphicsStream.ForcedCaptions;
graphicsStream.Width = clipGraphicsStream.Width;
graphicsStream.Height = clipGraphicsStream.Height;
graphicsStream.CaptionIDs = clipGraphicsStream.CaptionIDs;
}
}
}
}
@ -1041,55 +1092,56 @@ namespace BDInfo
{
return 1;
}
else
{
if (x.ChannelCount > y.ChannelCount)
{
return -1;
}
else if (y.ChannelCount > x.ChannelCount)
{
return 1;
}
else
{
int sortX = GetStreamTypeSortIndex(x.StreamType);
int sortY = GetStreamTypeSortIndex(y.StreamType);
if (x.ChannelCount > y.ChannelCount)
{
return -1;
if (sortX > sortY)
{
return -1;
}
else if (sortY > sortX)
{
return 1;
}
else
{
if (x.LanguageCode == "eng")
{
return -1;
}
else if (y.LanguageCode == "eng")
{
return 1;
}
else if (x.LanguageCode != y.LanguageCode)
{
return string.Compare(
x.LanguageName, y.LanguageName);
}
else if (x.PID < y.PID)
{
return -1;
}
else if (y.PID < x.PID)
{
return 1;
}
return 0;
}
}
}
else if (y.ChannelCount > x.ChannelCount)
{
return 1;
}
int sortX = GetStreamTypeSortIndex(x.StreamType);
int sortY = GetStreamTypeSortIndex(y.StreamType);
if (sortX > sortY)
{
return -1;
}
if (sortY > sortX)
{
return 1;
}
if (string.Equals(x.LanguageCode, "eng", StringComparison.Ordinal))
{
return -1;
}
else if (string.Equals(y.LanguageCode, "eng", StringComparison.Ordinal))
{
return 1;
}
var strCmp = string.Compare(
x.LanguageName, y.LanguageName, StringComparison.Ordinal);
if (strCmp != 0)
{
return strCmp;
}
if (x.PID < y.PID)
{
return -1;
}
else if (y.PID < x.PID)
{
return 1;
}
return 0;
}
public static int CompareTextStreams(
@ -1112,33 +1164,40 @@ namespace BDInfo
{
return 1;
}
if (string.Equals(x.LanguageCode, "eng", StringComparison.Ordinal))
else
{
return -1;
if (x.LanguageCode == "eng")
{
return -1;
}
else if (y.LanguageCode == "eng")
{
return 1;
}
else
{
if (x.LanguageCode == y.LanguageCode)
{
if (x.PID > y.PID)
{
return 1;
}
else if (y.PID > x.PID)
{
return -1;
}
else
{
return 0;
}
}
else
{
return string.Compare(
x.LanguageName, y.LanguageName);
}
}
}
else if (string.Equals(y.LanguageCode, "eng", StringComparison.Ordinal))
{
return 1;
}
var strCmp = string.Compare(
x.LanguageName, y.LanguageName, StringComparison.Ordinal);
if (strCmp != 0)
{
return strCmp;
}
if (x.PID < y.PID)
{
return -1;
}
else if (y.PID < x.PID)
{
return 1;
}
return 0;
}
private static int CompareGraphicsStreams(
@ -1161,45 +1220,50 @@ namespace BDInfo
{
return 1;
}
else
{
int sortX = GetStreamTypeSortIndex(x.StreamType);
int sortY = GetStreamTypeSortIndex(y.StreamType);
int sortX = GetStreamTypeSortIndex(x.StreamType);
int sortY = GetStreamTypeSortIndex(y.StreamType);
if (sortX > sortY)
{
return -1;
if (sortX > sortY)
{
return -1;
}
else if (sortY > sortX)
{
return 1;
}
else if (x.LanguageCode == "eng")
{
return -1;
}
else if (y.LanguageCode == "eng")
{
return 1;
}
else
{
if (x.LanguageCode == y.LanguageCode)
{
if (x.PID > y.PID)
{
return 1;
}
else if (y.PID > x.PID)
{
return -1;
}
else
{
return 0;
}
}
else
{
return string.Compare(x.LanguageName, y.LanguageName);
}
}
}
else if (sortY > sortX)
{
return 1;
}
if (string.Equals(x.LanguageCode, "eng", StringComparison.Ordinal))
{
return -1;
}
else if (string.Equals(y.LanguageCode, "eng", StringComparison.Ordinal))
{
return 1;
}
var strCmp = string.Compare(
x.LanguageName, y.LanguageName, StringComparison.Ordinal);
if (strCmp != 0)
{
return strCmp;
}
if (x.PID < y.PID)
{
return -1;
}
else if (y.PID < x.PID)
{
return 1;
}
return 0;
}
private static int GetStreamTypeSortIndex(TSStreamType streamType)
@ -1235,14 +1299,18 @@ namespace BDInfo
return 6;
case TSStreamType.AC3_PLUS_AUDIO:
return 7;
case TSStreamType.DTS_HD_AUDIO:
case TSStreamType.MPEG2_AAC_AUDIO:
return 8;
case TSStreamType.AC3_TRUE_HD_AUDIO:
case TSStreamType.MPEG4_AAC_AUDIO:
return 9;
case TSStreamType.DTS_HD_MASTER_AUDIO:
case TSStreamType.DTS_HD_AUDIO:
return 10;
case TSStreamType.LPCM_AUDIO:
case TSStreamType.AC3_TRUE_HD_AUDIO:
return 11;
case TSStreamType.DTS_HD_MASTER_AUDIO:
return 12;
case TSStreamType.LPCM_AUDIO:
return 13;
case TSStreamType.SUBTITLE:
return 1;
@ -1256,22 +1324,39 @@ namespace BDInfo
}
}
private static int ReadInt32(
protected int ReadInt32(
byte[] data,
ref int pos)
{
int val = BinaryPrimitives.ReadInt32BigEndian(data.AsSpan(pos));
int val =
(data[pos] << 24) +
(data[pos + 1] << 16) +
(data[pos + 2] << 8) +
data[pos + 3];
pos += 4;
return val;
}
private static int ReadInt16(
protected int ReadInt16(
byte[] data,
ref int pos)
{
int val = BinaryPrimitives.ReadUInt16BigEndian(data.AsSpan(pos));
int val =
(data[pos] << 8) +
data[pos + 1];
pos += 2;
return val;
}
protected byte ReadByte(
byte[] data,
ref int pos)
{
return data[pos++];
}
}
}

View File

@ -34,6 +34,8 @@ namespace BDInfo
VC1_VIDEO = 0xea,
MPEG1_AUDIO = 0x03,
MPEG2_AUDIO = 0x04,
MPEG2_AAC_AUDIO = 0x0F,
MPEG4_AAC_AUDIO = 0x11,
LPCM_AUDIO = 0x80,
AC3_AUDIO = 0x81,
AC3_PLUS_AUDIO = 0x84,
@ -191,6 +193,8 @@ namespace BDInfo
{
case TSStreamType.MPEG1_AUDIO:
case TSStreamType.MPEG2_AUDIO:
case TSStreamType.MPEG2_AAC_AUDIO:
case TSStreamType.MPEG4_AAC_AUDIO:
case TSStreamType.LPCM_AUDIO:
case TSStreamType.AC3_AUDIO:
case TSStreamType.AC3_PLUS_AUDIO:
@ -258,9 +262,10 @@ namespace BDInfo
case TSStreamType.VC1_VIDEO:
return "VC-1 Video";
case TSStreamType.MPEG1_AUDIO:
return "MP1 Audio";
case TSStreamType.MPEG2_AUDIO:
return "MP2 Audio";
case TSStreamType.MPEG2_AAC_AUDIO:
case TSStreamType.MPEG4_AAC_AUDIO:
return (string)((TSAudioStream)this).ExtendedData;
case TSStreamType.LPCM_AUDIO:
return "LPCM Audio";
case TSStreamType.AC3_AUDIO:
@ -276,7 +281,7 @@ namespace BDInfo
case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
return "Dolby Digital Plus Audio";
case TSStreamType.AC3_TRUE_HD_AUDIO:
if (((TSAudioStream) this).HasExtensions)
if (((TSAudioStream)this).HasExtensions)
return "Dolby TrueHD/Atmos Audio";
else
return "Dolby TrueHD Audio";
@ -293,7 +298,7 @@ namespace BDInfo
case TSStreamType.DTS_HD_SECONDARY_AUDIO:
return "DTS Express";
case TSStreamType.DTS_HD_MASTER_AUDIO:
if (((TSAudioStream) this).HasExtensions)
if (((TSAudioStream)this).HasExtensions)
return "DTS:X Master Audio";
else
return "DTS-HD Master Audio";
@ -331,6 +336,10 @@ namespace BDInfo
return "MP1";
case TSStreamType.MPEG2_AUDIO:
return "MP2";
case TSStreamType.MPEG2_AAC_AUDIO:
return "MPEG-2 AAC";
case TSStreamType.MPEG4_AAC_AUDIO:
return "MPEG-4 AAC";
case TSStreamType.LPCM_AUDIO:
return "LPCM";
case TSStreamType.AC3_AUDIO:
@ -391,6 +400,10 @@ namespace BDInfo
return "MP1";
case TSStreamType.MPEG2_AUDIO:
return "MP2";
case TSStreamType.MPEG2_AAC_AUDIO:
return "MPEG-2 AAC";
case TSStreamType.MPEG4_AAC_AUDIO:
return "MPEG-4 AAC";
case TSStreamType.LPCM_AUDIO:
return "LPCM";
case TSStreamType.AC3_AUDIO:
@ -616,7 +629,7 @@ namespace BDInfo
}
if (StreamType == TSStreamType.HEVC_VIDEO && ExtendedData != null)
{
var extendedData = (TSCodecHEVC.ExtendedDataSet) ExtendedData;
var extendedData = (TSCodecHEVC.ExtendedDataSet)ExtendedData;
string extendedInfo = string.Join(" / ", extendedData.ExtendedFormatInfo);
description += extendedInfo;
}
@ -654,7 +667,9 @@ namespace BDInfo
DualMono,
Stereo,
Surround,
Extended
Extended,
JointStereo,
Mono
}
public class TSAudioStream : TSStream
@ -671,6 +686,8 @@ namespace BDInfo
public bool HasExtensions = false;
public object ExtendedData;
public TSAudioMode AudioMode;
public TSAudioStream CoreStream;
public TSChannelLayout ChannelLayout;
@ -787,6 +804,10 @@ namespace BDInfo
case TSAudioMode.Surround:
description += " / Dolby Surround";
break;
case TSAudioMode.JointStereo:
description += " / Joint Stereo";
break;
}
}
if (description.EndsWith(" / "))
@ -808,7 +829,7 @@ namespace BDInfo
codec = "DD+ Embedded";
break;
}
description += string.Format( CultureInfo.InvariantCulture,
description += string.Format(CultureInfo.InvariantCulture,
" ({0}: {1})",
codec,
CoreStream.Description);
@ -829,6 +850,7 @@ namespace BDInfo
stream.LFE = LFE;
stream.DialNorm = DialNorm;
stream.AudioMode = AudioMode;
stream.ExtendedData = ExtendedData;
if (CoreStream != null)
{
@ -841,18 +863,62 @@ namespace BDInfo
public class TSGraphicsStream : TSStream
{
public int Width;
public int Height;
public int Captions;
public int ForcedCaptions;
public Dictionary<int, TSCodecPGS.Frame> CaptionIDs;
public TSCodecPGS.Frame LastFrame;
public TSGraphicsStream()
{
IsVBR = true;
IsInitialized = true;
IsInitialized = false;
Width = 0;
Height = 0;
Captions = 0;
ForcedCaptions = 0;
CaptionIDs = new Dictionary<int, TSCodecPGS.Frame>();
LastFrame = new TSCodecPGS.Frame();
}
public override TSStream Clone()
{
TSGraphicsStream stream = new TSGraphicsStream();
CopyTo(stream);
stream.Width = Width;
stream.Height = Height;
stream.Captions = Captions;
stream.ForcedCaptions = ForcedCaptions;
stream.CaptionIDs = CaptionIDs;
stream.LastFrame = LastFrame;
return stream;
}
public override string Description
{
get
{
string description = string.Empty;
if (Width > 0 || Height > 0)
{
description = string.Format(CultureInfo.InvariantCulture, "{0:D}x{1:D}", Width, Height);
}
if (Captions > 0 || ForcedCaptions > 0)
{
if (Captions > 0)
{
description += string.Format(CultureInfo.InvariantCulture, " / {0:D} Caption{1}", Captions, Captions > 1 ? "s" : "");
}
if (ForcedCaptions > 0)
{
description += string.Format(CultureInfo.InvariantCulture, (Captions > 0 ? " ( + " : " / ") + "{0:D} Forced Caption{1}" + (Captions > 0 ? ")" : ""), ForcedCaptions, ForcedCaptions > 1 ? "s" : "");
}
}
return description;
}
}
}
public class TSTextStream : TSStream

View File

@ -28,13 +28,14 @@ namespace BDInfo
{
private readonly MemoryStream _stream;
private int _skipBits;
private int _skippedBytes;
private readonly byte[] _buffer;
private int _bufferLength;
public int TransferLength;
public TSStreamBuffer()
{
_buffer = new byte[20480];
_buffer = new byte[5242880];
_stream = new MemoryStream(_buffer);
}
@ -71,6 +72,7 @@ namespace BDInfo
public void BeginRead()
{
_skipBits = 0;
_skippedBytes = 0;
_stream.Seek(0, SeekOrigin.Begin);
}
@ -90,45 +92,91 @@ namespace BDInfo
return value;
}
public byte ReadByte()
public byte ReadByte(bool skipH26xEmulationByte)
{
return (byte)_stream.ReadByte();
#if BETA || DEBUG
long streamPos = _stream.Position;
byte tempByte = _buffer[streamPos];
if (skipH26xEmulationByte && tempByte == 0x03)
{
if (streamPos > 2 && _buffer[streamPos - 2] == 0x00 && _buffer[streamPos - 1] == 0x00)
{
streamPos++;
tempByte = _buffer[streamPos];
_skippedBytes++;
}
}
_stream.Position = streamPos + 1;
return tempByte;
#else
byte tempByte = (byte)_stream.ReadByte();
var tempPosition = _stream.Position;
if (skipH26xEmulationByte && tempByte == 0x03)
{
_stream.Seek(-3, SeekOrigin.Current);
if (_stream.ReadByte() == 0x00 && _stream.ReadByte() == 0x00)
{
_stream.Seek(1, SeekOrigin.Current);
tempByte = (byte)_stream.ReadByte();
_skippedBytes++;
}
else
{
_stream.Seek(tempPosition, SeekOrigin.Begin);
}
}
return tempByte;
#endif
}
public bool ReadBool()
public byte ReadByte()
{
return ReadByte(false);
}
public bool ReadBool(bool skipH26xEmulationByte)
{
var pos = _stream.Position;
_skippedBytes = 0;
if (pos == _bufferLength) return false;
var shift = 24;
var data = 0;
for (var i = 0; i < 4; i++)
{
if (pos + i >= _bufferLength) break;
data += (_stream.ReadByte() << shift);
shift -= 8;
}
var data = ReadByte(skipH26xEmulationByte);
var vector = new BitVector32(data);
var value = vector[1 << (32 - _skipBits - 1)];
var value = vector[1 << (8 - _skipBits - 1)];
_skipBits += 1;
_stream.Seek(pos + (_skipBits >> 3), SeekOrigin.Begin);
#if BETA || DEBUG
_stream.Position = pos + (_skipBits >> 3) + _skippedBytes;
#else
_stream.Seek(pos + (_skipBits >> 3) + _skippedBytes, SeekOrigin.Begin);
#endif
_skipBits %= 8;
return value;
}
public ushort ReadBits2(int bits)
public bool ReadBool()
{
return ReadBool(false);
}
public ushort ReadBits2(int bits, bool skipH26xEmulationByte)
{
var pos = _stream.Position;
_skippedBytes = 0;
var shift = 8;
var data = 0;
for (var i = 0; i < 2; i++)
{
if (pos + i >= _bufferLength) break;
data += (_stream.ReadByte() << shift);
data += ReadByte(skipH26xEmulationByte) << shift;
shift -= 8;
}
var vector = new BitVector32(data);
@ -140,22 +188,32 @@ namespace BDInfo
value += (ushort)(vector[1 << (16 - i - 1)] ? 1 : 0);
}
_skipBits += bits;
_stream.Seek(pos + (_skipBits >> 3), SeekOrigin.Begin);
#if BETA || DEBUG
_stream.Position = pos + (_skipBits >> 3) + _skippedBytes;
#else
_stream.Seek(pos + (_skipBits >> 3) + _skippedBytes, SeekOrigin.Begin);
#endif
_skipBits %= 8;
return value;
}
public uint ReadBits4(int bits)
public ushort ReadBits2(int bits)
{
return ReadBits2(bits, false);
}
public uint ReadBits4(int bits, bool skipH26xEmulationByte)
{
var pos = _stream.Position;
_skippedBytes = 0;
var shift = 24;
var data = 0;
for (var i = 0; i < 4; i++)
{
if (pos + i >= _bufferLength) break;
data += (_stream.ReadByte() << shift);
data += ReadByte(skipH26xEmulationByte) << shift;
shift -= 8;
}
var vector = new BitVector32(data);
@ -164,25 +222,35 @@ namespace BDInfo
for (var i = _skipBits; i < _skipBits + bits; i++)
{
value <<= 1;
value += (uint)(vector[1<<(32 - i - 1)] ? 1 : 0);
value += (uint)(vector[1 << (32 - i - 1)] ? 1 : 0);
}
_skipBits += bits;
_stream.Seek(pos + (_skipBits >> 3), SeekOrigin.Begin);
#if BETA || DEBUG
_stream.Position = pos + (_skipBits >> 3) + _skippedBytes;
#else
_stream.Seek(pos + (_skipBits >> 3) + _skippedBytes, SeekOrigin.Begin);
#endif
_skipBits %= 8;
return value;
}
public ulong ReadBits8(int bits)
public uint ReadBits4(int bits)
{
return ReadBits4(bits, false);
}
public ulong ReadBits8(int bits, bool skipH26xEmulationByte)
{
var pos = _stream.Position;
_skippedBytes = 0;
var shift = 24;
var data = 0;
for (var i = 0; i < 4; i++)
{
if (pos + i >= _bufferLength) break;
data += (_stream.ReadByte() << shift);
data += ReadByte(skipH26xEmulationByte) << shift;
shift -= 8;
}
@ -191,34 +259,52 @@ namespace BDInfo
for (var i = 0; i < 4; i++)
{
if (pos + i >= _bufferLength) break;
data2 += (_stream.ReadByte() << shift);
data2 += ReadByte(skipH26xEmulationByte) << shift;
shift -= 8;
}
var vector = new BitArray(new []{data2, data});
var vector = new BitArray(new[] { data2, data });
ulong value = 0;
for (var i = _skipBits; i < _skipBits + bits; i++)
{
value <<= 1;
value += (ulong)(vector[(64 - i - 1)] ? 1 : 0);
value += (ulong)(vector[64 - i - 1] ? 1 : 0);
}
_skipBits += bits;
_stream.Seek(pos + (_skipBits >> 3), SeekOrigin.Begin);
#if BETA || DEBUG
_stream.Position = pos + (_skipBits >> 3) + _skippedBytes;
#else
_stream.Seek(pos + (_skipBits >> 3) + _skippedBytes, SeekOrigin.Begin);
#endif
_skipBits %= 8;
return value;
}
public ulong ReadBits8(int bits)
{
return ReadBits8(bits, false);
}
public void BSSkipBits(int bits, bool skipH26xEmulationByte)
{
int count = bits / 16 + (bits % 16 > 0 ? 1 : 0);
int bitsRead = 0;
var bitsToRead = 0;
for (int i = 0; i < count; i++)
{
bitsToRead = bits - bitsRead;
bitsToRead = bitsToRead > 16 ? 16 : bitsToRead;
ReadBits2(bitsToRead, skipH26xEmulationByte);
bitsRead += bitsToRead;
}
}
public void BSSkipBits(int bits)
{
var pos = _stream.Position;
if (pos == _bufferLength) return;
_skipBits += bits;
_stream.Seek(pos + (_skipBits >> 3), SeekOrigin.Begin);
_skipBits %= 8;
BSSkipBits(bits, false);
}
public void BSSkipNextByte()
@ -227,51 +313,87 @@ namespace BDInfo
BSSkipBits(8 - _skipBits);
}
public void BSSkipBytes(int bytes)
public void BSResetBits()
{
var pos = _stream.Position;
if (pos + bytes >= _bufferLength) return;
_stream.Seek(pos + bytes, SeekOrigin.Begin);
_skipBits = 0;
}
public uint ReadExp()
public void BSSkipBytes(int bytes, bool skipH26xEmulationByte)
{
if (bytes > 0)
{
for (int i = 0; i < bytes; i++)
ReadByte(skipH26xEmulationByte);
}
else
{
var pos = _stream.Position;
#if BETA || DEBUG
_stream.Position = pos + (_skipBits >> 3) + bytes;
#else
_stream.Seek(pos + (_skipBits >> 3) + bytes, SeekOrigin.Begin);
#endif
}
}
public void BSSkipBytes(int bytes)
{
BSSkipBytes(bytes, false);
}
public uint ReadExp(bool skipH26xEmulationByte)
{
byte leadingZeroes = 0;
while (DataBitStreamRemain() > 0 && !ReadBool())
while (DataBitStreamRemain() > 0 && !ReadBool(skipH26xEmulationByte))
leadingZeroes++;
var infoD = Math.Pow(2, leadingZeroes);
var result = (uint)infoD - 1 + ReadBits4(leadingZeroes);
var result = (uint)infoD - 1 + ReadBits4(leadingZeroes, skipH26xEmulationByte);
return result;
}
public void SkipExp()
public uint ReadExp()
{
return ReadExp(false);
}
public void SkipExp(bool skipH26xEmulationByte)
{
byte leadingZeroes = 0;
while (DataBitStreamRemain() > 0 && !ReadBool())
while (DataBitStreamRemain() > 0 && !ReadBool(skipH26xEmulationByte))
leadingZeroes++;
BSSkipBits(leadingZeroes);
BSSkipBits(leadingZeroes, skipH26xEmulationByte);
}
public void SkipExp()
{
SkipExp(false);
}
public void SkipExpMulti(int num, bool skipH26xEmulationByte)
{
for (int i = 0; i < num; i++)
{
SkipExp(skipH26xEmulationByte);
}
}
public void SkipExpMulti(int num)
{
for (int i = 0; i < num; i++)
{
SkipExp();
}
SkipExpMulti(num, false);
}
public long DataBitStreamRemain()
{
return (_stream.Length - _stream.Position)*8 - _skipBits;
var remain = (_bufferLength - _stream.Position) * 8 - _skipBits;
return remain;
}
public long DataBitStreamRemainBytes()
{
return (_stream.Length - _stream.Position);
return _bufferLength - _stream.Position;
}
}
}

View File

@ -31,6 +31,7 @@ namespace BDInfo
public double RelativeTimeIn;
public double RelativeTimeOut;
public double Length;
public double RelativeLength;
public ulong FileSize = 0;
public ulong InterleavedFileSize = 0;
@ -53,12 +54,12 @@ namespace BDInfo
StreamFile = streamFile;
if (StreamFile.FileInfo != null)
FileSize = (ulong) StreamFile.FileInfo.Length;
FileSize = (ulong)StreamFile.FileInfo.Length;
if (StreamFile.InterleavedFile != null)
{
if (StreamFile.InterleavedFile.FileInfo != null)
InterleavedFileSize = (ulong) StreamFile.InterleavedFile.FileInfo.Length;
InterleavedFileSize = (ulong)StreamFile.InterleavedFile.FileInfo.Length;
}
}
StreamClipFile = streamClipFile;
@ -92,7 +93,7 @@ namespace BDInfo
{
if (PacketSeconds > 0)
{
return (ulong)Math.Round(((PacketSize * 8.0) / PacketSeconds));
return (ulong)Math.Round(PacketSize * 8.0 / PacketSeconds);
}
return 0;
}

View File

@ -35,7 +35,7 @@ namespace BDInfo
public string Name = null;
public Dictionary<ushort, TSStream> Streams =
new Dictionary<ushort,TSStream>();
new Dictionary<ushort, TSStream>();
public TSStreamClipFile(IFileInfo fileInfo)
{
@ -121,18 +121,18 @@ namespace BDInfo
case TSStreamType.MPEG1_VIDEO:
case TSStreamType.MPEG2_VIDEO:
case TSStreamType.VC1_VIDEO:
{
TSVideoFormat videoFormat = (TSVideoFormat)
(clipData[streamOffset + 2] >> 4);
TSFrameRate frameRate = (TSFrameRate)
(clipData[streamOffset + 2] & 0xF);
TSAspectRatio aspectRatio = (TSAspectRatio)
(clipData[streamOffset + 3] >> 4);
{
TSVideoFormat videoFormat = (TSVideoFormat)
(clipData[streamOffset + 2] >> 4);
TSFrameRate frameRate = (TSFrameRate)
(clipData[streamOffset + 2] & 0xF);
TSAspectRatio aspectRatio = (TSAspectRatio)
(clipData[streamOffset + 3] >> 4);
stream = new TSVideoStream();
((TSVideoStream)stream).VideoFormat = videoFormat;
((TSVideoStream)stream).AspectRatio = aspectRatio;
((TSVideoStream)stream).FrameRate = frameRate;
stream = new TSVideoStream();
((TSVideoStream)stream).VideoFormat = videoFormat;
((TSVideoStream)stream).AspectRatio = aspectRatio;
((TSVideoStream)stream).FrameRate = frameRate;
#if DEBUG
Debug.WriteLine(string.Format(
"\t{0} {1} {2} {3} {4}",
@ -142,8 +142,8 @@ namespace BDInfo
frameRate,
aspectRatio));
#endif
}
break;
}
break;
case TSStreamType.AC3_AUDIO:
case TSStreamType.AC3_PLUS_AUDIO:
@ -156,23 +156,25 @@ namespace BDInfo
case TSStreamType.LPCM_AUDIO:
case TSStreamType.MPEG1_AUDIO:
case TSStreamType.MPEG2_AUDIO:
{
byte[] languageBytes = new byte[3];
Array.Copy(clipData, streamOffset + 3,
languageBytes, 0, languageBytes.Length);
string languageCode =
ASCIIEncoding.ASCII.GetString(languageBytes);
case TSStreamType.MPEG2_AAC_AUDIO:
case TSStreamType.MPEG4_AAC_AUDIO:
{
byte[] languageBytes = new byte[3];
Array.Copy(clipData, streamOffset + 3,
languageBytes, 0, languageBytes.Length);
string languageCode =
ASCIIEncoding.ASCII.GetString(languageBytes);
TSChannelLayout channelLayout = (TSChannelLayout)
(clipData[streamOffset + 2] >> 4);
TSSampleRate sampleRate = (TSSampleRate)
(clipData[streamOffset + 2] & 0xF);
TSChannelLayout channelLayout = (TSChannelLayout)
(clipData[streamOffset + 2] >> 4);
TSSampleRate sampleRate = (TSSampleRate)
(clipData[streamOffset + 2] & 0xF);
stream = new TSAudioStream();
((TSAudioStream)stream).LanguageCode = languageCode;
((TSAudioStream)stream).ChannelLayout = channelLayout;
((TSAudioStream)stream).SampleRate = TSAudioStream.ConvertSampleRate(sampleRate);
((TSAudioStream)stream).LanguageCode = languageCode;
stream = new TSAudioStream();
((TSAudioStream)stream).LanguageCode = languageCode;
((TSAudioStream)stream).ChannelLayout = channelLayout;
((TSAudioStream)stream).SampleRate = TSAudioStream.ConvertSampleRate(sampleRate);
((TSAudioStream)stream).LanguageCode = languageCode;
#if DEBUG
Debug.WriteLine(string.Format(
"\t{0} {1} {2} {3} {4}",
@ -182,20 +184,20 @@ namespace BDInfo
channelLayout,
sampleRate));
#endif
}
break;
}
break;
case TSStreamType.INTERACTIVE_GRAPHICS:
case TSStreamType.PRESENTATION_GRAPHICS:
{
byte[] languageBytes = new byte[3];
Array.Copy(clipData, streamOffset + 2,
languageBytes, 0, languageBytes.Length);
string languageCode =
Encoding.ASCII.GetString(languageBytes);
{
byte[] languageBytes = new byte[3];
Array.Copy(clipData, streamOffset + 2,
languageBytes, 0, languageBytes.Length);
string languageCode =
ASCIIEncoding.ASCII.GetString(languageBytes);
stream = new TSGraphicsStream();
stream.LanguageCode = languageCode;
stream = new TSGraphicsStream();
stream.LanguageCode = languageCode;
#if DEBUG
Debug.WriteLine(string.Format(
"\t{0} {1} {2}",
@ -203,16 +205,16 @@ namespace BDInfo
streamType,
languageCode));
#endif
}
break;
}
break;
case TSStreamType.SUBTITLE:
{
byte[] languageBytes = new byte[3];
Array.Copy(clipData, streamOffset + 3,
languageBytes, 0, languageBytes.Length);
string languageCode =
ASCIIEncoding.ASCII.GetString(languageBytes);
{
byte[] languageBytes = new byte[3];
Array.Copy(clipData, streamOffset + 3,
languageBytes, 0, languageBytes.Length);
string languageCode =
ASCIIEncoding.ASCII.GetString(languageBytes);
#if DEBUG
Debug.WriteLine(string.Format(
"\t{0} {1} {2}",
@ -220,10 +222,10 @@ namespace BDInfo
streamType,
languageCode));
#endif
stream = new TSTextStream();
stream.LanguageCode = languageCode;
}
break;
stream = new TSTextStream();
stream.LanguageCode = languageCode;
}
break;
}
if (stream != null)
@ -239,8 +241,8 @@ namespace BDInfo
}
finally
{
if (fileReader != null) fileReader.Close();
if (fileStream != null) fileStream.Close();
fileReader?.Close();
fileStream?.Close();
}
}
}

View File

@ -21,6 +21,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using BDInfo.IO;
namespace BDInfo
@ -49,25 +50,26 @@ namespace BDInfo
public bool TransferState = false;
public int TransferLength = 0;
public int PacketLength = 0;
public bool PacketLengthVariable = false;
public byte PacketLengthParse = 0;
public byte PacketParse = 0;
public byte PTSParse = 0;
public ulong PTS = 0;
public BigInteger PTS = 0;
public ulong PTSTemp = 0;
public ulong PTSLast = 0;
public ulong PTSPrev = 0;
public ulong PTSDiff = 0;
public BigInteger PTSLast = 0;
public BigInteger PTSPrev = 0;
public BigInteger PTSDiff = 0;
public ulong PTSCount = 0;
public ulong PTSTransfer = 0;
public BigInteger PTSTransfer = 0;
public byte DTSParse = 0;
public ulong DTSTemp = 0;
public ulong DTSPrev = 0;
public BigInteger DTSTemp = 0;
public BigInteger DTSPrev = 0;
public byte PESHeaderLength = 0;
public byte PESHeaderFlags = 0;
#if DEBUG
#if DEBUG && !BETA
public byte PESHeaderIndex = 0;
public byte[] PESHeader = new byte[256 + 9];
#endif
@ -91,15 +93,16 @@ namespace BDInfo
public bool AdaptionFieldState = false;
public byte AdaptionFieldParse = 0;
public byte AdaptionFieldLength = 0;
public bool VariablePacketEnd = false;
public ushort PCRPID = 0xFFFF;
public byte PCRParse = 0;
public ulong PreviousPCR = 0;
public ulong PCR = 0;
public ulong PCRCount = 0;
public ulong PTSFirst = ulong.MaxValue;
public ulong PTSLast = ulong.MinValue;
public ulong PTSDiff = 0;
public BigInteger PreviousPCR = 0;
public BigInteger PCR = 0;
public BigInteger PCRCount = 0;
public BigInteger PTSFirst = ulong.MaxValue;
public BigInteger PTSLast = ulong.MinValue;
public BigInteger PTSDiff = 0;
public byte[] PAT = new byte[1024];
public bool PATSectionStart = false;
@ -170,6 +173,10 @@ namespace BDInfo
new Dictionary<ushort, List<TSStreamDiagnostics>>();
private List<TSPlaylistFile> Playlists = null;
#if DEBUG && !BETA
private FileStream logFile = null;
private TextWriter logTextWriter = null;
#endif
public TSStreamFile(IFileInfo fileInfo)
{
@ -201,7 +208,8 @@ namespace BDInfo
private bool ScanStream(
TSStream stream,
TSStreamState streamState,
TSStreamBuffer buffer)
TSStreamBuffer buffer,
bool isFullScan)
{
streamState.StreamTag = null;
@ -210,7 +218,7 @@ namespace BDInfo
streamState.PTSTransfer > 0)
{
bitrate = (long)Math.Round(
(buffer.TransferLength * 8.0) /
buffer.TransferLength * 8.0 /
((double)streamState.PTSTransfer / 90000));
if (bitrate > streamState.PeakTransferRate)
@ -251,6 +259,18 @@ namespace BDInfo
(TSVideoStream)stream, buffer, ref streamState.StreamTag);
break;
case TSStreamType.MPEG1_AUDIO:
case TSStreamType.MPEG2_AUDIO:
TSCodecMPA.Scan(
(TSAudioStream)stream, buffer, ref streamState.StreamTag);
break;
case TSStreamType.MPEG2_AAC_AUDIO:
case TSStreamType.MPEG4_AAC_AUDIO:
TSCodecAAC.Scan(
(TSAudioStream)stream, buffer, ref streamState.StreamTag);
break;
case TSStreamType.AC3_AUDIO:
TSCodecAC3.Scan(
(TSAudioStream)stream, buffer, ref streamState.StreamTag);
@ -284,6 +304,14 @@ namespace BDInfo
(TSAudioStream)stream, buffer, bitrate, ref streamState.StreamTag);
break;
case TSStreamType.PRESENTATION_GRAPHICS:
if (isFullScan)
TSCodecPGS.Scan(
(TSGraphicsStream)stream, buffer, ref streamState.StreamTag);
else
stream.IsInitialized = true;
break;
default:
stream.IsInitialized = true;
break;
@ -317,8 +345,8 @@ namespace BDInfo
private void UpdateStreamBitrates(
ushort PTSPID,
ulong PTS,
ulong PTSDiff)
BigInteger PTS,
BigInteger PTSDiff)
{
if (Playlists == null) return;
@ -354,7 +382,7 @@ namespace BDInfo
if (playlistStream.IsVBR)
{
playlistStream.BitRate = (long)Math.Round(
((playlistStream.PayloadBytes * 8.0) / packetSeconds));
playlistStream.PayloadBytes * 8.0 / packetSeconds);
}
}
}
@ -364,8 +392,8 @@ namespace BDInfo
private void UpdateStreamBitrate(
ushort PID,
ushort PTSPID,
ulong PTS,
ulong PTSDiff)
BigInteger PTS,
BigInteger PTSDiff)
{
if (Playlists == null) return;
@ -411,8 +439,11 @@ namespace BDInfo
stream.PacketSeconds += streamInterval;
stream.ActiveBitRate = (long)Math.Round(
((stream.PayloadBytes * 8.0) /
stream.PacketSeconds));
stream.PayloadBytes * 8.0 /
stream.PacketSeconds);
#if DEBUG && !BETA
logTextWriter.WriteLine($"{PID,6}\t{stream.ActiveBitRate,16:000000.000}\t{streamState.WindowBytes,16}\t{stream.PayloadBytes,16}\t{streamState.WindowPackets,16}\t{stream.PacketCount,16}\t{stream.PacketSeconds,16:000000.000}\t{streamInterval,16:000000.000}");
#endif
}
if (stream.StreamType == TSStreamType.AC3_TRUE_HD_AUDIO &&
@ -457,20 +488,34 @@ namespace BDInfo
}
Playlists = playlists;
int dataSize = 16384;
int dataSize = 5242880;
Stream fileStream = null;
try
{
string fileName = "";
string fileName;
#if DEBUG && !BETA
string logFileName;
#endif
if (BDInfoSettings.EnableSSIF &&
InterleavedFile != null)
{
if (InterleavedFile.FileInfo != null)
{
fileName = InterleavedFile.FileInfo.FullName;
#if DEBUG && !BETA
logFileName = InterleavedFile.FileInfo.Name;
#endif
}
}
else
{
fileName = FileInfo.FullName;
if (FileInfo != null)
{
fileName = FileInfo.FullName;
#if DEBUG && !BETA
logFileName = FileInfo.Name;
#endif
}
}
@ -489,8 +534,29 @@ namespace BDInfo
long fileLength = (uint)fileStream.Length;
byte[] buffer = new byte[dataSize];
int bufferLength = 0;
#if DEBUG && !BETA
var appPath = this.GetType().Assembly.Location;
var appDirectory = Path.GetDirectoryName(appPath);
var logDir = Path.Combine(appDirectory, "StreamLogs");
try
{
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
logFile = new FileStream(Path.ChangeExtension(Path.Combine(logDir, logFileName), "txt"), FileMode.Create, FileAccess.Write);
logTextWriter = new StreamWriter(logFile);
logTextWriter.WriteLine(String.Format("{0,6}\t{1,16}\t{2,16}\t{3,16}\t{4,16}\t{5,16}\t{6,16}\t{7,16}", "PID", "Active Bitrate", "Window Bytes", "Payload Bytes", "Window Packets", "Packet Count", "Packet Seconds", "Stream Interval"));
#endif
while ((bufferLength =
fileStream.Read(buffer, 0, buffer.Length)) > 0)
fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
int offset = 0;
for (int i = 0; i < bufferLength; i++)
@ -505,7 +571,7 @@ namespace BDInfo
case 3:
parser.TimeCode = 0;
parser.TimeCode |=
((uint)buffer[i] & 0x3F) << 24;
((uint)buffer[i] & 0x3F) << 24;
break;
case 2:
parser.TimeCode |=
@ -517,7 +583,7 @@ namespace BDInfo
break;
case 0:
parser.TimeCode |=
(uint)buffer[i];
(uint)buffer[i] & 0xFF;
break;
}
}
@ -537,80 +603,81 @@ namespace BDInfo
switch (parser.HeaderParse)
{
case 2:
{
parser.TransportErrorIndicator =
(byte)((buffer[i] >> 7) & 0x1);
parser.PayloadUnitStartIndicator =
(byte)((buffer[i] >> 6) & 0x1);
parser.TransportPriority =
(byte)((buffer[i] >> 5) & 0x1);
parser.PID =
(ushort)((buffer[i] & 0x1f) << 8);
}
break;
{
parser.TransportErrorIndicator =
(byte)((buffer[i] >> 7) & 0x1);
parser.PayloadUnitStartIndicator =
(byte)((buffer[i] >> 6) & 0x1);
parser.TransportPriority =
(byte)((buffer[i] >> 5) & 0x1);
parser.PID =
(ushort)((buffer[i] & 0x1f) << 8);
}
break;
case 1:
{
parser.PID |= (ushort)buffer[i];
if (Streams.ContainsKey(parser.PID))
{
parser.Stream = Streams[parser.PID];
parser.PID |= buffer[i];
if (Streams.ContainsKey(parser.PID))
{
parser.Stream = Streams[parser.PID];
}
else
{
parser.Stream = null;
}
if (!StreamStates.ContainsKey(parser.PID))
{
StreamStates[parser.PID] = new TSStreamState();
}
parser.StreamState = StreamStates[parser.PID];
parser.StreamState.TotalPackets++;
parser.StreamState.WindowPackets++;
parser.TotalPackets++;
}
else
{
parser.Stream = null;
}
if (!StreamStates.ContainsKey(parser.PID))
{
StreamStates[parser.PID] = new TSStreamState();
}
parser.StreamState = StreamStates[parser.PID];
parser.StreamState.TotalPackets++;
parser.StreamState.WindowPackets++;
parser.TotalPackets++;
}
break;
break;
case 0:
{
parser.TransportScramblingControl =
(byte)((buffer[i] >> 6) & 0x3);
parser.AdaptionFieldControl =
(byte)((buffer[i] >> 4) & 0x3);
if ((parser.AdaptionFieldControl & 0x2) == 0x2)
{
parser.AdaptionFieldState = true;
}
if (parser.PayloadUnitStartIndicator == 1)
{
if (parser.PID == 0)
{
parser.PATSectionStart = true;
}
else if (parser.PID == parser.PMTPID)
{
parser.PMTSectionStart = true;
}
else if (parser.StreamState != null &&
parser.StreamState.TransferState)
{
parser.StreamState.TransferState = false;
parser.StreamState.TransferCount++;
parser.TransportScramblingControl =
(byte)((buffer[i] >> 6) & 0x3);
parser.AdaptionFieldControl =
(byte)((buffer[i] >> 4) & 0x3);
bool isFinished = ScanStream(
parser.Stream,
parser.StreamState,
parser.StreamState.StreamBuffer);
if (!isFullScan && isFinished)
if ((parser.AdaptionFieldControl & 0x2) == 0x2)
{
parser.AdaptionFieldState = true;
}
if (parser.PayloadUnitStartIndicator == 1)
{
if (parser.PID == 0)
{
return;
parser.PATSectionStart = true;
}
else if (parser.PID == parser.PMTPID)
{
parser.PMTSectionStart = true;
}
else if (parser.StreamState != null &&
parser.StreamState.TransferState)
{
parser.StreamState.TransferState = false;
parser.StreamState.TransferCount++;
bool isFinished = ScanStream(
parser.Stream,
parser.StreamState,
parser.StreamState.StreamBuffer,
isFullScan);
if (!isFullScan && isFinished)
{
return;
}
}
}
}
}
break;
break;
}
}
else if (parser.AdaptionFieldState)
@ -619,6 +686,7 @@ namespace BDInfo
parser.AdaptionFieldParse = buffer[i];
parser.AdaptionFieldLength = buffer[i];
parser.AdaptionFieldState = false;
parser.VariablePacketEnd = true;
}
else if (parser.AdaptionFieldParse > 0)
{
@ -644,7 +712,7 @@ namespace BDInfo
}
parser.PCRCount++;
}
if (parser.PacketLength == 0)
if (parser.PacketLength <= 0)
{
parser.SyncState = false;
}
@ -659,7 +727,7 @@ namespace BDInfo
}
else
{
offset = (bufferLength - i);
offset = bufferLength - i;
}
if (parser.PacketLength <= offset)
{
@ -671,7 +739,8 @@ namespace BDInfo
parser.PAT[parser.PATOffset++] = buffer[i++];
parser.PATSectionLength--;
parser.PacketLength--;
} --i;
}
--i;
if (parser.PATSectionLength == 0)
{
@ -770,7 +839,7 @@ namespace BDInfo
}
}
}
if (parser.PacketLength == 0)
if (parser.PacketLength <= 0)
{
parser.SyncState = false;
}
@ -785,7 +854,7 @@ namespace BDInfo
}
else
{
offset = (bufferLength - i);
offset = bufferLength - i;
}
if (parser.PacketLength <= offset)
{
@ -802,7 +871,8 @@ namespace BDInfo
PMT[parser.PMTOffset++] = buffer[i++];
--parser.PMTSectionLength;
--parser.PacketLength;
} --i;
}
--i;
if (parser.PMTSectionLength == 0)
{
@ -862,6 +932,8 @@ namespace BDInfo
}
*/
CreateStream(streamPID, streamType, streamDescriptors);
if (Streams[streamPID].IsGraphicsStream)
Streams[streamPID].IsInitialized = !isFullScan;
}
k += streamInfoLength;
}
@ -1016,7 +1088,7 @@ namespace BDInfo
}
}
}
if (parser.PacketLength == 0)
if (parser.PacketLength <= 0)
{
parser.SyncState = false;
}
@ -1034,13 +1106,18 @@ namespace BDInfo
if (streamState.TransferState)
{
if ((bufferLength - i) >= streamState.PacketLength &&
streamState.PacketLength > 0)
streamState.PacketLength > 0 && !streamState.PacketLengthVariable)
{
offset = streamState.PacketLength;
}
else if ((bufferLength - i) >= parser.PacketLength &&
parser.PacketLength > 0 && streamState.PacketLengthVariable)
{
offset = parser.PacketLength;
}
else
{
offset = (bufferLength - i);
offset = bufferLength - i;
}
if (parser.PacketLength <= offset)
{
@ -1049,7 +1126,8 @@ namespace BDInfo
streamState.TransferLength = offset;
if (!stream.IsInitialized ||
stream.IsVideoStream)
stream.IsVideoStream ||
stream.IsGraphicsStream)
{
streamState.StreamBuffer.Add(
buffer, i, offset);
@ -1059,13 +1137,19 @@ namespace BDInfo
streamState.StreamBuffer.TransferLength += offset;
}
i += (int)(streamState.TransferLength - 1);
i += streamState.TransferLength - 1;
streamState.PacketLength -= streamState.TransferLength;
parser.PacketLength -= (byte)streamState.TransferLength;
streamState.TotalBytes += (ulong)streamState.TransferLength;
streamState.WindowBytes += (ulong)streamState.TransferLength;
if (parser.VariablePacketEnd && streamState.PacketLengthVariable)
{
parser.VariablePacketEnd = false;
streamState.PacketLengthVariable = false;
}
if (streamState.PacketLength == 0)
{
streamState.TransferState = false;
@ -1073,7 +1157,8 @@ namespace BDInfo
bool isFinished = ScanStream(
stream,
streamState,
streamState.StreamBuffer);
streamState.StreamBuffer,
isFullScan);
if (!isFullScan && isFinished)
{
@ -1102,6 +1187,12 @@ namespace BDInfo
{
headerFound = true;
}
if (stream.IsAudioStream &&
streamState.Parse >= 0x000001C0 &&
streamState.Parse <= 0x000001DF)
{
headerFound = true;
}
if (stream.IsAudioStream &&
(streamState.Parse == 0x000001FA ||
streamState.Parse == 0x000001FD))
@ -1123,7 +1214,7 @@ namespace BDInfo
if (headerFound)
{
streamState.PacketLengthParse = 2;
#if DEBUG
#if DEBUG && !BETA
streamState.PESHeaderIndex = 0;
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)((streamState.Parse >> 24) & 0xFF);
@ -1141,7 +1232,7 @@ namespace BDInfo
switch (streamState.PacketLengthParse)
{
case 1:
#if DEBUG
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
@ -1150,8 +1241,15 @@ namespace BDInfo
case 0:
streamState.PacketLength =
(int)(streamState.Parse & 0xFFFF);
if (streamState.PacketLength == 0)
{
parser.VariablePacketEnd = false;
streamState.PacketLengthVariable = true;
}
streamState.PacketParse = 3;
#if DEBUG
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
@ -1166,7 +1264,7 @@ namespace BDInfo
switch (streamState.PacketParse)
{
case 2:
#if DEBUG
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
@ -1175,7 +1273,7 @@ namespace BDInfo
case 1:
streamState.PESHeaderFlags =
(byte)(streamState.Parse & 0xFF);
#if DEBUG
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
@ -1184,7 +1282,7 @@ namespace BDInfo
case 0:
streamState.PESHeaderLength =
(byte)(streamState.Parse & 0xFF);
#if DEBUG
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
@ -1213,58 +1311,59 @@ namespace BDInfo
{
case 4:
streamState.PTSTemp =
((streamState.Parse & 0xE) << 29);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xE) << 29;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
break;
case 3:
streamState.PTSTemp |=
((streamState.Parse & 0xFF) << 22);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFF) << 22;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
break;
case 2:
streamState.PTSTemp |=
((streamState.Parse & 0xFE) << 14);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFE) << 14;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
break;
case 1:
streamState.PTSTemp |=
((streamState.Parse & 0xFF) << 7);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFF) << 7;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
break;
case 0:
streamState.PTSTemp |=
((streamState.Parse & 0xFE) >> 1);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFE) >> 1;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
streamState.PTS = streamState.PTSTemp;
if (streamState.PTS > streamState.PTSLast)
if (streamState.PTS != streamState.PTSLast)
{
if (streamState.PTSLast > 0)
{
streamState.PTSTransfer = (streamState.PTS - streamState.PTSLast);
streamState.PTSTransfer = streamState.PTS - streamState.PTSLast;
}
streamState.PTSLast = streamState.PTS;
}
// TODO: Frame reorder for streams encoded with b-pyramid > 0
streamState.PTSDiff = streamState.PTS - streamState.DTSPrev;
if (streamState.PTSCount > 0 &&
@ -1301,45 +1400,45 @@ namespace BDInfo
{
case 9:
streamState.PTSTemp =
((streamState.Parse & 0xE) << 29);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xE) << 29;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
break;
case 8:
streamState.PTSTemp |=
((streamState.Parse & 0xFF) << 22);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFF) << 22;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
break;
case 7:
streamState.PTSTemp |=
((streamState.Parse & 0xFE) << 14);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFE) << 14;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
break;
case 6:
streamState.PTSTemp |=
((streamState.Parse & 0xFF) << 7);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFF) << 7;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
break;
case 5:
streamState.PTSTemp |=
((streamState.Parse & 0xFE) >> 1);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFE) >> 1;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
streamState.PTS = streamState.PTSTemp;
@ -1351,47 +1450,49 @@ namespace BDInfo
case 4:
streamState.DTSTemp =
((streamState.Parse & 0xE) << 29);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xE) << 29;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
break;
case 3:
streamState.DTSTemp |=
((streamState.Parse & 0xFF) << 22);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFF) << 22;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
break;
case 2:
streamState.DTSTemp |=
((streamState.Parse & 0xFE) << 14);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFE) << 14;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
break;
case 1:
streamState.DTSTemp |=
((streamState.Parse & 0xFF) << 7);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFF) << 7;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
break;
case 0:
streamState.DTSTemp |=
((streamState.Parse & 0xFE) >> 1);
#if DEBUG
streamState.PESHeader[streamState.PESHeaderIndex++] =
(streamState.Parse & 0xFE) >> 1;
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xff);
#endif
// TODO: Frame reorder for streams encoded with b-pyramid > 0
streamState.PTSDiff = streamState.DTSTemp - streamState.DTSPrev;
if (streamState.PTSCount > 0 &&
@ -1421,7 +1522,7 @@ namespace BDInfo
{
--streamState.PacketLength;
--streamState.PESHeaderLength;
#if DEBUG
#if DEBUG && !BETA
streamState.PESHeader[streamState.PESHeaderIndex++] =
(byte)(streamState.Parse & 0xFF);
#endif
@ -1431,7 +1532,7 @@ namespace BDInfo
}
}
}
if (parser.PacketLength == 0)
if (parser.PacketLength <= 0)
{
parser.SyncState = false;
}
@ -1446,10 +1547,10 @@ namespace BDInfo
}
else
{
parser.PacketLength -= (byte)((bufferLength - i) + 1);
parser.PacketLength -= (byte)(bufferLength - i + 1);
i = bufferLength;
}
if (parser.PacketLength == 0)
if (parser.PacketLength <= 0)
{
parser.SyncState = false;
}
@ -1458,8 +1559,9 @@ namespace BDInfo
Size += bufferLength;
}
ulong PTSLast = 0;
ulong PTSDiff = 0;
// TODO: Frame reorder for streams encoded with b-pyramid > 0
BigInteger PTSLast = 0;
BigInteger PTSDiff = 0;
foreach (TSStream stream in Streams.Values)
{
if (!stream.IsVideoStream) continue;
@ -1475,10 +1577,11 @@ namespace BDInfo
}
finally
{
if (fileStream != null)
{
fileStream.Close();
}
#if DEBUG && !BETA
logTextWriter?.Close();
logFile?.Close();
#endif
fileStream?.Close();
}
}
@ -1497,10 +1600,10 @@ namespace BDInfo
case TSStreamType.MPEG1_VIDEO:
case TSStreamType.MPEG2_VIDEO:
case TSStreamType.VC1_VIDEO:
{
stream = new TSVideoStream();
}
break;
{
stream = new TSVideoStream();
}
break;
case TSStreamType.AC3_AUDIO:
case TSStreamType.AC3_PLUS_AUDIO:
@ -1513,23 +1616,25 @@ namespace BDInfo
case TSStreamType.LPCM_AUDIO:
case TSStreamType.MPEG1_AUDIO:
case TSStreamType.MPEG2_AUDIO:
{
stream = new TSAudioStream();
}
break;
case TSStreamType.MPEG2_AAC_AUDIO:
case TSStreamType.MPEG4_AAC_AUDIO:
{
stream = new TSAudioStream();
}
break;
case TSStreamType.INTERACTIVE_GRAPHICS:
case TSStreamType.PRESENTATION_GRAPHICS:
{
stream = new TSGraphicsStream();
}
break;
{
stream = new TSGraphicsStream();
}
break;
case TSStreamType.SUBTITLE:
{
stream = new TSTextStream();
}
break;
{
stream = new TSTextStream();
}
break;
default:
break;