Merge pull request #4169 from stanionascu/bdiso-playback

Playback (direct-stream/transcode) of BDISO/BDAV containers
This commit is contained in:
Joshua M. Boniface 2020-12-01 22:36:04 -05:00 committed by GitHub
commit a6199f821b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 117 additions and 279 deletions

View File

@ -12,6 +12,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
@ -81,12 +82,7 @@ namespace Emby.Server.Implementations.MediaEncoder
return false;
}
if (video.VideoType == VideoType.Iso)
{
return false;
}
if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd)
if (video.VideoType == VideoType.Dvd)
{
return false;
}
@ -140,15 +136,19 @@ namespace Emby.Server.Implementations.MediaEncoder
// Add some time for the first chapter to make sure we don't end up with a black image
var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(_firstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks);
var protocol = MediaProtocol.File;
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, null, Array.Empty<string>());
var inputPath = video.Path;
Directory.CreateDirectory(Path.GetDirectoryName(path));
var container = video.Container;
var mediaSource = new MediaSourceInfo
{
VideoType = video.VideoType,
IsoType = video.IsoType,
Protocol = video.PathProtocol.Value,
};
var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false);
var tempFile = await _encoder.ExtractVideoImage(inputPath, container, mediaSource, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false);
File.Copy(tempFile, path, true);
try

View File

@ -762,11 +762,6 @@ namespace Jellyfin.Api.Helpers
private async Task AcquireResources(StreamState state, CancellationTokenSource cancellationTokenSource)
{
if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && _isoManager.CanMount(state.MediaPath))
{
state.IsoMount = await _isoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
}
if (state.MediaSource.RequiresOpening && string.IsNullOrWhiteSpace(state.Request.LiveStreamId))
{
var liveStreamResponse = await _mediaSourceManager.OpenLiveStream(

View File

@ -143,26 +143,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The video3 D format.</value>
public Video3DFormat? Video3DFormat { get; set; }
public string[] GetPlayableStreamFileNames()
{
var videoType = VideoType;
if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.BluRay)
{
videoType = VideoType.BluRay;
}
else if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.Dvd)
{
videoType = VideoType.Dvd;
}
else
{
return Array.Empty<string>();
}
throw new NotImplementedException();
}
/// <summary>
/// Gets or sets the aspect ratio.
/// </summary>
@ -415,31 +395,6 @@ namespace MediaBrowser.Controller.Entities
return updateType;
}
public static string[] QueryPlayableStreamFiles(string rootPath, VideoType videoType)
{
if (videoType == VideoType.Dvd)
{
return FileSystem.GetFiles(rootPath, new[] { ".vob" }, false, true)
.OrderByDescending(i => i.Length)
.ThenBy(i => i.FullName)
.Take(1)
.Select(i => i.FullName)
.ToArray();
}
if (videoType == VideoType.BluRay)
{
return FileSystem.GetFiles(rootPath, new[] { ".m2ts" }, false, true)
.OrderByDescending(i => i.Length)
.ThenBy(i => i.FullName)
.Take(1)
.Select(i => i.FullName)
.ToArray();
}
return Array.Empty<string>();
}
/// <summary>
/// Gets a value indicating whether [is3 D].
/// </summary>

View File

