Skip to content

Commit 71008ab

Browse files
Merge pull request #12 from MikeMoolenaar/release/1.2.0
Release 1.2.0
2 parents e323805 + 02851e8 commit 71008ab

File tree

16 files changed

+98
-57
lines changed

16 files changed

+98
-57
lines changed

MatroskaLib/MatroskaLib.Test/ByteHelperTest.cs

+19-19
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ namespace MatroskaLib.Test;
66
public class ByteHelperTest
77
{
88
public static TheoryData<ulong, List<byte>> TestData1 = new() {
9-
{ 2UL, new () { 0x2 } },
10-
{ 909UL, new () { 0x3, 0x8D } },
11-
{ 1_800_70UL, new () { 0x2, 0xBF, 0x66 } },
9+
{ 2UL, [0x2] },
10+
{ 909UL, [0x3, 0x8D] },
11+
{ 1_800_70UL, [0x2, 0xBF, 0x66] },
1212
};
1313
[Theory, MemberData(nameof(TestData1))]
1414
public void ToBytesTest(ulong value, List<byte> lsBytesExpected)
@@ -19,10 +19,10 @@ public void ToBytesTest(ulong value, List<byte> lsBytesExpected)
1919
}
2020

2121
public static TheoryData<List<byte>, List<byte>> TestData2 = new() {
22-
{ new() {0x0, 0x0, 0x0, 0x96}, new () { 0x96 } },
23-
{ new() {0x0, 0x0, 0x5, 0x0, 0x9}, new () { 0x5, 0x0, 0x9 } },
24-
{ new() {0x9}, new () { 0x9 } },
25-
{ new() {}, new () { } }
22+
{ [0x0, 0x0, 0x0, 0x96], [0x96] },
23+
{ [0x0, 0x0, 0x5, 0x0, 0x9], [0x5, 0x0, 0x9] },
24+
{ [0x9], [0x9] },
25+
{ [], [] }
2626
};
2727
[Theory, MemberData(nameof(TestData2))]
2828
public void RemoveLeftZeroesTest(List<byte> lsBytes, List<byte> lsBytesExpected)
@@ -34,34 +34,34 @@ public void RemoveLeftZeroesTest(List<byte> lsBytes, List<byte> lsBytesExpected)
3434

3535
public static IEnumerable<object[]> Data()
3636
{
37-
yield return new object[]
38-
{
37+
yield return
38+
[
3939
new List<byte>{ 0x6B, 0x2D, 0xAE, 0xBB, 0xD7, 0x81, 0x02 },
4040
new List<byte>{ 0x6B, 0x2D, 0xAE, 0xBE, 0xD7, 0x81, 0x02 },
4141
4,
4242
3
43-
};
44-
yield return new object[]
45-
{
43+
];
44+
yield return
45+
[
4646
new List<byte>{ 0x81, 0x02, 0xAE, 0x42, 0x83, 0xD7, 0x81, 0x03 },
4747
new List<byte>{ 0x81, 0x02, 0xAE, 0x42, 0x87, 0xD7, 0x81, 0x03 },
4848
5,
4949
4
50-
};
51-
yield return new object[]
52-
{
50+
];
51+
yield return
52+
[
5353
new List<byte>{ 0x81, 0x02, 0xAE, 0x42, 0x83, 0xD7, 0x81, 0x03 },
5454
new List<byte>{ 0x81, 0x02, 0xAE, 0x42, 0x87, 0xD7, 0x81, 0x03 },
5555
5,
5656
4
57-
};
58-
yield return new object[]
59-
{
57+
];
58+
yield return
59+
[
6060
new List<byte>{ 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x3A, 0xD7, 81 },
6161
new List<byte>{ 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x3D, 0xD7, 81 },
6262
11,
6363
3
64-
};
64+
];
6565
}
6666
[Theory, MemberData(nameof(Data))]
6767

