Exemple #1
0
        /// <summary>
        /// Used to execute custom commands after the conversion process is compelte just before the file is moved to the desination directory
        /// </summary>
        /// <param name="prefix">Prefix for reading lines from profile</param>
        /// <param name="profile">Profile name</param>
        /// <param name="taskName">Task Name</param>
        /// <param name="workingPath">Temp working path</param>
        /// <param name="destinationPath">Destination path for converted file</param>
        /// <param name="convertedFile">Full path to final converted file</param>
        /// <param name="sourceFile">Full path to original source file</param>
        /// <param name="remuxFile">Full path to intermediate remuxed file</param>
        /// <param name="edlFile">Full path to EDL file</param>
        /// <param name="srtFile">Full path to SRT file</param>
        /// <param name="metaData">Video metadata structure for source file</param>
        /// <param name="jobStatus">ref to JobStatus</param>
        /// <param name="jobLog">JobLog</param>
        public CustomCommand(string prefix, string profile, string taskName, string workingPath, string destinationPath, string convertedFile, string sourceFile, string remuxFile, string edlFile, string srtFile, VideoTags metaData, JobStatus jobStatus, Log jobLog)
        {
            _profile = profile;
            _taskName = taskName;
            _jobLog = jobLog;
            _jobStatus = jobStatus;
            _workingPath = workingPath;
            _destinationPath = destinationPath;
            _convertedFile = convertedFile;
            _sourceFile = sourceFile;
            _remuxFile = remuxFile;
            _edlFile = edlFile;
            _srtFile = srtFile;
            _metaData = metaData;
            _prefix = prefix;

            Ini ini = new Ini(GlobalDefs.ProfileFile);
            commandPath = ini.ReadString(profile, prefix + "Path", "").ToLower().Trim();
            commandParameters = ini.ReadString(profile, prefix + "Parameters", "");
            hangPeriod = ini.ReadInteger(profile, prefix + "HangPeriod", GlobalDefs.HANG_PERIOD_DETECT);
            customCommandCritical = ini.ReadBoolean(profile, prefix + "Critical", false); // NOTE: if customCommandCritical is TRUE will need to return false in case it's a failure
            customCommandUISession = ini.ReadBoolean(profile, prefix + "UISession", false); // Does the custom command need a UI Session (Session 1) with admin privileges
            customCommandShowWindow = ini.ReadBoolean(profile, prefix + "ShowWindow", true); // Show the window or hide it
            customCommandExitCodeCheck = ini.ReadBoolean(profile, prefix + "ExitCodeCheck", false); // Don't check for exit code

            _jobLog.WriteEntry(this, "Custom command parameters read -> " + " \n" + _prefix + "Path = " + commandPath + " \n" + _prefix + "Parameters = " + commandParameters + " \n" + _prefix + "HangPeriod = " + hangPeriod.ToString(System.Globalization.CultureInfo.InvariantCulture) + " \n" + _prefix + "Critical = " + customCommandCritical.ToString() + " \n" + _prefix + "UISession = " + customCommandUISession.ToString() + " \n" + _prefix + "ShowWindow = " + customCommandShowWindow.ToString() + " \n" + _prefix + "ExitCodeCheck = " + customCommandExitCodeCheck.ToString(), Log.LogEntryType.Debug);
        }
