internal static async Task<PlaylistItem> ToPlaylistItem(this BaseItemDto item, IApiClient apiClient, IPlaybackManager playbackManager)
        {
            var profile = VideoProfileHelper.GetWindowsPhoneProfile();
            var options = new AudioOptions
            {
                Profile = profile,
                ItemId = item.Id,
                DeviceId = apiClient.DeviceId,
                MediaSources = item.MediaSources
            };

            //var streamInfo = await playbackManager.GetAudioStreamInfo(App.ServerInfo.Id, options, true, apiClient);
            var streamBuilder = new StreamBuilder(new MBLogger());
            var streamInfo = streamBuilder.BuildAudioItem(options);

            var streamUrl = streamInfo.ToUrl(apiClient.GetApiUrl("/"), apiClient.AccessToken);

            return new PlaylistItem
            {
                Album = item.Album,
                Artist = item.AlbumArtist,
                TrackName = item.Name,
                TrackUrl = streamUrl.Replace(App.ServerInfo.LocalAddress, !string.IsNullOrEmpty(App.ServerInfo.ManualAddress) ? App.ServerInfo.ManualAddress : App.ServerInfo.RemoteAddress),
                MediaBrowserId = item.Id,
                IsJustAdded = true,
                ImageUrl = (string) ImageConverter.Convert(item, typeof (string), null, null),
                BackgroundImageUrl = (string) ImageConverter.Convert(item, typeof (string), "backdrop", null),
                RunTimeTicks = item.RunTimeTicks ?? 0
            };
        }
        private static string GetStreamedPath(BaseItemDto item, IApiClient apiClient, long? startTimeTicks, int? maxBitrate)
        {
            var profile = new MediaBrowserTheaterProfile();

            StreamInfo info;

            if (item.IsAudio)
            {
                var options = new AudioOptions
                {
                    Context = EncodingContext.Streaming,
                    DeviceId = apiClient.DeviceId,
                    ItemId = item.Id,

                    // TODO: Reduce to 2 is user only has stereo speakers
                    MaxAudioChannels = 6,

                    MaxBitrate = maxBitrate,
                    MediaSources = item.MediaSources,

                    Profile = profile
                };

                info = new StreamBuilder().BuildAudioItem(options);
                info.StartPositionTicks = startTimeTicks ?? 0;

                return info.ToUrl(apiClient.ServerAddress + "/mediabrowser");
            }
            else
            {
                var options = new VideoOptions
                {
                    Context = EncodingContext.Streaming,
                    DeviceId = apiClient.DeviceId,
                    ItemId = item.Id,

                    // TODO: Reduce to 2 is user only has stereo speakers
                    MaxAudioChannels = 6,

                    MaxBitrate = maxBitrate,
                    MediaSources = item.MediaSources,

                    Profile = profile
                };

                info = new StreamBuilder().BuildVideoItem(options);
                info.StartPositionTicks = startTimeTicks ?? 0;

                return info.ToUrl(apiClient.ServerAddress + "/mediabrowser") + "&EnableAdaptiveBitrateStreaming=false";
            }
        }
Example #3
0
        public async Task Run(Video item, CancellationToken cancellationToken)
        {
            var mediaSources = ((IHasMediaSources)item).GetMediaSources(false)
                .ToList();

            var modifier = GetItemModifier(item);

            var audioMode = Plugin.Instance.Configuration.AudioOutputMode;
            var profile = new RokuDeviceProfile(audioMode >= AudioOutputMode.DDPlus, audioMode >= AudioOutputMode.DTS);

            foreach (var mediaSource in mediaSources)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var streamInfo = new StreamBuilder(_logger).BuildVideoItem(new VideoOptions
                {
                    Context = EncodingContext.Streaming,
                    ItemId = item.Id.ToString("N"),
                    MediaSources = new List<MediaSourceInfo> { mediaSource },
                    Profile = profile,
                    MaxBitrate = Plugin.Instance.Configuration.MaxBitrate,
                    DeviceId = Guid.NewGuid().ToString("N"),
                    AudioStreamIndex = mediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Index).FirstOrDefault(),
                    MediaSourceId = mediaSource.Id
                });

                if (!streamInfo.IsDirectStream)
                {
                    continue;
                }

                if (Plugin.Instance.Configuration.EnableHdThumbnails)
                {
                    await Run(item, modifier, mediaSource, 320, cancellationToken).ConfigureAwait(false);
                }
                if (Plugin.Instance.Configuration.EnableSdThumbnails)
                {
                    await Run(item, modifier, mediaSource, 240, cancellationToken).ConfigureAwait(false);
                }
            }
        }
