コード例 #1
0
        /// <summary>
        /// Called when [transcode beginning].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="playSessionId">The play session identifier.</param>
        /// <param name="liveStreamId">The live stream identifier.</param>
        /// <param name="transcodingJobId">The transcoding job identifier.</param>
        /// <param name="type">The type.</param>
        /// <param name="process">The process.</param>
        /// <param name="deviceId">The device id.</param>
        /// <param name="state">The state.</param>
        /// <param name="cancellationTokenSource">The cancellation token source.</param>
        /// <returns>TranscodingJob.</returns>
        public TranscodingJob OnTranscodeBeginning(
            string path,
            string playSessionId,
            string liveStreamId,
            string transcodingJobId,
            TranscodingJobType type,
            Process process,
            string deviceId,
            StreamState state,
            CancellationTokenSource cancellationTokenSource)
        {
            lock (_activeTranscodingJobs)
            {
                var job = new TranscodingJob(_logger)
                {
                    Type                    = type,
                    Path                    = path,
                    Process                 = process,
                    ActiveRequestCount      = 1,
                    DeviceId                = deviceId,
                    CancellationTokenSource = cancellationTokenSource,
                    Id            = transcodingJobId,
                    PlaySessionId = playSessionId,
                    LiveStreamId  = liveStreamId,
                    MediaSource   = state.MediaSource
                };

                _activeTranscodingJobs.Add(job);

                ReportTranscodingProgress(job, state, null, null, null, null, null);

                return(job);
            }
        }
コード例 #2
0
        /// <summary>
        /// Called when [transcode end request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodeEndRequest(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return;
                }

                job.ActiveRequestCount--;

                if (job.ActiveRequestCount == 0)
                {
                    // The HLS kill timer is long - 1/2 hr. clients should use the manual kill command when stopping.
                    var timerDuration = type == TranscodingJobType.Progressive ? 1000 : 1800000;

                    if (job.KillTimer == null)
                    {
                        job.KillTimer = new Timer(OnTranscodeKillTimerStopped, job, timerDuration, Timeout.Infinite);
                    }
                    else
                    {
                        job.KillTimer.Change(timerDuration, Timeout.Infinite);
                    }
                }
            }
        }
コード例 #3
0
 /// <summary>
 /// Determines whether [has active transcoding job] [the specified path].
 /// </summary>
 /// <param name="path">The path.</param>
 /// <param name="type">The type.</param>
 /// <returns><c>true</c> if [has active transcoding job] [the specified path]; otherwise, <c>false</c>.</returns>
 public bool HasActiveTranscodingJob(string path, TranscodingJobType type)
 {
     lock (_activeTranscodingJobs)
     {
         return(_activeTranscodingJobs.Any(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)));
     }
 }
コード例 #4
0
 /// <summary>
 /// Get transcoding job.
 /// </summary>
 /// <param name="path">Path to the transcoding file.</param>
 /// <param name="type">The <see cref="TranscodingJobType"/>.</param>
 /// <returns>The transcoding job.</returns>
 public TranscodingJobDto?GetTranscodingJob(string path, TranscodingJobType type)
 {
     lock (_activeTranscodingJobs)
     {
         return(_activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase)));
     }
 }
コード例 #5
0
        private async void DeletePartialStreamFiles(string path, TranscodingJobType jobType, int retryCount, int delayMs)
        {
            if (retryCount >= 5)
            {
                return;
            }

            Logger.Info("Deleting partial stream file(s) {0}", path);

            await Task.Delay(delayMs).ConfigureAwait(false);

            try
            {
                if (jobType == TranscodingJobType.Progressive)
                {
                    DeleteProgressivePartialStreamFiles(path);
                }
                else
                {
                    DeleteHlsPartialStreamFiles(path);
                }
            }
            catch (IOException ex)
            {
                Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, path);

                DeletePartialStreamFiles(path, jobType, retryCount + 1, 500);
            }
            catch (Exception ex)
            {
                Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, path);
            }
        }
コード例 #6
0
        /// <summary>
        /// Called when [transcode end request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodeEndRequest(string path, TranscodingJobType type)
        {
            lock (ActiveTranscodingJobs)
            {
                var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return;
                }

                job.ActiveRequestCount--;

                if (job.ActiveRequestCount == 0)
                {
                    var timerDuration = type == TranscodingJobType.Progressive ? 1000 : 30000;

                    if (job.KillTimer == null)
                    {
                        job.KillTimer = new Timer(OnTranscodeKillTimerStopped, job, timerDuration, Timeout.Infinite);
                    }
                    else
                    {
                        job.KillTimer.Change(timerDuration, Timeout.Infinite);
                    }
                }
            }
        }
コード例 #7
0
        private async Task DeletePartialStreamFiles(string path, TranscodingJobType jobType, int retryCount, int delayMs)
        {
            if (retryCount >= 10)
            {
                return;
            }

            _logger.LogInformation("Deleting partial stream file(s) {Path}", path);

            await Task.Delay(delayMs).ConfigureAwait(false);

            try
            {
                if (jobType == TranscodingJobType.Progressive)
                {
                    DeleteProgressivePartialStreamFiles(path);
                }
                else
                {
                    DeleteHlsPartialStreamFiles(path);
                }
            }
            catch (IOException ex)
            {
                _logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path);

                await DeletePartialStreamFiles(path, jobType, retryCount + 1, 500).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path);
            }
        }
