Ejemplo n.º 1
0
        /// <summary>
        /// Gets the name of the output audio codec
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>System.String.</returns>
        protected string GetAudioCodec(StreamRequest request)
        {
            var codec = request.AudioCodec;

            if (codec.HasValue)
            {
                if (codec == AudioCodecs.Aac)
                {
                    return("libvo_aacenc");
                }
                if (codec == AudioCodecs.Mp3)
                {
                    return("libmp3lame");
                }
                if (codec == AudioCodecs.Vorbis)
                {
                    return("libvorbis");
                }
                if (codec == AudioCodecs.Wma)
                {
                    return("wmav2");
                }

                return(codec.ToString().ToLower());
            }

            return("copy");
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Parses the dlna headers.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ParseDlnaHeaders(StreamRequest request)
        {
            if (!request.StartTimeTicks.HasValue)
            {
                var timeSeek = GetHeader("TimeSeekRange.dlna.org");

                request.StartTimeTicks = ParseTimeSeekHeader(timeSeek);
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Parses query parameters as StreamOptions
 /// <summary>
 /// <param name="request">The stream request.</param>
 private void ParseStreamOptions(StreamRequest request)
 {
     foreach (var param in Request.QueryString)
     {
         if (char.IsLower(param.Key[0]))
         {
             // This was probably not parsed initially and should be a StreamOptions
             // TODO: This should be incorporated either in the lower framework for parsing requests
             // or the generated URL should correctly serialize it
             request.StreamOptions[param.Key] = param.Value;
         }
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Gets the number of audio channels to specify on the command line
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="audioStream">The audio stream.</param>
        /// <returns>System.Nullable{System.Int32}.</returns>
        protected int?GetNumAudioChannelsParam(StreamRequest request, MediaStream audioStream)
        {
            if (audioStream.Channels > 2 && request.AudioCodec.HasValue)
            {
                if (request.AudioCodec.Value == AudioCodecs.Wma)
                {
                    // wmav2 currently only supports two channel output
                    return(2);
                }
            }

            return(request.AudioChannels);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets the slow seek command line parameter.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>System.String.</returns>
        /// <value>The slow seek command line parameter.</value>
        protected string GetSlowSeekCommandLineParameter(StreamRequest request)
        {
            var time = request.StartTimeTicks;

            if (time.HasValue)
            {
                if (TimeSpan.FromTicks(time.Value).TotalSeconds - FastSeekOffsetSeconds > 0)
                {
                    return(string.Format(" -ss {0}", FastSeekOffsetSeconds.ToString(UsCulture)));
                }
            }

            return(string.Empty);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>StreamState.</returns>
        protected StreamState GetState(StreamRequest request)
        {
            var item = DtoService.GetItemByDtoId(request.Id);

            var media = (IHasMediaStreams)item;

            var url = RequestContext.PathInfo;

            if (!request.AudioCodec.HasValue)
            {
                request.AudioCodec = InferAudioCodec(url);
            }

            var state = new StreamState
            {
                Item    = item,
                Request = request,
                Url     = url
            };

            var videoRequest = request as VideoStreamRequest;

            if (videoRequest != null)
            {
                if (!videoRequest.VideoCodec.HasValue)
                {
                    videoRequest.VideoCodec = InferVideoCodec(url);
                }

                state.VideoStream    = GetMediaStream(media.MediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
                state.SubtitleStream = GetMediaStream(media.MediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
                state.AudioStream    = GetMediaStream(media.MediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
            }
            else
            {
                state.AudioStream = GetMediaStream(media.MediaStreams, null, MediaStreamType.Audio, true);
            }

            return(state);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>StreamState.</returns>
        protected async Task <StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
        {
            ParseDlnaHeaders(request);

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

            ParseStreamOptions(request);

            var url = Request.PathInfo;

            if (string.IsNullOrEmpty(request.AudioCodec))
            {
                request.AudioCodec = EncodingHelper.InferAudioCodec(url);
            }

            var enableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params) ||
                                    string.Equals(GetHeader("GetContentFeatures.DLNA.ORG"), "1", StringComparison.OrdinalIgnoreCase);

            var state = new StreamState(MediaSourceManager, TranscodingJobType)
            {
                Request           = request,
                RequestedUrl      = url,
                UserAgent         = Request.UserAgent,
                EnableDlnaHeaders = enableDlnaHeaders
            };

            var auth = AuthorizationContext.GetAuthorizationInfo(Request);

            if (!auth.UserId.Equals(Guid.Empty))
            {
                state.User = UserManager.GetUserById(auth.UserId);
            }

            //if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
            //    (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
            //    (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
            //{
            //    state.SegmentLength = 6;
            //}

            if (state.VideoRequest != null && !string.IsNullOrWhiteSpace(state.VideoRequest.VideoCodec))
            {
                state.SupportedVideoCodecs    = state.VideoRequest.VideoCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
                state.VideoRequest.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault();
            }

            if (!string.IsNullOrWhiteSpace(request.AudioCodec))
            {
                state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
                state.Request.AudioCodec   = state.SupportedAudioCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToAudioCodec(i))
                                             ?? state.SupportedAudioCodecs.FirstOrDefault();
            }

            if (!string.IsNullOrWhiteSpace(request.SubtitleCodec))
            {
                state.SupportedSubtitleCodecs = request.SubtitleCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
                state.Request.SubtitleCodec   = state.SupportedSubtitleCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToSubtitleCodec(i))
                                                ?? state.SupportedSubtitleCodecs.FirstOrDefault();
            }

            var item = LibraryManager.GetItemById(request.Id);

            state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);

            //var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ??
            //             item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null);
            //if (primaryImage != null)
            //{
            //    state.AlbumCoverPath = primaryImage.Path;
            //}

            MediaSourceInfo mediaSource = null;

            if (string.IsNullOrWhiteSpace(request.LiveStreamId))
            {
                var currentJob = !string.IsNullOrWhiteSpace(request.PlaySessionId) ?
                                 ApiEntryPoint.Instance.GetTranscodingJob(request.PlaySessionId)
                    : null;

                if (currentJob != null)
                {
                    mediaSource = currentJob.MediaSource;
                }

                if (mediaSource == null)
                {
                    var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(LibraryManager.GetItemById(request.Id), null, false, false, cancellationToken).ConfigureAwait(false)).ToList();

                    mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
                       ? mediaSources[0]
                       : mediaSources.Find(i => string.Equals(i.Id, request.MediaSourceId));

                    if (mediaSource == null && request.MediaSourceId.Equals(request.Id))
                    {
                        mediaSource = mediaSources[0];
                    }
                }
            }
            else
            {
                var liveStreamInfo = await MediaSourceManager.GetLiveStreamWithDirectStreamProvider(request.LiveStreamId, cancellationToken).ConfigureAwait(false);

                mediaSource = liveStreamInfo.Item1;
                state.DirectStreamProvider = liveStreamInfo.Item2;
            }

            var videoRequest = request as VideoStreamRequest;

            EncodingHelper.AttachMediaSourceInfo(state, mediaSource, url);

            var container = Path.GetExtension(state.RequestedUrl);

            if (string.IsNullOrEmpty(container))
            {
                container = request.Container;
            }

            if (string.IsNullOrEmpty(container))
            {
                container = request.Static ?
                            StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, state.MediaPath, null, DlnaProfileType.Audio) :
                            GetOutputFileExtension(state);
            }

            state.OutputContainer = (container ?? string.Empty).TrimStart('.');

            state.OutputAudioBitrate = EncodingHelper.GetAudioBitrateParam(state.Request, state.AudioStream);

            state.OutputAudioCodec = state.Request.AudioCodec;

            state.OutputAudioChannels = EncodingHelper.GetNumAudioChannelsParam(state, state.AudioStream, state.OutputAudioCodec);

            if (videoRequest != null)
            {
                state.OutputVideoCodec   = state.VideoRequest.VideoCodec;
                state.OutputVideoBitrate = EncodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);

                if (videoRequest != null)
                {
                    EncodingHelper.TryStreamCopy(state);
                }

                if (state.OutputVideoBitrate.HasValue && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
                {
                    var resolution = ResolutionNormalizer.Normalize(
                        state.VideoStream?.BitRate,
                        state.VideoStream?.Width,
                        state.VideoStream?.Height,
                        state.OutputVideoBitrate.Value,
                        state.VideoStream?.Codec,
                        state.OutputVideoCodec,
                        videoRequest.MaxWidth,
                        videoRequest.MaxHeight);

                    videoRequest.MaxWidth  = resolution.MaxWidth;
                    videoRequest.MaxHeight = resolution.MaxHeight;
                }
            }

            ApplyDeviceProfileSettings(state);

            var ext = string.IsNullOrWhiteSpace(state.OutputContainer)
                ? GetOutputFileExtension(state)
                : ('.' + state.OutputContainer);

            var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();

            state.OutputFilePath = GetOutputFilePath(state, encodingOptions, ext);

            return(state);
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Gets the slow seek command line parameter.
 /// </summary>
 /// <param name="request">The request.</param>
 /// <returns>System.String.</returns>
 /// <value>The slow seek command line parameter.</value>
 protected string GetSlowSeekCommandLineParameter(StreamRequest request)
 {
     return string.Empty;
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>StreamState.</returns>
        protected async Task <StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
        {
            ParseDlnaHeaders(request);

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

            var url = Request.PathInfo;

            if (string.IsNullOrEmpty(request.AudioCodec))
            {
                request.AudioCodec = EncodingHelper.InferAudioCodec(url);
            }

            var state = new StreamState(MediaSourceManager, Logger, TranscodingJobType)
            {
                Request      = request,
                RequestedUrl = url,
                UserAgent    = Request.UserAgent
            };

            var auth = AuthorizationContext.GetAuthorizationInfo(Request);

            if (!string.IsNullOrWhiteSpace(auth.UserId))
            {
                state.User = UserManager.GetUserById(auth.UserId);
            }

            //if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
            //    (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
            //    (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
            //{
            //    state.SegmentLength = 6;
            //}

            if (state.VideoRequest != null)
            {
                if (!string.IsNullOrWhiteSpace(state.VideoRequest.VideoCodec))
                {
                    state.SupportedVideoCodecs    = state.VideoRequest.VideoCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
                    state.VideoRequest.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault();
                }
            }

            if (!string.IsNullOrWhiteSpace(request.AudioCodec))
            {
                state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
                state.Request.AudioCodec   = state.SupportedAudioCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToAudioCodec(i))
                                             ?? state.SupportedAudioCodecs.FirstOrDefault();
            }

            if (!string.IsNullOrWhiteSpace(request.SubtitleCodec))
            {
                state.SupportedSubtitleCodecs = request.SubtitleCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
                state.Request.SubtitleCodec   = state.SupportedSubtitleCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToSubtitleCodec(i))
                                                ?? state.SupportedSubtitleCodecs.FirstOrDefault();
            }

            var item = LibraryManager.GetItemById(request.Id);

            state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);

            MediaSourceInfo mediaSource = null;

            if (string.IsNullOrWhiteSpace(request.LiveStreamId))
            {
                TranscodingJob currentJob = !string.IsNullOrWhiteSpace(request.PlaySessionId) ?
                                            ApiEntryPoint.Instance.GetTranscodingJob(request.PlaySessionId)
                    : null;

                if (currentJob != null)
                {
                    mediaSource = currentJob.MediaSource;
                }

                if (mediaSource == null)
                {
                    var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();

                    mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
                       ? mediaSources.First()
                       : mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));

                    if (mediaSource == null && string.Equals(request.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase))
                    {
                        mediaSource = mediaSources.First();
                    }
                }
            }
            else
            {
                var liveStreamInfo = await MediaSourceManager.GetLiveStreamWithDirectStreamProvider(request.LiveStreamId, cancellationToken).ConfigureAwait(false);

                mediaSource = liveStreamInfo.Item1;
                state.DirectStreamProvider = liveStreamInfo.Item2;
            }

            var videoRequest = request as VideoStreamRequest;

            EncodingHelper.AttachMediaSourceInfo(state, mediaSource, url);

            var container = Path.GetExtension(state.RequestedUrl);

            if (string.IsNullOrEmpty(container))
            {
                container = request.Static ?
                            state.InputContainer :
                            (Path.GetExtension(GetOutputFilePath(state)) ?? string.Empty).TrimStart('.');
            }

            state.OutputContainer = (container ?? string.Empty).TrimStart('.');

            state.OutputAudioBitrate    = EncodingHelper.GetAudioBitrateParam(state.Request, state.AudioStream);
            state.OutputAudioSampleRate = request.AudioSampleRate;

            state.OutputAudioCodec = state.Request.AudioCodec;

            state.OutputAudioChannels = EncodingHelper.GetNumAudioChannelsParam(state.Request, state.AudioStream, state.OutputAudioCodec);

            if (videoRequest != null)
            {
                state.OutputVideoCodec   = state.VideoRequest.VideoCodec;
                state.OutputVideoBitrate = EncodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);

                if (videoRequest != null)
                {
                    EncodingHelper.TryStreamCopy(state);
                }

                if (state.OutputVideoBitrate.HasValue && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
                {
                    var resolution = ResolutionNormalizer.Normalize(
                        state.VideoStream == null ? (int?)null : state.VideoStream.BitRate,
                        state.OutputVideoBitrate.Value,
                        state.VideoStream == null ? null : state.VideoStream.Codec,
                        state.OutputVideoCodec,
                        videoRequest.MaxWidth,
                        videoRequest.MaxHeight);

                    videoRequest.MaxWidth  = resolution.MaxWidth;
                    videoRequest.MaxHeight = resolution.MaxHeight;
                }

                ApplyDeviceProfileSettings(state);
            }
            else
            {
                ApplyDeviceProfileSettings(state);
            }

            state.OutputFilePath = GetOutputFilePath(state);

            return(state);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>StreamState.</returns>
        protected async Task<StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
        {
            if (!string.IsNullOrWhiteSpace(request.Params))
            {
                ParseParams(request);
            }

            if (request.ThrowDebugError)
            {
                throw new InvalidOperationException("You asked for a debug error, you got one.");
            }

            var user = AuthorizationRequestFilterAttribute.GetCurrentUser(Request, UserManager);

            var url = Request.PathInfo;

            if (!request.AudioCodec.HasValue)
            {
                request.AudioCodec = InferAudioCodec(url);
            }

            var state = new StreamState
            {
                Request = request,
                RequestedUrl = url
            };

            var item = DtoService.GetItemByDtoId(request.Id);

            if (user != null && item.GetPlayAccess(user) != PlayAccess.Full)
            {
                throw new ArgumentException(string.Format("{0} is not allowed to play media.", user.Name));
            }

            if (item is ILiveTvRecording)
            {
                var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);

                state.VideoType = VideoType.VideoFile;
                state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
                state.PlayableStreamFileNames = new List<string>();

                if (!string.IsNullOrEmpty(recording.RecordingInfo.Path) && File.Exists(recording.RecordingInfo.Path))
                {
                    state.MediaPath = recording.RecordingInfo.Path;
                    state.IsRemote = false;
                }
                else if (!string.IsNullOrEmpty(recording.RecordingInfo.Url))
                {
                    state.MediaPath = recording.RecordingInfo.Url;
                    state.IsRemote = true;
                }
                else
                {
                    var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false);

                    state.LiveTvStreamId = streamInfo.Id;

                    if (!string.IsNullOrEmpty(streamInfo.Path) && File.Exists(streamInfo.Path))
                    {
                        state.MediaPath = streamInfo.Path;
                        state.IsRemote = false;
                    }
                    else if (!string.IsNullOrEmpty(streamInfo.Url))
                    {
                        state.MediaPath = streamInfo.Url;
                        state.IsRemote = true;
                    }
                }

                //state.RunTimeTicks = recording.RunTimeTicks;
                state.ReadInputAtNativeFramerate = recording.RecordingInfo.Status == RecordingStatus.InProgress;
                state.SendInputOverStandardInput = recording.RecordingInfo.Status == RecordingStatus.InProgress;
                state.AudioSync = "1000";
                state.DeInterlace = true;
            }
            else if (item is LiveTvChannel)
            {
                var channel = LiveTvManager.GetInternalChannel(request.Id);

                state.VideoType = VideoType.VideoFile;
                state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
                state.PlayableStreamFileNames = new List<string>();

                var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false);

                state.LiveTvStreamId = streamInfo.Id;

                if (!string.IsNullOrEmpty(streamInfo.Path) && File.Exists(streamInfo.Path))
                {
                    state.MediaPath = streamInfo.Path;
                    state.IsRemote = false;
                }
                else if (!string.IsNullOrEmpty(streamInfo.Url))
                {
                    state.MediaPath = streamInfo.Url;
                    state.IsRemote = true;
                }

                state.SendInputOverStandardInput = true;
                state.ReadInputAtNativeFramerate = true;
                state.AudioSync = "1000";
                state.DeInterlace = true;
            }
            else
            {
                state.MediaPath = item.Path;
                state.IsRemote = item.LocationType == LocationType.Remote;

                var video = item as Video;

                if (video != null)
                {
                    state.IsInputVideo = true;
                    state.VideoType = video.VideoType;
                    state.IsoType = video.IsoType;

                    state.PlayableStreamFileNames = video.PlayableStreamFileNames == null
                        ? new List<string>()
                        : video.PlayableStreamFileNames.ToList();
                }

                state.RunTimeTicks = item.RunTimeTicks;
            }

            var videoRequest = request as VideoStreamRequest;

            var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery
            {
                ItemId = item.Id

            }).ToList();

            if (videoRequest != null)
            {
                if (!videoRequest.VideoCodec.HasValue)
                {
                    videoRequest.VideoCodec = InferVideoCodec(url);
                }

                state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
                state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
                state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);

                EnforceResolutionLimit(state, videoRequest);
            }
            else
            {
                state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
            }

            state.HasMediaStreams = mediaStreams.Count > 0;

            state.SegmentLength = state.ReadInputAtNativeFramerate ? 3 : 10;
            state.HlsListSize = state.ReadInputAtNativeFramerate ? 20 : 1440;

            return state;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Gets the fast seek command line parameter.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>System.String.</returns>
        /// <value>The fast seek command line parameter.</value>
        protected string GetFastSeekCommandLineParameter(StreamRequest request)
        {
            var time = request.StartTimeTicks;

            if (time.HasValue && time.Value > 0)
            {
                return string.Format("-ss {0}", MediaEncoder.GetTimeParameter(time.Value));
            }

            return string.Empty;
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Parses the dlna headers.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ParseDlnaHeaders(StreamRequest request)
        {
            if (!request.StartTimeTicks.HasValue)
            {
                var timeSeek = GetHeader("TimeSeekRange.dlna.org");

                request.StartTimeTicks = ParseTimeSeekHeader(timeSeek);
            }
        }
Ejemplo n.º 13
0
        private int? GetAudioBitrateParam(StreamRequest request, MediaStream audioStream)
        {
            if (request.AudioBitRate.HasValue)
            {
                // Make sure we don't request a bitrate higher than the source
                var currentBitrate = audioStream == null ? request.AudioBitRate.Value : audioStream.BitRate ?? request.AudioBitRate.Value;

                return request.AudioBitRate.Value;
                //return Math.Min(currentBitrate, request.AudioBitRate.Value);
            }

            return null;
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Parses the parameters.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ParseParams(StreamRequest request)
        {
            var vals = request.Params.Split(';');

            var videoRequest = request as VideoStreamRequest;

            for (var i = 0; i < vals.Length; i++)
            {
                var val = vals[i];

                if (string.IsNullOrWhiteSpace(val))
                {
                    continue;
                }

                switch (i)
                {
                case 0:
                    request.DeviceProfileId = val;
                    break;

                case 1:
                    request.DeviceId = val;
                    break;

                case 2:
                    request.MediaSourceId = val;
                    break;

                case 3:
                    request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    break;

                case 4:
                    if (videoRequest != null)
                    {
                        videoRequest.VideoCodec = val;
                    }

                    break;

                case 5:
                    request.AudioCodec = val;
                    break;

                case 6:
                    if (videoRequest != null)
                    {
                        videoRequest.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 7:
                    if (videoRequest != null)
                    {
                        videoRequest.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 8:
                    if (videoRequest != null)
                    {
                        videoRequest.VideoBitRate = int.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 9:
                    request.AudioBitRate = int.Parse(val, CultureInfo.InvariantCulture);
                    break;

                case 10:
                    request.MaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
                    break;

                case 11:
                    if (videoRequest != null)
                    {
                        videoRequest.MaxFramerate = float.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 12:
                    if (videoRequest != null)
                    {
                        videoRequest.MaxWidth = int.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 13:
                    if (videoRequest != null)
                    {
                        videoRequest.MaxHeight = int.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 14:
                    request.StartTimeTicks = long.Parse(val, CultureInfo.InvariantCulture);
                    break;

                case 15:
                    if (videoRequest != null)
                    {
                        videoRequest.Level = val;
                    }

                    break;

                case 16:
                    if (videoRequest != null)
                    {
                        videoRequest.MaxRefFrames = int.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 17:
                    if (videoRequest != null)
                    {
                        videoRequest.MaxVideoBitDepth = int.Parse(val, CultureInfo.InvariantCulture);
                    }

                    break;

                case 18:
                    if (videoRequest != null)
                    {
                        videoRequest.Profile = val;
                    }

                    break;

                case 19:
                    // cabac no longer used
                    break;

                case 20:
                    request.PlaySessionId = val;
                    break;

                case 21:
                    // api_key
                    break;

                case 22:
                    request.LiveStreamId = val;
                    break;

                case 23:
                    // Duplicating ItemId because of MediaMonkey
                    break;

                case 24:
                    if (videoRequest != null)
                    {
                        videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }

                    break;

                case 25:
                    if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
                    {
                        if (Enum.TryParse(val, out SubtitleDeliveryMethod method))
                        {
                            videoRequest.SubtitleMethod = method;
                        }
                    }

                    break;

                case 26:
                    request.TranscodingMaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
                    break;

                case 27:
                    if (videoRequest != null)
                    {
                        videoRequest.EnableSubtitlesInManifest = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }

                    break;

                case 28:
                    request.Tag = val;
                    break;

                case 29:
                    if (videoRequest != null)
                    {
                        videoRequest.RequireAvc = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }

                    break;

                case 30:
                    request.SubtitleCodec = val;
                    break;

                case 31:
                    if (videoRequest != null)
                    {
                        videoRequest.RequireNonAnamorphic = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }

                    break;

                case 32:
                    if (videoRequest != null)
                    {
                        videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }

                    break;

                case 33:
                    request.TranscodeReasons = val;
                    break;
                }
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Parses the parameters.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ParseParams(StreamRequest request)
        {
            var vals = request.Params.Split(';');

            var videoRequest = request as VideoStreamRequest;

            for (var i = 0; i < vals.Length; i++)
            {
                var val = vals[i];

                if (string.IsNullOrWhiteSpace(val))
                {
                    continue;
                }

                if (i == 0)
                {
                    request.DeviceProfileId = val;
                }
                else if (i == 1)
                {
                    request.DeviceId = val;
                }
                else if (i == 2)
                {
                    request.MediaSourceId = val;
                }
                else if (i == 3)
                {
                    request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                }
                else if (i == 4)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoCodec = val;
                    }
                }
                else if (i == 5)
                {
                    request.AudioCodec = val;
                }
                else if (i == 6)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.AudioStreamIndex = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 7)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.SubtitleStreamIndex = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 8)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoBitRate = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 9)
                {
                    request.AudioBitRate = int.Parse(val, UsCulture);
                }
                else if (i == 10)
                {
                    request.MaxAudioChannels = int.Parse(val, UsCulture);
                }
                else if (i == 11)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxFramerate = float.Parse(val, UsCulture);
                    }
                }
                else if (i == 12)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxWidth = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 13)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxHeight = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 14)
                {
                    request.StartTimeTicks = long.Parse(val, UsCulture);
                }
                else if (i == 15)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.Level = val;
                    }
                }
                else if (i == 16)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxRefFrames = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 17)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxVideoBitDepth = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 18)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.Profile = val;
                    }
                }
                else if (i == 19)
                {
                    // cabac no longer used
                }
                else if (i == 20)
                {
                    request.PlaySessionId = val;
                }
                else if (i == 21)
                {
                    // api_key
                }
                else if (i == 22)
                {
                    request.LiveStreamId = val;
                }
                else if (i == 23)
                {
                    // Duplicating ItemId because of MediaMonkey
                }
                else if (i == 24)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
                else if (i == 25)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.ForceLiveStream = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
                else if (i == 26)
                {
                    if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
                    {
                        SubtitleDeliveryMethod method;
                        if (Enum.TryParse(val, out method))
                        {
                            videoRequest.SubtitleMethod = method;
                        }
                    }
                }
                else if (i == 27)
                {
                    request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
                }
                else if (i == 28)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.EnableSubtitlesInManifest = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
            }
        }
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>StreamState.</returns>
        protected StreamState GetState(StreamRequest request)
        {
            var item = DtoService.GetItemByDtoId(request.Id);

            var media = (IHasMediaStreams)item;

            var url = RequestContext.PathInfo;

            if (!request.AudioCodec.HasValue)
            {
                request.AudioCodec = InferAudioCodec(url);
            }

            var state = new StreamState
            {
                Item = item,
                Request = request,
                Url = url
            };

            var videoRequest = request as VideoStreamRequest;

            if (videoRequest != null)
            {
                if (!videoRequest.VideoCodec.HasValue)
                {
                    videoRequest.VideoCodec = InferVideoCodec(url);
                }

                state.VideoStream = GetMediaStream(media.MediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
                state.SubtitleStream = GetMediaStream(media.MediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
                state.AudioStream = GetMediaStream(media.MediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
            }
            else
            {
                state.AudioStream = GetMediaStream(media.MediaStreams, null, MediaStreamType.Audio, true);
            }

            return state;
        }
        /// <summary>
        /// Gets the name of the output audio codec
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>System.String.</returns>
        protected string GetAudioCodec(StreamRequest request)
        {
            var codec = request.AudioCodec;

            if (codec.HasValue)
            {
                if (codec == AudioCodecs.Aac)
                {
                    return "libvo_aacenc";
                }
                if (codec == AudioCodecs.Mp3)
                {
                    return "libmp3lame";
                }
                if (codec == AudioCodecs.Vorbis)
                {
                    return "libvorbis";
                }
                if (codec == AudioCodecs.Wma)
                {
                    return "wmav2";
                }

                return codec.ToString().ToLower();
            }

            return "copy";
        }
        /// <summary>
        /// Gets the number of audio channels to specify on the command line
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="audioStream">The audio stream.</param>
        /// <returns>System.Nullable{System.Int32}.</returns>
        protected int? GetNumAudioChannelsParam(StreamRequest request, MediaStream audioStream)
        {
            if (audioStream != null)
            {
                if (audioStream.Channels > 2 && request.AudioCodec.HasValue)
                {
                    if (request.AudioCodec.Value == AudioCodecs.Wma)
                    {
                        // wmav2 currently only supports two channel output
                        return 2;
                    }
                }
            }

            return request.AudioChannels;
        }
        /// <summary>
        /// Gets the slow seek command line parameter.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>System.String.</returns>
        /// <value>The slow seek command line parameter.</value>
        protected string GetSlowSeekCommandLineParameter(StreamRequest request)
        {
            var time = request.StartTimeTicks;

            if (time.HasValue)
            {
                if (TimeSpan.FromTicks(time.Value).TotalSeconds - FastSeekOffsetSeconds > 0)
                {
                    return string.Format(" -ss {0}", FastSeekOffsetSeconds.ToString(UsCulture));
                }
            }

            return string.Empty;
        }
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>StreamState.</returns>
        protected async Task<StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
        {
            var url = Request.PathInfo;

            if (!request.AudioCodec.HasValue)
            {
                request.AudioCodec = InferAudioCodec(url);
            }

            var state = new StreamState
            {
                Request = request,
                RequestedUrl = url
            };

            BaseItem item;

            if (string.Equals(request.Type, "Recording", StringComparison.OrdinalIgnoreCase))
            {
                var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);

                state.VideoType = VideoType.VideoFile;
                state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
                state.PlayableStreamFileNames = new List<string>();

                if (!string.IsNullOrEmpty(recording.RecordingInfo.Path) && File.Exists(recording.RecordingInfo.Path))
                {
                    state.MediaPath = recording.RecordingInfo.Path;
                    state.IsRemote = false;
                }
                else if (!string.IsNullOrEmpty(recording.RecordingInfo.Url))
                {
                    state.MediaPath = recording.RecordingInfo.Url;
                    state.IsRemote = true;
                }
                else
                {
                    state.MediaPath = string.Format("http://localhost:{0}/mediabrowser/LiveTv/Recordings/{1}/Stream",
                        ServerConfigurationManager.Configuration.HttpServerPortNumber,
                        request.Id);

                    state.IsRemote = true;
                }

                item = recording;
            }
            else
            {
                item = DtoService.GetItemByDtoId(request.Id);

                state.MediaPath = item.Path;
                state.IsRemote = item.LocationType == LocationType.Remote;

                var video = item as Video;

                if (video != null)
                {
                    state.IsInputVideo = true;
                    state.VideoType = video.VideoType;
                    state.IsoType = video.IsoType;

                    state.PlayableStreamFileNames = video.PlayableStreamFileNames == null
                        ? new List<string>()
                        : video.PlayableStreamFileNames.ToList();
                }
            }

            var videoRequest = request as VideoStreamRequest;

            var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery
            {
                ItemId = item.Id

            }).ToList();

            if (videoRequest != null)
            {
                if (!videoRequest.VideoCodec.HasValue)
                {
                    videoRequest.VideoCodec = InferVideoCodec(url);
                }

                state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
                state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
                state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
            }
            else
            {
                state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
            }

            state.HasMediaStreams = mediaStreams.Count > 0;

            return state;
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>StreamState.</returns>
        protected async Task<StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
        {
            ParseDlnaHeaders(request);

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

            var url = Request.PathInfo;

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

            var state = new StreamState(MediaSourceManager, Logger)
            {
                Request = request,
                RequestedUrl = url
            };

            //if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
            //    (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
            //    (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
            //{
            //    state.SegmentLength = 6;
            //}

            if (!string.IsNullOrWhiteSpace(request.AudioCodec))
            {
                state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
                state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault();
            }

            var item = LibraryManager.GetItemById(request.Id);

            state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);

            var archivable = item as IArchivable;
            state.IsInputArchive = archivable != null && archivable.IsArchive;

            MediaSourceInfo mediaSource;
            if (string.IsNullOrWhiteSpace(request.LiveStreamId))
            {
                var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();

                mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
                   ? mediaSources.First()
                   : mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));

                if (mediaSource == null && string.Equals(request.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase))
                {
                    mediaSource = mediaSources.First();
                }
            }
            else
            {
                mediaSource = await MediaSourceManager.GetLiveStream(request.LiveStreamId, cancellationToken).ConfigureAwait(false);
            }

            var videoRequest = request as VideoStreamRequest;

            AttachMediaSourceInfo(state, mediaSource, videoRequest, url);

            var container = Path.GetExtension(state.RequestedUrl);

            if (string.IsNullOrEmpty(container))
            {
                container = request.Static ?
                    state.InputContainer :
                    (Path.GetExtension(GetOutputFilePath(state)) ?? string.Empty).TrimStart('.');
            }

            state.OutputContainer = (container ?? string.Empty).TrimStart('.');

            state.OutputAudioBitrate = GetAudioBitrateParam(state.Request, state.AudioStream);
            state.OutputAudioSampleRate = request.AudioSampleRate;

            state.OutputAudioCodec = state.Request.AudioCodec;

            state.OutputAudioChannels = GetNumAudioChannelsParam(state.Request, state.AudioStream, state.OutputAudioCodec);

            if (videoRequest != null)
            {
                state.OutputVideoCodec = state.VideoRequest.VideoCodec;
                state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream);

                if (state.OutputVideoBitrate.HasValue)
                {
                    var resolution = ResolutionNormalizer.Normalize(
						state.VideoStream == null ? (int?)null : state.VideoStream.BitRate,
						state.OutputVideoBitrate.Value,
						state.VideoStream == null ? null : state.VideoStream.Codec,
                        state.OutputVideoCodec,
                        videoRequest.MaxWidth,
                        videoRequest.MaxHeight);

                    videoRequest.MaxWidth = resolution.MaxWidth;
                    videoRequest.MaxHeight = resolution.MaxHeight;
                }
            }

            ApplyDeviceProfileSettings(state);

            if (videoRequest != null)
            {
                TryStreamCopy(state, videoRequest);
            }

            state.OutputFilePath = GetOutputFilePath(state);

            return state;
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Gets the number of audio channels to specify on the command line
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="audioStream">The audio stream.</param>
        /// <param name="outputAudioCodec">The output audio codec.</param>
        /// <returns>System.Nullable{System.Int32}.</returns>
        private int? GetNumAudioChannelsParam(StreamRequest request, MediaStream audioStream, string outputAudioCodec)
        {
            var inputChannels = audioStream == null
                ? null
                : audioStream.Channels;

            if (inputChannels <= 0)
            {
                inputChannels = null;
            }

            var codec = outputAudioCodec ?? string.Empty;

            if (codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1)
            {
                // wmav2 currently only supports two channel output
                return Math.Min(2, inputChannels ?? 2);
            }

            if (request.MaxAudioChannels.HasValue)
            {
                var channelLimit = codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1
                   ? 2
                   : 6;

                if (inputChannels.HasValue)
                {
                    channelLimit = Math.Min(channelLimit, inputChannels.Value);
                }

                // If we don't have any media info then limit it to 5 to prevent encoding errors due to asking for too many channels
                return Math.Min(request.MaxAudioChannels.Value, channelLimit);
            }

            return request.AudioChannels;
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Gets the number of audio channels to specify on the command line
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="audioStream">The audio stream.</param>
        /// <param name="outputAudioCodec">The output audio codec.</param>
        /// <returns>System.Nullable{System.Int32}.</returns>
        private int? GetNumAudioChannelsParam(StreamRequest request, MediaStream audioStream, string outputAudioCodec)
        {
            if (audioStream != null)
            {
                var codec = outputAudioCodec ?? string.Empty;

                if (audioStream.Channels > 2 && codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    // wmav2 currently only supports two channel output
                    return 2;
                }
            }

            if (request.MaxAudioChannels.HasValue)
            {
                if (audioStream != null && audioStream.Channels.HasValue)
                {
                    return Math.Min(request.MaxAudioChannels.Value, audioStream.Channels.Value);
                }

                return request.MaxAudioChannels.Value;
            }

            return request.AudioChannels;
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Parses the parameters.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ParseParams(StreamRequest request)
        {
            var vals = request.Params.Split(';');

            var videoRequest = request as VideoStreamRequest;

            for (var i = 0; i < vals.Length; i++)
            {
                var val = vals[i];

                if (string.IsNullOrWhiteSpace(val))
                {
                    continue;
                }

                if (i == 0)
                {
                    request.DeviceProfileId = val;
                }
                else if (i == 1)
                {
                    request.DeviceId = val;
                }
                else if (i == 2)
                {
                    request.MediaSourceId = val;
                }
                else if (i == 3)
                {
                    request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                }
                else if (i == 4)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoCodec = val;
                    }
                }
                else if (i == 5)
                {
                    request.AudioCodec = val;
                }
                else if (i == 6)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.AudioStreamIndex = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 7)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.SubtitleStreamIndex = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 8)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoBitRate = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 9)
                {
                    request.AudioBitRate = int.Parse(val, UsCulture);
                }
                else if (i == 10)
                {
                    request.MaxAudioChannels = int.Parse(val, UsCulture);
                }
                else if (i == 11)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxFramerate = float.Parse(val, UsCulture);
                    }
                }
                else if (i == 12)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxWidth = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 13)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxHeight = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 14)
                {
                    request.StartTimeTicks = long.Parse(val, UsCulture);
                }
                else if (i == 15)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.Level = val;
                    }
                }
            }
        }
