Add some support for ismt dfxp

This commit is contained in:
Nikolaj Olsson 2017-11-01 21:49:46 +01:00
parent 4173a4b382
commit d1212c005e
6 changed files with 238 additions and 92 deletions

View File

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Nikse.SubtitleEdit.Core.ContainerFormats.Mp4
{
@ -164,5 +165,40 @@ namespace Nikse.SubtitleEdit.Core.ContainerFormats.Mp4
}
}
public List<string> GetMdatsAsStrings()
{
var list = new List<string>();
using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
Position = 0;
fs.Seek(0, SeekOrigin.Begin);
bool moreBytes = true;
while (moreBytes)
{
moreBytes = InitializeSizeAndName(fs);
if (Size < 8)
return list;
if (Name == "mdat")
{
var before = (long)fs.Position;
var readLength = ((long)Position) - before;
if (readLength > 10)
{
var buffer = new byte[readLength];
fs.Read(buffer, 0, (int)readLength);
list.Add(Encoding.UTF8.GetString(buffer));
}
}
if (Position > (ulong)fs.Length)
break;
fs.Seek((long)Position, SeekOrigin.Begin);
}
fs.Close();
}
return list;
}
}
}

View File

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Nikse.SubtitleEdit.Core.Forms
{
public static class MergeLinesWithSameTimeCodes
{
public static Subtitle Merge(Subtitle subtitle, List<int> mergedIndexes, out int numberOfMerges, bool clearFixes, bool reBreak, int maxMsBetween, string language, List<int> removed, Dictionary<int, bool> isFixAllowedList, Subtitle info)
{
numberOfMerges = 0;
var mergedSubtitle = new Subtitle();
bool lastMerged = false;
Paragraph p = null;
var lineNumbers = new StringBuilder();
for (int i = 1; i < subtitle.Paragraphs.Count; i++)
{
if (!lastMerged)
{
p = new Paragraph(subtitle.GetParagraphOrDefault(i - 1));
mergedSubtitle.Paragraphs.Add(p);
}
Paragraph next = subtitle.GetParagraphOrDefault(i);
if (next != null)
{
if (QualifiesForMerge(p, next, maxMsBetween) && IsFixAllowed(p, isFixAllowedList))
{
if (p.Text.StartsWith("<i>", StringComparison.Ordinal) && p.Text.EndsWith("</i>", StringComparison.Ordinal) && next.Text.StartsWith("<i>", StringComparison.Ordinal) && next.Text.EndsWith("</i>", StringComparison.Ordinal))
{
p.Text = p.Text.Remove(p.Text.Length - 4) + Environment.NewLine + next.Text.Remove(0, 3);
}
else
{
p.Text = p.Text + Environment.NewLine + next.Text;
}
if (reBreak)
p.Text = Utilities.AutoBreakLine(p.Text, language);
lastMerged = true;
removed.Add(i);
numberOfMerges++;
if (!mergedIndexes.Contains(i))
mergedIndexes.Add(i);
if (!mergedIndexes.Contains(i - 1))
mergedIndexes.Add(i - 1);
if (!("," + lineNumbers).Contains("," + p.Number + ","))
{
lineNumbers.Append(p.Number);
lineNumbers.Append(',');
}
if (!("," + lineNumbers).Contains("," + next.Number + ","))
{
lineNumbers.Append(next.Number);
lineNumbers.Append(',');
}
}
else
{
lastMerged = false;
}
}
else
{
lastMerged = false;
}
if (!removed.Contains(i) && lineNumbers.Length > 0 && clearFixes)
{
info.Paragraphs.Add(new Paragraph(p) { Extra = lineNumbers.ToString() });
lineNumbers.Clear();
}
}
if (lineNumbers.Length > 0 && clearFixes && p != null)
{
info.Paragraphs.Add(new Paragraph(p) { Extra = lineNumbers.ToString() });
}
if (!lastMerged)
mergedSubtitle.Paragraphs.Add(new Paragraph(subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1)));
mergedSubtitle.Renumber();
return mergedSubtitle;
}
private static bool QualifiesForMerge(Paragraph p, Paragraph next, int maxMsBetween)
{
if (p == null || next == null)
return false;
return Math.Abs(next.StartTime.TotalMilliseconds - p.StartTime.TotalMilliseconds) <= maxMsBetween &&
Math.Abs(next.EndTime.TotalMilliseconds - p.EndTime.TotalMilliseconds) <= maxMsBetween;
}
private static bool IsFixAllowed(Paragraph p, Dictionary<int, bool> isFixAllowedList)
{
if (isFixAllowedList.ContainsKey(p.Number))
return isFixAllowedList[p.Number];
return true;
}
}
}

View File