Exemple #2
0
 public TiVOUserRemux(string Parameters, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
     : base(Parameters, APP_PATH, jobStatus, jobLog, ignoreSuspend)
 {
     // TODO: we need to relook at this, tivo filters still don't work in user space when launched from a service
     _uiAdminSessionProcess = true; // This apps needs to be run in User Space
     _success = false;
 }
Exemple #3
0
        private bool _encodeError = false; // Any critical error

        /// <summary>
        /// General FFMPEG to convert a file
        /// </summary>
        /// <param name="Parameters">Parameters to pass to FFMPEG</param>
        /// <param name="jobStatus">Reference to JobStatus</param>
        /// <param name="jobLog">JobLog</param>
        public FFmpeg(string Parameters, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
            : base(Parameters, APP_PATH, jobStatus, jobLog, ignoreSuspend)
        {
            _Parameters = " -probesize 100M -analyzeduration 300M " + _Parameters; // We need to probe deeper into the files to get the correct audio / video track information else it can lead to incorrect channel information and failure
            _success = false; //ffmpeg looks for a +ve output so we have a false to begin with
            _uiAdminSessionProcess = true; // Assume we are always using ffmpeg build with hardware API's (UI Session 1 process)
        }
Exemple #4
0
        private Collections.FixedSizeQueue<KeyValuePair<float, DateTime>> _percentageHistory = new Collections.FixedSizeQueue<KeyValuePair<float, DateTime>>(GlobalDefs.PERCENTAGE_HISTORY_SIZE); // Track last 5 % entries

        /// <summary>
        /// Default base class for starting a process within the MCEBuddy installation directory
        /// </summary>
        /// <param name="parameters">Parameters for a process</param>
        /// <param name="appPath">Relative path of app to MCEBuddy installation directory</param>
        /// <param name="ignoreSuspend">Don't stop the process if MCEBuddy is suspended by user (useful if app is being called by the GUI or can deadlock)</param>
        public Base(string parameters, string appPath, JobStatus jobStatus, Log jobLog, bool ignoreSuspend=false)
        {
            _ApplicationPath = Path.Combine(GlobalDefs.AppPath, appPath);
            _Parameters = parameters;
            _jobStatus = jobStatus;
            _jobLog = jobLog;
            _ignoreSuspend = ignoreSuspend;
        }
 public FileExtractMetadata(string videoFileName, VideoTags videoTags, string tivoMAKKey, bool ignoreSuspend, JobStatus jobStatus, Log jobLog)
 {
     _videoFileName = videoFileName;
     _videoTags = videoTags;
     _jobLog = jobLog;
     _jobStatus = jobStatus;
     _tivoMAKKey = tivoMAKKey;
     _ignoreSuspend = ignoreSuspend;
 }
        private string _srtFile = ""; // Subtitle file

        public ConvertWithFfmpeg(ConversionJobOptions conversionOptions, string tool, VideoInfo videoFile, JobStatus jobStatus, Log jobLog, Scanner commercialScan, string srtFile)
            : base(conversionOptions, tool, videoFile, jobStatus, jobLog, commercialScan)
        {
            passLog = Path.Combine(_workingPath, "MCEBuddy2Pass.log"); // Name of passlog file
            //Check if MEncoder EDL Removal has been disabled at conversion time
            Ini ini = new Ini(GlobalDefs.ProfileFile);
            if(ini.ReadBoolean(conversionOptions.profile, tool + "-SubtitleBurn", false))
                _srtFile = srtFile; // Save the SRT file info otherwise skip it
        }
        public RemuxMCERecording(ConversionJobOptions cjo, JobStatus jobStatus, Log jobLog)
        {
            _jobStatus = jobStatus;
            _jobLog = jobLog;
            _RecordingFile = cjo.sourceVideo;
            _destinationPath = cjo.workingPath;
            _requestedAudioLanguage = cjo.audioLanguage;
            _tivoMAKKey = cjo.tivoMAKKey;

            if (Util.FilePaths.CleanExt(_RecordingFile) == ".ts") // Handle TS files difference since they will have the same namess
                _RemuxedFile = Path.Combine(_destinationPath, Path.GetFileNameWithoutExtension(_RecordingFile) + "-REMUXED.ts");
            else
                _RemuxedFile = Path.Combine(_destinationPath, Path.GetFileNameWithoutExtension(_RecordingFile) + ".ts");

            // Read various profile parameters
            Ini configProfileIni = new Ini(GlobalDefs.ProfileFile);
            _useRemuxsupp = configProfileIni.ReadBoolean(cjo.profile, "UseWTVRemuxsupp", false); // Some videos fail with FFMPEG remuxing and Mencoder encoding (use remuxsupp for remuxing there)
            _jobLog.WriteEntry(this, "Force Remuxsupp (UseWTVRemuxsupp) : " + _useRemuxsupp.ToString(), Log.LogEntryType.Debug);

            _forceWTVStreamsRemuxing = configProfileIni.ReadBoolean(cjo.profile, "ForceWTVStreamsRemuxing", false); // Use Streams remuxing for DVRMS and WTV files
            _jobLog.WriteEntry(this, "Force Streams Remuxing (ForceWTVStreamsRemuxing) : " + _forceWTVStreamsRemuxing.ToString(), Log.LogEntryType.Debug);

            _allowH264CopyRemuxing = configProfileIni.ReadBoolean(cjo.profile, "AllowH264CopyRemuxing", true); // Allow H.264 files to be remuxed into TS without recoding to MPEG2
            _jobLog.WriteEntry(this, "Allow H264 Copy Remuxing (AllowH264CopyRemuxing) (default: true) : " + _allowH264CopyRemuxing.ToString(), Log.LogEntryType.Debug);

            _allowAllCopyRemuxing = configProfileIni.ReadBoolean(cjo.profile, "AllowAllCopyRemuxing", false); // Allow any video codec to be remuxed into TS without recoding to MPEG2
            _jobLog.WriteEntry(this, "Allow All Video codec formats Copy Remuxing (AllowAllCopyRemuxing) (default: false) : " + _allowAllCopyRemuxing.ToString(), Log.LogEntryType.Debug);

            // Get the media info for the recording file once for the entire operation to reuse
            _jobLog.WriteEntry(this, "Reading Recording file " + _RecordingFile + " media information", Log.LogEntryType.Debug);
            _RecordingFileMediaInfo = new FFmpegMediaInfo(_RecordingFile, _jobStatus, _jobLog);

            // Check for donator version of Comskip
            Comskip checkComskip = new Comskip(MCEBuddyConf.GlobalMCEConfig.GeneralOptions.comskipPath, _jobLog);

            // Check if we are using a mpeg4 video and allowing h264 video codec for commercial skipping purposes
            if (_allowH264CopyRemuxing)
            {
                if (_mpeg4Codecs.Any(s => s.Contains(_RecordingFileMediaInfo.MediaInfo.VideoInfo.VideoCodec.ToLower())))
                {
                    if (cjo.commercialRemoval == CommercialRemovalOptions.Comskip)
                    {
                        if (checkComskip.IsDonator)
                            _jobLog.WriteEntry(this, "AllowH264CopyRemuxing will run fast for commercial detection, using donator version of Comskip", Log.LogEntryType.Information);
                        else
                            _jobLog.WriteEntry(this, "AllowH264CopyRemuxing is SLOW with the bundled Comskip. Use ShowAnalyzer or Comskip Donator version (http://www.comskip.org) to speed up commercial detection. Codec detected -> " + _RecordingFileMediaInfo.MediaInfo.VideoInfo.VideoCodec, Log.LogEntryType.Warning);
                    }
                }
            }

            // Check if we are using an unsupported codec and copying to TS format
            if (_allowAllCopyRemuxing)
                if (!_supportedCodecs.Any(s => s.Contains(_RecordingFileMediaInfo.MediaInfo.VideoInfo.VideoCodec.ToLower()))) // Check if we using any of the default supported codecs
                        _jobLog.WriteEntry(this, "AllowAllCopyRemuxing is enabled and an unsupported codec in the source video is detected. Some underlying programs may not work with this codec. Codec detected -> " + _RecordingFileMediaInfo.MediaInfo.VideoInfo.VideoCodec, Log.LogEntryType.Warning);
        }
Exemple #8
0
        public RemuxExt(string originalFile, string workingPath, double fps, JobStatus jobStatus, Log jobLog, string remuxTo)
        {
            _jobLog = jobLog;
            _jobStatus = jobStatus;
            _originalFile = originalFile; // By default if we aren't remuxing then the remuxed file is the original file
            _fps = fps;
            _remuxTo = remuxTo.ToLower();
            _extension = FilePaths.CleanExt(originalFile);
            _workingPath = workingPath;

            _jobLog.WriteEntry(this, "Remux To : " + _remuxTo, Log.LogEntryType.Debug);
            _jobLog.WriteEntry(this, "Extension : " + _extension, Log.LogEntryType.Debug);
        }
        /// <summary>
        /// Detects the cropping information of a video file using MEncoder. Runs automatically on initialization
        /// </summary>
        /// <param name="sourceFile">Video file to detect cropping</param>
        /// <param name="edlFile">EDL file to skip video sections for crop</param>
        public MencoderCropDetect(string sourceFile, string edlFile, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
            : base(sourceFile, APP_PATH, jobStatus, jobLog, ignoreSuspend)
        {
            // Update the parameters to be passed to mEncoder for cropdetect (ladvopts supports a max of 8 threads)
            _Parameters = Util.FilePaths.FixSpaces(sourceFile) + " -lavdopts threads=" + Math.Min(8, Environment.ProcessorCount).ToString(System.Globalization.CultureInfo.InvariantCulture) + " -nosound -ovc raw -o nul -vf cropdetect"; // setup for multiple processors to speed it up
            
            if (!string.IsNullOrEmpty(edlFile))
                _Parameters += " -edl " + Util.FilePaths.FixSpaces(edlFile); // If there is an EDL file use it to speed things up

            _success = true; //by deafult everything here works unless the process hangs

            Run(); // Run it now
        }
Exemple #10
0
 /// <summary>
 /// Extract the metadata from the video file (WTV/DVRMS/MP4/MKV/AVI/TS XML) and supplement with information downloaded from TVDB and MovieDB
 /// </summary>
 /// <param name="cjo">Conversion job options</param>
 /// <param name="disableDownloadSeriesDetails">(Optional) True if you want to override adn disable the DownloadSeriesDetails option from TVDB/MovieDB</param>
 public VideoMetaData(ConversionJobOptions cjo, JobStatus jobStatus, Log jobLog, bool disableDownloadSeriesDetails = false)
 {
     _videoFileName = cjo.sourceVideo;
     _downloadSeriesDetails = (cjo.downloadSeriesDetails && !disableDownloadSeriesDetails); // special case, if want to override it
     _downloadBannerFile = (cjo.downloadBanner && !disableDownloadSeriesDetails);
     _jobStatus = jobStatus;
     _jobLog = jobLog;
     _metadataCorrections = cjo.metadataCorrections;
     _tivoMAKKey = cjo.tivoMAKKey;
     _profile = cjo.profile;
     _taskName = cjo.taskName;
     _forceShowType = cjo.forceShowType;
     _prioritizeMatchDate = cjo.prioritizeOriginalBroadcastDateMatch;
 }
Exemple #11
0
        public Scanner(ConversionJobOptions conversionOptions, string videoFileName, bool useShowAnalyzer, float duration, JobStatus jobStatus, Log jobLog)
            : base(conversionOptions.profile, videoFileName, duration, "", 0, jobStatus, jobLog)
        {
            _videoFileName = videoFileName;
            _useShowAnalyzer = useShowAnalyzer;
            _jobStatus = jobStatus;
            _jobLog = jobLog;
            _profile = conversionOptions.profile;
            _convOptions = conversionOptions;

            _customComskipPath = MCEBuddyConf.GlobalMCEConfig.GeneralOptions.comskipPath;
            if (!String.IsNullOrWhiteSpace(_customComskipPath))
                _jobLog.WriteEntry(this, "Using Custom Comskip Path -> " + MCEBuddyConf.GlobalMCEConfig.GeneralOptions.comskipPath, Log.LogEntryType.Information);
        }
        private const double DRC = 0.8; // Dynamic Range Compression to 80%

        public ConvertWithMencoder(ConversionJobOptions conversionOptions, string tool, VideoInfo videoFile, JobStatus jobStatus, Log jobLog, Scanner commercialScan)
            : base(conversionOptions, tool, videoFile, jobStatus, jobLog, commercialScan)
        {
            //Check if MEncoder EDL Removal has been disabled at conversion time
            Ini ini = new Ini(GlobalDefs.ProfileFile);
            mEncoderEDLSkip = ini.ReadBoolean(conversionOptions.profile, "MEncoderEDLSkip", false);
            
            _extractCC = conversionOptions.extractCC;
            if (!String.IsNullOrEmpty(_extractCC)) // If Closed Caption extraction is enabled, we don't use cut EDL using Mencoder during encoding, Mencoder has a bug which causes it to cut out of sync with the EDL file which throws the CC out of sync, it will be cut separately
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("Closed Captions Enabled, skipping EDL cutting during encoding"), Log.LogEntryType.Information);
                mEncoderEDLSkip = true;
            }
            
            if ((_startTrim != 0) || (_endTrim != 0)) // If trimming is enabled skip cutting using EDL otherwise MEncoder messes it up
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("Trimming Enabled, skipping EDL cutting during encoding"), Log.LogEntryType.Information);
                mEncoderEDLSkip = true;
            }
        }
