Пример #1
0
        public SaveResult Prepare(string filename, double interval)
        {
            if (imageDescriptor == null)
            {
                throw new NotSupportedException("ImageDescriptor must be set before prepare.");
            }

            this.filename = filename;

            if (writer != null)
            {
                writer.Dispose();
            }

            writer = new MJPEGWriter();

            VideoInfo info = new VideoInfo();

            info.OriginalSize = new Size(imageDescriptor.Width, imageDescriptor.Height);

            string formatString = FilenameHelper.GetFormatStringCapture();

            // If the capture happens at more than 100fps, set the video itself to be at 30fps.
            // This avoids erratic playback because the player can't cope with the framerate, drawback: prevents review in real time.
            // FIXME: fix the player so that it can playback high speed video in real time.
            if (interval < 10)
            {
                interval = 1000.0 / 30;
            }

            SaveResult result = writer.OpenSavingContext(filename, info, formatString, interval);

            return(result);
        }
Пример #2
0
        private void bgWorkerDualSave_DoWork(object sender, DoWorkEventArgs e)
        {
            // This is executed in Worker Thread space. (Do not call any UI methods)
            log.Debug("Saving side by side video.");

            int threadResult = 0;

            // Get first frame outside the loop to set up the saving context.
            long   currentTime = 0;
            Bitmap composite   = GetCompositeImage(currentTime);

            log.DebugFormat("Composite size: {0}.", composite.Size);

            VideoInfo info = new VideoInfo
            {
                ReferenceSize = composite.Size
            };

            string formatString = FilenameHelper.GetFormatString(dualSaveFileName);

            SaveResult result = videoFileWriter.OpenSavingContext(dualSaveFileName, info, formatString, fileFrameInterval);

            if (result != SaveResult.Success)
            {
                e.Result = 2;
                return;
            }

            videoFileWriter.SaveFrame(composite);
            composite.Dispose();

            while (currentTime < commonTimeline.LastTime && !dualSaveCancelled)
            {
                currentTime += commonTimeline.FrameTime;

                if (bgWorkerDualSave.CancellationPending)
                {
                    threadResult      = 1;
                    dualSaveCancelled = true;
                    break;
                }

                composite = GetCompositeImage(currentTime);
                videoFileWriter.SaveFrame(composite);
                composite.Dispose();

                int percent = (int)((double)currentTime * 100 / commonTimeline.LastTime);
                bgWorkerDualSave.ReportProgress(percent);
            }

            if (!dualSaveCancelled)
            {
                threadResult = 0;
            }

            e.Result = threadResult;
        }
Пример #3
0
        public void View_ValidateFilename(string filename)
        {
            bool allowEmpty = true;

            if (!FilenameHelper.IsFilenameValid(filename, allowEmpty))
            {
                ScreenManagerKernel.AlertInvalidFileName();
            }
        }
Пример #4
0
        public SaveResult StartRecord(string filename, double interval)
        {
            //-----------------------
            // Runs on the UI thread.
            //-----------------------

            if (imageDescriptor == null)
            {
                throw new NotSupportedException("ImageDescriptor must be set before prepare.");
            }

            this.filename = filename;

            if (writer != null)
            {
                writer.Dispose();
            }

            writer = new MJPEGWriter();

            VideoInfo info = new VideoInfo();

            info.OriginalSize = new Size(imageDescriptor.Width, imageDescriptor.Height);

            bool   uncompressed = PreferencesManager.CapturePreferences.SaveUncompressedVideo && imageDescriptor.Format != ImageFormat.JPEG;
            string formatString = FilenameHelper.GetFormatStringCapture(uncompressed);

            // If the capture happens too fast or too slow for a regular player, set the video metadata to a more sensible framerate.
            // This avoids erratic playback because the player can't cope with the framerate, drawback: prevents review in real time.
            double hrft         = PreferencesManager.CapturePreferences.HighspeedRecordingFramerateThreshold;
            double srft         = PreferencesManager.CapturePreferences.SlowspeedRecordingFramerateThreshold;
            double fps          = 1000.0 / interval;
            double fileInterval = interval;

            if (fps >= hrft)
            {
                double hrfo = PreferencesManager.CapturePreferences.HighspeedRecordingFramerateOutput;
                fileInterval = 1000.0 / hrfo;
                log.DebugFormat("High speed recording detected, {0:0.###} fps. Forcing output framerate to {1:0.###} fps.", fps, hrfo);
            }
            else if (fps <= srft)
            {
                double srfo = PreferencesManager.CapturePreferences.SlowspeedRecordingFramerateOutput;
                fileInterval = 1000.0 / srfo;
                log.DebugFormat("Slow speed recording detected, {0:0.###} fps. Forcing output framerate to {1:0.###} fps.", fps, srfo);
            }


            log.DebugFormat("Frame budget for writer [{0}]: {1:0.000} ms.", shortId, interval);

            SaveResult result = writer.OpenSavingContext(filename, info, formatString, imageDescriptor.Format, uncompressed, interval, fileInterval);

            recording = true;

            return(result);
        }