コード例 #8
0
ファイル: StreamState.cs プロジェクト: voxadam/Emby
 public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger, TranscodingJobType transcodingType)
     : base(logger)
 {
     _mediaSourceManager = mediaSourceManager;
     _logger             = logger;
     TranscodingType     = transcodingType;
 }
コード例 #9
0
ファイル: EncodingJobInfo.cs プロジェクト: ypid/jellyfin
 public EncodingJobInfo(TranscodingJobType jobType)
 {
     TranscodingType         = jobType;
     RemoteHttpHeaders       = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
     SupportedAudioCodecs    = Array.Empty <string>();
     SupportedVideoCodecs    = Array.Empty <string>();
     SupportedSubtitleCodecs = Array.Empty <string>();
 }
コード例 #10
0
ファイル: StreamState.cs プロジェクト: vvuk/Emby
 public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger, TranscodingJobType transcodingType)
     : base(logger)
 {
     _mediaSourceManager     = mediaSourceManager;
     _logger                 = logger;
     SupportedSubtitleCodecs = new List <string>();
     TranscodingType         = transcodingType;
 }
コード例 #11
0
        /// <summary>
        /// <summary>
        /// The progressive
        /// </summary>
        /// Called when [transcode failed to start].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodeFailedToStart(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.First(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                _activeTranscodingJobs.Remove(job);
            }
        }
コード例 #12
0
        /// <summary>
        /// Gets the current streaming state.
        /// </summary>
        /// <param name="streamingRequest">The <see cref="StreamingRequestDto"/>.</param>
        /// <param name="httpRequest">The <see cref="HttpRequest"/>.</param>
        /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
        /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
        /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
        /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
        /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
        /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
        /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
        /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
        /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
        /// <param name="transcodingJobHelper">Initialized <see cref="TranscodingJobHelper"/>.</param>
        /// <param name="transcodingJobType">The <see cref="TranscodingJobType"/>.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
        /// <returns>A <see cref="Task"/> containing the current <see cref="StreamState"/>.</returns>
        public static async Task <StreamState> GetStreamingState(
            StreamingRequestDto streamingRequest,
            HttpRequest httpRequest,
            IAuthorizationContext authorizationContext,
            IMediaSourceManager mediaSourceManager,
            IUserManager userManager,
            ILibraryManager libraryManager,
            IServerConfigurationManager serverConfigurationManager,
            IMediaEncoder mediaEncoder,
            EncodingHelper encodingHelper,
            IDlnaManager dlnaManager,
            IDeviceManager deviceManager,
            TranscodingJobHelper transcodingJobHelper,
            TranscodingJobType transcodingJobType,
            CancellationToken cancellationToken)
        {
            // Parse the DLNA time seek header
            if (!streamingRequest.StartTimeTicks.HasValue)
            {
                var timeSeek = httpRequest.Headers["TimeSeekRange.dlna.org"];

                streamingRequest.StartTimeTicks = ParseTimeSeekHeader(timeSeek.ToString());
            }

            if (!string.IsNullOrWhiteSpace(streamingRequest.Params))
            {
                ParseParams(streamingRequest);
            }

            streamingRequest.StreamOptions = ParseStreamOptions(httpRequest.Query);
            if (httpRequest.Path.Value == null)
            {
                throw new ResourceNotFoundException(nameof(httpRequest.Path));
            }

            var url = httpRequest.Path.Value.AsSpan().RightPart('.').ToString();

            if (string.IsNullOrEmpty(streamingRequest.AudioCodec))
            {
                streamingRequest.AudioCodec = encodingHelper.InferAudioCodec(url);
            }

            var enableDlnaHeaders = !string.IsNullOrWhiteSpace(streamingRequest.Params) ||
                                    streamingRequest.StreamOptions.ContainsKey("dlnaheaders") ||
                                    string.Equals(httpRequest.Headers["GetContentFeatures.DLNA.ORG"], "1", StringComparison.OrdinalIgnoreCase);

            var state = new StreamState(mediaSourceManager, transcodingJobType, transcodingJobHelper)
            {
                Request           = streamingRequest,
                RequestedUrl      = url,
                UserAgent         = httpRequest.Headers[HeaderNames.UserAgent],
                EnableDlnaHeaders = enableDlnaHeaders
            };

            var auth = await authorizationContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false);

            if (!auth.UserId.Equals(default))
コード例 #13
0
ファイル: EncodingJobInfo.cs プロジェクト: vadsaaa/Emby
 public EncodingJobInfo(ILogger logger, TranscodingJobType jobType)
 {
     _logger                 = logger;
     TranscodingType         = jobType;
     RemoteHttpHeaders       = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
     PlayableStreamFileNames = new string[] { };
     SupportedAudioCodecs    = new List <string>();
     SupportedVideoCodecs    = new List <string>();
     SupportedSubtitleCodecs = new List <string>();
 }
コード例 #14
0
ファイル: StreamState.cs プロジェクト: philip4077/Emby
 public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger, TranscodingJobType transcodingType)
 {
     _mediaSourceManager     = mediaSourceManager;
     _logger                 = logger;
     SupportedAudioCodecs    = new List <string>();
     SupportedVideoCodecs    = new List <string>();
     PlayableStreamFileNames = new List <string>();
     RemoteHttpHeaders       = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
     TranscodingType         = transcodingType;
 }