MatroskaLib/MatroskaLib.Test/Helpers/MkvValidator.cs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public static class MkvValidator
1111
private const string OutputRemoveRegex = @"(^At least one output file must be specified)|(^\[(.*)\] )";
1212
public static void Validate(string filePath)
1313
{
14+
// Validate with ffmpeg
1415
Process p = new Process();
1516
p.StartInfo.UseShellExecute = false;
1617
p.StartInfo.RedirectStandardError = true;
@@ -26,6 +27,7 @@ public static void Validate(string filePath)
2627
throw new Exception("ffmpeg's mkv validation produced errors:" + Environment.NewLine + output);
2728
}
2829

30+
// Validate with mkvalidator
2931
p = new Process();
3032
p.StartInfo.UseShellExecute = false;
3133
p.StartInfo.RedirectStandardError = true;

MatroskaLib/MatroskaLib.Test/MatroskaLib.Test.csproj

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
<Link>mkv files\TestFile5_MkvProEdit.mkv</Link>
5050
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
5151
</Content>
52+
<Content Include="..\..\TestMkvFiles\mkv files\TestFile6_SmallSeekHead.mkv">
53+
<Link>mkv files\TestFile6_SmallSeekHead.mkv</Link>
54+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
55+
</Content>
5256
<Content Include="mkvalidator.exe">
5357
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
5458
</Content>

MatroskaLib/MatroskaLib.Test/MatroskaLibTest.cs

