Use language info from ts files

This commit is contained in:
Nikolaj Olsson 2019-10-10 13:38:58 +02:00
parent 56b3f59f87
commit 06bf912e29
14 changed files with 719 additions and 57 deletions

View File

@ -221,9 +221,7 @@ namespace Nikse.SubtitleEdit.Core
{
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var tsp = new TransportStreamParser();
tsp.DetectFormat(fs);
return tsp.IsM2TransportStream;
return TransportStreamParser.IsM3TransportStream(fs);
}
}
@ -540,7 +538,7 @@ namespace Nikse.SubtitleEdit.Core
return info;
}
public static string GetTempFileName (string extension)
public static string GetTempFileName(string extension)
{
return Path.GetTempPath() + Guid.NewGuid() + extension;
}

257
libse/IsoCountryCodes.cs Normal file
View File

@ -0,0 +1,257 @@
using System.Collections.Generic;
namespace Nikse.SubtitleEdit.Core
{
public class IsoCountryCodes
{
public static Dictionary<string, string> ThreeToTweLetterLookup = new Dictionary<string, string>
{
{ "AFG", "AF" },
{ "ALA", "AX" },
{ "ALB", "AL" },
{ "DZA", "DZ" },
{ "ASM", "AS" },
{ "AND", "AD" },
{ "AGO", "AO" },
{ "AIA", "AI" },
{ "ATG", "AG" },
{ "ARG", "AR" },
{ "ARM", "AM" },
{ "ABW", "AW" },
{ "AUS", "AU" },
{ "AUT", "AT" },
{ "AZE", "AZ" },
{ "BHS", "BS" },
{ "BHR", "BH" },
{ "BGD", "BD" },
{ "BRB", "BB" },
{ "BLR", "BY" },
{ "BEL", "BE" },
{ "BLZ", "BZ" },
{ "BEN", "BJ" },
{ "BMU", "BM" },
{ "BTN", "BT" },
{ "BOL", "BO" },
{ "BIH", "BA" },
{ "BWA", "BW" },
{ "BVT", "BV" },
{ "BRA", "BR" },
{ "VGB", "VG" },
{ "IOT", "IO" },
{ "BRN", "BN" },
{ "BGR", "BG" },
{ "BFA", "BF" },
{ "BDI", "BI" },
{ "KHM", "KH" },
{ "CMR", "CM" },
{ "CAN", "CA" },
{ "CPV", "CV" },
{ "CYM", "KY" },
{ "CAF", "CF" },
{ "TCD", "TD" },
{ "CHL", "CL" },
{ "CHN", "CN" },
{ "HKG", "HK" },
{ "MAC", "MO" },
{ "CXR", "CX" },
{ "CCK", "CC" },
{ "COL", "CO" },
{ "COM", "KM" },
{ "COG", "CG" },
{ "COD", "CD" },
{ "COK", "CK" },
{ "CRI", "CR" },
{ "CIV", "CI" },
{ "HRV", "HR" },
{ "CUB", "CU" },
{ "CYP", "CY" },
{ "CZE", "CZ" },
{ "DAN", "DK" },
{ "DJI", "DJ" },
{ "DMA", "DM" },
{ "DOM", "DO" },
{ "ECU", "EC" },
{ "EGY", "EG" },
{ "SLV", "SV" },
{ "GNQ", "GQ" },
{ "ERI", "ER" },
{ "EST", "EE" },
{ "ETH", "ET" },
{ "FLK", "FK" },
{ "FRO", "FO" },
{ "FJI", "FJ" },
{ "FIN", "FI" },
{ "FRA", "FR" },
{ "GUF", "GF" },
{ "PYF", "PF" },
{ "ATF", "TF" },
{ "GAB", "GA" },
{ "GMB", "GM" },
{ "GEO", "GE" },
{ "DEU", "DE" },
{ "GHA", "GH" },
{ "GIB", "GI" },
{ "GRC", "GR" },
{ "GRL", "GL" },
{ "GRD", "GD" },
{ "GLP", "GP" },
{ "GUM", "GU" },
{ "GTM", "GT" },
{ "GGY", "GG" },
{ "GIN", "GN" },
{ "GNB", "GW" },
{ "GUY", "GY" },
{ "HTI", "HT" },
{ "HMD", "HM" },
{ "VAT", "VA" },
{ "HND", "HN" },
{ "HUN", "HU" },
{ "ISL", "IS" },
{ "IND", "IN" },
{ "IDN", "ID" },
{ "IRN", "IR" },
{ "IRQ", "IQ" },
{ "IRL", "IE" },
{ "IMN", "IM" },
{ "ISR", "IL" },
{ "ITA", "IT" },
{ "JAM", "JM" },
{ "JPN", "JP" },
{ "JEY", "JE" },
{ "JOR", "JO" },
{ "KAZ", "KZ" },
{ "KEN", "KE" },
{ "KIR", "KI" },
{ "PRK", "KP" },
{ "KOR", "KR" },
{ "KWT", "KW" },
{ "KGZ", "KG" },
{ "LAO", "LA" },
{ "LVA", "LV" },
{ "LBN", "LB" },
{ "LSO", "LS" },
{ "LBR", "LR" },
{ "LBY", "LY" },
{ "LIE", "LI" },
{ "LTU", "LT" },
{ "LUX", "LU" },
{ "MKD", "MK" },
{ "MDG", "MG" },
{ "MWI", "MW" },
{ "MYS", "MY" },
{ "MDV", "MV" },
{ "MLI", "ML" },
{ "MLT", "MT" },
{ "MHL", "MH" },
{ "MTQ", "MQ" },
{ "MRT", "MR" },
{ "MUS", "MU" },
{ "MYT", "YT" },
{ "MEX", "MX" },
{ "FSM", "FM" },
{ "MDA", "MD" },
{ "MCO", "MC" },
{ "MNG", "MN" },
{ "MNE", "ME" },
{ "MSR", "MS" },
{ "MAR", "MA" },
{ "MOZ", "MZ" },
{ "MMR", "MM" },
{ "NAM", "NA" },
{ "NRU", "NR" },
{ "NPL", "NP" },
{ "NLD", "NL" },
{ "ANT", "AN" },
{ "NCL", "NC" },
{ "NZL", "NZ" },
{ "NIC", "NI" },
{ "NER", "NE" },
{ "NGA", "NG" },
{ "NIU", "NU" },
{ "NFK", "NF" },
{ "MNP", "MP" },
{ "NOR", "NO" },
{ "OMN", "OM" },
{ "PAK", "PK" },
{ "PLW", "PW" },
{ "PSE", "PS" },
{ "PAN", "PA" },
{ "PNG", "PG" },
{ "PRY", "PY" },
{ "PER", "PE" },
{ "PHL", "PH" },
{ "PCN", "PN" },
{ "POL", "PL" },
{ "PRT", "PT" },
{ "PRI", "PR" },
{ "QAT", "QA" },
{ "REU", "RE" },
{ "ROU", "RO" },
{ "RUS", "RU" },
{ "RWA", "RW" },
{ "BLM", "BL" },
{ "SHN", "SH" },
{ "KNA", "KN" },
{ "LCA", "LC" },
{ "MAF", "MF" },
{ "SPM", "PM" },
{ "VCT", "VC" },
{ "WSM", "WS" },
{ "SMR", "SM" },
{ "STP", "ST" },
{ "SAU", "SA" },
{ "SEN", "SN" },
{ "SRB", "RS" },
{ "SYC", "SC" },
{ "SLE", "SL" },
{ "SGP", "SG" },
{ "SVK", "SK" },
{ "SVN", "SI" },
{ "SLB", "SB" },
{ "SOM", "SO" },
{ "ZAF", "ZA" },
{ "SGS", "GS" },
{ "SSD", "SS" },
{ "ESP", "ES" },
{ "LKA", "LK" },
{ "SDN", "SD" },
{ "SUR", "SR" },
{ "SJM", "SJ" },
{ "SWZ", "SZ" },
{ "SWE", "SE" },
{ "CHE", "CH" },
{ "SYR", "SY" },
{ "TWN", "TW" },
{ "TJK", "TJ" },
{ "TZA", "TZ" },
{ "THA", "TH" },
{ "TLS", "TL" },
{ "TGO", "TG" },
{ "TKL", "TK" },
{ "TON", "TO" },
{ "TTO", "TT" },
{ "TUN", "TN" },
{ "TUR", "TR" },
{ "TKM", "TM" },
{ "TCA", "TC" },
{ "TUV", "TV" },
{ "UGA", "UG" },
{ "UKR", "UA" },
{ "ARE", "AE" },
{ "GBR", "GB" },
{ "USA", "US" },
{ "UMI", "UM" },
{ "URY", "UY" },
{ "UZB", "UZ" },
{ "VUT", "VU" },
{ "VEN", "VE" },
{ "VNM", "VN" },
{ "VIR", "VI" },
{ "WLF", "WF" },
{ "ESH", "EH" },
{ "YEM", "YE" },
{ "ZMB", "ZM" },
{ "ZWE", "ZW" },
};
}
}

