Skip to content

Commit bbba054

Browse files
committed
Merge branch 'main' into develop
2 parents b09a899 + 1549f44 commit bbba054

File tree

19 files changed

+114
-65
lines changed

19 files changed

+114
-65
lines changed

.github/workflows/build-and-test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515
build-and-test:
1616
runs-on: windows-latest
1717
steps:
18-
- uses: actions/checkout@v2
18+
- uses: actions/checkout@v4
1919
- uses: FedericoCarboni/setup-ffmpeg@v1
2020
- name: Setup .NET
21-
uses: actions/setup-dotnet@v3
21+
uses: actions/setup-dotnet@v4
2222
with:
2323
dotnet-version: 8.0.x
2424
- name: Restore dependencies

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.Test/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The unit tests depend on ffmpeg and mkvalidator to make sure the program outputs
1313
If you are on a Ubuntu based distro: [use this PPA](https://launchpad.net/~hizo/+archive/ubuntu/mkv-extractor-gui) to install mkvalidator
1414
Otherwise: [Download the source code](https://sourceforge.net/projects/matroska/files/mkvalidator/) and compile using make.
1515

16-
**MacOS**
16+
**MacOS**
1717
Use homebrew:
1818
```
1919
brew install mkvalidator ffmpeg

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace MatroskaLib;
88

99
public static class MatroskaWriter
1010
{
11-
public static void WriteMkvFile(MkvFile mkfFile)
11+
public static void WriteMkvFile(MkvFile mkfFile, bool dryRun = false)
1212
{
1313
using var dataStream = File.Open(mkfFile.filePath, FileMode.Open);
1414
dataStream.Seek(0, SeekOrigin.Begin);
@@ -25,6 +25,7 @@ public static void WriteMkvFile(MkvFile mkfFile)
2525
offset, lsBytes);
2626

2727
// Write modified changes to file
28+
if (dryRun) return;
2829
dataStream.Seek(0, SeekOrigin.Begin);
2930
dataStream.Write(lsBytes.ToArray(), 0, lsBytes.Count);
3031
}
@@ -71,10 +72,14 @@ private static void _ChangeVoidLengthAndHeaders(List<Seek> seekList, int? seekHe
7172
foreach (var s in seekList.Where(s =>
7273
s.seekId is MatroskaElements.Tracks or MatroskaElements.SegmentInfo))
7374
{
74-
int desiredLength = Convert.ToInt32(lsBytes[s.seekPositionByteNumber - 1] - 0x80);
7575
List<byte> lsNewBytes = ByteHelper.ToBytes(s.seekPosition - (ulong)offset);
76-
if (desiredLength != lsNewBytes.Count)
77-
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+
}
7883

7984
lsBytes.RemoveRange(s.seekPositionByteNumber, lsNewBytes.Count);
8085
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>

0 commit comments

Comments
 (0)