Exemple #13
0
        private string _XMLCHAPFile = ""; // If the XML CHAP file exists

        /// <summary>
        /// Class for manipulating EDL, EDLP and CHAP files
        /// </summary>
        /// <param name="profile">Conversion Profile name</param>
        /// <param name="fileName">Full path Video from which EDL, EDLP and CHAP filenames will be dervied</param>
        /// <param name="duration">Length of video</param>
        /// <param name="edlFile">EDL File used to set the initial EDLFile property</param>
        /// <param name="initialSkipSeconds">Number of seconds of the file cut which needs to be adjusted while calculating cut segments</param>
        public EDL(string profile, string fileName, float duration, string edlFile, float initialSkipSeconds, JobStatus jobStatus, Log jobLog)
        {
            _profile = profile;
            _videoFileName = fileName;
            _duration = duration;
            _initialSkipSeconds = initialSkipSeconds;
            _jobLog = jobLog;
            _jobStatus = jobStatus;
            _EDLFile = edlFile;

            //check if we need to use the EDL file instead of the EDLP file
            Ini ini = new Ini(GlobalDefs.ProfileFile);
            _forceEDL = ini.ReadBoolean(_profile, "ForceEDL", false);
            _forceEDLP = ini.ReadBoolean(_profile, "ForceEDLP", false);

            // Fix duration for initial skip seconds
            _duration = (_duration - _initialSkipSeconds < 0 ? 0 : _duration - _initialSkipSeconds);

            _jobLog.WriteEntry(this, "EDL: Initial skip seconds adjustment " + _initialSkipSeconds.ToString(CultureInfo.InvariantCulture) + " seconds.", Log.LogEntryType.Debug);
        }
