Exemplo n.º 1
0
        public static bool IsImageStreamChanged(ImageTranscoding image)
        {
            bool notChanged = true;

            notChanged &= (image.SourceOrientation == 0 || image.TargetAutoRotate == false);
            notChanged &= (image.SourceHeight == 0 || image.SourceHeight <= image.TargetHeight);
            notChanged &= (image.SourceWidth == 0 || image.SourceWidth <= image.TargetWidth);
            notChanged &= (image.TargetPixelFormat == PixelFormat.Unknown || image.SourcePixelFormat == image.TargetPixelFormat);
            notChanged &= (image.TargetImageCodec == ImageContainer.Unknown || image.SourceImageCodec == image.TargetImageCodec);

            return(notChanged == false);
        }
Exemplo n.º 2
0
        public async Task Initialize(MediaItem item, int?edition = null)
        {
            IsLive      = false;
            MediaItemId = item.MediaItemId;
            if (MediaItemAspect.TryGetAttribute(item.Aspects, MediaAspect.ATTR_TITLE, out string title))
            {
                MediaItemTitle = title;
            }
            else
            {
                MediaItemTitle = "?";
            }

            var info = await MediaAnalyzer.ParseMediaItemAsync(item, edition);

            if (info == null)
            {
                Logger.Warn("MediaServer: Mediaitem {0} couldn't be analyzed", item.MediaItemId);
                return;
            }

            if (item.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
            {
                IsAudio = true;
            }
            else if (item.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
            {
                IsImage = true;
            }
            else if (item.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
            {
                IsVideo = true;
            }
            else
            {
                Logger.Warn("MediaServer: Mediaitem {0} contains no required aspect information", item.MediaItemId);
                return;
            }

            if (item.HasEditions && !edition.HasValue)
            {
                //Find edition with best matching audio that doesn't require transcoding
                int  currentPriority            = -1;
                bool currentRequiresTranscoding = false;
                var  preferredAudioLang         = Client.PreferredAudioLanguages.ToList();
                foreach (var checkEdition in info.Metadata.Keys)
                {
                    for (int idx = 0; idx < info.Audio[checkEdition].Count; idx++)
                    {
                        VideoTranscoding video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Client.Profile.ID,
                                                                                             info, checkEdition, Client.PreferredAudioLanguages, IsLive, "");

                        bool requiresTranscoding = video != null;

                        for (int priority = 0; priority < preferredAudioLang.Count; priority++)
                        {
                            if (preferredAudioLang[priority].Equals(info.Audio[checkEdition][idx].Language, StringComparison.InvariantCultureIgnoreCase) == true)
                            {
                                if (currentPriority == -1 || priority < currentPriority || (!requiresTranscoding && currentRequiresTranscoding && priority == currentPriority))
                                {
                                    currentPriority            = priority;
                                    currentRequiresTranscoding = requiresTranscoding;
                                    edition = checkEdition;
                                }
                            }
                        }
                    }
                }
            }
            if (!edition.HasValue)
            {
                //Assign first edition
                _edition = info.Metadata.Min(m => m.Key);
            }
            else
            {
                _edition = edition.Value;
            }

            string transcodeId = item.MediaItemId.ToString() + "_" + Client.Profile.ID;

            if (MediaServerPlugin.Settings.TranscodingAllowed)
            {
                if (IsAudio)
                {
                    AudioTranscoding audio = TranscodeProfileManager.GetAudioTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Client.Profile.ID,
                                                                                         info, _edition, IsLive, transcodeId);
                    TranscodingParameter = audio;
                }
                else if (IsImage)
                {
                    ImageTranscoding image = TranscodeProfileManager.GetImageTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Client.Profile.ID,
                                                                                         info, _edition, transcodeId);
                    TranscodingParameter = image;
                }
                else if (IsVideo)
                {
                    VideoTranscoding video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Client.Profile.ID,
                                                                                         info, _edition, Client.PreferredAudioLanguages, IsLive, transcodeId);
                    if (video != null)
                    {
                        if (video.TargetVideoContainer == VideoContainer.Hls)
                        {
                            IsSegmented = true;
                        }
                        if (MediaServerPlugin.Settings.HardcodedSubtitlesAllowed == false)
                        {
                            video.TargetSubtitleSupport = SubtitleSupport.None;
                        }
                    }
                    TranscodingParameter = video;
                }
            }

            if (TranscodingParameter == null)
            {
                if (IsVideo)
                {
                    VideoTranscoding video = TranscodeProfileManager.GetVideoSubtitleTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Client.Profile.ID,
                                                                                                 info, _edition, IsLive, transcodeId);
                    if (video != null)
                    {
                        if (video.TargetVideoContainer == VideoContainer.Hls)
                        {
                            IsSegmented = true;
                        }
                        if (MediaServerPlugin.Settings.HardcodedSubtitlesAllowed == false)
                        {
                            video.TargetSubtitleSupport = SubtitleSupport.None;
                        }
                    }
                    SubtitleTranscodingParameter = video;
                }
            }

            //Assign some extra meta data
            DateTime?aspectDate;

            if (MediaItemAspect.TryGetAttribute(item.Aspects, ImporterAspect.ATTR_DATEADDED, out aspectDate))
            {
                MediaItemAddedDate = aspectDate;
            }
            if (MediaItemAspect.TryGetAttribute(item.Aspects, MediaAspect.ATTR_RECORDINGTIME, out aspectDate))
            {
                MediaItemRecordingDate = aspectDate;
            }

            if (IsVideo)
            {
                if (MediaItemAspect.TryGetAspects(item.Aspects, VideoStreamAspect.Metadata, out var videoStreamAspects))
                {
                    MediaItemWidth  = videoStreamAspects.FirstOrDefault()?.GetAttributeValue <int?>(VideoStreamAspect.ATTR_WIDTH);
                    MediaItemHeight = videoStreamAspects.FirstOrDefault()?.GetAttributeValue <int?>(VideoStreamAspect.ATTR_HEIGHT);
                }
            }
            else if (IsImage)
            {
                if (MediaItemAspect.TryGetAspect(item.Aspects, ImageAspect.Metadata, out var imageAspect))
                {
                    MediaItemImageMake        = imageAspect?.GetAttributeValue <string>(ImageAspect.ATTR_MAKE);
                    MediaItemImageMake        = imageAspect?.GetAttributeValue <string>(ImageAspect.ATTR_MODEL);
                    MediaItemImageMake        = imageAspect?.GetAttributeValue <string>(ImageAspect.ATTR_FNUMBER);
                    MediaItemImageMake        = imageAspect?.GetAttributeValue <string>(ImageAspect.ATTR_ISO_SPEED);
                    MediaItemImageMake        = imageAspect?.GetAttributeValue <string>(ImageAspect.ATTR_EXPOSURE_TIME);
                    MediaItemImageOrientation = imageAspect?.GetAttributeValue <int?>(ImageAspect.ATTR_ORIENTATION);
                    MediaItemWidth            = imageAspect?.GetAttributeValue <int?>(ImageAspect.ATTR_WIDTH);
                    MediaItemHeight           = imageAspect?.GetAttributeValue <int?>(ImageAspect.ATTR_HEIGHT);
                }
            }

            AssignDlnaMetadata(info, _edition);
        }