コード例 #15
0
ファイル: EncodingJobInfo.cs プロジェクト: sxryt/jellyfin
 public EncodingJobInfo(ILogger logger, IMediaSourceManager unused, TranscodingJobType jobType)
 {
     _logger                 = logger;
     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>();
 }
コード例 #16
0
 /// <summary>
 /// Called when [transcode beginning].
 /// </summary>
 /// <param name="path">The path.</param>
 /// <param name="type">The type.</param>
 /// <param name="process">The process.</param>
 public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process)
 {
     lock (ActiveTranscodingJobs)
     {
         ActiveTranscodingJobs.Add(new TranscodingJob
         {
             Type               = type,
             Path               = path,
             Process            = process,
             ActiveRequestCount = 1
         });
     }
 }
コード例 #17
0
ファイル: ApiEntryPoint.cs プロジェクト: snap608/MediaBrowser
 /// <summary>
 /// Called when [transcode beginning].
 /// </summary>
 /// <param name="path">The path.</param>
 /// <param name="type">The type.</param>
 /// <param name="process">The process.</param>
 public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process)
 {
     lock (_activeTranscodingJobs)
     {
         _activeTranscodingJobs.Add(new TranscodingJob
         {
             Type = type,
             Path = path,
             Process = process,
             ActiveRequestCount = 1
         });
     }
 }
コード例 #18
0
        public EncodingJobInfo(ILogger logger, IMediaSourceManager mediaSourceManager, TranscodingJobType jobType)
        {
            Id = Guid.NewGuid();
            TaskCompletionSource = new TaskCompletionSource <bool>();

            Logger                  = logger;
            MediaSourceManager      = mediaSourceManager;
            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>();
        }
コード例 #19
0
        /// <summary>
        /// <summary>
        /// The progressive
        /// </summary>
        /// Called when [transcode failed to start].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        /// <param name="state">The state.</param>
        public void OnTranscodeFailedToStart(string path, TranscodingJobType type, StreamState state)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.First(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                _activeTranscodingJobs.Remove(job);
            }

            if (!string.IsNullOrWhiteSpace(state.Request.DeviceId))
            {
                _sessionManager.ClearTranscodingInfo(state.Request.DeviceId);
            }
        }
コード例 #20
0
        /// <summary>
        /// Returns a transcoded file from the server.
        /// </summary>
        /// <param name="state">The current <see cref="StreamState"/>.</param>
        /// <param name="isHeadRequest">Whether the current request is a HTTP HEAD request so only the headers get returned.</param>
        /// <param name="controller">The <see cref="ControllerBase"/> managing the response.</param>
        /// <param name="transcodingJobHelper">The <see cref="TranscodingJobHelper"/> singleton.</param>
        /// <param name="ffmpegCommandLineArguments">The command line arguments to start ffmpeg.</param>
        /// <param name="request">The <see cref="HttpRequest"/> starting the transcoding.</param>
        /// <param name="transcodingJobType">The <see cref="TranscodingJobType"/>.</param>
        /// <param name="cancellationTokenSource">The <see cref="CancellationTokenSource"/>.</param>
        /// <returns>A <see cref="Task{ActionResult}"/> containing the transcoded file.</returns>
        public static async Task <ActionResult> GetTranscodedFile(
            StreamState state,
            bool isHeadRequest,
            ControllerBase controller,
            TranscodingJobHelper transcodingJobHelper,
            string ffmpegCommandLineArguments,
            HttpRequest request,
            TranscodingJobType transcodingJobType,
            CancellationTokenSource cancellationTokenSource)
        {
            // Use the command line args with a dummy playlist path
            var outputPath = state.OutputFilePath;

            controller.Response.Headers[HeaderNames.AcceptRanges] = "none";

            var contentType = state.GetMimeType(outputPath);

            // Headers only
            if (isHeadRequest)
            {
                return(controller.File(Array.Empty <byte>(), contentType));
            }

            var transcodingLock = transcodingJobHelper.GetTranscodingLock(outputPath);
            await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);

            try
            {
                TranscodingJobDto?job;
                if (!File.Exists(outputPath))
                {
                    job = await transcodingJobHelper.StartFfMpeg(state, outputPath, ffmpegCommandLineArguments, request, transcodingJobType, cancellationTokenSource).ConfigureAwait(false);
                }
                else
                {
                    job = transcodingJobHelper.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
                    state.Dispose();
                }

                var memoryStream = new MemoryStream();
                await new ProgressiveFileCopier(outputPath, job, transcodingJobHelper, CancellationToken.None).WriteToAsync(memoryStream, CancellationToken.None).ConfigureAwait(false);
                memoryStream.Position = 0;
                return(controller.File(memoryStream, contentType));
            }
            finally
            {
                transcodingLock.Release();
            }
        }
