jellyfin/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs

184 lines
5.9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
2024-07-20 10:50:14 -07:00
using System.Globalization;
using System.Linq;
using BDInfo;
2024-07-20 10:50:14 -07:00
using Jellyfin.Extensions;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
2023-02-18 06:42:35 -07:00
namespace MediaBrowser.MediaEncoding.BdInfo;
/// <summary>
/// Class BdInfoExaminer.
/// </summary>
public class BdInfoExaminer : IBlurayExaminer
{
2023-02-18 06:42:35 -07:00
private readonly IFileSystem _fileSystem;
/// <summary>
2023-02-18 06:42:35 -07:00
/// Initializes a new instance of the <see cref="BdInfoExaminer" /> class.
/// </summary>
2023-02-18 06:42:35 -07:00
/// <param name="fileSystem">The filesystem.</param>
public BdInfoExaminer(IFileSystem fileSystem)
{
2023-02-18 06:42:35 -07:00
_fileSystem = fileSystem;
}
2023-02-18 06:42:35 -07:00
/// <summary>
/// Gets the disc info.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>BlurayDiscInfo.</returns>
public BlurayDiscInfo GetDiscInfo(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
2023-02-18 06:42:35 -07:00
throw new ArgumentNullException(nameof(path));
}
2023-02-18 06:42:35 -07:00
var bdrom = new BDROM(BdInfoDirectoryInfo.FromFileSystemPath(_fileSystem, path));
2023-02-18 06:42:35 -07:00
bdrom.Scan();
2023-02-18 06:42:35 -07:00
// Get the longest playlist
var playlist = bdrom.PlaylistFiles.Values.OrderByDescending(p => p.TotalLength).FirstOrDefault(p => p.IsValid);
2023-02-18 06:42:35 -07:00
var outputStream = new BlurayDiscInfo
{
MediaStreams = Array.Empty<MediaStream>()
};
2023-02-18 06:42:35 -07:00
if (playlist is null)
{
return outputStream;
}
2023-02-18 06:42:35 -07:00
outputStream.Chapters = playlist.Chapters.ToArray();
2023-02-18 06:42:35 -07:00
outputStream.RunTimeTicks = TimeSpan.FromSeconds(playlist.TotalLength).Ticks;
2023-02-18 06:42:35 -07:00
var sortedStreams = playlist.SortedStreams;
var mediaStreams = new List<MediaStream>(sortedStreams.Count);
for (int i = 0; i < sortedStreams.Count; i++)
2023-02-18 06:42:35 -07:00
{
var stream = sortedStreams[i];
2023-02-18 06:42:35 -07:00
switch (stream)
{
2023-02-18 06:42:35 -07:00
case TSVideoStream videoStream:
AddVideoStream(mediaStreams, i, videoStream);
2023-02-18 06:42:35 -07:00
break;
case TSAudioStream audioStream:
AddAudioStream(mediaStreams, i, audioStream);
2023-02-18 06:42:35 -07:00
break;
case TSTextStream:
case TSGraphicsStream:
AddSubtitleStream(mediaStreams, i, stream);
2023-02-18 06:42:35 -07:00
break;
}
2023-02-18 06:42:35 -07:00
}
2023-02-18 06:42:35 -07:00
outputStream.MediaStreams = mediaStreams.ToArray();
2023-02-18 06:42:35 -07:00
outputStream.PlaylistName = playlist.Name;
2023-02-18 06:42:35 -07:00
if (playlist.StreamClips is not null && playlist.StreamClips.Count > 0)
{
// Get the files in the playlist
outputStream.Files = playlist.StreamClips.Select(i => i.StreamFile.FileInfo.FullName).ToArray();
}
2023-02-18 06:42:35 -07:00
return outputStream;
}
2023-02-18 06:42:35 -07:00
/// <summary>
/// Adds the video stream.
/// </summary>
/// <param name="streams">The streams.</param>
/// <param name="index">The stream index.</param>
2023-02-18 06:42:35 -07:00
/// <param name="videoStream">The video stream.</param>
private void AddVideoStream(List<MediaStream> streams, int index, TSVideoStream videoStream)
2023-02-18 06:42:35 -07:00
{
var mediaStream = new MediaStream
{
BitRate = Convert.ToInt32(videoStream.BitRate),
Width = videoStream.Width,
Height = videoStream.Height,
2024-07-20 10:50:14 -07:00
Codec = GetNormalizedCodec(videoStream),
2023-02-18 06:42:35 -07:00
IsInterlaced = videoStream.IsInterlaced,
Type = MediaStreamType.Video,
Index = index
2023-02-18 06:42:35 -07:00
};
if (videoStream.FrameRateDenominator > 0)
{
float frameRateEnumerator = videoStream.FrameRateEnumerator;
float frameRateDenominator = videoStream.FrameRateDenominator;
2023-02-18 06:42:35 -07:00
mediaStream.AverageFrameRate = mediaStream.RealFrameRate = frameRateEnumerator / frameRateDenominator;
}
2023-02-18 06:42:35 -07:00
streams.Add(mediaStream);
}
2023-02-18 06:42:35 -07:00
/// <summary>
/// Adds the audio stream.
/// </summary>
/// <param name="streams">The streams.</param>
/// <param name="index">The stream index.</param>
2023-02-18 06:42:35 -07:00
/// <param name="audioStream">The audio stream.</param>
private void AddAudioStream(List<MediaStream> streams, int index, TSAudioStream audioStream)
2023-02-18 06:42:35 -07:00
{
var stream = new MediaStream
{
2024-07-20 10:50:14 -07:00
Codec = GetNormalizedCodec(audioStream),
2023-02-18 06:42:35 -07:00
Language = audioStream.LanguageCode,
2024-07-20 10:50:14 -07:00
ChannelLayout = string.Format(CultureInfo.InvariantCulture, "{0:D}.{1:D}", audioStream.ChannelCount, audioStream.LFE),
Channels = audioStream.ChannelCount + audioStream.LFE,
2023-02-18 06:42:35 -07:00
SampleRate = audioStream.SampleRate,
Type = MediaStreamType.Audio,
Index = index
2023-02-18 06:42:35 -07:00
};
2023-02-18 06:42:35 -07:00
var bitrate = Convert.ToInt32(audioStream.BitRate);
2023-02-18 06:42:35 -07:00
if (bitrate > 0)
{
stream.BitRate = bitrate;
}
2023-02-18 06:42:35 -07:00
streams.Add(stream);
}
/// <summary>
/// Adds the subtitle stream.
/// </summary>
/// <param name="streams">The streams.</param>
/// <param name="index">The stream index.</param>
2024-07-20 10:50:14 -07:00
/// <param name="stream">The stream.</param>
private void AddSubtitleStream(List<MediaStream> streams, int index, TSStream stream)
2023-02-18 06:42:35 -07:00
{
streams.Add(new MediaStream
{
2024-07-20 10:50:14 -07:00
Language = stream.LanguageCode,
Codec = GetNormalizedCodec(stream),
2023-02-18 06:42:35 -07:00
Type = MediaStreamType.Subtitle,
Index = index
2023-02-18 06:42:35 -07:00
});
}
2024-07-20 10:50:14 -07:00
private string GetNormalizedCodec(TSStream stream)
=> stream.StreamType switch
{
2024-07-20 10:50:14 -07:00
TSStreamType.MPEG1_VIDEO => "mpeg1video",
TSStreamType.MPEG2_VIDEO => "mpeg2video",
TSStreamType.VC1_VIDEO => "vc1",
2024-07-20 11:37:44 -07:00
TSStreamType.AC3_PLUS_AUDIO or TSStreamType.AC3_PLUS_SECONDARY_AUDIO => "eac3",
TSStreamType.DTS_AUDIO or TSStreamType.DTS_HD_AUDIO or TSStreamType.DTS_HD_MASTER_AUDIO or TSStreamType.DTS_HD_SECONDARY_AUDIO => "dts",
TSStreamType.PRESENTATION_GRAPHICS => "pgssub",
2024-07-20 10:50:14 -07:00
_ => stream.CodecShortName
};
}