Skip to content

Commit 19c5e9a

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 19c5e9a

14 files changed

Lines changed: 534 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: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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 void GetAllTrackFormats(Stream stream, IEnumerable<Track> tracks)
16+
{
17+
18+
try
19+
{
20+
if (!stream.CanSeek)
21+
{
22+
Debug.WriteLine($"Stream is not seekable, cannot use MediaInfo");
23+
return results;
24+
}
25+
26+
long originalPosition = stream.Position;
27+
stream.Position = 0;
28+
29+
var mediaInfo = new MediaInfoWrapper(stream, NullLogger.Instance);
30+
31+
stream.Position = originalPosition;
32+
33+
if (!mediaInfo.Success)
34+
{
35+
Debug.WriteLine($"MediaInfo failed to read from stream");
36+
return results;
37+
}
38+
39+
Debug.WriteLine($"MediaInfo found {mediaInfo.AudioStreams?.Count ?? 0} audio streams, {mediaInfo.Subtitles?.Count ?? 0} subtitle streams");
40+
41+
foreach (var track in tracks)
42+
{
43+
if (track.type == TrackTypeEnum.audio)
44+
{
45+
if (mediaInfo.AudioStreams != null && mediaInfo.AudioStreams.Any())
46+
{
47+
var audioStream = mediaInfo.AudioStreams.FirstOrDefault(a => a.Id == (int)track.number);
48+
49+
if (audioStream != null)
50+
{
51+
Debug.WriteLine($"Track #{track.number} (audio) - Format: '{audioStream.Format}', CodecDesc: '{audioStream.CodecDescription}', Bitrate: {audioStream.Bitrate}");
52+
var format = string.Empty;
53+
54+
if (!string.IsNullOrEmpty(audioStream.CodecDescription))
55+
format = audioStream.CodecDescription;
56+
else if (!string.IsNullOrEmpty(audioStream.CodecFriendly))
57+
format = audioStream.CodecFriendly;
58+
else if (!string.IsNullOrEmpty(audioStream.Format))
59+
format = audioStream.Format;
60+
61+
track.detectedFormat = format ?? string.Empty;
62+
track.bitrate = audioStream.Bitrate;
63+
}
64+
else
65+
{
66+
Debug.WriteLine($"Track #{track.number} (audio) - No matching MediaInfo stream found");
67+
}
68+
}
69+
}
70+
else if (track.type == TrackTypeEnum.subtitle)
71+
{
72+
var subtitleStream = mediaInfo.Subtitles?.FirstOrDefault(s => s.Id == (int)track.number);
73+
74+
if (subtitleStream != null)
75+
{
76+
Debug.WriteLine($"Track #{track.number} (subtitle) - Format: '{subtitleStream.Format}'");
77+
track.detectedFormat = subtitleStream.Format ?? string.Empty;
78+
track.bitrate = 0; // Subtitles typically don't have a bitrate, so we set it to 0
79+
}
80+
else
81+
{
82+
Debug.WriteLine($"Track #{track.number} (subtitle) - No matching MediaInfo stream found");
83+
}
84+
}
85+
}
86+
}
87+
catch (Exception ex)
88+
{
89+
Debug.WriteLine($"MediaInfoHelper exception: {ex.Message}");
90+
Debug.WriteLine($"Stack trace: {ex.StackTrace}");
91+
}
92+
}
93+
}

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)