Esempio n. 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ProgressiveFileCopier"/> class.
 /// </summary>
 /// <param name="directStreamProvider">Instance of the <see cref="IDirectStreamProvider"/> interface.</param>
 /// <param name="job">The transcoding job.</param>
 /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/>.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, CancellationToken cancellationToken)
 {
     _directStreamProvider = directStreamProvider;
     _job = job;
     _cancellationToken    = cancellationToken;
     _transcodingJobHelper = transcodingJobHelper;
 }
Esempio n. 2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ProgressiveFileCopier"/> class.
 /// </summary>
 /// <param name="path">The path to copy from.</param>
 /// <param name="job">The transcoding job.</param>
 /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/>.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 public ProgressiveFileCopier(string path, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, CancellationToken cancellationToken)
 {
     _path = path;
     _job  = job;
     _cancellationToken    = cancellationToken;
     _transcodingJobHelper = transcodingJobHelper;
 }
Esempio n. 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class.
 /// </summary>
 /// <param name="stream">The stream to progressively copy.</param>
 /// <param name="timeoutMs">The timeout duration in milliseconds.</param>
 public ProgressiveFileStream(Stream stream, int timeoutMs = 30000)
 {
     _job = null;
     _transcodingJobHelper = null;
     _timeoutMs            = timeoutMs;
     _stream = stream;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class.
 /// </summary>
 /// <param name="stream">The stream to progressively copy.</param>
 /// <param name="timeoutMs">The timeout duration in milliseconds.</param>
 public ProgressiveFileStream(Stream stream, int timeoutMs = 30000)
 {
     _job = null;
     _transcodingJobHelper = null;
     _timeoutMs            = timeoutMs;
     _allowAsyncFileRead   = AsyncFile.UseAsyncIO;
     _stream = stream;
 }
Esempio n. 5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class.
        /// </summary>
        /// <param name="filePath">The path to the transcoded file.</param>
        /// <param name="job">The transcoding job information.</param>
        /// <param name="transcodingJobHelper">The transcoding job helper.</param>
        /// <param name="timeoutMs">The timeout duration in milliseconds.</param>
        public ProgressiveFileStream(string filePath, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, int timeoutMs = 30000)
        {
            _job = job;
            _transcodingJobHelper = transcodingJobHelper;
            _timeoutMs            = timeoutMs;

            _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class.
        /// </summary>
        /// <param name="filePath">The path to the transcoded file.</param>
        /// <param name="job">The transcoding job information.</param>
        /// <param name="transcodingJobHelper">The transcoding job helper.</param>
        /// <param name="timeoutMs">The timeout duration in milliseconds.</param>
        public ProgressiveFileStream(string filePath, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, int timeoutMs = 30000)
        {
            _job = job;
            _transcodingJobHelper = transcodingJobHelper;
            _timeoutMs            = timeoutMs;

            var fileOptions = FileOptions.SequentialScan;

            _allowAsyncFileRead = false;

            // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
            if (AsyncFile.UseAsyncIO)
            {
                fileOptions        |= FileOptions.Asynchronous;
                _allowAsyncFileRead = true;
            }

            _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions);
        }
Esempio n. 7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class.
        /// </summary>
        /// <param name="filePath">The path to the transcoded file.</param>
        /// <param name="job">The transcoding job information.</param>
        /// <param name="transcodingJobHelper">The transcoding job helper.</param>
        public ProgressiveFileStream(string filePath, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper)
        {
            _job = job;
            _transcodingJobHelper = transcodingJobHelper;
            _bytesWritten         = 0;

            var fileOptions = FileOptions.SequentialScan;

            _allowAsyncFileRead = false;

            // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                fileOptions        |= FileOptions.Asynchronous;
                _allowAsyncFileRead = true;
            }

            _fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions);
        }