Exemplo n.º 3
0
        private void AssignDlnaMetadata(MetadataContainer info, int edition)
        {
            if (info == null)
            {
                return;
            }

            List <string> profileList = new List <string>();

            if (TranscodingParameter == null)
            {
                Metadata  = info.Metadata[edition];
                Video     = info.Video[edition];
                Audio     = info.Audio[edition];
                Image     = info.Image[edition];
                Subtitles = info.Subtitles[edition];
            }
            else
            {
                if (IsImage)
                {
                    ImageTranscoding        image    = (ImageTranscoding)TranscodingParameter;
                    TranscodedImageMetadata metadata = MediaConverter.GetTranscodedImageMetadata(image);
                    Metadata = new MetadataStream
                    {
                        Mime = info.Metadata[edition].Mime,
                        ImageContainerType = metadata.TargetImageCodec,
                        Size = Client.EstimateTransodedSize ? info.Metadata[edition].Size : 0,
                    };
                    Image = new ImageStream
                    {
                        Height          = metadata.TargetMaxHeight,
                        Orientation     = metadata.TargetOrientation,
                        PixelFormatType = metadata.TargetPixelFormat,
                        Width           = metadata.TargetMaxWidth
                    };
                }
                else if (IsAudio)
                {
                    AudioTranscoding        audio    = (AudioTranscoding)TranscodingParameter;
                    TranscodedAudioMetadata metadata = MediaConverter.GetTranscodedAudioMetadata(audio);
                    Metadata = new MetadataStream
                    {
                        Mime = info.Metadata[edition].Mime,
                        AudioContainerType = metadata.TargetAudioContainer,
                        Bitrate            = metadata.TargetAudioBitrate > 0 ? metadata.TargetAudioBitrate : null,
                        Duration           = info.Metadata[edition].Duration,
                        Size = Client.EstimateTransodedSize ? (metadata.TargetAudioBitrate > 0 ? Convert.ToInt64((metadata.TargetAudioBitrate * 1024 * info.Metadata[edition].Duration) / 8.0) : (long?)null) : null,
                    };
                    AudioStream audioStream = new AudioStream();
                    audioStream.Bitrate   = metadata.TargetAudioBitrate;
                    audioStream.Channels  = metadata.TargetAudioChannels;
                    audioStream.Codec     = metadata.TargetAudioCodec;
                    audioStream.Frequency = metadata.TargetAudioFrequency;
                    Audio = new List <AudioStream> {
                        audioStream
                    };
                }
                else if (IsVideo)
                {
                    VideoTranscoding        video    = (VideoTranscoding)TranscodingParameter;
                    TranscodedVideoMetadata metadata = MediaConverter.GetTranscodedVideoMetadata(video);
                    Metadata = new MetadataStream
                    {
                        Mime = info.Metadata[edition].Mime,
                        VideoContainerType = metadata.TargetVideoContainer,
                        Bitrate            = metadata.TargetAudioBitrate > 0 && metadata.TargetVideoBitrate > 0 ? metadata.TargetAudioBitrate + metadata.TargetVideoBitrate : null,
                        Duration           = info.Metadata[edition].Duration,
                        Size = Client.EstimateTransodedSize ? (metadata.TargetAudioBitrate > 0 && info.Metadata[edition].Duration > 0 ? Convert.ToInt64((metadata.TargetAudioBitrate * 1024 * info.Metadata[edition].Duration) / 8.0) : (long?)null) : null,
                    };
                    Video = new VideoStream
                    {
                        AspectRatio      = metadata.TargetVideoAspectRatio,
                        Bitrate          = metadata.TargetVideoBitrate,
                        Codec            = metadata.TargetVideoCodec,
                        Framerate        = metadata.TargetVideoFrameRate,
                        HeaderLevel      = metadata.TargetLevel,
                        ProfileType      = metadata.TargetProfile,
                        RefLevel         = metadata.TargetLevel,
                        Height           = metadata.TargetVideoMaxHeight,
                        PixelAspectRatio = metadata.TargetVideoPixelAspectRatio,
                        PixelFormatType  = metadata.TargetVideoPixelFormat,
                        TimestampType    = metadata.TargetVideoTimestamp,
                        Width            = metadata.TargetVideoMaxWidth,
                    };
                    AudioStream audioStream = new AudioStream();
                    audioStream.Bitrate   = metadata.TargetAudioBitrate;
                    audioStream.Channels  = metadata.TargetAudioChannels;
                    audioStream.Codec     = metadata.TargetAudioCodec;
                    audioStream.Frequency = metadata.TargetAudioFrequency;
                    Audio = new List <AudioStream> {
                        audioStream
                    };
                }
            }

            if (IsImage)
            {
                profileList = DlnaProfiles.ResolveImageProfile(Metadata.ImageContainerType, Image.Width, Image.Height);
            }
            else if (IsAudio)
            {
                var audio = Audio.FirstOrDefault();
                profileList = DlnaProfiles.ResolveAudioProfile(Metadata.AudioContainerType, audio?.Codec ?? AudioCodec.Unknown, audio?.Bitrate, audio?.Frequency, audio?.Channels);
            }
            else if (IsVideo)
            {
                var audio = Audio.FirstOrDefault();
                profileList = DlnaProfiles.ResolveVideoProfile(Metadata.VideoContainerType, Video.Codec, audio?.Codec ?? AudioCodec.Unknown, Video.ProfileType, Video.HeaderLevel,
                                                               Video.Framerate, Video.Width, Video.Height, Video.Bitrate, audio?.Bitrate, Video.TimestampType);
            }

            string profile = "";
            string mime    = info.Metadata[edition].Mime;

            if (DlnaProfiles.TryFindCompatibleProfile(Client, profileList, ref profile, ref mime))
            {
                DlnaMime    = mime;
                DlnaProfile = profile;
            }
        }
