3.0.5713.4
This commit is contained in:
parent
0e1b983ffc
commit
4ca526979d
|
@ -1634,11 +1634,6 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
private void TryStreamCopy(StreamState state, VideoStreamRequest videoRequest)
|
||||
{
|
||||
if (!EnableStreamCopy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream))
|
||||
{
|
||||
state.OutputVideoCodec = "copy";
|
||||
|
@ -1650,14 +1645,6 @@ namespace MediaBrowser.Api.Playback
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual bool EnableStreamCopy
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void AttachMediaSourceInfo(StreamState state,
|
||||
MediaSourceInfo mediaSource,
|
||||
VideoStreamRequest videoRequest,
|
||||
|
@ -1741,7 +1728,7 @@ namespace MediaBrowser.Api.Playback
|
|||
state.MediaSource = mediaSource;
|
||||
}
|
||||
|
||||
private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
||||
protected virtual bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
||||
{
|
||||
if (videoStream.IsInterlaced)
|
||||
{
|
||||
|
@ -1889,7 +1876,7 @@ namespace MediaBrowser.Api.Playback
|
|||
return Array.FindIndex(list.ToArray(), t => string.Equals(t, profile, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
|
||||
protected virtual bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
|
||||
{
|
||||
// Source and target codecs must match
|
||||
if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase))
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Devices;
|
||||
using MediaBrowser.Controller.Dlna;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
@ -310,5 +312,33 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
||||
{
|
||||
if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var previousSegment = 0;
|
||||
foreach (var frame in videoStream.KeyFrames)
|
||||
{
|
||||
var length = frame - previousSegment;
|
||||
|
||||
// Don't allow really long segments because this could result in long download times
|
||||
if (length > 10000)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
previousSegment = frame;
|
||||
}
|
||||
|
||||
return base.CanStreamCopyVideo(request, videoStream);
|
||||
}
|
||||
|
||||
protected override bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,7 +160,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
var playlistPath = Path.ChangeExtension(state.OutputFilePath, ".m3u8");
|
||||
|
||||
var segmentPath = GetSegmentPath(state, playlistPath, requestedIndex);
|
||||
var segmentLength = state.SegmentLength;
|
||||
|
||||
var segmentExtension = GetSegmentFileExtension(state);
|
||||
|
||||
|
@ -169,7 +168,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
if (File.Exists(segmentPath))
|
||||
{
|
||||
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
||||
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
|
@ -178,7 +177,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
if (File.Exists(segmentPath))
|
||||
{
|
||||
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
||||
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -214,7 +213,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
DeleteLastFile(playlistPath, segmentExtension, 0);
|
||||
}
|
||||
|
||||
request.StartTimeTicks = GetSeekPositionTicks(state, playlistPath, requestedIndex);
|
||||
request.StartTimeTicks = GetStartPositionTicks(state, requestedIndex);
|
||||
|
||||
job = await StartFfMpeg(state, playlistPath, cancellationTokenSource).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -249,37 +248,76 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
Logger.Info("returning {0}", segmentPath);
|
||||
job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
||||
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// 256k
|
||||
private const int BufferSize = 262144;
|
||||
|
||||
private long GetSeekPositionTicks(StreamState state, string playlist, int requestedIndex)
|
||||
private long GetStartPositionTicks(StreamState state, int requestedIndex)
|
||||
{
|
||||
double startSeconds = 0;
|
||||
var lengths = GetSegmentLengths(state);
|
||||
|
||||
for (var i = 0; i < requestedIndex; i++)
|
||||
{
|
||||
var segmentPath = GetSegmentPath(state, playlist, i);
|
||||
|
||||
//double length;
|
||||
//if (SegmentLengths.TryGetValue(Path.GetFileName(segmentPath), out length))
|
||||
//{
|
||||
// Logger.Debug("Found segment length of {0} for index {1}", length, i);
|
||||
// startSeconds += length;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// startSeconds += state.SegmentLength;
|
||||
//}
|
||||
startSeconds += state.SegmentLength;
|
||||
startSeconds += lengths[requestedIndex];
|
||||
}
|
||||
|
||||
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
||||
return position;
|
||||
}
|
||||
|
||||
private long GetEndPositionTicks(StreamState state, int requestedIndex)
|
||||
{
|
||||
double startSeconds = 0;
|
||||
var lengths = GetSegmentLengths(state);
|
||||
|
||||
for (var i = 0; i <= requestedIndex; i++)
|
||||
{
|
||||
startSeconds += lengths[requestedIndex];
|
||||
}
|
||||
|
||||
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
||||
return position;
|
||||
}
|
||||
|
||||
private double[] GetSegmentLengths(StreamState state)
|
||||
{
|
||||
var result = new List<double>();
|
||||
var encoder = GetVideoEncoder(state);
|
||||
|
||||
if (string.Equals(encoder, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var videoStream = state.VideoStream;
|
||||
if (videoStream.KeyFrames != null && videoStream.KeyFrames.Count > 0)
|
||||
{
|
||||
foreach (var frame in videoStream.KeyFrames)
|
||||
{
|
||||
var seconds = TimeSpan.FromMilliseconds(frame).TotalSeconds;
|
||||
seconds -= result.Sum();
|
||||
result.Add(seconds);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
var ticks = state.RunTimeTicks ?? 0;
|
||||
|
||||
var segmentLengthTicks = TimeSpan.FromSeconds(state.SegmentLength).Ticks;
|
||||
|
||||
while (ticks > 0)
|
||||
{
|
||||
var length = ticks >= segmentLengthTicks ? segmentLengthTicks : ticks;
|
||||
|
||||
result.Add(TimeSpan.FromTicks(length).TotalSeconds);
|
||||
|
||||
ticks -= length;
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public int? GetCurrentTranscodingIndex(string playlist, string segmentExtension)
|
||||
{
|
||||
var job = ApiEntryPoint.Instance.GetTranscodingJob(playlist, TranscodingJobType);
|
||||
|
@ -384,17 +422,16 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state));
|
||||
}
|
||||
|
||||
private async Task<object> GetSegmentResult(string playlistPath,
|
||||
private async Task<object> GetSegmentResult(StreamState state, string playlistPath,
|
||||
string segmentPath,
|
||||
int segmentIndex,
|
||||
int segmentLength,
|
||||
TranscodingJob transcodingJob,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// If all transcoding has completed, just return immediately
|
||||
if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath))
|
||||
{
|
||||
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
||||
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
|
||||
}
|
||||
|
||||
var segmentFilename = Path.GetFileName(segmentPath);
|
||||
|
@ -414,7 +451,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
{
|
||||
if (File.Exists(segmentPath))
|
||||
{
|
||||
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
||||
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
|
||||
}
|
||||
//break;
|
||||
}
|
||||
|
@ -465,13 +502,12 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
//}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
||||
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
|
||||
}
|
||||
|
||||
private object GetSegmentResult(string segmentPath, int index, int segmentLength, TranscodingJob transcodingJob)
|
||||
private object GetSegmentResult(StreamState state, string segmentPath, int index, TranscodingJob transcodingJob)
|
||||
{
|
||||
var segmentEndingSeconds = (1 + index) * segmentLength;
|
||||
var segmentEndingPositionTicks = TimeSpan.FromSeconds(segmentEndingSeconds).Ticks;
|
||||
var segmentEndingPositionTicks = GetEndPositionTicks(state, index);
|
||||
|
||||
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
||||
{
|
||||
|
@ -698,26 +734,22 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
{
|
||||
var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
var segmentLengths = GetSegmentLengths(state);
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
builder.AppendLine("#EXTM3U");
|
||||
builder.AppendLine("#EXT-X-VERSION:3");
|
||||
builder.AppendLine("#EXT-X-TARGETDURATION:" + (state.SegmentLength).ToString(UsCulture));
|
||||
builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling((segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength)).ToString(UsCulture));
|
||||
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
|
||||
|
||||
var queryStringIndex = Request.RawUrl.IndexOf('?');
|
||||
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
|
||||
|
||||
var seconds = TimeSpan.FromTicks(state.RunTimeTicks ?? 0).TotalSeconds;
|
||||
|
||||
var index = 0;
|
||||
|
||||
double segmentLength = state.SegmentLength;
|
||||
|
||||
while (seconds > 0)
|
||||
foreach (var length in segmentLengths)
|
||||
{
|
||||
var length = seconds >= state.SegmentLength ? segmentLength : seconds;
|
||||
|
||||
builder.AppendLine("#EXTINF:" + length.ToString("0.000000", UsCulture) + ",");
|
||||
|
||||
builder.AppendLine(string.Format("hlsdynamic/{0}/{1}{2}{3}",
|
||||
|
@ -727,7 +759,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
GetSegmentFileExtension(isOutputVideo),
|
||||
queryString));
|
||||
|
||||
seconds -= length;
|
||||
index++;
|
||||
}
|
||||
|
||||
|
@ -850,11 +881,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
args += " -flags +loop-global_header -sc_threshold 0";
|
||||
}
|
||||
|
||||
if (!EnableSplitTranscoding(state))
|
||||
{
|
||||
//args += " -copyts";
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
|
@ -870,21 +896,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
var toTimeParam = string.Empty;
|
||||
var timestampOffsetParam = string.Empty;
|
||||
|
||||
if (EnableSplitTranscoding(state))
|
||||
{
|
||||
var startTime = state.Request.StartTimeTicks ?? 0;
|
||||
var durationSeconds = ApiEntryPoint.Instance.GetEncodingOptions().ThrottleThresholdInSeconds;
|
||||
|
||||
var endTime = startTime + TimeSpan.FromSeconds(durationSeconds).Ticks;
|
||||
endTime = Math.Min(endTime, state.RunTimeTicks.Value);
|
||||
|
||||
if (endTime < state.RunTimeTicks.Value)
|
||||
{
|
||||
//toTimeParam = " -to " + MediaEncoder.GetTimeParameter(endTime);
|
||||
toTimeParam = " -t " + MediaEncoder.GetTimeParameter(TimeSpan.FromSeconds(durationSeconds).Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.IsOutputVideo && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
||||
{
|
||||
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0).ToString(CultureInfo.InvariantCulture);
|
||||
|
@ -927,36 +938,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
protected override bool EnableThrottling(StreamState state)
|
||||
{
|
||||
return !EnableSplitTranscoding(state);
|
||||
}
|
||||
|
||||
private bool EnableSplitTranscoding(StreamState state)
|
||||
{
|
||||
return false;
|
||||
if (string.Equals(Request.QueryString["EnableSplitTranscoding"], "false", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return state.RunTimeTicks.HasValue && state.IsOutputVideo;
|
||||
}
|
||||
|
||||
protected override bool EnableStreamCopy
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -226,7 +226,9 @@
|
|||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282014%29.xml" />
|
||||
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282014%29.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
|
|
@ -248,8 +248,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
{
|
||||
try
|
||||
{
|
||||
//stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken)
|
||||
// .ConfigureAwait(false);
|
||||
//stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
@ -283,7 +282,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
|
||||
private async Task<List<int>> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken)
|
||||
{
|
||||
const string args = "-i {0} -select_streams v:{1} -show_frames -show_entries frame=pkt_dts,key_frame -print_format compact";
|
||||
const string args = "-i {0} -select_streams v:{1} -show_packets -print_format compact -show_entries packet=flags -show_entries packet=pts_time";
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
|
@ -318,7 +317,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
{
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
await StartReadingOutput(process.StandardOutput.BaseStream, lines, 120000, cancellationToken).ConfigureAwait(false);
|
||||
await StartReadingOutput(process.StandardOutput.BaseStream, lines, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
@ -336,7 +335,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
}
|
||||
}
|
||||
|
||||
private async Task StartReadingOutput(Stream source, List<int> lines, int timeoutMs, CancellationToken cancellationToken)
|
||||
private async Task StartReadingOutput(Stream source, List<int> lines, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -354,14 +353,15 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
.Where(i => i.Length == 2)
|
||||
.ToDictionary(i => i[0], i => i[1]);
|
||||
|
||||
string pktDts;
|
||||
int frameMs;
|
||||
if (values.TryGetValue("pkt_dts", out pktDts) && int.TryParse(pktDts, NumberStyles.Any, CultureInfo.InvariantCulture, out frameMs))
|
||||
string flags;
|
||||
if (values.TryGetValue("flags", out flags) && string.Equals(flags, "k", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string keyFrame;
|
||||
if (values.TryGetValue("key_frame", out keyFrame) && string.Equals(keyFrame, "1", StringComparison.OrdinalIgnoreCase))
|
||||
string pts_time;
|
||||
double frameSeconds;
|
||||
if (values.TryGetValue("pts_time", out pts_time) && double.TryParse(pts_time, NumberStyles.Any, CultureInfo.InvariantCulture, out frameSeconds))
|
||||
{
|
||||
lines.Add(frameMs);
|
||||
var ms = frameSeconds * 1000;
|
||||
lines.Add(Convert.ToInt32(ms));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -376,7 +376,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
_logger.ErrorException("Error reading ffprobe output", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The us culture
|
||||
/// </summary>
|
||||
|
@ -802,7 +801,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
public ProcessWrapper(Process process, MediaEncoder mediaEncoder, ILogger logger)
|
||||
{
|
||||
Process = process;
|
||||
this._mediaEncoder = mediaEncoder;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_logger = logger;
|
||||
Process.Exited += Process_Exited;
|
||||
}
|
||||
|
@ -819,7 +818,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error determing process exit code", ex);
|
||||
}
|
||||
|
||||
lock (_mediaEncoder._runningProcesses)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using MediaBrowser.Model.Dlna;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
@ -225,5 +227,8 @@ namespace MediaBrowser.Model.Entities
|
|||
/// </summary>
|
||||
/// <value><c>null</c> if [is cabac] contains no value, <c>true</c> if [is cabac]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsCabac { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public List<int> KeyFrames { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
return ItemUpdateType.MetadataImport;
|
||||
}
|
||||
|
||||
private const string SchemaVersion = "5";
|
||||
private const string SchemaVersion = "6";
|
||||
|
||||
private async Task<Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
|
||||
IIsoMount isoMount,
|
||||
|
@ -140,14 +140,14 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var idString = item.Id.ToString("N");
|
||||
var cachePath = Path.Combine(_appPaths.CachePath,
|
||||
"ffprobe-video",
|
||||
idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
|
||||
//var idString = item.Id.ToString("N");
|
||||
//var cachePath = Path.Combine(_appPaths.CachePath,
|
||||
// "ffprobe-video",
|
||||
// idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
|
||||
|
||||
try
|
||||
{
|
||||
return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
|
||||
//return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
@ -174,8 +174,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
|
||||
_json.SerializeToFile(result, cachePath);
|
||||
//Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
|
||||
//_json.SerializeToFile(result, cachePath);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -187,6 +187,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
/// </summary>
|
||||
private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
private string[] _retriveItemColumns =
|
||||
{
|
||||
"type",
|
||||
"data",
|
||||
"IsOffline"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the statements.
|
||||
/// </summary>
|
||||
|
@ -398,7 +405,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
|
||||
_saveItemCommand.GetParameter(index++).Value = item.ForcedSortName;
|
||||
_saveItemCommand.GetParameter(index++).Value = item.IsOffline;
|
||||
|
||||
|
||||
_saveItemCommand.Transaction = transaction;
|
||||
|
||||
_saveItemCommand.ExecuteNonQuery();
|
||||
|
@ -455,7 +462,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select type,data from TypedBaseItems where guid = @guid";
|
||||
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid = @guid";
|
||||
cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = id;
|
||||
|
||||
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
|
||||
|
@ -482,11 +489,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
return null;
|
||||
}
|
||||
|
||||
BaseItem item;
|
||||
|
||||
using (var stream = reader.GetMemoryStream(1))
|
||||
{
|
||||
try
|
||||
{
|
||||
return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
|
||||
item = _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (SerializationException ex)
|
||||
{
|
||||
|
@ -494,6 +508,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reader.IsDBNull(2))
|
||||
{
|
||||
item.IsOffline = reader.GetBoolean(2);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -685,7 +706,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select type,data from TypedBaseItems where guid in (select ItemId from ChildrenIds where ParentId = @ParentId)";
|
||||
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid in (select ItemId from ChildrenIds where ParentId = @ParentId)";
|
||||
|
||||
cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId;
|
||||
|
||||
|
@ -715,7 +736,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select type,data from TypedBaseItems where type = @type";
|
||||
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where type = @type";
|
||||
|
||||
cmd.Parameters.Add(cmd, "@type", DbType.String).Value = type.FullName;
|
||||
|
||||
|
@ -745,7 +766,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "select type,data from TypedBaseItems";
|
||||
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
|
||||
|
||||
var whereClauses = GetWhereClauses(query, cmd, false);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Controller.Persistence;
|
||||
using System.Globalization;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
|
@ -38,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
|
||||
// Add PixelFormat column
|
||||
|
||||
createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, PRIMARY KEY (ItemId, StreamIndex))";
|
||||
createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, KeyFrames TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
|
||||
|
||||
string[] queries = {
|
||||
|
||||
|
@ -58,6 +59,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
AddBitDepthCommand();
|
||||
AddIsAnamorphicColumn();
|
||||
AddIsCabacColumn();
|
||||
AddKeyFramesColumn();
|
||||
AddRefFramesCommand();
|
||||
|
||||
PrepareStatements();
|
||||
|
@ -187,6 +189,37 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
_connection.RunQueries(new[] { builder.ToString() }, _logger);
|
||||
}
|
||||
|
||||
private void AddKeyFramesColumn()
|
||||
{
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "PRAGMA table_info(mediastreams)";
|
||||
|
||||
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
if (!reader.IsDBNull(1))
|
||||
{
|
||||
var name = reader.GetString(1);
|
||||
|
||||
if (string.Equals(name, "KeyFrames", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
builder.AppendLine("alter table mediastreams");
|
||||
builder.AppendLine("add column KeyFrames TEXT NULL");
|
||||
|
||||
_connection.RunQueries(new[] { builder.ToString() }, _logger);
|
||||
}
|
||||
|
||||
private void AddIsAnamorphicColumn()
|
||||
{
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
|
@ -245,7 +278,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
"BitDepth",
|
||||
"IsAnamorphic",
|
||||
"RefFrames",
|
||||
"IsCabac"
|
||||
"IsCabac",
|
||||
"KeyFrames"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -429,6 +463,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
item.IsCabac = reader.GetBoolean(25);
|
||||
}
|
||||
|
||||
if (!reader.IsDBNull(26))
|
||||
{
|
||||
var frames = reader.GetString(26);
|
||||
if (!string.IsNullOrWhiteSpace(frames))
|
||||
{
|
||||
item.KeyFrames = frames.Split(',').Select(i => int.Parse(i, CultureInfo.InvariantCulture)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -498,6 +541,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
_saveStreamCommand.GetParameter(index++).Value = stream.RefFrames;
|
||||
_saveStreamCommand.GetParameter(index++).Value = stream.IsCabac;
|
||||
|
||||
if (stream.KeyFrames == null || stream.KeyFrames.Count == 0)
|
||||
{
|
||||
_saveStreamCommand.GetParameter(index++).Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_saveStreamCommand.GetParameter(index++).Value = string.Join(",", stream.KeyFrames.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray());
|
||||
}
|
||||
|
||||
_saveStreamCommand.Transaction = transaction;
|
||||
_saveStreamCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("3.0.*")]
|
||||
//[assembly: AssemblyVersion("3.0.5713.3")]
|
||||
//[assembly: AssemblyVersion("3.0.*")]
|
||||
[assembly: AssemblyVersion("3.0.5713.4")]
|
||||
|
|
Loading…
Reference in New Issue
Block a user