Пример #5
0
        private bool FilePathSanityCheck(string path)
        {
            if (cameraGrabber == null)
            {
                return(false);
            }

            if (!FilenameHelper.IsFilenameValid(path, false))
            {
                ScreenManagerKernel.AlertInvalidFileName();
                return(false);
            }

            return(true);
        }
Пример #6
0
        public SaveResult StartRecord(string filename, double interval, ImageRotation rotation)
        {
            //-----------------------
            // Runs on the UI thread.
            //-----------------------

            if (imageDescriptor == null)
            {
                throw new NotSupportedException("ImageDescriptor must be set before prepare.");
            }

            this.filename = filename;

            if (writer != null)
            {
                writer.Dispose();
            }

            writer = new MJPEGWriter();

            VideoInfo info = new VideoInfo();

            info.OriginalSize = new Size(imageDescriptor.Width, imageDescriptor.Height);

            bool   uncompressed = PreferencesManager.CapturePreferences.SaveUncompressedVideo && imageDescriptor.Format != ImageFormat.JPEG;
            string formatString = FilenameHelper.GetFormatStringCapture(uncompressed);
            double fileInterval = CalibrationHelper.ComputeFileFrameInterval(interval);

            log.DebugFormat("Frame budget for writer [{0}]: {1:0.000} ms.", shortId, interval);

            SaveResult result = writer.OpenSavingContext(filename, info, formatString, imageDescriptor.Format, uncompressed, interval, fileInterval, rotation);

            recording = true;

            return(result);
        }
Пример #7
0
        private void bgWorkerSave_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.Name = "Saving";
            BackgroundWorker bgWorker = sender as BackgroundWorker;

            if (!(e.Argument is SavingSettings))
            {
                saveResult = SaveResult.UnknownError;
                e.Result   = 0;
                return;
            }

            SavingSettings settings = (SavingSettings)e.Argument;

            if (settings.ImageRetriever == null || settings.InputFrameInterval < 0 || bgWorker == null)
            {
                saveResult = SaveResult.UnknownError;
                e.Result   = 0;
                return;
            }

            try
            {
                log.DebugFormat("Saving selection [{0}]->[{1}] to: {2}", settings.Section.Start, settings.Section.End, Path.GetFileName(settings.File));

                // TODO it may actually make more sense to split the saving methods for regular
                // save, paused video and diaporama. It will cause inevitable code duplication but better encapsulation and simpler algo.
                // When each save method has its own class and UI panel, it will be a better design.

                if (!settings.PausedVideo)
                {
                    // Take special care for slowmotion, the frame interval can not go down indefinitely.
                    // Use frame duplication when under 8fps.
                    settings.Duplication         = (int)Math.Ceiling(settings.InputFrameInterval / 125.0);
                    settings.KeyframeDuplication = settings.Duplication;
                    settings.OutputFrameInterval = settings.InputFrameInterval / settings.Duplication;
                    if (settings.KeyframesOnly)
                    {
                        settings.EstimatedTotal = metadata.Count * settings.Duplication;
                    }
                    else
                    {
                        settings.EstimatedTotal = videoReader.EstimatedFrames * settings.Duplication;
                    }
                }
                else
                {
                    // For paused video, slow motion is not supported.
                    // InputFrameInterval will have been set to a multiple of the original frame interval.
                    settings.Duplication         = 1;
                    settings.KeyframeDuplication = (int)(settings.InputFrameInterval / metadata.UserInterval);
                    settings.OutputFrameInterval = metadata.UserInterval;

                    long regularFramesTotal = videoReader.EstimatedFrames - metadata.Count;
                    long keyframesTotal     = metadata.Count * settings.KeyframeDuplication;
                    settings.EstimatedTotal = regularFramesTotal + keyframesTotal;
                }

                log.DebugFormat("interval:{0}, duplication:{1}, kf duplication:{2}", settings.OutputFrameInterval, settings.Duplication, settings.KeyframeDuplication);

                videoReader.BeforeFrameEnumeration();
                IEnumerable <Bitmap> images = EnumerateImages(settings);

                VideoFileWriter w            = new VideoFileWriter();
                string          formatString = FilenameHelper.GetFormatString(settings.File);
                saveResult = w.Save(settings, videoReader.Info, formatString, images, bgWorker);
                videoReader.AfterFrameEnumeration();
            }
            catch (Exception exp)
            {
                saveResult = SaveResult.UnknownError;
                log.Error("Unknown error while saving video.");
                log.Error(exp.StackTrace);
            }

            e.Result = 0;
        }