View File

@ -197,6 +197,7 @@
<Compile Include="IfoParser.cs" />
<Compile Include="ImageSplitterItem.cs" />
<Compile Include="Interfaces\IRtfTextConverter.cs" />
<Compile Include="IsoCountryCodes.cs" />
<Compile Include="PlainTextImporter.cs" />
<Compile Include="Position.cs" />
<Compile Include="SeJsonValidator.cs" />
@ -593,6 +594,10 @@
<Compile Include="TransportStream\PageCompositionSegemnt.cs" />
<Compile Include="TransportStream\PageCompositionSegmentRegion.cs" />
<Compile Include="TransportStream\ProgramAssociationTable.cs" />
<Compile Include="TransportStream\ProgramMapTable.cs" />
<Compile Include="TransportStream\ProgramMapTableDescriptor.cs" />
<Compile Include="TransportStream\ProgramMapTableParser.cs" />
<Compile Include="TransportStream\ProgramMapTableStream.cs" />
<Compile Include="TransportStream\RegionClutSegmentEntry.cs" />
<Compile Include="TransportStream\RegionCompositionSegment.cs" />
<Compile Include="TransportStream\RegionCompositionSegmentObject.cs" />

View File

@ -143,7 +143,7 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
if (PacketId == ProgramAssociationTablePacketId) // PAT = Program Association Table: lists all programs available in the transport stream.
{
ProgramAssociationTable = new ProgramAssociationTable(packetBuffer, payloadStart + 1); // TODO: What index?
ProgramAssociationTable = new ProgramAssociationTable(packetBuffer, payloadStart);
}
// Save payload

