예제 #1
0
        private PlayMethod ValidatePlayMethod(PlayMethod method, string playSessionId)
        {
            if (method == PlayMethod.Transcode)
            {
                var job = string.IsNullOrWhiteSpace(playSessionId) ? null : _transcodingJobHelper.GetTranscodingJob(playSessionId);
                if (job == null)
                {
                    return(PlayMethod.DirectPlay);
                }
            }

            return(method);
        }
예제 #2
0
        public async Task <ActionResult> GetVideoStream(
            [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?maxWidth,
            [FromQuery] int?maxHeight,
            [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)
        {
            var isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head;
            // CTS lifecycle is managed internally.
            var cancellationTokenSource = new CancellationTokenSource();
            var 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,
                MaxWidth                    = maxWidth,
                MaxHeight                   = maxHeight,
                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
            };

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

            if (@static.HasValue && @static.Value && state.DirectStreamProvider != null)
            {
                StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager);

                await new ProgressiveFileCopier(state.DirectStreamProvider, null, _transcodingJobHelper, CancellationToken.None)
                {
                    AllowEndOfFile = false
                }.WriteToAsync(Response.Body, CancellationToken.None)
                .ConfigureAwait(false);

                // TODO (moved from MediaBrowser.Api): Don't hardcode contentType
                return(File(Response.Body, MimeTypes.GetMimeType("file.ts") !));
            }

            // Static remote stream
            if (@static.HasValue && @static.Value && state.InputProtocol == MediaProtocol.Http)
            {
                StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager);

                var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
                return(await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, HttpContext).ConfigureAwait(false));
            }

            if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File)
            {
                return(BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically"));
            }

            var outputPath       = state.OutputFilePath;
            var outputPathExists = System.IO.File.Exists(outputPath);

            var transcodingJob    = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive);
            var isTranscodeCached = outputPathExists && transcodingJob != null;

            StreamingHelpers.AddDlnaHeaders(state, Response.Headers, (@static.HasValue && @static.Value) || isTranscodeCached, startTimeTicks, Request, _dlnaManager);

            // Static stream
            if (@static.HasValue && @static.Value)
            {
                var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath);

                if (state.MediaSource.IsInfiniteStream)
                {
                    await new ProgressiveFileCopier(state.MediaPath, null, _transcodingJobHelper, CancellationToken.None)
                    {
                        AllowEndOfFile = false
                    }.WriteToAsync(Response.Body, CancellationToken.None)
                    .ConfigureAwait(false);

                    return(File(Response.Body, contentType));
                }

                return(FileStreamResponseHelpers.GetStaticFileResult(
                           state.MediaPath,
                           contentType,
                           isHeadRequest,
                           HttpContext));
            }

            // Need to start ffmpeg (because media can't be returned directly)
            var encodingOptions            = _serverConfigurationManager.GetEncodingOptions();
            var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast");

            return(await FileStreamResponseHelpers.GetTranscodedFile(
                       state,
                       isHeadRequest,
                       HttpContext,
                       _transcodingJobHelper,
                       ffmpegCommandLineArguments,
                       _transcodingJobType,
                       cancellationTokenSource).ConfigureAwait(false));
        }