コード例 #21
0
ファイル: DynamicHlsHelper.cs プロジェクト: junglerule/docker
        /// <summary>
        /// Get master hls playlist.
        /// </summary>
        /// <param name="transcodingJobType">Transcoding job type.</param>
        /// <param name="streamingRequest">Streaming request dto.</param>
        /// <param name="enableAdaptiveBitrateStreaming">Enable adaptive bitrate streaming.</param>
        /// <returns>A <see cref="Task"/> containing the resulting <see cref="ActionResult"/>.</returns>
        public async Task <ActionResult> GetMasterHlsPlaylist(
            TranscodingJobType transcodingJobType,
            StreamingRequestDto streamingRequest,
            bool enableAdaptiveBitrateStreaming)
        {
            var isHeadRequest           = _httpContextAccessor.HttpContext?.Request.Method == WebRequestMethods.Http.Head;
            var cancellationTokenSource = new CancellationTokenSource();

            return(await GetMasterPlaylistInternal(
                       streamingRequest,
                       isHeadRequest,
                       enableAdaptiveBitrateStreaming,
                       transcodingJobType,
                       cancellationTokenSource).ConfigureAwait(false));
        }
コード例 #22
0
 /// <summary>
 /// Called when [transcode beginning].
 /// </summary>
 /// <param name="path">The path.</param>
 /// <param name="type">The type.</param>
 /// <param name="process">The process.</param>
 /// <param name="isVideo">if set to <c>true</c> [is video].</param>
 /// <param name="startTimeTicks">The start time ticks.</param>
 public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process, bool isVideo, long?startTimeTicks)
 {
     lock (_activeTranscodingJobs)
     {
         _activeTranscodingJobs.Add(new TranscodingJob
         {
             Type               = type,
             Path               = path,
             Process            = process,
             ActiveRequestCount = 1,
             IsVideo            = isVideo,
             StartTimeTicks     = startTimeTicks
         });
     }
 }
コード例 #23
0
        /// <summary>
        /// Called when [transcode begin request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public TranscodingJob OnTranscodeBeginRequest(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return(null);
                }

                OnTranscodeBeginRequest(job);

                return(job);
            }
        }
コード例 #24
0
        /// <summary>
        /// Returns a transcoded file from the server.
        /// </summary>
        /// <param name="state">The current <see cref="StreamState"/>.</param>
        /// <param name="isHeadRequest">Whether the current request is a HTTP HEAD request so only the headers get returned.</param>
        /// <param name="httpContext">The current http context.</param>
        /// <param name="transcodingJobHelper">The <see cref="TranscodingJobHelper"/> singleton.</param>
        /// <param name="ffmpegCommandLineArguments">The command line arguments to start ffmpeg.</param>
        /// <param name="transcodingJobType">The <see cref="TranscodingJobType"/>.</param>
        /// <param name="cancellationTokenSource">The <see cref="CancellationTokenSource"/>.</param>
        /// <returns>A <see cref="Task{ActionResult}"/> containing the transcoded file.</returns>
        public static async Task <ActionResult> GetTranscodedFile(
            StreamState state,
            bool isHeadRequest,
            HttpContext httpContext,
            TranscodingJobHelper transcodingJobHelper,
            string ffmpegCommandLineArguments,
            TranscodingJobType transcodingJobType,
            CancellationTokenSource cancellationTokenSource)
        {
            // Use the command line args with a dummy playlist path
            var outputPath = state.OutputFilePath;

            httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none";

            var contentType = state.GetMimeType(outputPath);

            // Headers only
            if (isHeadRequest)
            {
                httpContext.Response.Headers[HeaderNames.ContentType] = contentType;
                return(new OkResult());
            }

            var transcodingLock = transcodingJobHelper.GetTranscodingLock(outputPath);
            await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);

            try
            {
                TranscodingJobDto?job;
                if (!File.Exists(outputPath))
                {
                    job = await transcodingJobHelper.StartFfMpeg(state, outputPath, ffmpegCommandLineArguments, httpContext.Request, transcodingJobType, cancellationTokenSource).ConfigureAwait(false);
                }
                else
                {
                    job = transcodingJobHelper.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
                    state.Dispose();
                }

                var stream = new ProgressiveFileStream(outputPath, job, transcodingJobHelper);
                return(new FileStreamResult(stream, contentType));
            }
            finally
            {
                transcodingLock.Release();
            }
        }
コード例 #25
0
        /// <summary>
        /// Called when [transcode begin request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public TranscodingJob OnTranscodeBeginRequest(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return(null);
                }

                job.ActiveRequestCount++;

                job.DisposeKillTimer();

                return(job);
            }
        }
コード例 #26
0
        /// <summary>
        /// Called when [transcoding finished].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodingFinished(string path, TranscodingJobType type)
        {
            lock (ActiveTranscodingJobs)
            {
                var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return;
                }

                ActiveTranscodingJobs.Remove(job);

                if (job.KillTimer != null)
                {
                    job.KillTimer.Dispose();
                    job.KillTimer = null;
                }
            }
        }
コード例 #27
0
        /// <summary>
        /// Called when [transcode begin request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodeBeginRequest(string path, TranscodingJobType type)
        {
            lock (ActiveTranscodingJobs)
            {
                var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return;
                }

                job.ActiveRequestCount++;

                if (job.KillTimer != null)
                {
                    job.KillTimer.Dispose();
                    job.KillTimer = null;
                }
            }
        }