Example #4
0
        private void AddAudioResource(DlnaOptions options, XmlElement container, IHasMediaSources audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
        {
            var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);

            if (streamInfo == null)
            {
                var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();

                streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
               {
                   ItemId = GetClientId(audio),
                   MediaSources = sources,
                   Profile = _profile,
                   DeviceId = deviceId
               });
            }

            var url = streamInfo.ToDlnaUrl(_serverAddress, _accessToken);

            res.InnerText = url;

            var mediaSource = streamInfo.MediaSource;

            if (mediaSource.RunTimeTicks.HasValue)
            {
                res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
            }

            if (filter.Contains("res@size"))
            {
                if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength)
                {
                    var size = streamInfo.TargetSize;

                    if (size.HasValue)
                    {
                        res.SetAttribute("size", size.Value.ToString(_usCulture));
                    }
                }
            }

            var targetAudioBitrate = streamInfo.TargetAudioBitrate;
            var targetSampleRate = streamInfo.TargetAudioSampleRate;
            var targetChannels = streamInfo.TargetAudioChannels;

            if (targetChannels.HasValue)
            {
                res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
            }

            if (targetSampleRate.HasValue)
            {
                res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
            }

            if (targetAudioBitrate.HasValue)
            {
                res.SetAttribute("bitrate", targetAudioBitrate.Value.ToString(_usCulture));
            }

            var mediaProfile = _profile.GetAudioMediaProfile(streamInfo.Container,
                streamInfo.AudioCodec,
                targetChannels,
                targetAudioBitrate);

            var filename = url.Substring(0, url.IndexOf('?'));

            var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
                ? MimeTypes.GetMimeType(filename)
                : mediaProfile.MimeType;

            var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container,
                streamInfo.TargetAudioCodec,
                targetAudioBitrate,
                targetSampleRate,
                targetChannels,
                streamInfo.IsDirectStream,
                streamInfo.RunTimeTicks,
                streamInfo.TranscodeSeekInfo);

            res.SetAttribute("protocolInfo", String.Format(
                "http-get:*:{0}:{1}",
                mimeType,
                contentFeatures
                ));

            container.AppendChild(res);
        }
Example #5
0
        private void AddVideoResource(DlnaOptions options, XmlElement container, IHasMediaSources video, string deviceId, Filter filter, StreamInfo streamInfo = null)
        {
            if (streamInfo == null)
            {
                var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();

                streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
                {
                    ItemId = GetClientId(video),
                    MediaSources = sources,
                    Profile = _profile,
                    DeviceId = deviceId,
                    MaxBitrate = _profile.MaxStreamingBitrate
                });
            }

            var targetWidth = streamInfo.TargetWidth;
            var targetHeight = streamInfo.TargetHeight;

            var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container,
                streamInfo.VideoCodec,
                streamInfo.AudioCodec,
                targetWidth,
                targetHeight,
                streamInfo.TargetVideoBitDepth,
                streamInfo.TargetVideoBitrate,
                streamInfo.TargetTimestamp,
                streamInfo.IsDirectStream,
                streamInfo.RunTimeTicks,
                streamInfo.TargetVideoProfile,
                streamInfo.TargetVideoLevel,
                streamInfo.TargetFramerate,
                streamInfo.TargetPacketLength,
                streamInfo.TranscodeSeekInfo,
                streamInfo.IsTargetAnamorphic,
                streamInfo.TargetRefFrames,
                streamInfo.TargetVideoStreamCount,
                streamInfo.TargetAudioStreamCount,
                streamInfo.TargetVideoCodecTag);

            foreach (var contentFeature in contentFeatureList)
            {
                AddVideoResource(container, video, deviceId, filter, contentFeature, streamInfo);
            }

            foreach (var subtitle in streamInfo.GetSubtitleProfiles(false, _serverAddress, _accessToken))
            {
                if (subtitle.DeliveryMethod == SubtitleDeliveryMethod.External)
                {
                    var subtitleAdded = AddSubtitleElement(container, subtitle);

                    if (subtitleAdded && _profile.EnableSingleSubtitleLimit)
                    {
                        break;
                    }
                }
            }
        }