@ -390,25 +390,9 @@ namespace MediaBrowser.Controller.MediaEncoding
public string GetInputPathArgument(EncodingJobInfo state)
{
var protocol = state.InputProtocol;
var mediaPath = state.MediaPath ?? string.Empty;
string[] inputPath;
if (state.IsInputVideo
&& !(state.VideoType == VideoType.Iso && state.IsoMount == null))
{
inputPath = MediaEncoderHelpers.GetInputArgument(
_fileSystem,
mediaPath,
state.IsoMount,
state.PlayableStreamFileNames);
}
else
{
inputPath = new[] { mediaPath };
}
return _mediaEncoder.GetInputArgument(inputPath, protocol);
return _mediaEncoder.GetInputArgument(mediaPath, state.MediaSource);
}
/// <summary>
@ -2673,18 +2657,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
public string GetProbeSizeArgument(int numInputFiles)
=> numInputFiles > 1 ? "-probesize " + _configuration.GetFFmpegProbeSize() : string.Empty;
public string GetAnalyzeDurationArgument(int numInputFiles)
=> numInputFiles > 1 ? "-analyzeduration " + _configuration.GetFFmpegAnalyzeDuration() : string.Empty;
public string GetInputModifier(EncodingJobInfo state, EncodingOptions encodingOptions)
{
var inputModifier = string.Empty;
var numInputFiles = state.PlayableStreamFileNames.Length > 0 ? state.PlayableStreamFileNames.Length : 1;
var probeSizeArgument = GetProbeSizeArgument(numInputFiles);
var probeSizeArgument = string.Empty;
string analyzeDurationArgument;
if (state.MediaSource.AnalyzeDurationMs.HasValue)
@ -2693,7 +2669,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else
{
analyzeDurationArgument = GetAnalyzeDurationArgument(numInputFiles);
analyzeDurationArgument = string.Empty;
}
if (!string.IsNullOrEmpty(probeSizeArgument))
@ -2877,32 +2853,6 @@ namespace MediaBrowser.Controller.MediaEncoding
state.IsoType = mediaSource.IsoType;
if (mediaSource.VideoType.HasValue)
{
state.VideoType = mediaSource.VideoType.Value;
if (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd)
{
state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, mediaSource.VideoType.Value).Select(Path.GetFileName).ToArray();
}
else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.BluRay)
{
state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.BluRay).Select(Path.GetFileName).ToArray();
}
else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.Dvd)
{
state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.Dvd).Select(Path.GetFileName).ToArray();
}
else
{
state.PlayableStreamFileNames = Array.Empty<string>();
}
}
else
{
state.PlayableStreamFileNames = Array.Empty<string>();
}
if (mediaSource.Timestamp.HasValue)
{
state.InputTimestamp = mediaSource.Timestamp.Value;

View File

@ -33,10 +33,6 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool IsInputVideo { get; set; }
public IIsoMount IsoMount { get; set; }
public string[] PlayableStreamFileNames { get; set; }
public string OutputAudioCodec { get; set; }
public int? OutputVideoBitrate { get; set; }
@ -313,7 +309,6 @@ namespace MediaBrowser.Controller.MediaEncoding
{
TranscodingType = jobType;
RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
PlayableStreamFileNames = Array.Empty<string>();
SupportedAudioCodecs = Array.Empty<string>();
SupportedVideoCodecs = Array.Empty<string>();
SupportedSubtitleCodecs = Array.Empty<string>();

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
@ -61,18 +62,18 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <summary>
/// Extracts the video image.
/// </summary>
Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken);
Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken);
/// <summary>
/// Extracts the video images on interval.
/// </summary>
Task ExtractVideoImagesOnInterval(
string[] inputFiles,
string inputFile,
string container,
MediaStream videoStream,
MediaProtocol protocol,
MediaSourceInfo mediaSource,
Video3DFormat? threedFormat,
TimeSpan interval,
string targetDirectory,
@ -91,10 +92,10 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <summary>
/// Gets the input argument.
/// </summary>
/// <param name="inputFiles">The input files.</param>
/// <param name="protocol">The protocol.</param>
/// <param name="inputFile">The input file.</param>
/// <param name="mediaSource">The mediaSource.</param>
/// <returns>System.String.</returns>
string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol);
string GetInputArgument(string inputFile, MediaSourceInfo mediaSource);
/// <summary>
/// Gets the time parameter.

View File

@ -13,38 +13,5 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary>
public static class MediaEncoderHelpers
{
/// <summary>
/// Gets the input argument.
/// </summary>
/// <param name="fileSystem">The file system.</param>
/// <param name="videoPath">The video path.</param>
/// <param name="isoMount">The iso mount.</param>
/// <param name="playableStreamFileNames">The playable stream file names.</param>
/// <returns>string[].</returns>
public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, IIsoMount isoMount, IReadOnlyCollection<string> playableStreamFileNames)
{
if (playableStreamFileNames.Count > 0)
{
if (isoMount == null)
{
return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames);
}
return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames);
}
return new[] { videoPath };
}
private static string[] GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, IEnumerable<string> filenames)
{
var allFiles = fileSystem
.GetFilePaths(rootPath, true)
.ToArray();
return filenames.Select(name => allFiles.FirstOrDefault(f => string.Equals(Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase)))
.Where(f => !string.IsNullOrEmpty(f))
.ToArray();
}
}
}

View File

@ -1,9 +1,7 @@
#pragma warning disable CS1591
using System;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Controller.MediaEncoding
{
@ -14,14 +12,5 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool ExtractChapters { get; set; }
public DlnaProfileType MediaType { get; set; }
public IIsoMount MountedIso { get; set; }
public string[] PlayableStreamFileNames { get; set; }
public MediaInfoRequest()
{
PlayableStreamFileNames = Array.Empty<string>();
}
}
}