Ejemplo n.º 25
0
        private bool CanStreamCopyAudio(StreamRequest request, MediaStream audioStream)
        {
            // Source and target codecs must match
            if (string.IsNullOrEmpty(request.AudioCodec) || !string.Equals(request.AudioCodec, audioStream.Codec, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }

            // Video bitrate must fall within requested value
            if (request.AudioBitRate.HasValue)
            {
                if (!audioStream.BitRate.HasValue || audioStream.BitRate.Value > request.AudioBitRate.Value)
                {
                    return false;
                }
            }

            // Channels must fall within requested value
            var channels = request.AudioChannels ?? request.MaxAudioChannels;
            if (channels.HasValue)
            {
                if (!audioStream.Channels.HasValue || audioStream.Channels.Value > channels.Value)
                {
                    return false;
                }
            }

            // Sample rate must fall within requested value
            if (request.AudioSampleRate.HasValue)
            {
                if (!audioStream.SampleRate.HasValue || audioStream.SampleRate.Value > request.AudioSampleRate.Value)
                {
                    return false;
                }
            }

            return SupportsAutomaticVideoStreamCopy;
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>StreamState.</returns>
        protected async Task<StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
        {
            ParseDlnaHeaders(request);

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

            var url = Request.PathInfo;

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

            var state = new StreamState(LiveTvManager, Logger)
            {
                Request = request,
                RequestedUrl = url
            };

            if (!string.IsNullOrWhiteSpace(request.AudioCodec))
            {
                state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
                state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault();
            }

            var item = LibraryManager.GetItemById(request.Id);

            List<MediaStream> mediaStreams = null;

            state.ItemType = item.GetType().Name;

            if (item is ILiveTvRecording)
            {
                var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);

                state.VideoType = VideoType.VideoFile;
                state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);

                var path = recording.RecordingInfo.Path;
                var mediaUrl = recording.RecordingInfo.Url;

                var source = string.IsNullOrEmpty(request.MediaSourceId)
                    ? recording.GetMediaSources(false).First()
                    : recording.GetMediaSources(false).First(i => string.Equals(i.Id, request.MediaSourceId));

                mediaStreams = source.MediaStreams;

                // Just to prevent this from being null and causing other methods to fail
                state.MediaPath = string.Empty;

                if (!string.IsNullOrEmpty(path))
                {
                    state.MediaPath = path;
                    state.InputProtocol = MediaProtocol.File;
                }
                else if (!string.IsNullOrEmpty(mediaUrl))
                {
                    state.MediaPath = mediaUrl;
                    state.InputProtocol = MediaProtocol.Http;
                }
                else
                {
                    // No media info, so this is probably needed
                    state.DeInterlace = true;
                }

                if (recording.RecordingInfo.Status == RecordingStatus.InProgress)
                {
                    state.ReadInputAtNativeFramerate = true;
                }

                state.RunTimeTicks = recording.RunTimeTicks;

                state.OutputAudioSync = "1000";
                state.InputVideoSync = "-1";
                state.InputAudioSync = "1";
                state.InputContainer = recording.Container;
            }
            else if (item is LiveTvChannel)
            {
                var channel = LiveTvManager.GetInternalChannel(request.Id);

                state.VideoType = VideoType.VideoFile;
                state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
                mediaStreams = new List<MediaStream>();

                state.ReadInputAtNativeFramerate = true;
                state.OutputAudioSync = "1000";
                state.DeInterlace = true;
                state.InputVideoSync = "-1";
                state.InputAudioSync = "1";

                // Just to prevent this from being null and causing other methods to fail
                state.MediaPath = string.Empty;
            }
            else if (item is IChannelMediaItem)
            {
                var mediaSource = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
                state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
                state.InputProtocol = mediaSource.Protocol;
                state.MediaPath = mediaSource.Path;
                state.RunTimeTicks = item.RunTimeTicks;
                state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
                mediaStreams = mediaSource.MediaStreams;
            }
            else
            {
                var hasMediaSources = (IHasMediaSources)item;
                var mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
                    ? hasMediaSources.GetMediaSources(false).First()
                    : hasMediaSources.GetMediaSources(false).First(i => string.Equals(i.Id, request.MediaSourceId));

                mediaStreams = mediaSource.MediaStreams;

                state.MediaPath = mediaSource.Path;
                state.InputProtocol = mediaSource.Protocol;
                state.InputContainer = mediaSource.Container;

                if (item is Video)
                {
                    state.IsInputVideo = true;

                    if (mediaSource.VideoType.HasValue)
                    {
                        state.VideoType = mediaSource.VideoType.Value;
                    }

                    state.IsoType = mediaSource.IsoType;

                    state.PlayableStreamFileNames = mediaSource.PlayableStreamFileNames.ToList();

                    if (mediaSource.Timestamp.HasValue)
                    {
                        state.InputTimestamp = mediaSource.Timestamp.Value;
                    }
                }

                state.RunTimeTicks = mediaSource.RunTimeTicks;
            }

            // If it's a wtv and we don't have media info, we will probably need to deinterlace
            if (string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) &&
                mediaStreams.Count == 0)
            {
                state.DeInterlace = true;
            }

            if (state.InputProtocol == MediaProtocol.Rtmp)
            {
                state.ReadInputAtNativeFramerate = true;
            }

            var videoRequest = request as VideoStreamRequest;

            AttachMediaStreamInfo(state, mediaStreams, videoRequest, url);

            state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 7;
            state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;

            var container = Path.GetExtension(state.RequestedUrl);

            if (string.IsNullOrEmpty(container))
            {
                container = request.Static ? state.InputContainer : Path.GetExtension(GetOutputFilePath(state));
            }

            state.OutputContainer = (container ?? string.Empty).TrimStart('.');

            state.OutputAudioBitrate = GetAudioBitrateParam(state.Request, state.AudioStream);
            state.OutputAudioSampleRate = request.AudioSampleRate;

            state.OutputAudioCodec = GetAudioCodec(state.Request);

            state.OutputAudioChannels = GetNumAudioChannelsParam(state.Request, state.AudioStream, state.OutputAudioCodec);

            if (videoRequest != null)
            {
                state.OutputVideoCodec = GetVideoCodec(videoRequest);
                state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream);
            }

            ApplyDeviceProfileSettings(state);

            if (videoRequest != null)
            {
                if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream))
                {
                    state.OutputVideoCodec = "copy";
                }

                if (state.AudioStream != null && CanStreamCopyAudio(request, state.AudioStream, state.SupportedAudioCodecs))
                {
                    state.OutputAudioCodec = "copy";
                }
            }

            state.OutputFilePath = GetOutputFilePath(state);

            return state;
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Parses the parameters.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ParseParams(StreamRequest request)
        {
            var vals = request.Params.Split(';');

            var videoRequest = request as VideoStreamRequest;

            for (var i = 0; i < vals.Length; i++)
            {
                var val = vals[i];

                if (string.IsNullOrWhiteSpace(val))
                {
                    continue;
                }

                if (i == 0)
                {
                    request.DeviceProfileId = val;
                }
                else if (i == 1)
                {
                    request.DeviceId = val;
                }
                else if (i == 2)
                {
                    request.MediaSourceId = val;
                }
                else if (i == 3)
                {
                    request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                }
                else if (i == 4)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoCodec = val;
                    }
                }
                else if (i == 5)
                {
                    request.AudioCodec = val;
                }
                else if (i == 6)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 7)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 8)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoBitRate = int.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 9)
                {
                    request.AudioBitRate = int.Parse(val, CultureInfo.InvariantCulture);
                }
                else if (i == 10)
                {
                    request.MaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
                }
                else if (i == 11)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxFramerate = float.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 12)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxWidth = int.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 13)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxHeight = int.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 14)
                {
                    request.StartTimeTicks = long.Parse(val, CultureInfo.InvariantCulture);
                }
                else if (i == 15)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.Level = val;
                    }
                }
                else if (i == 16)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxRefFrames = int.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 17)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.MaxVideoBitDepth = int.Parse(val, CultureInfo.InvariantCulture);
                    }
                }
                else if (i == 18)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.Profile = val;
                    }
                }
                else if (i == 19)
                {
                    // cabac no longer used
                }
                else if (i == 20)
                {
                    request.PlaySessionId = val;
                }
                else if (i == 21)
                {
                    // api_key
                }
                else if (i == 22)
                {
                    request.LiveStreamId = val;
                }
                else if (i == 23)
                {
                    // Duplicating ItemId because of MediaMonkey
                }
                else if (i == 24)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
                else if (i == 25)
                {
                    if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
                    {
                        if (Enum.TryParse(val, out SubtitleDeliveryMethod method))
                        {
                            videoRequest.SubtitleMethod = method;
                        }
                    }
                }
                else if (i == 26)
                {
                    request.TranscodingMaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
                }
                else if (i == 27)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.EnableSubtitlesInManifest = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
                else if (i == 28)
                {
                    request.Tag = val;
                }
                else if (i == 29)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.RequireAvc = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
                else if (i == 30)
                {
                    request.SubtitleCodec = val;
                }
                else if (i == 31)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.RequireNonAnamorphic = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
                else if (i == 32)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                    }
                }
                else if (i == 33)
                {
                    request.TranscodeReasons = val;
                }
            }
        }