View File

@ -16,6 +16,15 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
public ProgramAssociationTable(byte[] packetBuffer, int index)
{
var pointer = packetBuffer[index];
if (pointer > 0)
{
index += pointer;
}
else
{
index++;
}
TableId = packetBuffer[index];
SectionLength = (packetBuffer[index + 1] & Helper.B00000011) * 256 + packetBuffer[index + 2];
TransportStreamId = packetBuffer[index + 3] * 256 + packetBuffer[index + 4];
@ -23,7 +32,6 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
CurrentNextIndicator = packetBuffer[index + 5] & 1;
SectionNumber = packetBuffer[index + 6];
LastSectionNumber = packetBuffer[index + 7];
ProgramNumbers = new List<int>();
ProgramIds = new List<int>();
index = index + 8;

View File

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Linq;
namespace Nikse.SubtitleEdit.Core.TransportStream
{
public class ProgramMapTable
{
public int TableId { get; set; }
public int SectionLength { get; set; }
public int ProgramNumber { get; set; }
public int VersionNumber { get; set; }
public int CurrentNextIndicator { get; set; }
public int SectionNumber { get; set; }
public int LastSectionNumber { get; set; }
public int PcrId { get; set; }
public List<ProgramMapTableDescriptor> Descriptors { get; set; }
public List<ProgramMapTableStream> Streams { get; set; }
public ProgramMapTable(byte[] packetBuffer, int index)
{
var pointer = packetBuffer[index];
if (pointer > 0)
{
index += pointer;
}
else
{
index++;
}
TableId = packetBuffer[index];
SectionLength = (packetBuffer[index + 1] & Helper.B00000011) * 256 + packetBuffer[index + 2];
ProgramNumber = packetBuffer[index + 3] * 256 + packetBuffer[index + 4];
VersionNumber = (packetBuffer[index + 5] & Helper.B00111110) >> 1;
CurrentNextIndicator = packetBuffer[index + 5] & 1;
SectionNumber = packetBuffer[index + 6];
LastSectionNumber = packetBuffer[index + 7];
PcrId = (packetBuffer[index + 8] & Helper.B00011111) * 256 + packetBuffer[index + 9];
var programInfoLength = (packetBuffer[index + 10] & Helper.B00001111) * 256 + packetBuffer[index + 11];
Descriptors = ProgramMapTableDescriptor.ReadDescriptors(packetBuffer, programInfoLength, index + 12);
var newIndex = index + 12 + Descriptors.Sum(p => p.Size);
Streams = new List<ProgramMapTableStream>();
while (newIndex - index < SectionLength - 4)
{
var stream = new ProgramMapTableStream(packetBuffer, newIndex);
Streams.Add(stream);
newIndex += stream.Size;
}
}
}
}

View File

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Nikse.SubtitleEdit.Core.TransportStream
{
public class ProgramMapTableDescriptor
{
public const int TagCaDescriptor = 9;
public int Tag { get; set; }
public byte[] CaSystemId { get; set; } = new byte[2];
public uint CaPid { get; set; }
public byte[] PrivateDataBytes { get; set; }
public byte[] Content { get; set; }
public string ContentAsString { get; set; }
public ProgramMapTableDescriptor(byte[] data, int index)
{
Tag = data[index];
var length = data[index + 1];
if (Tag == TagCaDescriptor)
{
Buffer.BlockCopy(data, index + 2, CaSystemId, 0, 2);
// 13 bytes (skip first 3)
CaPid = (uint)((data[index + 4] & Helper.B00011111) * 256 + // first 5 bytes
data[index + 5]); // last 8 bytes
PrivateDataBytes = new byte[length - 4];
Buffer.BlockCopy(data, index + 6, PrivateDataBytes, 0, length - 4);
}
else
{
Content = new byte[length];
if (index + 2 + length < data.Length && length > 0)
{
Buffer.BlockCopy(data, index + 2, Content, 0, length);
ContentAsString = Encoding.UTF8.GetString(Content);
}
}
}
public int Length
{
get
{
if (Tag == TagCaDescriptor)
{
return PrivateDataBytes.Length + 4;
}
return Content.Length;
}
}
public int Size => Length + 2;
public static List<ProgramMapTableDescriptor> ReadDescriptors(byte[] data, int size, int index)
{
var total = 0;
var descriptors = new List<ProgramMapTableDescriptor>();
while (total < size)
{
var descriptor = new ProgramMapTableDescriptor(data, total + index);
descriptors.Add(descriptor);
total += descriptor.Size;
if (total != size)
{
break; // Excepted {size} bytes of descriptors, but got {total} bytes of descriptors.
}
}
return descriptors;
}
}
}

View File

@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Nikse.SubtitleEdit.Core.TransportStream
{
public class ProgramMapTableParser
{
private List<ProgramMapTable> _programMapTables;
public Exception Exception { get; set; }
public ProgramMapTableParser()
{
_programMapTables = new List<ProgramMapTable>();
}
public void Parse(string fileName)
{
try
{
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
Parse(fs);
}
}
catch (Exception e)
{
Exception = e;
}
}
private const int MaxScanSize = 5000000;
/// <summary>
/// Get Program Map Tables for a Transport Stream
/// </summary>
/// <param name="ms">Input stream</param>
public void Parse(Stream ms)
{
try
{
ms.Position = 0;
const int packetLength = 188;
var isM2TransportStream = TransportStreamParser.IsM3TransportStream(ms);
var packetBuffer = new byte[packetLength];
var m2TsTimeCodeBuffer = new byte[4];
long position = 0;
// check for Topfield .rec file
ms.Seek(position, SeekOrigin.Begin);
ms.Read(m2TsTimeCodeBuffer, 0, 3);
if (m2TsTimeCodeBuffer[0] == 0x54 && m2TsTimeCodeBuffer[1] == 0x46 && m2TsTimeCodeBuffer[2] == 0x72)
{
position = 3760;
}
var pmtPids = new List<int>();
_programMapTables = new List<ProgramMapTable>();
long transportStreamLength = ms.Length;
var max = Math.Min(transportStreamLength, MaxScanSize + position);
while (position < max)
{
ms.Seek(position, SeekOrigin.Begin);
if (isM2TransportStream)
{
ms.Read(m2TsTimeCodeBuffer, 0, m2TsTimeCodeBuffer.Length);
position += m2TsTimeCodeBuffer.Length;
}
ms.Read(packetBuffer, 0, packetLength);
byte syncByte = packetBuffer[0];
if (syncByte == Packet.SynchronizationByte)
{
var packet = new Packet(packetBuffer);
if (pmtPids.Contains(packet.PacketId))
{
var pmt = new ProgramMapTable(packet.Payload, 0);
_programMapTables.Add(pmt);
}
else if (packet.IsProgramAssociationTable)
{
var pat = new ProgramAssociationTable(packet.Payload, 0);
pmtPids.AddRange(pat.ProgramIds.Where(p => !pmtPids.Contains(p)));
}
position += packetLength;
}
else
{
position++;
}
}
}
catch (Exception e)
{
Exception = e;
}
}
public List<int> GetSubtitlePacketIds()
{
var list = new List<int>();
foreach (var programMapTable in _programMapTables)
{
foreach (var stream in programMapTable.Streams)
{
if (stream.StreamType == ProgramMapTableStream.StreamTypePrivateData && !list.Contains(stream.ElementaryPid))
{
list.Add(stream.ElementaryPid);
}
}
}
return list;
}
public string GetSubtitleLanguage(int packetId)
{
foreach (var programMapTable in _programMapTables)
{
foreach (var stream in programMapTable.Streams)
{
if (stream.ElementaryPid == packetId)
{
return stream.GetLanguage();
}
}
}
return string.Empty;
}
public string GetSubtitleLanguageTwoLetter(int packetId)
{
var language = GetSubtitleLanguage(packetId);
var uppercaseLanguage = language.ToUpperInvariant();
if (IsoCountryCodes.ThreeToTweLetterLookup.ContainsKey(uppercaseLanguage))
{
return IsoCountryCodes.ThreeToTweLetterLookup[uppercaseLanguage].ToLowerInvariant();
}
return language;
}
}
}

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Nikse.SubtitleEdit.Core.TransportStream
{
public class ProgramMapTableStream
{
public const int StreamTypePrivateData = 6;
public List<ProgramMapTableDescriptor> Descriptors;
public int StreamType { get; set; }
public int ElementaryPid { get; set; }
public int Size { get; set; }
public ProgramMapTableStream(byte[] data, int index)
{
StreamType = data[index];
// 13 bytes (skip first 3)
ElementaryPid = (data[index + 1] & Helper.B00011111) * 256 + // first 5 bytes
data[index + 2]; // last 8 bytes
var esInfoLength = (data[index + 3] & Helper.B00001111) * 256 + // first 5 bytes
data[index + 4]; // last 8 bytes
Descriptors = ProgramMapTableDescriptor.ReadDescriptors(data, esInfoLength, index + 5);
Size = 5 + Descriptors.Sum(p => p.Size);
}
public string GetStreamTypeString()
{
switch (StreamType)
{
case 0x00:
return "ITU-T | ISO/IEC Reserved";
case 0x01:
return "ISO/IEC 11172 Video";
case 0x02:
return
"ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or ISO/IEC 11172-2 constrained parameter video stream";
case 0x03:
return "ISO/IEC 11172 Audio";
case 0x04:
return "ISO/IEC 13818-3 Audio";
case 0x05:
return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections";
case 0x06:
return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing private data";
case 0x07:
return "ISO/IEC 13522 MHEG";
case 0x08:
return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A DSM-CC";
case 0x09:
return "ITU-T Rec. H.222.1";
case 0x0A:
return "ISO/IEC 13818-6 type A";
case 0x0B:
return "ISO/IEC 13818-6 type B";
case 0x0C:
return "ISO/IEC 13818-6 type C";
case 0x0D:
return "ISO/IEC 13818-6 type D";
case 0x0E:
return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 auxiliary";
case 0x0F:
return "ISO/IEC 13818-7 Audio with ADTS transport syntax";
case 0x10:
return "ISO/IEC 14496-2 Visual";
case 0x11:
return "ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3 / AMD 1";
case 0x12:
return "ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets";
case 0x13:
return "ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC14496_sections";
case 0x14:
return "ISO/IEC 13818-6 Synchronized Download Protocol";
case int n when (n < 0x15 && n >= 0x7F):
return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved";
default:
return "User Private";
}
}
internal string GetLanguage()
{
foreach (var descriptor in Descriptors)
{
if (descriptor.Tag != ProgramMapTableDescriptor.TagCaDescriptor)
{
var sb = new StringBuilder();
foreach (var b in descriptor.Content)
{
if (b >= 32)
{
sb.Append(Convert.ToChar(b));
}
else
{
break;
}
}
return sb.ToString();
}
}
return string.Empty;
}
}
}