コード例 #28
0
ファイル: StreamingHelpers.cs プロジェクト: zxhcom/jellyfin
        /// <summary>
        /// Gets the current streaming state.
        /// </summary>
        /// <param name="streamingRequest">The <see cref="StreamingRequestDto"/>.</param>
        /// <param name="httpRequest">The <see cref="HttpRequest"/>.</param>
        /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
        /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
        /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
        /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
        /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
        /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
        /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
        /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
        /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
        /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
        /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
        /// <param name="transcodingJobHelper">Initialized <see cref="TranscodingJobHelper"/>.</param>
        /// <param name="transcodingJobType">The <see cref="TranscodingJobType"/>.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
        /// <returns>A <see cref="Task"/> containing the current <see cref="StreamState"/>.</returns>
        public static async Task <StreamState> GetStreamingState(
            StreamingRequestDto streamingRequest,
            HttpRequest httpRequest,
            IAuthorizationContext authorizationContext,
            IMediaSourceManager mediaSourceManager,
            IUserManager userManager,
            ILibraryManager libraryManager,
            IServerConfigurationManager serverConfigurationManager,
            IMediaEncoder mediaEncoder,
            IFileSystem fileSystem,
            ISubtitleEncoder subtitleEncoder,
            IConfiguration configuration,
            IDlnaManager dlnaManager,
            IDeviceManager deviceManager,
            TranscodingJobHelper transcodingJobHelper,
            TranscodingJobType transcodingJobType,
            CancellationToken cancellationToken)
        {
            EncodingHelper encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration);

            // Parse the DLNA time seek header
            if (!streamingRequest.StartTimeTicks.HasValue)
            {
                var timeSeek = httpRequest.Headers["TimeSeekRange.dlna.org"];

                streamingRequest.StartTimeTicks = ParseTimeSeekHeader(timeSeek.ToString());
            }

            if (!string.IsNullOrWhiteSpace(streamingRequest.Params))
            {
                ParseParams(streamingRequest);
            }

            streamingRequest.StreamOptions = ParseStreamOptions(httpRequest.Query);
            if (httpRequest.Path.Value == null)
            {
                throw new ResourceNotFoundException(nameof(httpRequest.Path));
            }

            var url = httpRequest.Path.Value.Split('.')[^ 1];
コード例 #29
0
        /// <summary>
        /// Called when [transcode beginning].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        /// <param name="process">The process.</param>
        /// <param name="deviceId">The device id.</param>
        /// <param name="state">The state.</param>
        /// <param name="cancellationTokenSource">The cancellation token source.</param>
        public void OnTranscodeBeginning(string path,
                                         TranscodingJobType type,
                                         Process process,
                                         string deviceId,
                                         StreamState state,
                                         CancellationTokenSource cancellationTokenSource)
        {
            lock (_activeTranscodingJobs)
            {
                _activeTranscodingJobs.Add(new TranscodingJob
                {
                    Type                    = type,
                    Path                    = path,
                    Process                 = process,
                    ActiveRequestCount      = 1,
                    DeviceId                = deviceId,
                    CancellationTokenSource = cancellationTokenSource
                });

                ReportTranscodingProgress(state, null, null);
            }
        }
コード例 #30
0
ファイル: ApiEntryPoint.cs プロジェクト: snap608/MediaBrowser
        /// <summary>
        /// Called when [transcoding finished].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodingFinished(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return;
                }

                _activeTranscodingJobs.Remove(job);

                if (job.KillTimer != null)
                {
                    job.KillTimer.Dispose();
                    job.KillTimer = null;
                }
            }
        }
コード例 #31
0
ファイル: ApiEntryPoint.cs プロジェクト: 7illusions/Emby
        /// <summary>
        /// Called when [transcode begin request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public TranscodingJob OnTranscodeBeginRequest(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return null;
                }

                OnTranscodeBeginRequest(job);

                return job;
            }
        }
コード例 #32
0
ファイル: ApiEntryPoint.cs プロジェクト: snap608/MediaBrowser
 /// <summary>
 /// Determines whether [has active transcoding job] [the specified path].
 /// </summary>
 /// <param name="path">The path.</param>
 /// <param name="type">The type.</param>
 /// <returns><c>true</c> if [has active transcoding job] [the specified path]; otherwise, <c>false</c>.</returns>
 public bool HasActiveTranscodingJob(string path, TranscodingJobType type)
 {
     lock (_activeTranscodingJobs)
     {
         return _activeTranscodingJobs.Any(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));
     }
 }
