From 57e5b59b93272bbbafeb1b57bdacc862c48f0996 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Wed, 11 Nov 2020 17:08:50 +0800 Subject: adjust bitrate limit for HLS audio codecs --- .../Probing/ProbeResultNormalizer.cs | 112 ++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index cdeefbbbd..1b0d4d1af 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -234,8 +234,8 @@ namespace MediaBrowser.MediaEncoding.Probing var channelsValue = channels.Value; - if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) || - string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) { if (channelsValue <= 2) { @@ -248,6 +248,34 @@ namespace MediaBrowser.MediaEncoding.Probing } } + if (string.Equals(codec, "ac3", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) + { + if (channelsValue <= 2) + { + return 192000; + } + + if (channelsValue >= 5) + { + return 640000; + } + } + + if (string.Equals(codec, "flac", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "alac", StringComparison.OrdinalIgnoreCase)) + { + if (channelsValue <= 2) + { + return 960000; + } + + if (channelsValue >= 5) + { + return 2880000; + } + } + return null; } @@ -774,6 +802,35 @@ namespace MediaBrowser.MediaEncoding.Probing stream.BitRate = bitrate; } + // Extract bitrate info from tag "BPS" if possible. + if (!stream.BitRate.HasValue + && (string.Equals(streamInfo.CodecType, "audio", StringComparison.OrdinalIgnoreCase) + || string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase))) + { + var bps = GetBPSFromTags(streamInfo); + if (bps != null && bps > 0) + { + stream.BitRate = bps; + } + } + + // Get average bitrate info from tag "NUMBER_OF_BYTES" and "DURATION" if possible. + if (!stream.BitRate.HasValue + && (string.Equals(streamInfo.CodecType, "audio", StringComparison.OrdinalIgnoreCase) + || string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase))) + { + var durationInSeconds = GetRuntimeSecondsFromTags(streamInfo); + var bytes = GetNumberOfBytesFromTags(streamInfo); + if (durationInSeconds != null && bytes != null) + { + var bps = Convert.ToInt32(bytes * 8 / durationInSeconds); + if (bps > 0) + { + stream.BitRate = bps; + } + } + } + var disposition = streamInfo.Disposition; if (disposition != null) { @@ -963,6 +1020,57 @@ namespace MediaBrowser.MediaEncoding.Probing } } + private int? GetBPSFromTags(MediaStreamInfo streamInfo) + { + if (streamInfo != null && streamInfo.Tags != null) + { + var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); + if (!string.IsNullOrEmpty(bps)) + { + if (int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) + { + return parsedBps; + } + } + } + + return null; + } + + private double? GetRuntimeSecondsFromTags(MediaStreamInfo streamInfo) + { + if (streamInfo != null && streamInfo.Tags != null) + { + var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); + if (!string.IsNullOrEmpty(duration)) + { + if (TimeSpan.TryParse(duration, out var parsedDuration)) + { + return parsedDuration.TotalSeconds; + } + } + } + + return null; + } + + private long? GetNumberOfBytesFromTags(MediaStreamInfo streamInfo) + { + if (streamInfo != null && streamInfo.Tags != null) + { + var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); + if (!string.IsNullOrEmpty(numberOfBytes)) + { + if (long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) + { + return parsedBytes; + } + } + } + + return null; + } + private void SetSize(InternalMediaInfoResult data, MediaInfo info) { if (data.Format != null) -- cgit v1.2.3 From 6987cb83570a6a822260691f009f4b3762d98942 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Wed, 11 Nov 2020 17:25:14 +0800 Subject: fix ci --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 1b0d4d1af..d6b87477c 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -823,7 +823,7 @@ namespace MediaBrowser.MediaEncoding.Probing var bytes = GetNumberOfBytesFromTags(streamInfo); if (durationInSeconds != null && bytes != null) { - var bps = Convert.ToInt32(bytes * 8 / durationInSeconds); + var bps = Convert.ToInt32(bytes * 8 / durationInSeconds, CultureInfo.InvariantCulture); if (bps > 0) { stream.BitRate = bps; -- cgit v1.2.3 From 5ff08338d5a475d2975ecc6d4fe5222456368bd2 Mon Sep 17 00:00:00 2001 From: Nyanmisaka Date: Thu, 19 Nov 2020 15:02:36 +0000 Subject: Apply suggestions from code review Co-authored-by: Claus Vium --- Jellyfin.Api/Controllers/VideoHlsController.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 6 +++--- .../Probing/ProbeResultNormalizer.cs | 23 ++++++++-------------- MediaBrowser.Model/Dlna/StreamBuilder.cs | 12 +++++------ 4 files changed, 18 insertions(+), 25 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs') diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index bb8026543..b151f85e2 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -578,7 +578,7 @@ namespace Jellyfin.Api.Controllers args += _encodingHelper.GetOutputSizeParam(state, _encodingOptions, codec); } - if (!(state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)) + if (state.SubtitleStream == null || !state.SubtitleStream.IsExternal || state.SubtitleStream.IsTextSubtitleStream) { args += " -start_at_zero"; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index a2e3318f3..6e36adc16 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1194,7 +1194,7 @@ namespace MediaBrowser.Controller.MediaEncoding } } else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase) - || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)) + || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)) { param += " -level " + level; } @@ -1205,7 +1205,7 @@ namespace MediaBrowser.Controller.MediaEncoding // NVENC cannot adjust the given level, just throw an error. } else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) - || !string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) + || !string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) { param += " -level " + level; } @@ -1931,7 +1931,7 @@ namespace MediaBrowser.Controller.MediaEncoding retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\""; } else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) - || string.Equals(outputVideoCodec, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) + || string.Equals(outputVideoCodec, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) { /* QSV in FFMpeg can now setup hardware overlay for transcodes. diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 387594ce6..3d3d1eb48 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1025,12 +1025,10 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo != null && streamInfo.Tags != null) { var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); - if (!string.IsNullOrEmpty(bps)) + if (!string.IsNullOrEmpty(bps) + && int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) { - if (int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) - { - return parsedBps; - } + return parsedBps; } } @@ -1042,12 +1040,9 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo != null && streamInfo.Tags != null) { var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); - if (!string.IsNullOrEmpty(duration)) + if (!string.IsNullOrEmpty(duration) && TimeSpan.TryParse(duration, out var parsedDuration)) { - if (TimeSpan.TryParse(duration, out var parsedDuration)) - { - return parsedDuration.TotalSeconds; - } + return parsedDuration.TotalSeconds; } } @@ -1059,12 +1054,10 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo != null && streamInfo.Tags != null) { var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); - if (!string.IsNullOrEmpty(numberOfBytes)) + if (!string.IsNullOrEmpty(numberOfBytes) + && long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) { - if (long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) - { - return parsedBytes; - } + return parsedBytes; } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 76b137c49..2e5137005 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -928,12 +928,12 @@ namespace MediaBrowser.Model.Dlna defaultBitrate = GetDefaultAudioBitrate(targetAudioCodec, targetAudioChannels); } else if (targetAudioChannels.HasValue - && audioStream.Channels.HasValue - && audioStream.Channels.Value <= targetAudioChannels.Value - && !string.IsNullOrEmpty(audioStream.Codec) - && targetAudioCodecs != null - && targetAudioCodecs.Length > 0 - && !Array.Exists(targetAudioCodecs, elem => string.Equals(audioStream.Codec, elem, StringComparison.OrdinalIgnoreCase))) + && audioStream.Channels.HasValue + && audioStream.Channels.Value <= targetAudioChannels.Value + && !string.IsNullOrEmpty(audioStream.Codec) + && targetAudioCodecs != null + && targetAudioCodecs.Length > 0 + && !Array.Exists(targetAudioCodecs, elem => string.Equals(audioStream.Codec, elem, StringComparison.OrdinalIgnoreCase))) { // Shift the bitrate if we're transcoding to a different audio codec. defaultBitrate = GetDefaultAudioBitrate(targetAudioCodec, audioStream.Channels.Value); -- cgit v1.2.3