2019-01-13 20:02:23 +00:00
|
|
|
using System;
|
2018-12-30 23:28:23 +00:00
|
|
|
using System.IO;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using MediaBrowser.Controller.Library;
|
2018-12-14 09:40:55 +00:00
|
|
|
using MediaBrowser.Controller.MediaEncoding;
|
|
|
|
using MediaBrowser.Model.Dlna;
|
|
|
|
using MediaBrowser.Model.Net;
|
2018-12-14 23:48:06 +00:00
|
|
|
using Microsoft.Extensions.Logging;
|
2018-12-14 09:40:55 +00:00
|
|
|
|
|
|
|
namespace MediaBrowser.MediaEncoding.Encoder
|
|
|
|
{
|
|
|
|
public class EncodingJob : EncodingJobInfo, IDisposable
|
|
|
|
{
|
|
|
|
public bool HasExited { get; internal set; }
|
|
|
|
public bool IsCancelled { get; internal set; }
|
|
|
|
|
|
|
|
public Stream LogFileStream { get; set; }
|
|
|
|
public IProgress<double> Progress { get; set; }
|
|
|
|
public TaskCompletionSource<bool> TaskCompletionSource;
|
|
|
|
|
|
|
|
public EncodingJobOptions Options
|
|
|
|
{
|
2019-01-13 20:31:14 +00:00
|
|
|
get => (EncodingJobOptions)BaseRequest;
|
|
|
|
set => BaseRequest = value;
|
2018-12-14 09:40:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public string Id { get; set; }
|
|
|
|
|
|
|
|
public string MimeType { get; set; }
|
|
|
|
public bool EstimateContentLength { get; set; }
|
|
|
|
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
|
|
|
|
public long? EncodingDurationTicks { get; set; }
|
|
|
|
|
|
|
|
public string ItemType { get; set; }
|
|
|
|
|
|
|
|
public string GetMimeType(string outputPath)
|
|
|
|
{
|
|
|
|
if (!string.IsNullOrEmpty(MimeType))
|
|
|
|
{
|
|
|
|
return MimeType;
|
|
|
|
}
|
|
|
|
|
|
|
|
return MimeTypes.GetMimeType(outputPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
private readonly ILogger _logger;
|
|
|
|
private readonly IMediaSourceManager _mediaSourceManager;
|
|
|
|
|
2019-01-07 23:27:46 +00:00
|
|
|
public EncodingJob(ILogger logger, IMediaSourceManager mediaSourceManager) :
|
2018-12-14 09:40:55 +00:00
|
|
|
base(logger, mediaSourceManager, TranscodingJobType.Progressive)
|
|
|
|
{
|
|
|
|
_logger = logger;
|
|
|
|
_mediaSourceManager = mediaSourceManager;
|
|
|
|
Id = Guid.NewGuid().ToString("N");
|
|
|
|
|
|
|
|
_logger = logger;
|
|
|
|
TaskCompletionSource = new TaskCompletionSource<bool>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Dispose()
|
|
|
|
{
|
|
|
|
DisposeLiveStream();
|
|
|
|
DisposeLogStream();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void DisposeLogStream()
|
|
|
|
{
|
|
|
|
if (LogFileStream != null)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
LogFileStream.Dispose();
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
2018-12-20 12:11:26 +00:00
|
|
|
_logger.LogError(ex, "Error disposing log stream");
|
2018-12-14 09:40:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LogFileStream = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private async void DisposeLiveStream()
|
|
|
|
{
|
|
|
|
if (MediaSource.RequiresClosing && string.IsNullOrWhiteSpace(Options.LiveStreamId) && !string.IsNullOrWhiteSpace(MediaSource.LiveStreamId))
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).ConfigureAwait(false);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
2018-12-20 12:11:26 +00:00
|
|
|
_logger.LogError(ex, "Error closing media source");
|
2018-12-14 09:40:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string OutputFilePath { get; set; }
|
|
|
|
|
|
|
|
public string ActualOutputVideoCodec
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
var codec = OutputVideoCodec;
|
|
|
|
|
|
|
|
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
var stream = VideoStream;
|
|
|
|
|
|
|
|
if (stream != null)
|
|
|
|
{
|
|
|
|
return stream.Codec;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return codec;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string ActualOutputAudioCodec
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
var codec = OutputAudioCodec;
|
|
|
|
|
|
|
|
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
var stream = AudioStream;
|
|
|
|
|
|
|
|
if (stream != null)
|
|
|
|
{
|
|
|
|
return stream.Codec;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return codec;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
|
|
|
{
|
|
|
|
var ticks = transcodingPosition.HasValue ? transcodingPosition.Value.Ticks : (long?)null;
|
|
|
|
|
2018-12-30 23:28:23 +00:00
|
|
|
//job.Framerate = framerate;
|
2018-12-14 09:40:55 +00:00
|
|
|
|
|
|
|
if (!percentComplete.HasValue && ticks.HasValue && RunTimeTicks.HasValue)
|
|
|
|
{
|
|
|
|
var pct = ticks.Value / RunTimeTicks.Value;
|
|
|
|
percentComplete = pct * 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (percentComplete.HasValue)
|
|
|
|
{
|
|
|
|
Progress.Report(percentComplete.Value);
|
|
|
|
}
|
|
|
|
|
2018-12-30 23:28:23 +00:00
|
|
|
/*
|
|
|
|
job.TranscodingPositionTicks = ticks;
|
|
|
|
job.BytesTranscoded = bytesTranscoded;
|
2018-12-14 09:40:55 +00:00
|
|
|
|
|
|
|
var deviceId = Options.DeviceId;
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(deviceId))
|
|
|
|
{
|
|
|
|
var audioCodec = ActualOutputVideoCodec;
|
|
|
|
var videoCodec = ActualOutputVideoCodec;
|
|
|
|
|
2018-12-30 23:28:23 +00:00
|
|
|
SessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo
|
|
|
|
{
|
|
|
|
Bitrate = job.TotalOutputBitrate,
|
|
|
|
AudioCodec = audioCodec,
|
|
|
|
VideoCodec = videoCodec,
|
|
|
|
Container = job.Options.OutputContainer,
|
|
|
|
Framerate = framerate,
|
|
|
|
CompletionPercentage = percentComplete,
|
|
|
|
Width = job.OutputWidth,
|
|
|
|
Height = job.OutputHeight,
|
|
|
|
AudioChannels = job.OutputAudioChannels,
|
|
|
|
IsAudioDirect = string.Equals(job.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase),
|
|
|
|
IsVideoDirect = string.Equals(job.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)
|
|
|
|
});
|
|
|
|
}*/
|
2018-12-14 09:40:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|