mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-10-27 22:42:38 +01:00
Added German language file - thx JW 301 :)
Also some cleanup + some shortcuts (+ some testing of TS files) git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@716 99eadd0c-20b8-1223-b5c4-2a2b2df33de2
This commit is contained in:
parent
bfc04f7a70
commit
68397dbd57
@ -128,6 +128,8 @@ namespace Nikse.SubtitleEdit.Controls
|
||||
|
||||
public bool Locked { get; set; }
|
||||
|
||||
public double VerticalZoomPercent { get; set; }
|
||||
|
||||
public double EndPositionSeconds
|
||||
{
|
||||
get
|
||||
@ -198,6 +200,7 @@ namespace Nikse.SubtitleEdit.Controls
|
||||
AllowNewSelection = true;
|
||||
ShowSpectrogram = true;
|
||||
ShowWaveform = true;
|
||||
VerticalZoomPercent = 1.0;
|
||||
}
|
||||
|
||||
public void NearestSubtitles(Subtitle subtitle, double currentVideoPositionSeconds, int subtitleIndex)
|
||||
@ -316,6 +319,9 @@ namespace Nikse.SubtitleEdit.Controls
|
||||
}
|
||||
int imageHeight = Height;
|
||||
int maxHeight = (int)(Math.Max(Math.Abs(_wavePeaks.DataMinValue), Math.Abs(_wavePeaks.DataMaxValue)) + 0.5);
|
||||
maxHeight = (int)(maxHeight * VerticalZoomPercent);
|
||||
if (maxHeight < 0)
|
||||
maxHeight = 1000;
|
||||
Pen pen = new System.Drawing.Pen(Color);
|
||||
|
||||
DrawBackground(graphics);
|
||||
|
@ -123,6 +123,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
public void Initialize(Subtitle subtitle)
|
||||
{
|
||||
_autoDetectGoogleLanguage = Utilities.AutoDetectGoogleLanguage(subtitle);
|
||||
if (_autoDetectGoogleLanguage.ToLower() == "zh")
|
||||
_autoDetectGoogleLanguage = "zh-CHS"; // Note that "zh-CHS" (Simplified Chinese) and "zh-CHT" (Traditional Chinese) are neutral cultures
|
||||
CultureInfo ci = CultureInfo.GetCultureInfo(_autoDetectGoogleLanguage);
|
||||
string threeLetterISOLanguageName = ci.ThreeLetterISOLanguageName;
|
||||
|
||||
|
16
src/Forms/Main.Designer.cs
generated
16
src/Forms/Main.Designer.cs
generated
@ -157,8 +157,8 @@
|
||||
this.pointSyncViaOtherSubtitleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItemChangeFrameRate2 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItemAutoTranslate = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.translateByGoogleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.translateFromSwedishToDanishToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@ -1505,13 +1505,6 @@
|
||||
this.toolStripMenuItemAutoTranslate.Size = new System.Drawing.Size(97, 20);
|
||||
this.toolStripMenuItemAutoTranslate.Text = "Auto-translate";
|
||||
//
|
||||
// translatepoweredByMicrosoftToolStripMenuItem
|
||||
//
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Name = "translatepoweredByMicrosoftToolStripMenuItem";
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Size = new System.Drawing.Size(414, 22);
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Text = "Translate (powered by Microsoft)...";
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Click += new System.EventHandler(this.translatepoweredByMicrosoftToolStripMenuItem_Click);
|
||||
//
|
||||
// translateByGoogleToolStripMenuItem
|
||||
//
|
||||
this.translateByGoogleToolStripMenuItem.Name = "translateByGoogleToolStripMenuItem";
|
||||
@ -1521,6 +1514,13 @@
|
||||
this.translateByGoogleToolStripMenuItem.Text = "Translate (powered by Google)...";
|
||||
this.translateByGoogleToolStripMenuItem.Click += new System.EventHandler(this.TranslateByGoogleToolStripMenuItemClick);
|
||||
//
|
||||
// translatepoweredByMicrosoftToolStripMenuItem
|
||||
//
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Name = "translatepoweredByMicrosoftToolStripMenuItem";
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Size = new System.Drawing.Size(414, 22);
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Text = "Translate (powered by Microsoft)...";
|
||||
this.translatepoweredByMicrosoftToolStripMenuItem.Click += new System.EventHandler(this.translatepoweredByMicrosoftToolStripMenuItem_Click);
|
||||
//
|
||||
// translateFromSwedishToDanishToolStripMenuItem
|
||||
//
|
||||
this.translateFromSwedishToDanishToolStripMenuItem.Name = "translateFromSwedishToDanishToolStripMenuItem";
|
||||
|
@ -91,6 +91,10 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
Keys _mainAdjustSetStartAndOffsetTheRest = Keys.None;
|
||||
Keys _mainAdjustSetEndAndGotoNext = Keys.None;
|
||||
Keys _mainAdjustInsertViaEndAutoStartAndGoToNext = Keys.None;
|
||||
Keys _mainInsertAfter = Keys.None;
|
||||
Keys _mainInsertBefore = Keys.None;
|
||||
Keys _mainListViewToggleDashes = Keys.None;
|
||||
Keys _waveformVerticalZoom = Keys.None;
|
||||
bool _videoLoadedGoToSubPosAndPause = false;
|
||||
bool _makeHistory = true;
|
||||
string _cutText = string.Empty;
|
||||
@ -1434,11 +1438,11 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
var fi = new FileInfo(fileName);
|
||||
|
||||
if (Path.GetExtension(fileName).ToLower() == ".ts" && fi.Length > 10000)
|
||||
{
|
||||
//ImportSubtitleFromTransportStream();
|
||||
//return;
|
||||
}
|
||||
//if (Path.GetExtension(fileName).ToLower() == ".ts" && fi.Length > 10000 && IsTransportStream(fileName)) //TODO: Also check mpg, mpeg - and file header!
|
||||
//{
|
||||
// ImportSubtitleFromTransportStream();
|
||||
// return;
|
||||
//}
|
||||
|
||||
if ((Path.GetExtension(fileName).ToLower() == ".mp4" || Path.GetExtension(fileName).ToLower() == ".m4v" || Path.GetExtension(fileName).ToLower() == ".3gp")
|
||||
&& fi.Length > 10000)
|
||||
@ -1699,26 +1703,37 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsTransportStream(string fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var buffer = new byte[1];
|
||||
var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read) { Position = 0 };
|
||||
fs.Read(buffer, 0, buffer.Length);
|
||||
fs.Close();
|
||||
return buffer[0] == 0x47; // 47hex (71 dec) == TS sync byte
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetUndockedWindowsTitle()
|
||||
{
|
||||
string title = Configuration.Settings.Language.General.NoVideoLoaded;
|
||||
if (!string.IsNullOrEmpty(_videoFileName))
|
||||
title = Path.GetFileNameWithoutExtension(_videoFileName);
|
||||
|
||||
try //TODO: Remove in 3.2 final
|
||||
{
|
||||
if (_videoControlsUnDocked != null && !_videoControlsUnDocked.IsDisposed)
|
||||
_videoControlsUnDocked.Text = string.Format(Configuration.Settings.Language.General.ControlsWindowTitle, title);
|
||||
if (_videoControlsUnDocked != null && !_videoControlsUnDocked.IsDisposed)
|
||||
_videoControlsUnDocked.Text = string.Format(Configuration.Settings.Language.General.ControlsWindowTitle, title);
|
||||
|
||||
if (_videoPlayerUnDocked != null && !_videoPlayerUnDocked.IsDisposed)
|
||||
_videoPlayerUnDocked.Text = string.Format(Configuration.Settings.Language.General.VideoWindowTitle, title);
|
||||
if (_videoPlayerUnDocked != null && !_videoPlayerUnDocked.IsDisposed)
|
||||
_videoPlayerUnDocked.Text = string.Format(Configuration.Settings.Language.General.VideoWindowTitle, title);
|
||||
|
||||
if (_waveFormUnDocked != null && !_waveFormUnDocked.IsDisposed)
|
||||
_waveFormUnDocked.Text = string.Format(Configuration.Settings.Language.General.AudioWindowTitle, title);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
if (_waveFormUnDocked != null && !_waveFormUnDocked.IsDisposed)
|
||||
_waveFormUnDocked.Text = string.Format(Configuration.Settings.Language.General.AudioWindowTitle, title);
|
||||
}
|
||||
|
||||
private void ImportAndOcrBdnXml(string fileName, BdnXml bdnXml, List<string> list)
|
||||
@ -5818,16 +5833,69 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private void ImportSubtitleFromTransportStream()
|
||||
private bool ImportSubtitleFromTransportStream()
|
||||
{
|
||||
//TransportStreamParser tsParser = new TransportStreamParser();
|
||||
//tsParser.ParseTsFile(openFileDialog1.FileName);
|
||||
var tsParser = new Nikse.SubtitleEdit.Logic.TransportStream.TransportStreamParser();
|
||||
tsParser.ParseTsFile(openFileDialog1.FileName);
|
||||
|
||||
//var vobSubOcr = new VobSubOcr();
|
||||
//vobSubOcr.Initialize(tsParser.MergeVobSubPacks(), null, Configuration.Settings.VobSubOcr, null);
|
||||
//if (vobSubOcr.ShowDialog(this) == DialogResult.OK)
|
||||
//{
|
||||
//}
|
||||
if (tsParser.SubtitlePacketIds.Count == 0)
|
||||
{
|
||||
MessageBox.Show(_language.NoSubtitlesFound);
|
||||
return false;
|
||||
}
|
||||
|
||||
var log = new StringBuilder();
|
||||
List<BluRaySupPicture> subtitles = new List<BluRaySupPicture>();
|
||||
var pesList = tsParser.GetSubtitlePesPackets(tsParser.SubtitlePacketIds[0]);
|
||||
foreach (var sp in pesList)
|
||||
{
|
||||
if (sp.DataBuffer != null)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(sp.DataBuffer);
|
||||
var list = BluRaySupParser.ParseBluRaySup(ms, log, true);
|
||||
foreach (var sup in list)
|
||||
{
|
||||
//sup.StartTime = p.StartMilliseconds;
|
||||
//sup.EndTime = p.EndMilliseconds;
|
||||
subtitles.Add(sup);
|
||||
|
||||
// fix overlapping
|
||||
//if (subtitles.Count > 1 && sub[subtitles.Count - 2].EndMilliseconds > sub[subtitles.Count - 1].StartMilliseconds)
|
||||
// subtitles[subtitles.Count - 2].EndTime = subtitles[subtitles.Count - 1].StartTime - 1;
|
||||
}
|
||||
ms.Close();
|
||||
}
|
||||
}
|
||||
|
||||
var formSubOcr = new VobSubOcr();
|
||||
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr);
|
||||
if (formSubOcr.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
MakeHistoryForUndo(_language.BeforeImportingDvdSubtitle);
|
||||
|
||||
_subtitle.Paragraphs.Clear();
|
||||
SetCurrentFormat(new SubRip().FriendlyName);
|
||||
_subtitle.WasLoadedWithFrameNumbers = false;
|
||||
_subtitle.CalculateFrameNumbersFromTimeCodes(CurrentFrameRate);
|
||||
foreach (Paragraph p in formSubOcr.SubtitleFromOcr.Paragraphs)
|
||||
{
|
||||
_subtitle.Paragraphs.Add(p);
|
||||
}
|
||||
|
||||
ShowSource();
|
||||
SubtitleListview1.Fill(_subtitle, _subtitleAlternate);
|
||||
_change = true;
|
||||
_subtitleListViewIndex = -1;
|
||||
SubtitleListview1.FirstVisibleIndex = -1;
|
||||
SubtitleListview1.SelectIndexAndEnsureVisible(0);
|
||||
|
||||
_fileName = string.Empty;
|
||||
Text = Title;
|
||||
|
||||
Configuration.Settings.Save();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ImportSubtitleFromMp4(string fileName)
|
||||
@ -6437,18 +6505,28 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
bool inListView = tabControlSubtitle.SelectedIndex == TabControlListView;
|
||||
|
||||
if (e.Modifiers == Keys.Alt && e.KeyCode == Keys.Insert && inListView)
|
||||
if (audioVisualizer != null && audioVisualizer.Visible)
|
||||
{
|
||||
InsertAfter();
|
||||
e.SuppressKeyPress = true;
|
||||
textBoxListViewText.Focus();
|
||||
if (e.KeyData == _waveformVerticalZoom)
|
||||
{
|
||||
if (audioVisualizer.VerticalZoomPercent > 0.2)
|
||||
audioVisualizer.VerticalZoomPercent -= 0.1;
|
||||
else
|
||||
audioVisualizer.VerticalZoomPercent = 1;
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
}
|
||||
else if (e.Modifiers == (Keys.Shift | Keys.Control) && e.KeyCode == Keys.Insert && inListView)
|
||||
else if (_mainInsertBefore == e.KeyData && inListView)
|
||||
{
|
||||
InsertBefore();
|
||||
e.SuppressKeyPress = true;
|
||||
textBoxListViewText.Focus();
|
||||
}
|
||||
else if (_mainListViewToggleDashes == e.KeyData && inListView)
|
||||
{
|
||||
ToggleDashes();
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z)
|
||||
{
|
||||
ShowHistoryforUndoToolStripMenuItemClick(null, null);
|
||||
@ -6871,6 +6949,74 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
// put new entries above tabs
|
||||
}
|
||||
|
||||
private void ToggleDashes()
|
||||
{
|
||||
int index = FirstSelectedIndex;
|
||||
if (index >= 0)
|
||||
{
|
||||
bool hasStartDash = false;
|
||||
var p = _subtitle.Paragraphs[index];
|
||||
string[] lines = p.Text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Trim().StartsWith("-") || line.Trim().StartsWith("<i>-") || line.Trim().StartsWith("<i> -"))
|
||||
hasStartDash = true;
|
||||
}
|
||||
if (hasStartDash)
|
||||
RemoveDashes();
|
||||
else
|
||||
AddDashes();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDashes()
|
||||
{
|
||||
foreach (int index in SubtitleListview1.SelectedIndices)
|
||||
{
|
||||
var p = _subtitle.Paragraphs[index];
|
||||
string[] lines = p.Text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
||||
var sb = new StringBuilder();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Trim().StartsWith("-") || line.Trim().StartsWith("<i>-") || line.Trim().StartsWith("<i> -"))
|
||||
sb.AppendLine(line);
|
||||
else if (line.Trim().StartsWith("<i>") && line.Trim().Length > 3)
|
||||
sb.AppendLine("<i>-" + line.Substring(3));
|
||||
else
|
||||
sb.AppendLine("- " + line);
|
||||
}
|
||||
string text = sb.ToString().Trim(); ;
|
||||
_subtitle.Paragraphs[index].Text = text;
|
||||
SubtitleListview1.SetText(index, text);
|
||||
if (index == _subtitleListViewIndex)
|
||||
textBoxListViewText.Text = text;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveDashes()
|
||||
{
|
||||
foreach (int index in SubtitleListview1.SelectedIndices)
|
||||
{
|
||||
var p = _subtitle.Paragraphs[index];
|
||||
string[] lines = p.Text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
||||
var sb = new StringBuilder();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Trim().StartsWith("-"))
|
||||
sb.AppendLine(line.TrimStart().TrimStart('-').TrimStart());
|
||||
else if (line.Trim().StartsWith("<i>-") || line.Trim().StartsWith("<i> -"))
|
||||
sb.AppendLine("<i>" + line.TrimStart().Substring(3).TrimStart().TrimStart('-').TrimStart());
|
||||
else
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
string text = sb.ToString().Trim(); ;
|
||||
_subtitle.Paragraphs[index].Text = text;
|
||||
SubtitleListview1.SetText(index, text);
|
||||
if (index == _subtitleListViewIndex)
|
||||
textBoxListViewText.Text = text;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTitle()
|
||||
{
|
||||
Text = Title;
|
||||
@ -6981,12 +7127,12 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
ToolStripMenuItemDeleteClick(null, null);
|
||||
}
|
||||
else if (e.Modifiers == Keys.Shift && e.KeyCode == Keys.Insert)
|
||||
else if (e.KeyData == _mainInsertBefore)
|
||||
{
|
||||
InsertBefore();
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
else if (e.KeyCode == Keys.Insert)
|
||||
else if (e.KeyData == _mainInsertAfter)
|
||||
{
|
||||
InsertAfter();
|
||||
e.SuppressKeyPress = true;
|
||||
@ -8992,10 +9138,14 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
toolStripMenuItemAdjustAllTimes.ShortcutKeys = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainSynchronizationAdjustTimes);
|
||||
italicToolStripMenuItem.ShortcutKeys = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainListViewItalic);
|
||||
_mainListViewToggleDashes = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainListViewToggleDashes);
|
||||
italicToolStripMenuItem1.ShortcutKeys = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainTextBoxItalic);
|
||||
_mainAdjustSetStartAndOffsetTheRest = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetStartAndOffsetTheRest);
|
||||
_mainAdjustSetEndAndGotoNext = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetEndAndGotoNext);
|
||||
_mainAdjustInsertViaEndAutoStartAndGoToNext = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext);
|
||||
_mainInsertAfter = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainInsertAfter);
|
||||
_mainInsertBefore = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainInsertBefore);
|
||||
_waveformVerticalZoom = Utilities.GetKeys(Configuration.Settings.Shortcuts.WaveformVerticalZoom);
|
||||
}
|
||||
|
||||
private void LoadPlugins()
|
||||
|
@ -681,7 +681,7 @@
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
||||
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD2
|
||||
CAAAAk1TRnQBSQFMAgEBAgEAAYgBCwGIAQsBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
||||
CAAAAk1TRnQBSQFMAgEBAgEAAagBCwGoAQsBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
||||
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
|
||||
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
|
||||
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
|
||||
|
@ -51,7 +51,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
labelMaxCharacters.Text = Configuration.Settings.Language.MergedShortLines.MaximumCharacters;
|
||||
labelMaxMillisecondsBetweenLines.Text = Configuration.Settings.Language.MergedShortLines.MaximumMillisecondsBetween;
|
||||
|
||||
checkBoxOnlyContinuationLines.Visible = !string.IsNullOrEmpty(Configuration.Settings.Language.MergedShortLines.OnlyMergeContinuationLines); //TODO: Remove in se 3.2
|
||||
checkBoxOnlyContinuationLines.Text = Configuration.Settings.Language.MergedShortLines.OnlyMergeContinuationLines;
|
||||
|
||||
listViewFixes.Columns[0].Text = Configuration.Settings.Language.General.Apply;
|
||||
|
@ -423,10 +423,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
comboBoxSpectrogramAppearance.SelectedIndex = 1;
|
||||
|
||||
|
||||
//<MainFileNew>Control+N</MainFileNew>
|
||||
//<MainFileOpen>Control+O</MainFileOpen>
|
||||
//<MainFileSave>Control+S</MainFileSave>
|
||||
//<MainFileSaveAs>Control+Shift+S</MainFileSaveAs>
|
||||
TreeNode fileNode = new TreeNode(Configuration.Settings.Language.Main.Menu.File.Title);
|
||||
fileNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.File.New + GetShortcutText(Configuration.Settings.Shortcuts.MainFileNew));
|
||||
fileNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.File.Open + GetShortcutText(Configuration.Settings.Shortcuts.MainFileOpen));
|
||||
@ -435,10 +431,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
fileNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.File.Export + " -> " + Configuration.Settings.Language.Main.Menu.File.ExportEbu + GetShortcutText(Configuration.Settings.Shortcuts.MainFileExportEbu));
|
||||
treeViewShortcuts.Nodes.Add(fileNode);
|
||||
|
||||
//<MainEditFind>Control+F</MainEditFind>
|
||||
//<MainEditFindNext>F3</MainEditFindNext>
|
||||
//<MainEditReplace>Control+H</MainEditReplace>
|
||||
//<MainEditGoToLineNumber>Control+G</MainEditGoToLineNumber>
|
||||
TreeNode editNode = new TreeNode(Configuration.Settings.Language.Main.Menu.Edit.Title);
|
||||
editNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Edit.Find + GetShortcutText(Configuration.Settings.Shortcuts.MainEditFind));
|
||||
editNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Edit.FindNext + GetShortcutText(Configuration.Settings.Shortcuts.MainEditFindNext));
|
||||
@ -450,23 +442,22 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
toolsNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Tools.FixCommonErrors + GetShortcutText(Configuration.Settings.Shortcuts.MainToolsFixCommonErrors));
|
||||
treeViewShortcuts.Nodes.Add(toolsNode);
|
||||
|
||||
//<MainVideoShowHideVideo>Control+Q</MainVideoShowHideVideo>
|
||||
TreeNode videoNode = new TreeNode(Configuration.Settings.Language.Main.Menu.Video.Title);
|
||||
videoNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Video.ShowHideVideo + GetShortcutText(Configuration.Settings.Shortcuts.MainVideoShowHideVideo));
|
||||
videoNode.Nodes.Add(Configuration.Settings.Language.Settings.ToggleDockUndockOfVideoControls + GetShortcutText(Configuration.Settings.Shortcuts.MainVideoToggleVideoControls));
|
||||
treeViewShortcuts.Nodes.Add(videoNode);
|
||||
|
||||
//<MainSynchronizationAdjustTimes>Control+Shift+A</MainSynchronizationAdjustTimes>
|
||||
TreeNode SyncNode = new TreeNode(Configuration.Settings.Language.Main.Menu.Synchronization.Title);
|
||||
SyncNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Synchronization.AdjustAllTimes + GetShortcutText(Configuration.Settings.Shortcuts.MainSynchronizationAdjustTimes));
|
||||
treeViewShortcuts.Nodes.Add(SyncNode);
|
||||
|
||||
//<MainListViewItalic>Control+G</MainListViewItalic>
|
||||
TreeNode ListViewNode = new TreeNode(Configuration.Settings.Language.Main.Controls.ListView);
|
||||
ListViewNode.Nodes.Add(Configuration.Settings.Language.General.Italic + GetShortcutText(Configuration.Settings.Shortcuts.MainListViewItalic));
|
||||
ListViewNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.ContextMenu.InsertAfter + GetShortcutText(Configuration.Settings.Shortcuts.MainInsertAfter));
|
||||
ListViewNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.ContextMenu.InsertBefore + GetShortcutText(Configuration.Settings.Shortcuts.MainInsertBefore));
|
||||
ListViewNode.Nodes.Add("Toggle dashes" + GetShortcutText(Configuration.Settings.Shortcuts.MainListViewToggleDashes));
|
||||
treeViewShortcuts.Nodes.Add(ListViewNode);
|
||||
|
||||
//<MainTextBoxItalic>Control+I</MainTextBoxItalic>
|
||||
TreeNode TextBoxNode = new TreeNode(Configuration.Settings.Language.Settings.TextBox);
|
||||
TextBoxNode.Nodes.Add(Configuration.Settings.Language.General.Italic + GetShortcutText(Configuration.Settings.Shortcuts.MainTextBoxItalic));
|
||||
treeViewShortcuts.Nodes.Add(TextBoxNode);
|
||||
@ -477,6 +468,11 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
adjustNode.Nodes.Add(Configuration.Settings.Language.Settings.AdjustViaEndAutoStartAndGoToNext + GetShortcutText(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext));
|
||||
treeViewShortcuts.Nodes.Add(adjustNode);
|
||||
|
||||
TreeNode audioVisualizerNode = new TreeNode(Configuration.Settings.Language.Settings.WaveformAndSpectrogram);
|
||||
audioVisualizerNode.Nodes.Add("Vertical zoom" + GetShortcutText(Configuration.Settings.Shortcuts.WaveformVerticalZoom));
|
||||
treeViewShortcuts.Nodes.Add(audioVisualizerNode);
|
||||
|
||||
|
||||
foreach (TreeNode node in treeViewShortcuts.Nodes)
|
||||
{
|
||||
node.Text = node.Text.Replace("&", string.Empty);
|
||||
@ -886,6 +882,12 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
string text = node.Text.Substring(0, node.Text.IndexOf("[")).Trim();
|
||||
if (text == Configuration.Settings.Language.General.Italic.Replace("&", string.Empty))
|
||||
Configuration.Settings.Shortcuts.MainListViewItalic = GetShortcut(node.Text);
|
||||
else if (text == Configuration.Settings.Language.Main.Menu.ContextMenu.InsertAfter.Replace("&", string.Empty))
|
||||
Configuration.Settings.Shortcuts.MainInsertAfter = GetShortcut(node.Text);
|
||||
else if (text == Configuration.Settings.Language.Main.Menu.ContextMenu.InsertBefore.Replace("&", string.Empty))
|
||||
Configuration.Settings.Shortcuts.MainInsertBefore = GetShortcut(node.Text);
|
||||
else if (text == ("Toggle dashes").Replace("&", string.Empty))
|
||||
Configuration.Settings.Shortcuts.MainListViewToggleDashes = GetShortcut(node.Text);
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,6 +917,17 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
}
|
||||
|
||||
//Audio-visualizer
|
||||
foreach (TreeNode node in treeViewShortcuts.Nodes[8].Nodes)
|
||||
{
|
||||
if (node.Text.Contains("["))
|
||||
{
|
||||
string text = node.Text.Substring(0, node.Text.IndexOf("[")).Trim();
|
||||
if (text == ("Vertical zoom").Replace("&", string.Empty))
|
||||
Configuration.Settings.Shortcuts.WaveformVerticalZoom = GetShortcut(node.Text);
|
||||
}
|
||||
}
|
||||
|
||||
Configuration.Settings.Save();
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
public WaveFormUnDocked()
|
||||
{
|
||||
// TODO: Complete member initialization
|
||||
}
|
||||
|
||||
private void WaveFormUnDocked_FormClosing(object sender, FormClosingEventArgs e)
|
||||
|
1283
src/Languages/de-DE.xml
Normal file
1283
src/Languages/de-DE.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -427,10 +427,14 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
public string MainVideoToggleVideoControls { get; set; }
|
||||
public string MainSynchronizationAdjustTimes { get; set; }
|
||||
public string MainListViewItalic { get; set; }
|
||||
public string MainListViewToggleDashes { get; set; }
|
||||
public string MainTextBoxItalic { get; set; }
|
||||
public string MainAdjustSetStartAndOffsetTheRest { get; set; }
|
||||
public string MainAdjustSetEndAndGotoNext { get; set; }
|
||||
public string MainAdjustViaEndAutoStartAndGoToNext { get; set; }
|
||||
public string MainInsertAfter { get; set; }
|
||||
public string MainInsertBefore { get; set; }
|
||||
public string WaveformVerticalZoom { get; set; }
|
||||
|
||||
public Shortcuts()
|
||||
{
|
||||
@ -451,6 +455,9 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
MainAdjustSetStartAndOffsetTheRest = "Control+Space";
|
||||
MainAdjustSetEndAndGotoNext = "Shift+Space";
|
||||
MainAdjustViaEndAutoStartAndGoToNext = "Shift+End";
|
||||
MainInsertAfter = "Alt+Ins";
|
||||
MainInsertBefore = "Control+Shift+Ins";
|
||||
WaveformVerticalZoom = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,10 +537,8 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
|
||||
public void Save()
|
||||
{
|
||||
//slow
|
||||
//Serialize(Configuration.BaseDirectory + "Settings.xml", this);
|
||||
//this is too slow: Serialize(Configuration.BaseDirectory + "Settings.xml", this);
|
||||
|
||||
//Fast - TODO: Fix in release
|
||||
CustomSerialize(Configuration.SettingsFileName, this);
|
||||
}
|
||||
|
||||
@ -553,11 +558,9 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
{
|
||||
try
|
||||
{
|
||||
//TODO: Fix in release
|
||||
settings = CustomDeserialize(settingsFileName); // 15 msecs
|
||||
|
||||
//too slow... :(
|
||||
//settings = Deserialize(Configuration.BaseDirectory + "Settings.xml"); // 688 msecs
|
||||
//too slow... :( - settings = Deserialize(Configuration.BaseDirectory + "Settings.xml"); // 688 msecs
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -1138,6 +1141,9 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
subNode = node.SelectSingleNode("MainListViewItalic");
|
||||
if (subNode != null)
|
||||
settings.Shortcuts.MainListViewItalic = subNode.InnerText;
|
||||
subNode = node.SelectSingleNode("MainListViewToggleDashes");
|
||||
if (subNode != null)
|
||||
settings.Shortcuts.MainListViewToggleDashes = subNode.InnerText;
|
||||
subNode = node.SelectSingleNode("MainTextBoxItalic");
|
||||
if (subNode != null)
|
||||
settings.Shortcuts.MainTextBoxItalic = subNode.InnerText;
|
||||
@ -1150,6 +1156,15 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
subNode = node.SelectSingleNode("MainAdjustViaEndAutoStartAndGoToNext");
|
||||
if (subNode != null)
|
||||
settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext = subNode.InnerText;
|
||||
subNode = node.SelectSingleNode("MainInsertAfter");
|
||||
if (subNode != null)
|
||||
settings.Shortcuts.MainInsertAfter = subNode.InnerText;
|
||||
subNode = node.SelectSingleNode("MainInsertBefore");
|
||||
if (subNode != null)
|
||||
settings.Shortcuts.MainInsertBefore = subNode.InnerText;
|
||||
subNode = node.SelectSingleNode("WaveformVerticalZoom");
|
||||
if (subNode != null)
|
||||
settings.Shortcuts.WaveformVerticalZoom = subNode.InnerText;
|
||||
}
|
||||
|
||||
settings.RemoveTextForHearingImpaired = new RemoveTextForHearingImpairedSettings();
|
||||
@ -1410,10 +1425,14 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
textWriter.WriteElementString("MainVideoToggleVideoControls", settings.Shortcuts.MainVideoToggleVideoControls);
|
||||
textWriter.WriteElementString("MainSynchronizationAdjustTimes", settings.Shortcuts.MainSynchronizationAdjustTimes);
|
||||
textWriter.WriteElementString("MainListViewItalic", settings.Shortcuts.MainListViewItalic);
|
||||
textWriter.WriteElementString("MainListViewToggleDashes", settings.Shortcuts.MainListViewToggleDashes);
|
||||
textWriter.WriteElementString("MainTextBoxItalic", settings.Shortcuts.MainTextBoxItalic);
|
||||
textWriter.WriteElementString("MainAdjustSetStartAndOffsetTheRest", settings.Shortcuts.MainAdjustSetStartAndOffsetTheRest);
|
||||
textWriter.WriteElementString("MainAdjustSetEndAndGotoNext", settings.Shortcuts.MainAdjustSetEndAndGotoNext);
|
||||
textWriter.WriteElementString("MainAdjustViaEndAutoStartAndGoToNext", settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext);
|
||||
textWriter.WriteElementString("MainInsertAfter", settings.Shortcuts.MainInsertAfter);
|
||||
textWriter.WriteElementString("MainInsertBefore", settings.Shortcuts.MainInsertBefore);
|
||||
textWriter.WriteElementString("WaveformVerticalZoom", settings.Shortcuts.WaveformVerticalZoom);
|
||||
textWriter.WriteEndElement();
|
||||
|
||||
textWriter.WriteStartElement("RemoveTextForHearingImpaired", "");
|
||||
|
109
src/Logic/TransportStream/AdaptationField.cs
Normal file
109
src/Logic/TransportStream/AdaptationField.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.TransportStream
|
||||
{
|
||||
public class AdaptationField
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the adaptation field immediately following the Length
|
||||
/// </summary>
|
||||
public int Length { get; set; }
|
||||
|
||||
public bool DiscontinuityIndicator { get; set; }
|
||||
public bool RandomAccessIndicator { get; set; }
|
||||
public bool ElementaryStreamPriorityIndicator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// '1' indicates that the adaptation field contains a PCR field coded in two parts
|
||||
/// </summary>
|
||||
public bool PcrFlag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// '1' indicates that the adaptation field contains an OPCR field coded in two parts
|
||||
/// </summary>
|
||||
public bool OpcrFlag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// '1' indicates that a splice countdown field shall be present in the associated adaptation field
|
||||
/// </summary>
|
||||
public bool SplicingPointFlag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 1' indicates that the adaptation field contains one or more private data bytes
|
||||
/// </summary>
|
||||
public bool TransportPrivateDataFlag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// '1' indicates the presence of an adaptation field extension
|
||||
/// </summary>
|
||||
public bool AdaptationFieldExtensionFlag { get; set; }
|
||||
|
||||
public int ProgramClockReferenceBase { get; set; }
|
||||
public int ProgramClockReferenceExtension { get; set; }
|
||||
|
||||
public int OriginalProgramClockReferenceBase { get; set; }
|
||||
public int OriginalProgramClockReferenceExtension { get; set; }
|
||||
|
||||
public int SpliceCountdown { get; set; }
|
||||
|
||||
public int TransportPrivateDataLength { get; set; }
|
||||
public byte[] TransportPrivateData { get; set; }
|
||||
|
||||
public int AdaptationFieldExtensionLength { get; set; }
|
||||
|
||||
|
||||
public AdaptationField(byte[] packetBuffer)
|
||||
{
|
||||
Length = packetBuffer[4];
|
||||
DiscontinuityIndicator = 1 == packetBuffer[5] >> 7;
|
||||
RandomAccessIndicator = 1 == (packetBuffer[5] & 64); // and with 01000000 to get second byte
|
||||
ElementaryStreamPriorityIndicator = 1 == (packetBuffer[5] & 32); // and with 00100000 to get third byte
|
||||
PcrFlag = 1 == (packetBuffer[5] & 16); // and with 00010000 to get fourth byte
|
||||
OpcrFlag = 1 == (packetBuffer[5] & 8); // and with 00001000 to get fifth byte
|
||||
SplicingPointFlag = 1 == (packetBuffer[5] & 4); // and with 00000100 to get sixth byte
|
||||
TransportPrivateDataFlag = 1 == (packetBuffer[5] & 2); // and with 00000100 to get seventh byte
|
||||
AdaptationFieldExtensionFlag = 1 == (packetBuffer[5] & 1); // and with 00000010 to get 8th byte
|
||||
|
||||
int index = 6;
|
||||
if (PcrFlag)
|
||||
{
|
||||
ProgramClockReferenceBase = (packetBuffer[index] * 256 + packetBuffer[index + 1]) << 1;
|
||||
ProgramClockReferenceBase += packetBuffer[index + 2] >> 7;
|
||||
ProgramClockReferenceExtension = (packetBuffer[index + 2] & Helper.B00000001) * 256 + packetBuffer[index + 3];
|
||||
index += 4;
|
||||
}
|
||||
|
||||
if (OpcrFlag)
|
||||
{
|
||||
OriginalProgramClockReferenceBase = (packetBuffer[index] * 256 + packetBuffer[index + 1]) << 1;
|
||||
OriginalProgramClockReferenceBase += packetBuffer[index + 2] >> 7;
|
||||
OriginalProgramClockReferenceExtension = (packetBuffer[index + 2] & Helper.B00000001) * 256 + packetBuffer[index + 3];
|
||||
index += 4;
|
||||
}
|
||||
|
||||
if (SplicingPointFlag)
|
||||
{
|
||||
SpliceCountdown = packetBuffer[index];
|
||||
index++;
|
||||
}
|
||||
|
||||
if (TransportPrivateDataFlag)
|
||||
{
|
||||
TransportPrivateDataLength = packetBuffer[index];
|
||||
index++;
|
||||
TransportPrivateData = new byte[TransportPrivateDataLength];
|
||||
Buffer.BlockCopy(packetBuffer, index, TransportPrivateData, 0, TransportPrivateDataLength);
|
||||
index += TransportPrivateDataLength;
|
||||
}
|
||||
|
||||
if (AdaptationFieldExtensionFlag)
|
||||
{
|
||||
AdaptationFieldExtensionLength = packetBuffer[index];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
329
src/Logic/TransportStream/Helper.cs
Normal file
329
src/Logic/TransportStream/Helper.cs
Normal file
@ -0,0 +1,329 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.TransportStream
|
||||
{
|
||||
public static class Helper
|
||||
{
|
||||
|
||||
#region Binary constants
|
||||
public const int B00000000 = 0;
|
||||
public const int B00000001 = 1;
|
||||
public const int B00000010 = 2;
|
||||
public const int B00000011 = 3;
|
||||
public const int B00000100 = 4;
|
||||
public const int B00000101 = 5;
|
||||
public const int B00000110 = 6;
|
||||
public const int B00000111 = 7;
|
||||
public const int B00001000 = 8;
|
||||
public const int B00001001 = 9;
|
||||
public const int B00001010 = 10;
|
||||
public const int B00001011 = 11;
|
||||
public const int B00001100 = 12;
|
||||
public const int B00001101 = 13;
|
||||
public const int B00001110 = 14;
|
||||
public const int B00001111 = 15;
|
||||
public const int B00010000 = 16;
|
||||
public const int B00010001 = 17;
|
||||
public const int B00010010 = 18;
|
||||
public const int B00010011 = 19;
|
||||
public const int B00010100 = 20;
|
||||
public const int B00010101 = 21;
|
||||
public const int B00010110 = 22;
|
||||
public const int B00010111 = 23;
|
||||
public const int B00011000 = 24;
|
||||
public const int B00011001 = 25;
|
||||
public const int B00011010 = 26;
|
||||
public const int B00011011 = 27;
|
||||
public const int B00011100 = 28;
|
||||
public const int B00011101 = 29;
|
||||
public const int B00011110 = 30;
|
||||
public const int B00011111 = 31;
|
||||
public const int B00100000 = 32;
|
||||
public const int B00100001 = 33;
|
||||
public const int B00100010 = 34;
|
||||
public const int B00100011 = 35;
|
||||
public const int B00100100 = 36;
|
||||
public const int B00100101 = 37;
|
||||
public const int B00100110 = 38;
|
||||
public const int B00100111 = 39;
|
||||
public const int B00101000 = 40;
|
||||
public const int B00101001 = 41;
|
||||
public const int B00101010 = 42;
|
||||
public const int B00101011 = 43;
|
||||
public const int B00101100 = 44;
|
||||
public const int B00101101 = 45;
|
||||
public const int B00101110 = 46;
|
||||
public const int B00101111 = 47;
|
||||
public const int B00110000 = 48;
|
||||
public const int B00110001 = 49;
|
||||
public const int B00110010 = 50;
|
||||
public const int B00110011 = 51;
|
||||
public const int B00110100 = 52;
|
||||
public const int B00110101 = 53;
|
||||
public const int B00110110 = 54;
|
||||
public const int B00110111 = 55;
|
||||
public const int B00111000 = 56;
|
||||
public const int B00111001 = 57;
|
||||
public const int B00111010 = 58;
|
||||
public const int B00111011 = 59;
|
||||
public const int B00111100 = 60;
|
||||
public const int B00111101 = 61;
|
||||
public const int B00111110 = 62;
|
||||
public const int B00111111 = 63;
|
||||
public const int B01000000 = 64;
|
||||
public const int B01000001 = 65;
|
||||
public const int B01000010 = 66;
|
||||
public const int B01000011 = 67;
|
||||
public const int B01000100 = 68;
|
||||
public const int B01000101 = 69;
|
||||
public const int B01000110 = 70;
|
||||
public const int B01000111 = 71;
|
||||
public const int B01001000 = 72;
|
||||
public const int B01001001 = 73;
|
||||
public const int B01001010 = 74;
|
||||
public const int B01001011 = 75;
|
||||
public const int B01001100 = 76;
|
||||
public const int B01001101 = 77;
|
||||
public const int B01001110 = 78;
|
||||
public const int B01001111 = 79;
|
||||
public const int B01010000 = 80;
|
||||
public const int B01010001 = 81;
|
||||
public const int B01010010 = 82;
|
||||
public const int B01010011 = 83;
|
||||
public const int B01010100 = 84;
|
||||
public const int B01010101 = 85;
|
||||
public const int B01010110 = 86;
|
||||
public const int B01010111 = 87;
|
||||
public const int B01011000 = 88;
|
||||
public const int B01011001 = 89;
|
||||
public const int B01011010 = 90;
|
||||
public const int B01011011 = 91;
|
||||
public const int B01011100 = 92;
|
||||
public const int B01011101 = 93;
|
||||
public const int B01011110 = 94;
|
||||
public const int B01011111 = 95;
|
||||
public const int B01100000 = 96;
|
||||
public const int B01100001 = 97;
|
||||
public const int B01100010 = 98;
|
||||
public const int B01100011 = 99;
|
||||
public const int B01100100 = 100;
|
||||
public const int B01100101 = 101;
|
||||
public const int B01100110 = 102;
|
||||
public const int B01100111 = 103;
|
||||
public const int B01101000 = 104;
|
||||
public const int B01101001 = 105;
|
||||
public const int B01101010 = 106;
|
||||
public const int B01101011 = 107;
|
||||
public const int B01101100 = 108;
|
||||
public const int B01101101 = 109;
|
||||
public const int B01101110 = 110;
|
||||
public const int B01101111 = 111;
|
||||
public const int B01110000 = 112;
|
||||
public const int B01110001 = 113;
|
||||
public const int B01110010 = 114;
|
||||
public const int B01110011 = 115;
|
||||
public const int B01110100 = 116;
|
||||
public const int B01110101 = 117;
|
||||
public const int B01110110 = 118;
|
||||
public const int B01110111 = 119;
|
||||
public const int B01111000 = 120;
|
||||
public const int B01111001 = 121;
|
||||
public const int B01111010 = 122;
|
||||
public const int B01111011 = 123;
|
||||
public const int B01111100 = 124;
|
||||
public const int B01111101 = 125;
|
||||
public const int B01111110 = 126;
|
||||
public const int B01111111 = 127;
|
||||
public const int B10000000 = 128;
|
||||
public const int B10000001 = 129;
|
||||
public const int B10000010 = 130;
|
||||
public const int B10000011 = 131;
|
||||
public const int B10000100 = 132;
|
||||
public const int B10000101 = 133;
|
||||
public const int B10000110 = 134;
|
||||
public const int B10000111 = 135;
|
||||
public const int B10001000 = 136;
|
||||
public const int B10001001 = 137;
|
||||
public const int B10001010 = 138;
|
||||
public const int B10001011 = 139;
|
||||
public const int B10001100 = 140;
|
||||
public const int B10001101 = 141;
|
||||
public const int B10001110 = 142;
|
||||
public const int B10001111 = 143;
|
||||
public const int B10010000 = 144;
|
||||
public const int B10010001 = 145;
|
||||
public const int B10010010 = 146;
|
||||
public const int B10010011 = 147;
|
||||
public const int B10010100 = 148;
|
||||
public const int B10010101 = 149;
|
||||
public const int B10010110 = 150;
|
||||
public const int B10010111 = 151;
|
||||
public const int B10011000 = 152;
|
||||
public const int B10011001 = 153;
|
||||
public const int B10011010 = 154;
|
||||
public const int B10011011 = 155;
|
||||
public const int B10011100 = 156;
|
||||
public const int B10011101 = 157;
|
||||
public const int B10011110 = 158;
|
||||
public const int B10011111 = 159;
|
||||
public const int B10100000 = 160;
|
||||
public const int B10100001 = 161;
|
||||
public const int B10100010 = 162;
|
||||
public const int B10100011 = 163;
|
||||
public const int B10100100 = 164;
|
||||
public const int B10100101 = 165;
|
||||
public const int B10100110 = 166;
|
||||
public const int B10100111 = 167;
|
||||
public const int B10101000 = 168;
|
||||
public const int B10101001 = 169;
|
||||
public const int B10101010 = 170;
|
||||
public const int B10101011 = 171;
|
||||
public const int B10101100 = 172;
|
||||
public const int B10101101 = 173;
|
||||
public const int B10101110 = 174;
|
||||
public const int B10101111 = 175;
|
||||
public const int B10110000 = 176;
|
||||
public const int B10110001 = 177;
|
||||
public const int B10110010 = 178;
|
||||
public const int B10110011 = 179;
|
||||
public const int B10110100 = 180;
|
||||
public const int B10110101 = 181;
|
||||
public const int B10110110 = 182;
|
||||
public const int B10110111 = 183;
|
||||
public const int B10111000 = 184;
|
||||
public const int B10111001 = 185;
|
||||
public const int B10111010 = 186;
|
||||
public const int B10111011 = 187;
|
||||
public const int B10111100 = 188;
|
||||
public const int B10111101 = 189;
|
||||
public const int B10111110 = 190;
|
||||
public const int B10111111 = 191;
|
||||
public const int B11000000 = 192;
|
||||
public const int B11000001 = 193;
|
||||
public const int B11000010 = 194;
|
||||
public const int B11000011 = 195;
|
||||
public const int B11000100 = 196;
|
||||
public const int B11000101 = 197;
|
||||
public const int B11000110 = 198;
|
||||
public const int B11000111 = 199;
|
||||
public const int B11001000 = 200;
|
||||
public const int B11001001 = 201;
|
||||
public const int B11001010 = 202;
|
||||
public const int B11001011 = 203;
|
||||
public const int B11001100 = 204;
|
||||
public const int B11001101 = 205;
|
||||
public const int B11001110 = 206;
|
||||
public const int B11001111 = 207;
|
||||
public const int B11010000 = 208;
|
||||
public const int B11010001 = 209;
|
||||
public const int B11010010 = 210;
|
||||
public const int B11010011 = 211;
|
||||
public const int B11010100 = 212;
|
||||
public const int B11010101 = 213;
|
||||
public const int B11010110 = 214;
|
||||
public const int B11010111 = 215;
|
||||
public const int B11011000 = 216;
|
||||
public const int B11011001 = 217;
|
||||
public const int B11011010 = 218;
|
||||
public const int B11011011 = 219;
|
||||
public const int B11011100 = 220;
|
||||
public const int B11011101 = 221;
|
||||
public const int B11011110 = 222;
|
||||
public const int B11011111 = 223;
|
||||
public const int B11100000 = 224;
|
||||
public const int B11100001 = 225;
|
||||
public const int B11100010 = 226;
|
||||
public const int B11100011 = 227;
|
||||
public const int B11100100 = 228;
|
||||
public const int B11100101 = 229;
|
||||
public const int B11100110 = 230;
|
||||
public const int B11100111 = 231;
|
||||
public const int B11101000 = 232;
|
||||
public const int B11101001 = 233;
|
||||
public const int B11101010 = 234;
|
||||
public const int B11101011 = 235;
|
||||
public const int B11101100 = 236;
|
||||
public const int B11101101 = 237;
|
||||
public const int B11101110 = 238;
|
||||
public const int B11101111 = 239;
|
||||
public const int B11110000 = 240;
|
||||
public const int B11110001 = 241;
|
||||
public const int B11110010 = 242;
|
||||
public const int B11110011 = 243;
|
||||
public const int B11110100 = 244;
|
||||
public const int B11110101 = 245;
|
||||
public const int B11110110 = 246;
|
||||
public const int B11110111 = 247;
|
||||
public const int B11111000 = 248;
|
||||
public const int B11111001 = 249;
|
||||
public const int B11111010 = 250;
|
||||
public const int B11111011 = 251;
|
||||
public const int B11111100 = 252;
|
||||
public const int B11111101 = 253;
|
||||
public const int B11111110 = 254;
|
||||
public const int B11111111 = 255;
|
||||
#endregion
|
||||
|
||||
public static string IntToHex(UInt64 value, int digits)
|
||||
{
|
||||
return value.ToString("X").PadLeft(digits, '0');
|
||||
}
|
||||
|
||||
public static string IntToHex(int value, int digits)
|
||||
{
|
||||
return value.ToString("X").PadLeft(digits, '0');
|
||||
}
|
||||
|
||||
public static string IntToBin(long value, int digits)
|
||||
{
|
||||
return Convert.ToString(value, 2).PadLeft(digits, '0');
|
||||
}
|
||||
|
||||
public static UInt32 GetEndian(byte[] buffer, int index, int count)
|
||||
{
|
||||
UInt32 result = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
result = (result << 8) + buffer[index + i];
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int GetLittleEndian32(byte[] buffer, int index)
|
||||
{
|
||||
return ((int)buffer[index + 3] << 24 | (int)buffer[index + 2] << 16 | (int)buffer[index + 1] << 8 | (int)buffer[index + 0]);
|
||||
}
|
||||
|
||||
|
||||
//private int Swap4Bytes(byte[] b)
|
||||
//{
|
||||
// return ((int)b[3] << 24 | (int)b[2] << 16 | (int)b[1] << 8 | (int)b[0]);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Get two bytes word stored in endian order
|
||||
/// </summary>
|
||||
/// <param name="buffer">Byte array</param>
|
||||
/// <param name="index">Index in byte array</param>
|
||||
/// <returns>Word as int</returns>
|
||||
public static int GetEndianWord(byte[] buffer, int index)
|
||||
{
|
||||
if (index +1 < buffer.Length)
|
||||
return (buffer[index] << 8) + buffer[index+1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static string GetBinaryString(byte[] buffer, int index, int count)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (int i=0; i < count; i++)
|
||||
sb.Append(Convert.ToString(buffer[index + i], 2).PadLeft(8, '0'));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static UInt64 GetUInt32FromBinaryString(string binaryValue)
|
||||
{
|
||||
return Convert.ToUInt32(binaryValue, 2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
132
src/Logic/TransportStream/Packet.cs
Normal file
132
src/Logic/TransportStream/Packet.cs
Normal file
@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.TransportStream
|
||||
{
|
||||
/// <summary>
|
||||
/// MPEG transport stream packet
|
||||
/// </summary>
|
||||
public class Packet
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// ID byte of TS Packet
|
||||
/// </summary>
|
||||
public const byte SynchronizationByte = 0x47; // 74 decimal, or 01000111 binary
|
||||
|
||||
/// <summary>
|
||||
/// Null packets can ensure that the stream maintains a constant bitrate. Null packets is to be ignored
|
||||
/// </summary>
|
||||
public const int NullPacketId = 0x1FFF;
|
||||
|
||||
/// <summary>
|
||||
/// Program Association Table: lists all programs available in the transport stream.
|
||||
/// </summary>
|
||||
public const int ProgramAssociationTablePacketId = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public const int ConditionalAccessTablePacketId = 1;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public const int TransportStreamDescriptionTablePacketId = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Set by demodulator if can't correct errors in the stream, to tell the demultiplexer that the packet has an uncorrectable error
|
||||
/// </summary>
|
||||
public bool TransportErrorIndicator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start of PES data or PSI
|
||||
/// </summary>
|
||||
public bool PayloadUnitStartIndicator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Higher priority than other packets with the same PID
|
||||
/// </summary>
|
||||
public bool TransportPriority { get; set; }
|
||||
|
||||
public int PacketId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 1 = Reserved for future use, 10 = Scrambled with even key, 11 = Scrambled with odd key
|
||||
/// </summary>
|
||||
public int ScramblingControl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 1 = no adaptation fields (payload only), 10 = adaptation field only, 11 = adaptation field and payload
|
||||
/// </summary>
|
||||
public int AdaptationFieldControl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Incremented only when a payload is present (AdaptationFieldExist = 10 or 11). Starts at 0.
|
||||
/// </summary>
|
||||
public int ContinuityCounter { get; set; }
|
||||
|
||||
public int AdaptionFieldLength { get; set; }
|
||||
|
||||
public AdaptationField AdaptationField { get; private set; }
|
||||
|
||||
public bool IsNullPacket { get { return PacketId == NullPacketId; } }
|
||||
|
||||
public bool IsProgramAssociationTable { get { return PacketId == ProgramAssociationTablePacketId; } }
|
||||
|
||||
public byte[] Payload { get; private set; }
|
||||
|
||||
public bool IsPrivateStream1
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Payload == null || Payload.Length < 4)
|
||||
return false;
|
||||
|
||||
return Payload[0] == 0 &&
|
||||
Payload[1] == 0 &&
|
||||
Payload[2] == 1 &&
|
||||
Payload[3] == 0xbd; // 0xbd == 189 - MPEG-2 Private stream 1 (non MPEG audio, subpictures)
|
||||
}
|
||||
}
|
||||
|
||||
public ProgramAssociationTable ProgramAssociationTable { get; private set; }
|
||||
|
||||
public Packet(byte[] packetBuffer)
|
||||
{
|
||||
TransportErrorIndicator = 1 == packetBuffer[1] >> 7; // Set by demodulator if can't correct errors in the stream, to tell the demultiplexer that the packet has an uncorrectable error
|
||||
PayloadUnitStartIndicator = 1 == ((packetBuffer[1] & 64) >> 6); // and with 01000000 to get second byte - 1 means start of PES data or PSI otherwise zero
|
||||
TransportPriority = 1 == ((packetBuffer[1] & 32) >> 5); // and with 00100000 to get third byte - 1 means higher priority than other packets with the same PID
|
||||
PacketId = (packetBuffer[1] & 31) * 256 + packetBuffer[2];// and with 00011111 to get last 5 bytes
|
||||
ScramblingControl = packetBuffer[3] >> 6; // '00' = Not scrambled. The following per DVB spec:[12] '01' = Reserved for future use, '10' = Scrambled with even key, '11' = Scrambled with odd key
|
||||
AdaptationFieldControl = (packetBuffer[3] & 48) >> 4; // and with 00110000, 01 = no adaptation fields (payload only), 10 = adaptation field only, 11 = adaptation field and payload
|
||||
ContinuityCounter = packetBuffer[3] & 15;
|
||||
AdaptionFieldLength = AdaptationFieldControl > 1 ? (0xFF & packetBuffer[4]) + 1 : 0;
|
||||
|
||||
if (AdaptationFieldControl == Helper.B00000010 || AdaptationFieldControl == Helper.B00000011)
|
||||
AdaptationField = new AdaptationField(packetBuffer);
|
||||
|
||||
if (AdaptationFieldControl == Helper.B00000001 || AdaptationFieldControl == Helper.B00000011) // Payload exists - binary '01' || '11'
|
||||
{
|
||||
int payloadStart = 4;
|
||||
if (AdaptationField != null)
|
||||
payloadStart += (1 + AdaptationField.Length);
|
||||
|
||||
if (PacketId == ProgramAssociationTablePacketId) // PAT = Program Association Table: lists all programs available in the transport stream.
|
||||
{
|
||||
ProgramAssociationTable = new ProgramAssociationTable(packetBuffer, payloadStart+1); // TODO: what index?
|
||||
}
|
||||
|
||||
//if (PayloadUnitStartIndicator)
|
||||
// payloadStart += packetBuffer[payloadStart];
|
||||
|
||||
// Save payload
|
||||
Payload = new byte[packetBuffer.Length - payloadStart];
|
||||
|
||||
Buffer.BlockCopy(packetBuffer, payloadStart, Payload, 0, Payload.Length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
98
src/Logic/TransportStream/PacketizedElementaryStream.cs
Normal file
98
src/Logic/TransportStream/PacketizedElementaryStream.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.TransportStream
|
||||
{
|
||||
/// <summary>
|
||||
/// http://www.mpucoder.com/DVD/pes-hdr.html
|
||||
/// </summary>
|
||||
public class PacketizedElementaryStream
|
||||
{
|
||||
public const int HeaderLength = 6;
|
||||
public const int Mpeg2HeaderLength = 14;
|
||||
|
||||
public readonly UInt32 StartCode;
|
||||
public readonly int StreamId;
|
||||
public readonly int Length;
|
||||
public readonly int ScramblingControl;
|
||||
public readonly int Priority;
|
||||
public readonly int DataAlignmentIndicator;
|
||||
public readonly int Copyright;
|
||||
public readonly int OriginalOrCopy;
|
||||
public readonly int PresentationTimeStampDecodeTimeStampFlags;
|
||||
public readonly int ElementaryStreamClockReferenceFlag;
|
||||
public readonly int EsRateFlag;
|
||||
public readonly int DsmTrickModeFlag;
|
||||
public readonly int AdditionalCopyInfoFlag;
|
||||
public readonly int CrcFlag;
|
||||
public readonly int ExtensionFlag;
|
||||
public readonly int HeaderDataLength;
|
||||
|
||||
public readonly UInt64? PresentationTimeStamp;
|
||||
public readonly UInt64? DecodeTimeStamp;
|
||||
|
||||
public readonly int? SubPictureStreamId;
|
||||
|
||||
public readonly byte[] DataBuffer;
|
||||
|
||||
public PacketizedElementaryStream(byte[] buffer, int index)
|
||||
{
|
||||
StartCode = Helper.GetEndian(buffer, index + 0, 3);
|
||||
StreamId = buffer[index + 3];
|
||||
Length = Helper.GetEndianWord(buffer, index + 4);
|
||||
|
||||
ScramblingControl = (buffer[index + 6] >> 4) & Helper.B00000011;
|
||||
Priority = buffer[index + 6] & Helper.B00001000;
|
||||
DataAlignmentIndicator = buffer[index + 6] & Helper.B00000100;
|
||||
Copyright = buffer[index + 6] & Helper.B00000010;
|
||||
OriginalOrCopy = buffer[index + 6] & Helper.B00000001;
|
||||
PresentationTimeStampDecodeTimeStampFlags = buffer[index + 7] >> 6;
|
||||
ElementaryStreamClockReferenceFlag = buffer[index + 7] & Helper.B00100000;
|
||||
EsRateFlag = buffer[index + 7] & Helper.B00010000;
|
||||
DsmTrickModeFlag = buffer[index + 7] & Helper.B00001000;
|
||||
AdditionalCopyInfoFlag = buffer[index + 7] & Helper.B00000100;
|
||||
CrcFlag = buffer[index + 7] & Helper.B00001000;
|
||||
ExtensionFlag = buffer[index + 7] & Helper.B00000010;
|
||||
|
||||
HeaderDataLength = buffer[index + 8];
|
||||
|
||||
if (StreamId == 0xBD) // 10111101 binary = 189 decimal = 0xBD hex -> private_stream_1
|
||||
{
|
||||
int id = buffer[index + 9 + HeaderDataLength];
|
||||
if (id >= 0x20 && id <= 0x40) // x3f 0r x40 ?
|
||||
SubPictureStreamId = id;
|
||||
}
|
||||
|
||||
int tempIndex = index + 9;
|
||||
if (PresentationTimeStampDecodeTimeStampFlags == Helper.B00000010 ||
|
||||
PresentationTimeStampDecodeTimeStampFlags == Helper.B00000011)
|
||||
{
|
||||
string bString = Helper.GetBinaryString(buffer, tempIndex, 5);
|
||||
bString = bString.Substring(4, 3) + bString.Substring(8, 15) + bString.Substring(24, 15);
|
||||
PresentationTimeStamp = Convert.ToUInt64(bString, 2);
|
||||
tempIndex += 5;
|
||||
}
|
||||
if (PresentationTimeStampDecodeTimeStampFlags == Helper.B00000011)
|
||||
{
|
||||
string bString = Helper.GetBinaryString(buffer, tempIndex, 5);
|
||||
bString = bString.Substring(4, 3) + bString.Substring(8, 15) + bString.Substring(24, 15);
|
||||
DecodeTimeStamp = Convert.ToUInt64(bString, 2);
|
||||
}
|
||||
|
||||
int dataIndex = index + HeaderDataLength + 24 - Mpeg2HeaderLength;
|
||||
int dataSize = Length - (4 + HeaderDataLength);
|
||||
|
||||
if (dataSize < 0 || (dataSize + dataIndex > buffer.Length)) // to fix bad subs...
|
||||
{
|
||||
dataSize = buffer.Length - dataIndex;
|
||||
if (dataSize < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
DataBuffer = new byte[dataSize+1];
|
||||
//Buffer.BlockCopy(buffer, dataIndex, DataBuffer, 0, dataSize);
|
||||
Buffer.BlockCopy(buffer, dataIndex - 1, DataBuffer, 0, DataBuffer.Length); // why subtract one from dataIndex ?????
|
||||
}
|
||||
}
|
||||
}
|
42
src/Logic/TransportStream/ProgramAssociationTable.cs
Normal file
42
src/Logic/TransportStream/ProgramAssociationTable.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.TransportStream
|
||||
{
|
||||
public class ProgramAssociationTable
|
||||
{
|
||||
public int TableId { get; set; }
|
||||
public int SectionLength { get; set; }
|
||||
public int TransportStreamId { get; set; }
|
||||
public int VersionNumber { get; set; }
|
||||
public int CurrentNextIndicator { get; set; }
|
||||
public int SectionNumber { get; set; }
|
||||
public int LastSectionNumber { get; set; }
|
||||
public List<int> ProgramNumbers { get; set; }
|
||||
public List<int> ProgramIds { get; set; }
|
||||
|
||||
public ProgramAssociationTable(byte[] packetBuffer, int index)
|
||||
{
|
||||
TableId = packetBuffer[index];
|
||||
SectionLength = (packetBuffer[index + 1] & Helper.B00000011) * 256 + packetBuffer[index + 2];
|
||||
TransportStreamId = 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];
|
||||
|
||||
ProgramNumbers = new List<int>();
|
||||
ProgramIds = new List<int>();
|
||||
index = index + 8;
|
||||
for (int i = 0; i < (SectionLength - 5) / 8; i++)
|
||||
{
|
||||
int programNumber = packetBuffer[index] * 256 + packetBuffer[index + 1];
|
||||
int programId = (packetBuffer[index + 2] & Helper.B00011111) * 256 + packetBuffer[index + 3];
|
||||
ProgramNumbers.Add(programNumber);
|
||||
ProgramIds.Add(programId);
|
||||
index += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
168
src/Logic/TransportStream/TransportStreamParser.cs
Normal file
168
src/Logic/TransportStream/TransportStreamParser.cs
Normal file
@ -0,0 +1,168 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.TransportStream
|
||||
{
|
||||
/// <summary>
|
||||
/// MPEG transport stream parser
|
||||
/// </summary>
|
||||
public class TransportStreamParser
|
||||
{
|
||||
public int NumberOfNullPackets { get; private set; }
|
||||
public long TotalNumberOfPackets { get; private set; }
|
||||
public long TotalNumberOfPrivateStream1 { get; private set; }
|
||||
public long TotalNumberOfPrivateStream1Continuation0 { get; private set; }
|
||||
public List<int> SubtitlePacketIds { get; private set; }
|
||||
public List<Packet> SubtitlePackets { get; private set; }
|
||||
|
||||
public void ParseTsFile(string fileName)
|
||||
{
|
||||
var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
ParseTsFile(fs);
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used with e.g. MemoryStream or FileStream
|
||||
/// </summary>
|
||||
/// <param name="ms">Input stream</param>
|
||||
public void ParseTsFile(Stream ms)
|
||||
{
|
||||
NumberOfNullPackets = 0;
|
||||
TotalNumberOfPackets = 0;
|
||||
TotalNumberOfPrivateStream1 = 0;
|
||||
TotalNumberOfPrivateStream1Continuation0 = 0;
|
||||
SubtitlePacketIds = new List<int>();
|
||||
SubtitlePackets = new List<Packet>();
|
||||
ms.Position = 0;
|
||||
int packetLength = DeterminePacketLength(ms);
|
||||
var packetBuffer = new byte[packetLength];
|
||||
long position = 0;
|
||||
while (position < ms.Length)
|
||||
{
|
||||
ms.Seek(position, SeekOrigin.Begin);
|
||||
ms.Read(packetBuffer, 0, packetLength);
|
||||
byte syncByte = packetBuffer[0];
|
||||
if (syncByte == Packet.SynchronizationByte)
|
||||
{
|
||||
Packet packet = new Packet(packetBuffer);
|
||||
|
||||
if (packet.IsNullPacket)
|
||||
{
|
||||
NumberOfNullPackets++;
|
||||
}
|
||||
else if (packet.IsProgramAssociationTable)
|
||||
{
|
||||
StringBuilder 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);
|
||||
|
||||
// MessageBox.Show(sb.ToString());
|
||||
}
|
||||
else if (packet.IsPrivateStream1 || SubtitlePacketIds.Contains(packet.PacketId))
|
||||
{
|
||||
TotalNumberOfPrivateStream1++;
|
||||
|
||||
SubtitlePackets.Add(packet);
|
||||
|
||||
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_offset = 13 + packet.AdaptionFieldLength + pes_extensionlength;
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
TotalNumberOfPackets++;
|
||||
position += packetLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
position++;
|
||||
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<PacketizedElementaryStream> GetSubtitlePesPackets(int packetId)
|
||||
{
|
||||
var list = new List<PacketizedElementaryStream>();
|
||||
var buffer = new byte[20000];
|
||||
int index =0;
|
||||
foreach (Packet packet in SubtitlePackets)
|
||||
{
|
||||
if (packet.ContinuityCounter == 0)
|
||||
{
|
||||
if (index > 0)
|
||||
{
|
||||
var pes = new PacketizedElementaryStream(buffer, 0);
|
||||
list.Add(pes);
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
Buffer.BlockCopy(packet.Payload, 0, buffer, index, packet.Payload.Length);
|
||||
index += packet.Payload.Length;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private int DeterminePacketLength(Stream ms)
|
||||
{
|
||||
return 188;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user