Esempio n. 8
0
        public async Task <ActionResult> GetLiveHlsStream(
            [FromRoute, Required] Guid itemId,
            [FromQuery] string?container,
            [FromQuery] bool? @static,
            [FromQuery] string? @params,
            [FromQuery] string?tag,
            [FromQuery] string?deviceProfileId,
            [FromQuery] string?playSessionId,
            [FromQuery] string?segmentContainer,
            [FromQuery] int?segmentLength,
            [FromQuery] int?minSegments,
            [FromQuery] string?mediaSourceId,
            [FromQuery] string?deviceId,
            [FromQuery] string?audioCodec,
            [FromQuery] bool?enableAutoStreamCopy,
            [FromQuery] bool?allowVideoStreamCopy,
            [FromQuery] bool?allowAudioStreamCopy,
            [FromQuery] bool?breakOnNonKeyFrames,
            [FromQuery] int?audioSampleRate,
            [FromQuery] int?maxAudioBitDepth,
            [FromQuery] int?audioBitRate,
            [FromQuery] int?audioChannels,
            [FromQuery] int?maxAudioChannels,
            [FromQuery] string?profile,
            [FromQuery] string?level,
            [FromQuery] float?framerate,
            [FromQuery] float?maxFramerate,
            [FromQuery] bool?copyTimestamps,
            [FromQuery] long?startTimeTicks,
            [FromQuery] int?width,
            [FromQuery] int?height,
            [FromQuery] int?videoBitRate,
            [FromQuery] int?subtitleStreamIndex,
            [FromQuery] SubtitleDeliveryMethod?subtitleMethod,
            [FromQuery] int?maxRefFrames,
            [FromQuery] int?maxVideoBitDepth,
            [FromQuery] bool?requireAvc,
            [FromQuery] bool?deInterlace,
            [FromQuery] bool?requireNonAnamorphic,
            [FromQuery] int?transcodingMaxAudioChannels,
            [FromQuery] int?cpuCoreLimit,
            [FromQuery] string?liveStreamId,
            [FromQuery] bool?enableMpegtsM2TsMode,
            [FromQuery] string?videoCodec,
            [FromQuery] string?subtitleCodec,
            [FromQuery] string?transcodeReasons,
            [FromQuery] int?audioStreamIndex,
            [FromQuery] int?videoStreamIndex,
            [FromQuery] EncodingContext?context,
            [FromQuery] Dictionary <string, string> streamOptions,
            [FromQuery] int?maxWidth,
            [FromQuery] int?maxHeight,
            [FromQuery] bool?enableSubtitlesInManifest)
        {
            VideoRequestDto streamingRequest = new VideoRequestDto
            {
                Id                          = itemId,
                Container                   = container,
                Static                      = @static ?? false,
                Params                      = @params,
                Tag                         = tag,
                DeviceProfileId             = deviceProfileId,
                PlaySessionId               = playSessionId,
                SegmentContainer            = segmentContainer,
                SegmentLength               = segmentLength,
                MinSegments                 = minSegments,
                MediaSourceId               = mediaSourceId,
                DeviceId                    = deviceId,
                AudioCodec                  = audioCodec,
                EnableAutoStreamCopy        = enableAutoStreamCopy ?? true,
                AllowAudioStreamCopy        = allowAudioStreamCopy ?? true,
                AllowVideoStreamCopy        = allowVideoStreamCopy ?? true,
                BreakOnNonKeyFrames         = breakOnNonKeyFrames ?? false,
                AudioSampleRate             = audioSampleRate,
                MaxAudioChannels            = maxAudioChannels,
                AudioBitRate                = audioBitRate,
                MaxAudioBitDepth            = maxAudioBitDepth,
                AudioChannels               = audioChannels,
                Profile                     = profile,
                Level                       = level,
                Framerate                   = framerate,
                MaxFramerate                = maxFramerate,
                CopyTimestamps              = copyTimestamps ?? false,
                StartTimeTicks              = startTimeTicks,
                Width                       = width,
                Height                      = height,
                VideoBitRate                = videoBitRate,
                SubtitleStreamIndex         = subtitleStreamIndex,
                SubtitleMethod              = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
                MaxRefFrames                = maxRefFrames,
                MaxVideoBitDepth            = maxVideoBitDepth,
                RequireAvc                  = requireAvc ?? false,
                DeInterlace                 = deInterlace ?? false,
                RequireNonAnamorphic        = requireNonAnamorphic ?? false,
                TranscodingMaxAudioChannels = transcodingMaxAudioChannels,
                CpuCoreLimit                = cpuCoreLimit,
                LiveStreamId                = liveStreamId,
                EnableMpegtsM2TsMode        = enableMpegtsM2TsMode ?? false,
                VideoCodec                  = videoCodec,
                SubtitleCodec               = subtitleCodec,
                TranscodeReasons            = transcodeReasons,
                AudioStreamIndex            = audioStreamIndex,
                VideoStreamIndex            = videoStreamIndex,
                Context                     = context ?? EncodingContext.Streaming,
                StreamOptions               = streamOptions,
                MaxHeight                   = maxHeight,
                MaxWidth                    = maxWidth,
                EnableSubtitlesInManifest   = enableSubtitlesInManifest ?? true
            };

            var cancellationTokenSource = new CancellationTokenSource();

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

            TranscodingJobDto?job = null;
            var playlistPath      = Path.ChangeExtension(state.OutputFilePath, ".m3u8");

            if (!System.IO.File.Exists(playlistPath))
            {
                var transcodingLock = _transcodingJobHelper.GetTranscodingLock(playlistPath);
                await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);

                try
                {
                    if (!System.IO.File.Exists(playlistPath))
                    {
                        // If the playlist doesn't already exist, startup ffmpeg
                        try
                        {
                            job = await _transcodingJobHelper.StartFfMpeg(
                                state,
                                playlistPath,
                                GetCommandLineArguments(playlistPath, state),
                                Request,
                                TranscodingJobType,
                                cancellationTokenSource)
                                  .ConfigureAwait(false);

                            job.IsLiveOutput = true;
                        }
                        catch
                        {
                            state.Dispose();
                            throw;
                        }

                        minSegments = state.MinSegments;
                        if (minSegments > 0)
                        {
                            await HlsHelpers.WaitForMinimumSegmentCount(playlistPath, minSegments, _logger, cancellationTokenSource.Token).ConfigureAwait(false);
                        }
                    }
                }
                finally
                {
                    transcodingLock.Release();
                }
            }

            job ??= _transcodingJobHelper.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);

            if (job != null)
            {
                _transcodingJobHelper.OnTranscodeEndRequest(job);
            }

            var playlistText = HlsHelpers.GetLivePlaylistText(playlistPath, state);

            return(Content(playlistText, MimeTypes.GetMimeType("playlist.m3u8")));
        }