Exemplo n.º 4
0
        public async Task Initialize(Guid?userId, MediaItem item, int?edition, int?audioId = null, int?subtitleId = null)
        {
            MediaItemId = item.MediaItemId;

            var info = await MediaAnalyzer.ParseMediaItemAsync(item);

            if (info == null)
            {
                Logger.Warn("MP2Extended: Mediaitem {0} couldn't be analyzed", item.MediaItemId);
                return;
            }

            int?          audioStreamId         = null;
            List <string> preferredAudioLang    = new List <string>();
            List <string> preferredSubtitleLang = new List <string>();
            await ResourceAccessUtils.AddPreferredLanguagesAsync(userId, preferredAudioLang, preferredSubtitleLang);

            if (audioId.HasValue)
            {
                if (audioId.Value >= EDITION_OFFSET)
                {
                    edition       = (audioId.Value / EDITION_OFFSET) - 1;
                    audioStreamId = audioId.Value - ((audioId.Value / EDITION_OFFSET) * EDITION_OFFSET);
                }
                else
                {
                    audioStreamId = audioId;
                }
            }

            if (item.HasEditions && !edition.HasValue)
            {
                //Find edition with best matching audio that doesn't require transcoding
                int  currentPriority            = -1;
                bool currentRequiresTranscoding = false;
                foreach (var checkEdition in info.Metadata.Keys)
                {
                    for (int idx = 0; idx < info.Audio[checkEdition].Count; idx++)
                    {
                        VideoTranscoding video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID,
                                                                                             info, checkEdition, preferredAudioLang, IsLive, "");

                        bool requiresTranscoding = video != null;

                        for (int priority = 0; priority < preferredAudioLang.Count; priority++)
                        {
                            if (preferredAudioLang[priority].Equals(info.Audio[checkEdition][idx].Language, StringComparison.InvariantCultureIgnoreCase) == true)
                            {
                                if (currentPriority == -1 || priority < currentPriority || (!requiresTranscoding && currentRequiresTranscoding && priority == currentPriority))
                                {
                                    currentPriority            = priority;
                                    currentRequiresTranscoding = requiresTranscoding;
                                    audioStreamId = info.Audio[checkEdition][idx].StreamIndex;
                                    _edition      = checkEdition;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                //Assign first edition
                _edition = info.Metadata.Min(m => m.Key);
            }

            if (item.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
            {
                IsAudio = true;
            }
            else if (item.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
            {
                IsImage = true;
            }
            else if (item.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
            {
                IsVideo = true;
            }
            else
            {
                Logger.Warn("MP2Extended: Mediaitem {0} contains no required aspect information", item.MediaItemId);
                return;
            }

            string transcodeId = item.MediaItemId.ToString() + "_" + Profile.ID;

            if (IsLive)
            {
                transcodeId = Guid.NewGuid().ToString() + "_" + Profile.ID;
            }

            if (MP2Extended.Settings.TranscodingAllowed)
            {
                if (IsAudio)
                {
                    AudioTranscoding audio = TranscodeProfileManager.GetAudioTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID,
                                                                                         info, _edition, IsLive, transcodeId);
                    TranscodingParameter = audio;
                }
                else if (IsImage)
                {
                    ImageTranscoding image = TranscodeProfileManager.GetImageTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID,
                                                                                         info, _edition, transcodeId);
                    TranscodingParameter = image;
                }
                else if (IsVideo)
                {
                    VideoTranscoding video;
                    if (audioStreamId.HasValue)
                    {
                        video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID,
                                                                            info, _edition, audioStreamId.Value, subtitleId, IsLive, transcodeId);
                    }
                    else
                    {
                        video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID,
                                                                            info, _edition, preferredAudioLang, IsLive, transcodeId);
                    }

                    if (video != null)
                    {
                        if (video.TargetVideoContainer == VideoContainer.Hls)
                        {
                            IsSegmented = true;
                        }
                        if (MP2Extended.Settings.HardcodedSubtitlesAllowed == false)
                        {
                            video.TargetSubtitleSupport = SubtitleSupport.None;
                        }
                    }
                    TranscodingParameter = video;
                }
            }

            if (TranscodingParameter == null)
            {
                if (IsLive)
                {
                    if (IsVideo)
                    {
                        if (audioStreamId.HasValue)
                        {
                            TranscodingParameter = TranscodeProfileManager.GetLiveVideoTranscoding(info, audioStreamId.Value, transcodeId);
                        }
                        else
                        {
                            TranscodingParameter = TranscodeProfileManager.GetLiveVideoTranscoding(info, preferredAudioLang, transcodeId);
                        }
                    }
                    else if (IsAudio)
                    {
                        TranscodingParameter = TranscodeProfileManager.GetLiveAudioTranscoding(info, transcodeId);
                    }
                }
                else if (IsVideo)
                {
                    VideoTranscoding video = TranscodeProfileManager.GetVideoSubtitleTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID,
                                                                                                 info, _edition, IsLive, transcodeId);
                    if (video != null)
                    {
                        if (video.TargetVideoContainer == VideoContainer.Hls)
                        {
                            IsSegmented = true;
                        }
                        if (MP2Extended.Settings.HardcodedSubtitlesAllowed == false)
                        {
                            video.TargetSubtitleSupport = SubtitleSupport.None;
                        }
                    }
                    TranscodingParameter = video;
                }
            }

            AssignWebMetadata(info, _edition);
        }
        protected override async Task <TranscodeContext> TranscodeImageAsync(string clientId, ImageTranscoding image, bool waitForBuffer)
        {
            FFMpegTranscodeContext context = new FFMpegTranscodeContext(_cacheEnabled, _cachePath);

            context.Partial = false;
            string transcodingFile = Path.Combine(_cachePath, GetTranscodingImageFileName(image));

            if (File.Exists(transcodingFile) == true)
            {
                //Use existing context if possible
                TranscodeContext existingContext = await GetExistingTranscodeContextAsync(clientId, image.TranscodeId).ConfigureAwait(false);

                if (existingContext != null)
                {
                    existingContext.TargetFile = transcodingFile;
                    if (existingContext.Stream == null)
                    {
                        existingContext.AssignStream(await GetFileStreamAsync(transcodingFile).ConfigureAwait(false));
                    }
                    return(existingContext);
                }
                else
                {
                    //Presume that it is a cached file
                    TouchFile(transcodingFile);
                    context.Partial    = false;
                    context.TargetFile = transcodingFile;
                    context.AssignStream(await GetFileStreamAsync(transcodingFile).ConfigureAwait(false));
                    return(context);
                }
            }

            FFMpegTranscodeData data = new FFMpegTranscodeData(_cachePath)
            {
                TranscodeId = image.TranscodeId, ClientId = clientId
            };

            if (string.IsNullOrEmpty(image.TranscoderBinPath) == false)
            {
                data.TranscoderBinPath = image.TranscoderBinPath;
            }
            if (string.IsNullOrEmpty(image.TranscoderArguments) == false)
            {
                data.ConcatedFileInput   = image.ConcatSourceMediaPaths;
                data.TranscoderArguments = image.TranscoderArguments;
                data.InputMediaFilePaths = image.SourceMediaPaths;
            }
            else
            {
                _ffMpegCommandline.InitTranscodingParameters(image.ConcatSourceMediaPaths, image.SourceMediaPaths, ref data);
                _ffMpegCommandline.AddTranscodingThreadsParameters(true, ref data);

                _ffMpegCommandline.AddImageParameters(image, data);

                data.InputArguments[data.FirstResourceIndex].Add("-f image2pipe"); //pipe works with network drives
                data.OutputArguments.Add("-f image2");
            }
            data.OutputFilePath = transcodingFile;
            context.TargetFile  = transcodingFile;

            _logger.Debug("FFMpegMediaConverter: Invoking transcoder to transcode image file '{0}' for transcode '{1}'", image.SourceMediaPaths, image.TranscodeId);
            context.Start();
            context.AssignStream(await ExecuteTranscodingProcessAsync(data, context, waitForBuffer).ConfigureAwait(false));
            return(context);
        }