Example #6
0
        private async Task Sync(SyncJobItem jobItem, Audio item, DeviceProfile profile, CancellationToken cancellationToken)
        {
            var options = new AudioOptions
            {
                Context = EncodingContext.Static,
                ItemId = item.Id.ToString("N"),
                DeviceId = jobItem.TargetId,
                Profile = profile,
                MediaSources = item.GetMediaSources(false).ToList()
            };

            var streamInfo = new StreamBuilder().BuildAudioItem(options);
            var mediaSource = streamInfo.MediaSource;

            jobItem.MediaSourceId = streamInfo.MediaSourceId;

            if (streamInfo.PlayMethod == PlayMethod.Transcode)
            {
                jobItem.Status = SyncJobItemStatus.Converting;
                await _syncRepo.Update(jobItem).ConfigureAwait(false);
                
                jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, profile), new Progress<double>(), cancellationToken);
            }
            else
            {
                if (mediaSource.Protocol == MediaProtocol.File)
                {
                    jobItem.OutputPath = mediaSource.Path;
                }
                else if (mediaSource.Protocol == MediaProtocol.Http)
                {
                    jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
                }
            }

            jobItem.Progress = 50;
            jobItem.Status = SyncJobItemStatus.Transferring;
            await _syncRepo.Update(jobItem).ConfigureAwait(false);
        }
