mirror of
https://github.com/jellyfin/BDInfo.git
synced 2024-11-23 06:09:48 +00:00
Merge pull request #7 from Shadowghost/upstream-merge
Merge upstream changes
This commit is contained in:
commit
40d2c5be76
@ -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>
|
||||
|
@ -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
121
src/BDInfo/TSCodecAAC.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
157
src/BDInfo/TSCodecMPA.cs
Normal 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
123
src/BDInfo/TSCodecPGS.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user