Ejemplo n.º 28
0
        private bool CanStreamCopyAudio(StreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
        {
            // Source and target codecs must match
            if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase))
            {
                return false;
            }

            // Video bitrate must fall within requested value
            if (request.AudioBitRate.HasValue)
            {
                if (!audioStream.BitRate.HasValue || audioStream.BitRate.Value <= 0)
                {
                    return false;
                }
                if (audioStream.BitRate.Value > request.AudioBitRate.Value)
                {
                    return false;
                }
            }

            // Channels must fall within requested value
            var channels = request.AudioChannels ?? request.MaxAudioChannels;
            if (channels.HasValue)
            {
                if (!audioStream.Channels.HasValue || audioStream.Channels.Value <= 0)
                {
                    return false;
                }
                if (audioStream.Channels.Value > channels.Value)
                {
                    return false;
                }
            }

            // Sample rate must fall within requested value
            if (request.AudioSampleRate.HasValue)
            {
                if (!audioStream.SampleRate.HasValue || audioStream.SampleRate.Value <= 0)
                {
                    return false;
                }
                if (audioStream.SampleRate.Value > request.AudioSampleRate.Value)
                {
                    return false;
                }
            }

            return true;
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Parses the parameters.
        /// </summary>
        /// <param name="request">The request.</param>
        private void ParseParams(StreamRequest request)
        {
            var vals = request.Params.Split(';');

            var videoRequest = request as VideoStreamRequest;

            for (var i = 0; i < vals.Length; i++)
            {
                var val = vals[i];

                if (string.IsNullOrWhiteSpace(val))
                {
                    continue;
                }

                if (i == 0)
                {
                    request.DeviceId = val;
                }
                else if (i == 1)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoCodec = (VideoCodecs)Enum.Parse(typeof(VideoCodecs), val, true);
                    }
                }
                else if (i == 2)
                {
                    request.AudioCodec = (AudioCodecs)Enum.Parse(typeof(AudioCodecs), val, true);
                }
                else if (i == 3)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.AudioStreamIndex = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 4)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.SubtitleStreamIndex = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 5)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.VideoBitRate = int.Parse(val, UsCulture);
                    }
                }
                else if (i == 6)
                {
                    request.AudioBitRate = int.Parse(val, UsCulture);
                }
                else if (i == 7)
                {
                    request.AudioChannels = int.Parse(val, UsCulture);
                }
                else if (i == 8)
                {
                    if (videoRequest != null)
                    {
                        request.StartTimeTicks = long.Parse(val, UsCulture);
                    }
                }
                else if (i == 9)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.Profile = val;
                    }
                }
                else if (i == 10)
                {
                    if (videoRequest != null)
                    {
                        videoRequest.Level = val;
                    }
                }
            }
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Gets the name of the output audio codec
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>System.String.</returns>
        private string GetAudioCodec(StreamRequest request)
        {
            var codec = request.AudioCodec;

            if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
            {
                return "aac -strict experimental";
            }
            if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
            {
                return "libmp3lame";
            }
            if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase))
            {
                return "libvorbis";
            }
            if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase))
            {
                return "wmav2";
            }

            return codec.ToLower();
        }