Example #7
0
        private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter, StreamInfo streamInfo = null)
        {
            if (streamInfo == null)
            {
                var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList();

               streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
               {
                   ItemId = video.Id.ToString("N"),
                   MediaSources = sources,
                   Profile = _profile,
                   DeviceId = deviceId,
                   MaxBitrate = _profile.MaxStreamingBitrate
               });
            }

            var targetWidth = streamInfo.TargetWidth;
            var targetHeight = streamInfo.TargetHeight;

            var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container,
                streamInfo.VideoCodec,
                streamInfo.AudioCodec,
                targetWidth,
                targetHeight,
                streamInfo.TargetVideoBitDepth,
                streamInfo.TargetVideoBitrate,
                streamInfo.TargetAudioChannels,
                streamInfo.TargetAudioBitrate,
                streamInfo.TargetTimestamp,
                streamInfo.IsDirectStream,
                streamInfo.RunTimeTicks,
                streamInfo.TargetVideoProfile,
                streamInfo.TargetVideoLevel,
                streamInfo.TargetFramerate,
                streamInfo.TargetPacketLength,
                streamInfo.TranscodeSeekInfo,
                streamInfo.IsTargetAnamorphic);

            foreach (var contentFeature in contentFeatureList)
            {
                AddVideoResource(container, video, deviceId, filter, contentFeature, streamInfo);
            }

            foreach (var subtitle in streamInfo.GetExternalSubtitles(_serverAddress))
            {
                AddSubtitleElement(container, subtitle);
            }
        }
        private StreamInfo CreateVideoStream(string itemId, long startTimeTicks, List<MediaSourceInfo> mediaSources = null, bool useHls = false)
        {
            var profile = VideoProfileHelper.GetWindowsPhoneProfile(useHls);

            var streamingSettings = NavigationService.IsOnWifi
                ? App.SpecificSettings.WifiStreamingQuality.GetSettings()
                : App.SpecificSettings.StreamingQuality.GetSettings();

            var options = new VideoOptions
            {
                Profile = profile, 
                ItemId = itemId, 
                DeviceId = ApiClient.DeviceId, 
                MaxBitrate = streamingSettings.VideoBitrate,
                MediaSources = mediaSources
            };

            var builder = new StreamBuilder();
            var streamInfo = builder.BuildVideoItem(options);
            streamInfo.StartPositionTicks = startTimeTicks;

            return streamInfo;
        }
        private static PlayableItem GetStreamedItem(BaseItemDto item, List<MediaSourceInfo> mediaSources, IApiClient apiClient, long? startTimeTicks, int? maxBitrate)
        {
            var profile = new MediaBrowserTheaterProfile();

            StreamInfo info;

            if (item.IsAudio)
            {
                var options = new AudioOptions
                {
                    Context = EncodingContext.Streaming,
                    DeviceId = apiClient.DeviceId,
                    ItemId = item.Id,

                    // TODO: Reduce to 2 is user only has stereo speakers
                    MaxAudioChannels = 6,

                    MaxBitrate = maxBitrate,
                    MediaSources = mediaSources,

                    Profile = profile
                };

                info = new StreamBuilder().BuildAudioItem(options);
                info.StartPositionTicks = startTimeTicks ?? 0;

                if (info.MediaSource.Protocol == MediaProtocol.File && File.Exists(info.MediaSource.Path))
                {
                    return new PlayableItem
                    {
                        OriginalItem = item,
                        PlayablePath = info.MediaSource.Path,
                        MediaSource = info.MediaSource,
                        StreamInfo = info
                    };
                }

                return new PlayableItem
                {
                    OriginalItem = item,
                    PlayablePath = info.ToUrl(apiClient.ServerAddress + "/mediabrowser"),
                    MediaSource = info.MediaSource,
                    StreamInfo = info
                };
            }
            else
            {
                var options = new VideoOptions
                {
                    Context = EncodingContext.Streaming,
                    DeviceId = apiClient.DeviceId,
                    ItemId = item.Id,

                    // TODO: Reduce to 2 is user only has stereo speakers
                    MaxAudioChannels = 6,

                    MaxBitrate = maxBitrate,
                    MediaSources = mediaSources,

                    Profile = profile
                };

                info = new StreamBuilder().BuildVideoItem(options);
                info.StartPositionTicks = startTimeTicks ?? 0;

                if (info.MediaSource.Protocol == MediaProtocol.File && File.Exists(info.MediaSource.Path))
                {
                    return new PlayableItem
                    {
                        OriginalItem = item,
                        PlayablePath = info.MediaSource.Path,
                        MediaSource = info.MediaSource,
                        StreamInfo = info
                    };
                }

                //info.Container = "ts";
                //info.VideoCodec = "copy";
                //info.AudioCodec = "copy";
                //info.Protocol = "http";

                //if (item.IsType("tvchannel"))
                //{
                //    info.VideoCodec = "copy";
                //}

                var playable = new PlayableItem
                {
                    OriginalItem = item,
                    PlayablePath = info.ToUrl(apiClient.ServerAddress + "/mediabrowser"),
                    MediaSource = info.MediaSource,
                    StreamInfo = info
                };

                if (!info.IsDirectStream)
                {
                    playable.PlayablePath += "&EnableAdaptiveBitrateStreaming=false";
                }

                return playable;
            }
        }