Exemple #14
0
        public Remover(string profile, string uncutVideo, string workingPath, string edlFile, float initialSkipSeconds, VideoInfo remuxedVideoFileInfo, JobStatus jobStatus, Log jobLog)
            : base(profile, uncutVideo, remuxedVideoFileInfo.Duration, edlFile, initialSkipSeconds, jobStatus, jobLog)
        {
            _remuxedVideoFileInfo = remuxedVideoFileInfo;
            _uncutVideo = uncutVideo;
            _ext = Util.FilePaths.CleanExt(_uncutVideo);
            _workingPath = workingPath;
            _duration = _remuxedVideoFileInfo.Duration;
            _jobStatus = jobStatus;
            _jobLog = jobLog;

            // Read various profile parameters
            Ini configProfileIni = new Ini(GlobalDefs.ProfileFile);
            _cutMP4Alternative = configProfileIni.ReadBoolean(profile, "CutMP4Alternate", false); // for FFMPEG and Handbrake, we have commerical cutting options, for mEncoder cutting is done during conversion using -edl option
            jobLog.WriteEntry("MP4 Alternative Cutting -> " + _cutMP4Alternative.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Debug);
            _universalCommercialRemover = configProfileIni.ReadBoolean(profile, "UniversalCommercialRemover", false); // Forcing the use of CutFFMPEG which works on all video types
            jobLog.WriteEntry("Universal Commercial Remover -> " + _universalCommercialRemover.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Debug);
            string commercialMerge = configProfileIni.ReadString(profile, "CommercialMergeTool", ""); // Force tool to merge commercial segments
            jobLog.WriteEntry("Force Commercial Segment Merging Tool -> " + commercialMerge, Log.LogEntryType.Debug);

            switch (commercialMerge.ToLower())
            {
                case "avidemux":
                    _useAVIDemuxMerge = true;
                    break;

                case "ffmpeg":
                    _useFFMPEGMerge = true;
                    break;

                case "":
                    break;

                default:
                    jobLog.WriteEntry("INVALID Force Commercial Segment Merging Tool -> " + commercialMerge, Log.LogEntryType.Warning);
                    break;
            }
        }
        public ConvertWithHandbrake(ConversionJobOptions conversionOptions, string tool, VideoInfo videoFile, JobStatus jobStatus, Log jobLog, Scanner commercialScan)
            : base(conversionOptions, tool, videoFile, jobStatus, jobLog, commercialScan)
        {
            // Check if we have hardware encoding support available on the system
            Handbrake hb = new Handbrake(jobLog);
            hardwareEncodingAvailable = hb.QuickSyncEncodingAvailable;

            //Check if the profiles is setup for Hardware encoding, if so don't adjust hardware encoding options
            Ini ini = new Ini(GlobalDefs.ProfileFile);
            bool profileHardwareEncoding = ini.ReadBoolean(conversionOptions.profile, tool + "-UsingHardwareEncoding", false);
            if (_preferHardwareEncoding && profileHardwareEncoding)
            {
                _jobLog.WriteEntry(this, "Hardware enabled handbrake profile, disabling auto hardware encoder adjustments", Log.LogEntryType.Debug);
                _preferHardwareEncoding = false; // Don't change any settings, this profile is already setup for hardware encoding
            }

            // Check if we are using any of the h264 codecs, only then can we use hardware encoder for H264
            if (_preferHardwareEncoding && !h264Encoders.Any((new FFMpegMEncoderParams(_videoParams)).ParameterValue("-e").ToLower().Equals))
            {
                _jobLog.WriteEntry(this, "Cannot find h264 encoder, disabling auto hardware h264 encoder adjustments", Log.LogEntryType.Debug);
                _preferHardwareEncoding = false; // Don't use hardware encoder since this isn't a h264 profile
            }
        }