@ -169,6 +169,7 @@
<Compile Include="Forms\FixCommonErrors\FixUnneededSpaces.cs" />
<Compile Include="Forms\FixCommonErrors\FixUppercaseIInsideWords.cs" />
<Compile Include="Forms\FixCommonErrors\Helper.cs" />
<Compile Include="Forms\MergeLinesWithSameTimeCodes.cs" />
<Compile Include="Interfaces\IBinaryPersistableSubtitle.cs" />
<Compile Include="Interfaces\IFixCallbacks.cs" />
<Compile Include="Interfaces\IFixCommonError.cs" />
@ -233,6 +234,7 @@
<Compile Include="SubtitleFormats\Csv5.cs" />
<Compile Include="SubtitleFormats\DvdStudioProSpaceOneSemicolon.cs" />
<Compile Include="SubtitleFormats\FinalCutProXml15.cs" />
<Compile Include="SubtitleFormats\IsmtDfxp.cs" />
<Compile Include="SubtitleFormats\JsonType12.cs" />
<Compile Include="SubtitleFormats\TimeCodesOnly2.cs" />
<Compile Include="SubtitleFormats\Rtf1.cs" />

View File

@ -0,0 +1,72 @@
using Nikse.SubtitleEdit.Core.ContainerFormats.Mp4;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
{
public class IsmtDfxp : SubtitleFormat
{
public override string Extension => ".ismt";
public override string Name => "HBO GO";
public override bool IsMine(List<string> lines, string fileName)
{
if (string.IsNullOrEmpty(fileName))
return false;
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var buffer = new byte[12];
int l = fs.Read(buffer, 0, buffer.Length);
if (l != buffer.Length)
return false;
var str = Encoding.ASCII.GetString(buffer, 4, 8);
if (str != "ftypisml")
return false;
}
return true;
}
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
{
_errorCount = 0;
var mp4Parser = new MP4Parser(fileName);
var dfxpStrings = mp4Parser.GetMdatsAsStrings();
foreach (var xmlAsString in dfxpStrings)
{
try
{
var sub = new Subtitle();
var format = new TimedText();
sub.ReloadLoadSubtitle(xmlAsString.SplitToLines().ToList(), null, format);
if (sub.Paragraphs.Count == 0)
continue;
// merge lines with same time codes
int numberOfMerges;
sub = Forms.MergeLinesWithSameTimeCodes.Merge(sub, new List<int>(), out numberOfMerges, true, false, 1000, "en", new List<int>(), new Dictionary<int, bool>(), new Subtitle());
// adjust to last exisiting sub
var lastSub = subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1);
if (lastSub != null)
sub.AddTimeToAllParagraphs(lastSub.EndTime.TimeSpan);
subtitle.Paragraphs.AddRange(sub.Paragraphs);
}
catch
{
_errorCount++;
}
}
}
public override string ToText(Subtitle subtitle, string title)
{
return "Not supported";
}
}
}

View File

@ -1929,9 +1929,12 @@ namespace Nikse.SubtitleEdit.Forms
if ((ext == ".mp4" || ext == ".m4v" || ext == ".3gp") && file.Length > 10000)
{
if (ImportSubtitleFromMp4(fileName) && !Configuration.Settings.General.DisableVideoAutoLoading)
OpenVideo(fileName);
return;
if (!new IsmtDfxp().IsMine(null, fileName))
{
if (ImportSubtitleFromMp4(fileName) && !Configuration.Settings.General.DisableVideoAutoLoading)
OpenVideo(fileName);
return;
}
}
if (ext == ".mxf" && FileUtil.IsMaterialExchangeFormat(fileName))
@ -2692,6 +2695,20 @@ namespace Nikse.SubtitleEdit.Forms
}
}
if (format == null)
{
var f = new IsmtDfxp();
if (f.IsMine(null, fileName))
{
f.LoadSubtitle(_subtitle, null, fileName);
_oldSubtitleFormat = f;
SetCurrentFormat(Configuration.Settings.General.DefaultSubtitleFormat);
SetEncoding(Configuration.Settings.General.DefaultEncoding);
encoding = GetCurrentEncoding();
justConverted = true;
format = GetCurrentSubtitleFormat();
}
}
// retry vobsub (file with wrong extension)
if (format == null && file.Length > 500 && IsVobSubFile(fileName, false))

View File

