Skip to content

Commit 99374dd

Browse files
committed
Enhancements
Add parsing and display of all audio flags. Added Next/Previous button. Fuller Audio Track decoding. Enable ReadyToRun for all environments.
1 parent aed5f12 commit 99374dd

14 files changed

Lines changed: 538 additions & 130 deletions

File tree

MatroskaLib/MatroskaLib.Test/MkvFileTest.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public void TestToString()
2222
voidPosition = 40
2323
};
2424

25-
string json = mkvFile.ToString();
25+
string json = mkvFile.ToString().Replace("\r\n", "\n");
2626

2727
json.Should().Be("""
2828
{
@@ -35,10 +35,21 @@ public void TestToString()
3535
"flagDefaultByteNumber": 0,
3636
"flagForced": true,
3737
"flagForcedByteNumber": 0,
38+
"flagHearingImpaired": false,
39+
"flagHearingImpairedByteNumber": 0,
40+
"flagVisualImpaired": false,
41+
"flagVisualImpairedByteNumber": 0,
42+
"flagTextDescriptions": false,
43+
"flagTextDescriptionsByteNumber": 0,
44+
"flagOriginal": false,
45+
"flagOriginalByteNumber": 0,
46+
"flagCommentary": false,
47+
"flagCommentaryByteNumber": 0,
3848
"flagTypebytenumber": 0,
3949
"type": "subtitle",
4050
"name": "",
41-
"language": "eng"
51+
"language": "eng",
52+
"codecId": null,
4253
}
4354
],
4455
"seekList": [],
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.IO;
5+
using System.Linq;
6+
using MediaInfo;
7+
using MediaInfo.Model;
8+
using MatroskaLib.Types;
9+
using Microsoft.Extensions.Logging.Abstractions;
10+
11+
namespace MatroskaLib.Helpers;
12+
13+
public static class MediaInfoHelper
14+
{
15+
public static Dictionary<ulong, (string format, double bitrate)> GetAllTrackFormats(Stream stream, IEnumerable<Track> tracks)
16+
{
17+
var results = new Dictionary<ulong, (string format, double bitrate)>();
18+
19+
try
20+
{
21+
if (!stream.CanSeek)
22+
{
23+
Debug.WriteLine($"Stream is not seekable, cannot use MediaInfo");
24+
return results;
25+
}
26+
27+
long originalPosition = stream.Position;
28+
stream.Position = 0;
29+
30+
var mediaInfo = new MediaInfoWrapper(stream, NullLogger.Instance);
31+
32+
stream.Position = originalPosition;
33+
34+
if (!mediaInfo.Success)
35+
{
36+
Debug.WriteLine($"MediaInfo failed to read from stream");
37+
return results;
38+
}
39+
40+
Debug.WriteLine($"MediaInfo found {mediaInfo.AudioStreams?.Count ?? 0} audio streams, {mediaInfo.Subtitles?.Count ?? 0} subtitle streams");
41+
42+
foreach (var track in tracks)
43+
{
44+
if (track.type == TrackTypeEnum.audio)
45+
{
46+
if (mediaInfo.AudioStreams != null && mediaInfo.AudioStreams.Any())
47+
{
48+
var audioStream = mediaInfo.AudioStreams.FirstOrDefault(a => a.Id == (int)track.number);
49+
50+
if (audioStream != null)
51+
{
52+
Debug.WriteLine($"Track #{track.number} (audio) - Format: '{audioStream.Format}', CodecDesc: '{audioStream.CodecDescription}', Bitrate: {audioStream.Bitrate}");
53+
var format = string.Empty;
54+
55+
if (!string.IsNullOrEmpty(audioStream.CodecDescription))
56+
format = audioStream.CodecDescription;
57+
else if (!string.IsNullOrEmpty(audioStream.CodecFriendly))
58+
format = audioStream.CodecFriendly;
59+
else if (!string.IsNullOrEmpty(audioStream.Format))
60+
format = audioStream.Format;
61+
62+
track.detectedFormat = format ?? string.Empty;
63+
track.bitrate = audioStream.Bitrate;
64+
}
65+
else
66+
{
67+
Debug.WriteLine($"Track #{track.number} (audio) - No matching MediaInfo stream found");
68+
}
69+
}
70+
}
71+
else if (track.type == TrackTypeEnum.subtitle)
72+
{
73+
var subtitleStream = mediaInfo.Subtitles?.FirstOrDefault(s => s.Id == (int)track.number);
74+
75+
if (subtitleStream != null)
76+
{
77+
Debug.WriteLine($"Track #{track.number} (subtitle) - Format: '{subtitleStream.Format}'");
78+
track.detectedFormat = subtitleStream.Format ?? string.Empty;
79+
track.bitrate = 0; // Subtitles typically don't have a bitrate, so we set it to 0
80+
}
81+
else
82+
{
83+
Debug.WriteLine($"Track #{track.number} (subtitle) - No matching MediaInfo stream found");
84+
}
85+
}
86+
}
87+
88+
return results;
89+
}
90+
catch (Exception ex)
91+
{
92+
Debug.WriteLine($"MediaInfoHelper exception: {ex.Message}");
93+
Debug.WriteLine($"Stack trace: {ex.StackTrace}");
94+
return results;
95+
}
96+
}
97+
}

MatroskaLib/MatroskaLib/MatroskaLib.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="NEbml" Version="1.1.0.5"/>
11+
<PackageReference Include="MediaInfo.Wrapper.Core" Version="21.9.3" />
12+
<PackageReference Include="NEbml" Version="1.1.0.5" />
1213
</ItemGroup>
1314

1415
</Project>

MatroskaLib/MatroskaLib/MatroskaReader.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.IO;
34
using System.Linq;
5+
using MatroskaLib.Helpers;
46
using MatroskaLib.Types;
57
using NEbml.Core;
68
using NEbml.Matroska;
@@ -17,7 +19,7 @@ public static List<MkvFile> ReadMkvFiles(string[] filePaths)
1719
var tracks = new List<Track>();
1820
var seekList = new List<Seek>();
1921

20-
using var fileStream = File.Open(filePath, FileMode.Open);
22+
using var fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
2123
var reader = new EbmlReader(fileStream);
2224

2325
int? seekHeadCheckSum = _ReadSeekHead(reader, fileStream, seekList);
@@ -44,6 +46,23 @@ public static List<MkvFile> ReadMkvFiles(string[] filePaths)
4446

4547
return mkvFiles;
4648
}
49+
50+
public static void LoadMediaInfoForFile(MkvFile mkvFile)
51+
{
52+
if (mkvFile.mediaInfoLoaded)
53+
return;
54+
55+
try
56+
{
57+
using var fileStream = File.Open(mkvFile.filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
58+
MediaInfoHelper.GetAllTrackFormats(fileStream, mkvFile.tracks);
59+
mkvFile.mediaInfoLoaded = true;
60+
}
61+
catch (System.Exception ex)
62+
{
63+
System.Diagnostics.Debug.WriteLine($"Failed to load MediaInfo for {mkvFile.filePath}: {ex.Message}");
64+
}
65+
}
4766

4867
private static int? _ReadSeekHead(EbmlReader reader, FileStream fileStream, List<Seek> seekList)
4968
{

MatroskaLib/MatroskaLib/MkvFilesContainer.cs

Lines changed: 0 additions & 57 deletions
This file was deleted.

MatroskaLib/MatroskaLib/Types/MkvFile.cs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
21
using System.Collections.Generic;
3-
using System.Linq;
42
using System.Text.Json;
53
using System.Text.Json.Serialization;
64

@@ -17,27 +15,9 @@ public record MkvFile
1715
public required int endPosition { get; init; }
1816
public required int tracksPosition { get; init; }
1917
public required int beginHeaderPosition { get; init; }
20-
21-
public string? CompareToGetError(MkvFile? other)
22-
{
23-
if (other is null)
24-
throw new ArgumentNullException(nameof(other));
25-
26-
for (int i = 0; i < tracks.Count; i++)
27-
{
28-
var track = tracks[i];
29-
var trackOther = other.tracks.ElementAtOrDefault(i);
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}.";
37-
}
38-
39-
return null;
40-
}
18+
19+
[JsonIgnore]
20+
public bool mediaInfoLoaded { get; set; }
4121

4222
public override string ToString() =>
4323
JsonSerializer.Serialize(this with { filePath = string.Empty }, SourceGeneratedMkvFile.Default.MkvFile);

0 commit comments

Comments
 (0)