Exemple #16
0
        public ConversionJob(ConversionJobOptions conversionJobOptions, VideoMetaData metaData)
        {
            _conversionOptions = conversionJobOptions; // First thing to do
            _metaData = metaData; // Save the metadata if present

            _originalFileNameBackup = _conversionOptions.sourceVideo; // This is what we use to report to the world what we're working on, _sourceVideo may change under certain conditions below
            if (String.IsNullOrEmpty(_conversionOptions.destinationPath))
                _conversionOptions.destinationPath = Path.GetDirectoryName(_conversionOptions.sourceVideo); // No dest path = convert in place

            _jobStatus = new JobStatus();
            _jobStatus.SourceFile = _conversionOptions.sourceVideo;
            _jobStatus.TaskName = _conversionOptions.taskName;

            // Read various engine parameters
            _maxConcurrentJobs = MCEBuddyConf.GlobalMCEConfig.GeneralOptions.maxConcurrentJobs;
            _spaceCheck = MCEBuddyConf.GlobalMCEConfig.GeneralOptions.spaceCheck;
            _subtitleSegmentOffset = MCEBuddyConf.GlobalMCEConfig.GeneralOptions.subtitleSegmentOffset;

            // Read various profile parameters
            Ini configProfileIni = new Ini(GlobalDefs.ProfileFile);

            // Profile only parameters 
            _preConversionCommercialRemover = configProfileIni.ReadBoolean(_conversionOptions.profile, "PreConversionCommercialRemover", false); // Check if the user wants to remove commercials before the actual conversion in which case we always return false - i.e. remove commercial during remux stage
            _copyLOGFile = configProfileIni.ReadBoolean(_conversionOptions.profile, "CopyLogFile", false); // Check if the user wants to save the log file generated by Comskip
            _copyPropertiesFile = configProfileIni.ReadBoolean(_conversionOptions.profile, "CopyPropertiesFile", false); // Check if the user wants to save the properties file for SageTV metadata

            if (configProfileIni.ReadString(_conversionOptions.profile, "AutoDeinterlace", "default") == "default")
                _autoDeinterlace = _conversionOptions.autoDeInterlace;
            else
                _autoDeinterlace = configProfileIni.ReadBoolean(_conversionOptions.profile, "AutoDeinterlace", false);

            if (_conversionOptions.renameOnly)
                _commercialSkipCut = true; //no cutting if we are renaming only
            else if (configProfileIni.ReadString(_conversionOptions.profile, "CommercialSkipCut", "default") == "default")
                _commercialSkipCut = _conversionOptions.commercialSkipCut;
            else _commercialSkipCut = configProfileIni.ReadBoolean(_conversionOptions.profile, "CommercialSkipCut", false);
        }
Exemple #17
0
        /// <summary>
        /// Special function to run Scan Type detection using the IDET video filter.
        /// By default, this will skip 300 seconds into the video and then analyze it for 120 seconds to collect data about the field frames.
        /// You can override the default <paramref name="skipSeconds"/> and <paramref name="analyzeSeconds"/> by putting non 0 values in the respective parameters.
        /// The results are stored in the MFInterlaceDetectionResults (Multi Frame MORE reliable) and SFInterlaceDetectionResults (Single Frame).
        /// When this mode is active, ONLY interlace detection is done, the rest of the MediaInfo is NOT available (null)
        /// Run automatically on initialization
        /// </summary>
        /// <param name="skipSeconds">Number of seconds of the initial video to skip before starting interlace detection (0 for default)</param>
        /// <param name="analyzeSeconds">Number of seconds of the video to analyze for interlace detection (0 for default)</param>
        public FFmpegMediaInfo(string fileName, JobStatus jobStatus, Log jobLog, ulong skipSeconds, ulong analyzeSeconds, bool ignoreSuspend = false)
            : base(fileName, FFMPEG_APP_PATH, jobStatus, jobLog, ignoreSuspend)
        {
            mediaInfo = null; // In this mode, there is no media info
            idetMode = true; // We are running a special mode
            useFFProbe = false; // We are using FFMPEG here not FFProbe
            parseError = true; // In this mode parse error is default until we find what we need
            _success = true; // information always suceeds unless we find an error in the output

            // Check for custom overrides
            if (skipSeconds > 0)
                IDET_SKIP_SECONDS = skipSeconds;

            if (analyzeSeconds > 0)
                IDET_ANALYZE_SECONDS = analyzeSeconds;

            // -probesize 100M -analyzeduration 300M are important to identify broken audio streams in some files
            _Parameters = " -probesize 100M -analyzeduration 300M -y -ss " + IDET_SKIP_SECONDS.ToString(CultureInfo.InvariantCulture) + " -i " + Util.FilePaths.FixSpaces(fileName) + " -vf idet -an -sn -t " + IDET_ANALYZE_SECONDS.ToString(CultureInfo.InvariantCulture) + " -f rawvideo NUL"; // create the format for run the command
            Run();
        }