@ -96,7 +96,7 @@ namespace Nikse.SubtitleEdit.Forms
SubtitleListview1.Items.Clear();
SubtitleListview1.BeginUpdate();
int count;
_mergedSubtitle = MergeLinesWithSameTimeCodes(_subtitle, mergedIndexes, out count, true, checkBoxAutoBreakOn.Checked, (int)numericUpDownMaxMillisecondsBetweenLines.Value);
_mergedSubtitle = MergeLinesWithSameTimeCodes(_subtitle, mergedIndexes, out count, true, checkBoxAutoBreakOn.Checked, (int)numericUpDownMaxMillisecondsBetweenLines.Value, _language);
NumberOfMerges = count;
SubtitleListview1.Fill(_subtitle);
@ -108,13 +108,6 @@ namespace Nikse.SubtitleEdit.Forms
groupBoxLinesFound.Text = string.Format(Configuration.Settings.Language.MergeTextWithSameTimeCodes.NumberOfMergesX, NumberOfMerges);
}
private bool IsFixAllowed(Paragraph p)
{
if (_isFixAllowedList.ContainsKey(p.Number))
return _isFixAllowedList[p.Number];
return true;
}
private void listViewFixes_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (_loading)
@ -134,7 +127,7 @@ namespace Nikse.SubtitleEdit.Forms
SubtitleListview1.Items.Clear();
SubtitleListview1.BeginUpdate();
int count;
_mergedSubtitle = MergeLinesWithSameTimeCodes(_subtitle, mergedIndexes, out count, false, checkBoxAutoBreakOn.Checked, (int)numericUpDownMaxMillisecondsBetweenLines.Value);
_mergedSubtitle = MergeLinesWithSameTimeCodes(_subtitle, mergedIndexes, out count, false, checkBoxAutoBreakOn.Checked, (int)numericUpDownMaxMillisecondsBetweenLines.Value, _language);
NumberOfMerges = count;
SubtitleListview1.Fill(_subtitle);
foreach (var index in mergedIndexes)
@ -146,7 +139,7 @@ namespace Nikse.SubtitleEdit.Forms
groupBoxLinesFound.Text = string.Format(Configuration.Settings.Language.MergeTextWithSameTimeCodes.NumberOfMergesX, NumberOfMerges);
}
public Subtitle MergeLinesWithSameTimeCodes(Subtitle subtitle, List<int> mergedIndexes, out int numberOfMerges, bool clearFixes, bool reBreak, int maxMsBetween)
public Subtitle MergeLinesWithSameTimeCodes(Subtitle subtitle, List<int> mergedIndexes, out int numberOfMerges, bool clearFixes, bool reBreak, int maxMsBetween, string language)
{
listViewFixes.BeginUpdate();
var removed = new List<int>();
@ -157,90 +150,16 @@ namespace Nikse.SubtitleEdit.Forms
listViewFixes.Items.Clear();
_isFixAllowedList = new Dictionary<int, bool>();
}
numberOfMerges = 0;
var mergedSubtitle = new Subtitle();
bool lastMerged = false;
Paragraph p = null;
var lineNumbers = new StringBuilder();
for (int i = 1; i < subtitle.Paragraphs.Count; i++)
var info = new Subtitle();
var mergedSub = Core.Forms.MergeLinesWithSameTimeCodes.Merge(subtitle, mergedIndexes, out numberOfMerges, clearFixes, reBreak, maxMsBetween, language, removed, _isFixAllowedList, info);
foreach (var p in info.Paragraphs)
{
if (!lastMerged)
{
p = new Paragraph(subtitle.GetParagraphOrDefault(i - 1));
mergedSubtitle.Paragraphs.Add(p);
}
Paragraph next = subtitle.GetParagraphOrDefault(i);
if (next != null)
{
if (QualifiesForMerge(p, next, maxMsBetween) && IsFixAllowed(p))
{
if (p.Text.StartsWith("<i>", StringComparison.Ordinal) && p.Text.EndsWith("</i>", StringComparison.Ordinal) && next.Text.StartsWith("<i>", StringComparison.Ordinal) && next.Text.EndsWith("</i>", StringComparison.Ordinal))
{
p.Text = p.Text.Remove(p.Text.Length - 4) + Environment.NewLine + next.Text.Remove(0, 3);
}
else
{
p.Text = p.Text + Environment.NewLine + next.Text;
}
if (reBreak)
p.Text = Utilities.AutoBreakLine(p.Text, _language);
lastMerged = true;
removed.Add(i);
numberOfMerges++;
if (!mergedIndexes.Contains(i))
mergedIndexes.Add(i);
if (!mergedIndexes.Contains(i - 1))
mergedIndexes.Add(i - 1);
if (!("," + lineNumbers).Contains("," + p.Number + ","))
{
lineNumbers.Append(p.Number);
lineNumbers.Append(',');
}
if (!("," + lineNumbers).Contains("," + next.Number + ","))
{
lineNumbers.Append(next.Number);
lineNumbers.Append(',');
}
}
else
{
lastMerged = false;
}
}
else
{
lastMerged = false;
}
if (!removed.Contains(i) && lineNumbers.Length > 0 && clearFixes)
{
AddToListView(p, lineNumbers.ToString(), p.Text);
lineNumbers.Clear();
}
AddToListView(p, p.Extra, p.Text);
}
if (lineNumbers.Length > 0 && clearFixes && p != null)
{
AddToListView(p, lineNumbers.ToString(), p.Text);
}
if (!lastMerged)
mergedSubtitle.Paragraphs.Add(new Paragraph(subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1)));
listViewFixes.EndUpdate();
if (!_loading)
listViewFixes.ItemChecked += listViewFixes_ItemChecked;
mergedSubtitle.Renumber();
return mergedSubtitle;
}
private static bool QualifiesForMerge(Paragraph p, Paragraph next, int maxMsBetween)
{
if (p == null || next == null)
return false;
return Math.Abs(next.StartTime.TotalMilliseconds - p.StartTime.TotalMilliseconds) <= maxMsBetween &&
Math.Abs(next.EndTime.TotalMilliseconds - p.EndTime.TotalMilliseconds) <= maxMsBetween;
return mergedSub;
}
private void MergeTextWithSameTimeCodes_KeyDown(object sender, KeyEventArgs e)