コード例 #33
0
        private async Task <ActionResult> GetMasterPlaylistInternal(
            StreamingRequestDto streamingRequest,
            bool isHeadRequest,
            bool enableAdaptiveBitrateStreaming,
            TranscodingJobType transcodingJobType,
            CancellationTokenSource cancellationTokenSource)
        {
            if (_httpContextAccessor.HttpContext == null)
            {
                throw new ResourceNotFoundException(nameof(_httpContextAccessor.HttpContext));
            }

            using var state = await StreamingHelpers.GetStreamingState(
                      streamingRequest,
                      _httpContextAccessor.HttpContext.Request,
                      _authContext,
                      _mediaSourceManager,
                      _userManager,
                      _libraryManager,
                      _serverConfigurationManager,
                      _mediaEncoder,
                      _encodingHelper,
                      _dlnaManager,
                      _deviceManager,
                      _transcodingJobHelper,
                      transcodingJobType,
                      cancellationTokenSource.Token)
                              .ConfigureAwait(false);

            _httpContextAccessor.HttpContext.Response.Headers.Add(HeaderNames.Expires, "0");
            if (isHeadRequest)
            {
                return(new FileContentResult(Array.Empty <byte>(), MimeTypes.GetMimeType("playlist.m3u8")));
            }

            var totalBitrate = (state.OutputAudioBitrate ?? 0) + (state.OutputVideoBitrate ?? 0);

            var builder = new StringBuilder();

            builder.AppendLine("#EXTM3U");

            var isLiveStream = state.IsSegmentedLiveStream;

            var queryString = _httpContextAccessor.HttpContext.Request.QueryString.ToString();

            // from universal audio service
            if (!string.IsNullOrWhiteSpace(state.Request.SegmentContainer) &&
                !queryString.Contains("SegmentContainer", StringComparison.OrdinalIgnoreCase))
            {
                queryString += "&SegmentContainer=" + state.Request.SegmentContainer;
            }

            // from universal audio service
            if (!string.IsNullOrWhiteSpace(state.Request.TranscodeReasons) &&
                !queryString.Contains("TranscodeReasons=", StringComparison.OrdinalIgnoreCase))
            {
                queryString += "&TranscodeReasons=" + state.Request.TranscodeReasons;
            }

            // Main stream
            var playlistUrl = isLiveStream ? "live.m3u8" : "main.m3u8";

            playlistUrl += queryString;

            var subtitleStreams = state.MediaSource
                                  .MediaStreams
                                  .Where(i => i.IsTextSubtitleStream)
                                  .ToList();

            var subtitleGroup = subtitleStreams.Count > 0 && (state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Hls || state.VideoRequest !.EnableSubtitlesInManifest)
                ? "subs"
                : null;

            // If we're burning in subtitles then don't add additional subs to the manifest
            if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
            {
                subtitleGroup = null;
            }

            if (!string.IsNullOrWhiteSpace(subtitleGroup))
            {
                AddSubtitles(state, subtitleStreams, builder, _httpContextAccessor.HttpContext.User);
            }

            var basicPlaylist = AppendPlaylist(builder, state, playlistUrl, totalBitrate, subtitleGroup);

            if (state.VideoStream != null && state.VideoRequest != null)
            {
                // Provide SDR HEVC entrance for backward compatibility.
                if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec) &&
                    !string.IsNullOrEmpty(state.VideoStream.VideoRange) &&
                    string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase) &&
                    string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
                {
                    var requestedVideoProfiles = state.GetRequestedProfiles("hevc");
                    if (requestedVideoProfiles != null && requestedVideoProfiles.Length > 0)
                    {
                        // Force HEVC Main Profile and disable video stream copy.
                        state.OutputVideoCodec = "hevc";
                        var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main");
                        sdrVideoUrl += "&AllowVideoStreamCopy=false";

                        var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0;
                        var sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0;
                        var sdrTotalBitrate       = sdrOutputAudioBitrate + sdrOutputVideoBitrate;

                        AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup);

                        // Restore the video codec
                        state.OutputVideoCodec = "copy";
                    }
                }

                // Provide Level 5.0 entrance for backward compatibility.
                // e.g. Apple A10 chips refuse the master playlist containing SDR HEVC Main Level 5.1 video,
                // but in fact it is capable of playing videos up to Level 6.1.
                if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec) &&
                    state.VideoStream.Level.HasValue &&
                    state.VideoStream.Level > 150 &&
                    !string.IsNullOrEmpty(state.VideoStream.VideoRange) &&
                    string.Equals(state.VideoStream.VideoRange, "SDR", StringComparison.OrdinalIgnoreCase) &&
                    string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
                {
                    var playlistCodecsField = new StringBuilder();
                    AppendPlaylistCodecsField(playlistCodecsField, state);

                    // Force the video level to 5.0.
                    var originalLevel = state.VideoStream.Level;
                    state.VideoStream.Level = 150;
                    var newPlaylistCodecsField = new StringBuilder();
                    AppendPlaylistCodecsField(newPlaylistCodecsField, state);

                    // Restore the video level.
                    state.VideoStream.Level = originalLevel;
                    var newPlaylist = ReplacePlaylistCodecsField(basicPlaylist, playlistCodecsField, newPlaylistCodecsField);
                    builder.Append(newPlaylist);
                }
            }

            if (EnableAdaptiveBitrateStreaming(state, isLiveStream, enableAdaptiveBitrateStreaming, _httpContextAccessor.HttpContext.GetNormalizedRemoteIp()))
            {
                var requestedVideoBitrate = state.VideoRequest == null ? 0 : state.VideoRequest.VideoBitRate ?? 0;

                // By default, vary by just 200k
                var variation = GetBitrateVariation(totalBitrate);

                var newBitrate = totalBitrate - variation;
                var variantUrl = ReplaceVideoBitrate(playlistUrl, requestedVideoBitrate, requestedVideoBitrate - variation);
                AppendPlaylist(builder, state, variantUrl, newBitrate, subtitleGroup);

                variation *= 2;
                newBitrate = totalBitrate - variation;
                variantUrl = ReplaceVideoBitrate(playlistUrl, requestedVideoBitrate, requestedVideoBitrate - variation);
                AppendPlaylist(builder, state, variantUrl, newBitrate, subtitleGroup);
            }

            return(new FileContentResult(Encoding.UTF8.GetBytes(builder.ToString()), MimeTypes.GetMimeType("playlist.m3u8")));
        }