Example #10
0
        private async Task Sync(SyncJobItem jobItem, SyncJob job, Audio item, User user, bool enableConversion, SyncOptions syncOptions, IProgress<double> progress, CancellationToken cancellationToken)
        {
            var jobOptions = _syncManager.GetAudioOptions(jobItem, job);
            var conversionOptions = new AudioOptions
            {
                Profile = jobOptions.DeviceProfile
            };

            conversionOptions.DeviceId = jobItem.TargetId;
            conversionOptions.Context = EncodingContext.Static;
            conversionOptions.ItemId = item.Id.ToString("N");
            conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList();

            var streamInfo = new StreamBuilder(_logger).BuildAudioItem(conversionOptions);
            var mediaSource = streamInfo.MediaSource;

            jobItem.MediaSourceId = streamInfo.MediaSourceId;
            jobItem.TemporaryPath = GetTemporaryPath(jobItem);

            if (streamInfo.PlayMethod == PlayMethod.Transcode && jobOptions.IsConverting)
            {
                if (!enableConversion)
                {
                    return;
                }

                jobItem.Status = SyncJobItemStatus.Converting;
                await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
                await UpdateJobStatus(job).ConfigureAwait(false);

                try
                {
                    var lastJobUpdate = DateTime.MinValue;
                    var innerProgress = new ActionableProgress<double>();
                    innerProgress.RegisterAction(async pct =>
                    {
                        progress.Report(pct);

                        if ((DateTime.UtcNow - lastJobUpdate).TotalSeconds >= DatabaseProgressUpdateIntervalSeconds)
                        {
                            jobItem.Progress = pct / 2;
                            await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
                            await UpdateJobStatus(job).ConfigureAwait(false);
                        }
                    });

                    jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, conversionOptions.Profile)
                    {
                        OutputDirectory = jobItem.TemporaryPath,
                        CpuCoreLimit = syncOptions.TranscodingCpuCoreLimit

                    }, innerProgress, cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    jobItem.Status = SyncJobItemStatus.Queued;
                    jobItem.Progress = 0;
                }
                catch (Exception ex)
                {
                    jobItem.Status = SyncJobItemStatus.Failed;
                    _logger.ErrorException("Error during sync transcoding", ex);
                }

                if (jobItem.Status == SyncJobItemStatus.Failed || jobItem.Status == SyncJobItemStatus.Queued)
                {
                    await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
                    return;
                }

                jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, false).ConfigureAwait(false);
            }
            else
            {
                if (mediaSource.Protocol == MediaProtocol.File)
                {
                    jobItem.OutputPath = mediaSource.Path;
                }
                else if (mediaSource.Protocol == MediaProtocol.Http)
                {
                    jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
                }

                jobItem.MediaSource = mediaSource;
            }

            jobItem.MediaSource.SupportsTranscoding = false;

            jobItem.Progress = 50;
            jobItem.Status = SyncJobItemStatus.ReadyToTransfer;
            await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
        }
Example #11
0
        private async Task Sync(SyncJobItem jobItem, SyncJob job, Video item, User user, bool enableConversion, SyncOptions syncOptions, IProgress<double> progress, CancellationToken cancellationToken)
        {
            var jobOptions = _syncManager.GetVideoOptions(jobItem, job);
            var conversionOptions = new VideoOptions
            {
                Profile = jobOptions.DeviceProfile
            };

            conversionOptions.DeviceId = jobItem.TargetId;
            conversionOptions.Context = EncodingContext.Static;
            conversionOptions.ItemId = item.Id.ToString("N");
            conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList();

            var streamInfo = new StreamBuilder(_logger).BuildVideoItem(conversionOptions);
            var mediaSource = streamInfo.MediaSource;

            // No sense creating external subs if we're already burning one into the video
            var externalSubs = streamInfo.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode ?
                new List<SubtitleStreamInfo>() :
                streamInfo.GetExternalSubtitles(false, true, null, null);

            // Mark as requiring conversion if transcoding the video, or if any subtitles need to be extracted
            var requiresVideoTranscoding = streamInfo.PlayMethod == PlayMethod.Transcode && jobOptions.IsConverting;
            var requiresConversion = requiresVideoTranscoding || externalSubs.Any(i => RequiresExtraction(i, mediaSource));

            if (requiresConversion && !enableConversion)
            {
                return;
            }

            jobItem.MediaSourceId = streamInfo.MediaSourceId;
            jobItem.TemporaryPath = GetTemporaryPath(jobItem);

            if (requiresConversion)
            {
                jobItem.Status = SyncJobItemStatus.Converting;
            }

            if (requiresVideoTranscoding)
            {
                // Save the job item now since conversion could take a while
                await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
                await UpdateJobStatus(job).ConfigureAwait(false);

                try
                {
                    var lastJobUpdate = DateTime.MinValue;
                    var innerProgress = new ActionableProgress<double>();
                    innerProgress.RegisterAction(async pct =>
                    {
                        progress.Report(pct);

                        if ((DateTime.UtcNow - lastJobUpdate).TotalSeconds >= DatabaseProgressUpdateIntervalSeconds)
                        {
                            jobItem.Progress = pct / 2;
                            await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
                            await UpdateJobStatus(job).ConfigureAwait(false);
                        }
                    });

                    jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, conversionOptions.Profile)
                    {
                        OutputDirectory = jobItem.TemporaryPath,
                        CpuCoreLimit = syncOptions.TranscodingCpuCoreLimit,
                        ReadInputAtNativeFramerate = !syncOptions.EnableFullSpeedTranscoding

                    }, innerProgress, cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    jobItem.Status = SyncJobItemStatus.Queued;
                    jobItem.Progress = 0;
                }
                catch (Exception ex)
                {
                    jobItem.Status = SyncJobItemStatus.Failed;
                    _logger.ErrorException("Error during sync transcoding", ex);
                }

                if (jobItem.Status == SyncJobItemStatus.Failed || jobItem.Status == SyncJobItemStatus.Queued)
                {
                    await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
                    return;
                }

                jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, true).ConfigureAwait(false);
            }
            else
            {
                if (mediaSource.Protocol == MediaProtocol.File)
                {
                    jobItem.OutputPath = mediaSource.Path;
                }
                else if (mediaSource.Protocol == MediaProtocol.Http)
                {
                    jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
                }

                jobItem.MediaSource = mediaSource;
            }

            jobItem.MediaSource.SupportsTranscoding = false;

            if (externalSubs.Count > 0)
            {
                // Save the job item now since conversion could take a while
                await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);

                await ConvertSubtitles(jobItem, externalSubs, streamInfo, cancellationToken).ConfigureAwait(false);
            }

            jobItem.Progress = 50;
            jobItem.Status = SyncJobItemStatus.ReadyToTransfer;
            await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
        }
