Esempio n. 1
0
        void ProbeScript()
        {
            string avsFileName = null;

            switch (Program.InputType)
            {
                case FileType.Video:
                    // Make our temporary file for the AviSynth script
                    avsFileName = GetTemporaryFile();
                    WriteAvisynthScript(avsFileName, textBoxIn.Text);
                    break;
                case FileType.Avisynth:
                    avsFileName = Program.InputFile;
                    break;
            }

            // ffprobe it
            var ffprobe = new FFprobe(avsFileName);
            avsScriptInfo = ffprobe.Probe();
        }
Esempio n. 2
0
        void SetFile(string path)
        {
            try
            {
                ValidateInputFile(path);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (inputFile != null)
                inputFile.Close();
            UnloadFonts();

            textBoxIn.Text = path;
            string fullPath = Path.GetDirectoryName(path);
            string name = Path.GetFileNameWithoutExtension(path);
            string title = name;
            if (textBoxOut.Text == _autoOutput || textBoxOut.Text == "")
                textBoxOut.Text = _autoOutput = Path.Combine(string.IsNullOrWhiteSpace(Properties.Settings.Default.RememberedFolderOut) ? fullPath : Properties.Settings.Default.RememberedFolderOut, name + ".webm");
            audioDisabled = false;

            progressBarIndexing.Style = ProgressBarStyle.Marquee;
            progressBarIndexing.Value = 30;
            boxIndexingProgress.Text = "";
            panelHideTheOptions.BringToFront();

            buttonGo.Enabled = false;
            buttonPreview.Enabled = false;
            buttonBrowseIn.Enabled = false;
            textBoxIn.Enabled = false;

            inputFile = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);

            // Reset filters
            Filters.ResetFilters();
            DefaultSettings();
            listViewProcessingScript.Clear();
            boxAdvancedScripting.Checked = false; // STUB: this part is weak
            boxAdvancedScripting.Enabled = true;
            textBoxProcessingScript.Hide();
            listViewProcessingScript.Show();

            if (Path.GetExtension(path) == ".avs")
            {
                Program.InputFile = path;
                Program.InputType = FileType.Avisynth;

                BackgroundWorker probebw = new BackgroundWorker();
                probebw.DoWork += delegate(object sender, DoWorkEventArgs e)
                {
                    ProbeScript();
                };
                probebw.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
                {
                    boxAdvancedScripting.Enabled = false;
                    listViewProcessingScript.Enabled = false;
                    showToolTip("You're loading an AviSynth script, so Processing is disabled!", 3000);

                    comboLevels.Enabled = boxDeinterlace.Enabled = boxDenoise.Enabled = false;
                    buttonGo.Enabled = buttonBrowseIn.Enabled = textBoxIn.Enabled = true;
                    toolStripFilterButtonsEnabled(false);
                    panelHideTheOptions.SendToBack();
                };

                labelIndexingProgress.Text = "Probing script...";
                probebw.RunWorkerAsync();
                return;
            }
            else
            {
                Program.InputFile = path;
                Program.InputType = FileType.Video;
                Program.FileMd5 = null;
                listViewProcessingScript.Enabled = true;
                comboLevels.Enabled = boxDeinterlace.Enabled = boxDenoise.Enabled = true;
            }

            GenerateAvisynthScript();

            // Hash some of the file to make sure we didn't index it already
            labelIndexingProgress.Text = "Hashing...";
            logIndexingProgress("Hashing...");
            using (MD5 md5 = MD5.Create())
            using (FileStream stream = File.OpenRead(path))
            {
                var filename = new UTF8Encoding().GetBytes(name);
                var buffer = new byte[4096];

                filename.CopyTo(buffer, 0);
                stream.Read(buffer, filename.Length, 4096 - filename.Length);

                Program.FileMd5 = BitConverter.ToString(md5.ComputeHash(buffer));
                logIndexingProgress("File hash is " + Program.FileMd5.Replace("-", ""));
                _indexFile = Path.Combine(Path.GetTempPath(), Program.FileMd5 + ".ffindex");
            }

            FFMSSharp.Index index = null;
            indexbw = new BackgroundWorker();
            BackgroundWorker extractbw = new BackgroundWorker();

            indexbw.WorkerSupportsCancellation = true;
            indexbw.WorkerReportsProgress = true;
            indexbw.ProgressChanged += new ProgressChangedEventHandler(delegate(object sender, ProgressChangedEventArgs e)
            {
                this.progressBarIndexing.Value = e.ProgressPercentage;
            });
            indexbw.DoWork += delegate(object sender, DoWorkEventArgs e)
            {
                logIndexingProgress("Indexing starting...");
                FFMSSharp.Indexer indexer = new FFMSSharp.Indexer(path, FFMSSharp.Source.Lavf);

                indexer.UpdateIndexProgress += delegate(object sendertwo, FFMSSharp.IndexingProgressChangeEventArgs etwo)
                {
                    indexbw.ReportProgress((int)(((double)etwo.Current / (double)etwo.Total) * 100));
                    indexer.CancelIndexing = indexbw.CancellationPending;
                };

                try
                {
                    if (audioDisabled) // Indexing failed because of the audio, so the user disabled it.
                    {
                        List<int> indexList = new List<int>(); // An empty list means index no tracks.
                        index = indexer.Index(indexList);
                    }
                    else
                    {
                        index = indexer.Index();
                    }
                }
                catch (OperationCanceledException)
                {
                    audioDisabled = false; // This enables us to cancel the bw even if audio was disabled by the user.
                    e.Cancel = true;
                    return;
                }
                catch (Exception error)
                {
                    if (error.Message.StartsWith("Audio format change detected"))
                    {
                        const string message = "\nIf you were planning on making a WebM with audio, I'm afraid that's not going to happen.\nWould you like to index the file without audio?";
                        const string caption = "Error";
                        DialogResult result = DialogResult.Cancel;

                        this.InvokeIfRequired(() =>
                        {
                            result = MessageBox.Show(message, caption, MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                        });

                        audioDisabled = (result == DialogResult.OK);
                    }
                    else
                    {
                        MessageBox.Show(error.Message);
                    }
                    e.Cancel = true;
                    return;
                }

                index.WriteIndex(_indexFile);
            };
            extractbw.DoWork += new DoWorkEventHandler(delegate
            {
                logIndexingProgress("Extraction starting...");

                List<int> videoTracks = new List<int>(), audioTracks = new List<int>();
                for (int i = 0; i < index.NumberOfTracks; i++)
                {
                    switch (index.GetTrack(i).TrackType)
                    {
                        case FFMSSharp.TrackType.Video:
                            videoTracks.Add(i);
                            break;
                        case FFMSSharp.TrackType.Audio:
                            audioTracks.Add(i);
                            break;
                    }
                }

                if (videoTracks.Count == 0)
                    throw new Exception("No video tracks found!");

                else if (videoTracks.Count == 1)
                {
                    videotrack = videoTracks[0];
                }
                else
                {
                    this.InvokeIfRequired(() =>
                    {
                        var dialog = new TrackSelectDialog("Video", videoTracks);
                        logIndexingProgress("Waiting for user input...");
                        dialog.ShowDialog(this);
                        videotrack = dialog.SelectedTrack;
                    });
                }

                if (!audioDisabled)
                {
                    if (audioTracks.Count == 0)
                    {
                        audioDisabled = true;
                    }
                    else if (audioTracks.Count == 1)
                    {
                        audiotrack = audioTracks[0];
                        audioDisabled = false;
                    }
                    else
                    {
                        this.InvokeIfRequired(() =>
                        {
                            var dialog = new TrackSelectDialog("Audio", audioTracks);
                            logIndexingProgress("Waiting for user input...");
                            dialog.ShowDialog(this);
                            audiotrack = dialog.SelectedTrack;
                        });
                        audioDisabled = false;
                    }
                }

                Program.AttachmentDirectory = Path.Combine(Path.GetTempPath(), Program.FileMd5 + ".attachments");
                Directory.CreateDirectory(Program.AttachmentDirectory);

                logIndexingProgress("Probing input file...");
                using (var prober = new FFprobe(Program.InputFile, format: "", argument: "-show_streams -show_format"))
                {
                    string streamInfo = prober.Probe();
                    Program.SubtitleTracks = new Dictionary<int, Tuple<string, SubtitleType, string>>();
                    Program.AttachmentList = new List<string>();

                    using (var s = new StringReader(streamInfo))
                    {
                        var doc = new XPathDocument(s);
                        var attachindex = 0; // mkvextract separates track and attachment indices

                        foreach (XPathNavigator nav in doc.CreateNavigator().Select("//ffprobe/streams/stream"))
                        {
                            int streamindex;
                            string streamtitle;
                            string file;

                            streamindex = int.Parse(nav.GetAttribute("index", ""));

                            switch (nav.GetAttribute("codec_type", ""))
                            {
                                case "video":
                                    if (streamindex != videotrack) break;

                                    // Check if this is a FRAPS yuvj420p video - if so, we need to do something weird here.
                                    if (nav.GetAttribute("codec_name", "") == "fraps" && nav.GetAttribute("pix_fmt", "") == "yuvj420p")
                                    {
                                        logIndexingProgress("Detected yuvj420p FRAPS video, the Color Level fixing setting has been set for you.");
                                        this.InvokeIfRequired(() =>
                                        {
                                            comboLevels.SelectedIndex = 2; // PC -> TV conversion
                                        });
                                        // If we don't do this, the contrast gets f****d.
                                        // See: https://github.com/nixxquality/WebMConverter/issues/89
                                    }

                                    // Probe for sample aspect ratio
                                    string[] sar = null, dar = null;

                                    sar = nav.GetAttribute("sample_aspect_ratio", "").Split(':');
                                    if ((sar[0] == "1" && sar[1] == "1") || (sar[0] == "0" || sar[1] == "0")) break;

                                    dar = nav.GetAttribute("display_aspect_ratio", "").Split(':');

                                    float SarNum, SarDen, DarNum, DarDen;
                                    SarNum = float.Parse(sar[0]);
                                    SarDen = float.Parse(sar[1]);
                                    DarNum = float.Parse(dar[0]);
                                    DarDen = float.Parse(dar[1]);

                                    SarWidth = int.Parse(nav.GetAttribute("width", ""));
                                    SarHeight = int.Parse(nav.GetAttribute("height", ""));
                                    if (DarNum < DarDen)
                                    {
                                        SarHeight = (int)(SarHeight / (SarNum / SarDen));
                                    }
                                    else
                                    {
                                        SarWidth = (int)(SarWidth * (SarNum / SarDen));
                                    }
                                    SarCompensate = true;
                                    logIndexingProgress("We need to compensate for Sample Aspect Ratio, it seems.");

                                    break;
                                case "subtitle": // Extract the subtitle file
                                    // Get a title
                                    streamtitle = nav.GetAttribute("codec_name", "");
                                    SubtitleType type;
                                    string extension;

                                    if (streamtitle == "dvdsub") // Hold on a moment, this is a vobsub!
                                    {
                                        type = SubtitleType.VobSub;
                                        extension = ".idx";
                                    }
                                    else
                                    {
                                        type = SubtitleType.TextSub;
                                        extension = "." + streamtitle; // YOLO
                                    }
                                    
                                    file = Path.Combine(Program.AttachmentDirectory, string.Format("sub{0}{1}", streamindex, extension));
                                    logIndexingProgress(string.Format("Found subtitle track #{0}", streamindex));

                                    if (!File.Exists(file)) // If we didn't extract it already
                                    {
                                        logIndexingProgress("Extracting...");
                                        using (var mkvextract = new MkvExtract(string.Format(@"tracks ""{0}"" ""{1}:{2}""", Program.InputFile, streamindex, file)))
                                        {
                                            mkvextract.Start();
                                            mkvextract.WaitForExit();
                                        }
                                    }
                                    else
                                    {
                                        logIndexingProgress("Already extracted! Skipping...");
                                    }

                                    if (!File.Exists(file)) // Holy shit, it still doesn't exist?
                                        break; // Whatever, skip it.

                                    if (!nav.IsEmptyElement) // There might be a tag element
                                    {
                                        nav.MoveTo(nav.SelectSingleNode(".//tag[@key='title']"));
                                        var titleTag = nav.GetAttribute("value", "");

                                        streamtitle = titleTag == "" ? streamtitle : titleTag;
                                    }

                                    // Save it
                                    Program.SubtitleTracks.Add(streamindex, new Tuple<string, SubtitleType, string>(streamtitle, type, extension));
                                    break;
                                case @"attachment": // Extract the attachment using mkvmerge
                                    nav.MoveTo(nav.SelectSingleNode(".//tag[@key='filename']"));
                                    var filename = nav.GetAttribute("value", "");

                                    nav.MoveToNext();
                                    var mimetype = nav.GetAttribute("value", "");

                                    file = Path.Combine(Program.AttachmentDirectory, filename);
                                    logIndexingProgress(string.Format("Found attachment '{0}'", filename));

                                    attachindex += 1;

                                    if (!mimetype.Contains(@"font"))
                                    {
                                        logIndexingProgress("Not a font! Skipping...");
                                        break;
                                    }

                                    Program.AttachmentList.Add(filename);

                                    if (File.Exists(file)) // Did we extract it already?
                                    {
                                        logIndexingProgress("Already extracted! Skipping...");
                                        break;
                                    }

                                    logIndexingProgress("Extracting...");
                                    using (var mkvextract = new MkvExtract(string.Format(@"attachments ""{0}"" ""{1}:{2}""", Program.InputFile, attachindex, file)))
                                    {
                                        mkvextract.Start();
                                        mkvextract.WaitForExit();
                                    }
                                    break;
                            }
                        }

                        var selectSingleNode = doc.CreateNavigator().SelectSingleNode("//ffprobe/format/tag[@key='title']");
                        if (selectSingleNode != null)
                        {
                            title = selectSingleNode.GetAttribute("value", "");
                            logIndexingProgress("Found title " + title);
                        }
                    }
                }

                Program.VideoSource = index.VideoSource(path, videotrack);
                var frame = Program.VideoSource.GetFrame(0); // We're assuming that the entire video has the same settings here, which should be fine. (These options usually don't vary, I hope.)
                Program.VideoColorRange = frame.ColorRange;
                Program.VideoInterlaced = frame.InterlacedFrame;
                SetSlices(frame.EncodedResolution);
                LoadFonts(msg => logIndexingProgress((string)msg));
            });
            indexbw.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                if (audioDisabled == true && e.Cancelled)
                {
                    indexbw.RunWorkerAsync();
                    return;
                }

                indexing = false;
                buttonGo.Enabled = false;
                buttonGo.Text = "Convert";

                if (e.Cancelled)
                {
                    CancelIndexing();
                }
                else
                {
                    labelIndexingProgress.Text = "Extracting subtitle tracks and attachments...";
                    progressBarIndexing.Value = 30;
                    progressBarIndexing.Style = ProgressBarStyle.Marquee;

                    extractbw.RunWorkerAsync();
                }
            };
            extractbw.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Error != null)
                {
                    CancelIndexing();
                    const string text = "We couldn't find any video tracks!\nPlease use another input file.";
                    const string caption = "ERROR";
                    MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                boxAudio.Enabled = Program.InputHasAudio = true;
                if (audioDisabled)
                {
                    switch (Path.GetExtension(path).ToLower())
                    {
                        case ".png":
                            break;
                        case ".gif":
                            break;
                        case ".jpg":
                            break;
                        case ".jpeg":
                            break;
                        case ".bmp":
                            break;
                        default:
                            const string text = "We couldn't find any audio tracks.\nIf you want sound, please use another input file.\nIf you don't want audio in your output webm, there's nothing to worry about.";
                            const string caption = "FYI";
                            MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Information);
                            break;
                    }
                    boxAudio.Checked = boxAudio.Enabled = Program.InputHasAudio = false;
                }

                buttonGo.Enabled = true;
                buttonPreview.Enabled = true;
                buttonBrowseIn.Enabled = true;
                textBoxIn.Enabled = true;
                toolStripFilterButtonsEnabled(true);

                if (boxTitle.Text == _autoTitle || boxTitle.Text == "")
                    boxTitle.Text = _autoTitle = title;

                if (Program.VideoColorRange == FFMSSharp.ColorRange.MPEG)
                    //boxLevels.Checked = true;
                    if (Program.VideoInterlaced)
                        boxDeinterlace.Checked = true;

                panelHideTheOptions.SendToBack();
            };

            if (File.Exists(_indexFile))
            {
                try
                {
                    index = new FFMSSharp.Index(_indexFile);

                    if (index.BelongsToFile(path))
                    {
                        try
                        {
                            index.GetFirstIndexedTrackOfType(FFMSSharp.TrackType.Audio);
                        }
                        catch (KeyNotFoundException)
                        {
                            audioDisabled = true;
                        }

                        labelIndexingProgress.Text = "Extracting subtitle tracks and attachments...";
                        progressBarIndexing.Value = 30;
                        progressBarIndexing.Style = ProgressBarStyle.Marquee;

                        extractbw.RunWorkerAsync();
                        return;
                    }
                }
                catch
                {
                    File.Delete(_indexFile);
                }
            }

            indexing = true;
            buttonGo.Enabled = true;
            buttonGo.Text = "Cancel";
            progressBarIndexing.Value = 0;
            progressBarIndexing.Style = ProgressBarStyle.Continuous;
            labelIndexingProgress.Text = "Indexing...";
            indexbw.RunWorkerAsync();
        }