コード例 #34
0
ファイル: ApiEntryPoint.cs プロジェクト: Kampari/MediaBrowser
 /// <summary>
 /// Called when [transcode beginning].
 /// </summary>
 /// <param name="path">The path.</param>
 /// <param name="type">The type.</param>
 /// <param name="process">The process.</param>
 /// <param name="isVideo">if set to <c>true</c> [is video].</param>
 /// <param name="startTimeTicks">The start time ticks.</param>
 /// <param name="sourcePath">The source path.</param>
 public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process, bool isVideo, long? startTimeTicks, string sourcePath)
 {
     lock (_activeTranscodingJobs)
     {
         _activeTranscodingJobs.Add(new TranscodingJob
         {
             Type = type,
             Path = path,
             Process = process,
             ActiveRequestCount = 1,
             IsVideo = isVideo,
             StartTimeTicks = startTimeTicks,
             SourcePath = sourcePath
         });
     }
 }
コード例 #35
0
ファイル: ApiEntryPoint.cs プロジェクト: snap608/MediaBrowser
        /// <summary>
        /// Called when [transcode begin request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodeBeginRequest(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return;
                }

                job.ActiveRequestCount++;

                if (job.KillTimer != null)
                {
                    job.KillTimer.Dispose();
                    job.KillTimer = null;
                }
            }
        }
コード例 #36
0
        /// <summary>
        /// Called when [transcode beginning].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        /// <param name="process">The process.</param>
        /// <param name="deviceId">The device id.</param>
        /// <param name="state">The state.</param>
        /// <param name="cancellationTokenSource">The cancellation token source.</param>
        public void OnTranscodeBeginning(string path,
            TranscodingJobType type,
            Process process,
            string deviceId,
            StreamState state,
            CancellationTokenSource cancellationTokenSource)
        {
            lock (_activeTranscodingJobs)
            {
                _activeTranscodingJobs.Add(new TranscodingJob
                {
                    Type = type,
                    Path = path,
                    Process = process,
                    ActiveRequestCount = 1,
                    DeviceId = deviceId,
                    CancellationTokenSource = cancellationTokenSource
                });

                ReportTranscodingProgress(state, null, null);
            }
        }
コード例 #37
0
ファイル: ApiEntryPoint.cs プロジェクト: snap608/MediaBrowser
        /// <summary>
        /// Called when [transcode end request].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodeEndRequest(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                if (job == null)
                {
                    return;
                }

                job.ActiveRequestCount--;

                if (job.ActiveRequestCount == 0)
                {
                    var timerDuration = type == TranscodingJobType.Progressive ? 1000 : 30000;

                    if (job.KillTimer == null)
                    {
                        job.KillTimer = new Timer(OnTranscodeKillTimerStopped, job, timerDuration, Timeout.Infinite);
                    }
                    else
                    {
                        job.KillTimer.Change(timerDuration, Timeout.Infinite);
                    }
                }
            }
        }
コード例 #38
0
        /// <summary>
        /// Starts FFmpeg.
        /// </summary>
        /// <param name="state">The state.</param>
        /// <param name="outputPath">The output path.</param>
        /// <param name="commandLineArguments">The command line arguments for FFmpeg.</param>
        /// <param name="request">The <see cref="HttpRequest"/>.</param>
        /// <param name="transcodingJobType">The <see cref="TranscodingJobType"/>.</param>
        /// <param name="cancellationTokenSource">The cancellation token source.</param>
        /// <param name="workingDirectory">The working directory.</param>
        /// <returns>Task.</returns>
        public async Task <TranscodingJobDto> StartFfMpeg(
            StreamState state,
            string outputPath,
            string commandLineArguments,
            HttpRequest request,
            TranscodingJobType transcodingJobType,
            CancellationTokenSource cancellationTokenSource,
            string?workingDirectory = null)
        {
            var directory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath));

            Directory.CreateDirectory(directory);

            await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);

            if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec))
            {
                var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false);

                if (auth.User != null && !auth.User.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding))
                {
                    this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state);

                    throw new ArgumentException("User does not have access to video transcoding.");
                }
            }

            if (string.IsNullOrEmpty(_mediaEncoder.EncoderPath))
            {
                throw new ArgumentException("FFmpeg path not set.");
            }

            // If subtitles get burned in fonts may need to be extracted from the media file
            if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
            {
                var attachmentPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id);
                await _attachmentExtractor.ExtractAllAttachments(state.MediaPath, state.MediaSource, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false);

                if (state.SubtitleStream.IsExternal && string.Equals(Path.GetExtension(state.SubtitleStream.Path), ".mks", StringComparison.OrdinalIgnoreCase))
                {
                    string subtitlePath         = state.SubtitleStream.Path;
                    string subtitlePathArgument = string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", subtitlePath.Replace("\"", "\\\"", StringComparison.Ordinal));
                    string subtitleId           = subtitlePath.GetMD5().ToString("N", CultureInfo.InvariantCulture);

                    await _attachmentExtractor.ExtractAllAttachmentsExternal(subtitlePathArgument, subtitleId, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false);
                }
            }

            var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    WindowStyle     = ProcessWindowStyle.Hidden,
                    CreateNoWindow  = true,
                    UseShellExecute = false,

                    // Must consume both stdout and stderr or deadlocks may occur
                    // RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    RedirectStandardInput = true,
                    FileName         = _mediaEncoder.EncoderPath,
                    Arguments        = commandLineArguments,
                    WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? string.Empty : workingDirectory,
                    ErrorDialog      = false
                },
                EnableRaisingEvents = true
            };

            var transcodingJob = this.OnTranscodeBeginning(
                outputPath,
                state.Request.PlaySessionId,
                state.MediaSource.LiveStreamId,
                Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
                transcodingJobType,
                process,
                state.Request.DeviceId,
                state,
                cancellationTokenSource);

            _logger.LogInformation("{Filename} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments);

            var logFilePrefix = "FFmpeg.Transcode-";

            if (state.VideoRequest != null &&
                EncodingHelper.IsCopyCodec(state.OutputVideoCodec))
            {
                logFilePrefix = EncodingHelper.IsCopyCodec(state.OutputAudioCodec)
                    ? "FFmpeg.Remux-"
                    : "FFmpeg.DirectStream-";
            }

            var logFilePath = Path.Combine(
                _serverConfigurationManager.ApplicationPaths.LogDirectoryPath,
                $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log");
コード例 #39
0
ファイル: ApiEntryPoint.cs プロジェクト: 7illusions/Emby
 public TranscodingJob GetTranscodingJob(string path, TranscodingJobType type)
 {
     lock (_activeTranscodingJobs)
     {
         return _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase));
     }
 }