Example #12
0
        private void AddAudioResource(XmlElement container, Audio audio, string deviceId, Filter filter)
        {
            var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);

            var sources = _dtoService.GetMediaSources(audio);

            var streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
            {
                ItemId = audio.Id.ToString("N"),
                MediaSources = sources,
                Profile = _profile,
                DeviceId = deviceId
            });

            var url = streamInfo.ToDlnaUrl(_serverAddress);
            res.InnerText = url;

            var mediaSource = sources.First(i => string.Equals(i.Id, streamInfo.MediaSourceId));

            if (mediaSource.RunTimeTicks.HasValue)
            {
                res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
            }

            if (filter.Contains("res@size"))
            {
                if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength)
                {
                    var size = streamInfo.TargetSize;

                    if (size.HasValue)
                    {
                        res.SetAttribute("size", size.Value.ToString(_usCulture));
                    }
                }
            }

            var targetAudioBitrate = streamInfo.TargetAudioBitrate;
            var targetSampleRate = streamInfo.TargetAudioSampleRate;
            var targetChannels = streamInfo.TargetAudioChannels;

            if (targetChannels.HasValue)
            {
                res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
            }

            if (targetSampleRate.HasValue)
            {
                res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
            }

            if (targetAudioBitrate.HasValue)
            {
                res.SetAttribute("bitrate", targetAudioBitrate.Value.ToString(_usCulture));
            }

            var formatProfile = new MediaFormatProfileResolver().ResolveAudioFormat(streamInfo.Container, targetAudioBitrate, targetSampleRate, targetChannels);

            var filename = url.Substring(0, url.IndexOf('?'));

            var orgOpValue = DlnaMaps.GetOrgOpValue(mediaSource.RunTimeTicks.HasValue, streamInfo.IsDirectStream, streamInfo.TranscodeSeekInfo);

            var orgCi = streamInfo.IsDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";

            res.SetAttribute("protocolInfo", String.Format(
                "http-get:*:{0}:DLNA.ORG_PN={1};DLNA.ORG_OP={2};DLNA.ORG_CI={3};DLNA.ORG_FLAGS={4}",
                MimeTypes.GetMimeType(filename),
                formatProfile,
                orgOpValue,
                orgCi,
                DlnaMaps.DefaultStreaming
                ));

            container.AppendChild(res);
        }