Ejemplo n.º 31
0
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>StreamState.</returns>
        protected async Task<StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
        {
            ParseDlnaHeaders(request);

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

            var user = AuthorizationRequestFilterAttribute.GetCurrentUser(Request, UserManager);

            var url = Request.PathInfo;

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

            var state = new StreamState(LiveTvManager, Logger)
            {
                Request = request,
                RequestedUrl = url
            };

            var item = string.IsNullOrEmpty(request.MediaSourceId) ?
                DtoService.GetItemByDtoId(request.Id) :
                DtoService.GetItemByDtoId(request.MediaSourceId);

            if (user != null && item.GetPlayAccess(user) != PlayAccess.Full)
            {
                throw new ArgumentException(string.Format("{0} is not allowed to play media.", user.Name));
            }

            if (item is ILiveTvRecording)
            {
                var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);

                state.VideoType = VideoType.VideoFile;
                state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
                state.PlayableStreamFileNames = new List<string>();

                var path = recording.RecordingInfo.Path;
                var mediaUrl = recording.RecordingInfo.Url;

                if (string.IsNullOrWhiteSpace(path) && string.IsNullOrWhiteSpace(mediaUrl))
                {
                    var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false);

                    state.LiveTvStreamId = streamInfo.Id;

                    path = streamInfo.Path;
                    mediaUrl = streamInfo.Url;
                }

                if (!string.IsNullOrEmpty(path))
                {
                    state.MediaPath = path;
                    state.IsRemote = false;
                }
                else if (!string.IsNullOrEmpty(mediaUrl))
                {
                    state.MediaPath = mediaUrl;
                    state.IsRemote = true;
                }

                state.RunTimeTicks = recording.RunTimeTicks;

                if (recording.RecordingInfo.Status == RecordingStatus.InProgress)
                {
                    await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
                }

                state.ReadInputAtNativeFramerate = recording.RecordingInfo.Status == RecordingStatus.InProgress;
                state.AudioSync = "1000";
                state.DeInterlace = true;
                state.InputVideoSync = "-1";
                state.InputAudioSync = "1";
            }
            else if (item is LiveTvChannel)
            {
                var channel = LiveTvManager.GetInternalChannel(request.Id);

                state.VideoType = VideoType.VideoFile;
                state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
                state.PlayableStreamFileNames = new List<string>();

                var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false);

                state.LiveTvStreamId = streamInfo.Id;

                if (!string.IsNullOrEmpty(streamInfo.Path))
                {
                    state.MediaPath = streamInfo.Path;
                    state.IsRemote = false;

                    await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
                }
                else if (!string.IsNullOrEmpty(streamInfo.Url))
                {
                    state.MediaPath = streamInfo.Url;
                    state.IsRemote = true;
                }

                state.ReadInputAtNativeFramerate = true;
                state.AudioSync = "1000";
                state.DeInterlace = true;
                state.InputVideoSync = "-1";
                state.InputAudioSync = "1";
            }
            else
            {
                state.MediaPath = item.Path;
                state.IsRemote = item.LocationType == LocationType.Remote;

                var video = item as Video;

                if (video != null)
                {
                    state.IsInputVideo = true;
                    state.VideoType = video.VideoType;
                    state.IsoType = video.IsoType;

                    state.PlayableStreamFileNames = video.PlayableStreamFileNames == null
                        ? new List<string>()
                        : video.PlayableStreamFileNames.ToList();
                }

                state.RunTimeTicks = item.RunTimeTicks;
            }

            var videoRequest = request as VideoStreamRequest;

            var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery
            {
                ItemId = item.Id

            }).ToList();

            if (videoRequest != null)
            {
                if (string.IsNullOrEmpty(videoRequest.VideoCodec))
                {
                    videoRequest.VideoCodec = InferVideoCodec(url);
                }

                state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
                state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
                state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);

                if (state.VideoStream != null && state.VideoStream.IsInterlaced)
                {
                    state.DeInterlace = true;
                }

                EnforceResolutionLimit(state, videoRequest);
            }
            else
            {
                state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
            }

            state.HasMediaStreams = mediaStreams.Count > 0;

            state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
            state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;

            ApplyDeviceProfileSettings(state);

            if (videoRequest != null && state.VideoStream != null)
            {
                if (CanStreamCopyVideo(videoRequest, state.VideoStream, state.VideoType))
                {
                    videoRequest.VideoCodec = "copy";
                }
            }

            if (state.AudioStream != null)
            {
                //if (CanStreamCopyAudio(request, state.AudioStream))
                //{
                //    request.AudioCodec = "copy";
                //}
            }

            return state;
        }