Exemplo n.º 1
0
        /// <summary>
        /// Generates configuration file used by H264StereoSource plugin
        /// </summary>
        /// <param name="stereoVideoInfo"></param>
        /// <returns></returns>
        private static string GenerateStereoSourceConfig(StereoVideoInfo stereoVideoInfo)
        {
            var sb = new StringBuilder();

            sb.AppendLine($"InputFile = \"{stereoVideoInfo.LeftTempFile}\"");
            sb.AppendLine($"InputFile2 = \"{stereoVideoInfo.RightTempFile}\"");
            sb.AppendLine("FileFormat = 0");
            sb.AppendLine("POCScale = 1");
            sb.AppendLine("DisplayDecParams = 1");
            sb.AppendLine("ConcealMode = 0");
            sb.AppendLine("RefPOCGap = 2");
            sb.AppendLine("POCGap = 2");
            sb.AppendLine("IntraProfileDeblocking = 1");
            sb.AppendLine("DecFrmNum = 0");

            return(WriteScript(sb.ToString(), "cfg"));
        }
Exemplo n.º 2
0
        public void GetBdInfo()
        {
            const string strChapters  = "Chapters";  //ProcessingService.GetResourceString("streamselect_chapters");
            const string strVideo     = "Video";     //ProcessingService.GetResourceString("streamselect_video");
            const string strAudio     = "Audio";     //ProcessingService.GetResourceString("streamselect_audio");
            const string strSubtitles = "Subtitles"; //ProcessingService.GetResourceString("streamselect_subtitles");

            _bdInfo = new BDROM(JobInfo.InputFile);
            _bdInfo.Scan();

            var longestClip = GetLongestBdPlaylist();

            var playlistIndex = 1;

            foreach (var item in _bdInfo.PlaylistFiles.Values)
            {
                if (!item.IsValid)
                {
                    playlistIndex++;
                    continue;
                }

                var streamIndex = 0;

                var duration = new DateTime();

                duration = duration.AddSeconds(item.TotalLength);

                var treeRoot = $"Title: {playlistIndex:0} ({item.Name}), Length: {duration.ToString("H:mm:ss.fff")}";

                var treeData = new Dictionary <string, object>
                {
                    {
                        "Name",
                        Path.Combine(_bdInfo.DirectoryPLAYLIST.FullName, item.Name)
                    },
                    { "PlaylistIndex", playlistIndex }
                };

                var root = new StreamTreeNode
                {
                    ID         = _treeNodeID++,
                    Name       = treeRoot,
                    Data       = treeData,
                    Children   = new List <StreamTreeNode>(),
                    IsChecked  = true,
                    IsExpanded = true
                };
                root.PropertyChanged += TreeNodePropertyChanged;
                _tree.Add(root);

                var chaptersStreamTree = CreateNode(root, strChapters, null);
                var videoStreamTree    = CreateNode(root, strVideo, null);
                var audioStreamTree    = CreateNode(root, strAudio, null);
                var subStreamTree      = CreateNode(root, strSubtitles, null);

                var streamChapters = new List <TimeSpan>();
                if (item.Chapters.Count > 1)
                {
                    streamIndex++;

                    streamChapters.AddRange(item.Chapters.Select(TimeSpan.FromSeconds));

                    var chaptersFormat = $"{streamChapters.Count:0} {strChapters}";

                    CreateNode(chaptersStreamTree, chaptersFormat, streamChapters);
                }

                var videoDescStereo       = string.Empty;
                var leftVideoStreamID     = -1;
                var leftVideoDiscStreamID = -1;
                foreach (var clip in item.VideoStreams)
                {
                    streamIndex++;
                    var videoCodec      = clip.CodecName;
                    var videoCodecShort = clip.CodecShortName;
                    var videoDesc       = clip.Description;

                    if ((clip.StreamType == TSStreamType.AVC_VIDEO) && (item.VideoStreams.Count > 1) &&
                        (item.VideoStreams[0].PID == clip.PID) &&
                        (item.VideoStreams[item.VideoStreams.Count - 1].StreamType == TSStreamType.MVC_VIDEO))
                    {
                        videoDescStereo = videoDesc;
                        videoCodec     += item.MVCBaseViewR ? " (right eye)" : " (left eye)";

                        leftVideoStreamID     = streamIndex;
                        leftVideoDiscStreamID = clip.PID;
                    }
                    if ((clip.StreamType == TSStreamType.MVC_VIDEO) && (item.VideoStreams.Count > 1) &&
                        (item.VideoStreams[item.VideoStreams.Count - 1].PID == clip.PID) &&
                        (item.VideoStreams[0].StreamType == TSStreamType.AVC_VIDEO))
                    {
                        videoDesc   = videoDescStereo;
                        videoCodec  = "MPEG-4 MVC Video";
                        videoCodec += item.MVCBaseViewR ? " (right eye)" : " (left eye)";
                    }

                    var videoStreamFormat = $"{streamIndex:0}: {videoCodec} ({videoCodecShort}), {videoDesc}";
                    switch (clip.StreamType)
                    {
                    case TSStreamType.AVC_VIDEO:
                    case TSStreamType.MPEG2_VIDEO:
                    case TSStreamType.MPEG1_VIDEO:
                    case TSStreamType.VC1_VIDEO:
                    {
                        var vid = new VideoInfo
                        {
                            StreamId             = streamIndex,
                            TrackId              = playlistIndex,
                            Fps                  = (float)clip.FrameRateEnumerator / clip.FrameRateDenominator,
                            PicSize              = (VideoFormat)clip.VideoFormat,
                            Interlaced           = clip.IsInterlaced,
                            Format               = clip.CodecShortName,
                            DemuxStreamId        = clip.PID,
                            FrameCount           = 0,
                            Encoded              = false,
                            IsRawStream          = false,
                            StreamSize           = 0,
                            Length               = item.TotalLength,
                            FrameRateEnumerator  = clip.FrameRateEnumerator,
                            FrameRateDenominator = clip.FrameRateDenominator,
                            Height               = clip.Height
                        };

                        int.TryParse(item.Name.Substring(0, item.Name.LastIndexOf('.')), NumberStyles.Number,
                                     _configService.CInfo, out vid.DemuxPlayList);

                        foreach (var streamClip in item.StreamClips)
                        {
                            vid.DemuxStreamNames.Add(streamClip.StreamFile.FileInfo.FullName);
                        }

                        float mod;
                        switch (clip.AspectRatio)
                        {
                        case TSAspectRatio.ASPECT_16_9:
                            mod = (float)1.777778;
                            break;

                        default:
                            mod = (float)1.333333;
                            break;
                        }
                        vid.Width       = (int)(vid.Height * mod);
                        vid.AspectRatio = mod;

                        CreateNode(videoStreamTree, videoStreamFormat, vid);
                    }
                    break;

                    case TSStreamType.MVC_VIDEO:
                    {
                        var vid = new StereoVideoInfo
                        {
                            RightStreamId      = streamIndex,
                            DemuxRightStreamId = clip.PID,
                            LeftStreamId       = leftVideoStreamID,
                            DemuxLeftStreamId  = leftVideoDiscStreamID
                        };
                        CreateNode(videoStreamTree, videoStreamFormat, vid);
                    }
                    break;
                    }
                }

                foreach (var audio in item.AudioStreams)
                {
                    streamIndex++;
                    var audioCodec      = audio.CodecName;
                    var audioCodecShort = audio.CodecShortName;
                    var audioDesc       = audio.Description;
                    var audioLangCode   = audio.LanguageCode;
                    var audioLanguage   = audio.LanguageName;

                    var audioStreamFormat = $"{streamIndex:0}: {audioCodec} ({audioCodecShort}) / {audioLangCode} ({audioLanguage}) / {audioDesc}";

                    var aud = new AudioInfo
                    {
                        Format        = audioCodecShort,
                        FormatProfile = string.Empty,
                        Id            = streamIndex,
                        StreamId      = streamIndex,
                        LangCode      = audioLangCode,
                        TempFile      = string.Empty,
                        OriginalId    = streamIndex,
                        Delay         = 0,
                        Bitrate       = audio.BitRate,
                        DemuxStreamId = audio.PID,
                        SampleRate    = audio.SampleRate,
                        ChannelCount  = audio.ChannelCount + audio.LFE,
                        BitDepth      = audio.BitDepth,
                        ShortLang     = audio.LanguageCode,
                        StreamSize    = 0,
                        Length        = item.TotalLength,
                        IsHdStream    = audio.CoreStream != null
                    };

                    CreateNode(audioStreamTree, audioStreamFormat, aud);
                }

                foreach (var sub in item.TextStreams)
                {
                    streamIndex++;
                    var subCodecShort = sub.CodecShortName;
                    var subDesc       = sub.Description;
                    var subLangCode   = sub.LanguageCode;
                    var subLanguage   = sub.LanguageName;

                    var subStreamFormat = $"{streamIndex:0}: {subCodecShort} / {subLangCode} ({subLanguage}); {subDesc}";

                    var subInfo = new SubtitleInfo
                    {
                        Id            = streamIndex,
                        StreamId      = streamIndex,
                        TempFile      = string.Empty,
                        LangCode      = subLangCode,
                        Format        = subCodecShort,
                        Delay         = 0,
                        DemuxStreamId = sub.PID,
                        StreamSize    = 0
                    };

                    CreateNode(subStreamTree, subStreamFormat, subInfo);
                }

                foreach (var sub in item.GraphicsStreams)
                {
                    streamIndex++;
                    var subCodecShort = sub.CodecShortName;
                    var subDesc       = sub.Description;
                    var subLangCode   = sub.LanguageCode;
                    var subLanguage   = sub.LanguageName;

                    var subStreamFormat = $"{streamIndex:0}: {subCodecShort} / {subLangCode} ({subLanguage}); {subDesc}";

                    var subInfo = new SubtitleInfo
                    {
                        Id            = streamIndex,
                        StreamId      = streamIndex,
                        TempFile      = string.Empty,
                        LangCode      = subLangCode,
                        Format        = subCodecShort,
                        DemuxStreamId = sub.PID,
                        StreamSize    = 0
                    };

                    CreateNode(subStreamTree, subStreamFormat, subInfo);
                }
                playlistIndex++;
            }
            _defaultSelection = longestClip - 1;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generates AviSynth script used for video encoding
        /// </summary>
        /// <param name="videoInfo">All video properties</param>
        /// <param name="changeFps">Defines whether framerate should be changed</param>
        /// <param name="targetFps">Sets target framerate</param>
        /// <param name="resizeTo">Sets target video resolution</param>
        /// <param name="stereoEncoding">Defines, which stereo encoding mode should be used</param>
        /// <param name="stereoVideoInfo">Sets all parameters for stereo encoding</param>
        /// <param name="isDvdResolution">Defines whether target resolution is used for DVD encoding</param>
        /// <param name="subtitleFile">Sets subtitle file for hardcoding into video</param>
        /// <param name="subtitleOnlyForced">Defines whether only forced captions should be hardcoded</param>
        /// <param name="skipScaling"></param>
        /// <returns>Path to AviSynth script</returns>
        public string Generate(VideoInfo videoInfo, bool changeFps, float targetFps, Size resizeTo,
                               StereoEncoding stereoEncoding, StereoVideoInfo stereoVideoInfo, bool isDvdResolution,
                               string subtitleFile, bool subtitleOnlyForced, bool skipScaling)
        {
            var sb = new StringBuilder();

            var mtUseful = (videoInfo.Interlaced && _appConfig.UseHQDeinterlace) || changeFps;

            var useStereo = stereoEncoding != StereoEncoding.None && stereoVideoInfo.RightStreamId > -1;

            // support for multithreaded AviSynth
            if (_appConfig.UseAviSynthMT && mtUseful)
            {
                sb.AppendLine("SetMTMode(2,0)");
                sb.AppendLine("SetMemoryMax(512)");
            }

            var pluginList = new List <string> {
                "ffms2.dll"
            };
            var scriptList = new List <string>();

            //loading plugins

            if (changeFps || (videoInfo.Interlaced && _appConfig.UseHQDeinterlace))
            {
                pluginList.Add("mvtools2.dll");
            }

            if (videoInfo.Interlaced && _appConfig.UseHQDeinterlace)
            {
                pluginList.Add(_appConfig.LastAviSynthVer.StartsWith("2.5")
                                    ? "mt_masktools-25.dll"
                                    : "mt_masktools-26.dll");
                pluginList.Add("nnedi3.dll");
                pluginList.Add("RemoveGrainSSE2.dll");
                pluginList.Add("RepairSSE2.dll");

                scriptList.Add("QTGMC-3.32.avsi");
            }
            else if (videoInfo.Interlaced)
            {
                pluginList.Add("Decomb.dll");
            }

            if (useStereo)
            {
                pluginList.Add("H264StereoSource.dll");
            }

            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                case "sup":
                    pluginList.Add("SupTitle.dll");
                    break;

                case "ass":
                case "ssa":
                case "srt":
                    pluginList.Add("VSFilter.dll");
                    break;
                }
            }

            // generate plugin and script loading
            foreach (var plugin in pluginList)
            {
                sb.AppendLine($"LoadPlugin(\"{Path.Combine(_appConfig.AvsPluginsPath, plugin)}\")");
            }
            foreach (var script in scriptList)
            {
                sb.AppendLine($"Import(\"{Path.Combine(_appConfig.AvsPluginsPath, script)}\")");
            }

            //generate rest of the script

            // calculate framerate numerator & denominator
            if (videoInfo.Fps <= 0)
            {
                var mi = new MediaInfoContainer();
                try
                {
                    mi = GenHelper.GetMediaInfo(videoInfo.TempFile);
                }
                catch (TimeoutException ex)
                {
                    Log.Error(ex);
                    mi = new MediaInfoContainer();
                }
                finally
                {
                    if (mi.Video.Count > 0)
                    {
                        videoInfo.Fps = mi.Video[0].FrameRate;
                        VideoHelper.GetFpsNumDenom(videoInfo.Fps, out videoInfo.FrameRateEnumerator,
                                                   out videoInfo.FrameRateDenominator);

                        if (videoInfo.FrameRateEnumerator == 0)
                        {
                            videoInfo.FrameRateEnumerator  = (int)Math.Round(videoInfo.Fps) * 1000;
                            videoInfo.FrameRateDenominator =
                                (int)(Math.Round(Math.Ceiling(videoInfo.Fps) - Math.Floor(videoInfo.Fps)) + 1000);
                        }
                    }
                }
            }
            sb.Append($"FFVideoSource(\"{videoInfo.TempFile}\",");

            if (videoInfo.FrameRateEnumerator > 0 && videoInfo.FrameRateDenominator > 0)
            {
                sb.Append($"fpsnum={videoInfo.FrameRateEnumerator:0},fpsden={videoInfo.FrameRateDenominator:0},");
            }

            var threadCount = _appConfig.LimitDecoderThreads ? 1 : 0;

            sb.Append($"threads={threadCount:0})");
            sb.AppendLine();

            var stereoVar = string.Empty;

            if (useStereo)
            {
                var configFile = GenerateStereoSourceConfig(stereoVideoInfo);
                sb.AppendLine($"VideoRight = H264StereoSource(\"{configFile}\",{videoInfo.FrameCount - 50:0})");
                StereoConfigFile = configFile;
                stereoVar        = "VideoRight";
            }

            // deinterlace video source
            if (videoInfo.Interlaced)
            {
                if (_appConfig.UseHQDeinterlace)
                {
                    sb.AppendLine("QTGMC(Preset=\"Slower\")");
                }
                else
                {
                    sb.AppendLine("ConvertToYUY2(interlaced=true)");
                    sb.AppendLine("Telecide(post=4)");
                    sb.AppendLine("Crop(4, 0, -4, 0)");
                    sb.AppendLine("AddBorders(4, 0, 4, 0)");
                    sb.AppendLine("ConvertToYV12()");
                }
            }

            // hardcode subtitles
            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                case "sup":
                    var subForced = subtitleOnlyForced ? "true" : "false";
                    sb.Append($"SupTitle(\"{subtitleFile}\", forcedOnly={subForced})");
                    break;

                case "ass":
                case "ssa":
                case "srt":
                    sb.Append($"TextSub(\"{subtitleFile}\")");
                    break;
                }

                sb.AppendLine();
            }

            // video cropping
            if (!videoInfo.CropRect.IsEmpty && !skipScaling)
            {
                int temp;

                Math.DivRem(videoInfo.CropRect.X, 2, out temp);
                videoInfo.CropRect.X += temp;
                Math.DivRem(videoInfo.CropRect.Y, 2, out temp);
                videoInfo.CropRect.Y += temp;
                Math.DivRem(videoInfo.CropRect.Width, 2, out temp);
                videoInfo.CropRect.Width += temp;
                Math.DivRem(videoInfo.CropRect.Height, 2, out temp);
                videoInfo.CropRect.Height += temp;

                videoInfo.Height = videoInfo.CropRect.Height;
                videoInfo.Width  = videoInfo.CropRect.Width;

                if ((videoInfo.CropRect.X > 0) || (videoInfo.CropRect.Y > 0) || (videoInfo.CropRect.Width < videoInfo.Width) ||
                    (videoInfo.CropRect.Height < videoInfo.Height))
                {
                    sb.Append(useStereo ? "CroppedVideoRight = Crop(VideoRight," : "Crop(");

                    sb.Append($"{videoInfo.CropRect.Left:0},{videoInfo.CropRect.Top:0},");
                    sb.Append($"{videoInfo.CropRect.Width:0},{videoInfo.CropRect.Height:0})");
                    sb.AppendLine();

                    if (useStereo)
                    {
                        stereoVar = "CroppedVideoRight";
                    }
                }
            }

            // Side-By-Side stereo encoding
            if (!string.IsNullOrEmpty(stereoVar))
            {
                switch (stereoEncoding)
                {
                case StereoEncoding.FullSideBySideLeft:
                case StereoEncoding.HalfSideBySideLeft:
                    sb.AppendLine($"StackHorizontal(last,{stereoVar})");
                    break;

                case StereoEncoding.FullSideBySideRight:
                case StereoEncoding.HalfSideBySideRight:
                    sb.AppendLine($"StackHorizontal({stereoVar},last)");
                    break;
                }
                sb.AppendLine("ConvertToYV12()");
            }

            var calculatedHeight = videoInfo.Height;
            var calculatedWidth  = videoInfo.Width;

            var borderRight  = 0;
            var borderLeft   = 0;
            var borderBottom = 0;
            var borderTop    = 0;
            var addBorders   = false;

            // video resizing
            if (!resizeTo.IsEmpty && (resizeTo.Height != videoInfo.Height || resizeTo.Width != videoInfo.Width) && !skipScaling)
            {
                // aspect ratios

                var toAr   = (float)Math.Round(resizeTo.Width / (float)resizeTo.Height, 3);
                var fromAr = videoInfo.AspectRatio;
                var mod    = 1f;

                calculatedWidth = resizeTo.Width;

                if (fromAr > toAr) // source aspectratio higher than target aspectratio
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / fromAr);
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                        }
                        calculatedWidth = 720;
                    }
                    else
                    {
                        calculatedWidth  = resizeTo.Width;
                        calculatedHeight = (int)(calculatedWidth / fromAr);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else if (Math.Abs(fromAr - toAr) <= 0)  // source and target aspectratio equals
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / fromAr);
                        calculatedWidth  = 720;
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                        }
                    }
                    else
                    {
                        calculatedWidth  = resizeTo.Width;
                        calculatedHeight = (int)(calculatedWidth / toAr);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else
                {
                    if (fromAr > 1.4f && isDvdResolution)  // source aspectratio not 4:3, encoding for dvd resolution
                    {
                        mod = 720f / resizeTo.Width;

                        calculatedHeight = (int)(calculatedWidth / fromAr);
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                            calculatedWidth  = (int)(calculatedHeight * fromAr * mod);
                        }
                        else
                        {
                            calculatedWidth = 720;
                        }
                    }
                    else if (isDvdResolution)
                    {
                        calculatedHeight = resizeTo.Height;
                        calculatedWidth  = (int)(calculatedHeight * fromAr);
                    }
                    else
                    {
                        calculatedHeight = resizeTo.Height;
                    }

                    int temp;
                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (Math.Abs(toAr - 1.778f) <= 0)     // aspectratio 16:9
                    {
                        addBorders = true;
                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;

                        var borderWidth = (int)((resizeTo.Width * mod) - calculatedWidth);
                        borderLeft = borderWidth / 2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;
                    }
                    else if (calculatedWidth != resizeTo.Width)
                    {
                        addBorders = true;
                        var borderWidth = resizeTo.Width - calculatedWidth;
                        borderLeft = borderWidth / 2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;

                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
            }

            // apply resize filter
            if (calculatedHeight != videoInfo.Height || calculatedWidth != videoInfo.Width ||
                (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                 stereoEncoding == StereoEncoding.HalfSideBySideRight &&
                 useStereo) && !skipScaling)
            {
                if (calculatedHeight < videoInfo.Height || calculatedWidth < videoInfo.Width ||
                    (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                     stereoEncoding == StereoEncoding.HalfSideBySideRight &&
                     useStereo))
                {
                    sb.Append("BicubicResize");
                }
                else
                {
                    sb.Append("Lanczos4Resize");
                }

                sb.Append($"({calculatedWidth:0},{calculatedHeight:0})");
                sb.AppendLine();
            }

            // add borders if needed
            if (addBorders && (borderLeft > 0 || borderRight > 0 || borderTop > 0 || borderBottom > 0) && !skipScaling)
            {
                sb.AppendLine($"AddBorders({borderLeft:0},{borderTop:0},{borderRight:0},{borderBottom:0})");
            }

            // change framerate
            if (changeFps)
            {
                int fpsnum;
                int fpsden;

                // get framerate numerator & denominator for target framerate
                VideoHelper.GetFpsNumDenom(targetFps, out fpsnum, out fpsden);

                // source is 23.976 or 24 fps
                if (videoInfo.FrameRateEnumerator == 24000 && (videoInfo.FrameRateDenominator == 1001 || videoInfo.FrameRateDenominator == 1000))
                {
                    if (fpsnum == 30000 && fpsden == 1001)
                    {
                        // 3:2 pulldown / telecine
                        sb.AppendLine("AssumeFrameBased()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        sb.AppendLine("Weave()");
                    }
                    else if (fpsnum == 25000 && fpsden == 1000)
                    {
                        // convert to 25 fps
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine("ConvertFPS(50)");
                        sb.AppendLine("AssumeTFF()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(4,0,3)");
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // source is 30fps
                else if (videoInfo.FrameRateEnumerator == 30000)
                {
                    sb.AppendLine("ConvertToYUY2()");
                    sb.AppendLine("DoubleWeave()");
                    sb.AppendLine($"ConvertFPS(numerator={fpsnum * 2:0},denominator={fpsden:0})");
                    sb.AppendLine("SelectEven()");
                    sb.AppendLine("ConvertToYV12()");
                }
                // source is 25fps
                else if (videoInfo.FrameRateEnumerator == 25000 && videoInfo.FrameRateDenominator == 1000)
                {
                    if ((fpsnum == 30000 || fpsnum == 24000) && fpsden == 1001)
                    {
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine("ConvertFPS(numerator=48000,denominator=1001");
                        if (fpsnum == 30000)
                        {
                            sb.AppendLine("AssumeFrameBased()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        }
                        else
                        {
                            sb.AppendLine("AssumeTFF()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEven()");
                        }
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // every other framerate
                else
                {
                    // very slow framerate interpolation
                    sb.AppendLine("super = MSuper(pel=2)");
                    sb.AppendLine("backward_vec = MAnalyse(super, overlap=4, isb = true, search=3)");
                    sb.AppendLine("forward_vec = MAnalyse(super, overlap=4, isb = false, search=3)");
                    sb.Append($"MFlowFps(super, backward_vec, forward_vec, num={fpsnum:0}, den={fpsden:0})");
                }

                sb.AppendLine();
            }

            // multithreaded avisynth
            if (!_appConfig.UseAviSynthMT || !mtUseful)
            {
                return(WriteScript(sb.ToString()));
            }

            sb.AppendLine("SetMTMode(1)");
            sb.AppendLine("GetMTMode(false) > 0 ? distributor() : last");

            return(WriteScript(sb.ToString()));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Generates configuration file used by H264StereoSource plugin
        /// </summary>
        /// <param name="stereoVideoInfo"></param>
        /// <returns></returns>
        private static string GenerateStereoSourceConfig(StereoVideoInfo stereoVideoInfo)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat(AppSettings.CInfo, "InputFile = \"{0:s}\"", stereoVideoInfo.LeftTempFile);
            sb.AppendLine();
            sb.AppendFormat(AppSettings.CInfo, "InputFile2 = \"{0:s}\"", stereoVideoInfo.RightTempFile);
            sb.AppendLine();
            sb.AppendLine("FileFormat = 0");
            sb.AppendLine("POCScale = 1");
            sb.AppendLine("DisplayDecParams = 1");
            sb.AppendLine("ConcealMode = 0");
            sb.AppendLine("RefPOCGap = 2");
            sb.AppendLine("POCGap = 2");
            sb.AppendLine("IntraProfileDeblocking = 1");
            sb.AppendLine("DecFrmNum = 0");

            return (WriteScript(sb.ToString(), "cfg"));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Generates AviSynth script used for video encoding
        /// </summary>
        /// <param name="videoInfo">All video properties</param>
        /// <param name="changeFps">Defines whether framerate should be changed</param>
        /// <param name="targetFps">Sets target framerate</param>
        /// <param name="resizeTo">Sets target video resolution</param>
        /// <param name="stereoEncoding">Defines, which stereo encoding mode should be used</param>
        /// <param name="stereoVideoInfo">Sets all parameters for stereo encoding</param>
        /// <param name="isDvdResolution">Defines whether target resolution is used for DVD encoding</param>
        /// <param name="subtitleFile">Sets subtitle file for hardcoding into video</param>
        /// <param name="subtitleOnlyForced">Defines whether only forced captions should be hardcoded</param>
        /// <returns>Path to AviSynth script</returns>
        public static string Generate(VideoInfo videoInfo, bool changeFps, float targetFps, Size resizeTo,
                                      StereoEncoding stereoEncoding, StereoVideoInfo stereoVideoInfo, bool isDvdResolution, string subtitleFile, bool subtitleOnlyForced)
        {
            StringBuilder sb = new StringBuilder();

            bool mtUseful = (videoInfo.Interlaced && AppSettings.UseHQDeinterlace) || changeFps;

            bool useStereo = stereoEncoding != StereoEncoding.None && stereoVideoInfo.RightStreamId > -1;

            // support for multithreaded AviSynth
            if (AppSettings.UseAviSynthMT && mtUseful)
            {
                sb.AppendLine("SetMTMode(2,0)");
                sb.AppendLine("SetMemoryMax(512)");
            }

            //loading plugins
            sb.AppendLine(ImportFFMPEGSource());  // ffms2

            if (changeFps || (videoInfo.Interlaced && AppSettings.UseHQDeinterlace))
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "mvtools2.dll")));

            if (videoInfo.Interlaced && AppSettings.UseHQDeinterlace)
            {
                sb.AppendLine(AppSettings.LastAviSynthVer.StartsWith("2.5")
                                  ? string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                                  Path.Combine(AppSettings.AppPath, "AvsPlugins", "mt_masktools-25.dll"))
                                  : string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                                  Path.Combine(AppSettings.AppPath, "AvsPlugins", "mt_masktools-26.dll")));

                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "nnedi3.dll")));
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "RemoveGrainSSE2.dll")));
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "RepairSSE2.dll")));
                sb.AppendLine(string.Format(AppSettings.CInfo, "Import(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "QTGMC-3.32.avsi")));
            }
            else if (videoInfo.Interlaced)
            {
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "Decomb.dll")));
            }

            if (useStereo)
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "H264StereoSource.dll")));

            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                    case "sup":
                        sb.AppendFormat(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                        Path.Combine(AppSettings.AppPath, "AvsPlugins", "SupTitle.dll"));
                        break;
                    case "ass":
                    case "ssa":
                    case "srt":
                        sb.AppendFormat(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                        Path.Combine(AppSettings.AppPath, "AvsPlugins", "VSFilter.dll"));
                        break;
                }
                sb.AppendLine();
            }

            //generate rest of the script

            // calculate framerate numerator & denominator
            if (videoInfo.FPS <= 0)
            {
                MediaInfoContainer mi = new MediaInfoContainer();
                try
                {
                     mi = Processing.GetMediaInfo(videoInfo.TempFile);
                }
                catch (TimeoutException ex)
                {
                    Log.Error(ex);
                    mi = new MediaInfoContainer();
                }
                finally
                {
                    if (mi.Video.Count > 0)
                    {
                        videoInfo.FPS = mi.Video[0].FrameRate;
                        Processing.GetFPSNumDenom(videoInfo.FPS, out videoInfo.FrameRateEnumerator,
                                                  out videoInfo.FrameRateDenominator);

                        if (videoInfo.FrameRateEnumerator == 0)
                        {
                            videoInfo.FrameRateEnumerator = (int)Math.Round(videoInfo.FPS) * 1000;
                            videoInfo.FrameRateDenominator =
                                (int)(Math.Round(Math.Ceiling(videoInfo.FPS) - Math.Floor(videoInfo.FPS)) + 1000);
                        }
                    }
                }

            }

            if (videoInfo.FrameRateEnumerator > 0 && videoInfo.FrameRateDenominator > 0)
                sb.AppendLine(string.Format(AppSettings.CInfo,
                                            "FFVideoSource(\"{0:s}\",fpsnum={1:0},fpsden={2:0},threads=1)",
                                            videoInfo.TempFile, videoInfo.FrameRateEnumerator,
                                            videoInfo.FrameRateDenominator));
            else
                sb.AppendLine(string.Format(AppSettings.CInfo, "FFVideoSource(\"{0:s}\",threads=1)", videoInfo.TempFile));

            string stereoVar = string.Empty;

            if (useStereo)
            {
                string configFile = GenerateStereoSourceConfig(stereoVideoInfo);
                sb.AppendLine(string.Format(AppSettings.CInfo, "VideoRight = H264StereoSource(\"{0:s}\",{1:g})",
                                            configFile, videoInfo.FrameCount - 50));
                StereoConfigFile = configFile;
                stereoVar = "VideoRight";
            }

            // deinterlace video source
            if (videoInfo.Interlaced)
            {
                if (AppSettings.UseHQDeinterlace)
                    sb.AppendLine("QTGMC(Preset=\"Slower\")");
                else
                {
                    sb.AppendLine("ConvertToYUY2(interlaced=true)");
                    sb.AppendLine("Telecide(post=4)");
                    sb.AppendLine("Crop(4, 0, -4, 0)");
                    sb.AppendLine("AddBorders(4, 0, 4, 0)");
                    sb.AppendLine("ConvertToYV12()");
                }
            }

            // hardcode subtitles
            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                    case "sup":
                        sb.AppendFormat(AppSettings.CInfo, "SupTitle(\"{0}\", forcedOnly={1})", subtitleFile,
                                                        subtitleOnlyForced ? "true" : "false");
                        break;
                    case "ass":
                    case "ssa":
                    case "srt":
                        sb.AppendFormat(AppSettings.CInfo, "TextSub(\"{0}\")", subtitleFile);
                        break;
                }

                sb.AppendLine();
            }

            // video cropping
            if (!videoInfo.CropRect.IsEmpty)
            {
                int temp;

                Math.DivRem(videoInfo.CropRect.X, 2, out temp);
                videoInfo.CropRect.X += temp;
                Math.DivRem(videoInfo.CropRect.Y, 2, out temp);
                videoInfo.CropRect.Y += temp;
                Math.DivRem(videoInfo.CropRect.Width, 2, out temp);
                videoInfo.CropRect.Width += temp;
                Math.DivRem(videoInfo.CropRect.Height, 2, out temp);
                videoInfo.CropRect.Height += temp;

                videoInfo.Height = videoInfo.CropRect.Height;
                videoInfo.Width = videoInfo.CropRect.Width;

                if ((videoInfo.CropRect.X > 0) || (videoInfo.CropRect.Y > 0) || (videoInfo.CropRect.Width < videoInfo.Width) ||
                    (videoInfo.CropRect.Height < videoInfo.Height))
                {
                    sb.AppendLine(string.Format(AppSettings.CInfo, "Crop({0:g},{1:g},{2:g},{3:g})",
                                                videoInfo.CropRect.Left,
                                                videoInfo.CropRect.Top,
                                                videoInfo.CropRect.Width,
                                                videoInfo.CropRect.Height));
                    if (useStereo)
                    {
                        sb.AppendLine(string.Format(AppSettings.CInfo,
                                                    "CroppedVideoRight = Crop(VideoRight,{0:g},{1:g},{2:g},{3:g})",
                                                    videoInfo.CropRect.Left,
                                                    videoInfo.CropRect.Top,
                                                    videoInfo.CropRect.Width,
                                                    videoInfo.CropRect.Height));
                        stereoVar = "CroppedVideoRight";
                    }
                }
            }

            // Side-By-Side stereo encoding
            if (!string.IsNullOrEmpty(stereoVar))
            {
                switch(stereoEncoding)
                {
                    case StereoEncoding.FullSideBySideLeft:
                    case StereoEncoding.HalfSideBySideLeft:
                        sb.AppendLine(string.Format("StackHorizontal(last,{0})", stereoVar));
                        break;
                    case StereoEncoding.FullSideBySideRight:
                    case StereoEncoding.HalfSideBySideRight:
                        sb.AppendLine(string.Format("StackHorizontal({0},last)", stereoVar));
                        break;
                }
                sb.AppendLine("ConvertToYV12()");
            }

            int calculatedHeight = videoInfo.Height;
            int calculatedWidth = videoInfo.Width;
            int borderRight = 0;
            int borderLeft = 0;
            int borderBottom = 0;
            int borderTop = 0;
            bool addBorders = false;

            // video resizing
            if (!resizeTo.IsEmpty && (resizeTo.Height != videoInfo.Height || resizeTo.Width != videoInfo.Width))
            {
                // aspect ratios

                float toAr = (float) Math.Round(resizeTo.Width / (float)resizeTo.Height, 3);

                calculatedWidth = resizeTo.Width;

                float mod = 1f;

                if (videoInfo.AspectRatio > toAr) // source aspectratio higher than target aspectratio
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                        if (calculatedHeight > resizeTo.Height)
                            calculatedHeight = resizeTo.Height;
                        calculatedWidth = 720;
                    }
                    else
                    {
                        calculatedWidth = resizeTo.Width;
                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else if (Math.Abs(videoInfo.AspectRatio - toAr) <= 0)  // source and target aspectratio equals
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                        calculatedWidth = 720;
                        if (calculatedHeight > resizeTo.Height)
                            calculatedHeight = resizeTo.Height;
                    }
                    else
                    {
                        calculatedWidth = resizeTo.Width;
                        calculatedHeight = (int) (calculatedWidth/toAr);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else
                {
                    if (videoInfo.AspectRatio > 1.4f && isDvdResolution)  // source aspectratio not 4:3, encoding for dvd resolution
                    {
                        mod = 720f/resizeTo.Width;

                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                            calculatedWidth = (int)(calculatedHeight * videoInfo.AspectRatio * mod);
                        }
                        else
                            calculatedWidth = 720;
                    }
                    else if (isDvdResolution)
                    {
                        calculatedHeight = resizeTo.Height;
                        calculatedWidth = (int) (calculatedHeight*videoInfo.AspectRatio);
                    }
                    else
                        calculatedHeight = resizeTo.Height;

                    int temp;
                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (Math.Abs(toAr - 1.778f) <= 0)     // aspectratio 16:9
                    {
                        addBorders = true;
                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;

                        int borderWidth = (int) ((resizeTo.Width*mod) - calculatedWidth);
                        borderLeft = borderWidth/2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;
                    }
                    else if (calculatedWidth != resizeTo.Width)
                    {
                        addBorders = true;
                        int borderWidth = resizeTo.Width - calculatedWidth;
                        borderLeft = borderWidth/2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;

                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
            }

            // apply resize filter
            if (calculatedHeight != videoInfo.Height || calculatedWidth != videoInfo.Width ||
                (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                 stereoEncoding == StereoEncoding.HalfSideBySideRight
                && useStereo))
            {
                if (calculatedHeight < videoInfo.Height || calculatedWidth < videoInfo.Width ||
                    (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                     stereoEncoding == StereoEncoding.HalfSideBySideRight
                     && useStereo))
                    sb.AppendLine(string.Format(AppSettings.CInfo, "BicubicResize({0:g},{1:g})",
                                                calculatedWidth,
                                                calculatedHeight));
                else
                    sb.AppendLine(string.Format(AppSettings.CInfo, "Lanczos4Resize({0:g},{1:g})",
                                                calculatedWidth,
                                                calculatedHeight));
            }

            // add borders if needed
            if (addBorders && (borderLeft > 0 || borderRight > 0 || borderTop > 0 || borderBottom > 0))
                sb.AppendLine(string.Format(AppSettings.CInfo, "AddBorders({0:g},{1:g},{2:g},{3:g})",
                                            borderLeft,
                                            borderTop,
                                            borderRight,
                                            borderBottom));

            // change framerate
            if (changeFps)
            {
                int fpsnum;
                int fpsden;

                // get framerate numerator & denominator for target framerate
                Processing.GetFPSNumDenom(targetFps, out fpsnum, out fpsden);

                // source is 23.976 or 24 fps
                if (videoInfo.FrameRateEnumerator == 24000 && (videoInfo.FrameRateDenominator == 1001 || videoInfo.FrameRateDenominator == 1000))
                {
                    if (fpsnum == 30000 && fpsden == 1001)
                    {
                        // 3:2 pulldown / telecine
                        sb.AppendLine("AssumeFrameBased()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        sb.AppendLine("Weave()");
                    }
                    else if (fpsnum == 25000 && fpsden == 1000)
                    {
                        // convert to 25 fps
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine("ConvertFPS(50)");
                        sb.AppendLine("AssumeTFF()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(4,0,3)");
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // source is 30fps
                else if (videoInfo.FrameRateEnumerator == 30000)
                {
                    sb.AppendLine("ConvertToYUY2()");
                    sb.AppendLine("DoubleWeave()");
                    sb.AppendLine(string.Format(AppSettings.CInfo, "ConvertFPS({0:0.000})", targetFps*2));
                    sb.AppendLine("SelectEven()");
                    sb.AppendLine("ConvertToYV12()");
                }
                // source is 25fps
                else if (videoInfo.FrameRateEnumerator == 25000 && videoInfo.FrameRateDenominator == 1000)
                {
                    if ((fpsnum == 30000 || fpsnum == 24000) && fpsden == 1001)
                    {
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine(string.Format(AppSettings.CInfo, "ConvertFPS({0:0.000}*2)", 23.976));
                        if (fpsnum == 30000)
                        {
                            sb.AppendLine("AssumeFrameBased()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        }
                        else
                        {
                            sb.AppendLine("AssumeTFF()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEven()");
                        }
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // every other framerate
                else
                {
                    // very slow framerate interpolation
                    sb.AppendLine("super = MSuper(pel=2)");
                    sb.AppendLine("backward_vec = MAnalyse(super, overlap=4, isb = true, search=3)");
                    sb.AppendLine("forward_vec = MAnalyse(super, overlap=4, isb = false, search=3)");
                    sb.AppendFormat("MFlowFps(super, backward_vec, forward_vec, num={0:0}, den={1:0})", fpsnum,
                                    fpsden);
                }

                sb.AppendLine();
            }

            // multithreaded avisynth
            if (AppSettings.UseAviSynthMT && mtUseful)
            {
                sb.AppendLine("SetMTMode(1)");
                sb.AppendLine("GetMTMode(false) > 0 ? distributor() : last");
            }

            return WriteScript(sb.ToString());
        }