View File

@ -20,10 +20,7 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
public long TotalNumberOfPrivateStream1Continuation0 { get; private set; }
public List<int> SubtitlePacketIds { get; private set; }
public List<Packet> SubtitlePackets { get; private set; }
// public List<Packet> ProgramAssociationTables { get; private set; }
private Dictionary<int, List<DvbSubPes>> SubtitlesLookup { get; set; }
private Dictionary<int, List<TransportStreamSubtitle>> DvbSubtitlesLookup { get; set; }
public bool IsM2TransportStream { get; private set; }
public ulong FirstVideoPts { get; private set; }
@ -51,10 +48,9 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
TotalNumberOfPrivateStream1Continuation0 = 0;
SubtitlePacketIds = new List<int>();
SubtitlePackets = new List<Packet>();
// ProgramAssociationTables = new List<Packet>();
ms.Position = 0;
const int packetLength = 188;
DetectFormat(ms);
IsM2TransportStream = IsM3TransportStream(ms);
var packetBuffer = new byte[packetLength];
var m2TsTimeCodeBuffer = new byte[4];
long position = 0;
@ -76,7 +72,6 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
if (IsM2TransportStream)
{
ms.Read(m2TsTimeCodeBuffer, 0, m2TsTimeCodeBuffer.Length);
//var tc = (m2tsTimeCodeBuffer[0]<< 24) | (m2tsTimeCodeBuffer[1] << 16) | (m2tsTimeCodeBuffer[2] << 8) | (m2tsTimeCodeBuffer[3]);
position += m2TsTimeCodeBuffer.Length;
}
@ -109,38 +104,7 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
}
else if (packet.IsProgramAssociationTable)
{
//var sb = new StringBuilder();
//sb.AppendLine("PacketNo: " + TotalNumberOfPackets + 1);
//sb.AppendLine("PacketId: " + packet.PacketId);
//sb.AppendLine();
//sb.AppendLine("TransportErrorIndicator: " + packet.TransportErrorIndicator);
//sb.AppendLine("PayloadUnitStartIndicator: " + packet.PayloadUnitStartIndicator);
//sb.AppendLine("TransportPriority: " + packet.TransportPriority);
//sb.AppendLine("ScramblingControl: " + packet.ScramblingControl);
//sb.AppendLine("AdaptationFieldExist: " + packet.AdaptationFieldControl);
//sb.AppendLine("ContinuityCounter: " + packet.ContinuityCounter);
//sb.AppendLine();
//if (packet.AdaptationField != null)
//{
//sb.AppendLine("AdaptationFieldLength: " + packet.AdaptationField.Length);
//sb.AppendLine("DiscontinuityIndicator: " + packet.AdaptationField.DiscontinuityIndicator);
//sb.AppendLine("RandomAccessIndicator: " + packet.AdaptationField.RandomAccessIndicator);
//sb.AppendLine("ElementaryStreamPriorityIndicator: " + packet.AdaptationField.ElementaryStreamPriorityIndicator);
//sb.AppendLine("PcrFlag: " + packet.AdaptationField.PcrFlag);
//sb.AppendLine("OpcrFlag: " + packet.AdaptationField.OpcrFlag);
//sb.AppendLine("SplicingPointFlag: " + packet.AdaptationField.SplicingPointFlag);
//sb.AppendLine("TransportPrivateDataFlag: " + packet.AdaptationField.TransportPrivateDataFlag);
//sb.AppendLine("AdaptationFieldExtensionFlag: " + packet.AdaptationField.AdaptationFieldExtensionFlag);
//sb.AppendLine();
//}
//sb.AppendLine("TableId: " + packet.ProgramAssociationTable.TableId);
//sb.AppendLine("SectionLength: " + packet.ProgramAssociationTable.SectionLength);
//sb.AppendLine("TransportStreamId: " + packet.ProgramAssociationTable.TransportStreamId);
//sb.AppendLine("VersionNumber: " + packet.ProgramAssociationTable.VersionNumber);
//sb.AppendLine("CurrentNextIndicator: " + packet.ProgramAssociationTable.CurrentNextIndicator);
//sb.AppendLine("SectionNumber: " + packet.ProgramAssociationTable.SectionNumber);
//sb.AppendLine("LastSectionNumber: " + packet.ProgramAssociationTable.LastSectionNumber);
//ProgramAssociationTables.Add(packet);
}
else if (packet.IsPrivateStream1 || SubtitlePacketIds.Contains(packet.PacketId))
{
@ -434,7 +398,7 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
list.Add(pes);
}
internal void DetectFormat(Stream ms)
public static bool IsM3TransportStream(Stream ms)
{
if (ms.Length > 192 + 192 + 5)
{
@ -443,14 +407,15 @@ namespace Nikse.SubtitleEdit.Core.TransportStream
ms.Read(buffer, 0, buffer.Length);
if (buffer[0] == Packet.SynchronizationByte && buffer[188] == Packet.SynchronizationByte)
{
return;
return false;
}
if (buffer[4] == Packet.SynchronizationByte && buffer[192 + 4] == Packet.SynchronizationByte && buffer[192 + 192 + 4] == Packet.SynchronizationByte)
{
IsM2TransportStream = true;
return true;
}
}
return false;
}
public static bool IsDvbSup(string fileName)