+25-12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ namespace MatroskaLib.Test;
1313
* Only first void with checksum elements
1414
* MkvProEdit
1515
* Only second void and may need to change length of that void
16+
* TestFile6_SmallSeekHead.mkv
17+
* SeekHead size of 2, which caused an exception (see github issue #10).
18+
* Do that this is not a valid mkv file accordant to MkValidator.
1619
*/
1720
public class MatroskaLibTest
1821
{
@@ -22,7 +25,7 @@ public class MatroskaLibTest
2225
[InlineData("mkv files/TestFile1_MkvToolNix.mkv")]
2326
public void ReadTestFile1(string file)
2427
{
25-
string[] filePaths = { file };
28+
string[] filePaths = [file];
2629

2730
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(filePaths);
2831
List<Track> lsTracks = lsMkvFiles[0].tracks;
@@ -40,12 +43,12 @@ public void ReadTestFile1(string file)
4043
public void WriteTestFile1(string file)
4144
{
4245
File.Copy(file, TestFilePath, true);
43-
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
46+
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
4447
lsMkvFiles[0].tracks[0].flagDefault = false;
4548
lsMkvFiles[0].tracks[2].flagDefault = false;
4649

4750
MatroskaWriter.WriteMkvFile(lsMkvFiles[0]);
48-
lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
51+
lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
4952
List<Track> lsTracks = lsMkvFiles[0].tracks;
5053

5154
lsTracks.Should().HaveCount(3);
@@ -59,7 +62,7 @@ public void WriteTestFile1(string file)
5962
[InlineData("mkv files/TestFile2_MkvToolNix.mkv")]
6063
public void ReadTestFile2(string file)
6164
{
62-
string[] filePaths = { file };
65+
string[] filePaths = [file];
6366

6467
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(filePaths);
6568
List<Track> lsTracks = lsMkvFiles[0].tracks;
@@ -79,12 +82,12 @@ public void ReadTestFile2(string file)
7982
public void WriteTestFile2(string file)
8083
{
8184
File.Copy(file, TestFilePath, true);
82-
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
85+
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
8386
lsMkvFiles[0].tracks[1].flagDefault = true;
8487
lsMkvFiles[0].tracks[3].flagDefault = true;
8588

8689
MatroskaWriter.WriteMkvFile(lsMkvFiles[0]);
87-
lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
90+
lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
8891
List<Track> lsTracks = lsMkvFiles[0].tracks;
8992

9093
lsTracks.Should().HaveCount(5);
@@ -100,7 +103,7 @@ public void WriteTestFile2(string file)
100103
[InlineData("mkv files/TestFile3_HandBrake.mkv")]
101104
public void ReadTestFile3(string file)
102105
{
103-
string[] filePaths = { file };
106+
string[] filePaths = [file];
104107

105108
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(filePaths);
106109
List<Track> lsTracks = lsMkvFiles[0].tracks;
@@ -119,12 +122,12 @@ public void ReadTestFile3(string file)
119122
public void WriteTestFile3(string file)
120123
{
121124
File.Copy(file, TestFilePath, true);
122-
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
125+
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
123126
lsMkvFiles[0].tracks[1].flagDefault = true;
124127
lsMkvFiles[0].tracks[3].flagDefault = true;
125128

126129
MatroskaWriter.WriteMkvFile(lsMkvFiles[0]);
127-
lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
130+
lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
128131
List<Track> lsTracks = lsMkvFiles[0].tracks;
129132

130133
lsTracks.Should().HaveCount(4);
@@ -140,7 +143,7 @@ public void WriteTestFile3(string file)
140143
[InlineData("mkv files/TestFile5_MkvProEdit.mkv")]
141144
public void ReadTestFile4(string file)
142145
{
143-
string[] filePaths = { file };
146+
string[] filePaths = [file];
144147

145148
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(filePaths);
146149
List<Track> lsTracks = lsMkvFiles[0].tracks;
@@ -158,12 +161,12 @@ public void ReadTestFile4(string file)
158161
public void WriteTestFile4(string file)
159162
{
160163
File.Copy(file, TestFilePath, true);
161-
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
164+
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
162165
lsMkvFiles[0].tracks[0].flagDefault = false;
163166
lsMkvFiles[0].tracks[2].flagDefault = false;
164167

165168
MatroskaWriter.WriteMkvFile(lsMkvFiles[0]);
166-
lsMkvFiles = MatroskaReader.ReadMkvFiles(new[] { TestFilePath });
169+
lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
167170
List<Track> lsTracks = lsMkvFiles[0].tracks;
168171

169172
lsTracks.Should().HaveCount(3);
@@ -172,4 +175,14 @@ public void WriteTestFile4(string file)
172175
lsTracks[2].Should().BeEquivalentTo(new { flagDefault = false, flagForced = false, language = "jpn", type = TrackTypeEnum.audio });
173176
MkvValidator.Validate(TestFilePath);
174177
}
178+
179+
[Fact]
180+
public void FileWithSeekHeadSizeOf2ShouldNotThrow()
181+
{
182+
File.Copy("mkv files/TestFile6_SmallSeekHead.mkv", TestFilePath, true);
183+
List<MkvFile> lsMkvFiles = MatroskaReader.ReadMkvFiles([TestFilePath]);
184+
lsMkvFiles[0].tracks[0].flagDefault = false;
185+
186+
MatroskaWriter.WriteMkvFile(lsMkvFiles[0]);
187+
}
175188
}

MatroskaLib/MatroskaLib/Helpers/ByteHelper.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ public static void ChangeLength(List<byte> lsBytes, int position, List<byte> lsL
5757

5858
// Convert new length to bytes and strip bytes
5959
List<byte> lsNewBytes = ToBytes(ret);
60-
if (lsNewBytes.Count != lsLengthBytes.Count) throw new Exception("New length doesn't fit into existing length element");
60+
if (lsNewBytes.Count != lsLengthBytes.Count)
61+
throw new InvalidOperationException($"New length bytes are not the same length as the old ones. Old length: {lsLengthBytes.Count}, new length: {lsNewBytes.Count}");
6162

6263
// Replace old length with new length bytes
6364
lsBytes.RemoveRange(position, lsNewBytes.Count);

MatroskaLib/MatroskaLib/Helpers/CustomExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static void LocateElement(this EbmlReader reader, ulong descriptor)
1616
}
1717
}
1818

19-
throw new Exception($"Cannot find descriptor 0x{descriptor:X}");
19+
throw new InvalidOperationException($"Cannot find descriptor 0x{descriptor:X}");
2020
}
2121
}
2222
}

MatroskaLib/MatroskaLib/MatroskaWriter.cs

+7-3
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,14 @@ private static void _ChangeVoidLengthAndHeaders(List<Seek> seekList, int? seekHe
7272
foreach (var s in seekList.Where(s =>
7373
s.seekId is MatroskaElements.Tracks or MatroskaElements.SegmentInfo))
7474
{
75-
int desiredLength = Convert.ToInt32(lsBytes[s.seekPositionByteNumber - 1] - 0x80);
7675
List<byte> lsNewBytes = ByteHelper.ToBytes(s.seekPosition - (ulong)offset);
77-
if (desiredLength != lsNewBytes.Count)
78-
throw new Exception("New seekposition doesn't fit into existing element");
76+
if (lsNewBytes.Count > s.elementLength)
77+
throw new InvalidOperationException($"New seekPosition bytes are bigger than the old one. Trying to fit {lsNewBytes.Count} bytes into {s.elementLength} bytes");
78+
if (lsNewBytes.Count < s.elementLength)
79+
{
80+
// The new seekPosition is smaller than the old one, add padding
81+
lsNewBytes.AddRange(new byte[s.elementLength - lsNewBytes.Count]);
82+
}
7983

8084
lsBytes.RemoveRange(s.seekPositionByteNumber, lsNewBytes.Count);
8185
lsBytes.InsertRange(s.seekPositionByteNumber, lsNewBytes);

MatroskaLib/MatroskaLib/MkvFilesContainer.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@ namespace MatroskaLib;
88
public class MkvFilesContainer
99
{
1010
public readonly List<MkvFile> MkvFiles = new();
11-
public readonly List<MkvFile> MkFilesRejected = new();
11+
public readonly List<(MkvFile file, string error)> MkFilesRejected = new();
1212

1313
public MkvFilesContainer(string[] filePaths)
1414
{
1515
var files = MatroskaReader.ReadMkvFiles(filePaths);
1616
MkvFiles.Add(files[0]);
1717
for (int i = 1; i < files.Count; i++)
1818
{
19-
if (files[0].CompareTo(files[i]) == 0)
19+
string? error = files[0].CompareToGetError(files[i]);
20+
if (error is null)
2021
MkvFiles.Add(files[i]);
2122
else
22-
MkFilesRejected.Add(files[i]);
23+
MkFilesRejected.Add((files[i], error));
2324
}
2425
}
2526

MatroskaLib/MatroskaLib/Types/MkvFile.cs

+10-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace MatroskaLib.Types;
88

9-
public record MkvFile : IComparable<MkvFile>
9+
public record MkvFile
1010
{
1111
public required string filePath { get; init; }
1212
public required List<Track> tracks { get; init; }
@@ -18,7 +18,7 @@ public record MkvFile : IComparable<MkvFile>
1818
public required int tracksPosition { get; init; }
1919
public required int beginHeaderPosition { get; init; }
2020

21-
public int CompareTo(MkvFile? other)
21+
public string? CompareToGetError(MkvFile? other)
2222
{
2323
if (other is null)
2424
throw new ArgumentNullException(nameof(other));
@@ -27,11 +27,16 @@ public int CompareTo(MkvFile? other)
2727
{
2828
var track = tracks[i];
2929
var trackOther = other.tracks.ElementAtOrDefault(i);
30-
if (trackOther is null || track.number != trackOther.number || track.language != trackOther.language)
31-
return -1;
30+
31+
if (trackOther is null)
32+
return $"Track at index {i} does not exist, expected {track.type} with language {track.language}.";
33+
if (track.number != trackOther.number)
34+
return $"Track number at index {i} does not match. Expected {track.number}, got {trackOther.number}.";
35+
if (track.language != trackOther.language)
36+
return $"Track language at index {i} does not match. Expected {track.language}, got {trackOther.language}.";
3237
}
3338

34-
return 0;
39+
return null;
3540
}
3641

3742
public override string ToString() =>

MatroskaLib/MatroskaLib/Types/Seek.cs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public class Seek
99
public ulong seekId { get; private set; }
1010
public ulong seekPosition { get; private set; }
1111
public int seekPositionByteNumber { get; private set; }
12+
public int elementLength { get; private set; }
1213

1314
public Seek(EbmlReader reader) =>
1415
_reader = reader;
@@ -23,6 +24,7 @@ public void ApplyElement(FileStream fileStream)
2324
{
2425
seekPositionByteNumber = (int)fileStream.Position;
2526
seekPosition = _reader.ReadUInt();
27+
elementLength = (int)_reader.ElementSize;
2628
}
2729
}
2830
}

MkvDefaultTrackChanger/MkvDefaultTrackChanger.Mac/Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<key>CFBundleIdentifier</key>
88
<string>com.mikemoolenaar.MkvDefaultTrackChanger</string>
99
<key>CFBundleShortVersionString</key>
10-
<string>1.1.0</string>
10+
<string>1.2.0</string>
1111
<key>LSMinimumSystemVersion</key>
1212
<string>10.12</string>
1313
<key>CFBundleDevelopmentRegion</key>

MkvDefaultTrackChanger/MkvDefaultTrackChanger/ErrorForm.xeto

+13-7
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@
33
xmlns="http://schema.picoe.ca/eto.forms"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
55
Title="MkvDefaultTrackChanger"
6-
MinimumSize="370,530"
6+
MinimumSize="370,570"
77
Size="370,530"
88
Padding="10"
99
>
10-
<StackLayout Spacing="20" HorizontalContentAlignment="Center">
11-
<Label x:Name="lblTitle" Text="An error occured!"></Label>
12-
<LinkButton Text="Create issue" Click="BtnCreateIssueClicked"></LinkButton>
10+
<DynamicLayout Spacing="0,15" Padding="15,5,15,0">
11+
<StackLayout Spacing="5" HorizontalContentAlignment="Center">
12+
<Label x:Name="lblTitle" Text="An error occured!"></Label>
13+
<LinkButton Text="Create issue" Click="BtnCreateIssueClicked"></LinkButton>
14+
</StackLayout>
1315
<Label Text="You can report this error by creating an issue on GitHub, please copy and paste the below box-contained text in the issue description."></Label>
1416
<Label Text="DISCLAIMER: The text includes basic info about your OS, tracks of the MKV file and about where the error occured in the codebase. It does not include the filename(s). By creating an issue you consent to sharing the below text publicly on the internet."></Label>
1517

16-
<TextArea Width="320" Height="150" Wrap="false" x:Name="txaExceptionMessage" ReadOnly="true"></TextArea>
18+
<DynamicLayout Spacing="0,10">
19+
<TextArea Wrap="false" Height="200" x:Name="txaExceptionMessage" ReadOnly="true"></TextArea>
20+
</DynamicLayout>
1721

18-
<Button x:Name="btnClose" Click="BtnCloseClicked">Close</Button>
19-
</StackLayout>
22+
<StackLayout Spacing="5" HorizontalContentAlignment="Center">
23+
<Button x:Name="btnClose" Click="BtnCloseClicked">Close</Button>
24+
</StackLayout>
25+
</DynamicLayout>
2026
</Form>

MkvDefaultTrackChanger/MkvDefaultTrackChanger/MainForm.xeto.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,15 @@ private void LoadFiles()
5858
mkvContainer = new MkvFilesContainer(filePaths);
5959
if (mkvContainer.MkFilesRejected.Count > 0)
6060
{
61+
var sourceFile = Path.GetFileName(filePaths[0]);
62+
6163
string rejectedFiles = Environment.NewLine + Environment.NewLine;
6264
mkvContainer.MkFilesRejected.ForEach((x) =>
6365
{
64-
rejectedFiles += Path.GetFileName(x.filePath) + Environment.NewLine + Environment.NewLine;
66+
rejectedFiles += $"- {Path.GetFileName(x.file.filePath)}: {x.error} {Environment.NewLine}{Environment.NewLine}";
6567
});
66-
MessageBox.Show("The following files were rejected: " + rejectedFiles, MessageBoxType.Warning);
68+
MessageBox.Show($"The following files have different tracks or the order is different than {sourceFile}: {rejectedFiles}These files cannot be processed.",
69+
MessageBoxType.Warning);
6770
}
6871

6972
var lsSubtitleTracks = mkvContainer.GetSubtitleTracks();

0 commit comments

Comments
 (0)