コード例 #40
0
ファイル: ApiEntryPoint.cs プロジェクト: 7illusions/Emby
 /// <summary>
 /// Determines whether [has active transcoding job] [the specified path].
 /// </summary>
 /// <param name="path">The path.</param>
 /// <param name="type">The type.</param>
 /// <returns><c>true</c> if [has active transcoding job] [the specified path]; otherwise, <c>false</c>.</returns>
 public bool HasActiveTranscodingJob(string path, TranscodingJobType type)
 {
     return GetTranscodingJob(path, type) != null;
 }
コード例 #41
0
ファイル: ApiEntryPoint.cs プロジェクト: 7illusions/Emby
        /// <summary>
        /// <summary>
        /// The progressive
        /// </summary>
        /// Called when [transcode failed to start].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        /// <param name="state">The state.</param>
        public void OnTranscodeFailedToStart(string path, TranscodingJobType type, StreamState state)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase));

                if (job != null)
                {
                    _activeTranscodingJobs.Remove(job);
                }
            }

            if (!string.IsNullOrWhiteSpace(state.Request.DeviceId))
            {
                _sessionManager.ClearTranscodingInfo(state.Request.DeviceId);
            }
        }
コード例 #42
0
ファイル: ApiEntryPoint.cs プロジェクト: snap608/MediaBrowser
        /// <summary>
        /// <summary>
        /// The progressive
        /// </summary>
        /// Called when [transcode failed to start].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="type">The type.</param>
        public void OnTranscodeFailedToStart(string path, TranscodingJobType type)
        {
            lock (_activeTranscodingJobs)
            {
                var job = _activeTranscodingJobs.First(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

                _activeTranscodingJobs.Remove(job);
            }
        }
コード例 #43
0
ファイル: ApiEntryPoint.cs プロジェクト: 7illusions/Emby
        /// <summary>
        /// Called when [transcode beginning].
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="playSessionId">The play session identifier.</param>
        /// <param name="liveStreamId">The live stream identifier.</param>
        /// <param name="transcodingJobId">The transcoding job identifier.</param>
        /// <param name="type">The type.</param>
        /// <param name="process">The process.</param>
        /// <param name="deviceId">The device id.</param>
        /// <param name="state">The state.</param>
        /// <param name="cancellationTokenSource">The cancellation token source.</param>
        /// <returns>TranscodingJob.</returns>
        public TranscodingJob OnTranscodeBeginning(string path,
            string playSessionId,
            string liveStreamId,
            string transcodingJobId,
            TranscodingJobType type,
            Process process,
            string deviceId,
            StreamState state,
            CancellationTokenSource cancellationTokenSource)
        {
            lock (_activeTranscodingJobs)
            {
                var job = new TranscodingJob(Logger)
                {
                    Type = type,
                    Path = path,
                    Process = process,
                    ActiveRequestCount = 1,
                    DeviceId = deviceId,
                    CancellationTokenSource = cancellationTokenSource,
                    Id = transcodingJobId,
                    PlaySessionId = playSessionId,
                    LiveStreamId = liveStreamId
                };

                _activeTranscodingJobs.Add(job);

                ReportTranscodingProgress(job, state, null, null, null, null, null);

                return job;
            }
        }
コード例 #44
0
ファイル: ApiEntryPoint.cs プロジェクト: 7illusions/Emby
        private async void DeletePartialStreamFiles(string path, TranscodingJobType jobType, int retryCount, int delayMs)
        {
            if (retryCount >= 10)
            {
                return;
            }

            Logger.Info("Deleting partial stream file(s) {0}", path);

            await Task.Delay(delayMs).ConfigureAwait(false);

            try
            {
                if (jobType == TranscodingJobType.Progressive)
                {
                    DeleteProgressivePartialStreamFiles(path);
                }
                else
                {
                    DeleteHlsPartialStreamFiles(path);
                }
            }
            catch (DirectoryNotFoundException)
            {

            }
            catch (FileNotFoundException)
            {

            }
            catch (IOException)
            {
                //Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, path);

                DeletePartialStreamFiles(path, jobType, retryCount + 1, 500);
            }
            catch
            {
                //Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, path);
            }
        }