View File

@ -12044,8 +12044,16 @@ namespace Nikse.SubtitleEdit.Forms
{
using (var formSubOcr = new VobSubOcr())
{
string language = null;
var programMapTableParser = new ProgramMapTableParser();
programMapTableParser.Parse(fileName); // get languages
if (programMapTableParser.GetSubtitlePacketIds().Count > 0)
{
language = programMapTableParser.GetSubtitleLanguageTwoLetter(programMapTableParser.GetSubtitlePacketIds().First());
}
var subtitles = TransportStreamParser.GetDvbSup(fileName);
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, fileName);
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, fileName, language);
if (formSubOcr.ShowDialog(this) == DialogResult.OK)
{
MakeHistoryForUndo(_language.BeforeImportingDvdSubtitle);
@ -12107,7 +12115,15 @@ namespace Nikse.SubtitleEdit.Forms
using (var formSubOcr = new VobSubOcr())
{
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, fileName);
string language = null;
var programMapTableParser = new ProgramMapTableParser();
programMapTableParser.Parse(fileName); // get languages
if (programMapTableParser.GetSubtitlePacketIds().Count > 0)
{
language = programMapTableParser.GetSubtitleLanguage(packedId);
}
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, fileName, language);
if (formSubOcr.ShowDialog(this) == DialogResult.OK)
{
MakeHistoryForUndo(_language.BeforeImportingDvdSubtitle);

View File

@ -8740,8 +8740,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
}
}
// TODO: Get language from ts file
internal void Initialize(List<TransportStreamSubtitle> subtitles, VobSubOcrSettings vobSubOcrSettings, string fileName)
internal void Initialize(List<TransportStreamSubtitle> subtitles, VobSubOcrSettings vobSubOcrSettings, string fileName, string language)
{
buttonOK.Enabled = false;
buttonCancel.Enabled = false;
@ -8757,7 +8756,8 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
numericUpDownNumberOfPixelsIsSpaceNOCR.Value = vobSubOcrSettings.XOrMorePixelsMakesSpace;
_vobSubOcrSettings = vobSubOcrSettings;
InitializeTesseract();
InitializeTesseract(language);
SetTesseractLanguageFromLanguageString(language);
LoadImageCompareCharacterDatabaseList();
SetOcrMethod();

View File

@ -13,6 +13,7 @@ namespace Nikse.SubtitleEdit.Forms
{
private TransportStreamParser _tsParser;
private string _fileName;
private ProgramMapTableParser _programMapTableParser;
public TransportStreamSubtitleChooser()
{
@ -50,13 +51,23 @@ namespace Nikse.SubtitleEdit.Forms
internal void Initialize(TransportStreamParser tsParser, string fileName)
{
_programMapTableParser = new ProgramMapTableParser();
_programMapTableParser.Parse(fileName); // get languages
_tsParser = tsParser;
_fileName = fileName;
Text = string.Format(Configuration.Settings.Language.TransportStreamSubtitleChooser.Title, fileName);
foreach (int id in tsParser.SubtitlePacketIds)
{
listBoxTracks.Items.Add(string.Format(Configuration.Settings.Language.TransportStreamSubtitleChooser.PidLine, id, tsParser.GetDvbSubtitles(id).Count));
var language = _programMapTableParser.GetSubtitleLanguage(id);
if (!string.IsNullOrEmpty(language))
{
listBoxTracks.Items.Add(string.Format(Configuration.Settings.Language.TransportStreamSubtitleChooser.PidLine, id + "=" + language, tsParser.GetDvbSubtitles(id).Count));
}
else
{
listBoxTracks.Items.Add(string.Format(Configuration.Settings.Language.TransportStreamSubtitleChooser.PidLine, id, tsParser.GetDvbSubtitles(id).Count));
}
}
listBoxTracks.SelectedIndex = 0;
}
@ -121,6 +132,18 @@ namespace Nikse.SubtitleEdit.Forms
return _tsParser.GetDvbSubtitles(pid);
}
private string GetSelectedLanguage()
{
int idx = listBoxSubtitles.SelectedIndex;
if (idx < 0)
{
return null;
}
int pid = _tsParser.SubtitlePacketIds[listBoxTracks.SelectedIndex];
return _programMapTableParser.GetSubtitleLanguage(pid);
}
private void BluraySupToolStripMenuItem_Click(object sender, EventArgs e)
{
ExportTo(ExportPngXml.ExportFormats.BluraySup);
@ -151,10 +174,10 @@ namespace Nikse.SubtitleEdit.Forms
using (var formSubOcr = new VobSubOcr())
{
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, _fileName);
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, _fileName, GetSelectedLanguage());
using (var exportBdnXmlPng = new ExportPngXml())
{
exportBdnXmlPng.InitializeFromVobSubOcr(formSubOcr.SubtitleFromOcr, new SubRip(), exportType, _fileName, formSubOcr, null);
exportBdnXmlPng.InitializeFromVobSubOcr(formSubOcr.SubtitleFromOcr, new SubRip(), exportType, _fileName, formSubOcr, GetSelectedLanguage());
exportBdnXmlPng.ShowDialog(this);
}
}
@ -171,7 +194,7 @@ namespace Nikse.SubtitleEdit.Forms
using (var formSubOcr = new VobSubOcr())
{
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, _fileName);
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, _fileName, GetSelectedLanguage());
formSubOcr.SaveAllImagesWithHtmlIndexViewToolStripMenuItem_Click(sender, e);
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using Nikse.SubtitleEdit.Core;
using Nikse.SubtitleEdit.Core.SubtitleFormats;
@ -12,6 +13,8 @@ namespace Nikse.SubtitleEdit.Logic.CommandLineConvert
{
public static bool ConvertFromTsToBluRaySup(string fileName, string outputFolder, bool overwrite, StreamWriter stdOutWriter, CommandLineConverter.BatchConvertProgress progressCallback)
{
var programMapTableParser = new ProgramMapTableParser();
programMapTableParser.Parse(fileName); // get languages
var tsParser = new TransportStreamParser();
tsParser.Parse(fileName, (position, total) =>
{
@ -50,7 +53,12 @@ namespace Nikse.SubtitleEdit.Logic.CommandLineConvert
form.Initialize(new Subtitle(), new SubRip(), BatchConvert.BluRaySubtitle, fileName, videoInfo, fileName);
foreach (int pid in tsParser.SubtitlePacketIds)
{
var outputFileName = CommandLineConverter.FormatOutputFileNameForBatchConvert(Utilities.GetPathAndFileNameWithoutExtension(fileName) + "-" + pid + Path.GetExtension(fileName), ".sup", outputFolder, overwrite);
var language = programMapTableParser.GetSubtitleLanguageTwoLetter(pid);
if (string.IsNullOrEmpty(language))
{
language = pid.ToString(CultureInfo.InvariantCulture);
}
var outputFileName = CommandLineConverter.FormatOutputFileNameForBatchConvert(Utilities.GetPathAndFileNameWithoutExtension(fileName) + "." + language + Path.GetExtension(fileName), ".sup", outputFolder, overwrite);
stdOutWriter?.WriteLine($"Saving PID {pid} to {outputFileName}...");
var sub = tsParser.GetDvbSubtitles(pid);
progressCallback?.Invoke($"Save PID {pid}");