Exemple #18
0
        /// <summary>
        /// Gets information about the video file and stores it.
        /// The ParseError flag is set if there is an error trying to parse the video information, in which the information available in not reliable.
        /// Run automatically on initialization
        /// </summary>
        /// <param name="ignoreSuspend">Set this if you want to ignore the suspend/pause command, typically used when this function is called from a GUI to prevent a deadlock/hang</param>
        public FFmpegMediaInfo(string fileName, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
            : base(fileName, FFPROBE_APP_PATH, jobStatus, jobLog, ignoreSuspend)
        {
            // Check if FFProbe exists, if not then fallback to FFMpeg
            if (useFFProbe && !File.Exists(_ApplicationPath))
            {
                jobLog.WriteEntry(this, "FFProbe not found, switching to FFMpeg", Log.LogEntryType.Warning);
                _ApplicationPath = Path.Combine(GlobalDefs.AppPath, FFMPEG_APP_PATH);
                useFFProbe = false;
            }

            mediaInfo = new MediaInfo();
            mediaInfo.VideoInfo = new MediaInfo.Video(); // We have only 1 video track per file, audio/subtitle tracks are created and added as detected
            _success = true; // information always suceeds unless we find an error in the output
            // -probesize 100M -analyzeduration 300M are important to identify broken audio streams in some files
            // TODO: FFPROBE -> For now we only process independent streams and ignore streams embedded within programs (-show_programs). This is because streams embedded within programs do not have unique stream ID's and PID's (they repeat within each program). How does MCEBuddy handle mpegts_service_id (programs)?
            if (useFFProbe) // FFPROBE
                _Parameters = " -probesize 100M -analyzeduration 300M -v quiet -print_format json -show_format -show_streams -i " + Util.FilePaths.FixSpaces(fileName); // FFPROBE create the format for run the command
            else // FFMPEG
                _Parameters = " -probesize 100M -analyzeduration 300M -i " + Util.FilePaths.FixSpaces(fileName); // FFMPEG create the format for run the command
            Run();
        }
Exemple #19
0
        /// <summary>
        /// Dumps all media information about file into the log using either FFProbe or FFMPEG, does NOT analyze, parse or store the information
        /// </summary>
        /// <param name="fileName">Filename to dump information about</param>
        public static void DumpFileInformation(string fileName, JobStatus jobStatus, Log jobLog)
        {

            jobLog.WriteEntry("Dumping complete information about the file " + fileName, Log.LogEntryType.Debug);

            // Check if FFProbe exists, if not then fallback to FFMpeg
            string applicationPath = FFPROBE_APP_PATH;
            if (!File.Exists(Path.Combine(GlobalDefs.AppPath, FFPROBE_APP_PATH)))
            {
                jobLog.WriteEntry("FFProbe not found, switching to FFMpeg", Log.LogEntryType.Warning);
                applicationPath = FFMPEG_APP_PATH;
            }

            // -probesize 100M -analyzeduration 300M are important to identify broken audio streams in some files
            string parameters = " -probesize 100M -analyzeduration 300M -i " + Util.FilePaths.FixSpaces(fileName); // FFMPEG create the format for run the command

            Base mediaInfo = new Base(parameters, applicationPath, jobStatus, jobLog);
            mediaInfo.Run(); // Dump it
        }
Exemple #20
0
 /// <summary>
 /// FFMPEG to convert a DVRMS file
 /// </summary>
 /// <param name="Parameters">Parameters to pass to FFMPEG</param>
 /// <param name="DVRMS">Set to true if converting a DVRMS file</param>
 /// <param name="jobStatus">Reference to JobStatus</param>
 /// <param name="jobLog">JobLog</param>
 public FFmpeg(string Parameters, bool DVRMS, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
     : base(Parameters, DVRMS_APP_PATH, jobStatus, jobLog, ignoreSuspend)
 {
     _success = false; //ffmpeg looks for a +ve output so we have a false to begin with
 }
Exemple #21
0
        /// <summary>
        /// Generic function to run a FFMPEG command handle common errors related to FFMPEG conversion
        /// </summary>
        /// <param name="cmdParams">Command parameters to pass to ffmpeg</param>
        /// <param name="outputFile">Exact name of the output file as it appears in the command paramters (including quotes if required)</param>
        /// <param name="checkZeroOutputFileSize">If true, will check output file size and function will return false if the size is 0 or file doesn't exist, false to ignore output filesize and presence</param>
        /// <param name="ffmpegExecutedObject">Returns a pointer to the final executed ffmpeg object</param>
        /// <returns>True if successful</returns>
        public static bool FFMpegExecuteAndHandleErrors(string cmdParams, JobStatus jobStatus, Log jobLog, string outputFile, bool checkZeroOutputFileSize, out FFmpeg ffmpegExecutedObject)
        {
            FFmpeg ffmpeg = new FFmpeg(cmdParams, jobStatus, jobLog);
            ffmpeg.Run();

            // Check if it's a h264_mp4toannexb error, when converting H.264 video to MPEGTS format this can sometimes be an issue
            if (!ffmpeg.Success && ffmpeg.H264MP4ToAnnexBError)
            {
                jobLog.WriteEntry("h264_mp4toannexb error, retying and setting bitstream flag", Log.LogEntryType.Warning);

                // -bsf h264_mp4toannexb is required when this error occurs, put it just before the output filename
                cmdParams = cmdParams.Insert(cmdParams.IndexOf(outputFile), "-bsf h264_mp4toannexb ");
                ffmpeg = new FFmpeg(cmdParams, jobStatus, jobLog);
                ffmpeg.Run();
            }

            // Check if it's a aac_adtstoasc error, when converting AAC Audio from MPEGTS to MP4 format this can sometimes be an issue
            if (!ffmpeg.Success && ffmpeg.AACADTSToASCError)
            {
                jobLog.WriteEntry("aac_adtstoasc error, retying and setting bitstream flag", Log.LogEntryType.Warning);

                // -bsf aac_adtstoasc is required when this error occurs, put it just before the output filename
                cmdParams = cmdParams.Insert(cmdParams.IndexOf(outputFile), "-bsf:a aac_adtstoasc ");
                ffmpeg = new FFmpeg(cmdParams, jobStatus, jobLog);
                ffmpeg.Run();
            }

            // Check if we are asked to check for output filesize only here (generic errors)
            // Otherwise it might an error related to genpts (check if we ran the previous ffmpeg related to h264_mp4toannexb and it succeded) - genpts is done after trying to fix other issues
            if (checkZeroOutputFileSize)
                jobLog.WriteEntry("Checking output file size [KB] -> " + (Util.FileIO.FileSize(outputFile) / 1024).ToString("N", System.Globalization.CultureInfo.InvariantCulture), Log.LogEntryType.Debug);

            if ((!ffmpeg.Success || (checkZeroOutputFileSize ? (FileIO.FileSize(outputFile) <= 0) : false)) && !cmdParams.Contains("genpts")) // Possible that some combinations used prior to calling this already have genpts in the command line
            {
                jobLog.WriteEntry("Ffmpeg conversion failed, retying using GenPts", Log.LogEntryType.Warning);

                // genpt is required sometimes when -ss is specified before the inputs file, see ffmpeg ticket #2054
                cmdParams = "-fflags +genpts " + cmdParams;
                ffmpeg = new FFmpeg(cmdParams, jobStatus, jobLog);
                ffmpeg.Run();
            }

            // Check again post genpts if it's a h264_mp4toannexb error (if not already done), when converting H.264 video to MPEGTS format this can sometimes be an issue
            if (!ffmpeg.Success && ffmpeg.H264MP4ToAnnexBError && !cmdParams.Contains("h264_mp4toannexb"))
            {
                jobLog.WriteEntry("H264MP4ToAnnexBError error, retying and setting bitstream flag", Log.LogEntryType.Warning);

                // -bsf h264_mp4toannexb is required when this error occurs, put it just before the output filename
                cmdParams = cmdParams.Insert(cmdParams.IndexOf(outputFile), "-bsf h264_mp4toannexb ");
                ffmpeg = new FFmpeg(cmdParams, jobStatus, jobLog);
                ffmpeg.Run();
            }

            // Check again post genpts if it's a aac_adtstoasc error (if not already done), when converting AAC Audio from MPEGTS to MP4 format this can sometimes be an issue
            if (!ffmpeg.Success && ffmpeg.AACADTSToASCError && !cmdParams.Contains("aac_adtstoasc"))
            {
                jobLog.WriteEntry("aac_adtstoasc error, retying and setting bitstream flag", Log.LogEntryType.Warning);

                // -bsf aac_adtstoasc is required when this error occurs, put it just before the output filename
                cmdParams = cmdParams.Insert(cmdParams.IndexOf(outputFile), "-bsf:a aac_adtstoasc ");
                ffmpeg = new FFmpeg(cmdParams, jobStatus, jobLog);
                ffmpeg.Run();
            }

            ffmpegExecutedObject = ffmpeg; // Set the return object to the final run ffmpeg object

            jobLog.WriteEntry("FFMpeg output file size [KB] -> " + (Util.FileIO.FileSize(outputFile) / 1024).ToString("N", System.Globalization.CultureInfo.InvariantCulture), Log.LogEntryType.Debug);

            return (ffmpeg.Success && (checkZeroOutputFileSize ? (FileIO.FileSize(outputFile) > 0) : true));
        }
Exemple #22
0
 /// <summary>
 /// Generic function to run a FFMPEG command handle common errors related to FFMPEG conversion
 /// </summary>
 /// <param name="cmdParams">Command parameters to pass to ffmpeg</param>
 /// <param name="outputFile">Exact name of the output file as it appears in the command paramters (including quotes if required)</param>
 /// <param name="checkZeroOutputFileSize">If true, will check output file size and function will return false if the size is 0 or file doesn't exist, false to ignore output filesize and presence</param>
 /// <returns>True if successful</returns>
 public static bool FFMpegExecuteAndHandleErrors(string cmdParams, JobStatus jobStatus, Log jobLog, string outputFile, bool checkZeroOutputFileSize)
 {
     FFmpeg retFFMpeg; // Dummy
     return FFMpegExecuteAndHandleErrors(cmdParams, jobStatus, jobLog, outputFile, checkZeroOutputFileSize, out retFFMpeg);
 }
Exemple #23
0
 /// <summary>
 /// Generic function to run a FFMPEG command handle common errors related to FFMPEG conversion
 /// </summary>
 /// <param name="cmdParams">Command parameters to pass to ffmpeg</param>
 /// <param name="outputFile">Exact name of the output file as it appears in the command paramters (including quotes if required)</param>
 /// <returns>True if successful</returns>
 public static bool FFMpegExecuteAndHandleErrors(string cmdParams, JobStatus jobStatus, Log jobLog, string outputFile)
 {
     return FFMpegExecuteAndHandleErrors(cmdParams, jobStatus, jobLog, outputFile, true);
 }
Exemple #24
0
 public RemuxSupp(string Parameters, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
     : base(Parameters, APP_PATH, jobStatus, jobLog, ignoreSuspend)
 {
     _success = true; //ReMuxSupp looks for an error in it's handlers so by default we are true
 }
Exemple #25
0
 public AVIDemux(string Parameters, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
     : base(Parameters, APP_PATH, jobStatus, jobLog, ignoreSuspend)
 {
     _success = true;
 }
Exemple #26
0
        public ConvertWithCopy(ConversionJobOptions conversionOptions, string tool, VideoInfo videoFile, JobStatus jobStatus, Log jobLog, Scanner commercialScan)
            : base(conversionOptions, tool, videoFile, jobStatus, jobLog, commercialScan)
        {

        }
Exemple #27
0
 public CCExtractor(string Parameters, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
     : base(Parameters, APP_PATH, jobStatus, jobLog, ignoreSuspend)
 {
     _success = false; //CCExtractor looks for success criteria
 }
Exemple #28
0
        /// <summary>
        /// Base class for starting a custom process with custom parameters and absolute path
        /// </summary>
        /// <param name="showWindow">If false then the window for the custom app is hidden</param>
        /// <param name="parameters">Parameters for the custom process</param>
        /// <param name="appPath">Absolute Path to custom process</param>
        /// <param name="uiAdminSession">True if the app needs to run in UI Session 1</param>
        /// <param name="ignoreSuspend">Don't stop the process if MCEBuddy is suspended by user (useful if app is being called by the GUI or can deadlock)</param>
        public Base(bool showWindow, string parameters, string appPath, bool uiAdminSession, JobStatus jobStatus, Log jobLog, bool ignoreSuspend = false)
        {
            _showWindow = showWindow; // Do we need to hide the window?
            _ApplicationPath = appPath; // Absolute path
            _Parameters = parameters;
            _jobStatus = jobStatus;
            _jobLog = jobLog;
            _uiAdminSessionProcess = uiAdminSession;
            _ignoreSuspend = ignoreSuspend;

            // Set the default, it can be overriden later
            _success = true; // by default for custom apps, there is no output handler to assume success is true
        }
Exemple #29
0
        private string _renameConvertedFileWithOriginalName = ""; // Keep track incase of filename conflict

        protected ConvertBase(ConversionJobOptions conversionOptions, string tool, VideoInfo videoFile, JobStatus jobStatus, Log jobLog, Scanner commercialScan)
            : base (true)
        {
            //Setup log and status
            _jobStatus = jobStatus;
            _jobLog = jobLog;

            //Set the destination paths
            _workingPath = conversionOptions.workingPath;
            Util.FilePaths.CreateDir(_workingPath);

            // Check first up to see if the source video uses an unsupported combination for this profile
            // Container, Video Codec, Audio Codec and whether it was originally a Media Center recording or not
            _videoFile = videoFile;
            _commercialScan = commercialScan;
            if (CheckUnsupported(conversionOptions.profile, tool)) return;

            // Set the input params and get the standard settings
            _maxWidth = conversionOptions.maxWidth;
            _userQuality = conversionOptions.qualityMultiplier;
            _volume = conversionOptions.volumeMultiplier;
            _drc = conversionOptions.drc;
            _startTrim = conversionOptions.startTrim;
            _endTrim = conversionOptions.endTrim;
            _encoderChooseBestAudioTrack = conversionOptions.encoderSelectBestAudioTrack;
            _fps = conversionOptions.FPS;
            _preferHardwareEncoding = conversionOptions.preferHardwareEncoding;

            Ini ini = new Ini(GlobalDefs.ProfileFile);

            // Profile override parameters - if default (i.e. does not exist then use conversion options else use profile parameters)
            if (ini.ReadString(conversionOptions.profile, "2ChannelAudio", "default") == "default")
                _2ChannelAudio = conversionOptions.stereoAudio;
            else
                _2ChannelAudio = ini.ReadBoolean(conversionOptions.profile, "2ChannelAudio", false); // Fix output to 2 channels (from profile)
            
            if (ini.ReadString(conversionOptions.profile, "SkipCropping", "default") == "default")
                _skipCropping = conversionOptions.disableCropping;
            else
                _skipCropping = ini.ReadBoolean(conversionOptions.profile, "SkipCropping", false); // Cropping can be forced in the profile
            
            if (ini.ReadString(conversionOptions.profile, "AutoDeinterlace", "default") == "default")
                _autoDeInterlacing = conversionOptions.autoDeInterlace;
            else
                _autoDeInterlacing = ini.ReadBoolean(conversionOptions.profile, "AutoDeinterlace", false);

            if (conversionOptions.renameOnly)
                _commercialSkipCut = true; //no cutting if we are renaming only
            else if (ini.ReadString(conversionOptions.profile, "CommercialSkipCut", "default") == "default")
                _commercialSkipCut = conversionOptions.commercialSkipCut;
            else _commercialSkipCut = ini.ReadBoolean(conversionOptions.profile, "CommercialSkipCut", false);

            // Profile only parameters
            _fixedResolution = ini.ReadBoolean(conversionOptions.profile, "FixedResolution", false);
            _2Pass = ini.ReadBoolean(conversionOptions.profile, "2pass", false);
            _generalParams = ini.ReadString(conversionOptions.profile, tool + "-general", "");
            _videoParams = ini.ReadString(conversionOptions.profile, tool + "-video", "");
            _audioParams = ini.ReadString(conversionOptions.profile, tool + "-audio", "");
            _extension = _videoFile.Extension = ini.ReadString(conversionOptions.profile, tool + "-ext", "").ToLower().Trim();
            if (string.IsNullOrWhiteSpace(_extension)) // Special case copy converter if there is no specified extension, it will be using the source file extension
                _extension = FilePaths.CleanExt(SourceVideo);
            _remuxTo = _videoFile.RemuxTo = ini.ReadString(conversionOptions.profile, tool + "-remuxto", "").ToLower().Trim();
            _audioDelay = ini.ReadString(conversionOptions.profile, tool + "-audiodelay", "skip").ToLower().Trim();

            if (_audioDelay == "auto") // Use the audio delay specified in the file
                _toolAudioDelay = videoFile.AudioDelay;
            else if (_audioDelay != "skip")
                double.TryParse(_audioDelay, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out _toolAudioDelay);

            if (conversionOptions.audioOffset != 0) // Conversion options Audio Delay takes priority over profile Audio Delay
                _toolAudioDelay = conversionOptions.audioOffset; 

            // Audio select the AC3 audio option if the source video has AC3)
            if (((videoFile.AudioCodec == "ac-3") || (videoFile.AudioCodec == "ac3") || (videoFile.AudioCodec != "e-ac-3") || (videoFile.AudioCodec != "eac3")) && (ini.ReadString(conversionOptions.profile, tool + "-audioac3", "") != ""))
                _audioParams = ini.ReadString(conversionOptions.profile, tool + "-audioac3", _audioParams);

            // E-AC3 test option if the source video has E-AC3 - Not required as mencoder can handle eac3 audio
            /*
            if (videoFile.AudioCodec == "e-ac-3" || _videoFile.AudioCodec != "eac3")
            {
                _audioParams = ini.ReadString(conversionOptions.profile, tool + "-audioeac3", _audioParams);
                if ((_audioParams == "") && (tool == "mencoder"))
                    _audioParams = "-noaudio ";
            }*/

            // Important to use temp name while converting - sometimes the sources files are copied to the working directory and the converted files conflict with teh original filename, compensate. E.g. TS file input, TS file output with Copy converter
            _convertedFile = Path.Combine(_workingPath, Path.GetFileNameWithoutExtension(SourceVideo) + "-converted" + _extension);
            _renameConvertedFileWithOriginalName = Path.Combine(_workingPath, Path.GetFileNameWithoutExtension(SourceVideo) + _extension);
        }
Exemple #30
0
 public TrimVideo(string profile, JobStatus jobStatus, Log jobLog)
 {
     _profile = profile;
     _jobLog = jobLog;
     _jobStatus = jobStatus;
 }