Example #13
0
        private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter)
        {
            var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);

            var sources = _dtoService.GetMediaSources(video);

            int? maxBitrateSetting = null;

            var streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
            {
                ItemId = video.Id.ToString("N"),
                MediaSources = sources,
                Profile = _profile,
                DeviceId = deviceId,
                MaxBitrate = maxBitrateSetting
            });

            var url = streamInfo.ToDlnaUrl(_serverAddress);
            res.InnerText = url;

            var mediaSource = sources.First(i => string.Equals(i.Id, streamInfo.MediaSourceId));

            if (mediaSource.RunTimeTicks.HasValue)
            {
                res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
            }

            if (filter.Contains("res@size"))
            {
                if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength)
                {
                    var size = streamInfo.TargetSize;

                    if (size.HasValue)
                    {
                        res.SetAttribute("size", size.Value.ToString(_usCulture));
                    }
                }
            }

            var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video && !string.Equals(i.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase));

            var targetAudioBitrate = streamInfo.TargetAudioBitrate;
            var targetSampleRate = streamInfo.TargetAudioSampleRate;
            var targetChannels = streamInfo.TargetAudioChannels;

            var targetWidth = streamInfo.MaxWidth ?? (videoStream == null ? null : videoStream.Width);
            var targetHeight = streamInfo.MaxHeight ?? (videoStream == null ? null : videoStream.Height);

            var targetVideoCodec = streamInfo.IsDirectStream
                ? (videoStream == null ? null : videoStream.Codec)
                : streamInfo.VideoCodec;

            var targetAudioCodec = streamInfo.TargetAudioCodec;

            var targetBitrate = maxBitrateSetting ?? mediaSource.Bitrate;

            if (targetChannels.HasValue)
            {
                res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
            }

            if (filter.Contains("res@resolution"))
            {
                if (targetWidth.HasValue && targetHeight.HasValue)
                {
                    res.SetAttribute("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value));
                }
            }

            if (targetSampleRate.HasValue)
            {
                res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
            }

            if (targetAudioBitrate.HasValue)
            {
                res.SetAttribute("bitrate", targetAudioBitrate.Value.ToString(_usCulture));
            }

            var formatProfile = new MediaFormatProfileResolver().ResolveVideoFormat(streamInfo.Container,
                targetVideoCodec,
                targetAudioCodec,
                targetWidth,
                targetHeight,
                targetBitrate,
                TransportStreamTimestamp.NONE);

            var filename = url.Substring(0, url.IndexOf('?'));

            var orgOpValue = DlnaMaps.GetOrgOpValue(mediaSource.RunTimeTicks.HasValue, streamInfo.IsDirectStream, streamInfo.TranscodeSeekInfo);

            var orgCi = streamInfo.IsDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";

            res.SetAttribute("protocolInfo", String.Format(
                "http-get:*:{0}:DLNA.ORG_PN={1};DLNA.ORG_OP={2};DLNA.ORG_CI={3};DLNA.ORG_FLAGS={4}",
                MimeTypes.GetMimeType(filename),
                formatProfile,
                orgOpValue,
                orgCi,
                DlnaMaps.DefaultStreaming
                ));

            container.AppendChild(res);
        }
Example #14
0
        private async Task<string> Sync(SyncJobItem jobItem, Audio item, DeviceProfile profile, CancellationToken cancellationToken)
        {
            var options = new AudioOptions
            {
                Context = EncodingContext.Streaming,
                ItemId = item.Id.ToString("N"),
                DeviceId = jobItem.TargetId,
                Profile = profile,
                MediaSources = item.GetMediaSources(false).ToList()
            };

            var streamInfo = new StreamBuilder().BuildAudioItem(options);
            var mediaSource = streamInfo.MediaSource;

            if (streamInfo.PlayMethod != PlayMethod.Transcode)
            {
                if (mediaSource.Protocol == MediaProtocol.File)
                {
                    return mediaSource.Path;
                }
                if (mediaSource.Protocol == MediaProtocol.Http)
                {
                    return await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
                }
                throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
            }

            // TODO: Transcode
            return mediaSource.Path;
        }