diff --git a/src/Forms/Main.cs b/src/Forms/Main.cs
index 8f7cff74e..8df40363a 100644
--- a/src/Forms/Main.cs
+++ b/src/Forms/Main.cs
@@ -2242,11 +2242,11 @@ namespace Nikse.SubtitleEdit.Forms
var fi = new FileInfo(fileName);
- //if (Path.GetExtension(fileName).ToLower() == ".ts" && fi.Length > 10000 && IsTransportStream(fileName)) //TODO: Also check mpg, mpeg - and file header!
- //{
- // ImportSubtitleFromTransportStream(fileName);
- // return;
- //}
+ if (Path.GetExtension(fileName).ToLower() == ".ts" && fi.Length > 10000 && IsTransportStream(fileName)) //TODO: Also check mpg, mpeg - and file header!
+ {
+ ImportSubtitleFromTransportStream(fileName);
+ return;
+ }
if ((Path.GetExtension(fileName).ToLower() == ".mp4" || Path.GetExtension(fileName).ToLower() == ".m4v" || Path.GetExtension(fileName).ToLower() == ".3gp")
&& fi.Length > 10000)
@@ -9056,8 +9056,10 @@ namespace Nikse.SubtitleEdit.Forms
private bool ImportSubtitleFromTransportStream(string fileName)
{
+ ShowStatus("Parsing transport stream - please wait...");
var tsParser = new Nikse.SubtitleEdit.Logic.TransportStream.TransportStreamParser();
tsParser.ParseTsFile(fileName);
+ ShowStatus(string.Empty);
if (tsParser.SubtitlePacketIds.Count == 0)
{
@@ -9065,43 +9067,49 @@ namespace Nikse.SubtitleEdit.Forms
return false;
}
- // choose subtitle track
- if (tsParser.SubtitlePacketIds.Count == 0)
+ int packedId = tsParser.SubtitlePacketIds[0];
+ if (tsParser.SubtitlePacketIds.Count > 1)
{
- MessageBox.Show(_language.NoSubtitlesFound);
- return false;
+ var subChooser = new TransportStreamSubtitleChooser();
+ _formPositionsAndSizes.SetPositionAndSize(subChooser);
+ subChooser.Initialize(tsParser);
+ if (subChooser.ShowDialog(this) == DialogResult.Cancel)
+ return false;
+ packedId = tsParser.SubtitlePacketIds[subChooser.SelectedIndex];
+ _formPositionsAndSizes.SavePositionAndSize(subChooser);
}
+ var subtitles = tsParser.GetSubtitlePesPackets(packedId);
+
+ var formSubOcr = new VobSubOcr();
+ _formPositionsAndSizes.SetPositionAndSize(formSubOcr);
+ formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, fileName);
+ if (formSubOcr.ShowDialog(this) == DialogResult.OK)
+ {
+ MakeHistoryForUndo(_language.BeforeImportingDvdSubtitle);
- //var formSubOcr = new VobSubOcr();
- //_formPositionsAndSizes.SetPositionAndSize(formSubOcr);
- //formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr, fileName);
- //if (formSubOcr.ShowDialog(this) == DialogResult.OK)
- //{
- // MakeHistoryForUndo(_language.BeforeImportingDvdSubtitle);
+ _subtitle.Paragraphs.Clear();
+ SetCurrentFormat(Configuration.Settings.General.DefaultSubtitleFormat);
+ _subtitle.WasLoadedWithFrameNumbers = false;
+ _subtitle.CalculateFrameNumbersFromTimeCodes(CurrentFrameRate);
+ foreach (Paragraph p in formSubOcr.SubtitleFromOcr.Paragraphs)
+ {
+ _subtitle.Paragraphs.Add(p);
+ }
- // _subtitle.Paragraphs.Clear();
- // SetCurrentFormat(Configuration.Settings.General.DefaultSubtitleFormat);
- // _subtitle.WasLoadedWithFrameNumbers = false;
- // _subtitle.CalculateFrameNumbersFromTimeCodes(CurrentFrameRate);
- // foreach (Paragraph p in formSubOcr.SubtitleFromOcr.Paragraphs)
- // {
- // _subtitle.Paragraphs.Add(p);
- // }
+ ShowSource();
+ SubtitleListview1.Fill(_subtitle, _subtitleAlternate);
+ _subtitleListViewIndex = -1;
+ SubtitleListview1.FirstVisibleIndex = -1;
+ SubtitleListview1.SelectIndexAndEnsureVisible(0);
- // ShowSource();
- // SubtitleListview1.Fill(_subtitle, _subtitleAlternate);
- // _subtitleListViewIndex = -1;
- // SubtitleListview1.FirstVisibleIndex = -1;
- // SubtitleListview1.SelectIndexAndEnsureVisible(0);
+ _fileName = string.Empty;
+ Text = Title;
- // _fileName = string.Empty;
- // Text = Title;
-
- // Configuration.Settings.Save();
- // _formPositionsAndSizes.SavePositionAndSize(formSubOcr);
- // return true;
- //}
- //_formPositionsAndSizes.SavePositionAndSize(formSubOcr);
+ Configuration.Settings.Save();
+ _formPositionsAndSizes.SavePositionAndSize(formSubOcr);
+ return true;
+ }
+ _formPositionsAndSizes.SavePositionAndSize(formSubOcr);
return false;
}
diff --git a/src/Forms/TransportStreamSubtitleChooser.Designer.cs b/src/Forms/TransportStreamSubtitleChooser.Designer.cs
new file mode 100644
index 000000000..4f397c12e
--- /dev/null
+++ b/src/Forms/TransportStreamSubtitleChooser.Designer.cs
@@ -0,0 +1,109 @@
+namespace Nikse.SubtitleEdit.Forms
+{
+ partial class TransportStreamSubtitleChooser
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.labelChoose = new System.Windows.Forms.Label();
+ this.listBox1 = new System.Windows.Forms.ListBox();
+ this.buttonCancel = new System.Windows.Forms.Button();
+ this.buttonOK = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // labelChoose
+ //
+ this.labelChoose.AutoSize = true;
+ this.labelChoose.Location = new System.Drawing.Point(9, 21);
+ this.labelChoose.Name = "labelChoose";
+ this.labelChoose.Size = new System.Drawing.Size(220, 13);
+ this.labelChoose.TabIndex = 52;
+ this.labelChoose.Text = "More than one subtitle found - please choose";
+ //
+ // listBox1
+ //
+ this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.listBox1.FormattingEnabled = true;
+ this.listBox1.Location = new System.Drawing.Point(12, 44);
+ this.listBox1.Name = "listBox1";
+ this.listBox1.Size = new System.Drawing.Size(548, 264);
+ this.listBox1.TabIndex = 51;
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonCancel.BackColor = System.Drawing.SystemColors.Control;
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.Location = new System.Drawing.Point(485, 312);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(75, 21);
+ this.buttonCancel.TabIndex = 50;
+ this.buttonCancel.Text = "C&ancel";
+ this.buttonCancel.UseVisualStyleBackColor = false;
+ this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
+ //
+ // buttonOK
+ //
+ this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonOK.Location = new System.Drawing.Point(404, 312);
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.Size = new System.Drawing.Size(75, 21);
+ this.buttonOK.TabIndex = 49;
+ this.buttonOK.Text = "OK";
+ this.buttonOK.UseVisualStyleBackColor = true;
+ this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
+ //
+ // TransportStreamSubtitleChooser
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(572, 345);
+ this.Controls.Add(this.labelChoose);
+ this.Controls.Add(this.listBox1);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.buttonOK);
+ this.KeyPreview = true;
+ this.Name = "TransportStreamSubtitleChooser";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Transport stream subtitle chooser";
+ this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TransportStreamSubtitleChooser_KeyDown);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label labelChoose;
+ private System.Windows.Forms.ListBox listBox1;
+ private System.Windows.Forms.Button buttonCancel;
+ private System.Windows.Forms.Button buttonOK;
+ }
+}
\ No newline at end of file
diff --git a/src/Forms/TransportStreamSubtitleChooser.cs b/src/Forms/TransportStreamSubtitleChooser.cs
new file mode 100644
index 000000000..46f49c852
--- /dev/null
+++ b/src/Forms/TransportStreamSubtitleChooser.cs
@@ -0,0 +1,70 @@
+using Nikse.SubtitleEdit.Logic;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Nikse.SubtitleEdit.Forms
+{
+ public partial class TransportStreamSubtitleChooser : Form
+ {
+ public TransportStreamSubtitleChooser()
+ {
+ InitializeComponent();
+ //Text = Configuration.Settings.Language.MatroskaSubtitleChooser.Title;
+ labelChoose.Text = Configuration.Settings.Language.MatroskaSubtitleChooser.PleaseChoose;
+ buttonOK.Text = Configuration.Settings.Language.General.OK;
+ buttonCancel.Text = Configuration.Settings.Language.General.Cancel;
+ FixLargeFonts();
+ }
+
+ private void FixLargeFonts()
+ {
+ Graphics graphics = this.CreateGraphics();
+ SizeF textSize = graphics.MeasureString(buttonOK.Text, this.Font);
+ if (textSize.Height > buttonOK.Height - 4)
+ {
+ int newButtonHeight = (int)(textSize.Height + 7 + 0.5);
+ Utilities.SetButtonHeight(this, newButtonHeight, 1);
+ }
+ }
+
+ private void buttonOK_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.OK;
+ }
+
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ }
+
+ private void TransportStreamSubtitleChooser_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Escape)
+ DialogResult = DialogResult.Cancel;
+ }
+
+ internal void Initialize(Logic.TransportStream.TransportStreamParser tsParser)
+ {
+ foreach (int id in tsParser.SubtitlePacketIds)
+ {
+ string s = string.Format(string.Format("Packet id {0}", id));
+ listBox1.Items.Add(s);
+ }
+ listBox1.SelectedIndex = 0;
+ }
+
+ public int SelectedIndex
+ {
+ get
+ {
+ return listBox1.SelectedIndex;
+ }
+ }
+
+ }
+}
diff --git a/src/Forms/TransportStreamSubtitleChooser.resx b/src/Forms/TransportStreamSubtitleChooser.resx
new file mode 100644
index 000000000..5ea0895e3
--- /dev/null
+++ b/src/Forms/TransportStreamSubtitleChooser.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/Forms/VobSubOcr.cs b/src/Forms/VobSubOcr.cs
index 0ed3b27cf..f69538eeb 100644
--- a/src/Forms/VobSubOcr.cs
+++ b/src/Forms/VobSubOcr.cs
@@ -220,6 +220,9 @@ namespace Nikse.SubtitleEdit.Forms
// XSub (DivX)
List _xSubList;
+ // DVB (from transport stream)
+ List _dvbSubtitles;
+
string _lastLine;
string _languageId;
string _importLanguageString;
@@ -1249,6 +1252,15 @@ namespace Nikse.SubtitleEdit.Forms
return _xSubList[index].GetImage();
}
}
+ else if (_dvbSubtitles != null)
+ {
+ foreach (var segment in _dvbSubtitles[index].SubtitleSegments)
+ {
+ if (segment.ObjectData != null && segment.ObjectData.Image != null)
+ return segment.ObjectData.Image;
+ }
+ return new Bitmap(1, 1);
+ }
if (_bluRaySubtitlesOriginal != null)
{
@@ -1299,6 +1311,8 @@ namespace Nikse.SubtitleEdit.Forms
return (_bluRaySubtitles[index].StartTime + 45) / 90;
else if (_xSubList != null)
return (long)_xSubList[index].Start.TotalMilliseconds;
+ else if (_dvbSubtitles != null)
+ return (long)_dvbSubtitles[index].PresentationTimeStamp + 45 / 90;
else
return (long)_vobSubMergedPackist[index].StartTime.TotalMilliseconds;
}
@@ -1315,6 +1329,8 @@ namespace Nikse.SubtitleEdit.Forms
return (_bluRaySubtitles[index].EndTime + 45) / 90;
else if (_xSubList != null)
return (long)_xSubList[index].End.TotalMilliseconds;
+ else if (_dvbSubtitles != null)
+ return (long)_dvbSubtitles[index].PresentationTimeStamp + 45 / 90;
else
return (long)_vobSubMergedPackist[index].EndTime.TotalMilliseconds;
}
@@ -1331,6 +1347,8 @@ namespace Nikse.SubtitleEdit.Forms
return _bluRaySubtitles.Count;
else if (_xSubList != null)
return _xSubList.Count;
+ else if (_dvbSubtitles != null)
+ return _dvbSubtitles.Count;
else
return _vobSubMergedPackist.Count;
}
@@ -3719,6 +3737,19 @@ namespace Nikse.SubtitleEdit.Forms
buttonEditCharacterDatabase.Enabled = true;
buttonStartOcr.Focus();
}
+ else if (_dvbSubtitles != null)
+ {
+ checkBoxShowOnlyForced.Visible = false;
+ checkBoxUseTimeCodesFromIdx.Visible = false;
+
+ buttonOK.Enabled = true;
+ buttonCancel.Enabled = true;
+ buttonStartOcr.Enabled = true;
+ buttonStop.Enabled = false;
+ buttonNewCharacterDatabase.Enabled = true;
+ buttonEditCharacterDatabase.Enabled = true;
+ buttonStartOcr.Focus();
+ }
else if (_bdnXmlOriginal != null)
{
LoadBdnXml();
@@ -6958,5 +6989,44 @@ namespace Nikse.SubtitleEdit.Forms
exportBdnXmlPng.ShowDialog(this);
}
+ internal void Initialize(List subtitles, VobSubOcrSettings vobSubOcrSettings, string fileName)
+ {
+ buttonOK.Enabled = false;
+ buttonCancel.Enabled = false;
+ buttonStartOcr.Enabled = false;
+ buttonStop.Enabled = false;
+ buttonNewCharacterDatabase.Enabled = false;
+ buttonEditCharacterDatabase.Enabled = false;
+ labelStatus.Text = string.Empty;
+ progressBar1.Visible = false;
+ progressBar1.Maximum = 100;
+ progressBar1.Value = 0;
+ numericUpDownPixelsIsSpace.Value = vobSubOcrSettings.XOrMorePixelsMakesSpace;
+ numericUpDownNumberOfPixelsIsSpaceNOCR.Value = vobSubOcrSettings.XOrMorePixelsMakesSpace;
+ _vobSubOcrSettings = vobSubOcrSettings;
+
+ InitializeModi();
+ InitializeTesseract();
+ LoadImageCompareCharacterDatabaseList();
+
+ SetOcrMethod();
+
+ _dvbSubtitles = subtitles;
+
+ foreach (Logic.TransportStream.DvbSubPes pes in _dvbSubtitles)
+ {
+ double pts = 0;
+ if (pes.PresentationTimeStamp != null)
+ pts = pes.PresentationTimeStamp.Value;
+ var p = new Paragraph(string.Empty, ((pts + 45) / 90.0), ((pts + 45) / 90.0));
+ _subtitle.Paragraphs.Add(p);
+ }
+ subtitleListView1.Fill(_subtitle);
+ subtitleListView1.SelectIndexAndEnsureVisible(0);
+
+ //SetTesseractLanguageFromLanguageString(languageString);
+ //_importLanguageString = languageString;
+ }
+
}
}
diff --git a/src/Logic/SubtitleFormats/FLVCoreCuePoints.cs b/src/Logic/SubtitleFormats/FLVCoreCuePoints.cs
new file mode 100644
index 000000000..af61f89cb
--- /dev/null
+++ b/src/Logic/SubtitleFormats/FLVCoreCuePoints.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Xml;
+
+namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
+{
+ public class FLVCoreCuePoints : SubtitleFormat
+ {
+ public override string Extension
+ {
+ get { return ".xml"; }
+ }
+
+ public override string Name
+ {
+ get { return "FLVCoreCuePoints"; }
+ }
+
+ public override bool IsTimeBased
+ {
+ get { return true; }
+ }
+
+ public override bool IsMine(List lines, string fileName)
+ {
+ var subtitle = new Subtitle();
+ LoadSubtitle(subtitle, lines, fileName);
+ return subtitle.Paragraphs.Count > 0;
+ }
+
+ public override string ToText(Subtitle subtitle, string title)
+ {
+ string xmlStructure =
+ "" + Environment.NewLine +
+ "";
+
+ var xml = new XmlDocument();
+ xml.LoadXml(xmlStructure);
+
+ foreach (Paragraph p in subtitle.Paragraphs)
+ {
+ XmlNode paragraph = xml.CreateElement("CuePoint");
+
+ XmlNode startTime = xml.CreateElement("Time");
+ startTime.InnerText = p.StartTime.TotalMilliseconds.ToString();
+ paragraph.AppendChild(startTime);
+
+ XmlNode paragraphType = xml.CreateElement("Type");
+ paragraphType.InnerText = "event";
+ paragraph.AppendChild(paragraphType);
+
+ XmlNode name = xml.CreateElement("Name");
+ name.InnerText = p.Text;
+ paragraph.AppendChild(name);
+
+ XmlNode parameters = xml.CreateElement("Parameters");
+
+ XmlNode parameter = xml.CreateElement("Parameter");
+ name = xml.CreateElement("Name");
+ name.InnerText = "source";
+ XmlNode value = xml.CreateElement("Value");
+ value.InnerText = "transcription";
+ parameter.AppendChild(name);
+ parameter.AppendChild(value);
+ parameters.AppendChild(parameter);
+
+ parameter = xml.CreateElement("Parameter");
+ name = xml.CreateElement("Name");
+ name.InnerText = "duration";
+ value = xml.CreateElement("Value");
+ value.InnerText = p.Duration.TotalMilliseconds.ToString();
+ parameter.AppendChild(name);
+ parameter.AppendChild(value);
+ parameters.AppendChild(parameter);
+
+ parameter = xml.CreateElement("Parameter");
+ name = xml.CreateElement("Name");
+ name.InnerText = "confidence";
+ value = xml.CreateElement("Value");
+ value.InnerText = "50";
+ parameter.AppendChild(name);
+ parameter.AppendChild(value);
+ parameters.AppendChild(parameter);
+
+ paragraph.AppendChild(parameters);
+
+ xml.DocumentElement.AppendChild(paragraph);
+ }
+
+
+ return ToUtf8XmlString(xml);
+ }
+
+ public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName)
+ {
+ _errorCount = 0;
+
+ var sb = new StringBuilder();
+ lines.ForEach(line => sb.AppendLine(line));
+
+ string allText = sb.ToString();
+ if (!allText.Contains(" next.StartTime.TotalMilliseconds)
+ p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MininumMillisecondsBetweenLines;
+ }
+ }
+
+ subtitle.Renumber(1);
+ }
+
+ }
+}
+
+
diff --git a/src/Logic/SubtitleFormats/SubtitleFormat.cs b/src/Logic/SubtitleFormats/SubtitleFormat.cs
index 764ae13fb..eab81923f 100644
--- a/src/Logic/SubtitleFormats/SubtitleFormat.cs
+++ b/src/Logic/SubtitleFormats/SubtitleFormat.cs
@@ -62,6 +62,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
new FinalCutProTestXml(),
new FinalCutProTest2Xml(),
new FlashXml(),
+ new FLVCoreCuePoints(),
new Footage(),
new GpacTtxt(),
new ImageLogicAutocaption(),
diff --git a/src/Logic/TransportStream/DvbSubPes.cs b/src/Logic/TransportStream/DvbSubPes.cs
index 935b8bd5c..7ec1c5d29 100644
--- a/src/Logic/TransportStream/DvbSubPes.cs
+++ b/src/Logic/TransportStream/DvbSubPes.cs
@@ -35,6 +35,9 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
public DvbSubPes(byte[] buffer, int index)
{
+ if (buffer.Length < 9)
+ return;
+
StartCode = Helper.GetEndian(buffer, index + 0, 3);
StreamId = buffer[index + 3];
Length = Helper.GetEndianWord(buffer, index + 4);
diff --git a/src/Logic/TransportStream/ObjectDataSegment.cs b/src/Logic/TransportStream/ObjectDataSegment.cs
index 2a3a94ed8..6ea26b292 100644
--- a/src/Logic/TransportStream/ObjectDataSegment.cs
+++ b/src/Logic/TransportStream/ObjectDataSegment.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
+
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
public class ObjectDataSegment
@@ -31,15 +32,24 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
public const int MapTable4To8Bit = 0x22;
public const int EndOfObjectLineCode = 0xf0;
- Random r = new Random();
+ public ObjectDataSegment(byte[] buffer, int index, ClutDefinitionSegment cds)
+ {
+ ObjectId = Helper.GetEndianWord(buffer, index);
+ ObjectVersionNumber = buffer[index + 2] >> 4;
+ ObjectCodingMethod = (buffer[index + 2] & Helper.B00001100) >> 2;
+ NonModifyingColorFlag = (buffer[index + 2] & Helper.B00000010) > 0;
+ DecodeImage(buffer, index, cds);
+ }
public void DecodeImage(byte[] buffer, int index, ClutDefinitionSegment cds)
{
Image = new Bitmap(720, 40);
var r = new Random();
Color c = Color.Red;
- List twoBitColorLookup = new List { 0, 1, 2, 3 };
+ List twoToFourBitColorLookup = new List { 0, 1, 2, 3 };
+ List twoToEightBitColorLookup = new List { 0, 1, 2, 3 };
+ List fourToEightBitColorLookup = new List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ,15 };
if (ObjectCodingMethod == 0)
{
@@ -60,13 +70,13 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
int bitIndex = 0;
while (index < start + TopFieldDataBlockLength && TwoBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength, ref bitIndex))
{
- DrawPixels(cds, twoBitColorLookup[pixelCode], runLength, ref x, ref y);
+ DrawPixels(cds, twoToFourBitColorLookup[pixelCode], runLength, ref x, ref y);
}
}
else if (dataType == PixelDecoding4Bit)
{
bool startHalf = false;
- while (FourBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength, ref startHalf))
+ while (index < start + TopFieldDataBlockLength && FourBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength, ref startHalf))
{
DrawPixels(cds, pixelCode, runLength, ref x, ref y);
}
@@ -74,28 +84,49 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
else if (dataType == PixelDecoding8Bit)
{
System.Windows.Forms.MessageBox.Show("8-bit pixel decoding!");
- while (EightBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength))
+ while (index < start + TopFieldDataBlockLength && EightBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength))
{
DrawPixels(cds, pixelCode, runLength, ref x, ref y);
}
}
else if (dataType == MapTable2To4Bit)
{
- //4 entry numbers of 4-bits each; entry number 0 first, entry number 3 last.
- twoBitColorLookup[0] = buffer[index] >> 4;
- twoBitColorLookup[1] = buffer[index] & Helper.B00001111;
+ //4 entry numbers of 4-bits each; entry number 0 first, entry number 3 last
+ twoToFourBitColorLookup[0] = buffer[index] >> 4;
+ twoToFourBitColorLookup[1] = buffer[index] & Helper.B00001111;
index++;
- twoBitColorLookup[2] = buffer[index] >> 4;
- twoBitColorLookup[3] = buffer[index] & Helper.B00001111;
+ twoToFourBitColorLookup[2] = buffer[index] >> 4;
+ twoToFourBitColorLookup[3] = buffer[index] & Helper.B00001111;
index++;
}
+ else if (dataType == MapTable2To8Bit)
+ {
+ //4 entry numbers of 8-bits each; entry number 0 first, entry number 3 last
+ twoToEightBitColorLookup[0] = buffer[index];
+ index++;
+ twoToEightBitColorLookup[1] = buffer[index];
+ index++;
+ twoToEightBitColorLookup[2] = buffer[index];
+ index++;
+ twoToEightBitColorLookup[4] = buffer[index];
+ index++;
+ }
+ else if (dataType == MapTable4To8Bit)
+ {
+ // 16 entry numbers of 8-bits each
+ for (int k = 0; k < 16; k++)
+ {
+ fourToEightBitColorLookup[k] = buffer[index];
+ index++;
+ }
+ }
else if (dataType == EndOfObjectLineCode)
{
x = 0;
y += 2; // interlaced - skip one line
}
if (index < start + TopFieldDataBlockLength)
- {
+ {
dataType = buffer[index];
index++;
}
@@ -113,13 +144,13 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
int bitIndex = 0;
while (index < start + BottomFieldDataBlockLength - 1 && TwoBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength, ref bitIndex))
{
- DrawPixels(cds, twoBitColorLookup[pixelCode], runLength, ref x, ref y);
+ DrawPixels(cds, twoToFourBitColorLookup[pixelCode], runLength, ref x, ref y);
}
}
else if (dataType == PixelDecoding4Bit)
{
bool startHalf = false;
- while (FourBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength, ref startHalf))
+ while (index < start + BottomFieldDataBlockLength - 1 && FourBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength, ref startHalf))
{
DrawPixels(cds, pixelCode, runLength, ref x, ref y);
}
@@ -127,21 +158,42 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
else if (dataType == PixelDecoding8Bit)
{
System.Windows.Forms.MessageBox.Show("8-bit pixel decoding!");
- while (EightBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength))
+ while (index < start + BottomFieldDataBlockLength - 1 && EightBitPixelDecoding(buffer, ref index, ref pixelCode, ref runLength))
{
DrawPixels(cds, pixelCode, runLength, ref x, ref y);
}
}
else if (dataType == MapTable2To4Bit)
{
- //4 entry numbers of 4-bits each; entry number 0 first, entry number 3 last.
- twoBitColorLookup[0] = buffer[index] >> 4;
- twoBitColorLookup[1] = buffer[index] & Helper.B00001111;
+ //4 entry numbers of 4-bits each; entry number 0 first, entry number 3 last
+ twoToFourBitColorLookup[0] = buffer[index] >> 4;
+ twoToFourBitColorLookup[1] = buffer[index] & Helper.B00001111;
index++;
- twoBitColorLookup[2] = buffer[index] >> 4;
- twoBitColorLookup[3] = buffer[index] & Helper.B00001111;
+ twoToFourBitColorLookup[2] = buffer[index] >> 4;
+ twoToFourBitColorLookup[3] = buffer[index] & Helper.B00001111;
index++;
}
+ else if (dataType == MapTable2To8Bit)
+ {
+ //4 entry numbers of 8-bits each; entry number 0 first, entry number 3 last
+ twoToEightBitColorLookup[0] = buffer[index];
+ index++;
+ twoToEightBitColorLookup[1] = buffer[index];
+ index++;
+ twoToEightBitColorLookup[2] = buffer[index];
+ index++;
+ twoToEightBitColorLookup[4] = buffer[index];
+ index++;
+ }
+ else if (dataType == MapTable4To8Bit)
+ {
+ // 16 entry numbers of 8-bits each
+ for (int k = 0; k < 16; k++)
+ {
+ fourToEightBitColorLookup[k] = buffer[index];
+ index++;
+ }
+ }
else if (dataType == EndOfObjectLineCode)
{
x = 0;
@@ -183,17 +235,7 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
Image.SetPixel(x, y, c);
x++;
}
- }
-
- public ObjectDataSegment(byte[] buffer, int index, ClutDefinitionSegment cds)
- {
- ObjectId = Helper.GetEndianWord(buffer, index);
- ObjectVersionNumber = buffer[index + 2] >> 4;
- ObjectCodingMethod = (buffer[index + 2] & Helper.B00001100) >> 2;
- NonModifyingColorFlag = (buffer[index + 2] & Helper.B00000010) > 0;
-
- DecodeImage(buffer, index, cds);
- }
+ }
private int Next8Bits(byte[] buffer, ref int index)
{
diff --git a/src/Logic/TransportStream/SubtitleSegment.cs b/src/Logic/TransportStream/SubtitleSegment.cs
index f20b03344..c4b0963f8 100644
--- a/src/Logic/TransportStream/SubtitleSegment.cs
+++ b/src/Logic/TransportStream/SubtitleSegment.cs
@@ -44,6 +44,9 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
if (buffer.Length - 6 < DataBuffer.Length)
return;
+ if (index + 6 + DataBuffer.Length > buffer.Length)
+ return;
+
Buffer.BlockCopy(buffer, index + 6, DataBuffer, 0, DataBuffer.Length);
IsValid = true;
diff --git a/src/Logic/TransportStream/TransportStreamParser.cs b/src/Logic/TransportStream/TransportStreamParser.cs
index 4cab37e22..3eaca6b45 100644
--- a/src/Logic/TransportStream/TransportStreamParser.cs
+++ b/src/Logic/TransportStream/TransportStreamParser.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
-using System.Windows.Forms;
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
@@ -17,6 +16,7 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
public long TotalNumberOfPrivateStream1Continuation0 { get; private set; }
public List SubtitlePacketIds { get; private set; }
public List SubtitlePackets { get; private set; }
+ public List ProgramAssociationTables { get; private set; }
public void ParseTsFile(string fileName)
{
@@ -37,6 +37,7 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
TotalNumberOfPrivateStream1Continuation0 = 0;
SubtitlePacketIds = new List();
SubtitlePackets = new List();
+ ProgramAssociationTables = new List();
ms.Position = 0;
int packetLength = DeterminePacketLength(ms);
var packetBuffer = new byte[packetLength];
@@ -48,7 +49,7 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
byte syncByte = packetBuffer[0];
if (syncByte == Packet.SynchronizationByte)
{
- Packet packet = new Packet(packetBuffer);
+ var packet = new Packet(packetBuffer);
if (packet.IsNullPacket)
{
@@ -56,7 +57,7 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
}
else if (packet.IsProgramAssociationTable)
{
- StringBuilder sb = new StringBuilder();
+ var sb = new StringBuilder();
sb.AppendLine("PacketNo: " + TotalNumberOfPackets + 1);
sb.AppendLine("PacketId: " + packet.PacketId);
sb.AppendLine();
@@ -87,8 +88,7 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
sb.AppendLine("CurrentNextIndicator: " + packet.ProgramAssociationTable.CurrentNextIndicator);
sb.AppendLine("SectionNumber: " + packet.ProgramAssociationTable.SectionNumber);
sb.AppendLine("LastSectionNumber: " + packet.ProgramAssociationTable.LastSectionNumber);
-
- //MessageBox.Show(sb.ToString());
+ ProgramAssociationTables.Add(packet);
}
else if (packet.IsPrivateStream1 || SubtitlePacketIds.Contains(packet.PacketId))
{
@@ -99,25 +99,25 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
if (!SubtitlePacketIds.Contains(packet.PacketId))
{
SubtitlePacketIds.Add(packet.PacketId);
-// MessageBox.Show("Subtitle packet id=" + packet.PacketId);
}
if (packet.ContinuityCounter == 0)
{
TotalNumberOfPrivateStream1Continuation0++;
- int pes_extensionlength = 0xFF & packetBuffer[12 + packet.AdaptionFieldLength];
+ int pes_extensionlength = 0;
+ if (12 + packet.AdaptionFieldLength < packetBuffer.Length)
+ pes_extensionlength = 0xFF & packetBuffer[12 + packet.AdaptionFieldLength];
int pes_offset = 13 + packet.AdaptionFieldLength + pes_extensionlength;
- bool isTeletext = (pes_extensionlength == 0x24 && (0xFF & packetBuffer[pes_offset])>>4 == 1);
+ bool isTeletext = (pes_extensionlength == 0x24 && (0xFF & packetBuffer[pes_offset]) >> 4 == 1);
// workaround uk freesat teletext
if (!isTeletext)
isTeletext = (pes_extensionlength == 0x24 && (0xFF & packetBuffer[pes_offset]) == 0x99);
- //if (isTeletext)
- // MessageBox.Show(TotalNumberOfPackets.ToString() + ": Teletext!");
- //if (!isTeletext)
- // pes_subID = ((0xFF & ts_packet[pes_offset]) == 0x20 && (0xFF & ts_packet[pes_offset + 1]) == 0 && (0xFF & ts_packet[pes_offset + 2]) == 0xF) ? 0x20 : 0;
+ if (!isTeletext)
+ {
+ }
}
}
TotalNumberOfPackets++;
@@ -129,36 +129,62 @@ namespace Nikse.SubtitleEdit.Logic.TransportStream
break;
}
}
- //MessageBox.Show("Done parsing " + Environment.NewLine +
- // Environment.NewLine +
- // "#Packets: " + TotalNumberOfPackets.ToString() + Environment.NewLine +
- // "#Null packets: " + NumberOfNullPackets.ToString() + Environment.NewLine +
- // "#Private stream 1's: " + TotalNumberOfPrivateStream1.ToString() + Environment.NewLine +
- // "#Private stream 1's with continuation=0: " + TotalNumberOfPrivateStream1Continuation0.ToString());
}
- public List GetSubtitlePesPackets(int packetId)
+ public List GetSubtitlePesPackets(int packetId)
{
- var list = new List();
- var buffer = new byte[20000];
- int index =0;
+ var list = new List();
+ int last = -1;
+ List packetList = new List();
foreach (Packet packet in SubtitlePackets)
{
- if (packet.ContinuityCounter == 0)
+ if (packet.PacketId == packetId)
{
- if (index > 0)
+ if (packet.PayloadUnitStartIndicator)
{
- var pes = new PacketizedElementaryStream(buffer, 0);
- list.Add(pes);
+ if (packetList.Count > 0)
+ AddPesPacket(list, packetList);
+ packetList = new List();
}
- index = 0;
+ if (packet.Payload != null && last != packet.ContinuityCounter)
+ packetList.Add(packet);
+ last = packet.ContinuityCounter;
}
- Buffer.BlockCopy(packet.Payload, 0, buffer, index, packet.Payload.Length);
- index += packet.Payload.Length;
}
+ if (packetList.Count > 0)
+ AddPesPacket(list, packetList);
return list;
}
+ private static void AddPesPacket(List list, List packetList)
+ {
+ int bufferSize = 0;
+ foreach (Packet p in packetList)
+ bufferSize += p.Payload.Length;
+ var pesData = new byte[bufferSize];
+ int pesIndex = 0;
+ foreach (Packet p in packetList)
+ {
+ Buffer.BlockCopy(p.Payload, 0, pesData, pesIndex, p.Payload.Length);
+ pesIndex += p.Payload.Length;
+ }
+
+ DvbSubPes pes;
+ if (Nikse.SubtitleEdit.Logic.VobSub.VobSubParser.IsMpeg2PackHeader(pesData))
+ {
+ pes = new DvbSubPes(pesData, Nikse.SubtitleEdit.Logic.VobSub.Mpeg2Header.Length);
+ }
+ else if (Nikse.SubtitleEdit.Logic.VobSub.VobSubParser.IsPrivateStream1(pesData, 0))
+ {
+ pes = new DvbSubPes(pesData, 0);
+ }
+ else
+ {
+ pes = new DvbSubPes(pesData, 0);
+ }
+ list.Add(pes);
+ }
+
private int DeterminePacketLength(Stream ms)
{
return 188;
diff --git a/src/SubtitleEdit.csproj b/src/SubtitleEdit.csproj
index 85628969b..fab77d662 100644
--- a/src/SubtitleEdit.csproj
+++ b/src/SubtitleEdit.csproj
@@ -617,6 +617,12 @@
TimedTextStyles.cs
+
+ Form
+
+
+ TransportStreamSubtitleChooser.cs
+
Form
@@ -864,6 +870,7 @@
+
@@ -1386,6 +1393,9 @@
TimedTextStyles.cs
+
+ TransportStreamSubtitleChooser.cs
+
UnknownSubtitle.cs
Designer