View File

@ -87,19 +87,19 @@ namespace MediaBrowser.MediaEncoding.Attachments
MediaAttachment mediaAttachment,
CancellationToken cancellationToken)
{
var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false);
var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource, mediaAttachment, cancellationToken).ConfigureAwait(false);
return File.OpenRead(attachmentPath);
}
private async Task<string> GetReadableFile(
string mediaPath,
string inputFile,
MediaProtocol protocol,
MediaSourceInfo mediaSource,
MediaAttachment mediaAttachment,
CancellationToken cancellationToken)
{
var outputPath = GetAttachmentCachePath(mediaPath, protocol, mediaAttachment.Index);
await ExtractAttachment(inputFile, protocol, mediaAttachment.Index, outputPath, cancellationToken)
var outputPath = GetAttachmentCachePath(mediaPath, mediaSource, mediaAttachment.Index);
await ExtractAttachment(inputFile, mediaSource, mediaAttachment.Index, outputPath, cancellationToken)
.ConfigureAwait(false);
return outputPath;
@ -107,7 +107,7 @@ namespace MediaBrowser.MediaEncoding.Attachments
private async Task ExtractAttachment(
string inputFile,
MediaProtocol protocol,
MediaSourceInfo mediaSource,
int attachmentStreamIndex,
string outputPath,
CancellationToken cancellationToken)
@ -121,7 +121,7 @@ namespace MediaBrowser.MediaEncoding.Attachments
if (!File.Exists(outputPath))
{
await ExtractAttachmentInternal(
_mediaEncoder.GetInputArgument(new[] { inputFile }, protocol),
_mediaEncoder.GetInputArgument(inputFile, mediaSource),
attachmentStreamIndex,
outputPath,
cancellationToken).ConfigureAwait(false);
@ -234,10 +234,10 @@ namespace MediaBrowser.MediaEncoding.Attachments
}
}
private string GetAttachmentCachePath(string mediaPath, MediaProtocol protocol, int attachmentStreamIndex)
private string GetAttachmentCachePath(string mediaPath, MediaSourceInfo mediaSource, int attachmentStreamIndex)
{
string filename;
if (protocol == MediaProtocol.File)
if (mediaSource.Protocol == MediaProtocol.File)
{
var date = _fileSystem.GetLastWriteTimeUtc(mediaPath);
filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D", CultureInfo.InvariantCulture);

View File

@ -1,53 +1,44 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.MediaEncoding.Encoder
{
public static class EncodingUtils
{
public static string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol)
public static string GetInputArgument(string inputPrefix, string inputFile, MediaProtocol protocol)
{
if (protocol != MediaProtocol.File)
{
var url = inputFiles[0];
return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", url);
return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", inputFile);
}
return GetConcatInputArgument(inputFiles);
return GetConcatInputArgument(inputFile, inputPrefix);
}
/// <summary>
/// Gets the concat input argument.
/// </summary>
/// <param name="inputFiles">The input files.</param>
/// <param name="inputFile">The input file.</param>
/// <param name="inputPrefix">The input prefix.</param>
/// <returns>System.String.</returns>
private static string GetConcatInputArgument(IReadOnlyList<string> inputFiles)
private static string GetConcatInputArgument(string inputFile, string inputPrefix)
{
// Get all streams
// If there's more than one we'll need to use the concat command
if (inputFiles.Count > 1)
{
var files = string.Join("|", inputFiles.Select(NormalizePath));
return string.Format(CultureInfo.InvariantCulture, "concat:\"{0}\"", files);
}
// Determine the input path for video files
return GetFileInputArgument(inputFiles[0]);
return GetFileInputArgument(inputFile, inputPrefix);
}
/// <summary>
/// Gets the file input argument.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="inputPrefix">The path prefix.</param>
/// <returns>System.String.</returns>
private static string GetFileInputArgument(string path)
private static string GetFileInputArgument(string path, string inputPrefix)
{
if (path.IndexOf("://", StringComparison.Ordinal) != -1)
{
@ -57,7 +48,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
// Quotes are valid path characters in linux and they need to be escaped here with a leading \
path = NormalizePath(path);
return string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", path);
return string.Format(CultureInfo.InvariantCulture, "{1}:\"{0}\"", path, inputPrefix);
}
/// <summary>

View File

@ -18,6 +18,7 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.MediaEncoding.Probing;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
@ -83,8 +84,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
_jsonSerializerOptions = JsonDefaults.GetOptions();
}
private EncodingHelper EncodingHelper => _encodingHelperFactory.Value;
/// <inheritdoc />
public string EncoderPath => _ffmpegPath;
@ -320,33 +319,24 @@ namespace MediaBrowser.MediaEncoding.Encoder
public Task<MediaInfo> GetMediaInfo(MediaInfoRequest request, CancellationToken cancellationToken)
{
var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters;
var inputFile = request.MediaSource.Path;
var inputFiles = MediaEncoderHelpers.GetInputArgument(_fileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames);
var probeSize = EncodingHelper.GetProbeSizeArgument(inputFiles.Length);
string analyzeDuration;
string analyzeDuration = string.Empty;
if (request.MediaSource.AnalyzeDurationMs > 0)
{
analyzeDuration = "-analyzeduration " +
(request.MediaSource.AnalyzeDurationMs * 1000).ToString();
}
else
{
analyzeDuration = EncodingHelper.GetAnalyzeDurationArgument(inputFiles.Length);
}
probeSize = probeSize + " " + analyzeDuration;
probeSize = probeSize.Trim();
var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File;
return GetMediaInfoInternal(
GetInputArgument(inputFiles, request.MediaSource.Protocol),
GetInputArgument(inputFile, request.MediaSource),
request.MediaSource.Path,
request.MediaSource.Protocol,
extractChapters,
probeSize,
analyzeDuration,
request.MediaType == DlnaProfileType.Audio,
request.MediaSource.VideoType,
forceEnableLogging,
@ -356,12 +346,20 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <summary>
/// Gets the input argument.
/// </summary>
/// <param name="inputFiles">The input files.</param>
/// <param name="protocol">The protocol.</param>
/// <param name="inputFile">The input file.</param>
/// <param name="mediaSource">The mediaSource.</param>
/// <returns>System.String.</returns>
/// <exception cref="ArgumentException">Unrecognized InputType.</exception>
public string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol)
=> EncodingUtils.GetInputArgument(inputFiles, protocol);
public string GetInputArgument(string inputFile, MediaSourceInfo mediaSource)
{
var prefix = "file";
if (mediaSource.VideoType == VideoType.BluRay || mediaSource.VideoType == VideoType.Iso)
{
prefix = "bluray";
}
return EncodingUtils.GetInputArgument(prefix, inputFile, mediaSource.Protocol);
}
/// <summary>
/// Gets the media info internal.
@ -459,31 +457,36 @@ namespace MediaBrowser.MediaEncoding.Encoder
public Task<string> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken)
{
return ExtractImage(new[] { path }, null, null, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken);
var mediaSource = new MediaSourceInfo
{
Protocol = MediaProtocol.File
};
return ExtractImage(path, null, null, imageStreamIndex, mediaSource, true, null, null, cancellationToken);
}
public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
{
return ExtractImage(inputFiles, container, videoStream, null, protocol, false, threedFormat, offset, cancellationToken);
return ExtractImage(inputFile, container, videoStream, null, mediaSource, false, threedFormat, offset, cancellationToken);
}
public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken)
public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken)
{
return ExtractImage(inputFiles, container, imageStream, imageStreamIndex, protocol, false, null, null, cancellationToken);
return ExtractImage(inputFile, container, imageStream, imageStreamIndex, mediaSource, false, null, null, cancellationToken);
}
private async Task<string> ExtractImage(
string[] inputFiles,
string inputFile,
string container,
MediaStream videoStream,
int? imageStreamIndex,
MediaProtocol protocol,
MediaSourceInfo mediaSource,
bool isAudio,
Video3DFormat? threedFormat,
TimeSpan? offset,
CancellationToken cancellationToken)
{
var inputArgument = GetInputArgument(inputFiles, protocol);
var inputArgument = GetInputArgument(inputFile, mediaSource);
if (isAudio)
{
@ -569,8 +572,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads);
var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1);
var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1);
var probeSizeArgument = string.Empty;
var analyzeDurationArgument = string.Empty;
if (!string.IsNullOrWhiteSpace(probeSizeArgument))
{
@ -679,10 +682,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
public async Task ExtractVideoImagesOnInterval(
string[] inputFiles,
string inputFile,
string container,
MediaStream videoStream,
MediaProtocol protocol,
MediaSourceInfo mediaSource,
Video3DFormat? threedFormat,
TimeSpan interval,
string targetDirectory,
@ -690,7 +693,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
int? maxWidth,
CancellationToken cancellationToken)
{
var inputArgument = GetInputArgument(inputFiles, protocol);
var inputArgument = GetInputArgument(inputFile, mediaSource);
var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(_usCulture);
@ -706,8 +709,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, threads);
var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1);
var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1);
var probeSizeArgument = string.Empty;
var analyzeDurationArgument = string.Empty;
if (!string.IsNullOrWhiteSpace(probeSizeArgument))
{

View File

@ -168,18 +168,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
MediaStream subtitleStream,
CancellationToken cancellationToken)
{
string[] inputFiles;
if (mediaSource.VideoType.HasValue
&& (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd))
{
var mediaSourceItem = (Video)_libraryManager.GetItemById(new Guid(mediaSource.Id));
inputFiles = mediaSourceItem.GetPlayableStreamFileNames();
}
else
{
inputFiles = new[] { mediaSource.Path };
}
var inputFile = mediaSource.Path;
var protocol = mediaSource.Protocol;
if (subtitleStream.IsExternal)
@ -187,7 +176,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
protocol = _mediaSourceManager.GetPathProtocol(subtitleStream.Path);
}
var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, protocol, subtitleStream, cancellationToken).ConfigureAwait(false);
var fileInfo = await GetReadableFile(mediaSource.Path, inputFile, mediaSource, subtitleStream, cancellationToken).ConfigureAwait(false);
var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false);
@ -220,8 +209,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
private async Task<SubtitleInfo> GetReadableFile(
string mediaPath,
string[] inputFiles,
MediaProtocol protocol,
string inputFile,
MediaSourceInfo mediaSource,
MediaStream subtitleStream,
CancellationToken cancellationToken)
{
@ -252,9 +241,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
// Extract
var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, "." + outputFormat);
var outputPath = GetSubtitleCachePath(mediaPath, mediaSource, subtitleStream.Index, "." + outputFormat);
await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, outputCodec, outputPath, cancellationToken)
await ExtractTextSubtitle(inputFile, mediaSource, subtitleStream.Index, outputCodec, outputPath, cancellationToken)
.ConfigureAwait(false);
return new SubtitleInfo(outputPath, MediaProtocol.File, outputFormat, false);
@ -266,14 +255,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (GetReader(currentFormat, false) == null)
{
// Convert
var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, ".srt");
var outputPath = GetSubtitleCachePath(mediaPath, mediaSource, subtitleStream.Index, ".srt");
await ConvertTextSubtitleToSrt(subtitleStream.Path, subtitleStream.Language, protocol, outputPath, cancellationToken).ConfigureAwait(false);
await ConvertTextSubtitleToSrt(subtitleStream.Path, subtitleStream.Language, mediaSource, outputPath, cancellationToken).ConfigureAwait(false);
return new SubtitleInfo(outputPath, MediaProtocol.File, "srt", true);
}
return new SubtitleInfo(subtitleStream.Path, protocol, currentFormat, true);
return new SubtitleInfo(subtitleStream.Path, mediaSource.Protocol, currentFormat, true);
}
private ISubtitleParser GetReader(string format, bool throwIfMissing)
@ -363,11 +352,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="language">The language.</param>
/// <param name="inputProtocol">The input protocol.</param>
/// <param name="mediaSource">The input mediaSource.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task ConvertTextSubtitleToSrt(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken)
private async Task ConvertTextSubtitleToSrt(string inputPath, string language, MediaSourceInfo mediaSource, string outputPath, CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@ -377,7 +366,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
if (!File.Exists(outputPath))
{
await ConvertTextSubtitleToSrtInternal(inputPath, language, inputProtocol, outputPath, cancellationToken).ConfigureAwait(false);
await ConvertTextSubtitleToSrtInternal(inputPath, language, mediaSource, outputPath, cancellationToken).ConfigureAwait(false);
}
}
finally
@ -391,14 +380,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="language">The language.</param>
/// <param name="inputProtocol">The input protocol.</param>
/// <param name="mediaSource">The input mediaSource.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">
/// The <c>inputPath</c> or <c>outputPath</c> is <c>null</c>.
/// </exception>
private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken)
private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaSourceInfo mediaSource, string outputPath, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{
@ -412,7 +401,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false);
var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, mediaSource.Protocol, cancellationToken).ConfigureAwait(false);
// FFmpeg automatically convert character encoding when it is UTF-16
// If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event"
@ -515,8 +504,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// <summary>
/// Extracts the text subtitle.
/// </summary>
/// <param name="inputFiles">The input files.</param>
/// <param name="protocol">The protocol.</param>
/// <param name="inputFile">The input file.</param>
/// <param name="mediaSource">The mediaSource.</param>
/// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
/// <param name="outputCodec">The output codec.</param>
/// <param name="outputPath">The output path.</param>
@ -524,8 +513,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// <returns>Task.</returns>
/// <exception cref="ArgumentException">Must use inputPath list overload.</exception>
private async Task ExtractTextSubtitle(
string[] inputFiles,
MediaProtocol protocol,
string inputFile,
MediaSourceInfo mediaSource,
int subtitleStreamIndex,
string outputCodec,
string outputPath,
@ -540,7 +529,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (!File.Exists(outputPath))
{
await ExtractTextSubtitleInternal(
_mediaEncoder.GetInputArgument(inputFiles, protocol),
_mediaEncoder.GetInputArgument(inputFile, mediaSource),
subtitleStreamIndex,
outputCodec,
outputPath,
@ -706,9 +695,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
private string GetSubtitleCachePath(string mediaPath, MediaProtocol protocol, int subtitleStreamIndex, string outputSubtitleExtension)
private string GetSubtitleCachePath(string mediaPath, MediaSourceInfo mediaSource, int subtitleStreamIndex, string outputSubtitleExtension)
{
if (protocol == MediaProtocol.File)
if (mediaSource.Protocol == MediaProtocol.File)
{
var ticksParam = string.Empty;

View File

@ -150,11 +150,6 @@ namespace MediaBrowser.Providers.MediaInfo
public Task<ItemUpdateType> FetchVideoInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
where T : Video
{
if (item.VideoType == VideoType.Iso)
{
return _cachedTask;
}
if (item.IsPlaceHolder)
{
return _cachedTask;

View File

@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.MediaInfo
streamFileNames = Array.Empty<string>();
}
mediaInfoResult = await GetMediaInfo(item, streamFileNames, cancellationToken).ConfigureAwait(false);
mediaInfoResult = await GetMediaInfo(item, cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
}
@ -128,7 +128,6 @@ namespace MediaBrowser.Providers.MediaInfo
private Task<Model.MediaInfo.MediaInfo> GetMediaInfo(
Video item,
string[] streamFileNames,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@ -145,7 +144,6 @@ namespace MediaBrowser.Providers.MediaInfo
return _mediaEncoder.GetMediaInfo(
new MediaInfoRequest
{
PlayableStreamFileNames = streamFileNames,
ExtractChapters = true,
MediaType = DlnaProfileType.Video,
MediaSource = new MediaSourceInfo

View File

@ -9,6 +9,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
@ -50,7 +51,7 @@ namespace MediaBrowser.Providers.MediaInfo
}
// No support for this
if (video.VideoType == VideoType.Iso || video.VideoType == VideoType.Dvd || video.VideoType == VideoType.BluRay)
if (video.VideoType == VideoType.Dvd)
{
return Task.FromResult(new DynamicImageResponse { HasImage = false });
}
@ -69,11 +70,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
var protocol = item.PathProtocol ?? MediaProtocol.File;
var inputPath = MediaEncoderHelpers.GetInputArgument(
_fileSystem,
item.Path,
null,
item.GetPlayableStreamFileNames());
var inputPath = item.Path;
var mediaStreams =
item.GetMediaStreams();
@ -107,7 +104,14 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, imageStream, videoIndex, cancellationToken).ConfigureAwait(false);
MediaSourceInfo mediaSource = new MediaSourceInfo
{
VideoType = item.VideoType,
IsoType = item.IsoType,
Protocol = item.PathProtocol.Value,
};
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, mediaSource, imageStream, videoIndex, cancellationToken).ConfigureAwait(false);
}
else
{
@ -119,8 +123,14 @@ namespace MediaBrowser.Providers.MediaInfo
: TimeSpan.FromSeconds(10);
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
var mediaSource = new MediaSourceInfo
{
VideoType = item.VideoType,
IsoType = item.IsoType,
Protocol = item.PathProtocol.Value,
};
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, mediaSource, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
}
return new DynamicImageResponse