Index: /trunk/include/VBox/log.h
===================================================================
--- /trunk/include/VBox/log.h	(revision 75250)
+++ /trunk/include/VBox/log.h	(revision 75251)
@@ -354,4 +354,10 @@
     /** Main group, IBIOSSettings. */
     LOG_GROUP_MAIN_BIOSSETTINGS,
+    /** Main group, ICaptureChangedEvent. */
+    LOG_GROUP_MAIN_CAPTURECHANGEDEVENT,
+    /** Main group, ICaptureSettings. */
+    LOG_GROUP_MAIN_CAPTURESETTINGS,
+    /** Main group, ICaptureScreenSettings. */
+    LOG_GROUP_MAIN_CAPTURESCREENSETTINGS,
     /** Main group, ICanShowWindowEvent. */
     LOG_GROUP_MAIN_CANSHOWWINDOWEVENT,
@@ -662,6 +668,4 @@
     /** Main group, IVFSExplorer. */
     LOG_GROUP_MAIN_VFSEXPLORER,
-    /** Main group, IVideoCaptureChangedEvent. */
-    LOG_GROUP_MAIN_VIDEOCAPTURECHANGEDEVENT,
     /** Main group, IVirtualBox. */
     LOG_GROUP_MAIN_VIRTUALBOX,
@@ -1000,4 +1004,7 @@
     "MAIN_BANDWIDTHGROUPCHANGEDEVENT", \
     "MAIN_BIOSSETTINGS", \
+    "MAIN_CAPTURECHANGEDEVENT", \
+    "MAIN_CAPTURESETTINGS", \
+    "MAIN_CAPTURESCREENSETTINGS", \
     "MAIN_CANSHOWWINDOWEVENT", \
     "MAIN_CERTIFICATE", \
Index: /trunk/include/VBox/settings.h
===================================================================
--- /trunk/include/VBox/settings.h	(revision 75250)
+++ /trunk/include/VBox/settings.h	(revision 75251)
@@ -18,5 +18,5 @@
 
 /*
- * Copyright (C) 2007-2017 Oracle Corporation
+ * Copyright (C) 2007-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -481,4 +481,95 @@
 };
 
+/** List for keeping a capturing feature list. */
+typedef std::map<CaptureFeature_T, bool> CaptureFeatureMap;
+
+class CaptureScreenSettings
+{
+public:
+
+    CaptureScreenSettings();
+
+    virtual ~CaptureScreenSettings();
+
+    void applyDefaults(void);
+
+    bool areDefaultSettings(void) const;
+
+    bool isFeatureEnabled(CaptureFeature_T enmFeature) const;
+
+    bool operator==(const CaptureScreenSettings &d) const;
+
+    bool                 fEnabled;       // requires settings version 1.14 (VirtualBox 4.3)
+    CaptureDestination_T enmDest;        // new since VirtualBox 6.0.
+    CaptureFeatureMap    featureMap;     // new since VirtualBox 6.0.
+    uint32_t             ulMaxTimeS;     // requires settings version 1.14 (VirtualBox 4.3)
+    com::Utf8Str         strOptions;     // new since VirtualBox 5.2.
+
+    struct Audio
+    {
+        Audio()
+            : enmAudioCodec(CaptureAudioCodec_Opus)
+            , uHz(22050)
+            , cBits(16)
+            , cChannels(2) { }
+
+        /** The audio codec type to use. */
+        CaptureAudioCodec_T enmAudioCodec; // new since VirtualBox 6.0.
+        /** Hz rate. */
+        uint16_t            uHz;           // new since VirtualBox 6.0.
+        /** Bits per sample. */
+        uint8_t             cBits;         // new since VirtualBox 6.0.
+        /** Number of audio channels. */
+        uint8_t             cChannels;     // new since VirtualBox 6.0.
+    } Audio;
+
+    struct Video
+    {
+        Video()
+            : enmCodec(CaptureVideoCodec_VP8)
+            , ulWidth(1024)
+            , ulHeight(768)
+            , ulRate(512)
+            , ulFPS(25) { }
+
+        CaptureVideoCodec_T  enmCodec;  // new since VirtualBox 6.0.
+        uint32_t             ulWidth;   // requires settings version 1.14 (VirtualBox 4.3)
+        uint32_t             ulHeight;  // requires settings version 1.14 (VirtualBox 4.3)
+        uint32_t             ulRate;    // requires settings version 1.14 (VirtualBox 4.3)
+        uint32_t             ulFPS;     // requires settings version 1.14 (VirtualBox 4.3)
+    } Video;
+
+    struct File
+    {
+        File()
+            : ulMaxSizeMB(0) { }
+
+        uint32_t     ulMaxSizeMB; // requires settings version 1.14 (VirtualBox 4.3)
+        com::Utf8Str strName;     // requires settings version 1.14 (VirtualBox 4.3)
+    } File;
+};
+
+/** Map for keeping settings per virtual screen. */
+typedef std::map<unsigned long, CaptureScreenSettings> CaptureScreenMap;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct CaptureSettings
+{
+    CaptureSettings();
+
+    void applyDefaults(void);
+
+    bool areDefaultSettings(void) const;
+
+    bool operator==(const CaptureSettings &d) const;
+
+    bool             fEnabled;       // requires settings version 1.14 (VirtualBox 4.3)
+    CaptureScreenMap mapScreens;
+};
+
 /**
  * NOTE: If you add any fields in here, you must update a) the constructor and b)
@@ -890,5 +981,4 @@
     bool areBootOrderDefaultSettings() const;
     bool areDisplayDefaultSettings() const;
-    bool areVideoCaptureDefaultSettings() const;
     bool areAllNetworkAdaptersDefaultSettings(SettingsVersion_T sv) const;
 
@@ -937,15 +1027,4 @@
                         fAccelerate2DVideo;     // requires settings version 1.8 (VirtualBox 3.1)
 
-    uint32_t            ulVideoCaptureHorzRes;  // requires settings version 1.14 (VirtualBox 4.3)
-    uint32_t            ulVideoCaptureVertRes;  // requires settings version 1.14 (VirtualBox 4.3)
-    uint32_t            ulVideoCaptureRate;     // requires settings version 1.14 (VirtualBox 4.3)
-    uint32_t            ulVideoCaptureFPS;      // requires settings version 1.14 (VirtualBox 4.3)
-    uint32_t            ulVideoCaptureMaxTime;  // requires settings version 1.14 (VirtualBox 4.3)
-    uint32_t            ulVideoCaptureMaxSize;  // requires settings version 1.14 (VirtualBox 4.3)
-    bool                fVideoCaptureEnabled;   // requires settings version 1.14 (VirtualBox 4.3)
-    uint64_t            u64VideoCaptureScreens; // requires settings version 1.14 (VirtualBox 4.3)
-    com::Utf8Str        strVideoCaptureFile;    // requires settings version 1.14 (VirtualBox 4.3)
-    com::Utf8Str        strVideoCaptureOptions; // new since VirtualBox 5.2.
-
     FirmwareType_T      firmwareType;           // requires settings version 1.9 (VirtualBox 3.1)
 
@@ -962,4 +1041,5 @@
 
     BIOSSettings        biosSettings;
+    CaptureSettings     captureSettings;
     USB                 usbSettings;
     NetworkAdaptersList llNetworkAdapters;
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2017 Oracle Corporation
+ * Copyright (C) 2006-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -395,9 +395,9 @@
         /* get the associated console */
         CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
+        if (!console)
+            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Machine '%s' is not currently running", a->argv[0]);
+
         /* ... and session machine */
         CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
-
-        if (!console)
-            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Machine '%s' is not currently running", a->argv[0]);
 
         /* which command? */
@@ -1855,12 +1855,7 @@
         }
 #ifdef VBOX_WITH_VIDEOREC
-        /*
-         * Note: Commands starting with "vcp" are the deprecated versions and are
-         *       kept to ensure backwards compatibility.
-         */
-        else if (   !strcmp(a->argv[1], "videocap")
-                 || !strcmp(a->argv[1], "vcpenabled"))
-        {
-            if (a->argc != 3)
+        else if (!strcmp(a->argv[1], "capture"))
+        {
+            if (a->argc < 3)
             {
                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
@@ -1868,223 +1863,215 @@
                 break;
             }
-            if (!strcmp(a->argv[2], "on"))
-            {
-                CHECK_ERROR_RET(sessionMachine, COMSETTER(VideoCaptureEnabled)(TRUE), RTEXITCODE_FAILURE);
-            }
-            else if (!strcmp(a->argv[2], "off"))
-            {
-                CHECK_ERROR_RET(sessionMachine, COMSETTER(VideoCaptureEnabled)(FALSE), RTEXITCODE_FAILURE);
-            }
-            else
-            {
-                errorArgument("Invalid state '%s'", Utf8Str(a->argv[2]).c_str());
-                rc = E_FAIL;
-                break;
-            }
-        }
-        else if (   !strcmp(a->argv[1], "videocapscreens")
-                 || !strcmp(a->argv[1], "vcpscreens"))
-        {
-            ULONG cMonitors = 64;
-            CHECK_ERROR_BREAK(machine, COMGETTER(MonitorCount)(&cMonitors));
-            com::SafeArray<BOOL> saScreens(cMonitors);
-            if (   a->argc == 3
-                && !strcmp(a->argv[2], "all"))
-            {
-                /* enable all screens */
-                for (unsigned i = 0; i < cMonitors; i++)
-                    saScreens[i] = true;
-            }
-            else if (   a->argc == 3
-                     && !strcmp(a->argv[2], "none"))
-            {
-                /* disable all screens */
-                for (unsigned i = 0; i < cMonitors; i++)
-                    saScreens[i] = false;
-
-                /** @todo r=andy What if this is specified? */
-            }
-            else
-            {
-                /* enable selected screens */
-                for (unsigned i = 0; i < cMonitors; i++)
-                    saScreens[i] = false;
-                for (int i = 2; SUCCEEDED(rc) && i < a->argc; i++)
-                {
-                    uint32_t iScreen;
-                    int vrc = RTStrToUInt32Ex(a->argv[i], NULL, 0, &iScreen);
-                    if (vrc != VINF_SUCCESS)
-                    {
-                        errorArgument("Error parsing display number '%s'", a->argv[i]);
-                        rc = E_FAIL;
-                        break;
-                    }
-                    if (iScreen >= cMonitors)
-                    {
-                        errorArgument("Invalid screen ID specified '%u'", iScreen);
-                        rc = E_FAIL;
-                        break;
-                    }
-                    saScreens[iScreen] = true;
-                }
-            }
-
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureScreens)(ComSafeArrayAsInParam(saScreens)));
-        }
-        else if (   !strcmp(a->argv[1], "videocapfile")
-                 || !strcmp(a->argv[1], "vcpfile"))
-        {
-            if (a->argc != 3)
-            {
-                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
-                rc = E_FAIL;
-                break;
-            }
-
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureFile)(Bstr(a->argv[2]).raw()));
-        }
-        else if (!strcmp(a->argv[1], "videocapres"))
-        {
-            if (a->argc != 4)
-            {
-                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
-                rc = E_FAIL;
-                break;
-            }
-
-            uint32_t uVal;
-            int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing width '%s'", a->argv[2]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureWidth)(uVal));
-
-            vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing height '%s'", a->argv[3]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureHeight)(uVal));
-        }
-        else if (!strcmp(a->argv[1], "vcpwidth")) /* Deprecated; keeping for compatibility. */
-        {
-            uint32_t uVal;
-            int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing width '%s'", a->argv[2]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureWidth)(uVal));
-        }
-        else if (!strcmp(a->argv[1], "vcpheight")) /* Deprecated; keeping for compatibility. */
-        {
-            uint32_t uVal;
-            int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing height '%s'", a->argv[2]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureHeight)(uVal));
-        }
-        else if (   !strcmp(a->argv[1], "videocaprate")
-                 || !strcmp(a->argv[1], "vcprate"))
-        {
-            if (a->argc != 3)
-            {
-                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
-                rc = E_FAIL;
-                break;
-            }
-
-            uint32_t uVal;
-            int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing rate '%s'", a->argv[2]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureRate)(uVal));
-        }
-        else if (   !strcmp(a->argv[1], "videocapfps")
-                 || !strcmp(a->argv[1], "vcpfps"))
-        {
-            if (a->argc != 3)
-            {
-                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
-                rc = E_FAIL;
-                break;
-            }
-
-            uint32_t uVal;
-            int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing FPS '%s'", a->argv[2]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureFPS)(uVal));
-        }
-        else if (   !strcmp(a->argv[1], "videocapmaxtime")
-                 || !strcmp(a->argv[1], "vcpmaxtime"))
-        {
-            if (a->argc != 3)
-            {
-                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
-                rc = E_FAIL;
-                break;
-            }
-
-            uint32_t uVal;
-            int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing maximum time '%s'", a->argv[2]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureMaxTime)(uVal));
-        }
-        else if (   !strcmp(a->argv[1], "videocapmaxsize")
-                 || !strcmp(a->argv[1], "vcpmaxsize"))
-        {
-            if (a->argc != 3)
-            {
-                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
-                rc = E_FAIL;
-                break;
-            }
-
-            uint32_t uVal;
-            int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
-            if (RT_FAILURE(vrc))
-            {
-                errorArgument("Error parsing maximum file size '%s'", a->argv[2]);
-                rc = E_FAIL;
-                break;
-            }
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureMaxFileSize)(uVal));
-        }
-        else if (   !strcmp(a->argv[1], "videocapopts")
-                 || !strcmp(a->argv[1], "vcpoptions"))
-        {
-            if (a->argc != 3)
-            {
-                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
-                rc = E_FAIL;
-                break;
-            }
-
-            CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureOptions)(Bstr(a->argv[3]).raw()));
+
+            ComPtr<ICaptureSettings> captureSettings;
+            CHECK_ERROR_BREAK(machine, COMGETTER(CaptureSettings)(captureSettings.asOutParam()));
+
+            SafeIfaceArray <ICaptureScreenSettings> saCaptureScreenScreens;
+            CHECK_ERROR_BREAK(captureSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saCaptureScreenScreens)));
+
+            /* Note: For now all screens have the same configuration. */
+
+            /*
+             * Note: Commands starting with "vcp" are the deprecated versions and are
+             *       kept to ensure backwards compatibility.
+             */
+            if (!strcmp(a->argv[2], "enable"))
+            {
+                CHECK_ERROR_RET(captureSettings, COMSETTER(Enabled)(TRUE), RTEXITCODE_FAILURE);
+            }
+            else if (!strcmp(a->argv[2], "disable"))
+            {
+                CHECK_ERROR_RET(captureSettings, COMSETTER(Enabled)(FALSE), RTEXITCODE_FAILURE);
+            }
+            else if (!strcmp(a->argv[2], "screens"))
+            {
+                ULONG cMonitors = 64;
+                CHECK_ERROR_BREAK(machine, COMGETTER(MonitorCount)(&cMonitors));
+                com::SafeArray<BOOL> saScreens(cMonitors);
+                if (   a->argc == 4
+                    && !strcmp(a->argv[3], "all"))
+                {
+                    /* enable all screens */
+                    for (unsigned i = 0; i < cMonitors; i++)
+                        saScreens[i] = true;
+                }
+                else if (   a->argc == 4
+                         && !strcmp(a->argv[3], "none"))
+                {
+                    /* disable all screens */
+                    for (unsigned i = 0; i < cMonitors; i++)
+                        saScreens[i] = false;
+
+                    /** @todo r=andy What if this is specified? */
+                }
+                else
+                {
+                    /* enable selected screens */
+                    for (unsigned i = 0; i < cMonitors; i++)
+                        saScreens[i] = false;
+                    for (int i = 3; SUCCEEDED(rc) && i < a->argc; i++)
+                    {
+                        uint32_t iScreen;
+                        int vrc = RTStrToUInt32Ex(a->argv[i], NULL, 0, &iScreen);
+                        if (vrc != VINF_SUCCESS)
+                        {
+                            errorArgument("Error parsing display number '%s'", a->argv[i]);
+                            rc = E_FAIL;
+                            break;
+                        }
+                        if (iScreen >= cMonitors)
+                        {
+                            errorArgument("Invalid screen ID specified '%u'", iScreen);
+                            rc = E_FAIL;
+                            break;
+                        }
+                        saScreens[iScreen] = true;
+                    }
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(Enabled)(saScreens[i]));
+            }
+            else if (!strcmp(a->argv[2], "filename"))
+            {
+                if (a->argc != 3)
+                {
+                    errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                    rc = E_FAIL;
+                    break;
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(FileName)(Bstr(a->argv[2]).raw()));
+            }
+            else if (   !strcmp(a->argv[2], "res")
+                     || !strcmp(a->argv[2], "resolution"))
+            {
+                if (a->argc != 5)
+                {
+                    errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                    rc = E_FAIL;
+                    break;
+                }
+
+                uint32_t uVal;
+                int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal);
+                if (RT_FAILURE(vrc))
+                {
+                    errorArgument("Error parsing width '%s'", a->argv[3]);
+                    rc = E_FAIL;
+                    break;
+                }
+
+                vrc = RTStrToUInt32Ex(a->argv[4], NULL, 0, &uVal);
+                if (RT_FAILURE(vrc))
+                {
+                    errorArgument("Error parsing height '%s'", a->argv[4]);
+                    rc = E_FAIL;
+                    break;
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                {
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoWidth)(uVal));
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoHeight)(uVal));
+                }
+            }
+            else if (!strcmp(a->argv[2], "videorate"))
+            {
+                if (a->argc != 4)
+                {
+                    errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                    rc = E_FAIL;
+                    break;
+                }
+
+                uint32_t uVal;
+                int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal);
+                if (RT_FAILURE(vrc))
+                {
+                    errorArgument("Error parsing rate '%s'", a->argv[3]);
+                    rc = E_FAIL;
+                    break;
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoRate)(uVal));
+            }
+            else if (!strcmp(a->argv[2], "videofps"))
+            {
+                if (a->argc != 4)
+                {
+                    errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                    rc = E_FAIL;
+                    break;
+                }
+
+                uint32_t uVal;
+                int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal);
+                if (RT_FAILURE(vrc))
+                {
+                    errorArgument("Error parsing FPS '%s'", a->argv[3]);
+                    rc = E_FAIL;
+                    break;
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoFPS)(uVal));
+            }
+            else if (!strcmp(a->argv[2], "maxtime"))
+            {
+                if (a->argc != 4)
+                {
+                    errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                    rc = E_FAIL;
+                    break;
+                }
+
+                uint32_t uVal;
+                int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal);
+                if (RT_FAILURE(vrc))
+                {
+                    errorArgument("Error parsing maximum time '%s'", a->argv[3]);
+                    rc = E_FAIL;
+                    break;
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(MaxTime)(uVal));
+            }
+            else if (!strcmp(a->argv[2], "maxfilesize"))
+            {
+                if (a->argc != 4)
+                {
+                    errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                    rc = E_FAIL;
+                    break;
+                }
+
+                uint32_t uVal;
+                int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal);
+                if (RT_FAILURE(vrc))
+                {
+                    errorArgument("Error parsing maximum file size '%s'", a->argv[3]);
+                    rc = E_FAIL;
+                    break;
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(MaxFileSize)(uVal));
+            }
+            else if (!strcmp(a->argv[2], "opts"))
+            {
+                if (a->argc != 4)
+                {
+                    errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                    rc = E_FAIL;
+                    break;
+                }
+
+                for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                    CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(Options)(Bstr(a->argv[3]).raw()));
+            }
         }
 #endif /* VBOX_WITH_VIDEOREC */
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 75251)
@@ -713,13 +713,13 @@
 #endif
 #ifdef VBOX_WITH_VIDEOREC
-                     "                            [--videocap on|off]\n"
-                     "                            [--videocapscreens all|<screen ID> [<screen ID> ...]]\n"
-                     "                            [--videocapfile <filename>]\n"
-                     "                            [--videocapres <width> <height>]\n"
-                     "                            [--videocaprate <rate>]\n"
-                     "                            [--videocapfps <fps>]\n"
-                     "                            [--videocapmaxtime <ms>]\n"
-                     "                            [--videocapmaxsize <MB>]\n"
-                     "                            [--videocapopts <key=value> [,<key=value> ...]]\n"
+                     "                            [--capture on|off]\n"
+                     "                            [--capture screens all|<screen ID> [<screen ID> ...]]\n"
+                     "                            [--capture filename <filename>]\n"
+                     "                            [--capture resolution <width> <height>]\n"
+                     "                            [--capture videorate <rate>]\n"
+                     "                            [--capture videofps <fps>]\n"
+                     "                            [--capture maxtime <ms>]\n"
+                     "                            [--capture maxfilesize <MB>]\n"
+                     "                            [--capture opts <key=value> [,<key=value> ...]]\n"
 #endif
                      "                            [--defaultfrontend default|<name>]\n"
@@ -831,12 +831,14 @@
                      "                            setscreenlayout <display> on|primary <xorigin> <yorigin> <xres> <yres> <bpp> | off\n"
                      "                            screenshotpng <file> [display] |\n"
-                     "                            videocap on|off |\n"
-                     "                            videocapscreens all|none|<screen>,[<screen>...] |\n"
-                     "                            videocapfile <file>\n"
-                     "                            videocapres <width>x<height>\n"
-                     "                            videocaprate <rate>\n"
-                     "                            videocapfps <fps>\n"
-                     "                            videocapmaxtime <ms>\n"
-                     "                            videocapmaxsize <MB>\n"
+#ifdef VBOX_WITH_VIDEOREC
+                     "                            capture on|off |\n"
+                     "                            capture screens all|none|<screen>,[<screen>...] |\n"
+                     "                            capture filename <file> |\n"
+                     "                            capture resolution <width>x<height> |\n"
+                     "                            capture videorate <rate> |\n"
+                     "                            capture videofps <fps> |\n"
+                     "                            capture maxtime <s> |\n"
+                     "                            capture maxfilesize <MB> |\n"
+#endif /* VBOX_WITH_VIDEOREC */
                      "                            setcredentials <username>\n"
                      "                                           --passwordfile <file> | <password>\n"
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 75251)
@@ -2379,19 +2379,25 @@
 # endif
 
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureEnabled)(&fCaptureVideo), rc);
-        com::SafeArray<BOOL> screens;
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(screens)), rc);
+        ComPtr<ICaptureSettings> captureSettings;
+        CHECK_ERROR_RET(machine, COMGETTER(CaptureSettings)(captureSettings.asOutParam()), rc);
+
+        SafeIfaceArray <ICaptureScreenSettings> saCaptureScreenScreens;
+        CHECK_ERROR_RET(captureSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saCaptureScreenScreens)), rc);
+
+        /* For now all screens have the same configuration; so take screen 0 and work with that. */
+        ULONG fFeatures;
+        CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(Features)(&fFeatures), rc);
         ULONG Width;
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureWidth)(&Width), rc);
+        CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoWidth)(&Width), rc);
         ULONG Height;
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureHeight)(&Height), rc);
+        CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoHeight)(&Height), rc);
         ULONG Rate;
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureRate)(&Rate), rc);
+        CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoRate)(&Rate), rc);
         ULONG Fps;
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureFPS)(&Fps), rc);
+        CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoFPS)(&Fps), rc);
         Bstr  bstrFile;
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureFile)(bstrFile.asOutParam()), rc);
+        CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(FileName)(bstrFile.asOutParam()), rc);
         Bstr  bstrOptions;
-        CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureOptions)(bstrOptions.asOutParam()), rc);
+        CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(Options)(bstrOptions.asOutParam()), rc);
 
         Utf8Str strOptions(bstrOptions);
@@ -2417,14 +2423,18 @@
 # endif
         szValue[0] = '\0';
-        for (size_t i = 0, off = 0; i < screens.size(); i++)
-            if (screens[i] && off < sizeof(szValue) - 3)
+        for (size_t i = 0, off = 0; i < saCaptureScreenScreens.size(); i++)
+        {
+            BOOL fEnabled;
+            CHECK_ERROR_RET(saCaptureScreenScreens[i], COMGETTER(Enabled)(&fEnabled), rc);
+            if (fEnabled && off < sizeof(szValue) - 3)
                 off += RTStrPrintf(&szValue[off], sizeof(szValue) - off, off ? ",%zu" : "%zu", i);
-        SHOW_UTF8_STRING("videocapscreens", "Capture screens:", szValue);
-        SHOW_BSTR_STRING("videocapfile", "Capture file:", bstrFile);
+        }
+        SHOW_UTF8_STRING("capturescreens", "Capture screens:", szValue);
+        SHOW_BSTR_STRING("capturefilename", "Capture file:", bstrFile);
         RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height);
-        SHOW_UTF8_STRING("videocapres", "Capture dimensions:", szValue);
-        SHOW_ULONG_VALUE("videocaprate", "Capture rate:", Rate, "kbps");
-        SHOW_ULONG_VALUE("videocapfps", "Capture FPS:", Fps, "kbps");
-        SHOW_BSTR_STRING("videocapopts", "Capture options:", bstrOptions);
+        SHOW_UTF8_STRING("captureres", "Capture dimensions:", szValue);
+        SHOW_ULONG_VALUE("capturevideorate", "Capture rate:", Rate, "kbps");
+        SHOW_ULONG_VALUE("capturevideofps", "Capture FPS:", Fps, "kbps");
+        SHOW_BSTR_STRING("captureopts", "Capture options:", bstrOptions);
 
         if (details != VMINFO_MACHINEREADABLE)
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 75251)
@@ -2929,98 +2929,149 @@
 #ifdef VBOX_WITH_VIDEOREC
             case MODIFYVM_CAPTURE:
-            {
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureEnabled)(ValueUnion.f));
-                break;
-            }
+                RT_FALL_THROUGH();
             case MODIFYVM_CAPTURE_SCREENS:
-            {
-                ULONG cMonitors = 64;
-                CHECK_ERROR(sessionMachine, COMGETTER(MonitorCount)(&cMonitors));
-                com::SafeArray<BOOL> screens(cMonitors);
-                if (parseScreens(ValueUnion.psz, &screens))
-                {
-                    errorArgument("Invalid list of screens specified\n");
-                    rc = E_FAIL;
-                    break;
-                }
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureScreens)(ComSafeArrayAsInParam(screens)));
-                break;
-            }
+                RT_FALL_THROUGH();
             case MODIFYVM_CAPTURE_FILENAME:
-            {
-                Bstr bstr;
-                /* empty string will fall through, leaving bstr empty */
-                if (*ValueUnion.psz)
-                {
-                    char szVCFileAbs[RTPATH_MAX] = "";
-                    int vrc = RTPathAbs(ValueUnion.psz, szVCFileAbs, sizeof(szVCFileAbs));
-                    if (RT_FAILURE(vrc))
-                    {
-                        errorArgument("Cannot convert filename \"%s\" to absolute path\n", ValueUnion.psz);
-                        rc = E_FAIL;
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_WIDTH:
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_HEIGHT:
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_VIDEO_RES:
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_VIDEO_RATE:
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_VIDEO_FPS:
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_MAXTIME:
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_MAXSIZE:
+                RT_FALL_THROUGH();
+            case MODIFYVM_CAPTURE_OPTIONS:
+            {
+                ComPtr<ICaptureSettings> captureSettings;
+                CHECK_ERROR_BREAK(machine, COMGETTER(CaptureSettings)(captureSettings.asOutParam()));
+                SafeIfaceArray <ICaptureScreenSettings> saCaptureScreenScreens;
+                CHECK_ERROR_BREAK(captureSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saCaptureScreenScreens)));
+
+                switch (c)
+                {
+                    case MODIFYVM_CAPTURE:
+                    {
+                        CHECK_ERROR(captureSettings, COMSETTER(Enabled)(ValueUnion.f));
                         break;
                     }
-                    bstr = szVCFileAbs;
-                }
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureFile)(bstr.raw()));
-                break;
-            }
-            case MODIFYVM_CAPTURE_WIDTH:
-            {
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureWidth)(ValueUnion.u32));
-                break;
-            }
-            case MODIFYVM_CAPTURE_HEIGHT:
-            {
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureHeight)(ValueUnion.u32));
-                break;
-            }
-            case MODIFYVM_CAPTURE_VIDEO_RES:
-            {
-                uint32_t uWidth = 0;
-                char *pszNext;
-                int vrc = RTStrToUInt32Ex(ValueUnion.psz, &pszNext, 0, &uWidth);
-                if (RT_FAILURE(vrc) || vrc != VWRN_TRAILING_CHARS || !pszNext || *pszNext != 'x')
-                {
-                    errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz);
-                    rc = E_FAIL;
-                    break;
-                }
-                uint32_t uHeight = 0;
-                vrc = RTStrToUInt32Ex(pszNext+1, NULL, 0, &uHeight);
-                if (vrc != VINF_SUCCESS)
-                {
-                    errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz);
-                    rc = E_FAIL;
-                    break;
-                }
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureWidth)(uWidth));
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureHeight)(uHeight));
-                break;
-            }
-            case MODIFYVM_CAPTURE_VIDEO_RATE:
-            {
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureRate)(ValueUnion.u32));
-                break;
-            }
-            case MODIFYVM_CAPTURE_VIDEO_FPS:
-            {
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureFPS)(ValueUnion.u32));
-                break;
-            }
-            case MODIFYVM_CAPTURE_MAXTIME:
-            {
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureMaxTime)(ValueUnion.u32));
-                break;
-            }
-            case MODIFYVM_CAPTURE_MAXSIZE:
-            {
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureMaxFileSize)(ValueUnion.u32));
-                break;
-            }
-            case MODIFYVM_CAPTURE_OPTIONS:
-            {
-                Bstr bstr(ValueUnion.psz);
-                CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureOptions)(bstr.raw()));
+                    case MODIFYVM_CAPTURE_SCREENS:
+                    {
+                        ULONG cMonitors = 64;
+                        CHECK_ERROR(sessionMachine, COMGETTER(MonitorCount)(&cMonitors));
+                        com::SafeArray<BOOL> screens(cMonitors);
+                        if (parseScreens(ValueUnion.psz, &screens))
+                        {
+                            errorArgument("Invalid list of screens specified\n");
+                            rc = E_FAIL;
+                            break;
+                        }
+
+                        if (cMonitors > saCaptureScreenScreens.size()) /* Paranoia. */
+                            cMonitors = saCaptureScreenScreens.size();
+
+                        for (size_t i = 0; i < cMonitors; ++i)
+                            CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(Enabled)(screens[i]));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_FILENAME:
+                    {
+                        Bstr bstr;
+                        /* empty string will fall through, leaving bstr empty */
+                        if (*ValueUnion.psz)
+                        {
+                            char szVCFileAbs[RTPATH_MAX] = "";
+                            int vrc = RTPathAbs(ValueUnion.psz, szVCFileAbs, sizeof(szVCFileAbs));
+                            if (RT_FAILURE(vrc))
+                            {
+                                errorArgument("Cannot convert filename \"%s\" to absolute path\n", ValueUnion.psz);
+                                rc = E_FAIL;
+                                break;
+                            }
+                            bstr = szVCFileAbs;
+                        }
+
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(FileName)(bstr.raw()));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_WIDTH:
+                    {
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoWidth)(ValueUnion.u32));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_HEIGHT:
+                    {
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoHeight)(ValueUnion.u32));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_VIDEO_RES:
+                    {
+                        uint32_t uWidth = 0;
+                        char *pszNext;
+                        int vrc = RTStrToUInt32Ex(ValueUnion.psz, &pszNext, 0, &uWidth);
+                        if (RT_FAILURE(vrc) || vrc != VWRN_TRAILING_CHARS || !pszNext || *pszNext != 'x')
+                        {
+                            errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz);
+                            rc = E_FAIL;
+                            break;
+                        }
+                        uint32_t uHeight = 0;
+                        vrc = RTStrToUInt32Ex(pszNext+1, NULL, 0, &uHeight);
+                        if (vrc != VINF_SUCCESS)
+                        {
+                            errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz);
+                            rc = E_FAIL;
+                            break;
+                        }
+
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                        {
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoWidth)(uWidth));
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoHeight)(uHeight));
+                        }
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_VIDEO_RATE:
+                    {
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoRate)(ValueUnion.u32));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_VIDEO_FPS:
+                    {
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoFPS)(ValueUnion.u32));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_MAXTIME:
+                    {
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(MaxTime)(ValueUnion.u32));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_MAXSIZE:
+                    {
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(MaxFileSize)(ValueUnion.u32));
+                        break;
+                    }
+                    case MODIFYVM_CAPTURE_OPTIONS:
+                    {
+                        Bstr bstr(ValueUnion.psz);
+                        for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i)
+                            CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(Options)(bstr.raw()));
+                        break;
+                    }
+                }
+
                 break;
             }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp	(revision 75251)
@@ -1403,5 +1403,5 @@
         case IndicatorType_SharedFolders: strResult = "SharedFolders"; break;
         case IndicatorType_Display:       strResult = "Display"; break;
-        case IndicatorType_VideoCapture:  strResult = "VideoCapture"; break;
+        case IndicatorType_Capture:       strResult = "VideoCapture"; break;
         case IndicatorType_Features:      strResult = "Features"; break;
         case IndicatorType_Mouse:         strResult = "Mouse"; break;
@@ -1430,5 +1430,5 @@
     keys << "SharedFolders"; values << IndicatorType_SharedFolders;
     keys << "Display";       values << IndicatorType_Display;
-    keys << "VideoCapture";  values << IndicatorType_VideoCapture;
+    keys << "VideoCapture";  values << IndicatorType_Capture;
     keys << "Features";      values << IndicatorType_Features;
     keys << "Mouse";         values << IndicatorType_Mouse;
@@ -1455,5 +1455,5 @@
         case IndicatorType_SharedFolders: strResult = QApplication::translate("VBoxGlobal", "Shared Folders", "IndicatorType"); break;
         case IndicatorType_Display:       strResult = QApplication::translate("VBoxGlobal", "Display", "IndicatorType"); break;
-        case IndicatorType_VideoCapture:  strResult = QApplication::translate("VBoxGlobal", "Video Capture", "IndicatorType"); break;
+        case IndicatorType_Capture:  strResult = QApplication::translate("VBoxGlobal", "Video Capture", "IndicatorType"); break;
         case IndicatorType_Features:      strResult = QApplication::translate("VBoxGlobal", "Features", "IndicatorType"); break;
         case IndicatorType_Mouse:         strResult = QApplication::translate("VBoxGlobal", "Mouse", "IndicatorType"); break;
@@ -1481,5 +1481,5 @@
         case IndicatorType_SharedFolders: return UIIconPool::iconSet(":/sf_16px.png");
         case IndicatorType_Display:       return UIIconPool::iconSet(":/display_software_16px.png");
-        case IndicatorType_VideoCapture:  return UIIconPool::iconSet(":/video_capture_16px.png");
+        case IndicatorType_Capture:  return UIIconPool::iconSet(":/video_capture_16px.png");
         case IndicatorType_Features:      return UIIconPool::iconSet(":/vtx_amdv_16px.png");
         case IndicatorType_Mouse:         return UIIconPool::iconSet(":/mouse_16px.png");
Index: /trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h	(revision 75251)
@@ -765,5 +765,5 @@
     IndicatorType_SharedFolders,
     IndicatorType_Display,
-    IndicatorType_VideoCapture,
+    IndicatorType_Capture,
     IndicatorType_Features,
     IndicatorType_Mouse,
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.cpp	(revision 75251)
@@ -3307,6 +3307,6 @@
     m_pool[UIActionIndexRT_M_View_S_TakeScreenshot] = new UIActionSimpleRuntimePerformTakeScreenshot(this);
     m_pool[UIActionIndexRT_M_View_M_VideoCapture] = new UIActionMenuRuntimeVideoCapture(this);
-    m_pool[UIActionIndexRT_M_View_M_VideoCapture_S_Settings] = new UIActionSimpleRuntimeShowVideoCaptureSettings(this);
-    m_pool[UIActionIndexRT_M_View_M_VideoCapture_T_Start] = new UIActionToggleRuntimeVideoCapture(this);
+    m_pool[UIActionIndexRT_M_View_M_Capture_S_Settings] = new UIActionSimpleRuntimeShowVideoCaptureSettings(this);
+    m_pool[UIActionIndexRT_M_View_M_Capture_T_Start] = new UIActionToggleRuntimeVideoCapture(this);
     m_pool[UIActionIndexRT_M_View_T_VRDEServer] = new UIActionToggleRuntimeVRDEServer(this);
     m_pool[UIActionIndexRT_M_View_M_MenuBar] = new UIActionMenuRuntimeMenuBar(this);
@@ -3662,5 +3662,5 @@
     updateMenuViewVideoCapture();
     /* 'Video Capture Start' action: */
-    fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)) || fSeparator;
+    fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_Capture_T_Start)) || fSeparator;
     /* 'VRDE Server' action: */
     fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_T_VRDEServer)) || fSeparator;
@@ -3777,5 +3777,5 @@
 
     /* 'Video Capture Settings' action: */
-    fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_VideoCapture_S_Settings)) || fSeparator;
+    fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_Capture_S_Settings)) || fSeparator;
 
     /* Separator: */
@@ -3787,5 +3787,5 @@
 
     /* 'Start Video Capture' action: */
-    fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)) || fSeparator;
+    fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_Capture_T_Start)) || fSeparator;
 
     /* Mark menu as valid: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.h	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.h	(revision 75251)
@@ -65,6 +65,6 @@
     UIActionIndexRT_M_View_S_TakeScreenshot,
     UIActionIndexRT_M_View_M_VideoCapture,
-    UIActionIndexRT_M_View_M_VideoCapture_S_Settings,
-    UIActionIndexRT_M_View_M_VideoCapture_T_Start,
+    UIActionIndexRT_M_View_M_Capture_S_Settings,
+    UIActionIndexRT_M_View_M_Capture_T_Start,
     UIActionIndexRT_M_View_T_VRDEServer,
     UIActionIndexRT_M_View_M_MenuBar,
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.cpp	(revision 75251)
@@ -375,7 +375,7 @@
             break;
         }
-        case KVBoxEventType_OnVideoCaptureChanged:
-        {
-            emit sigVideoCaptureChange();
+        case KVBoxEventType_OnCaptureChanged:
+        {
+            emit sigCaptureChange();
             break;
         }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.h	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.h	(revision 75251)
@@ -124,6 +124,6 @@
         /** Notifies about VRDE device state change. */
         void sigVRDEChange();
-        /** Notifies about Video Capture device state change. */
-        void sigVideoCaptureChange();
+        /** Notifies about capture state change. */
+        void sigCaptureChange();
         /** Notifies about USB controller state change. */
         void sigUSBControllerChange();
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp	(revision 75251)
@@ -570,5 +570,5 @@
 }
 
-void UIPopupCenter::cannotToggleVideoCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable)
+void UIPopupCenter::cannotToggleCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable)
 {
     /* Get machine-name preserving error-info: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.h	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.h	(revision 75251)
@@ -162,5 +162,5 @@
     void cannotDetachWebCam(QWidget *pParent, const CEmulatedUSB &comDispatcher,
                             const QString &strWebCamName, const QString &strMachineName);
-    void cannotToggleVideoCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable);
+    void cannotToggleCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable);
     void cannotToggleVRDEServer(QWidget *pParent,  const CVRDEServer &comServer,
                                 const QString &strMachineName, bool fEnable);
Index: /trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElements.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElements.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElements.cpp	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012-2017 Oracle Corporation
+ * Copyright (C) 2012-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -44,4 +44,6 @@
 # include "CMediumAttachment.h"
 # include "CAudioAdapter.h"
+# include "CCaptureSettings.h"
+# include "CCaptureScreenSettings.h"
 # include "CNetworkAdapter.h"
 # include "CSerialPort.h"
@@ -447,16 +449,22 @@
         }
 
-        /* Video Capture info: */
-        if (machine.GetVideoCaptureEnabled())
-        {
+        /* Capture info: */
+        CCaptureSettings captureSettings = machine.GetCaptureSettings();
+        if (captureSettings.GetEnabled())
+        {
+            /* For now all screens have the same config: */
+            CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0);
+
+            /** @todo r=andy Refine these texts (wrt audio and/or video). */
             table << UITextTableLine(QApplication::translate("UIDetails", "Video Capture File", "details (display/video capture)"),
-                                     machine.GetVideoCaptureFile());
+                                     captureScreen0Settings.GetFileName());
             table << UITextTableLine(QApplication::translate("UIDetails", "Video Capture Attributes", "details (display/video capture)"),
                                      QApplication::translate("UIDetails", "Frame Size: %1x%2, Frame Rate: %3fps, Bit Rate: %4kbps")
-                                         .arg(machine.GetVideoCaptureWidth()).arg(machine.GetVideoCaptureHeight())
-                                         .arg(machine.GetVideoCaptureFPS()).arg(machine.GetVideoCaptureRate()));
+                                         .arg(captureScreen0Settings.GetVideoWidth()).arg(captureScreen0Settings.GetVideoHeight())
+                                         .arg(captureScreen0Settings.GetVideoFPS()).arg(captureScreen0Settings.GetVideoRate()));
         }
         else
         {
+            /** @todo r=andy Refine these texts (wrt audio and/or video). */
             table << UITextTableLine(QApplication::translate("UIDetails", "Video Capture", "details (display/video capture)"),
                                      QApplication::translate("UIDetails", "Disabled", "details (display/video capture)"));
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIConsoleEventHandler.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIConsoleEventHandler.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIConsoleEventHandler.cpp	(revision 75251)
@@ -188,5 +188,5 @@
         << KVBoxEventType_OnVRDEServerChanged
         << KVBoxEventType_OnVRDEServerInfoChanged
-        << KVBoxEventType_OnVideoCaptureChanged
+        << KVBoxEventType_OnCaptureChanged
         << KVBoxEventType_OnUSBControllerChanged
         << KVBoxEventType_OnUSBDeviceStateChanged
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2010-2017 Oracle Corporation
+ * Copyright (C) 2010-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -43,4 +43,6 @@
 /* COM includes: */
 # include "CAudioAdapter.h"
+# include "CCaptureSettings.h"
+# include "CCaptureScreenSettings.h"
 # include "CConsole.h"
 # include "CMachine.h"
@@ -781,5 +783,5 @@
 
 /** UISessionStateStatusBarIndicator extension for Runtime UI: Video-capture indicator. */
-class UIIndicatorVideoCapture : public UISessionStateStatusBarIndicator
+class UIIndicatorCapture : public UISessionStateStatusBarIndicator
 {
     Q_OBJECT;
@@ -788,18 +790,18 @@
     Q_PROPERTY(double rotationAngle READ rotationAngle WRITE setRotationAngle);
 
-    /** Video-capture states. */
-    enum UIIndicatorStateVideoCapture
-    {
-        UIIndicatorStateVideoCapture_Disabled = 0,
-        UIIndicatorStateVideoCapture_Enabled  = 1,
-        UIIndicatorStateVideoCapture_Paused   = 2
+    /** Capture states. */
+    enum UIIndicatorStateCapture
+    {
+        UIIndicatorStateCapture_Disabled = 0,
+        UIIndicatorStateCapture_Enabled  = 1,
+        UIIndicatorStateCapture_Paused   = 2
     };
 
-    /** Video-capture modes. */
-    enum UIIndicatorStateVideoCaptureMode
-    {
-        UIIndicatorStateVideoCaptureMode_None   = RT_BIT(0),
-        UIIndicatorStateVideoCaptureMode_Video  = RT_BIT(1),
-        UIIndicatorStateVideoCaptureMode_Audio  = RT_BIT(2)
+    /** Capture modes. */
+    enum UIIndicatorStateCaptureMode
+    {
+        UIIndicatorStateCaptureMode_None   = RT_BIT(0),
+        UIIndicatorStateCaptureMode_Video  = RT_BIT(1),
+        UIIndicatorStateCaptureMode_Audio  = RT_BIT(2)
     };
 
@@ -807,14 +809,14 @@
 
     /** Constructor, passes @a pSession to the UISessionStateStatusBarIndicator constructor. */
-    UIIndicatorVideoCapture(UISession *pSession)
-        : UISessionStateStatusBarIndicator(IndicatorType_VideoCapture, pSession)
+    UIIndicatorCapture(UISession *pSession)
+        : UISessionStateStatusBarIndicator(IndicatorType_Capture, pSession)
         , m_pAnimation(0)
         , m_dRotationAngle(0)
-        , m_eCaptureMode(UIIndicatorStateVideoCaptureMode_None)
+        , m_eCaptureMode(UIIndicatorStateCaptureMode_None)
     {
         /* Assign state-icons: */
-        setStateIcon(UIIndicatorStateVideoCapture_Disabled, UIIconPool::iconSet(":/video_capture_16px.png"));
-        setStateIcon(UIIndicatorStateVideoCapture_Enabled,  UIIconPool::iconSet(":/movie_reel_16px.png"));
-        setStateIcon(UIIndicatorStateVideoCapture_Paused,   UIIconPool::iconSet(":/movie_reel_16px.png"));
+        setStateIcon(UIIndicatorStateCapture_Disabled, UIIconPool::iconSet(":/video_capture_16px.png"));
+        setStateIcon(UIIndicatorStateCapture_Enabled,  UIIconPool::iconSet(":/movie_reel_16px.png"));
+        setStateIcon(UIIndicatorStateCapture_Paused,   UIIconPool::iconSet(":/movie_reel_16px.png"));
         /* Create *enabled* state animation: */
         m_pAnimation = UIAnimationLoop::installAnimationLoop(this, "rotationAngle",
@@ -833,12 +835,12 @@
         switch (iState)
         {
-            case UIIndicatorStateVideoCapture_Disabled:
+            case UIIndicatorStateCapture_Disabled:
                 m_pAnimation->stop();
                 m_dRotationAngle = 0;
                 break;
-            case UIIndicatorStateVideoCapture_Enabled:
+            case UIIndicatorStateCapture_Enabled:
                 m_pAnimation->start();
                 break;
-            case UIIndicatorStateVideoCapture_Paused:
+            case UIIndicatorStateCapture_Paused:
                 m_pAnimation->stop();
                 break;
@@ -858,5 +860,5 @@
         QPainter painter(this);
         /* Configure painter for *enabled* state: */
-        if (state() == UIIndicatorStateVideoCapture_Enabled)
+        if (state() == UIIndicatorStateCapture_Enabled)
         {
             /* Configure painter for smooth animation: */
@@ -882,10 +884,13 @@
 
         /* Update indicator state early: */
-        if (!machine.GetVideoCaptureEnabled())
-            setState(UIIndicatorStateVideoCapture_Disabled);
+        CCaptureSettings captureSettings = machine.GetCaptureSettings();
+        /* For now all screens have the same config: */
+        CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0);
+        if (!captureScreen0Settings.GetEnabled())
+            setState(UIIndicatorStateCapture_Disabled);
         else if (!fMachinePaused)
-            setState(UIIndicatorStateVideoCapture_Enabled);
+            setState(UIIndicatorStateCapture_Enabled);
         else
-            setState(UIIndicatorStateVideoCapture_Paused);
+            setState(UIIndicatorStateCapture_Paused);
 
         updateCaptureMode();
@@ -895,25 +900,25 @@
         switch (state())
         {
-            case UIIndicatorStateVideoCapture_Disabled:
+            case UIIndicatorStateCapture_Disabled:
             {
-                strFullData += s_strTableRow1
+                strFullData += s_strTableRow1 /** @todo r=andy Refine this tooltip (audio and/or video). */
                     .arg(QApplication::translate("UIIndicatorsPool", "Video capture disabled", "Video capture tooltip"));
                 break;
             }
-            case UIIndicatorStateVideoCapture_Enabled:
-            case UIIndicatorStateVideoCapture_Paused:
+            case UIIndicatorStateCapture_Enabled:
+            case UIIndicatorStateCapture_Paused:
             {
                 QString strToolTip;
-                if ( m_eCaptureMode & UIIndicatorStateVideoCaptureMode_Audio &&
-                    m_eCaptureMode & UIIndicatorStateVideoCaptureMode_Video)
+                if ( m_eCaptureMode & UIIndicatorStateCaptureMode_Audio &&
+                    m_eCaptureMode & UIIndicatorStateCaptureMode_Video)
                     strToolTip = "Video/audio capture file";
-                else if (m_eCaptureMode & UIIndicatorStateVideoCaptureMode_Audio)
+                else if (m_eCaptureMode & UIIndicatorStateCaptureMode_Audio)
                     strToolTip = "Audio capture file";
-                else if (m_eCaptureMode & UIIndicatorStateVideoCaptureMode_Video)
+                else if (m_eCaptureMode & UIIndicatorStateCaptureMode_Video)
                     strToolTip = "Video capture file";
 
-                strFullData += s_strTableRow2
+                strFullData += s_strTableRow2 /** @todo r=andy Refine this tooltip (audio and/or video). */
                     .arg(QApplication::translate("UIIndicatorsPool", strToolTip.toLatin1().constData(), "Video capture tooltip"))
-                    .arg(machine.GetVideoCaptureFile());
+                    .arg(captureScreen0Settings.GetFileName());
                 break;
             }
@@ -935,8 +940,8 @@
     void setRotationAngle(double dRotationAngle) { m_dRotationAngle = dRotationAngle; update(); }
 
-    /* Parses CMachine::videoCaptureOptions and updates m_eCaptureMode accordingly. */
+    /* Parses CaptureScreenSettings::Options and updates m_eCaptureMode accordingly. */
     void updateCaptureMode()
     {
-        m_eCaptureMode = UIIndicatorStateVideoCaptureMode_None;
+        m_eCaptureMode = UIIndicatorStateCaptureMode_None;
 
         /* Get machine: */
@@ -946,5 +951,10 @@
         if (machine.isNull())
             return;
-        QStringList strOptionsPairList = machine.GetVideoCaptureOptions().split(",", QString::SkipEmptyParts);
+
+        CCaptureSettings captureSettings = machine.GetCaptureSettings();
+        /* For now all screens have the same config: */
+        CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0);
+
+        QStringList strOptionsPairList = captureScreen0Settings.GetOptions().split(",", QString::SkipEmptyParts);
 
         for (int i = 0; i < strOptionsPairList.size(); ++i)
@@ -952,9 +962,9 @@
             if (strOptionsPairList.at(i).contains("vc_enabled", Qt::CaseInsensitive) &&
                 strOptionsPairList.at(i).contains("true", Qt::CaseInsensitive))
-                m_eCaptureMode = (UIIndicatorStateVideoCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateVideoCaptureMode_Video);
+                m_eCaptureMode = (UIIndicatorStateCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateCaptureMode_Video);
 
             if (strOptionsPairList.at(i).contains("ac_enabled", Qt::CaseInsensitive) &&
                 strOptionsPairList.at(i).contains("true", Qt::CaseInsensitive))
-                m_eCaptureMode = (UIIndicatorStateVideoCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateVideoCaptureMode_Audio);
+                m_eCaptureMode = (UIIndicatorStateCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateCaptureMode_Audio);
         }
     }
@@ -965,5 +975,5 @@
     double m_dRotationAngle;
 
-    UIIndicatorStateVideoCaptureMode m_eCaptureMode;
+    UIIndicatorStateCaptureMode m_eCaptureMode;
 };
 
@@ -1464,5 +1474,5 @@
                 case IndicatorType_SharedFolders:     m_pool[indicatorType] = new UIIndicatorSharedFolders(m_pSession); break;
                 case IndicatorType_Display:           m_pool[indicatorType] = new UIIndicatorDisplay(m_pSession);       break;
-                case IndicatorType_VideoCapture:      m_pool[indicatorType] = new UIIndicatorVideoCapture(m_pSession);  break;
+                case IndicatorType_Capture:      m_pool[indicatorType] = new UIIndicatorCapture(m_pSession);  break;
                 case IndicatorType_Features:          m_pool[indicatorType] = new UIIndicatorFeatures(m_pSession);      break;
                 case IndicatorType_Mouse:             m_pool[indicatorType] = new UIIndicatorMouse(m_pSession);         break;
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2010-2017 Oracle Corporation
+ * Copyright (C) 2010-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -77,4 +77,5 @@
 /* COM includes: */
 # include "CAudioAdapter.h"
+# include "CCaptureSettings.h"
 # include "CVirtualBoxErrorInfo.h"
 # include "CMachineDebugger.h"
@@ -1052,6 +1053,6 @@
     m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_S_TakeScreenshot));
     m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture));
-    m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_S_Settings));
-    m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start));
+    m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_Capture_S_Settings));
+    m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start));
     m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer));
     m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_MenuBar));
@@ -1136,8 +1137,8 @@
     connect(actionPool()->action(UIActionIndexRT_M_View_S_TakeScreenshot), SIGNAL(triggered()),
             this, SLOT(sltTakeScreenshot()));
-    connect(actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_S_Settings), SIGNAL(triggered()),
-            this, SLOT(sltOpenVideoCaptureOptions()));
-    connect(actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start), SIGNAL(toggled(bool)),
-            this, SLOT(sltToggleVideoCapture(bool)));
+    connect(actionPool()->action(UIActionIndexRT_M_View_M_Capture_S_Settings), SIGNAL(triggered()),
+            this, SLOT(sltOpenCaptureOptions()));
+    connect(actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start), SIGNAL(toggled(bool)),
+            this, SLOT(sltToggleCapture(bool)));
     connect(actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer), SIGNAL(toggled(bool)),
             this, SLOT(sltToggleVRDE(bool)));
@@ -2090,5 +2091,5 @@
 }
 
-void UIMachineLogic::sltOpenVideoCaptureOptions()
+void UIMachineLogic::sltOpenCaptureOptions()
 {
     /* Open VM settings : Display page : Video Capture tab: */
@@ -2096,5 +2097,5 @@
 }
 
-void UIMachineLogic::sltToggleVideoCapture(bool fEnabled)
+void UIMachineLogic::sltToggleCapture(bool fEnabled)
 {
     /* Do not process if window(s) missed! */
@@ -2103,15 +2104,16 @@
 
     /* Make sure something had changed: */
-    if (machine().GetVideoCaptureEnabled() == static_cast<BOOL>(fEnabled))
+    CCaptureSettings captureSettings = machine().GetCaptureSettings();
+    if (captureSettings.GetEnabled() == static_cast<BOOL>(fEnabled))
         return;
 
     /* Update Video Capture state: */
-    machine().SetVideoCaptureEnabled(fEnabled);
-    if (!machine().isOk())
+    captureSettings.SetEnabled(fEnabled);
+    if (!captureSettings.isOk())
     {
         /* Make sure action is updated: */
-        uisession()->updateStatusVideoCapture();
+        uisession()->updateStatusCapture();
         /* Notify about the error: */
-        return popupCenter().cannotToggleVideoCapture(activeMachineWindow(), machine(), fEnabled);
+        return popupCenter().cannotToggleCapture(activeMachineWindow(), machine(), fEnabled);
     }
 
@@ -2121,5 +2123,5 @@
     {
         /* Make sure action is updated: */
-        uisession()->updateStatusVideoCapture();
+        uisession()->updateStatusCapture();
         /* Notify about the error: */
         return msgCenter().cannotSaveMachineSettings(machine());
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h	(revision 75251)
@@ -291,6 +291,6 @@
     void sltToggleGuestAutoresize(bool fEnabled);
     void sltTakeScreenshot();
-    void sltOpenVideoCaptureOptions();
-    void sltToggleVideoCapture(bool fEnabled);
+    void sltOpenCaptureOptions();
+    void sltToggleCapture(bool fEnabled);
     void sltToggleVRDE(bool fEnabled);
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp	(revision 75251)
@@ -60,4 +60,5 @@
 /* COM includes: */
 # include "CAudioAdapter.h"
+# include "CCaptureSettings.h"
 # include "CSystemProperties.h"
 # include "CStorageController.h"
@@ -721,13 +722,15 @@
 }
 
-void UISession::sltVideoCaptureChange()
-{
-    /* Check/Uncheck Video Capture action depending on feature status: */
-    actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(true);
-    actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->setChecked(machine().GetVideoCaptureEnabled());
-    actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(false);
-
-    /* Notify listeners about Video Capture change: */
-    emit sigVideoCaptureChange();
+void UISession::sltCaptureChange()
+{
+    CCaptureSettings captureSettings = machine().GetCaptureSettings();
+
+    /* Check/Uncheck Capture action depending on feature status: */
+    actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)->blockSignals(true);
+    actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)->setChecked(captureSettings.GetEnabled());
+    actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)->blockSignals(false);
+
+    /* Notify listeners about Capture change: */
+    emit sigCaptureChange();
 }
 
@@ -1131,5 +1134,5 @@
 
     connect(gConsoleEvents, SIGNAL(sigVideoCaptureChange()),
-            this, SLOT(sltVideoCaptureChange()));
+            this, SLOT(sltCaptureChange()));
 
     connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)),
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h	(revision 75251)
@@ -259,5 +259,5 @@
     void updateStatusVRDE() { sltVRDEChange(); }
     /** Updates Video Capture action state. */
-    void updateStatusVideoCapture() { sltVideoCaptureChange(); }
+    void updateStatusCapture() { sltCaptureChange(); }
     /** Updates Audio output action state. */
     void updateAudioOutput() { sltAudioAdapterChange(); }
@@ -305,5 +305,5 @@
     void sigMediumChange(const CMediumAttachment &mediumAttachment);
     void sigVRDEChange();
-    void sigVideoCaptureChange();
+    void sigCaptureChange();
     void sigUSBControllerChange();
     void sigUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error);
@@ -357,5 +357,5 @@
     void sltAdditionsChange();
     void sltVRDEChange();
-    void sltVideoCaptureChange();
+    void sltCaptureChange();
     void sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo);
     /** Handles storage device change for @a attachment, which was @a fRemoved and it was @a fSilent for guest. */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp	(revision 75251)
@@ -219,5 +219,5 @@
         case IndicatorType_SharedFolders: pAction = actionPool()->action(UIActionIndexRT_M_Devices_M_SharedFolders);  break;
         case IndicatorType_Display:       pAction = actionPool()->action(UIActionIndexRT_M_ViewPopup);                break;
-        case IndicatorType_VideoCapture:  pAction = actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture);      break;
+        case IndicatorType_Capture:  pAction = actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture);      break;
         case IndicatorType_Mouse:         pAction = actionPool()->action(UIActionIndexRT_M_Input_M_Mouse);            break;
         case IndicatorType_Keyboard:      pAction = actionPool()->action(UIActionIndexRT_M_Input_M_Keyboard);         break;
@@ -640,5 +640,5 @@
         {
             if (iElement & UIVisualElement_VideoCapture)
-                m_pIndicatorsPool->updateAppearance(IndicatorType_VideoCapture);
+                m_pIndicatorsPool->updateAppearance(IndicatorType_Capture);
         }
     }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2008-2017 Oracle Corporation
+ * Copyright (C) 2008-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -31,4 +31,6 @@
 
 /* COM includes: */
+# include "CCaptureSettings.h"
+# include "CCaptureScreenSettings.h"
 # include "CExtPack.h"
 # include "CExtPackManager.h"
@@ -380,14 +382,27 @@
     }
 
-    /* Gather old 'Video Capture' data: */
-    oldDisplayData.m_fVideoCaptureEnabled = m_machine.GetVideoCaptureEnabled();
-    oldDisplayData.m_strVideoCaptureFolder = QFileInfo(m_machine.GetSettingsFilePath()).absolutePath();
-    oldDisplayData.m_strVideoCaptureFilePath = m_machine.GetVideoCaptureFile();
-    oldDisplayData.m_iVideoCaptureFrameWidth = m_machine.GetVideoCaptureWidth();
-    oldDisplayData.m_iVideoCaptureFrameHeight = m_machine.GetVideoCaptureHeight();
-    oldDisplayData.m_iVideoCaptureFrameRate = m_machine.GetVideoCaptureFPS();
-    oldDisplayData.m_iVideoCaptureBitRate = m_machine.GetVideoCaptureRate();
-    oldDisplayData.m_screens = m_machine.GetVideoCaptureScreens();
-    oldDisplayData.m_strVideoCaptureOptions = m_machine.GetVideoCaptureOptions();
+    /* Gather old 'Capture' data: */
+    CCaptureSettings captureSettings = m_machine.GetCaptureSettings();
+    oldDisplayData.m_fVideoCaptureEnabled = captureSettings.GetEnabled();
+
+    /* For now we're using the same settings for all screens; so get settings from screen 0 and work with that. */
+    CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0);
+    if (!captureScreen0Settings.isNull())
+    {
+        oldDisplayData.m_strVideoCaptureFolder = QFileInfo(m_machine.GetSettingsFilePath()).absolutePath();
+        oldDisplayData.m_strVideoCaptureFilePath = captureScreen0Settings.GetFileName();
+        oldDisplayData.m_iVideoCaptureFrameWidth = captureScreen0Settings.GetVideoWidth();
+        oldDisplayData.m_iVideoCaptureFrameHeight = captureScreen0Settings.GetVideoHeight();
+        oldDisplayData.m_iVideoCaptureFrameRate = captureScreen0Settings.GetVideoFPS();
+        oldDisplayData.m_iVideoCaptureBitRate = captureScreen0Settings.GetVideoRate();
+        oldDisplayData.m_strVideoCaptureOptions = captureScreen0Settings.GetOptions();
+    }
+
+    CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens();
+    for (int iScreenIndex = 0; iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex)
+    {
+        CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex);
+        oldDisplayData.m_screens[iScreenIndex] = captureScreenSettings.GetEnabled();
+    }
 
     /* Gather other old display data: */
@@ -1493,4 +1508,6 @@
         const UIDataSettingsMachineDisplay &newDisplayData = m_pCache->data();
 
+        CCaptureSettings captureSettings = m_machine.GetCaptureSettings();
+
         /* Save new 'Video Capture' data for online case: */
         if (isMachineOnline())
@@ -1499,17 +1516,22 @@
             if (oldDisplayData.m_fVideoCaptureEnabled)
             {
+                /* Save whether capture is enabled: */
+                if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)
+                {
+                    captureSettings.SetEnabled(newDisplayData.m_fVideoCaptureEnabled);
+                    fSuccess = captureSettings.isOk();
+                }
+
                 // We can still save the *screens* option.
-                // And finally we should *disable* 'Video Capture' if necessary.
                 /* Save video capture screens: */
                 if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens)
                 {
-                    m_machine.SetVideoCaptureScreens(newDisplayData.m_screens);
-                    fSuccess = m_machine.isOk();
-                }
-                /* Save whether video capture is enabled: */
-                if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)
-                {
-                    m_machine.SetVideoCaptureEnabled(newDisplayData.m_fVideoCaptureEnabled);
-                    fSuccess = m_machine.isOk();
+                    CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens();
+                    for (int iScreenIndex = 0; fSuccess && iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex)
+                    {
+                        CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex);
+                        captureScreenSettings.SetEnabled(newDisplayData.m_screens[iScreenIndex]);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
                 }
             }
@@ -1517,107 +1539,121 @@
             else
             {
-                // We should save all the options *before* 'Video Capture' activation.
-                // And finally we should *enable* Video Capture if necessary.
+                /* Save whether capture is enabled: */
+                if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)
+                {
+                    captureSettings.SetEnabled(newDisplayData.m_fVideoCaptureEnabled);
+                    fSuccess = captureSettings.isOk();
+                }
+
+                CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens();
+                for (int iScreenIndex = 0; fSuccess && iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex)
+                {
+                    CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex);
+
+                    // We should save all the options *before* 'Video Capture' activation.
+                    // And finally we should *enable* Video Capture if necessary.
+                    /* Save video capture file path: */
+                    if (fSuccess && newDisplayData.m_strVideoCaptureFilePath != oldDisplayData.m_strVideoCaptureFilePath)
+                    {
+                        captureScreenSettings.SetFileName(newDisplayData.m_strVideoCaptureFilePath);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
+                    /* Save video capture frame width: */
+                    if (fSuccess && newDisplayData.m_iVideoCaptureFrameWidth != oldDisplayData.m_iVideoCaptureFrameWidth)
+                    {
+                        captureScreenSettings.SetVideoWidth(newDisplayData.m_iVideoCaptureFrameWidth);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
+                    /* Save video capture frame height: */
+                    if (fSuccess && newDisplayData.m_iVideoCaptureFrameHeight != oldDisplayData.m_iVideoCaptureFrameHeight)
+                    {
+                        captureScreenSettings.SetVideoHeight(newDisplayData.m_iVideoCaptureFrameHeight);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
+                    /* Save video capture frame rate: */
+                    if (fSuccess && newDisplayData.m_iVideoCaptureFrameRate != oldDisplayData.m_iVideoCaptureFrameRate)
+                    {
+                        captureScreenSettings.SetVideoFPS(newDisplayData.m_iVideoCaptureFrameRate);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
+                    /* Save video capture frame bit rate: */
+                    if (fSuccess && newDisplayData.m_iVideoCaptureBitRate != oldDisplayData.m_iVideoCaptureBitRate)
+                    {
+                        captureScreenSettings.SetVideoRate(newDisplayData.m_iVideoCaptureBitRate);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
+                    /* Save video capture screens: */
+                    if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens)
+                    {
+                        captureScreenSettings.SetEnabled(newDisplayData.m_screens[iScreenIndex]);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
+                    /* Save video capture options: */
+                    if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions)
+                    {
+                        captureScreenSettings.SetOptions(newDisplayData.m_strVideoCaptureOptions);
+                        fSuccess = captureScreenSettings.isOk();
+                    }
+                }
+            }
+        }
+        /* Save new 'Video Capture' data for offline case: */
+        else
+        {
+            // For 'offline', 'powered off' and 'saved' states the order is irrelevant.
+            /* Save whether video capture is enabled: */
+            if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)
+            {
+                captureSettings.SetEnabled(newDisplayData.m_fVideoCaptureEnabled);
+                fSuccess = captureSettings.isOk();
+            }
+
+            CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens();
+            for (int iScreenIndex = 0; fSuccess && iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex)
+            {
+                CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex);
+
                 /* Save video capture file path: */
                 if (fSuccess && newDisplayData.m_strVideoCaptureFilePath != oldDisplayData.m_strVideoCaptureFilePath)
                 {
-                    m_machine.SetVideoCaptureFile(newDisplayData.m_strVideoCaptureFilePath);
-                    fSuccess = m_machine.isOk();
+                    captureScreenSettings.SetFileName(newDisplayData.m_strVideoCaptureFilePath);
+                    fSuccess = captureScreenSettings.isOk();
                 }
                 /* Save video capture frame width: */
                 if (fSuccess && newDisplayData.m_iVideoCaptureFrameWidth != oldDisplayData.m_iVideoCaptureFrameWidth)
                 {
-                    m_machine.SetVideoCaptureWidth(newDisplayData.m_iVideoCaptureFrameWidth);
-                    fSuccess = m_machine.isOk();
+                    captureScreenSettings.SetVideoWidth(newDisplayData.m_iVideoCaptureFrameWidth);
+                    fSuccess = captureScreenSettings.isOk();
                 }
                 /* Save video capture frame height: */
                 if (fSuccess && newDisplayData.m_iVideoCaptureFrameHeight != oldDisplayData.m_iVideoCaptureFrameHeight)
                 {
-                    m_machine.SetVideoCaptureHeight(newDisplayData.m_iVideoCaptureFrameHeight);
-                    fSuccess = m_machine.isOk();
+                    captureScreenSettings.SetVideoHeight(newDisplayData.m_iVideoCaptureFrameHeight);
+                    fSuccess = captureScreenSettings.isOk();
                 }
                 /* Save video capture frame rate: */
                 if (fSuccess && newDisplayData.m_iVideoCaptureFrameRate != oldDisplayData.m_iVideoCaptureFrameRate)
                 {
-                    m_machine.SetVideoCaptureFPS(newDisplayData.m_iVideoCaptureFrameRate);
-                    fSuccess = m_machine.isOk();
+                    captureScreenSettings.SetVideoFPS(newDisplayData.m_iVideoCaptureFrameRate);
+                    fSuccess = captureScreenSettings.isOk();
                 }
                 /* Save video capture frame bit rate: */
                 if (fSuccess && newDisplayData.m_iVideoCaptureBitRate != oldDisplayData.m_iVideoCaptureBitRate)
                 {
-                    m_machine.SetVideoCaptureRate(newDisplayData.m_iVideoCaptureBitRate);
-                    fSuccess = m_machine.isOk();
+                    captureScreenSettings.SetVideoRate(newDisplayData.m_iVideoCaptureBitRate);
+                    fSuccess = captureScreenSettings.isOk();
                 }
-                /* Save video capture screens: */
+                /* Save capture options: */
+                if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions)
+                {
+                    captureScreenSettings.SetOptions(newDisplayData.m_strVideoCaptureOptions);
+                    fSuccess = captureScreenSettings.isOk();
+                }
+                /* Save screen enabled state: */
                 if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens)
                 {
-                    m_machine.SetVideoCaptureScreens(newDisplayData.m_screens);
-                    fSuccess = m_machine.isOk();
+                    captureScreenSettings.SetEnabled(newDisplayData.m_screens[iScreenIndex]);
+                    fSuccess = captureScreenSettings.isOk();
                 }
-                /* Save video capture options: */
-                if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions)
-                {
-                    m_machine.SetVideoCaptureOptions(newDisplayData.m_strVideoCaptureOptions);
-                    fSuccess = m_machine.isOk();
-                }
-                /* Save whether video capture is enabled: */
-                if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)
-                {
-                    m_machine.SetVideoCaptureEnabled(newDisplayData.m_fVideoCaptureEnabled);
-                    fSuccess = m_machine.isOk();
-                }
-            }
-        }
-        /* Save new 'Video Capture' data for offline case: */
-        else
-        {
-            // For 'offline', 'powered off' and 'saved' states the order is irrelevant.
-            /* Save whether video capture is enabled: */
-            if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)
-            {
-                m_machine.SetVideoCaptureEnabled(newDisplayData.m_fVideoCaptureEnabled);
-                fSuccess = m_machine.isOk();
-            }
-            /* Save video capture file path: */
-            if (fSuccess && newDisplayData.m_strVideoCaptureFilePath != oldDisplayData.m_strVideoCaptureFilePath)
-            {
-                m_machine.SetVideoCaptureFile(newDisplayData.m_strVideoCaptureFilePath);
-                fSuccess = m_machine.isOk();
-            }
-            /* Save video capture frame width: */
-            if (fSuccess && newDisplayData.m_iVideoCaptureFrameWidth != oldDisplayData.m_iVideoCaptureFrameWidth)
-            {
-                m_machine.SetVideoCaptureWidth(newDisplayData.m_iVideoCaptureFrameWidth);
-                fSuccess = m_machine.isOk();
-            }
-            /* Save video capture frame height: */
-            if (fSuccess && newDisplayData.m_iVideoCaptureFrameHeight != oldDisplayData.m_iVideoCaptureFrameHeight)
-            {
-                m_machine.SetVideoCaptureHeight(newDisplayData.m_iVideoCaptureFrameHeight);
-                fSuccess = m_machine.isOk();
-            }
-            /* Save video capture frame rate: */
-            if (fSuccess && newDisplayData.m_iVideoCaptureFrameRate != oldDisplayData.m_iVideoCaptureFrameRate)
-            {
-                m_machine.SetVideoCaptureFPS(newDisplayData.m_iVideoCaptureFrameRate);
-                fSuccess = m_machine.isOk();
-            }
-            /* Save video capture frame bit rate: */
-            if (fSuccess && newDisplayData.m_iVideoCaptureBitRate != oldDisplayData.m_iVideoCaptureBitRate)
-            {
-                m_machine.SetVideoCaptureRate(newDisplayData.m_iVideoCaptureBitRate);
-                fSuccess = m_machine.isOk();
-            }
-            /* Save video capture screens: */
-            if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens)
-            {
-                m_machine.SetVideoCaptureScreens(newDisplayData.m_screens);
-                fSuccess = m_machine.isOk();
-            }
-            /* Save video capture options: */
-            if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions)
-            {
-                m_machine.SetVideoCaptureOptions(newDisplayData.m_strVideoCaptureOptions);
-                fSuccess = m_machine.isOk();
             }
         }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/snapshots/UISnapshotDetailsWidget.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/snapshots/UISnapshotDetailsWidget.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/snapshots/UISnapshotDetailsWidget.cpp	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2008-2017 Oracle Corporation
+ * Copyright (C) 2008-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -48,4 +48,6 @@
 /* COM includes: */
 # include "CAudioAdapter.h"
+# include "CCaptureSettings.h"
+# include "CCaptureScreenSettings.h"
 # include "CMachine.h"
 # include "CMedium.h"
@@ -1745,15 +1747,18 @@
     /* Prepare report: */
     QStringList aReport;
-    /* Acquire video capture status: */
-    if (comMachine.GetVideoCaptureEnabled())
+    /* Acquire capture status: */
+    CCaptureSettings captureSettings = comMachine.GetCaptureSettings();
+    /* For now all screens have the same config: */
+    CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0);
+    if (captureScreen0Settings.GetEnabled())
     {
         /* Video Capture File: */
-        aReport << comMachine.GetVideoCaptureFile();
+        aReport << captureScreen0Settings.GetFileName();
         /* Video Capture Attributes: */
         aReport << QApplication::translate("UIGDetails", "Frame Size: %1x%2, Frame Rate: %3fps, Bit Rate: %4kbps")
-                                           .arg(comMachine.GetVideoCaptureWidth())
-                                           .arg(comMachine.GetVideoCaptureHeight())
-                                           .arg(comMachine.GetVideoCaptureFPS())
-                                           .arg(comMachine.GetVideoCaptureRate());
+                                           .arg(captureScreen0Settings.GetVideoWidth())
+                                           .arg(captureScreen0Settings.GetVideoHeight())
+                                           .arg(captureScreen0Settings.GetVideoFPS())
+                                           .arg(captureScreen0Settings.GetVideoRate());
     }
     /* Return report: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMenuBarEditorWindow.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMenuBarEditorWindow.cpp	(revision 75250)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMenuBarEditorWindow.cpp	(revision 75251)
@@ -1304,5 +1304,5 @@
         pMenu->addSeparator();
         prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_S_TakeScreenshot));
-        prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start));
+        prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start));
         prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer));
         pMenu->addSeparator();
Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 75250)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 75251)
@@ -457,4 +457,6 @@
 	src-server/BandwidthGroupImpl.cpp \
 	src-server/BIOSSettingsImpl.cpp \
+	src-server/CaptureSettingsImpl.cpp \
+	src-server/CaptureScreenSettingsImpl.cpp \
 	src-server/ClientWatcher.cpp \
 	src-server/ClientToken.cpp \
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 75250)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 75251)
@@ -4689,4 +4689,244 @@
   </interface>
 
+  <enum
+    name="CaptureDestination"
+    uuid="E54603A9-6751-4255-93F8-C69E61693391"
+    >
+    <desc>
+      Capturing destination enumeration.
+    </desc>
+
+    <const name="None"                  value="0">
+      <desc>No destination.</desc>
+    </const>
+    <const name="File"                  value="1">
+      <desc>Destination is a regular file.</desc>
+    </const>
+  </enum>
+
+  <enum
+    name="CaptureFeature"
+    uuid="F606CDDB-91B2-4E41-9DFE-4713D4DBA96F"
+    >
+    <desc>
+      Capturing features enumeration.
+    </desc>
+
+    <const name="None"                  value="0">
+      <desc>No feature set.</desc>
+    </const>
+    <const name="Video"                 value="1">
+      <desc>Video capturing.</desc>
+    </const>
+    <const name="Audio"                 value="2">
+      <desc>Audio capturing.</desc>
+    </const>
+  </enum>
+
+  <enum
+    name="CaptureAudioCodec"
+    uuid="9B80C37F-7984-412C-A755-C18FE5859554"
+    >
+    <desc>
+      Capturing audio codec enumeration.
+    </desc>
+
+    <const name="None"                  value="0">
+      <desc>No codec set.</desc>
+    </const>
+    <const name="WavPCM"                value="1">
+      <desc>WAV format, linear PCM, uncompressed.
+        Not implemented yet.</desc>
+    </const>
+    <const name="Opus"                  value="2">
+      <desc>Opus Audio.</desc>
+    </const>
+  </enum>
+
+  <enum
+    name="CaptureVideoCodec"
+    uuid="98BBC021-E119-497D-8C66-4336D539A8D6"
+    >
+    <desc>
+      Capturing video codec enumeration.
+    </desc>
+
+    <const name="None"                  value="0">
+      <desc>No codec set.</desc>
+    </const>
+    <const name="VP8"                   value="1">
+      <desc>VP8 codec.</desc>
+    </const>
+    <const name="VP9"                   value="2">
+      <desc>VP9 codec. Not implemented yet.</desc>
+    </const>
+    <const name="AV1"                   value="3">
+      <desc>AV1 codec. Not implemented yet.</desc>
+    </const>
+  </enum>
+
+  <interface
+    name="ICaptureScreenSettings" extends="$unknown"
+    uuid="9C8FE192-DD9A-45E9-B17B-2BA23B5951F7"
+    wsmap="managed"
+    >
+
+    <desc>
+      The ICaptureScreenSettings interface represents capturing settings of a
+      singke virtual screen. This is used only in the <link to="ICaptureSettings" />
+      interface.
+    </desc>
+
+    <method name="isFeatureEnabled">
+      <desc>TODO</desc>
+      <param name="feature" type="CaptureFeature" dir="in">
+        <desc>TODO</desc>
+      </param>
+      <param name="enabled" type="boolean" dir="return">
+        <desc>TODO</desc>
+      </param>
+    </method>
+
+    <attribute name="enabled" type="boolean" default="false">
+      <desc>
+        This setting determines whether this screen is enabled while capturing.
+      </desc>
+    </attribute>
+
+    <attribute name="features" type="unsigned long">
+      <desc>This setting determines all enabled capturing features for this
+        screen.</desc>
+    </attribute>
+
+    <attribute name="destination" type="CaptureDestination">
+      <desc>This setting determines the capturing destination for this
+        screen.</desc>
+    </attribute>
+
+    <attribute name="fileName" type="wstring">
+      <desc>
+        This setting determines the filename VirtualBox uses to save
+        the recorded content. This setting cannot be changed while video
+        capturing is enabled.
+        <note>
+          When setting this attribute, the specified path has to be
+          absolute (full path). When reading this attribute, a full path is
+          always returned.
+        </note>
+      </desc>
+    </attribute>
+
+    <attribute name="maxTime" type="unsigned long" default="0">
+      <desc>
+        This setting defines the maximum amount of time in milliseconds
+        to capture. Capturing will stop as soon as the defined time
+        interval has elapsed. If this value is zero, capturing will not be
+        limited by time. This setting cannot be changed while capturing is
+        enabled.
+      </desc>
+    </attribute>
+
+    <attribute name="maxFileSize" type="unsigned long" default="0">
+      <desc>
+        This setting determines the maximal number of captured file
+        size in MB. Capturing will stop as soon as the file size has
+        reached the defined value. If this value is zero, capturing
+        will not be limited by the file size. This setting cannot be changed
+        while capturing is enabled.
+      </desc>
+    </attribute>
+
+    <attribute name="options" type="wstring">
+      <desc>
+        This setting contains any additional capturing options
+        required in comma-separated key=value format. This setting
+        cannot be changed while capturing is enabled.
+
+        The following keys and their corresponding values are available:
+
+        <table>
+          <tr>
+            <td>ac_enabled</td>
+            <td>Enables audio recording when set to <pre>true</pre>, otherwise
+                set to <pre>false</pre> to disable.
+
+                <b>This feature is considered being experimental.</b></td>
+          </tr>
+        </table>
+
+      </desc>
+    </attribute>
+
+    <attribute name="videoWidth" type="unsigned long" default="1024">
+      <desc>
+        This setting determines the horizontal resolution of the recorded
+        video. This setting cannot be changed while capturing is enabled.
+      </desc>
+    </attribute>
+
+    <attribute name="videoHeight" type="unsigned long" default="768">
+      <desc>
+        This setting determines the vertical resolution of the recorded
+        video. This setting cannot be changed while capturing is enabled.
+      </desc>
+    </attribute>
+
+    <attribute name="videoRate" type="unsigned long" default="512">
+      <desc>
+        This setting determines the bitrate in kilobits per second.
+        Increasing this value makes the video look better for the
+        cost of an increased file size. This setting cannot be changed
+        while capturing is enabled.
+      </desc>
+    </attribute>
+
+    <attribute name="videoFPS" type="unsigned long" default="25">
+      <desc>
+        This setting determines the maximum number of frames per second.
+        Frames with a higher frequency will be skipped. Reducing this
+        value increases the number of skipped frames and reduces the
+        file size. This setting cannot be changed while capturing
+        is enabled.
+      </desc>
+    </attribute>
+
+  </interface>
+
+  <interface
+    name="ICaptureSettings" extends="$unknown"
+    uuid="F35B5C06-F6F0-475D-908A-F5FECC820043"
+    wsmap="managed"
+    >
+
+    <desc>
+      The ICaptureSettings interface represents capturing settings of the virtual
+      machine. This is used only in the <link to="IMachine::CaptureSettings" />
+      attribute.
+    </desc>
+
+    <method name="getScreenSettings">
+      <desc>TODO</desc>
+      <param name="screenId" type="unsigned long" dir="in">
+        <desc>TODO</desc>
+      </param>
+      <param name="captureScreenSettings" type="ICaptureScreenSettings" dir="return">
+        <desc>TODO</desc>
+      </param>
+    </method>
+
+    <attribute name="enabled" type="boolean" default="false">
+      <desc>
+        This setting determines whether VirtualBox uses capturing to record a
+        VM session.</desc>
+    </attribute>
+
+    <attribute name="screens" type="ICaptureScreenSettings" readonly="yes" safearray="yes">
+      <desc>
+        This setting returns an array for capturing settings of all configured
+        virtual screens.</desc>
+    </attribute>
+
+  </interface>
+
   <interface
     name="IPCIAddress" extends="$unknown"
@@ -4883,5 +5123,5 @@
   <interface
     name="IMachine" extends="$unknown"
-    uuid="fecae8e8-46da-44cf-8fc0-2ba9aeb796a7"
+    uuid="316A9802-03A5-44BE-B2A6-51261A021353"
     wsmap="managed"
     wrap-hint-server-addinterfaces="IInternalMachineControl"
@@ -5164,107 +5404,10 @@
     </attribute>
 
-    <attribute name="videoCaptureEnabled" type="boolean" default="false">
-      <desc>
-        This setting determines whether VirtualBox uses video capturing to
-        record a VM session.</desc>
-    </attribute>
-
-    <attribute name="videoCaptureScreens" type="boolean" safearray="yes">
-      <desc>
-        This setting determines for which screens video capturing is
-        enabled.</desc>
-    </attribute>
-
-    <attribute name="videoCaptureFile" type="wstring">
-      <desc>
-        This setting determines the filename VirtualBox uses to save
-        the recorded content. This setting cannot be changed while video
-        capturing is enabled.
-        <note>
-          When setting this attribute, the specified path has to be
-          absolute (full path). When reading this attribute, a full path is
-          always returned.
-        </note>
-      </desc>
-    </attribute>
-
-    <attribute name="videoCaptureWidth" type="unsigned long" default="640">
-      <desc>
-        This setting determines the horizontal resolution of the recorded
-        video. This setting cannot be changed while video capturing is
-        enabled.
-      </desc>
-    </attribute>
-
-    <attribute name="videoCaptureHeight" type="unsigned long" default="480">
-      <desc>
-        This setting determines the vertical resolution of the recorded
-        video. This setting cannot be changed while video capturing is
-        enabled.
-      </desc>
-    </attribute>
-
-    <attribute name="videoCaptureRate" type="unsigned long" default="512">
-      <desc>
-        This setting determines the bitrate in kilobits per second.
-        Increasing this value makes the video look better for the
-        cost of an increased file size. This setting cannot be changed
-        while video capturing is enabled.
-      </desc>
-    </attribute>
-
-    <attribute name="videoCaptureFPS" type="unsigned long" default="25">
-      <desc>
-        This setting determines the maximum number of frames per second.
-        Frames with a higher frequency will be skipped. Reducing this
-        value increases the number of skipped frames and reduces the
-        file size. This setting cannot be changed while video capturing
-        is enabled.
-      </desc>
-    </attribute>
-
-    <attribute name="videoCaptureMaxTime" type="unsigned long" default="0">
-      <desc>
-        This setting determines the maximum amount of time in milliseconds
-        the video capture will work for. The capture stops as the defined time
-        interval  has elapsed. If this value is zero the capturing will not be
-        limited by time. This setting cannot be changed while video capturing is
-        enabled.
-      </desc>
-    </attribute>
-
-    <attribute name="videoCaptureMaxFileSize" type="unsigned long" default="0">
-      <desc>
-        This setting determines the maximal number of captured video file
-        size in MB. The capture stops as the captured video file size
-        has reached the defined. If this value is zero the capturing
-        will not be limited by file size. This setting cannot be changed
-        while video capturing is enabled.
-      </desc>
-    </attribute>
-
-    <attribute name="videoCaptureOptions" type="wstring">
-      <desc>
-        This setting contains any additional video capture options
-        required in comma-separated key=value format. This setting
-        cannot be changed while video capturing is enabled.
-
-        The following keys and their corresponding values are available:
-
-        <table>
-          <tr>
-            <td>ac_enabled</td>
-            <td>Enables audio recording when set to <pre>true</pre>, otherwise
-                set to <pre>false</pre> to disable.
-
-                <b>This feature is considered being experimental.</b></td>
-          </tr>
-        </table>
-
-      </desc>
-    </attribute>
-
     <attribute name="BIOSSettings" type="IBIOSSettings" readonly="yes">
       <desc>Object containing all BIOS settings.</desc>
+    </attribute>
+
+    <attribute name="captureSettings" type="ICaptureSettings" readonly="yes">
+      <desc>Object containing all capturing settings.</desc>
     </attribute>
 
@@ -20411,5 +20554,5 @@
   <interface
     name="IInternalSessionControl" extends="$unknown"
-    uuid="747e397e-69c8-45a0-88d9-f7f070960718"
+    uuid="96BDA9B7-92E6-402F-AA8C-2E77818DAE6E"
     internal="yes"
     wsmap="suppress"
@@ -20711,7 +20854,7 @@
     </method>
 
-    <method name="onVideoCaptureChange">
-      <desc>
-        Triggered when video capture settings have changed.
+    <method name="onCaptureChange">
+      <desc>
+        Triggered when capture settings have changed.
       </desc>
     </method>
@@ -22895,7 +23038,7 @@
       </desc>
     </const>
-    <const name="OnVideoCaptureChanged" value="91">
-      <desc>
-        See <link to="IVideoCaptureChangedEvent">IVideoCapturedChangeEvent</link>.
+    <const name="OnCaptureChanged" value="91">
+      <desc>
+        See <link to="ICaptureChangedEvent">ICapturedChangeEvent</link>.
       </desc>
     </const>
@@ -24282,10 +24425,10 @@
 
   <interface
-    name="IVideoCaptureChangedEvent" extends="IEvent"
-    uuid="6215d169-25dd-4719-ab34-c908701efb58"
-    wsmap="managed" autogen="VBoxEvent" id="OnVideoCaptureChanged"
+    name="ICaptureChangedEvent" extends="IEvent"
+    uuid="C694687C-F432-4435-B457-F2E55B845C81"
+    wsmap="managed" autogen="VBoxEvent" id="OnCaptureChanged"
     >
     <desc>
-      Notification when video capture settings have changed.
+      Notification when capture settings have changed.
     </desc>
     <attribute name="midlDoesNotLikeEmptyInterfaces" readonly="yes" type="boolean"/>
Index: /trunk/src/VBox/Main/include/CaptureScreenSettingsImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/CaptureScreenSettingsImpl.h	(revision 75251)
+++ /trunk/src/VBox/Main/include/CaptureScreenSettingsImpl.h	(revision 75251)
@@ -0,0 +1,99 @@
+/* $Id$ */
+
+/** @file
+ *
+ * VirtualBox COM class implementation - Capture settings of one virtual screen.
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_CAPTURESCREENSETTINGS
+#define ____H_CAPTURESCREENSETTINGS
+
+#include "CaptureScreenSettingsWrap.h"
+
+namespace settings
+{
+    struct CaptureScreenSettings;
+}
+
+class ATL_NO_VTABLE CaptureScreenSettings :
+    public CaptureScreenSettingsWrap
+{
+public:
+
+    DECLARE_EMPTY_CTOR_DTOR(CaptureScreenSettings)
+
+    HRESULT FinalConstruct();
+    void FinalRelease();
+
+    // public initializer/uninitializer for internal purposes only
+    HRESULT init(Machine *aParent, unsigned long uScreenId, const settings::CaptureScreenSettings& data);
+    HRESULT init(Machine *aParent, CaptureScreenSettings *that);
+    HRESULT initCopy(Machine *aParent, CaptureScreenSettings *that);
+    void uninit();
+
+    // public methods only for internal purposes
+    HRESULT i_loadSettings(const settings::CaptureScreenSettings &data);
+    HRESULT i_saveSettings(settings::CaptureScreenSettings &data);
+
+    void i_rollback();
+    void i_commit();
+    void i_copyFrom(CaptureScreenSettings *aThat);
+    void i_applyDefaults();
+
+private:
+
+    // wrapped ICaptureScreenSettings methods
+    HRESULT isFeatureEnabled(CaptureFeature_T aFeature, BOOL *aEnabled);
+
+    // wrapped ICaptureScreenSettings properties
+    HRESULT getEnabled(BOOL *enabled);
+    HRESULT setEnabled(BOOL enabled);
+    HRESULT getFeatures(ULONG *aFeatures);
+    HRESULT setFeatures(ULONG aFeatures);
+    HRESULT getDestination(CaptureDestination_T *aDestination);
+    HRESULT setDestination(CaptureDestination_T aDestination);
+
+    HRESULT getFileName(com::Utf8Str &aFileName);
+    HRESULT setFileName(const com::Utf8Str &aFileName);
+    HRESULT getMaxTime(ULONG *aMaxTimeS);
+    HRESULT setMaxTime(ULONG aMaxTimeS);
+    HRESULT getMaxFileSize(ULONG *aMaxFileSizeMB);
+    HRESULT setMaxFileSize(ULONG aMaxFileSizeMB);
+    HRESULT getOptions(com::Utf8Str &aOptions);
+    HRESULT setOptions(const com::Utf8Str &aOptions);
+
+    HRESULT getVideoWidth(ULONG *aVideoWidth);
+    HRESULT setVideoWidth(ULONG aVideoWidth);
+    HRESULT getVideoHeight(ULONG *aVideoHeight);
+    HRESULT setVideoHeight(ULONG aVideoHeight);
+    HRESULT getVideoRate(ULONG *aVideoRate);
+    HRESULT setVideoRate(ULONG aVideoRate);
+    HRESULT getVideoFPS(ULONG *aVideoFPS);
+    HRESULT setVideoFPS(ULONG aVideoFPS);
+
+private:
+
+    // internal methods
+    bool i_canChangeSettings();
+    int  i_getDefaultCaptureFile(Utf8Str &strFile);
+
+private:
+
+    struct Data;
+    Data *m;
+};
+
+#endif // ____H_CAPTURESCREENSETTINGS
+
Index: /trunk/src/VBox/Main/include/CaptureSettingsImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/CaptureSettingsImpl.h	(revision 75251)
+++ /trunk/src/VBox/Main/include/CaptureSettingsImpl.h	(revision 75251)
@@ -0,0 +1,77 @@
+/* $Id$ */
+
+/** @file
+ *
+ * VirtualBox COM class implementation - Machine capture settings.
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_CAPTURESETTINGS
+#define ____H_CAPTURESETTINGS
+
+#include "CaptureSettingsWrap.h"
+
+namespace settings
+{
+    struct CaptureSettings;
+}
+
+class ICaptureScreenSettings;
+class CaptureScreenSettings;
+
+class ATL_NO_VTABLE CaptureSettings :
+    public CaptureSettingsWrap
+{
+public:
+
+    DECLARE_EMPTY_CTOR_DTOR(CaptureSettings)
+
+    HRESULT FinalConstruct();
+    void FinalRelease();
+
+    // public initializer/uninitializer for internal purposes only
+    HRESULT init(Machine *parent);
+    HRESULT init(Machine *parent, CaptureSettings *that);
+    HRESULT initCopy(Machine *parent, CaptureSettings *that);
+    void uninit();
+
+    // public methods only for internal purposes
+    HRESULT i_loadSettings(const settings::CaptureSettings &data);
+    HRESULT i_saveSettings(settings::CaptureSettings &data);
+
+    void i_rollback();
+    void i_commit();
+    void i_copyFrom(CaptureSettings *aThat);
+    void i_applyDefaults(void);
+
+private:
+
+    // wrapped ICaptureSettings properties
+    HRESULT getEnabled(BOOL *enabled);
+    HRESULT setEnabled(BOOL enable);
+    HRESULT getScreens(std::vector<ComPtr<ICaptureScreenSettings> > &aCaptureScreenSettings);
+
+    // wrapped ICaptureSettings methods
+    HRESULT getScreenSettings(ULONG uScreenId, ComPtr<ICaptureScreenSettings> &aCaptureScreenSettings);
+
+private:
+
+    /** Map of screen settings objects. The key specifies the screen ID. */
+    typedef std::map <ULONG, ComObjPtr<CaptureScreenSettings> > CaptureScreenSettingsMap;
+
+    struct Data;
+    Data *m;
+};
+#endif // ____H_CAPTURESETTINGS
+
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 75251)
@@ -24,4 +24,7 @@
 #include "SecretKeyStore.h"
 #include "ConsoleWrap.h"
+#ifdef VBOX_WITH_VIDEOREC
+# include "VideoRec.h"
+#endif
 
 class Guest;
@@ -139,6 +142,10 @@
 #endif
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-    AudioVideoRec *i_getAudioVideoRec() const { return mAudioVideoRec; }
-    HRESULT i_audioVideoRecSendAudio(const void *pvData, size_t cbData, uint64_t uDurationMs);
+    int i_videoRecLoad(settings::CaptureSettings &Settings);
+    int i_videoRecStart(void);
+    int i_videoRecStop(void);
+    AudioVideoRec *i_videoRecGetAudioDrv(void) const { return Capture.mAudioVideoRec; }
+    CaptureContext *i_videoRecGetContext(void) const { return Capture.mpVideoRecCtx; }
+    HRESULT i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uDurationMs);
 #endif
 
@@ -169,5 +176,5 @@
     HRESULT i_onDnDModeChange(DnDMode_T aDnDMode);
     HRESULT i_onVRDEServerChange(BOOL aRestart);
-    HRESULT i_onVideoCaptureChange();
+    HRESULT i_onCaptureChange();
     HRESULT i_onUSBControllerChange();
     HRESULT i_onSharedFolderChange(BOOL aGlobal);
@@ -939,8 +946,4 @@
     VMMDev *                    m_pVMMDev;
     AudioVRDE * const           mAudioVRDE;
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-    /** The video recording audio backend. */
-    AudioVideoRec * const       mAudioVideoRec;
-#endif
     Nvram   * const             mNvram;
 #ifdef VBOX_WITH_USB_CARDREADER
@@ -1028,4 +1031,20 @@
     ComPtr<IEventListener> mVmListener;
 
+#ifdef VBOX_WITH_VIDEOREC
+    struct Capture
+    {
+        Capture()
+            : mpVideoRecCtx(NULL)
+            , mAudioVideoRec(NULL) { }
+
+        /** The capturing context. */
+        CaptureContext       *mpVideoRecCtx;
+# ifdef VBOX_WITH_AUDIO_VIDEOREC
+        /** Pointer to capturing audio backend. */
+        AudioVideoRec * const mAudioVideoRec;
+# endif
+    } Capture;
+#endif /* VBOX_WITH_VIDEOREC */
+
     friend class VMTask;
     friend class ConsoleVRDPServer;
Index: /trunk/src/VBox/Main/include/DisplayImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/DisplayImpl.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/DisplayImpl.h	(revision 75251)
@@ -32,9 +32,4 @@
 #endif
 
-#ifdef VBOX_WITH_VIDEOREC
-# include "VideoRec.h"
-struct VIDEORECCONTEXT;
-#endif
-
 #include "DisplaySourceBitmapWrap.h"
 #include "GuestScreenInfoWrap.h"
@@ -184,10 +179,7 @@
                                           uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBitsPerPixel,
                                           uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight,
-                                          uint8_t *pu8BufferAddress, uint64_t u64TimeStamp);
-    /** @todo r=bird: u64TimeStamp - using the 'u64' prefix add nothing.
-     *        However, using one of the prefixes indicating the timestamp unit
-     *        would be very valuable!  */
-    bool i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp);
-    void i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64TimeStamp);
+                                          uint8_t *pu8BufferAddress, uint64_t uTimestampMs);
+    bool i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t uTimestampMs);
+    void i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t uTimestampMs);
     void i_handleVRecCompletion();
 #endif
@@ -209,12 +201,6 @@
 
 #ifdef VBOX_WITH_VIDEOREC
-    PVIDEORECCFG             i_videoRecGetConfig(void) { return &mVideoRecCfg; }
-    VIDEORECFEATURES         i_videoRecGetFeatures(void);
-    bool                     i_videoRecStarted(void);
-    void                     i_videoRecInvalidate();
-    int                      i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs);
-    int                      i_videoRecStart(void);
-    void                     i_videoRecStop(void);
-    void                     i_videoRecScreenChanged(unsigned uScreenId);
+    int  i_videoRecInvalidate(void);
+    void i_videoRecScreenChanged(unsigned uScreenId);
 #endif
 
@@ -486,9 +472,5 @@
     /* Serializes access to video recording source bitmaps. */
     RTCRITSECT           mVideoRecLock;
-    /** The current video recording configuration being used. */
-    VIDEORECCFG          mVideoRecCfg;
-    /** The video recording context. */
-    VIDEORECCONTEXT     *mpVideoRecCtx;
-    /** Array which defines which screens are being enabled for recording. */
+    /** Array which defines which screens are being enabled for capturing. */
     bool                 maVideoRecEnabled[SchemaDefs::MaxGuestMonitors];
 #endif
Index: /trunk/src/VBox/Main/include/DrvAudioVideoRec.h
===================================================================
--- /trunk/src/VBox/Main/include/DrvAudioVideoRec.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/DrvAudioVideoRec.h	(revision 75251)
@@ -20,4 +20,5 @@
 
 #include <VBox/com/ptr.h>
+#include <VBox/settings.h>
 #include <VBox/vmm/pdmdrv.h>
 #include <VBox/vmm/pdmifs.h>
@@ -44,5 +45,5 @@
 public:
 
-    int applyConfiguration(const PVIDEORECCFG pVideoRecCfg);
+    int applyConfiguration(const settings::CaptureSettings &a_Settings);
 
 public:
@@ -58,7 +59,7 @@
 
     /** Pointer to the associated video recording audio driver. */
-    struct DRVAUDIOVIDEOREC *mpDrv;
-    /** Video recording configuration used for configuring the driver. */
-    struct VIDEORECCFG       mVideoRecCfg;
+    struct DRVAUDIOVIDEOREC         *mpDrv;
+    /** Capturing configuration used for configuring the driver. */
+    struct settings::CaptureSettings mVideoRecCfg;
 };
 
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2017 Oracle Corporation
+ * Copyright (C) 2006-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -32,4 +32,5 @@
 #include "ParallelPortImpl.h"
 #include "BIOSSettingsImpl.h"
+#include "CaptureSettingsImpl.h"
 #include "StorageControllerImpl.h"          // required for MachineImpl.h to compile on Windows
 #include "USBControllerImpl.h"              // required for MachineImpl.h to compile on Windows
@@ -265,14 +266,5 @@
         GraphicsControllerType_T mGraphicsControllerType;
         ULONG               mVRAMSize;
-        ULONG               mVideoCaptureWidth;
-        ULONG               mVideoCaptureHeight;
-        ULONG               mVideoCaptureRate;
-        ULONG               mVideoCaptureFPS;
-        ULONG               mVideoCaptureMaxTime;
-        ULONG               mVideoCaptureMaxFileSize;
-        Utf8Str             mVideoCaptureOptions;
-        Utf8Str             mVideoCaptureFile;
-        BOOL                mVideoCaptureEnabled;
-        BOOL                maVideoCaptureScreens[SchemaDefs::MaxGuestMonitors];
+        settings::CaptureSettings mCaptureSettings;
         ULONG               mMonitorCount;
         BOOL                mHWVirtExEnabled;
@@ -484,5 +476,6 @@
         IsModified_SharedFolders        = 0x0400,
         IsModified_Snapshots            = 0x0800,
-        IsModified_BandwidthControl     = 0x1000
+        IsModified_BandwidthControl     = 0x1000,
+        IsModified_Capture              = 0x2000
     };
 
@@ -528,5 +521,5 @@
     virtual HRESULT i_onStorageDeviceChange(IMediumAttachment * /* mediumAttachment */, BOOL /* remove */,
                                             BOOL /* silent */) { return S_OK; }
-    virtual HRESULT i_onVideoCaptureChange() { return S_OK; }
+    virtual HRESULT i_onCaptureChange() { return S_OK; }
 
     HRESULT i_saveRegistryEntry(settings::MachineRegistryEntry &data);
@@ -540,6 +533,4 @@
 
     void i_composeSavedStateFilename(Utf8Str &strStateFilePath);
-
-    void i_getDefaultVideoCaptureFile(Utf8Str &strFile);
 
     bool i_isUSBControllerPresent();
@@ -783,4 +774,5 @@
     const ComObjPtr<USBDeviceFilters>  mUSBDeviceFilters;
     const ComObjPtr<BIOSSettings>      mBIOSSettings;
+    const ComObjPtr<CaptureSettings>   mCaptureSettings;
     const ComObjPtr<BandwidthControl>  mBandwidthControl;
 
@@ -829,7 +821,9 @@
     void i_deleteConfigHandler(DeleteConfigTask &task);
 
+    friend class Appliance;
+    friend class CaptureSettings;
+    friend class CaptureScreenSettings;
     friend class SessionMachine;
     friend class SnapshotMachine;
-    friend class Appliance;
     friend class VirtualBox;
 
@@ -882,25 +876,6 @@
     HRESULT getMonitorCount(ULONG *aMonitorCount);
     HRESULT setMonitorCount(ULONG aMonitorCount);
-    HRESULT getVideoCaptureEnabled(BOOL *aVideoCaptureEnabled);
-    HRESULT setVideoCaptureEnabled(BOOL aVideoCaptureEnabled);
-    HRESULT getVideoCaptureScreens(std::vector<BOOL> &aVideoCaptureScreens);
-    HRESULT setVideoCaptureScreens(const std::vector<BOOL> &aVideoCaptureScreens);
-    HRESULT getVideoCaptureFile(com::Utf8Str &aVideoCaptureFile);
-    HRESULT setVideoCaptureFile(const com::Utf8Str &aVideoCaptureFile);
-    HRESULT getVideoCaptureWidth(ULONG *aVideoCaptureWidth);
-    HRESULT setVideoCaptureWidth(ULONG aVideoCaptureWidth);
-    HRESULT getVideoCaptureHeight(ULONG *aVideoCaptureHeight);
-    HRESULT setVideoCaptureHeight(ULONG aVideoCaptureHeight);
-    HRESULT getVideoCaptureRate(ULONG *aVideoCaptureRate);
-    HRESULT setVideoCaptureRate(ULONG aVideoCaptureRate);
-    HRESULT getVideoCaptureFPS(ULONG *aVideoCaptureFPS);
-    HRESULT setVideoCaptureFPS(ULONG aVideoCaptureFPS);
-    HRESULT getVideoCaptureMaxTime(ULONG *aVideoCaptureMaxTime);
-    HRESULT setVideoCaptureMaxTime(ULONG aVideoCaptureMaxTime);
-    HRESULT getVideoCaptureMaxFileSize(ULONG *aVideoCaptureMaxFileSize);
-    HRESULT setVideoCaptureMaxFileSize(ULONG aVideoCaptureMaxFileSize);
-    HRESULT getVideoCaptureOptions(com::Utf8Str &aVideoCaptureOptions);
-    HRESULT setVideoCaptureOptions(const com::Utf8Str &aVideoCaptureOptions);
     HRESULT getBIOSSettings(ComPtr<IBIOSSettings> &aBIOSSettings);
+    HRESULT getCaptureSettings(ComPtr<ICaptureSettings> &aCaptureSettings);
     HRESULT getFirmwareType(FirmwareType_T *aFirmwareType);
     HRESULT setFirmwareType(FirmwareType_T aFirmwareType);
@@ -1348,5 +1323,5 @@
     HRESULT i_onCPUChange(ULONG aCPU, BOOL aRemove);
     HRESULT i_onVRDEServerChange(BOOL aRestart);
-    HRESULT i_onVideoCaptureChange();
+    HRESULT i_onCaptureChange();
     HRESULT i_onUSBControllerChange();
     HRESULT i_onUSBDeviceAttach(IUSBDevice *aDevice,
Index: /trunk/src/VBox/Main/include/SessionImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/SessionImpl.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/SessionImpl.h	(revision 75251)
@@ -102,5 +102,5 @@
     HRESULT onCPUExecutionCapChange(ULONG aExecutionCap);
     HRESULT onVRDEServerChange(BOOL aRestart);
-    HRESULT onVideoCaptureChange();
+    HRESULT onCaptureChange();
     HRESULT onUSBControllerChange();
     HRESULT onSharedFolderChange(BOOL aGlobal);
Index: /trunk/src/VBox/Main/include/VideoRec.h
===================================================================
--- /trunk/src/VBox/Main/include/VideoRec.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/VideoRec.h	(revision 75251)
@@ -23,4 +23,5 @@
 #include <VBox/com/VirtualBox.h>
 #include <VBox/err.h>
+#include <VBox/settings.h>
 
 using namespace com;
@@ -29,4 +30,5 @@
 #include "VideoRecStream.h"
 
+#if 0
 /**
  * Enumeration for definining a video / audio
@@ -54,10 +56,10 @@
 
 /**
- * Structure for keeping a video recording configuration.
- */
-typedef struct VIDEORECCFG
+ * Structure for keeping a screen recording configuration.
+ */
+typedef struct VIDEORECSCREENCFG
 {
-    VIDEORECCFG(void)
-        :  enmDst(VIDEORECDEST_INVALID)
+    VIDEORECSCREENCFG(void)
+        : enmDst(VIDEORECDEST_INVALID)
         , uMaxTimeS(0)
     {
@@ -68,7 +70,19 @@
     }
 
-    /** Array of all screens containing whether they're enabled
-     *  for recording or not.  */
-    com::SafeArray<BOOL>    aScreens;
+    VIDEORECSCREENCFG& operator=(const VIDEORECSCREENCFG &that)
+    {
+        enmDst          = that.enmDst;
+
+        File.strName    = that.File.strName;
+        File.uMaxSizeMB = that.File.uMaxSizeMB;
+#ifdef VBOX_WITH_AUDIO_VIDEOREC
+        Audio           = that.Audio;
+#endif
+        Video           = that.Video;
+        uMaxTimeS       = that.uMaxTimeS;
+        return *this;
+    }
+
+    unsigned long           uScreenId;
     /** Destination where to write the stream to. */
     VIDEORECDEST            enmDst;
@@ -135,52 +149,83 @@
 
     } Video;
+
     /** Maximum time (in s) to record.
      *  Specify 0 to disable this check. */
     uint32_t                uMaxTimeS;
-
-    VIDEORECCFG& operator=(const VIDEORECCFG &that)
-    {
-        aScreens.resize(that.aScreens.size());
-        for (size_t i = 0; i < that.aScreens.size(); ++i)
-            aScreens[i] = that.aScreens[i];
-
-        enmDst   = that.enmDst;
-
-        File.strName    = that.File.strName;
-        File.uMaxSizeMB = that.File.uMaxSizeMB;
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-        Audio           = that.Audio;
-#endif
-        Video           = that.Video;
-        uMaxTimeS       = that.uMaxTimeS;
-        return *this;
-    }
-
-} VIDEORECCFG, *PVIDEORECCFG;
+} VIDEORECSCREENCFG, *PVIDEORECSCREENCFG;
+#endif
+
+class Console;
 
 /**
- * Structure for keeping a video recording context.
- */
-typedef struct VIDEORECCONTEXT
+ * Class for managing a capturing context.
+ */
+class CaptureContext
 {
+public:
+
+    CaptureContext(Console *pConsole);
+
+    CaptureContext(Console *pConsole, const settings::CaptureSettings &a_Settings);
+
+    virtual ~CaptureContext(void);
+
+public:
+
+    const settings::CaptureSettings &GetConfig(void) const;
+    CaptureStream *GetStream(unsigned uScreen) const;
+    size_t GetStreamCount(void) const;
+
+    int Create(const settings::CaptureSettings &a_Settings);
+    int Destroy(void);
+
+    int SendAudioFrame(const void *pvData, size_t cbData, uint64_t uTimestampMs);
+    int SendVideoFrame(uint32_t uScreen,
+                       uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP,
+                       uint32_t uBytesPerLine, uint32_t uSrcWidth, uint32_t uSrcHeight,
+                       uint8_t *puSrcData, uint64_t uTimeStampMs);
+public:
+
+    bool IsFeatureEnabled(CaptureFeature_T enmFeature) const;
+    bool IsReady(void) const;
+    bool IsReady(uint32_t uScreen, uint64_t uTimeStampMs) const;
+    bool IsStarted(void) const;
+    bool IsLimitReached(uint32_t uScreen, uint64_t tsNowMs) const;
+
+protected:
+
+    int createInternal(const settings::CaptureSettings &a_Settings);
+
+    int destroyInternal(void);
+
+    CaptureStream *getStreamInternal(unsigned uScreen) const;
+
+    static DECLCALLBACK(int) threadMain(RTTHREAD hThreadSelf, void *pvUser);
+
+    int threadNotify(void);
+
+protected:
+
+    /** Pointer to the console object. */
+    Console                  *pConsole;
     /** Used recording configuration. */
-    VIDEORECCFG         Cfg;
+    settings::CaptureSettings Settings;
     /** The current state. */
-    uint32_t            enmState;
+    uint32_t                  enmState;
     /** Critical section to serialize access. */
-    RTCRITSECT          CritSect;
+    RTCRITSECT                CritSect;
     /** Semaphore to signal the encoding worker thread. */
-    RTSEMEVENT          WaitEvent;
-    /** Whether this conext is in started state or not. */
-    bool                fStarted;
+    RTSEMEVENT                WaitEvent;
+    /** Whether this context is in started state or not. */
+    bool                      fStarted;
     /** Shutdown indicator. */
-    bool                fShutdown;
+    bool                      fShutdown;
     /** Worker thread. */
-    RTTHREAD            Thread;
+    RTTHREAD                  Thread;
     /** Vector of current recording streams.
      *  Per VM screen (display) one recording stream is being used. */
-    VideoRecStreams     vecStreams;
+    VideoRecStreams           vecStreams;
     /** Timestamp (in ms) of when recording has been started. */
-    uint64_t            tsStartMs;
+    uint64_t                  tsStartMs;
     /** Block map of common blocks which need to get multiplexed
      *  to all recording streams. This common block maps should help
@@ -190,22 +235,6 @@
      *  For now this only affects audio, e.g. all recording streams
      *  need to have the same audio data at a specific point in time. */
-    VideoRecBlockMap    mapBlocksCommon;
-} VIDEORECCONTEXT, *PVIDEORECCONTEXT;
-
-int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCFG pVideoRecCfg, PVIDEORECCONTEXT *ppCtx);
-int VideoRecContextDestroy(PVIDEORECCONTEXT pCtx);
-
-VIDEORECFEATURES VideoRecGetFeatures(PVIDEORECCFG pCfg);
-PVIDEORECSTREAM VideoRecGetStream(PVIDEORECCONTEXT pCtx, uint32_t uScreen);
-
-int VideoRecSendAudioFrame(PVIDEORECCONTEXT pCtx, const void *pvData, size_t cbData, uint64_t uTimestampMs);
-int VideoRecSendVideoFrame(PVIDEORECCONTEXT pCtx, uint32_t uScreen,
-                            uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP,
-                            uint32_t uBytesPerLine, uint32_t uSrcWidth, uint32_t uSrcHeight,
-                            uint8_t *puSrcData, uint64_t uTimeStampMs);
-bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t uTimeStampMs);
-bool VideoRecIsStarted(PVIDEORECCONTEXT pCtx);
-bool VideoRecIsLimitReached(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t tsNowMs);
-
+    VideoRecBlockMap          mapBlocksCommon;
+};
 #endif /* !____H_VIDEOREC */
 
Index: /trunk/src/VBox/Main/include/VideoRecInternals.h
===================================================================
--- /trunk/src/VBox/Main/include/VideoRecInternals.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/VideoRecInternals.h	(revision 75251)
@@ -30,36 +30,8 @@
 
 /**
- * Enumeration for video recording destinations.
- */
-typedef enum VIDEORECDEST
-{
-    /** Invalid destination, do not use. */
-    VIDEORECDEST_INVALID = 0,
-    /** Write to a file. */
-    VIDEORECDEST_FILE    = 1
-} VIDEORECDEST;
-
-/**
- * Enumeration for the video recording video codec type.
- */
-typedef enum VIDEORECVIDEOCODECTYPE
-{
-    /** Unknown codec type, do not use. */
-    VIDEORECVIDEOCODECTYPE_UNKNOWN,
-    /** Codec is VP8. */
-    VIDEORECVIDEOCODECTYPE_VP8,
-# ifdef VBOX_WITH_LIBVPX_VP9
-    /** Codec is VP9. */
-    VIDEORECVIDEOCODECTYPE_VP9
-#endif
-} VIDEORECVIDEOCODECTYPE;
-
-/**
  * Structure for keeping specific video recording codec data.
  */
 typedef struct VIDEORECVIDEOCODEC
 {
-    /** Used codec type. */
-    VIDEORECVIDEOCODECTYPE enmType;
 #ifdef VBOX_WITH_LIBVPX
     union
@@ -75,4 +47,5 @@
             /** Pointer to the codec's internal YUV buffer. */
             uint8_t            *pu8YuvBuf;
+            unsigned int        uEncoderDeadline;
         } VPX;
     };
Index: /trunk/src/VBox/Main/include/VideoRecStream.h
===================================================================
--- /trunk/src/VBox/Main/include/VideoRecStream.h	(revision 75250)
+++ /trunk/src/VBox/Main/include/VideoRecStream.h	(revision 75251)
@@ -27,4 +27,5 @@
 #include <VBox/com/VirtualBox.h>
 #include <VBox/err.h>
+#include <VBox/settings.h>
 
 #include "VideoRecInternals.h"
@@ -32,16 +33,13 @@
 class WebMWriter;
 
-struct VIDEORECCFG;
-typedef struct VIDEORECCFG *PVIDEORECCFG;
-
-struct VIDEORECCONTEXT;
-typedef struct VIDEORECCONTEXT *PVIDEORECCONTEXT;
+struct CaptureContext;
+typedef struct CaptureContext *PVIDEORECCONTEXT;
 
 
 /** Structure for queuing all blocks bound to a single timecode.
  *  This can happen if multiple tracks are being involved. */
-struct VideoRecBlocks
+struct CaptureBlocks
 {
-    virtual ~VideoRecBlocks()
+    virtual ~CaptureBlocks()
     {
         Clear();
@@ -71,12 +69,12 @@
  *  The key specifies a unique timecode, whereas the value
  *  is a list of blocks which all correlate to the same key (timecode). */
-typedef std::map<uint64_t, VideoRecBlocks *> VideoRecBlockMap;
+typedef std::map<uint64_t, CaptureBlocks *> VideoRecBlockMap;
 
 /**
- * Structure for holding a set of video recording (data) blocks.
- */
-struct VideoRecBlockSet
+ * Structure for holding a set of recording (data) blocks.
+ */
+struct CaptureBlockSet
 {
-    virtual ~VideoRecBlockSet()
+    virtual ~CaptureBlockSet()
     {
         Clear();
@@ -84,8 +82,8 @@
 
     /**
-     * Resets a video recording block set by removing (destroying)
+     * Resets a recording block set by removing (destroying)
      * all current elements.
      */
-    void Clear()
+    void Clear(void)
     {
         VideoRecBlockMap::iterator it = Map.begin();
@@ -108,12 +106,56 @@
 
 /**
- * Structure for maintaining a video recording stream.
- */
-typedef struct VIDEORECSTREAM
+ * Class for managing a recording stream.
+ */
+class CaptureStream
 {
-    /** Video recording context this stream is associated to. */
-    PVIDEORECCONTEXT            pCtx;
-    /** Destination where to write the stream to. */
-    VIDEORECDEST                enmDst;
+public:
+
+    CaptureStream(void);
+
+    CaptureStream(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings);
+
+    virtual ~CaptureStream(void);
+
+public:
+
+    int Init(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings);
+    int Uninit(void);
+
+    int Process(VideoRecBlockMap &mapBlocksCommon);
+    int SendVideoFrame(uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine,
+                       uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, uint64_t uTimeStampMs);
+
+    const settings::CaptureScreenSettings &GetConfig(void) const;
+    bool IsLimitReached(uint64_t tsNowMs) const;
+    bool IsReady(void) const;
+
+protected:
+
+    int open(void);
+    int close(void);
+
+    int initInternal(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings);
+    int uninitInternal(void);
+
+    int initVideo(void);
+    int unitVideo(void);
+
+    int initAudio(void);
+
+#ifdef VBOX_WITH_LIBVPX
+    int initVideoVPX(void);
+    int uninitVideoVPX(void);
+    int writeVideoVPX(uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame);
+#endif
+    void lock(void);
+    void unlock(void);
+
+    int parseOptionsString(const com::Utf8Str &strOptions);
+
+protected:
+
+    /** Recording context this stream is associated to. */
+    CaptureContext             *pCtx;
     union
     {
@@ -123,9 +165,10 @@
             RTFILE              hFile;
             /** File name being used for this stream. */
-            char               *pszFile;
+            Utf8Str             strName;
             /** Pointer to WebM writer instance being used. */
             WebMWriter         *pWEBM;
         } File;
     };
+    bool                fEnabled;
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
     /** Track number of audio stream. */
@@ -136,48 +179,29 @@
     /** Screen ID. */
     uint16_t            uScreenID;
-    /** Whether video recording is enabled or not. */
-    bool                fEnabled;
     /** Critical section to serialize access. */
     RTCRITSECT          CritSect;
+    /** Timestamp (in ms) of when recording has been start. */
+    uint64_t            tsStartMs;
 
     struct
     {
-        /** Codec-specific data. */
-        VIDEORECVIDEOCODEC  Codec;
         /** Minimal delay (in ms) between two video frames.
          *  This value is based on the configured FPS rate. */
         uint32_t            uDelayMs;
-        /** Target X resolution (in pixels). */
-        uint32_t            uWidth;
-        /** Target Y resolution (in pixels). */
-        uint32_t            uHeight;
         /** Time stamp (in ms) of the last video frame we encoded. */
         uint64_t            uLastTimeStampMs;
         /** Number of failed attempts to encode the current video frame in a row. */
         uint16_t            cFailedEncodingFrames;
+        VIDEORECVIDEOCODEC  Codec;
     } Video;
 
+    settings::CaptureScreenSettings Settings;
     /** Common set of video recording (data) blocks, needed for
      *  multiplexing to all recording streams. */
-    VideoRecBlockSet Blocks;
-} VIDEORECSTREAM, *PVIDEORECSTREAM;
+    CaptureBlockSet                 Blocks;
+};
 
 /** Vector of video recording streams. */
-typedef std::vector <PVIDEORECSTREAM> VideoRecStreams;
-
-int VideoRecStreamClose(PVIDEORECSTREAM pStream);
-int VideoRecStreamOpen(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg);
-int VideoRecStreamProcess(PVIDEORECSTREAM pStream);
-int VideoRecStreamInit(PVIDEORECSTREAM pStream, PVIDEORECCONTEXT pCtx, uint32_t uScreen);
-int VideoRecStreamUninit(PVIDEORECSTREAM pStream);
-int VideoRecStreamUnitVideo(PVIDEORECSTREAM pStream);
-int VideoRecStreamInitVideo(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg);
-#ifdef VBOX_WITH_LIBVPX
-int VideoRecStreamInitVideoVPX(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg);
-int VideoRecStreamUninitVideoVPX(PVIDEORECSTREAM pStream);
-int VideoRecStreamWriteVideoVPX(PVIDEORECSTREAM pStream, uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame);
-#endif
-void VideoRecStreamLock(PVIDEORECSTREAM pStream);
-void VideoRecStreamUnlock(PVIDEORECSTREAM pStream);
+typedef std::vector <CaptureStream *> VideoRecStreams;
 
 #endif /* ____H_VIDEOREC_STREAM */
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 75251)
@@ -402,7 +402,4 @@
     , m_pVMMDev(NULL)
     , mAudioVRDE(NULL)
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-    , mAudioVideoRec(NULL)
-#endif
     , mNvram(NULL)
 #ifdef VBOX_WITH_USB_CARDREADER
@@ -590,6 +587,6 @@
 #endif
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-        unconst(mAudioVideoRec) = new AudioVideoRec(this);
-        AssertReturn(mAudioVideoRec, E_FAIL);
+        unconst(Capture.mAudioVideoRec) = new AudioVideoRec(this);
+        AssertReturn(Capture.mAudioVideoRec, E_FAIL);
 #endif
         FirmwareType_T enmFirmwareType;
@@ -738,8 +735,8 @@
 
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-    if (mAudioVideoRec)
-    {
-        delete mAudioVideoRec;
-        unconst(mAudioVideoRec) = NULL;
+    if (Capture.mAudioVideoRec)
+    {
+        delete Capture.mAudioVideoRec;
+        unconst(Capture.mAudioVideoRec) = NULL;
     }
 #endif
@@ -5619,5 +5616,5 @@
     if (pDisplay)
     {
-        if (RT_BOOL(fEnable) != pDisplay->i_videoRecStarted())
+        if (RT_BOOL(fEnable) != Capture.mpVideoRecCtx->IsStarted())
         {
             LogRel(("VideoRec: %s\n", fEnable ? "Enabling" : "Disabling"));
@@ -5629,23 +5626,23 @@
 # ifdef VBOX_WITH_AUDIO_VIDEOREC
                 /* Attach the video recording audio driver if required. */
-                if (   pDisplay->i_videoRecGetFeatures() & VIDEORECFEATURE_AUDIO
-                    && mAudioVideoRec)
+                if (   Capture.mpVideoRecCtx->IsFeatureEnabled(CaptureFeature_Audio)
+                    && Capture.mAudioVideoRec)
                 {
-                    vrc = mAudioVideoRec->applyConfiguration(pDisplay->i_videoRecGetConfig());
+                    vrc = Capture.mAudioVideoRec->applyConfiguration(Capture.mpVideoRecCtx->GetConfig());
                     if (RT_SUCCESS(vrc))
-                        vrc = mAudioVideoRec->doAttachDriverViaEmt(mpUVM, pAutoLock);
+                        vrc = Capture.mAudioVideoRec->doAttachDriverViaEmt(mpUVM, pAutoLock);
                 }
 # endif
                 if (   RT_SUCCESS(vrc)
-                    && pDisplay->i_videoRecGetFeatures()) /* Any video recording (audio and/or video) feature enabled? */
+                    && Capture.mpVideoRecCtx->IsReady()) /* Any video recording (audio and/or video) feature enabled? */
                 {
-                    vrc = pDisplay->i_videoRecStart();
+                    vrc = i_videoRecStart();
                 }
             }
             else
             {
-                mDisplay->i_videoRecStop();
+                i_videoRecStop();
 # ifdef VBOX_WITH_AUDIO_VIDEOREC
-                mAudioVideoRec->doDetachDriverViaEmt(mpUVM, pAutoLock);
+                Capture.mAudioVideoRec->doDetachDriverViaEmt(mpUVM, pAutoLock);
 # endif
             }
@@ -5662,5 +5659,5 @@
 #endif /* VBOX_WITH_VIDEOREC */
 
-HRESULT Console::i_onVideoCaptureChange()
+HRESULT Console::i_onCaptureChange()
 {
     AutoCaller autoCaller(this);
@@ -5675,6 +5672,10 @@
     if (ptrVM.isOk())
     {
+        ComPtr<ICaptureSettings> CaptureSettings;
+        rc = mMachine->COMGETTER(CaptureSettings)(CaptureSettings.asOutParam());
+        AssertComRCReturnRC(rc);
+
         BOOL fEnabled;
-        rc = mMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled);
+        rc = CaptureSettings->COMGETTER(Enabled)(&fEnabled);
         AssertComRCReturnRC(rc);
 
@@ -5683,5 +5684,5 @@
         {
             alock.release();
-            fireVideoCaptureChangedEvent(mEventSource);
+            fireCaptureChangedEvent(mEventSource);
         }
 
@@ -6867,10 +6868,13 @@
  * @param   uTimestampMs        Timestamp (in ms) of audio data.
  */
-HRESULT Console::i_audioVideoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs)
-{
-    if (mDisplay)
-    {
-        int rc2 = mDisplay->i_videoRecSendAudio(pvData, cbData, uTimestampMs);
-        AssertRC(rc2);
+HRESULT Console::i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs)
+{
+    if (!Capture.mpVideoRecCtx)
+        return S_OK;
+
+    if (   Capture.mpVideoRecCtx->IsStarted()
+        && Capture.mpVideoRecCtx->IsFeatureEnabled(CaptureFeature_Audio))
+    {
+        return Capture.mpVideoRecCtx->SendAudioFrame(pvData, cbData, uTimestampMs);
     }
 
@@ -6878,4 +6882,123 @@
 }
 #endif /* VBOX_WITH_AUDIO_VIDEOREC */
+
+#ifdef VBOX_WITH_VIDEOREC
+int Console::i_videoRecLoad(settings::CaptureSettings &Settings)
+{
+    Assert(mMachine.isNotNull());
+
+    ComPtr<ICaptureSettings> pCaptureSettings;
+    HRESULT hrc = mMachine->COMGETTER(CaptureSettings)(pCaptureSettings.asOutParam());
+    AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+
+    SafeIfaceArray<ICaptureScreenSettings> paCaptureScreens;
+    hrc = pCaptureSettings->GetScreens(ComSafeArrayAsOutParam(paCaptureScreens));
+    AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+
+    Settings.mapScreens.clear();
+
+    for (size_t i = 0; i < paCaptureScreens.size(); ++i)
+    {
+        settings::CaptureScreenSettings CaptureScreenSettings;
+        ComPtr<ICaptureScreenSettings> pCaptureScreenSettings = paCaptureScreens[i];
+
+        hrc = pCaptureScreenSettings->COMGETTER(MaxTime)((ULONG *)&CaptureScreenSettings.ulMaxTimeS);
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+        hrc = pCaptureScreenSettings->COMGETTER(MaxFileSize)((ULONG *)&CaptureScreenSettings.File.ulMaxSizeMB);
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+        Bstr bstrTemp;
+        hrc = pCaptureScreenSettings->COMGETTER(FileName)(bstrTemp.asOutParam());
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+        CaptureScreenSettings.File.strName = bstrTemp;
+        hrc = pCaptureScreenSettings->COMGETTER(Options)(bstrTemp.asOutParam());
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+        CaptureScreenSettings.strOptions = bstrTemp;
+        hrc = pCaptureScreenSettings->COMGETTER(VideoWidth)((ULONG *)&CaptureScreenSettings.Video.ulWidth);
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+        hrc = pCaptureScreenSettings->COMGETTER(VideoHeight)((ULONG *)&CaptureScreenSettings.Video.ulHeight);
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+        hrc = pCaptureScreenSettings->COMGETTER(VideoRate)((ULONG *)&CaptureScreenSettings.Video.ulRate);
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+        hrc = pCaptureScreenSettings->COMGETTER(VideoFPS)((ULONG *)&CaptureScreenSettings.Video.ulFPS);
+        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
+
+        Settings.mapScreens[i] = CaptureScreenSettings;
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Starts capturing. Does nothing if capturing is already active.
+ *
+ * @returns IPRT status code.
+ */
+int Console::i_videoRecStart(void)
+{
+    if (Capture.mpVideoRecCtx && Capture.mpVideoRecCtx->IsStarted())
+        return VINF_SUCCESS;
+
+    LogRel(("VideoRec: Starting ...\n"));
+
+    try
+    {
+        Capture.mpVideoRecCtx = new CaptureContext(this);
+    }
+    catch (std::bad_alloc &)
+    {
+        return VERR_NO_MEMORY;
+    }
+    catch (int &rc)
+    {
+        return rc;
+    }
+
+    settings::CaptureSettings Settings;
+    int rc = i_videoRecLoad(Settings);
+    if (RT_SUCCESS(rc))
+    {
+        rc = Capture.mpVideoRecCtx->Create(Settings);
+        if (RT_SUCCESS(rc))
+        {
+            for (unsigned uScreen = 0; uScreen < Capture.mpVideoRecCtx->GetStreamCount(); uScreen++)
+                mDisplay->i_videoRecScreenChanged(uScreen);
+        }
+    }
+
+    if (RT_FAILURE(rc))
+        LogRel(("VideoRec: Failed to start video recording (%Rrc)\n", rc));
+
+    return rc;
+}
+
+/**
+ * Stops capturing. Does nothing if capturing is not active.
+ */
+int Console::i_videoRecStop(void)
+{
+    if (Capture.mpVideoRecCtx && Capture.mpVideoRecCtx->IsStarted())
+        return VINF_SUCCESS;
+
+    LogRel(("VideoRec: Stopping ...\n"));
+
+    const size_t cStreams = Capture.mpVideoRecCtx->GetStreamCount();
+
+    for (unsigned uScreen = 0; uScreen < cStreams; ++uScreen)
+        mDisplay->i_videoRecScreenChanged(uScreen);
+
+    delete Capture.mpVideoRecCtx;
+    Capture.mpVideoRecCtx = NULL;
+
+    ComPtr<ICaptureSettings> pCaptureSettings;
+    HRESULT hrc = mMachine->COMGETTER(CaptureSettings)(pCaptureSettings.asOutParam());
+    ComAssertComRC(hrc);
+    hrc = pCaptureSettings->COMSETTER(Enabled)(false);
+    ComAssertComRC(hrc);
+
+    LogRel(("VideoRec: Stopped\n"));
+
+    return VINF_SUCCESS;
+}
+#endif /* VBOX_WITH_VIDEOREC */
 
 /**
@@ -9966,14 +10089,18 @@
 
 #ifdef VBOX_WITH_VIDEOREC
-        BOOL fVideoRecEnabled = FALSE;
-        rc = pConsole->mMachine->COMGETTER(VideoCaptureEnabled)(&fVideoRecEnabled);
+        ComPtr<ICaptureSettings> CaptureSettings;
+        rc = pConsole->mMachine->COMGETTER(CaptureSettings)(CaptureSettings.asOutParam());
         AssertComRCReturnVoid(rc);
 
-        if (fVideoRecEnabled)
-        {
-            int vrc2 = pConsole->i_videoCaptureEnable(fVideoRecEnabled, &alock);
+        BOOL fCaptureEnabled;
+        rc = CaptureSettings->COMGETTER(Enabled)(&fCaptureEnabled);
+        AssertComRCReturnVoid(rc);
+
+        if (fCaptureEnabled)
+        {
+            int vrc2 = pConsole->i_videoCaptureEnable(fCaptureEnabled, &alock);
             if (RT_SUCCESS(vrc2))
             {
-                fireVideoCaptureChangedEvent(pConsole->mEventSource);
+                fireCaptureChangedEvent(pConsole->mEventSource);
             }
             else
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 75251)
@@ -2998,5 +2998,5 @@
                 InsertConfigString(pLunL0, "Driver", "AUDIO");
             AudioDriverCfg DrvCfgVideoRec(strAudioDevice, 0 /* Instance */, uAudioLUN, "AudioVideoRec");
-            rc = mAudioVideoRec->InitializeConfig(&DrvCfgVideoRec);
+            rc = Capture.mAudioVideoRec->InitializeConfig(&DrvCfgVideoRec);
             if (RT_SUCCESS(rc))
                 uAudioLUN++;
Index: /trunk/src/VBox/Main/src-client/DisplayImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 75251)
@@ -150,5 +150,4 @@
     AssertRC(rc);
 
-    mpVideoRecCtx = NULL;
     for (unsigned i = 0; i < RT_ELEMENTS(maVideoRecEnabled); i++)
         maVideoRecEnabled[i] = true;
@@ -2408,185 +2407,28 @@
 #ifdef VBOX_WITH_VIDEOREC
 /**
- * Returns the currently enabled video capturing features.
+ * Invalidates the capturing configuration.
  *
- * @returns Enables video capturing features.
+ * @returns IPRT status code.
  */
-VIDEORECFEATURES Display::i_videoRecGetFeatures(void)
-{
-    return VideoRecGetFeatures(&mVideoRecCfg);
-}
-
-/**
- * Returns whether video capturing is currently is active or not.
- *
- * @returns True if video capturing is active, false if not.
- */
-bool Display::i_videoRecStarted(void)
-{
-    return VideoRecIsStarted(mpVideoRecCtx);
-}
-
-/**
- * Invalidates the video recording configuration.
- */
-void Display::i_videoRecInvalidate(void)
-{
-    AssertPtr(mParent);
-    ComPtr<IMachine> pMachine = mParent->i_machine();
-    Assert(pMachine.isNotNull());
-
-    mVideoRecCfg.enmDst = VIDEORECDEST_FILE; /** @todo Make this configurable once we have more variations. */
-
-    /*
-     * Cache parameters from API.
-     */
-    com::SafeArray<BOOL> aScreens;
-    HRESULT hrc = pMachine->COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(aScreens));
-    AssertComRCReturnVoid(hrc);
-
-    mVideoRecCfg.aScreens.resize(aScreens.size());
-    for (size_t i = 0; i < aScreens.size(); ++i)
-        mVideoRecCfg.aScreens[i] = aScreens[i];
-
-    hrc = pMachine->COMGETTER(VideoCaptureWidth)((ULONG *)&mVideoRecCfg.Video.uWidth);
-    AssertComRCReturnVoid(hrc);
-    hrc = pMachine->COMGETTER(VideoCaptureHeight)((ULONG *)&mVideoRecCfg.Video.uHeight);
-    AssertComRCReturnVoid(hrc);
-    hrc = pMachine->COMGETTER(VideoCaptureRate)((ULONG *)&mVideoRecCfg.Video.uRate);
-    AssertComRCReturnVoid(hrc);
-    hrc = pMachine->COMGETTER(VideoCaptureFPS)((ULONG *)&mVideoRecCfg.Video.uFPS);
-    AssertComRCReturnVoid(hrc);
-    hrc = pMachine->COMGETTER(VideoCaptureFile)(mVideoRecCfg.File.strName.asOutParam());
-    AssertComRCReturnVoid(hrc);
-    hrc = pMachine->COMGETTER(VideoCaptureMaxFileSize)((ULONG *)&mVideoRecCfg.File.uMaxSizeMB);
-    AssertComRCReturnVoid(hrc);
-    hrc = pMachine->COMGETTER(VideoCaptureMaxTime)((ULONG *)&mVideoRecCfg.uMaxTimeS);
-    AssertComRCReturnVoid(hrc);
-    BSTR bstrOptions;
-    hrc = pMachine->COMGETTER(VideoCaptureOptions)(&bstrOptions);
-    AssertComRCReturnVoid(hrc);
-
-    /*
-     * Set sensible defaults.
-     */
-    mVideoRecCfg.Video.fEnabled = true; /* Enabled by default. */
-
-    if (!mVideoRecCfg.Video.uFPS) /* Prevent division by zero. */
-        mVideoRecCfg.Video.uFPS = 15;
-
-#ifdef VBOX_WITH_LIBVPX
-    mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = 1000000 / mVideoRecCfg.Video.uFPS;
-#endif
-
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-    mVideoRecCfg.Audio.fEnabled  = false; /* Disabled by default, unless set otherwise below. */
-    /* By default we use 22,5kHz, 16-bit, stereo for the audio track. */
-    mVideoRecCfg.Audio.uHz       = 22050;
-    mVideoRecCfg.Audio.cBits     = 16;
-    mVideoRecCfg.Audio.cChannels = 2;
-#endif
-
-    /*
-     * Parse options string.
-     */
-    com::Utf8Str strOptions(bstrOptions);
-    size_t pos = 0;
-    com::Utf8Str key, value;
-    while ((pos = strOptions.parseKeyValue(key, value, pos)) != com::Utf8Str::npos)
-    {
-        if (key.compare("vc_quality", Utf8Str::CaseInsensitive) == 0)
-        {
-#ifdef VBOX_WITH_LIBVPX
-            if (value.compare("realtime", Utf8Str::CaseInsensitive) == 0)
-                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = VPX_DL_REALTIME;
-            else if (value.compare("good", Utf8Str::CaseInsensitive) == 0)
-                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = 1000000 / mVideoRecCfg.Video.uFPS;
-            else if (value.compare("best", Utf8Str::CaseInsensitive) == 0)
-                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = VPX_DL_BEST_QUALITY;
-            else
-            {
-                LogRel(("VideoRec: Setting quality deadline to '%s'\n", value.c_str()));
-                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = value.toUInt32();
-#endif
-            }
-        }
-        else if (key.compare("vc_enabled", Utf8Str::CaseInsensitive) == 0)
-        {
-            if (value.compare("false", Utf8Str::CaseInsensitive) == 0)
-            {
-                mVideoRecCfg.Video.fEnabled = false;
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-                LogRel(("VideoRec: Only audio will be recorded\n"));
-#endif
-            }
-        }
-        else if (key.compare("ac_enabled", Utf8Str::CaseInsensitive) == 0)
-        {
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-            if (value.compare("true", Utf8Str::CaseInsensitive) == 0)
-            {
-                mVideoRecCfg.Audio.fEnabled = true;
-
-            }
-            else
-                LogRel(("VideoRec: Only video will be recorded\n"));
-#endif
-        }
-        else if (key.compare("ac_profile", Utf8Str::CaseInsensitive) == 0)
-        {
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-            if (value.compare("low", Utf8Str::CaseInsensitive) == 0)
-            {
-                mVideoRecCfg.Audio.uHz       = 8000;
-                mVideoRecCfg.Audio.cBits     = 16;
-                mVideoRecCfg.Audio.cChannels = 1;
-            }
-            else if (value.startsWith("med" /* "med[ium]" */, Utf8Str::CaseInsensitive) == 0)
-            {
-                /* Stay with the default set above. */
-            }
-            else if (value.compare("high", Utf8Str::CaseInsensitive) == 0)
-            {
-                mVideoRecCfg.Audio.uHz       = 48000;
-                mVideoRecCfg.Audio.cBits     = 16;
-                mVideoRecCfg.Audio.cChannels = 2;
-            }
-#endif
-        }
-        else
-            LogRel(("VideoRec: Unknown option '%s' (value '%s'), skipping\n", key.c_str(), value.c_str()));
-
-    } /* while */
+int Display::i_videoRecInvalidate(void)
+{
+    CaptureContext *pCtx = mParent->i_videoRecGetContext();
+    if (!pCtx || !pCtx->IsStarted())
+        return VINF_SUCCESS;
 
     /*
      * Invalidate screens.
      */
-    for (unsigned i = 0; i < mVideoRecCfg.aScreens.size(); i++)
-    {
-        bool fChanged = maVideoRecEnabled[i] != RT_BOOL(mVideoRecCfg.aScreens[i]);
-
-        maVideoRecEnabled[i] = RT_BOOL(mVideoRecCfg.aScreens[i]);
-
-        if (fChanged && i < mcMonitors)
-            i_videoRecScreenChanged(i);
-
-    }
-}
-
-/**
- * Sends belonging audio samples to the video capturing code.
- * Does nothing if capturing is disabled or if audio support for video capturing is disabled.
- *
- * @returns IPRT status code.
- * @param   pvData              Audio data.
- * @param   cbData              Size (in bytes) of audio data.
- * @param   uTimestampMs        Timestamp (in ms) of the audio data.
- */
-int Display::i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs)
-{
-    if (   VideoRecIsStarted(mpVideoRecCtx)
-        && VideoRecGetFeatures(&mVideoRecCfg) & VIDEORECFEATURE_AUDIO)
-    {
-        return VideoRecSendAudioFrame(mpVideoRecCtx, pvData, cbData, uTimestampMs);
+    for (unsigned uScreen = 0; uScreen < mcMonitors; uScreen++)
+    {
+        CaptureStream *pCaptureStream = pCtx->GetStream(uScreen);
+
+        const bool fStreamEnabled = pCaptureStream->IsReady();
+              bool fChanged       = maVideoRecEnabled[uScreen] != fStreamEnabled;
+
+        maVideoRecEnabled[uScreen] = fStreamEnabled;
+
+        if (fChanged && uScreen < mcMonitors)
+            i_videoRecScreenChanged(uScreen);
     }
 
@@ -2594,63 +2436,10 @@
 }
 
-/**
- * Start video capturing. Does nothing if capturing is already active.
- *
- * @param   pVideoRecCfg        Video recording configuration to use.
- * @returns IPRT status code.
- */
-int Display::i_videoRecStart(void)
-{
-    if (VideoRecIsStarted(mpVideoRecCtx))
-        return VINF_SUCCESS;
-
-    LogRel(("VideoRec: Starting ...\n"));
-
-    int rc = VideoRecContextCreate(mcMonitors, &mVideoRecCfg, &mpVideoRecCtx);
-    if (RT_SUCCESS(rc))
-    {
-        for (unsigned uScreen = 0; uScreen < mcMonitors; uScreen++)
-        {
-            int rc2 = VideoRecStreamInit(VideoRecGetStream(mpVideoRecCtx, uScreen), mpVideoRecCtx, uScreen);
-            if (RT_SUCCESS(rc2))
-            {
-                i_videoRecScreenChanged(uScreen);
-            }
-            else
-                LogRel(("VideoRec: Failed to initialize video recording context #%u (%Rrc)\n", uScreen, rc2));
-
-            if (RT_SUCCESS(rc))
-                rc = rc2;
-        }
-    }
-
-    if (RT_FAILURE(rc))
-        LogRel(("VideoRec: Failed to start video recording (%Rrc)\n", rc));
-
-    return rc;
-}
-
-/**
- * Stops video capturing. Does nothing if video capturing is not active.
- */
-void Display::i_videoRecStop(void)
-{
-    if (!VideoRecIsStarted(mpVideoRecCtx))
-        return;
-
-    LogRel(("VideoRec: Stopping ...\n"));
-
-    VideoRecContextDestroy(mpVideoRecCtx);
-    mpVideoRecCtx = NULL;
-
-    unsigned uScreenId;
-    for (uScreenId = 0; uScreenId < mcMonitors; ++uScreenId)
-        i_videoRecScreenChanged(uScreenId);
-}
-
 void Display::i_videoRecScreenChanged(unsigned uScreenId)
 {
-    if (   !VideoRecIsStarted(mpVideoRecCtx)
-        || !maVideoRecEnabled[uScreenId])
+    CaptureContext *pCtx = mParent->i_videoRecGetContext();
+
+    if (   RT_LIKELY(!maVideoRecEnabled[uScreenId])
+        || !pCtx || !pCtx->IsStarted())
     {
         /* Skip recording this screen. */
@@ -3599,6 +3388,10 @@
 
 #ifdef VBOX_WITH_VIDEOREC
-    if (   VideoRecIsStarted(pDisplay->mpVideoRecCtx)
-        && VideoRecGetFeatures(&pDisplay->mVideoRecCfg) & VIDEORECFEATURE_VIDEO)
+    AssertPtr(pDisplay->mParent);
+    CaptureContext *pCtx = pDisplay->mParent->i_videoRecGetContext();
+
+    if (   pCtx
+        && pCtx->IsStarted()
+        && pCtx->IsFeatureEnabled(CaptureFeature_Video))
     {
         do {
@@ -3638,5 +3431,5 @@
 # endif /* VBOX_WITH_HGCM && VBOX_WITH_CROGL */
 
-            uint64_t u64Now = RTTimeProgramMilliTS();
+            uint64_t tsNowMs = RTTimeProgramMilliTS();
             for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
             {
@@ -3644,8 +3437,7 @@
                     continue;
 
-                if (VideoRecIsLimitReached(pDisplay->mpVideoRecCtx, uScreenId, u64Now))
+                if (pCtx->IsLimitReached(uScreenId, tsNowMs))
                 {
-                    pDisplay->i_videoRecStop();
-                    pDisplay->mParent->i_machine()->COMSETTER(VideoCaptureEnabled)(false);
+                    pDisplay->mParent->i_videoRecStop();
                     break;
                 }
@@ -3677,8 +3469,7 @@
                                                                     &bitmapFormat);
                         if (SUCCEEDED(hr) && pbAddress)
-                            rc = VideoRecSendVideoFrame(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
-                                                        BitmapFormat_BGR,
-                                                        ulBitsPerPixel, ulBytesPerLine, ulWidth, ulHeight,
-                                                        pbAddress, u64Now);
+                            rc = pCtx->SendVideoFrame(uScreenId, 0, 0, BitmapFormat_BGR,
+                                                      ulBitsPerPixel, ulBytesPerLine, ulWidth, ulHeight,
+                                                      pbAddress, tsNowMs);
                         else
                             rc = VERR_NOT_SUPPORTED;
@@ -4039,20 +3830,19 @@
 }
 
-bool  Display::i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64Timestamp)
-{
-    /** @todo r=bird: u64Timestamp - using the 'u64' prefix add nothing.
-     *        However, using one of the prefixes indicating the timestamp unit
-     *        would be very valuable!  */
+bool  Display::i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t uTimestampMs)
+{
 # ifdef VBOX_WITH_VIDEOREC
-    return VideoRecIsReady(mpVideoRecCtx, uScreen, u64Timestamp);
+    CaptureContext *pCtx = mParent->i_videoRecGetContext();
+    return (      pCtx
+               && pCtx->IsReady(uScreen, uTimestampMs));
 # else
-    RT_NOREF(uScreen, u64Timestamp);
+    RT_NOREF(uScreen, uTimestampMs);
     return false;
 # endif
 }
 
-void  Display::i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64Timestamp)
-{
-    RT_NOREF(uScreen, u64Timestamp);
+void  Display::i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t uTimestampMs)
+{
+    RT_NOREF(uScreen, uTimestampMs);
 }
 
@@ -4061,16 +3851,19 @@
                                                uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
                                                uint32_t uGuestWidth, uint32_t uGuestHeight,
-                                               uint8_t *pu8BufferAddress, uint64_t u64Timestamp)
+                                               uint8_t *pu8BufferAddress, uint64_t uTimestampMs)
 {
     Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED);
 # ifdef VBOX_WITH_VIDEOREC
-    if (   VideoRecIsStarted(mpVideoRecCtx)
-        && VideoRecGetFeatures(&mVideoRecCfg) & VIDEORECFEATURE_VIDEO)
-    {
-        int rc2 = VideoRecSendVideoFrame(mpVideoRecCtx, uScreen, x, y,
-                                         uPixelFormat,
-                                         uBitsPerPixel, uBytesPerLine,
-                                         uGuestWidth, uGuestHeight,
-                                         pu8BufferAddress, u64Timestamp);
+    CaptureContext *pCtx = mParent->i_videoRecGetContext();
+
+    if (   pCtx
+        && pCtx->IsStarted()
+        && pCtx->IsFeatureEnabled(CaptureFeature_Video))
+    {
+        int rc2 = pCtx->SendVideoFrame(uScreen, x, y,
+                                       uPixelFormat,
+                                       uBitsPerPixel, uBytesPerLine,
+                                       uGuestWidth, uGuestHeight,
+                                       pu8BufferAddress, uTimestampMs);
         RT_NOREF(rc2);
         Assert(rc2 == VINF_SUCCESS /* || rc == VERR_TRY_AGAIN || rc == VINF_TRY_AGAIN*/);
@@ -4078,5 +3871,5 @@
 # else
     RT_NOREF(uScreen, x, y, uPixelFormat, \
-             uBitsPerPixel, uBytesPerLine, uGuestWidth, uGuestHeight, pu8BufferAddress, u64Timestamp);
+             uBitsPerPixel, uBytesPerLine, uGuestWidth, uGuestHeight, pu8BufferAddress, uTimestampMs);
 # endif /* VBOX_WITH_VIDEOREC */
 }
@@ -4706,5 +4499,5 @@
         AutoWriteLock displayLock(pThis->pDisplay COMMA_LOCKVAL_SRC_POS);
 #ifdef VBOX_WITH_VIDEOREC
-        pThis->pDisplay->i_videoRecStop();
+        pThis->pDisplay->mParent->i_videoRecStop();
 #endif
 #ifdef VBOX_WITH_CRHGSMI
Index: /trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp	(revision 75251)
@@ -828,5 +828,5 @@
                 case AVRECCONTAINERTYPE_MAIN_CONSOLE:
                 {
-                    HRESULT hr = pSink->Con.Main.pConsole->i_audioVideoRecSendAudio(pStreamAV->pvDstBuf, cbDst, uPTSMs);
+                    HRESULT hr = pSink->Con.Main.pConsole->i_videoRecSendAudio(pStreamAV->pvDstBuf, cbDst, uPTSMs);
                     Assert(hr == S_OK);
                     RT_NOREF(hr);
@@ -1086,10 +1086,10 @@
  *
  * @returns IPRT status code.
- * @param   pVideoRecCfg        Pointer to video recording configuration to apply.
- */
-int AudioVideoRec::applyConfiguration(const PVIDEORECCFG pVideoRecCfg)
+ * @param   Settings        Capturing configuration to apply.
+ */
+int AudioVideoRec::applyConfiguration(const settings::CaptureSettings &a_Settings)
 {
     /** @todo Do some validation here. */
-    mVideoRecCfg = *pVideoRecCfg; /* Note: Does have an own copy operator. */
+    mVideoRecCfg = a_Settings; /* Note: Does have an own copy operator. */
     return VINF_SUCCESS;
 }
@@ -1101,21 +1101,25 @@
 int AudioVideoRec::configureDriver(PCFGMNODE pLunCfg)
 {
-    int rc = CFGMR3InsertInteger(pLunCfg, "Object",    (uintptr_t)mpConsole->i_getAudioVideoRec());
+    int rc = CFGMR3InsertInteger(pLunCfg, "Object",    (uintptr_t)mpConsole->i_videoRecGetAudioDrv());
     AssertRCReturn(rc, rc);
     rc = CFGMR3InsertInteger(pLunCfg, "ObjectConsole", (uintptr_t)mpConsole);
     AssertRCReturn(rc, rc);
 
-    rc = CFGMR3InsertInteger(pLunCfg, "ContainerType", (uint64_t)mVideoRecCfg.enmDst);
+    /** @todo For now we're using the configuration of the first screen here audio-wise. */
+    Assert(mVideoRecCfg.mapScreens.size() >= 1);
+    const settings::CaptureScreenSettings &Screen0Settings = mVideoRecCfg.mapScreens[0];
+
+    rc = CFGMR3InsertInteger(pLunCfg, "ContainerType", (uint64_t)Screen0Settings.enmDest);
     AssertRCReturn(rc, rc);
-    if (mVideoRecCfg.enmDst == VIDEORECDEST_FILE)
-    {
-        rc = CFGMR3InsertString(pLunCfg, "ContainerFileName", Utf8Str(mVideoRecCfg.File.strName).c_str());
+    if (Screen0Settings.enmDest == CaptureDestination_File)
+    {
+        rc = CFGMR3InsertString(pLunCfg, "ContainerFileName", Utf8Str(Screen0Settings.File.strName).c_str());
         AssertRCReturn(rc, rc);
     }
-    rc = CFGMR3InsertInteger(pLunCfg, "CodecHz", mVideoRecCfg.Audio.uHz);
+    rc = CFGMR3InsertInteger(pLunCfg, "CodecHz", Screen0Settings.Audio.uHz);
     AssertRCReturn(rc, rc);
-    rc = CFGMR3InsertInteger(pLunCfg, "CodecBits", mVideoRecCfg.Audio.cBits);
+    rc = CFGMR3InsertInteger(pLunCfg, "CodecBits", Screen0Settings.Audio.cBits);
     AssertRCReturn(rc, rc);
-    rc = CFGMR3InsertInteger(pLunCfg, "CodecChannels", mVideoRecCfg.Audio.cChannels);
+    rc = CFGMR3InsertInteger(pLunCfg, "CodecChannels", Screen0Settings.Audio.cChannels);
     AssertRCReturn(rc, rc);
     rc = CFGMR3InsertInteger(pLunCfg, "CodecBitrate", 0); /* Let Opus decide for now. */
Index: /trunk/src/VBox/Main/src-client/SessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 75251)
@@ -725,15 +725,15 @@
 }
 
-HRESULT Session::onVideoCaptureChange()
-{
-    LogFlowThisFunc(("\n"));
-
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
-#ifndef VBOX_COM_INPROC_API_CLIENT
-    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
-
-    return mConsole->i_onVideoCaptureChange();
+HRESULT Session::onCaptureChange()
+{
+    LogFlowThisFunc(("\n"));
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+#ifndef VBOX_COM_INPROC_API_CLIENT
+    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
+
+    return mConsole->i_onCaptureChange();
 #else
     return S_OK;
Index: /trunk/src/VBox/Main/src-client/VideoRec.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/VideoRec.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-client/VideoRec.cpp	(revision 75251)
@@ -43,9 +43,10 @@
 #include <VBox/com/VirtualBox.h>
 
-#include "WebMWriter.h"
+#include "ConsoleImpl.h"
 #include "VideoRec.h"
 #include "VideoRecInternals.h"
 #include "VideoRecStream.h"
 #include "VideoRecUtils.h"
+#include "WebMWriter.h"
 
 using namespace com;
@@ -103,4 +104,20 @@
 
 
+CaptureContext::CaptureContext(Console *a_pConsole)
+    : pConsole(a_pConsole) { }
+
+CaptureContext::CaptureContext(Console *a_pConsole, const settings::CaptureSettings &a_Settings)
+    : pConsole(a_pConsole)
+{
+    int rc = CaptureContext::createInternal(a_Settings);
+    if (RT_FAILURE(rc))
+        throw rc;
+}
+
+CaptureContext::~CaptureContext(void)
+{
+    destroyInternal();
+}
+
 /**
  * Worker thread for all streams of a video recording context.
@@ -108,7 +125,7 @@
  * For video frames, this also does the RGB/YUV conversion and encoding.
  */
-static DECLCALLBACK(int) videoRecThread(RTTHREAD hThreadSelf, void *pvUser)
-{
-    PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)pvUser;
+DECLCALLBACK(int) CaptureContext::threadMain(RTTHREAD hThreadSelf, void *pvUser)
+{
+    CaptureContext *pThis = (CaptureContext *)pvUser;
 
     /* Signal that we're up and rockin'. */
@@ -119,18 +136,18 @@
     for (;;)
     {
-        int rc = RTSemEventWait(pCtx->WaitEvent, RT_INDEFINITE_WAIT);
+        int rc = RTSemEventWait(pThis->WaitEvent, RT_INDEFINITE_WAIT);
         AssertRCBreak(rc);
 
-        Log2Func(("Processing %zu streams\n", pCtx->vecStreams.size()));
+        Log2Func(("Processing %zu streams\n", pThis->vecStreams.size()));
 
         /** @todo r=andy This is inefficient -- as we already wake up this thread
          *               for every screen from Main, we here go again (on every wake up) through
          *               all screens.  */
-        VideoRecStreams::iterator itStream = pCtx->vecStreams.begin();
-        while (itStream != pCtx->vecStreams.end())
-        {
-            PVIDEORECSTREAM pStream = (*itStream);
-
-            rc = VideoRecStreamProcess(pStream);
+        VideoRecStreams::iterator itStream = pThis->vecStreams.begin();
+        while (itStream != pThis->vecStreams.end())
+        {
+            CaptureStream *pStream = (*itStream);
+
+            rc = pStream->Process(pThis->mapBlocksCommon);
             if (RT_FAILURE(rc))
                 break;
@@ -144,5 +161,5 @@
         /* Keep going in case of errors. */
 
-        if (ASMAtomicReadBool(&pCtx->fShutdown))
+        if (ASMAtomicReadBool(&pThis->fShutdown))
         {
             LogFunc(("Thread is shutting down ...\n"));
@@ -160,11 +177,8 @@
  *
  * @returns IPRT status code.
- * @param   pCtx                Video recording context to notify thread for.
- */
-static int videoRecThreadNotify(PVIDEORECCONTEXT pCtx)
-{
-    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
-
-    return RTSemEventSignal(pCtx->WaitEvent);
+ */
+int CaptureContext::threadNotify(void)
+{
+    return RTSemEventSignal(this->WaitEvent);
 }
 
@@ -175,35 +189,19 @@
  * @param   cScreens            Number of screens to create context for.
  * @param   pVideoRecCfg        Pointer to video recording configuration to use.
- * @param   ppCtx               Pointer to created video recording context on success.
- */
-int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCFG pVideoRecCfg, PVIDEORECCONTEXT *ppCtx)
-{
-    AssertReturn(cScreens,        VERR_INVALID_PARAMETER);
-    AssertPtrReturn(pVideoRecCfg, VERR_INVALID_POINTER);
-    AssertPtrReturn(ppCtx,        VERR_INVALID_POINTER);
-
-    VIDEORECCONTEXT *pCtx = NULL;
-    try
-    {
-        pCtx = new VIDEORECCONTEXT();
-    }
-    catch (std::bad_alloc &)
-    {
-        return VERR_NO_MEMORY;
-    }
-
-    int rc = RTCritSectInit(&pCtx->CritSect);
+ */
+int CaptureContext::createInternal(const settings::CaptureSettings &a_Settings)
+{
+    int rc = RTCritSectInit(&this->CritSect);
     if (RT_FAILURE(rc))
-    {
-        delete pCtx;
         return rc;
-    }
-
-    for (uint32_t uScreen = 0; uScreen < cScreens; uScreen++)
-    {
-        VIDEORECSTREAM *pStream = NULL;
+
+    settings::CaptureScreenMap::const_iterator itScreen = a_Settings.mapScreens.begin();
+    while (itScreen != a_Settings.mapScreens.end())
+    {
+        CaptureStream *pStream = NULL;
         try
         {
-            pStream = new VIDEORECSTREAM();
+            pStream = new CaptureStream(itScreen->first /* Screen ID */, itScreen->second);
+            this->vecStreams.push_back(pStream);
         }
         catch (std::bad_alloc &)
@@ -212,50 +210,29 @@
             break;
         }
-
-        rc = RTCritSectInit(&pStream->CritSect);
-        if (RT_FAILURE(rc))
-            break;
-
-        try
-        {
-            pStream->uScreenID = uScreen;
-
-            pCtx->vecStreams.push_back(pStream);
-
-            pStream->File.pWEBM = new WebMWriter();
-        }
-        catch (std::bad_alloc &)
-        {
-            rc = VERR_NO_MEMORY;
-            break;
-        }
     }
 
     if (RT_SUCCESS(rc))
     {
-        pCtx->tsStartMs = RTTimeMilliTS();
-        pCtx->enmState  = VIDEORECSTS_UNINITIALIZED;
-        pCtx->fStarted  = false;
-        pCtx->fShutdown = false;
-
-        /* Copy the configuration to our context. */
-        pCtx->Cfg       = *pVideoRecCfg;
-
-        rc = RTSemEventCreate(&pCtx->WaitEvent);
+        this->tsStartMs = RTTimeMilliTS();
+        this->enmState  = VIDEORECSTS_UNINITIALIZED;
+        this->fStarted  = false;
+        this->fShutdown = false;
+
+        /* Copy the settings to our context. */
+        this->Settings  = a_Settings;
+
+        rc = RTSemEventCreate(&this->WaitEvent);
         AssertRCReturn(rc, rc);
 
-        rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void *)pCtx, 0,
+        rc = RTThreadCreate(&this->Thread, CaptureContext::threadMain, (void *)this, 0,
                             RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec");
 
         if (RT_SUCCESS(rc)) /* Wait for the thread to start. */
-            rc = RTThreadUserWait(pCtx->Thread, 30 * RT_MS_1SEC /* 30s timeout */);
+            rc = RTThreadUserWait(this->Thread, 30 * RT_MS_1SEC /* 30s timeout */);
 
         if (RT_SUCCESS(rc))
         {
-            pCtx->enmState = VIDEORECSTS_INITIALIZED;
-            pCtx->fStarted = true;
-
-            if (ppCtx)
-                *ppCtx = pCtx;
+            this->enmState = VIDEORECSTS_INITIALIZED;
+            this->fStarted = true;
         }
     }
@@ -263,5 +240,5 @@
     if (RT_FAILURE(rc))
     {
-        int rc2 = VideoRecContextDestroy(pCtx);
+        int rc2 = destroyInternal();
         AssertRC(rc2);
     }
@@ -272,35 +249,30 @@
 /**
  * Destroys a video recording context.
- *
- * @param pCtx                  Video recording context to destroy.
- */
-int VideoRecContextDestroy(PVIDEORECCONTEXT pCtx)
-{
-    if (!pCtx)
-        return VINF_SUCCESS;
-
+ */
+int CaptureContext::destroyInternal(void)
+{
     int rc = VINF_SUCCESS;
 
-    if (pCtx->enmState == VIDEORECSTS_INITIALIZED)
+    if (this->enmState == VIDEORECSTS_INITIALIZED)
     {
         LogFunc(("Shutting down thread ...\n"));
 
         /* Set shutdown indicator. */
-        ASMAtomicWriteBool(&pCtx->fShutdown, true);
+        ASMAtomicWriteBool(&this->fShutdown, true);
 
         /* Signal the thread and wait for it to shut down. */
-        rc = videoRecThreadNotify(pCtx);
+        rc = threadNotify();
         if (RT_SUCCESS(rc))
-            rc = RTThreadWait(pCtx->Thread, 30 * 1000 /* 10s timeout */, NULL);
+            rc = RTThreadWait(this->Thread, 30 * 1000 /* 10s timeout */, NULL);
 
         if (RT_SUCCESS(rc))
         {
             /* Disable the context. */
-            ASMAtomicWriteBool(&pCtx->fStarted, false);
-
-            int rc2 = RTSemEventDestroy(pCtx->WaitEvent);
+            ASMAtomicWriteBool(&this->fStarted, false);
+
+            int rc2 = RTSemEventDestroy(this->WaitEvent);
             AssertRC(rc2);
 
-            pCtx->WaitEvent = NIL_RTSEMEVENT;
+            this->WaitEvent = NIL_RTSEMEVENT;
         }
     }
@@ -312,44 +284,34 @@
     }
 
-    rc = RTCritSectEnter(&pCtx->CritSect);
+    rc = RTCritSectEnter(&this->CritSect);
     if (RT_SUCCESS(rc))
     {
-        VideoRecStreams::iterator it = pCtx->vecStreams.begin();
-        while (it != pCtx->vecStreams.end())
-        {
-            PVIDEORECSTREAM pStream = (*it);
-
-            VideoRecStreamLock(pStream);
-
-            int rc2 = VideoRecStreamClose(pStream);
+        VideoRecStreams::iterator it = this->vecStreams.begin();
+        while (it != this->vecStreams.end())
+        {
+            CaptureStream *pStream = (*it);
+
+            int rc2 = pStream->Uninit();
             if (RT_SUCCESS(rc))
                 rc = rc2;
 
-            rc2 = VideoRecStreamUninit(pStream);
-            if (RT_SUCCESS(rc))
-                rc = rc2;
-
-            pCtx->vecStreams.erase(it);
-            it = pCtx->vecStreams.begin();
-
-            VideoRecStreamUnlock(pStream);
-
-            RTCritSectDelete(&pStream->CritSect);
-
             delete pStream;
             pStream = NULL;
+
+            this->vecStreams.erase(it);
+            it = this->vecStreams.begin();
+
+            delete pStream;
+            pStream = NULL;
         }
 
         /* Sanity. */
-        Assert(pCtx->vecStreams.empty());
-        Assert(pCtx->mapBlocksCommon.size() == 0);
-
-        int rc2 = RTCritSectLeave(&pCtx->CritSect);
+        Assert(this->vecStreams.empty());
+        Assert(this->mapBlocksCommon.size() == 0);
+
+        int rc2 = RTCritSectLeave(&this->CritSect);
         AssertRC(rc2);
 
-        RTCritSectDelete(&pCtx->CritSect);
-
-        delete pCtx;
-        pCtx = NULL;
+        RTCritSectDelete(&this->CritSect);
     }
 
@@ -357,26 +319,23 @@
 }
 
-/**
- * Returns which recording features currently are enabled for a given configuration.
- *
- * @returns Enabled video recording features.
- * @param   pCfg                Pointer to recording configuration.
- */
-VIDEORECFEATURES VideoRecGetFeatures(PVIDEORECCFG pCfg)
-{
-    if (!pCfg)
-        return VIDEORECFEATURE_NONE;
-
-    VIDEORECFEATURES fFeatures = VIDEORECFEATURE_NONE;
-
-    if (pCfg->Video.fEnabled)
-        fFeatures |= VIDEORECFEATURE_VIDEO;
-
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-    if (pCfg->Audio.fEnabled)
-        fFeatures |= VIDEORECFEATURE_AUDIO;
-#endif
-
-    return fFeatures;
+const settings::CaptureSettings &CaptureContext::GetConfig(void) const
+{
+    return this->Settings;
+}
+
+CaptureStream *CaptureContext::getStreamInternal(unsigned uScreen) const
+{
+    CaptureStream *pStream;
+
+    try
+    {
+        pStream = this->vecStreams.at(uScreen);
+    }
+    catch (std::out_of_range &)
+    {
+        pStream = NULL;
+    }
+
+    return pStream;
 }
 
@@ -385,23 +344,42 @@
  *
  * @returns Pointer to recording stream if found, or NULL if not found.
- * @param   pCtx                Recording context to look up stream for.
  * @param   uScreen             Screen number of recording stream to look up.
  */
-PVIDEORECSTREAM VideoRecGetStream(PVIDEORECCONTEXT pCtx, uint32_t uScreen)
-{
-    AssertPtrReturn(pCtx, NULL);
-
-    PVIDEORECSTREAM pStream;
-
-    try
-    {
-        pStream = pCtx->vecStreams.at(uScreen);
-    }
-    catch (std::out_of_range &)
-    {
-        pStream = NULL;
-    }
-
-    return pStream;
+CaptureStream *CaptureContext::GetStream(unsigned uScreen) const
+{
+    return getStreamInternal(uScreen);
+}
+
+size_t CaptureContext::GetStreamCount(void) const
+{
+    return this->vecStreams.size();
+}
+
+int CaptureContext::Create(const settings::CaptureSettings &a_Settings)
+{
+    return createInternal(a_Settings);
+}
+
+int CaptureContext::Destroy(void)
+{
+    return destroyInternal();
+}
+
+bool CaptureContext::IsFeatureEnabled(CaptureFeature_T enmFeature) const
+{
+    VideoRecStreams::const_iterator itStream = this->vecStreams.begin();
+    while (itStream != this->vecStreams.end())
+    {
+        if ((*itStream)->GetConfig().isFeatureEnabled(enmFeature))
+            return true;
+        ++itStream;
+    }
+
+    return false;
+}
+
+bool CaptureContext::IsReady(void) const
+{
+    return this->fStarted;
 }
 
@@ -410,25 +388,19 @@
  *
  * @returns true if recording engine is ready, false if not.
- * @param   pCtx                Pointer to video recording context.
  * @param   uScreen             Screen ID.
  * @param   uTimeStampMs        Current time stamp (in ms). Currently not being used.
  */
-bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t uTimeStampMs)
-{
-    AssertPtrReturn(pCtx, false);
+bool CaptureContext::IsReady(uint32_t uScreen, uint64_t uTimeStampMs) const
+{
     RT_NOREF(uTimeStampMs);
 
-    if (ASMAtomicReadU32(&pCtx->enmState) != VIDEORECSTS_INITIALIZED)
+    if (this->enmState != VIDEORECSTS_INITIALIZED)
         return false;
 
     bool fIsReady = false;
 
-    PVIDEORECSTREAM pStream = VideoRecGetStream(pCtx, uScreen);
+    const CaptureStream *pStream = GetStream(uScreen);
     if (pStream)
-    {
-        VideoRecStreamLock(pStream);
-        fIsReady = pStream->fEnabled;
-        VideoRecStreamUnlock(pStream);
-    }
+        fIsReady = pStream->IsReady();
 
     /* Note: Do not check for other constraints like the video FPS rate here,
@@ -443,12 +415,8 @@
  *
  * @returns true if active, false if not.
- * @param   pCtx                 Pointer to video recording context.
- */
-bool VideoRecIsStarted(PVIDEORECCONTEXT pCtx)
-{
-    if (!pCtx)
-        return false;
-
-    return ASMAtomicReadBool(&pCtx->fStarted);
+ */
+bool CaptureContext::IsStarted(void) const
+{
+    return this->fStarted;
 }
 
@@ -457,44 +425,16 @@
  *
  * @returns true if any limit has been reached.
- * @param   pCtx                Pointer to video recording context.
  * @param   uScreen             Screen ID.
  * @param   tsNowMs             Current time stamp (in ms).
  */
-bool VideoRecIsLimitReached(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t tsNowMs)
-{
-    PVIDEORECSTREAM pStream = VideoRecGetStream(pCtx, uScreen);
+bool CaptureContext::IsLimitReached(uint32_t uScreen, uint64_t tsNowMs) const
+{
+    const CaptureStream *pStream = GetStream(uScreen);
     if (   !pStream
-        || !pStream->fEnabled)
-    {
-        return false;
-    }
-
-    const PVIDEORECCFG pCfg = &pCtx->Cfg;
-
-    if (   pCfg->uMaxTimeS
-        && tsNowMs >= pCtx->tsStartMs + (pCfg->uMaxTimeS * RT_MS_1SEC))
+        || pStream->IsLimitReached(tsNowMs))
     {
         return true;
     }
 
-    if (pCfg->enmDst == VIDEORECDEST_FILE)
-    {
-
-        if (pCfg->File.uMaxSizeMB)
-        {
-            uint64_t sizeInMB = pStream->File.pWEBM->GetFileSize() / _1M;
-            if(sizeInMB >= pCfg->File.uMaxSizeMB)
-                return true;
-        }
-
-        /* Check for available free disk space */
-        if (   pStream->File.pWEBM
-            && pStream->File.pWEBM->GetAvailableSpace() < 0x100000) /** @todo r=andy WTF? Fix this. */
-        {
-            LogRel(("VideoRec: Not enough free storage space available, stopping video capture\n"));
-            return true;
-        }
-    }
-
     return false;
 }
@@ -506,10 +446,9 @@
  *
  * @returns IPRT status code.
- * @param   pCtx                Pointer to the video recording context.
  * @param   pvData              Audio frame data to send.
  * @param   cbData              Size (in bytes) of (encoded) audio frame data.
  * @param   uTimeStampMs        Time stamp (in ms) of audio playback.
  */
-int VideoRecSendAudioFrame(PVIDEORECCONTEXT pCtx, const void *pvData, size_t cbData, uint64_t uTimeStampMs)
+int CaptureContext::SendAudioFrame(const void *pvData, size_t cbData, uint64_t uTimeStampMs)
 {
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
@@ -537,8 +476,8 @@
     pBlock->pvData       = pFrame;
     pBlock->cbData       = sizeof(VIDEORECAUDIOFRAME) + cbData;
-    pBlock->cRefs        = (uint16_t)pCtx->vecStreams.size(); /* All streams need the same audio data. */
+    pBlock->cRefs        = (uint16_t)this->vecStreams.size(); /* All streams need the same audio data. */
     pBlock->uTimeStampMs = uTimeStampMs;
 
-    int rc = RTCritSectEnter(&pCtx->CritSect);
+    int rc = RTCritSectEnter(&this->CritSect);
     if (RT_FAILURE(rc))
         return rc;
@@ -546,11 +485,11 @@
     try
     {
-        VideoRecBlockMap::iterator itBlocks = pCtx->mapBlocksCommon.find(uTimeStampMs);
-        if (itBlocks == pCtx->mapBlocksCommon.end())
-        {
-            VideoRecBlocks *pVideoRecBlocks = new VideoRecBlocks();
+        VideoRecBlockMap::iterator itBlocks = this->mapBlocksCommon.find(uTimeStampMs);
+        if (itBlocks == this->mapBlocksCommon.end())
+        {
+            CaptureBlocks *pVideoRecBlocks = new CaptureBlocks();
             pVideoRecBlocks->List.push_back(pBlock);
 
-            pCtx->mapBlocksCommon.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks));
+            this->mapBlocksCommon.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks));
         }
         else
@@ -563,9 +502,9 @@
     }
 
-    int rc2 = RTCritSectLeave(&pCtx->CritSect);
+    int rc2 = RTCritSectLeave(&this->CritSect);
     AssertRC(rc2);
 
     if (RT_SUCCESS(rc))
-        rc = videoRecThreadNotify(pCtx);
+        rc = threadNotify();
 
     return rc;
@@ -583,6 +522,5 @@
  *
  * @returns IPRT status code.
- * @param   pCtx               Pointer to the video recording context.
- * @param   uScreen            Screen number.
+ * @param   uScreen            Screen number to send video frame to.
  * @param   x                  Starting x coordinate of the video frame.
  * @param   y                  Starting y coordinate of the video frame.
@@ -595,21 +533,20 @@
  * @param   uTimeStampMs       Time stamp (in ms).
  */
-int VideoRecSendVideoFrame(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint32_t x, uint32_t y,
-                           uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine,
-                           uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData,
-                           uint64_t uTimeStampMs)
-{
-    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
+int CaptureContext::SendVideoFrame(uint32_t uScreen, uint32_t x, uint32_t y,
+                                   uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine,
+                                   uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData,
+                                   uint64_t uTimeStampMs)
+{
     AssertReturn(uSrcWidth,  VERR_INVALID_PARAMETER);
     AssertReturn(uSrcHeight, VERR_INVALID_PARAMETER);
     AssertReturn(puSrcData,  VERR_INVALID_POINTER);
 
-    int rc = RTCritSectEnter(&pCtx->CritSect);
+    int rc = RTCritSectEnter(&this->CritSect);
     AssertRC(rc);
 
-    PVIDEORECSTREAM pStream = VideoRecGetStream(pCtx, uScreen);
+    CaptureStream *pStream = GetStream(uScreen);
     if (!pStream)
     {
-        rc = RTCritSectLeave(&pCtx->CritSect);
+        rc = RTCritSectLeave(&this->CritSect);
         AssertRC(rc);
 
@@ -617,216 +554,7 @@
     }
 
-    VideoRecStreamLock(pStream);
-
-    PVIDEORECVIDEOFRAME pFrame = NULL;
-
-    do
-    {
-        if (!pStream->fEnabled)
-        {
-            rc = VINF_TRY_AGAIN; /* Not (yet) enabled. */
-            break;
-        }
-
-        if (uTimeStampMs < pStream->Video.uLastTimeStampMs + pStream->Video.uDelayMs)
-        {
-            rc = VINF_TRY_AGAIN; /* Respect maximum frames per second. */
-            break;
-        }
-
-        pStream->Video.uLastTimeStampMs = uTimeStampMs;
-
-        int xDiff = ((int)pStream->Video.uWidth - (int)uSrcWidth) / 2;
-        uint32_t w = uSrcWidth;
-        if ((int)w + xDiff + (int)x <= 0)  /* Nothing visible. */
-        {
-            rc = VERR_INVALID_PARAMETER;
-            break;
-        }
-
-        uint32_t destX;
-        if ((int)x < -xDiff)
-        {
-            w += xDiff + x;
-            x = -xDiff;
-            destX = 0;
-        }
-        else
-            destX = x + xDiff;
-
-        uint32_t h = uSrcHeight;
-        int yDiff = ((int)pStream->Video.uHeight - (int)uSrcHeight) / 2;
-        if ((int)h + yDiff + (int)y <= 0)  /* Nothing visible. */
-        {
-            rc = VERR_INVALID_PARAMETER;
-            break;
-        }
-
-        uint32_t destY;
-        if ((int)y < -yDiff)
-        {
-            h += yDiff + (int)y;
-            y = -yDiff;
-            destY = 0;
-        }
-        else
-            destY = y + yDiff;
-
-        if (   destX > pStream->Video.uWidth
-            || destY > pStream->Video.uHeight)
-        {
-            rc = VERR_INVALID_PARAMETER;  /* Nothing visible. */
-            break;
-        }
-
-        if (destX + w > pStream->Video.uWidth)
-            w = pStream->Video.uWidth - destX;
-
-        if (destY + h > pStream->Video.uHeight)
-            h = pStream->Video.uHeight - destY;
-
-        pFrame = (PVIDEORECVIDEOFRAME)RTMemAllocZ(sizeof(VIDEORECVIDEOFRAME));
-        AssertBreakStmt(pFrame, rc = VERR_NO_MEMORY);
-
-        /* Calculate bytes per pixel and set pixel format. */
-        const unsigned uBytesPerPixel = uBPP / 8;
-        if (uPixelFormat == BitmapFormat_BGR)
-        {
-            switch (uBPP)
-            {
-                case 32:
-                    pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB32;
-                    break;
-                case 24:
-                    pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB24;
-                    break;
-                case 16:
-                    pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB565;
-                    break;
-                default:
-                    AssertMsgFailed(("Unknown color depth (%RU32)\n", uBPP));
-                    break;
-            }
-        }
-        else
-            AssertMsgFailed(("Unknown pixel format (%RU32)\n", uPixelFormat));
-
-        const size_t cbRGBBuf =   pStream->Video.uWidth
-                                * pStream->Video.uHeight
-                                * uBytesPerPixel;
-        AssertBreakStmt(cbRGBBuf, rc = VERR_INVALID_PARAMETER);
-
-        pFrame->pu8RGBBuf = (uint8_t *)RTMemAlloc(cbRGBBuf);
-        AssertBreakStmt(pFrame->pu8RGBBuf, rc = VERR_NO_MEMORY);
-        pFrame->cbRGBBuf  = cbRGBBuf;
-        pFrame->uWidth    = uSrcWidth;
-        pFrame->uHeight   = uSrcHeight;
-
-        /* If the current video frame is smaller than video resolution we're going to encode,
-         * clear the frame beforehand to prevent artifacts. */
-        if (   uSrcWidth  < pStream->Video.uWidth
-            || uSrcHeight < pStream->Video.uHeight)
-        {
-            RT_BZERO(pFrame->pu8RGBBuf, pFrame->cbRGBBuf);
-        }
-
-        /* Calculate start offset in source and destination buffers. */
-        uint32_t offSrc = y * uBytesPerLine + x * uBytesPerPixel;
-        uint32_t offDst = (destY * pStream->Video.uWidth + destX) * uBytesPerPixel;
-
-#ifdef VBOX_VIDEOREC_DUMP
-        VIDEORECBMPHDR bmpHdr;
-        RT_ZERO(bmpHdr);
-
-        VIDEORECBMPDIBHDR bmpDIBHdr;
-        RT_ZERO(bmpDIBHdr);
-
-        bmpHdr.u16Magic   = 0x4d42; /* Magic */
-        bmpHdr.u32Size    = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR) + (w * h * uBytesPerPixel));
-        bmpHdr.u32OffBits = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR));
-
-        bmpDIBHdr.u32Size          = sizeof(VIDEORECBMPDIBHDR);
-        bmpDIBHdr.u32Width         = w;
-        bmpDIBHdr.u32Height        = h;
-        bmpDIBHdr.u16Planes        = 1;
-        bmpDIBHdr.u16BitCount      = uBPP;
-        bmpDIBHdr.u32XPelsPerMeter = 5000;
-        bmpDIBHdr.u32YPelsPerMeter = 5000;
-
-        char szFileName[RTPATH_MAX];
-        RTStrPrintf2(szFileName, sizeof(szFileName), "/tmp/VideoRecFrame-%RU32.bmp", uScreen);
-
-        RTFILE fh;
-        int rc2 = RTFileOpen(&fh, szFileName,
-                             RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-        if (RT_SUCCESS(rc2))
-        {
-            RTFileWrite(fh, &bmpHdr,    sizeof(bmpHdr),    NULL);
-            RTFileWrite(fh, &bmpDIBHdr, sizeof(bmpDIBHdr), NULL);
-        }
-#endif
-        Assert(pFrame->cbRGBBuf >= w * h * uBytesPerPixel);
-
-        /* Do the copy. */
-        for (unsigned int i = 0; i < h; i++)
-        {
-            /* Overflow check. */
-            Assert(offSrc + w * uBytesPerPixel <= uSrcHeight * uBytesPerLine);
-            Assert(offDst + w * uBytesPerPixel <= pStream->Video.uHeight * pStream->Video.uWidth * uBytesPerPixel);
-
-            memcpy(pFrame->pu8RGBBuf + offDst, puSrcData + offSrc, w * uBytesPerPixel);
-
-#ifdef VBOX_VIDEOREC_DUMP
-            if (RT_SUCCESS(rc2))
-                RTFileWrite(fh, pFrame->pu8RGBBuf + offDst, w * uBytesPerPixel, NULL);
-#endif
-            offSrc += uBytesPerLine;
-            offDst += pStream->Video.uWidth * uBytesPerPixel;
-        }
-
-#ifdef VBOX_VIDEOREC_DUMP
-        if (RT_SUCCESS(rc2))
-            RTFileClose(fh);
-#endif
-
-    } while (0);
-
-    if (rc == VINF_SUCCESS) /* Note: Also could be VINF_TRY_AGAIN. */
-    {
-        PVIDEORECBLOCK pBlock = (PVIDEORECBLOCK)RTMemAlloc(sizeof(VIDEORECBLOCK));
-        if (pBlock)
-        {
-            AssertPtr(pFrame);
-
-            pBlock->enmType = VIDEORECBLOCKTYPE_VIDEO;
-            pBlock->pvData  = pFrame;
-            pBlock->cbData  = sizeof(VIDEORECVIDEOFRAME) + pFrame->cbRGBBuf;
-
-            try
-            {
-                VideoRecBlocks *pVideoRecBlocks = new VideoRecBlocks();
-                pVideoRecBlocks->List.push_back(pBlock);
-
-                Assert(pStream->Blocks.Map.find(uTimeStampMs) == pStream->Blocks.Map.end());
-                pStream->Blocks.Map.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks));
-            }
-            catch (const std::exception &ex)
-            {
-                RT_NOREF(ex);
-
-                RTMemFree(pBlock);
-                rc = VERR_NO_MEMORY;
-            }
-        }
-        else
-            rc = VERR_NO_MEMORY;
-    }
-
-    if (RT_FAILURE(rc))
-        VideoRecVideoFrameFree(pFrame);
-
-    VideoRecStreamUnlock(pStream);
-
-    int rc2 = RTCritSectLeave(&pCtx->CritSect);
+    rc = pStream->SendVideoFrame(x, y, uPixelFormat, uBPP, uBytesPerLine, uSrcWidth, uSrcHeight, puSrcData, uTimeStampMs);
+
+    int rc2 = RTCritSectLeave(&this->CritSect);
     AssertRC(rc2);
 
@@ -834,5 +562,5 @@
         && rc != VINF_TRY_AGAIN) /* Only signal the thread if operation was successful. */
     {
-        videoRecThreadNotify(pCtx);
+        threadNotify();
     }
 
Index: /trunk/src/VBox/Main/src-client/VideoRecStream.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/VideoRecStream.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-client/VideoRecStream.cpp	(revision 75251)
@@ -42,24 +42,21 @@
 
 
-/**
- * Locks a recording stream.
- *
- * @param   pStream             Recording stream to lock.
- */
-void VideoRecStreamLock(PVIDEORECSTREAM pStream)
-{
-    int rc = RTCritSectEnter(&pStream->CritSect);
-    AssertRC(rc);
-}
-
-/**
- * Unlocks a locked recording stream.
- *
- * @param   pStream             Recording stream to unlock.
- */
-void VideoRecStreamUnlock(PVIDEORECSTREAM pStream)
-{
-    int rc = RTCritSectLeave(&pStream->CritSect);
-    AssertRC(rc);
+CaptureStream::CaptureStream(void)
+    : tsStartMs(0)
+{
+}
+
+CaptureStream::CaptureStream(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings)
+    : tsStartMs(0)
+{
+    int rc2 = initInternal(a_uScreen, a_Settings);
+    if (RT_FAILURE(rc2))
+        throw rc2;
+}
+
+CaptureStream::~CaptureStream(void)
+{
+    int rc2 = uninitInternal();
+    AssertRC(rc2);
 }
 
@@ -68,23 +65,18 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to open.
- * @param   pCfg                Recording configuration to use.
- */
-int VideoRecStreamOpen(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg)
-{
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
-
-    Assert(pStream->enmDst == VIDEORECDEST_INVALID);
+ */
+int CaptureStream::open(void)
+{
+    Assert(Settings.enmDest == CaptureDestination_None);
 
     int rc;
 
-    switch (pCfg->enmDst)
-    {
-        case VIDEORECDEST_FILE:
-        {
-            Assert(pCfg->File.strName.isNotEmpty());
-
-            char *pszAbsPath = RTPathAbsDup(com::Utf8Str(pCfg->File.strName).c_str());
+    switch (Settings.enmDest)
+    {
+        case CaptureDestination_File:
+        {
+            Assert(Settings.File.strName.isNotEmpty());
+
+            char *pszAbsPath = RTPathAbsDup(Settings.File.strName.c_str());
             AssertPtrReturn(pszAbsPath, VERR_NO_MEMORY);
 
@@ -101,6 +93,6 @@
             char *pszFile = NULL;
 
-            if (pCfg->aScreens.size() > 1)
-                rc = RTStrAPrintf(&pszFile, "%s-%u%s", pszAbsPath, pStream->uScreenID + 1, pszSuff);
+            if (this->uScreenID > 0)
+                rc = RTStrAPrintf(&pszFile, "%s-%u%s", pszAbsPath, this->uScreenID + 1, pszSuff);
             else
                 rc = RTStrAPrintf(&pszFile, "%s%s", pszAbsPath, pszSuff);
@@ -127,9 +119,9 @@
                     RTTimeExplode(&time, &ts);
 
-                    if (pCfg->aScreens.size() > 1)
+                    if (this->uScreenID > 0)
                         rc = RTStrAPrintf(&pszFile, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ-%u%s",
                                           pszAbsPath, time.i32Year, time.u8Month, time.u8MonthDay,
                                           time.u8Hour, time.u8Minute, time.u8Second, time.u32Nanosecond,
-                                          pStream->uScreenID + 1, pszSuff);
+                                          this->uScreenID + 1, pszSuff);
                     else
                         rc = RTStrAPrintf(&pszFile, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ%s",
@@ -144,7 +136,6 @@
                 if (RT_SUCCESS(rc))
                 {
-                    pStream->enmDst       = VIDEORECDEST_FILE;
-                    pStream->File.hFile   = hFile;
-                    pStream->File.pszFile = pszFile; /* Assign allocated string to our stream's config. */
+                    this->File.hFile   = hFile;
+                    this->File.strName = pszFile;
                 }
             }
@@ -156,8 +147,8 @@
             {
                 LogRel(("VideoRec: Failed to open file '%s' for screen %RU32, rc=%Rrc\n",
-                        pszFile ? pszFile : "<Unnamed>", pStream->uScreenID, rc));
-                RTStrFree(pszFile);
-            }
-
+                        pszFile ? pszFile : "<Unnamed>", this->uScreenID, rc));
+            }
+
+            RTStrFree(pszFile);
             break;
         }
@@ -170,4 +161,126 @@
     LogFlowFuncLeaveRC(rc);
     return rc;
+}
+
+int CaptureStream::parseOptionsString(const com::Utf8Str &strOptions)
+{
+    size_t pos = 0;
+    com::Utf8Str key, value;
+    while ((pos = strOptions.parseKeyValue(key, value, pos)) != com::Utf8Str::npos)
+    {
+        if (key.compare("vc_quality", Utf8Str::CaseInsensitive) == 0)
+        {
+#ifdef VBOX_WITH_LIBVPX
+            Assert(this->Settings.Video.ulFPS);
+            if (value.compare("realtime", Utf8Str::CaseInsensitive) == 0)
+                this->Video.Codec.VPX.uEncoderDeadline = VPX_DL_REALTIME;
+            else if (value.compare("good", Utf8Str::CaseInsensitive) == 0)
+                this->Video.Codec.VPX.uEncoderDeadline = 1000000 / this->Settings.Video.ulFPS;
+            else if (value.compare("best", Utf8Str::CaseInsensitive) == 0)
+                this->Video.Codec.VPX.uEncoderDeadline = VPX_DL_BEST_QUALITY;
+            else
+            {
+                LogRel(("VideoRec: Setting encoder deadline to '%s'\n", value.c_str()));
+                this->Video.Codec.VPX.uEncoderDeadline = value.toUInt32();
+#endif
+            }
+        }
+        else if (key.compare("vc_enabled", Utf8Str::CaseInsensitive) == 0)
+        {
+            if (value.compare("false", Utf8Str::CaseInsensitive) == 0)
+            {
+                this->Settings.featureMap[CaptureFeature_Video] = false;
+#ifdef VBOX_WITH_AUDIO_VIDEOREC
+                LogRel(("VideoRec: Only audio will be recorded\n"));
+#endif
+            }
+        }
+        else if (key.compare("ac_enabled", Utf8Str::CaseInsensitive) == 0)
+        {
+#ifdef VBOX_WITH_AUDIO_VIDEOREC
+            if (value.compare("true", Utf8Str::CaseInsensitive) == 0)
+            {
+                this->Settings.featureMap[CaptureFeature_Audio] = true;
+            }
+            else
+                LogRel(("VideoRec: Only video will be recorded\n"));
+#endif
+        }
+        else if (key.compare("ac_profile", Utf8Str::CaseInsensitive) == 0)
+        {
+#ifdef VBOX_WITH_AUDIO_VIDEOREC
+            if (value.compare("low", Utf8Str::CaseInsensitive) == 0)
+            {
+                this->Settings.Audio.uHz       = 8000;
+                this->Settings.Audio.cBits     = 16;
+                this->Settings.Audio.cChannels = 1;
+            }
+            else if (value.startsWith("med" /* "med[ium]" */, Utf8Str::CaseInsensitive) == 0)
+            {
+                /* Stay with the default set above. */
+            }
+            else if (value.compare("high", Utf8Str::CaseInsensitive) == 0)
+            {
+                this->Settings.Audio.uHz       = 48000;
+                this->Settings.Audio.cBits     = 16;
+                this->Settings.Audio.cChannels = 2;
+            }
+#endif
+        }
+        else
+            LogRel(("VideoRec: Unknown option '%s' (value '%s'), skipping\n", key.c_str(), value.c_str()));
+
+    } /* while */
+
+    return VINF_SUCCESS;
+}
+
+const settings::CaptureScreenSettings &CaptureStream::GetConfig(void) const
+{
+    return this->Settings;
+}
+
+/**
+ * Checks if a specified limit for recording has been reached.
+ *
+ * @returns true if any limit has been reached.
+ * @param   tsNowMs             Current time stamp (in ms).
+ */
+bool CaptureStream::IsLimitReached(uint64_t tsNowMs) const
+{
+    if (!IsReady())
+        return true;
+
+    if (   Settings.ulMaxTimeS
+        && tsNowMs >= this->tsStartMs + (Settings.ulMaxTimeS * RT_MS_1SEC))
+    {
+        return true;
+    }
+
+    if (Settings.enmDest == CaptureDestination_File)
+    {
+
+        if (Settings.File.ulMaxSizeMB)
+        {
+            uint64_t sizeInMB = this->File.pWEBM->GetFileSize() / _1M;
+            if(sizeInMB >= Settings.File.ulMaxSizeMB)
+                return true;
+        }
+
+        /* Check for available free disk space */
+        if (   this->File.pWEBM
+            && this->File.pWEBM->GetAvailableSpace() < 0x100000) /** @todo r=andy WTF? Fix this. */
+        {
+            LogRel(("VideoRec: Not enough free storage space available, stopping video capture\n"));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool CaptureStream::IsReady(void) const
+{
+    return this->fEnabled;
 }
 
@@ -178,15 +291,13 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to process.
- */
-int VideoRecStreamProcess(PVIDEORECSTREAM pStream)
-{
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-
-    VideoRecStreamLock(pStream);
-
-    if (!pStream->fEnabled)
-    {
-        VideoRecStreamUnlock(pStream);
+ * @param   mapBlocksCommon     Map of common block to process for this stream.
+ */
+int CaptureStream::Process(VideoRecBlockMap &mapBlocksCommon)
+{
+    lock();
+
+    if (!Settings.fEnabled)
+    {
+        unlock();
         return VINF_SUCCESS;
     }
@@ -194,12 +305,9 @@
     int rc = VINF_SUCCESS;
 
-    const PVIDEORECCONTEXT pCtx = pStream->pCtx;
-    AssertPtr(pCtx);
-
-    VideoRecBlockMap::iterator itStreamBlocks = pStream->Blocks.Map.begin();
-    while (itStreamBlocks != pStream->Blocks.Map.end())
+    VideoRecBlockMap::iterator itStreamBlocks = Blocks.Map.begin();
+    while (itStreamBlocks != Blocks.Map.end())
     {
         const uint64_t        uTimeStampMs = itStreamBlocks->first;
-              VideoRecBlocks *pBlocks      = itStreamBlocks->second;
+              CaptureBlocks *pBlocks       = itStreamBlocks->second;
 
         AssertPtr(pBlocks);
@@ -217,10 +325,10 @@
                 rc = videoRecRGBToYUV(pVideoFrame->uPixelFormat,
                                       /* Destination */
-                                      pStream->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight,
+                                      this->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight,
                                       /* Source */
-                                      pVideoFrame->pu8RGBBuf, pStream->Video.uWidth, pStream->Video.uHeight);
+                                      pVideoFrame->pu8RGBBuf, this->Settings.Video.ulWidth, this->Settings.Video.ulHeight);
                 if (RT_SUCCESS(rc))
                 {
-                    rc = VideoRecStreamWriteVideoVPX(pStream, uTimeStampMs, pVideoFrame);
+                    rc = writeVideoVPX(uTimeStampMs, pVideoFrame);
                 }
                 else
@@ -238,8 +346,10 @@
 
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
+    AssertPtr(pCtx);
+
     /* As each (enabled) screen has to get the same audio data, look for common (audio) data which needs to be
      * written to the screen's assigned recording stream. */
-    VideoRecBlockMap::iterator itCommonBlocks = pCtx->mapBlocksCommon.begin();
-    while (itCommonBlocks != pCtx->mapBlocksCommon.end())
+    VideoRecBlockMap::iterator itCommonBlocks = mapBlocksCommon.begin();
+    while (itCommonBlocks != mapBlocksCommon.end())
     {
         VideoRecBlockList::iterator itBlock = itCommonBlocks->second->List.begin();
@@ -258,6 +368,6 @@
                     WebMWriter::BlockData_Opus blockData = { pAudioFrame->pvBuf, pAudioFrame->cbBuf,
                                                              pBlockCommon->uTimeStampMs };
-                    AssertPtr(pStream->File.pWEBM);
-                    rc = pStream->File.pWEBM->WriteBlock(pStream->uTrackAudio, &blockData, sizeof(blockData));
+                    AssertPtr(this->File.pWEBM);
+                    rc = this->File.pWEBM->WriteBlock(this->uTrackAudio, &blockData, sizeof(blockData));
                     break;
                 }
@@ -287,11 +397,11 @@
         {
             delete itCommonBlocks->second;
-            pCtx->mapBlocksCommon.erase(itCommonBlocks);
-            itCommonBlocks = pCtx->mapBlocksCommon.begin();
+            mapBlocksCommon.erase(itCommonBlocks);
+            itCommonBlocks = mapBlocksCommon.begin();
         }
         else
             ++itCommonBlocks;
 
-        LogFunc(("Common blocks: %zu\n", pCtx->mapBlocksCommon.size()));
+        LogFunc(("Common blocks: %zu\n", mapBlocksCommon.size()));
 
         if (RT_FAILURE(rc))
@@ -300,64 +410,288 @@
 #endif
 
-    VideoRecStreamUnlock(pStream);
+    unlock();
 
     return rc;
 }
 
+int CaptureStream::SendVideoFrame(uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine,
+                                  uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, uint64_t uTimeStampMs)
+{
+    lock();
+
+    PVIDEORECVIDEOFRAME pFrame = NULL;
+
+    int rc = VINF_SUCCESS;
+
+    do
+    {
+        if (!this->fEnabled)
+        {
+            rc = VINF_TRY_AGAIN; /* Not (yet) enabled. */
+            break;
+        }
+
+        if (uTimeStampMs < this->Video.uLastTimeStampMs + this->Video.uDelayMs)
+        {
+            rc = VINF_TRY_AGAIN; /* Respect maximum frames per second. */
+            break;
+        }
+
+        this->Video.uLastTimeStampMs = uTimeStampMs;
+
+        int xDiff = ((int)this->Settings.Video.ulWidth - (int)uSrcWidth) / 2;
+        uint32_t w = uSrcWidth;
+        if ((int)w + xDiff + (int)x <= 0)  /* Nothing visible. */
+        {
+            rc = VERR_INVALID_PARAMETER;
+            break;
+        }
+
+        uint32_t destX;
+        if ((int)x < -xDiff)
+        {
+            w += xDiff + x;
+            x = -xDiff;
+            destX = 0;
+        }
+        else
+            destX = x + xDiff;
+
+        uint32_t h = uSrcHeight;
+        int yDiff = ((int)this->Settings.Video.ulHeight - (int)uSrcHeight) / 2;
+        if ((int)h + yDiff + (int)y <= 0)  /* Nothing visible. */
+        {
+            rc = VERR_INVALID_PARAMETER;
+            break;
+        }
+
+        uint32_t destY;
+        if ((int)y < -yDiff)
+        {
+            h += yDiff + (int)y;
+            y = -yDiff;
+            destY = 0;
+        }
+        else
+            destY = y + yDiff;
+
+        if (   destX > this->Settings.Video.ulWidth
+            || destY > this->Settings.Video.ulHeight)
+        {
+            rc = VERR_INVALID_PARAMETER;  /* Nothing visible. */
+            break;
+        }
+
+        if (destX + w > this->Settings.Video.ulWidth)
+            w = this->Settings.Video.ulWidth - destX;
+
+        if (destY + h > this->Settings.Video.ulHeight)
+            h = this->Settings.Video.ulHeight - destY;
+
+        pFrame = (PVIDEORECVIDEOFRAME)RTMemAllocZ(sizeof(VIDEORECVIDEOFRAME));
+        AssertBreakStmt(pFrame, rc = VERR_NO_MEMORY);
+
+        /* Calculate bytes per pixel and set pixel format. */
+        const unsigned uBytesPerPixel = uBPP / 8;
+        if (uPixelFormat == BitmapFormat_BGR)
+        {
+            switch (uBPP)
+            {
+                case 32:
+                    pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB32;
+                    break;
+                case 24:
+                    pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB24;
+                    break;
+                case 16:
+                    pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB565;
+                    break;
+                default:
+                    AssertMsgFailedBreakStmt(("Unknown color depth (%RU32)\n", uBPP), rc = VERR_NOT_SUPPORTED);
+                    break;
+            }
+        }
+        else
+            AssertMsgFailedBreakStmt(("Unknown pixel format (%RU32)\n", uPixelFormat), rc = VERR_NOT_SUPPORTED);
+
+        const size_t cbRGBBuf =   this->Settings.Video.ulWidth
+                                * this->Settings.Video.ulHeight
+                                * uBytesPerPixel;
+        AssertBreakStmt(cbRGBBuf, rc = VERR_INVALID_PARAMETER);
+
+        pFrame->pu8RGBBuf = (uint8_t *)RTMemAlloc(cbRGBBuf);
+        AssertBreakStmt(pFrame->pu8RGBBuf, rc = VERR_NO_MEMORY);
+        pFrame->cbRGBBuf  = cbRGBBuf;
+        pFrame->uWidth    = uSrcWidth;
+        pFrame->uHeight   = uSrcHeight;
+
+        /* If the current video frame is smaller than video resolution we're going to encode,
+         * clear the frame beforehand to prevent artifacts. */
+        if (   uSrcWidth  < this->Settings.Video.ulWidth
+            || uSrcHeight < this->Settings.Video.ulHeight)
+        {
+            RT_BZERO(pFrame->pu8RGBBuf, pFrame->cbRGBBuf);
+        }
+
+        /* Calculate start offset in source and destination buffers. */
+        uint32_t offSrc = y * uBytesPerLine + x * uBytesPerPixel;
+        uint32_t offDst = (destY * this->Settings.Video.ulWidth + destX) * uBytesPerPixel;
+
+#ifdef VBOX_VIDEOREC_DUMP
+        VIDEORECBMPHDR bmpHdr;
+        RT_ZERO(bmpHdr);
+
+        VIDEORECBMPDIBHDR bmpDIBHdr;
+        RT_ZERO(bmpDIBHdr);
+
+        bmpHdr.u16Magic   = 0x4d42; /* Magic */
+        bmpHdr.u32Size    = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR) + (w * h * uBytesPerPixel));
+        bmpHdr.u32OffBits = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR));
+
+        bmpDIBHdr.u32Size          = sizeof(VIDEORECBMPDIBHDR);
+        bmpDIBHdr.u32Width         = w;
+        bmpDIBHdr.u32Height        = h;
+        bmpDIBHdr.u16Planes        = 1;
+        bmpDIBHdr.u16BitCount      = uBPP;
+        bmpDIBHdr.u32XPelsPerMeter = 5000;
+        bmpDIBHdr.u32YPelsPerMeter = 5000;
+
+        char szFileName[RTPATH_MAX];
+        RTStrPrintf2(szFileName, sizeof(szFileName), "/tmp/VideoRecFrame-%RU32.bmp", this->uScreenID);
+
+        RTFILE fh;
+        int rc2 = RTFileOpen(&fh, szFileName,
+                             RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
+        if (RT_SUCCESS(rc2))
+        {
+            RTFileWrite(fh, &bmpHdr,    sizeof(bmpHdr),    NULL);
+            RTFileWrite(fh, &bmpDIBHdr, sizeof(bmpDIBHdr), NULL);
+        }
+#endif
+        Assert(pFrame->cbRGBBuf >= w * h * uBytesPerPixel);
+
+        /* Do the copy. */
+        for (unsigned int i = 0; i < h; i++)
+        {
+            /* Overflow check. */
+            Assert(offSrc + w * uBytesPerPixel <= uSrcHeight * uBytesPerLine);
+            Assert(offDst + w * uBytesPerPixel <= this->Settings.Video.ulHeight * this->Settings.Video.ulWidth * uBytesPerPixel);
+
+            memcpy(pFrame->pu8RGBBuf + offDst, puSrcData + offSrc, w * uBytesPerPixel);
+
+#ifdef VBOX_VIDEOREC_DUMP
+            if (RT_SUCCESS(rc2))
+                RTFileWrite(fh, pFrame->pu8RGBBuf + offDst, w * uBytesPerPixel, NULL);
+#endif
+            offSrc += uBytesPerLine;
+            offDst += this->Settings.Video.ulWidth * uBytesPerPixel;
+        }
+
+#ifdef VBOX_VIDEOREC_DUMP
+        if (RT_SUCCESS(rc2))
+            RTFileClose(fh);
+#endif
+
+    } while (0);
+
+    if (rc == VINF_SUCCESS) /* Note: Also could be VINF_TRY_AGAIN. */
+    {
+        PVIDEORECBLOCK pBlock = (PVIDEORECBLOCK)RTMemAlloc(sizeof(VIDEORECBLOCK));
+        if (pBlock)
+        {
+            AssertPtr(pFrame);
+
+            pBlock->enmType = VIDEORECBLOCKTYPE_VIDEO;
+            pBlock->pvData  = pFrame;
+            pBlock->cbData  = sizeof(VIDEORECVIDEOFRAME) + pFrame->cbRGBBuf;
+
+            try
+            {
+                CaptureBlocks *pVideoRecBlocks = new CaptureBlocks();
+                pVideoRecBlocks->List.push_back(pBlock);
+
+                Assert(this->Blocks.Map.find(uTimeStampMs) == this->Blocks.Map.end());
+                this->Blocks.Map.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks));
+            }
+            catch (const std::exception &ex)
+            {
+                RT_NOREF(ex);
+
+                RTMemFree(pBlock);
+                rc = VERR_NO_MEMORY;
+            }
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+
+    if (RT_FAILURE(rc))
+        VideoRecVideoFrameFree(pFrame);
+
+    lock();
+
+    return rc;
+}
+
+int CaptureStream::Init(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings)
+{
+    return initInternal(a_uScreen, a_Settings);
+}
+
 /**
  * Initializes a recording stream.
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to initialize.
- * @param   pCtx                Recording context to use for initialization.
- * @param   uScreen             Screen number to record.
- */
-int VideoRecStreamInit(PVIDEORECSTREAM pStream, PVIDEORECCONTEXT pCtx, uint32_t uScreen)
-{
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
-
-    PVIDEORECCFG pCfg = &pCtx->Cfg;
-
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-    if (pCfg->Audio.fEnabled)
-    {
-        /* Sanity. */
-        AssertReturn(pCfg->Audio.uHz,       VERR_INVALID_PARAMETER);
-        AssertReturn(pCfg->Audio.cBits,     VERR_INVALID_PARAMETER);
-        AssertReturn(pCfg->Audio.cChannels, VERR_INVALID_PARAMETER);
-    }
-#endif
-
-    int rc = VideoRecStreamOpen(pStream, pCfg);
+ * @param   uScreen             Screen number to use for this recording stream.
+ * @param   Cfg                 Recording screen configuration to use for initialization.
+ */
+int CaptureStream::initInternal(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings)
+{
+    int rc = parseOptionsString(a_Settings.strOptions);
     if (RT_FAILURE(rc))
         return rc;
 
-    if (pCfg->Video.fEnabled)
-        rc = VideoRecStreamInitVideo(pStream, pCfg);
-
-    switch (pStream->enmDst)
-    {
-        case VIDEORECDEST_FILE:
-        {
-            rc = pStream->File.pWEBM->OpenEx(pStream->File.pszFile, &pStream->File.hFile,
+    rc = RTCritSectInit(&this->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    rc = open();
+    if (RT_FAILURE(rc))
+        return rc;
+
+    const bool fVideoEnabled = a_Settings.isFeatureEnabled(CaptureFeature_Video);
+    const bool fAudioEnabled = a_Settings.isFeatureEnabled(CaptureFeature_Audio);
+
+    if (fVideoEnabled)
+        rc = initVideo();
+
+    if (fAudioEnabled)
+        rc = initAudio();
+
+    switch (this->Settings.enmDest)
+    {
+        case CaptureDestination_File:
+        {
+            const char *pszFile = this->Settings.File.strName.c_str();
+
+            rc = File.pWEBM->OpenEx(pszFile, &this->File.hFile,
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-                                             pCfg->Audio.fEnabled ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None,
+                                      a_Settings.isFeatureEnabled(CaptureFeature_Audio)
+                                    ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None,
 #else
-                                             WebMWriter::AudioCodec_None,
-#endif
-                                             pCfg->Video.fEnabled ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None);
+                                      WebMWriter::AudioCodec_None,
+#endif
+                                      a_Settings.isFeatureEnabled(CaptureFeature_Video)
+                                    ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None);
             if (RT_FAILURE(rc))
             {
-                LogRel(("VideoRec: Failed to create the capture output file '%s' (%Rrc)\n", pStream->File.pszFile, rc));
+                LogRel(("VideoRec: Failed to create the capture output file '%s' (%Rrc)\n", pszFile, rc));
                 break;
             }
 
-            const char *pszFile = pStream->File.pszFile;
-
-            if (pCfg->Video.fEnabled)
-            {
-                rc = pStream->File.pWEBM->AddVideoTrack(pCfg->Video.uWidth, pCfg->Video.uHeight, pCfg->Video.uFPS,
-                                                        &pStream->uTrackVideo);
+            if (fVideoEnabled)
+            {
+                rc = this->File.pWEBM->AddVideoTrack(a_Settings.Video.ulWidth, a_Settings.Video.ulHeight,
+                                                     a_Settings.Video.ulFPS, &this->uTrackVideo);
                 if (RT_FAILURE(rc))
                 {
@@ -367,13 +701,13 @@
 
                 LogRel(("VideoRec: Recording video of screen #%u with %RU32x%RU32 @ %RU32 kbps, %RU32 FPS (track #%RU8)\n",
-                        uScreen, pCfg->Video.uWidth, pCfg->Video.uHeight, pCfg->Video.uRate, pCfg->Video.uFPS,
-                        pStream->uTrackVideo));
+                        this->uScreenID, a_Settings.Video.ulWidth, a_Settings.Video.ulHeight, a_Settings.Video.ulRate,
+                        a_Settings.Video.ulFPS, this->uTrackVideo));
             }
 
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-            if (pCfg->Audio.fEnabled)
-            {
-                rc = pStream->File.pWEBM->AddAudioTrack(pCfg->Audio.uHz, pCfg->Audio.cChannels, pCfg->Audio.cBits,
-                                                        &pStream->uTrackAudio);
+            if (fAudioEnabled)
+            {
+                rc = this->File.pWEBM->AddAudioTrack(a_Settings.Audio.uHz, a_Settings.Audio.cChannels, a_Settings.Audio.cBits,
+                                                     &this->uTrackAudio);
                 if (RT_FAILURE(rc))
                 {
@@ -383,22 +717,22 @@
 
                 LogRel(("VideoRec: Recording audio in %RU16Hz, %RU8 bit, %RU8 %s (track #%RU8)\n",
-                        pCfg->Audio.uHz, pCfg->Audio.cBits, pCfg->Audio.cChannels, pCfg->Audio.cChannels ? "channels" : "channel",
-                        pStream->uTrackAudio));
-            }
-#endif
-
-            if (   pCfg->Video.fEnabled
+                        a_Settings.Audio.uHz, a_Settings.Audio.cBits, a_Settings.Audio.cChannels,
+                        a_Settings.Audio.cChannels ? "channels" : "channel", this->uTrackAudio));
+            }
+#endif
+
+            if (   fVideoEnabled
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-                || pCfg->Audio.fEnabled
+                || fAudioEnabled
 #endif
                )
             {
                 char szWhat[32] = { 0 };
-                if (pCfg->Video.fEnabled)
+                if (fVideoEnabled)
                     RTStrCat(szWhat, sizeof(szWhat), "video");
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-                if (pCfg->Audio.fEnabled)
+                if (fAudioEnabled)
                 {
-                    if (pCfg->Video.fEnabled)
+                    if (fVideoEnabled)
                         RTStrCat(szWhat, sizeof(szWhat), " + ");
                     RTStrCat(szWhat, sizeof(szWhat), "audio");
@@ -419,10 +753,13 @@
     if (RT_SUCCESS(rc))
     {
-        pStream->pCtx     = pCtx;
-        pStream->fEnabled = true;
+        this->pCtx      = pCtx;
+        this->fEnabled  = true;
+        this->uScreenID = a_uScreen;
+        this->tsStartMs = RTTimeMilliTS();
+        this->Settings  = a_Settings;
     }
     else
     {
-        int rc2 = VideoRecStreamClose(pStream);
+        int rc2 = uninitInternal();
         AssertRC(rc2);
         return rc;
@@ -438,19 +775,17 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to close.
- *
- */
-int VideoRecStreamClose(PVIDEORECSTREAM pStream)
+ */
+int CaptureStream::close(void)
 {
     int rc = VINF_SUCCESS;
 
-    if (pStream->fEnabled)
-    {
-        switch (pStream->enmDst)
-        {
-            case VIDEORECDEST_FILE:
-            {
-                if (pStream->File.pWEBM)
-                    rc = pStream->File.pWEBM->Close();
+    if (this->fEnabled)
+    {
+        switch (this->Settings.enmDest)
+        {
+            case CaptureDestination_File:
+            {
+                if (this->File.pWEBM)
+                    rc = this->File.pWEBM->Close();
                 break;
             }
@@ -461,41 +796,37 @@
         }
 
-        pStream->Blocks.Clear();
-
-        LogRel(("VideoRec: Recording screen #%u stopped\n", pStream->uScreenID));
+        this->Blocks.Clear();
+
+        LogRel(("VideoRec: Recording screen #%u stopped\n", this->uScreenID));
     }
 
     if (RT_FAILURE(rc))
     {
-        LogRel(("VideoRec: Error stopping recording screen #%u, rc=%Rrc\n", pStream->uScreenID, rc));
+        LogRel(("VideoRec: Error stopping recording screen #%u, rc=%Rrc\n", this->uScreenID, rc));
         return rc;
     }
 
-    switch (pStream->enmDst)
-    {
-        case VIDEORECDEST_FILE:
-        {
-            AssertPtr(pStream->File.pszFile);
-            if (RTFileIsValid(pStream->File.hFile))
-            {
-                rc = RTFileClose(pStream->File.hFile);
+    switch (this->Settings.enmDest)
+    {
+        case CaptureDestination_File:
+        {
+            if (RTFileIsValid(this->File.hFile))
+            {
+                rc = RTFileClose(this->File.hFile);
                 if (RT_SUCCESS(rc))
                 {
-                    LogRel(("VideoRec: Closed file '%s'\n", pStream->File.pszFile));
+                    LogRel(("VideoRec: Closed file '%s'\n", this->Settings.File.strName.c_str()));
                 }
                 else
                 {
-                    LogRel(("VideoRec: Error closing file '%s', rc=%Rrc\n", pStream->File.pszFile, rc));
+                    LogRel(("VideoRec: Error closing file '%s', rc=%Rrc\n", this->Settings.File.strName.c_str(), rc));
                     break;
                 }
             }
 
-            RTStrFree(pStream->File.pszFile);
-            pStream->File.pszFile = NULL;
-
-            if (pStream->File.pWEBM)
-            {
-                delete pStream->File.pWEBM;
-                pStream->File.pWEBM = NULL;
+            if (this->File.pWEBM)
+            {
+                delete this->File.pWEBM;
+                this->File.pWEBM = NULL;
             }
             break;
@@ -507,9 +838,4 @@
     }
 
-    if (RT_SUCCESS(rc))
-    {
-        pStream->enmDst = VIDEORECDEST_INVALID;
-    }
-
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -520,17 +846,27 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to uninitialize.
- */
-int VideoRecStreamUninit(PVIDEORECSTREAM pStream)
-{
-    int rc = VINF_SUCCESS;
-
-    if (pStream->pCtx->Cfg.Video.fEnabled)
-    {
-        int rc2 = VideoRecStreamUnitVideo(pStream);
+ */
+int CaptureStream::Uninit(void)
+{
+    return uninitInternal();
+}
+
+int CaptureStream::uninitInternal(void)
+{
+    int rc = close();
+    if (RT_FAILURE(rc))
+        return rc;
+
+    if (this->Settings.isFeatureEnabled(CaptureFeature_Video))
+    {
+        int rc2 = unitVideo();
         if (RT_SUCCESS(rc))
             rc = rc2;
     }
 
+    RTCritSectDelete(&this->CritSect);
+
+    this->fEnabled = false;
+
     return rc;
 }
@@ -540,11 +876,10 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to uninitialize video recording for.
- */
-int VideoRecStreamUnitVideo(PVIDEORECSTREAM pStream)
+ */
+int CaptureStream::unitVideo(void)
 {
 #ifdef VBOX_WITH_LIBVPX
     /* At the moment we only have VPX. */
-    return VideoRecStreamUninitVideoVPX(pStream);
+    return uninitVideoVPX();
 #else
     return VERR_NOT_SUPPORTED;
@@ -557,10 +892,9 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to uninitialize VPX codec for.
- */
-int VideoRecStreamUninitVideoVPX(PVIDEORECSTREAM pStream)
-{
-    vpx_img_free(&pStream->Video.Codec.VPX.RawImage);
-    vpx_codec_err_t rcv = vpx_codec_destroy(&pStream->Video.Codec.VPX.Ctx);
+ */
+int CaptureStream::uninitVideoVPX(void)
+{
+    vpx_img_free(&this->Video.Codec.VPX.RawImage);
+    vpx_codec_err_t rcv = vpx_codec_destroy(&this->Video.Codec.VPX.Ctx);
     Assert(rcv == VPX_CODEC_OK); RT_NOREF(rcv);
 
@@ -573,14 +907,21 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to initialize video recording for.
- * @param   pCfg                Video recording configuration to use for initialization.
- */
-int VideoRecStreamInitVideo(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg)
-{
+ */
+int CaptureStream::initVideo(void)
+{
+    /* Sanity. */
+    AssertReturn(this->Settings.Video.ulRate,   VERR_INVALID_PARAMETER);
+    AssertReturn(this->Settings.Video.ulWidth,  VERR_INVALID_PARAMETER);
+    AssertReturn(this->Settings.Video.ulHeight, VERR_INVALID_PARAMETER);
+    AssertReturn(this->Settings.Video.ulFPS,    VERR_INVALID_PARAMETER);
+
+    this->Video.cFailedEncodingFrames = 0;
+    this->Video.uDelayMs = RT_MS_1SEC / this->Settings.Video.ulFPS;
+
 #ifdef VBOX_WITH_LIBVPX
     /* At the moment we only have VPX. */
-    return VideoRecStreamInitVideoVPX(pStream, pCfg);
+    return initVideoVPX();
 #else
-    return VERR_NOT_SUPPORTED;
+    return VINF_SUCCESS;
 #endif
 }
@@ -591,19 +932,7 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Recording stream to initialize VPX codec for.
- * @param   pCfg                Video recording configuration to use for initialization.
- */
-int VideoRecStreamInitVideoVPX(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg)
-{
-    pStream->Video.uWidth                = pCfg->Video.uWidth;
-    pStream->Video.uHeight               = pCfg->Video.uHeight;
-    pStream->Video.cFailedEncodingFrames = 0;
-
-    PVIDEORECVIDEOCODEC pVC = &pStream->Video.Codec;
-
-    pStream->Video.uDelayMs = RT_MS_1SEC / pCfg->Video.uFPS;
-
-    pVC->enmType = VIDEORECVIDEOCODECTYPE_VP8; /** @todo Make this configurable. */
-
+ */
+int CaptureStream::initVideoVPX(void)
+{
 # ifdef VBOX_WITH_LIBVPX_VP9
     vpx_codec_iface_t *pCodecIface = vpx_codec_vp9_cx();
@@ -612,5 +941,7 @@
 # endif
 
-    vpx_codec_err_t rcv = vpx_codec_enc_config_default(pCodecIface, &pVC->VPX.Cfg, 0 /* Reserved */);
+    PVIDEORECVIDEOCODEC pCodec = &this->Video.Codec;
+
+    vpx_codec_err_t rcv = vpx_codec_enc_config_default(pCodecIface, &pCodec->VPX.Cfg, 0 /* Reserved */);
     if (rcv != VPX_CODEC_OK)
     {
@@ -620,17 +951,17 @@
 
     /* Target bitrate in kilobits per second. */
-    pVC->VPX.Cfg.rc_target_bitrate = pCfg->Video.uRate;
+    pCodec->VPX.Cfg.rc_target_bitrate = this->Settings.Video.ulRate;
     /* Frame width. */
-    pVC->VPX.Cfg.g_w = pCfg->Video.uWidth;
+    pCodec->VPX.Cfg.g_w = this->Settings.Video.ulWidth;
     /* Frame height. */
-    pVC->VPX.Cfg.g_h = pCfg->Video.uHeight;
+    pCodec->VPX.Cfg.g_h = this->Settings.Video.ulHeight;
     /* 1ms per frame. */
-    pVC->VPX.Cfg.g_timebase.num = 1;
-    pVC->VPX.Cfg.g_timebase.den = 1000;
+    pCodec->VPX.Cfg.g_timebase.num = 1;
+    pCodec->VPX.Cfg.g_timebase.den = 1000;
     /* Disable multithreading. */
-    pVC->VPX.Cfg.g_threads = 0;
+    pCodec->VPX.Cfg.g_threads = 0;
 
     /* Initialize codec. */
-    rcv = vpx_codec_enc_init(&pVC->VPX.Ctx, pCodecIface, &pVC->VPX.Cfg, 0 /* Flags */);
+    rcv = vpx_codec_enc_init(&pCodec->VPX.Ctx, pCodecIface, &pCodec->VPX.Cfg, 0 /* Flags */);
     if (rcv != VPX_CODEC_OK)
     {
@@ -639,12 +970,14 @@
     }
 
-    if (!vpx_img_alloc(&pVC->VPX.RawImage, VPX_IMG_FMT_I420, pCfg->Video.uWidth, pCfg->Video.uHeight, 1))
-    {
-        LogRel(("VideoRec: Failed to allocate image %RU32x%RU32\n", pCfg->Video.uWidth, pCfg->Video.uHeight));
+    if (!vpx_img_alloc(&pCodec->VPX.RawImage, VPX_IMG_FMT_I420,
+                       this->Settings.Video.ulWidth, this->Settings.Video.ulHeight, 1))
+    {
+        LogRel(("VideoRec: Failed to allocate image %RU32x%RU32\n",
+                this->Settings.Video.ulWidth, this->Settings.Video.ulHeight));
         return VERR_NO_MEMORY;
     }
 
     /* Save a pointer to the first raw YUV plane. */
-    pStream->Video.Codec.VPX.pu8YuvBuf = pVC->VPX.RawImage.planes[0];
+    pCodec->VPX.pu8YuvBuf = pCodec->VPX.RawImage.planes[0];
 
     return VINF_SUCCESS;
@@ -652,4 +985,19 @@
 #endif
 
+int CaptureStream::initAudio(void)
+{
+#ifdef VBOX_WITH_AUDIO_VIDEOREC
+    if (this->Settings.isFeatureEnabled(CaptureFeature_Audio))
+    {
+        /* Sanity. */
+        AssertReturn(this->Settings.Audio.uHz,       VERR_INVALID_PARAMETER);
+        AssertReturn(this->Settings.Audio.cBits,     VERR_INVALID_PARAMETER);
+        AssertReturn(this->Settings.Audio.cChannels, VERR_INVALID_PARAMETER);
+    }
+#endif
+
+    return VINF_SUCCESS;
+}
+
 #ifdef VBOX_WITH_LIBVPX
 /**
@@ -657,30 +1005,26 @@
  *
  * @returns IPRT status code.
- * @param   pStream             Stream to encode and submit to.
  * @param   uTimeStampMs        Absolute timestamp (PTS) of frame (in ms) to encode.
  * @param   pFrame              Frame to encode and submit.
  */
-int VideoRecStreamWriteVideoVPX(PVIDEORECSTREAM pStream, uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame)
-{
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertPtrReturn(pFrame,  VERR_INVALID_POINTER);
+int CaptureStream::writeVideoVPX(uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame)
+{
+    AssertPtrReturn(pFrame, VERR_INVALID_POINTER);
 
     int rc;
 
-    AssertPtr(pStream->pCtx);
-    PVIDEORECCFG        pCfg = &pStream->pCtx->Cfg;
-    PVIDEORECVIDEOCODEC pVC  = &pStream->Video.Codec;
+    PVIDEORECVIDEOCODEC pCodec = &this->Video.Codec;
 
     /* Presentation Time Stamp (PTS). */
     vpx_codec_pts_t pts = uTimeStampMs;
-    vpx_codec_err_t rcv = vpx_codec_encode(&pVC->VPX.Ctx,
-                                           &pVC->VPX.RawImage,
-                                           pts                                    /* Time stamp */,
-                                           pStream->Video.uDelayMs                /* How long to show this frame */,
-                                           0                                      /* Flags */,
-                                           pCfg->Video.Codec.VPX.uEncoderDeadline /* Quality setting */);
+    vpx_codec_err_t rcv = vpx_codec_encode(&pCodec->VPX.Ctx,
+                                           &pCodec->VPX.RawImage,
+                                           pts                          /* Time stamp */,
+                                           this->Video.uDelayMs         /* How long to show this frame */,
+                                           0                            /* Flags */,
+                                           pCodec->VPX.uEncoderDeadline /* Quality setting */);
     if (rcv != VPX_CODEC_OK)
     {
-        if (pStream->Video.cFailedEncodingFrames++ < 64)
+        if (this->Video.cFailedEncodingFrames++ < 64) /** @todo Make this configurable. */
         {
             LogRel(("VideoRec: Failed to encode video frame: %s\n", vpx_codec_err_to_string(rcv)));
@@ -689,5 +1033,5 @@
     }
 
-    pStream->Video.cFailedEncodingFrames = 0;
+    this->Video.cFailedEncodingFrames = 0;
 
     vpx_codec_iter_t iter = NULL;
@@ -695,5 +1039,5 @@
     for (;;)
     {
-        const vpx_codec_cx_pkt_t *pPacket = vpx_codec_get_cx_data(&pVC->VPX.Ctx, &iter);
+        const vpx_codec_cx_pkt_t *pPacket = vpx_codec_get_cx_data(&pCodec->VPX.Ctx, &iter);
         if (!pPacket)
             break;
@@ -703,6 +1047,6 @@
             case VPX_CODEC_CX_FRAME_PKT:
             {
-                WebMWriter::BlockData_VP8 blockData = { &pVC->VPX.Cfg, pPacket };
-                rc = pStream->File.pWEBM->WriteBlock(pStream->uTrackVideo, &blockData, sizeof(blockData));
+                WebMWriter::BlockData_VP8 blockData = { &pCodec->VPX.Cfg, pPacket };
+                rc = this->File.pWEBM->WriteBlock(this->uTrackVideo, &blockData, sizeof(blockData));
                 break;
             }
@@ -719,2 +1063,24 @@
 #endif /* VBOX_WITH_LIBVPX */
 
+/**
+ * Locks a recording stream.
+ *
+ * @param   pStream             Recording stream to lock.
+ */
+void CaptureStream::lock(void)
+{
+    int rc = RTCritSectEnter(&CritSect);
+    AssertRC(rc);
+}
+
+/**
+ * Unlocks a locked recording stream.
+ *
+ * @param   pStream             Recording stream to unlock.
+ */
+void CaptureStream::unlock(void)
+{
+    int rc = RTCritSectLeave(&CritSect);
+    AssertRC(rc);
+}
+
Index: /trunk/src/VBox/Main/src-server/CaptureScreenSettingsImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/CaptureScreenSettingsImpl.cpp	(revision 75251)
+++ /trunk/src/VBox/Main/src-server/CaptureScreenSettingsImpl.cpp	(revision 75251)
@@ -0,0 +1,532 @@
+/* $Id$ */
+/** @file
+ *
+ * VirtualBox COM class implementation - Capture settings of one virtual screen.
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "CaptureScreenSettingsImpl.h"
+#include "MachineImpl.h"
+
+#include <iprt/path.h>
+#include <iprt/cpp/utils.h>
+#include <VBox/settings.h>
+
+#include "AutoStateDep.h"
+#include "AutoCaller.h"
+#include "Global.h"
+#include "Logging.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// CaptureScreenSettings private data definition
+//
+////////////////////////////////////////////////////////////////////////////////
+
+struct CaptureScreenSettings::Data
+{
+    Data()
+        : pMachine(NULL)
+    { }
+
+    Machine * const                  pMachine;
+    ComObjPtr<CaptureScreenSettings> pPeer;
+    unsigned long                    uScreenId;
+
+    // use the XML settings structure in the members for simplicity
+    Backupable<settings::CaptureScreenSettings> bd;
+};
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(CaptureScreenSettings)
+
+HRESULT CaptureScreenSettings::FinalConstruct()
+{
+    return BaseFinalConstruct();
+}
+
+void CaptureScreenSettings::FinalRelease()
+{
+    uninit();
+    BaseFinalRelease();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Initializes the audio adapter object.
+ *
+ * @returns COM result indicator
+ */
+HRESULT CaptureScreenSettings::init(Machine *aParent, unsigned long uScreenId, const settings::CaptureScreenSettings& data)
+{
+    LogFlowThisFuncEnter();
+    LogFlowThisFunc(("aParent: %p\n", aParent));
+
+    ComAssertRet(aParent, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m = new Data();
+
+    /* share the parent weakly */
+    unconst(m->pMachine) = aParent;
+
+    // simply copy
+    m->uScreenId = uScreenId;
+    m->bd.assignCopy(&data);
+
+    autoInitSpan.setSucceeded();
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
+/**
+ *  Initializes the capture settings object given another capture settings object
+ *  (a kind of copy constructor). This object shares data with
+ *  the object passed as an argument.
+ *
+ *  @note This object must be destroyed before the original object
+ *  it shares data with is destroyed.
+ */
+HRESULT CaptureScreenSettings::init(Machine *aParent, CaptureScreenSettings *that)
+{
+    LogFlowThisFuncEnter();
+    LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
+
+    ComAssertRet(aParent && that, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m = new Data();
+
+    unconst(m->pMachine) = aParent;
+    m->pPeer = that;
+
+    AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS);
+
+    m->uScreenId = that->m->uScreenId;
+    m->bd.share(that->m->bd);
+
+    autoInitSpan.setSucceeded();
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
+/**
+ *  Initializes the guest object given another guest object
+ *  (a kind of copy constructor). This object makes a private copy of data
+ *  of the original object passed as an argument.
+ */
+HRESULT CaptureScreenSettings::initCopy(Machine *aParent, CaptureScreenSettings *that)
+{
+    LogFlowThisFuncEnter();
+    LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
+
+    ComAssertRet(aParent && that, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m = new Data();
+
+    unconst(m->pMachine) = aParent;
+    // mPeer is left null
+
+    AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS);
+
+    m->uScreenId = that->m->uScreenId;
+    m->bd.attachCopy(that->m->bd);
+
+    autoInitSpan.setSucceeded();
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
+/**
+ *  Uninitializes the instance and sets the ready flag to FALSE.
+ *  Called either from FinalRelease() or by the parent when it gets destroyed.
+ */
+void CaptureScreenSettings::uninit()
+{
+    LogFlowThisFuncEnter();
+
+    /* Enclose the state transition Ready->InUninit->NotReady */
+    AutoUninitSpan autoUninitSpan(this);
+    if (autoUninitSpan.uninitDone())
+        return;
+
+    m->bd.free();
+
+    unconst(m->pPeer) = NULL;
+    unconst(m->pMachine) = NULL;
+
+    delete m;
+    m = NULL;
+
+    LogFlowThisFuncLeave();
+}
+
+HRESULT CaptureScreenSettings::isFeatureEnabled(CaptureFeature_T aFeature, BOOL *aEnabled)
+{
+    settings::CaptureFeatureMap::const_iterator itFeature = m->bd->featureMap.find(aFeature);
+
+    *aEnabled = (   itFeature != m->bd->featureMap.end()
+                 && itFeature->second == true);
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getEnabled(BOOL *enabled)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *enabled = m->bd->fEnabled;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setEnabled(BOOL enabled)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (m->bd->fEnabled != enabled)
+    {
+        alock.release();
+
+        HRESULT rc = m->pMachine->i_onCaptureChange();
+        if (FAILED(rc)) return rc;
+
+        m->pMachine->i_setModified(Machine::IsModified_Capture);
+
+        alock.acquire();
+        m->bd->fEnabled = enabled;
+        alock.release();
+
+        /** Save settings if online - @todo why is this required? -- @bugref{6818} */
+        AutoAnyStateDependency adep(m->pMachine);
+        AssertComRCReturn(adep.rc(), E_UNEXPECTED);
+
+        if (Global::IsOnline(adep.machineState()))
+            m->pMachine->i_saveSettings(NULL);
+    }
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getFeatures(ULONG *aFeatures)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aFeatures = 0;
+
+    settings::CaptureFeatureMap::const_iterator itFeature = m->bd->featureMap.begin();
+    while (itFeature != m->bd->featureMap.end())
+    {
+        if (itFeature->second) /* Is feature enable? */
+            *aFeatures |= (ULONG)itFeature->first;
+
+        ++itFeature;
+    }
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setFeatures(ULONG aFeatures)
+{
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change features while capturing is enabled"));
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->featureMap.clear();
+
+    if (aFeatures & CaptureFeature_Audio)
+        m->bd->featureMap[CaptureFeature_Audio] = true;
+    if (aFeatures & CaptureFeature_Video)
+        m->bd->featureMap[CaptureFeature_Video] = true;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getDestination(CaptureDestination_T *aDestination)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aDestination = m->bd->enmDest;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setDestination(CaptureDestination_T aDestination)
+{
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change destination type while capturing is enabled"));
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+    m->bd->enmDest = aDestination;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getFileName(com::Utf8Str &aFileName)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (m->bd->File.strName.isEmpty())
+        i_getDefaultCaptureFile(aFileName);
+    else
+        aFileName = m->bd->File.strName;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setFileName(const com::Utf8Str &aFileName)
+{
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change file name while capturing is enabled"));
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    Utf8Str strFile(aFileName);
+
+    if (!RTPathStartsWithRoot(strFile.c_str()))
+        return setError(E_INVALIDARG, tr("Capture file name '%s' is not absolute"), strFile.c_str());
+
+    if (!strFile.isEmpty())
+    {
+        Utf8Str defaultFile;
+        i_getDefaultCaptureFile(defaultFile);
+        if (!RTPathCompare(strFile.c_str(), defaultFile.c_str()))
+            strFile.setNull();
+    }
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+    m->bd->File.strName = strFile;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getMaxTime(ULONG *aMaxTimeS)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aMaxTimeS =  m->bd->ulMaxTimeS;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setMaxTime(ULONG aMaxTimeS)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change maximum time while capturing is enabled"));
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->ulMaxTimeS = aMaxTimeS;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getMaxFileSize(ULONG *aMaxFileSizeMB)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aMaxFileSizeMB = m->bd->File.ulMaxSizeMB;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setMaxFileSize(ULONG aMaxFileSize)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change maximum file size while capturing is enabled"));
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->File.ulMaxSizeMB = aMaxFileSize;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getOptions(com::Utf8Str &aOptions)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    aOptions = m->bd->strOptions;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setOptions(const com::Utf8Str &aOptions)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change options string while capturing is enabled"));
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->strOptions = aOptions;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getVideoWidth(ULONG *aVideoWidth)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aVideoWidth = m->bd->Video.ulWidth;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setVideoWidth(ULONG aVideoWidth)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change video width while capturing is enabled"));
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->Video.ulWidth = aVideoWidth;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getVideoHeight(ULONG *aVideoHeight)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aVideoHeight = m->bd->Video.ulHeight;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setVideoHeight(ULONG aVideoHeight)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change video height while capturing is enabled"));
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->Video.ulHeight = aVideoHeight;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getVideoRate(ULONG *aVideoRate)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aVideoRate = m->bd->Video.ulRate;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setVideoRate(ULONG aVideoRate)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change video rate while capturing is enabled"));
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->Video.ulRate = aVideoRate;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::getVideoFPS(ULONG *aVideoFPS)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aVideoFPS = m->bd->Video.ulFPS;
+
+    return S_OK;
+}
+
+HRESULT CaptureScreenSettings::setVideoFPS(ULONG aVideoFPS)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!i_canChangeSettings())
+        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
+
+    m->pMachine->i_setModified(Machine::IsModified_Capture);
+    m->bd.backup();
+
+    m->bd->Video.ulFPS = aVideoFPS;
+
+    return S_OK;
+}
+
+bool CaptureScreenSettings::i_canChangeSettings(void)
+{
+    AutoAnyStateDependency adep(m->pMachine);
+    AssertComRCReturn(adep.rc(), E_UNEXPECTED);
+
+    if (   Global::IsOnline(adep.machineState())
+        && m->bd->fEnabled)
+        return false;
+
+    return true;
+}
+
+/**
+ * Returns the full path to the default video capture file.
+ */
+int CaptureScreenSettings::i_getDefaultCaptureFile(Utf8Str &strFile)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    strFile = m->pMachine->i_getSettingsFileFull(); // path/to/machinesfolder/vmname/vmname.vbox
+    strFile.stripSuffix();                          // path/to/machinesfolder/vmname/vmname
+    strFile.append(".webm");                        // path/to/machinesfolder/vmname/vmname.webm
+
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/Main/src-server/CaptureSettingsImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/CaptureSettingsImpl.cpp	(revision 75251)
+++ /trunk/src/VBox/Main/src-server/CaptureSettingsImpl.cpp	(revision 75251)
@@ -0,0 +1,406 @@
+/* $Id$ */
+/** @file
+ *
+ * VirtualBox COM class implementation - Machine capture settings.
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "CaptureSettingsImpl.h"
+#include "CaptureScreenSettingsImpl.h"
+#include "MachineImpl.h"
+
+#include <iprt/cpp/utils.h>
+#include <VBox/settings.h>
+
+#include "AutoStateDep.h"
+#include "AutoCaller.h"
+#include "Global.h"
+#include "Logging.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// CaptureSettings private data definition
+//
+////////////////////////////////////////////////////////////////////////////////
+
+struct CaptureSettings::Data
+{
+    Data()
+        : pMachine(NULL)
+    { }
+
+    Machine * const             pMachine;
+    ComObjPtr<CaptureSettings>  pPeer;
+    CaptureScreenSettingsMap    mapScreenSettings;
+
+    // use the XML settings structure in the members for simplicity
+    Backupable<settings::CaptureSettings> bd;
+};
+
+DEFINE_EMPTY_CTOR_DTOR(CaptureSettings)
+
+HRESULT CaptureSettings::FinalConstruct()
+{
+    return BaseFinalConstruct();
+}
+
+void CaptureSettings::FinalRelease()
+{
+    uninit();
+    BaseFinalRelease();
+}
+
+/**
+ * Initializes the audio adapter object.
+ *
+ * @returns COM result indicator
+ */
+HRESULT CaptureSettings::init(Machine *aParent)
+{
+    LogFlowThisFuncEnter();
+    LogFlowThisFunc(("aParent: %p\n", aParent));
+
+    ComAssertRet(aParent, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m = new Data();
+
+    /* share the parent weakly */
+    unconst(m->pMachine) = aParent;
+
+    m->bd.allocate();
+
+    autoInitSpan.setSucceeded();
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
+/**
+ *  Initializes the capture settings object given another capture settings object
+ *  (a kind of copy constructor). This object shares data with
+ *  the object passed as an argument.
+ *
+ *  @note This object must be destroyed before the original object
+ *  it shares data with is destroyed.
+ */
+HRESULT CaptureSettings::init(Machine *aParent, CaptureSettings *that)
+{
+    LogFlowThisFuncEnter();
+    LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
+
+    ComAssertRet(aParent && that, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m = new Data();
+
+    unconst(m->pMachine) = aParent;
+    m->pPeer = that;
+
+    AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS);
+    m->bd.share(that->m->bd);
+
+    autoInitSpan.setSucceeded();
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
+/**
+ *  Initializes the guest object given another guest object
+ *  (a kind of copy constructor). This object makes a private copy of data
+ *  of the original object passed as an argument.
+ */
+HRESULT CaptureSettings::initCopy(Machine *aParent, CaptureSettings *that)
+{
+    LogFlowThisFuncEnter();
+    LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
+
+    ComAssertRet(aParent && that, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m = new Data();
+
+    unconst(m->pMachine) = aParent;
+    // mPeer is left null
+
+    AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS);
+    m->bd.attachCopy(that->m->bd);
+
+    autoInitSpan.setSucceeded();
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
+/**
+ *  Uninitializes the instance and sets the ready flag to FALSE.
+ *  Called either from FinalRelease() or by the parent when it gets destroyed.
+ */
+void CaptureSettings::uninit()
+{
+    LogFlowThisFuncEnter();
+
+    /* Enclose the state transition Ready->InUninit->NotReady */
+    AutoUninitSpan autoUninitSpan(this);
+    if (autoUninitSpan.uninitDone())
+        return;
+
+    m->bd.free();
+
+    unconst(m->pPeer) = NULL;
+    unconst(m->pMachine) = NULL;
+
+    delete m;
+    m = NULL;
+
+    LogFlowThisFuncLeave();
+}
+
+// ICaptureSettings properties
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CaptureSettings::getEnabled(BOOL *enabled)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *enabled = m->bd->fEnabled;
+
+    return S_OK;
+}
+
+HRESULT CaptureSettings::setEnabled(BOOL enable)
+{
+    /* the machine needs to be mutable */
+    AutoMutableStateDependency adep(m->pMachine);
+    if (FAILED(adep.rc())) return adep.rc();
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    const bool fEnabled = RT_BOOL(enable);
+
+    HRESULT rc = S_OK;
+
+    if (m->bd->fEnabled != fEnabled)
+    {
+        m->bd.backup();
+        m->bd->fEnabled = fEnabled;
+
+        alock.release();
+        rc = m->pMachine->i_onCaptureChange();
+        if (FAILED(rc))
+        {
+            /*
+             * Normally we would do the actual change _after_ i_onVideoCaptureChange() succeeded.
+             * We cannot do this because that function uses Machine::GetVideoCaptureEnabled to
+             * determine if it should start or stop capturing. Therefore we need to manually
+             * undo change.
+             */
+            alock.acquire();
+            m->bd->fEnabled = m->bd.backedUpData()->fEnabled;
+            return rc;
+        }
+        else
+        {
+            AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);  // mParent is const, needs no locking
+            m->pMachine->i_setModified(Machine::IsModified_Capture);
+
+            /** Save settings if online - @todo why is this required? -- @bugref{6818} */
+            if (Global::IsOnline(adep.machineState()))
+                m->pMachine->i_saveSettings(NULL);
+        }
+    }
+
+    return rc;
+}
+
+HRESULT CaptureSettings::getScreens(std::vector<ComPtr<ICaptureScreenSettings> > &aCaptureScreenSettings)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    aCaptureScreenSettings.clear();
+    aCaptureScreenSettings.resize(m->mapScreenSettings.size());
+
+    CaptureScreenSettingsMap::const_iterator itScreenSettings = m->mapScreenSettings.begin();
+    size_t i = 0;
+    while (itScreenSettings != m->mapScreenSettings.end())
+    {
+        itScreenSettings->second.queryInterfaceTo(aCaptureScreenSettings[i].asOutParam());
+        ++i;
+        ++itScreenSettings;
+    }
+
+    return S_OK;
+}
+
+HRESULT CaptureSettings::getScreenSettings(ULONG uScreenId, ComPtr<ICaptureScreenSettings> &aCaptureScreenSettings)
+{
+    if (uScreenId + 1 > m->mapScreenSettings.size())
+        return setError(E_INVALIDARG, tr("Invalid screen ID specified"));
+
+    CaptureScreenSettingsMap::const_iterator itScreenSettings = m->mapScreenSettings.find(uScreenId);
+    if (itScreenSettings != m->mapScreenSettings.end())
+    {
+        itScreenSettings->second.queryInterfaceTo(aCaptureScreenSettings.asOutParam());
+        return S_OK;
+    }
+
+    return VBOX_E_OBJECT_NOT_FOUND;
+}
+
+// ICaptureSettings methods
+/////////////////////////////////////////////////////////////////////////////
+
+// public methods only for internal purposes
+/////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Loads settings from the given settings.
+ * May be called once right after this object creation.
+ *
+ * @param data                  Capture settings to load from.
+ *
+ * @note Locks this object for writing.
+ */
+HRESULT CaptureSettings::i_loadSettings(const settings::CaptureSettings &data)
+{
+    AutoCaller autoCaller(this);
+    AssertComRCReturnRC(autoCaller.rc());
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    HRESULT rc = S_OK;
+
+    settings::CaptureScreenMap::const_iterator itScreen = data.mapScreens.begin();
+    while (itScreen != data.mapScreens.end())
+    {
+        ComObjPtr<CaptureScreenSettings> captureScreenSettings;
+        rc = captureScreenSettings.createObject();
+        if (FAILED(rc))
+            break;
+
+        rc = captureScreenSettings->init(m->pMachine, itScreen->first /* uScreenId */, itScreen->second /* Settings */);
+        if (FAILED(rc))
+            break;
+
+        ++itScreen;
+    }
+
+    // simply copy
+    m->bd.assignCopy(&data);
+
+    return rc;
+}
+
+/**
+ * Saves settings to the given settings.
+ *
+ * @param data                  Where to store the capture settings to.
+ *
+ * @note Locks this object for reading.
+ */
+HRESULT CaptureSettings::i_saveSettings(settings::CaptureSettings &data)
+{
+    AutoCaller autoCaller(this);
+    AssertComRCReturnRC(autoCaller.rc());
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    data = *m->bd.data();
+
+    settings::CaptureScreenMap::iterator itScreen = data.mapScreens.begin();
+    while (itScreen != data.mapScreens.end())
+    {
+        /* Store relative path of capture file if possible. */
+        m->pMachine->i_copyPathRelativeToMachine(itScreen->second.File.strName /* Source */,
+                                                 itScreen->second.File.strName /* Target */);
+        ++itScreen;
+    }
+
+    return S_OK;
+}
+
+void CaptureSettings::i_rollback()
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+    m->bd.rollback();
+}
+
+void CaptureSettings::i_commit()
+{
+    /* sanity */
+    AutoCaller autoCaller(this);
+    AssertComRCReturnVoid(autoCaller.rc());
+
+    /* sanity too */
+    AutoCaller peerCaller(m->pPeer);
+    AssertComRCReturnVoid(peerCaller.rc());
+
+    /* lock both for writing since we modify both (mPeer is "master" so locked
+     * first) */
+    AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
+
+    if (m->bd.isBackedUp())
+    {
+        m->bd.commit();
+        if (m->pPeer)
+        {
+            /* attach new data to the peer and reshare it */
+            AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
+            m->pPeer->m->bd.attach(m->bd);
+        }
+    }
+}
+
+void CaptureSettings::i_copyFrom(CaptureSettings *aThat)
+{
+    AssertReturnVoid(aThat != NULL);
+
+    /* sanity */
+    AutoCaller autoCaller(this);
+    AssertComRCReturnVoid(autoCaller.rc());
+
+    /* sanity too */
+    AutoCaller thatCaller(aThat);
+    AssertComRCReturnVoid(thatCaller.rc());
+
+    /* peer is not modified, lock it for reading (aThat is "master" so locked
+     * first) */
+    AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
+    AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
+
+    /* this will back up current data */
+    m->bd.assignCopy(aThat->m->bd);
+}
+
+void CaptureSettings::i_applyDefaults(void)
+{
+    /* sanity */
+    AutoCaller autoCaller(this);
+    AssertComRCReturnVoid(autoCaller.rc());
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    /* Initialize default capturing settings here. */
+}
+
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 75251)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2004-2017 Oracle Corporation
+ * Copyright (C) 2004-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -168,14 +168,4 @@
     mAccelerate2DVideoEnabled = false;
     mMonitorCount = 1;
-    mVideoCaptureWidth = 1024;
-    mVideoCaptureHeight = 768;
-    mVideoCaptureRate = 512;
-    mVideoCaptureFPS = 25;
-    mVideoCaptureMaxTime = 0;
-    mVideoCaptureMaxFileSize = 0;
-    mVideoCaptureEnabled = false;
-    for (unsigned i = 0; i < RT_ELEMENTS(maVideoCaptureScreens); ++i)
-        maVideoCaptureScreens[i] = true;
-
     mHWVirtExEnabled = true;
     mHWVirtExNestedPagingEnabled = true;
@@ -365,6 +355,9 @@
         }
 
-        /* Apply BIOS defaults */
+        /* Apply BIOS defaults. */
         mBIOSSettings->i_applyDefaults(aOsType);
+
+        /* Apply capture defaults. */
+        mCaptureSettings->i_applyDefaults();
 
         /* Apply network adapters defaults */
@@ -1732,276 +1725,4 @@
 }
 
-HRESULT Machine::getVideoCaptureEnabled(BOOL *aVideoCaptureEnabled)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    *aVideoCaptureEnabled = mHWData->mVideoCaptureEnabled;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureEnabled(BOOL aVideoCaptureEnabled)
-{
-    HRESULT rc = S_OK;
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureEnabled = aVideoCaptureEnabled;
-
-    alock.release();
-    rc = i_onVideoCaptureChange();
-    alock.acquire();
-    if (FAILED(rc))
-    {
-        /*
-         * Normally we would do the actual change _after_ i_onVideoCaptureChange() succeeded.
-         * We cannot do this because that function uses Machine::GetVideoCaptureEnabled to
-         * determine if it should start or stop capturing. Therefore we need to manually
-         * undo change.
-         */
-        mHWData->mVideoCaptureEnabled = mHWData.backedUpData()->mVideoCaptureEnabled;
-        return rc;
-    }
-
-    /** Save settings if online - @todo why is this required? -- @bugref{6818} */
-    if (Global::IsOnline(mData->mMachineState))
-        i_saveSettings(NULL);
-
-    return rc;
-}
-
-HRESULT Machine::getVideoCaptureScreens(std::vector<BOOL> &aVideoCaptureScreens)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    aVideoCaptureScreens.resize(mHWData->mMonitorCount);
-    for (unsigned i = 0; i < mHWData->mMonitorCount; ++i)
-        aVideoCaptureScreens[i] = mHWData->maVideoCaptureScreens[i];
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureScreens(const std::vector<BOOL> &aVideoCaptureScreens)
-{
-    AssertReturn(aVideoCaptureScreens.size() <= RT_ELEMENTS(mHWData->maVideoCaptureScreens), E_INVALIDARG);
-    bool fChanged = false;
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    for (unsigned i = 0; i < aVideoCaptureScreens.size(); ++i)
-    {
-        if (mHWData->maVideoCaptureScreens[i] != RT_BOOL(aVideoCaptureScreens[i]))
-        {
-            mHWData->maVideoCaptureScreens[i] = RT_BOOL(aVideoCaptureScreens[i]);
-            fChanged = true;
-        }
-    }
-    if (fChanged)
-    {
-        alock.release();
-        HRESULT rc = i_onVideoCaptureChange();
-        alock.acquire();
-        if (FAILED(rc)) return rc;
-        i_setModified(IsModified_MachineData);
-
-        /** Save settings if online - @todo why is this required? -- @bugref{6818} */
-        if (Global::IsOnline(mData->mMachineState))
-            i_saveSettings(NULL);
-    }
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureFile(com::Utf8Str &aVideoCaptureFile)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    if (mHWData->mVideoCaptureFile.isEmpty())
-        i_getDefaultVideoCaptureFile(aVideoCaptureFile);
-    else
-        aVideoCaptureFile = mHWData->mVideoCaptureFile;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureFile(const com::Utf8Str &aVideoCaptureFile)
-{
-    Utf8Str strFile(aVideoCaptureFile);
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    if (!RTPathStartsWithRoot(strFile.c_str()))
-        return setError(E_INVALIDARG, tr("Video capture file name '%s' is not absolute"), strFile.c_str());
-
-    if (!strFile.isEmpty())
-    {
-        Utf8Str defaultFile;
-        i_getDefaultVideoCaptureFile(defaultFile);
-        if (!RTPathCompare(strFile.c_str(), defaultFile.c_str()))
-            strFile.setNull();
-    }
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureFile = strFile;
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureWidth(ULONG *aVideoCaptureWidth)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    *aVideoCaptureWidth = mHWData->mVideoCaptureWidth;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureWidth(ULONG aVideoCaptureWidth)
-{
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureWidth = aVideoCaptureWidth;
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureHeight(ULONG *aVideoCaptureHeight)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    *aVideoCaptureHeight = mHWData->mVideoCaptureHeight;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureHeight(ULONG aVideoCaptureHeight)
-{
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureHeight = aVideoCaptureHeight;
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureRate(ULONG *aVideoCaptureRate)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    *aVideoCaptureRate = mHWData->mVideoCaptureRate;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureRate(ULONG aVideoCaptureRate)
-{
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureRate = aVideoCaptureRate;
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureFPS(ULONG *aVideoCaptureFPS)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    *aVideoCaptureFPS = mHWData->mVideoCaptureFPS;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureFPS(ULONG aVideoCaptureFPS)
-{
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureFPS = aVideoCaptureFPS;
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureMaxTime(ULONG *aVideoCaptureMaxTime)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    *aVideoCaptureMaxTime = mHWData->mVideoCaptureMaxTime;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureMaxTime(ULONG aVideoCaptureMaxTime)
-{
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureMaxTime = aVideoCaptureMaxTime;
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureMaxFileSize(ULONG *aVideoCaptureMaxFileSize)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    *aVideoCaptureMaxFileSize = mHWData->mVideoCaptureMaxFileSize;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureMaxFileSize(ULONG aVideoCaptureMaxFileSize)
-{
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureMaxFileSize = aVideoCaptureMaxFileSize;
-
-    return S_OK;
-}
-
-HRESULT Machine::getVideoCaptureOptions(com::Utf8Str &aVideoCaptureOptions)
-{
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    aVideoCaptureOptions = mHWData->mVideoCaptureOptions;
-    return S_OK;
-}
-
-HRESULT Machine::setVideoCaptureOptions(const com::Utf8Str &aVideoCaptureOptions)
-{
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (   Global::IsOnline(mData->mMachineState)
-        && mHWData->mVideoCaptureEnabled)
-        return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));
-
-    i_setModified(IsModified_MachineData);
-    mHWData.backup();
-    mHWData->mVideoCaptureOptions = aVideoCaptureOptions;
-
-    return S_OK;
-}
-
 HRESULT Machine::getGraphicsControllerType(GraphicsControllerType_T *aGraphicsControllerType)
 {
@@ -2215,4 +1936,12 @@
     /* mBIOSSettings is constant during life time, no need to lock */
     aBIOSSettings = mBIOSSettings;
+
+    return S_OK;
+}
+
+HRESULT Machine::getCaptureSettings(ComPtr<ICaptureSettings> &aCaptureSettings)
+{
+    /* mCaptureSettings is constant during life time, no need to lock */
+    aCaptureSettings = mCaptureSettings;
 
     return S_OK;
@@ -7654,19 +7383,4 @@
 
 /**
- *  Returns the full path to the default video capture file.
- */
-void Machine::i_getDefaultVideoCaptureFile(Utf8Str &strFile)
-{
-    AutoCaller autoCaller(this);
-    AssertComRCReturnVoid(autoCaller.rc());
-
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    strFile = mData->m_strConfigFileFull;       // path/to/machinesfolder/vmname/vmname.vbox
-    strFile.stripSuffix();                      // path/to/machinesfolder/vmname/vmname
-    strFile.append(".webm");                    // path/to/machinesfolder/vmname/vmname.webm
-}
-
-/**
  * Returns whether at least one USB controller is present for the VM.
  */
@@ -8545,4 +8259,8 @@
     mBIOSSettings->init(this);
 
+    /* create associated capture settings object */
+    unconst(mCaptureSettings).createObject();
+    mCaptureSettings->init(this);
+
     /* create an associated VRDE object (default is disabled) */
     unconst(mVRDEServer).createObject();
@@ -8658,4 +8376,10 @@
         mBIOSSettings->uninit();
         unconst(mBIOSSettings).setNull();
+    }
+
+    if (mCaptureSettings)
+    {
+        mCaptureSettings->uninit();
+        unconst(mCaptureSettings).setNull();
     }
 
@@ -9157,17 +8881,4 @@
         mHWData->mAccelerate3DEnabled = data.fAccelerate3D;
         mHWData->mAccelerate2DVideoEnabled = data.fAccelerate2DVideo;
-        mHWData->mVideoCaptureWidth = data.ulVideoCaptureHorzRes;
-        mHWData->mVideoCaptureHeight = data.ulVideoCaptureVertRes;
-        mHWData->mVideoCaptureEnabled = data.fVideoCaptureEnabled;
-        for (unsigned i = 0; i < RT_ELEMENTS(mHWData->maVideoCaptureScreens); ++i)
-            mHWData->maVideoCaptureScreens[i] = ASMBitTest(&data.u64VideoCaptureScreens, i);
-        AssertCompile(RT_ELEMENTS(mHWData->maVideoCaptureScreens) == sizeof(data.u64VideoCaptureScreens) * 8);
-        mHWData->mVideoCaptureRate = data.ulVideoCaptureRate;
-        mHWData->mVideoCaptureFPS = data.ulVideoCaptureFPS;
-        if (!data.strVideoCaptureFile.isEmpty())
-            i_calculateFullPath(data.strVideoCaptureFile, mHWData->mVideoCaptureFile);
-        else
-            mHWData->mVideoCaptureFile.setNull();
-        mHWData->mVideoCaptureOptions = data.strVideoCaptureOptions;
         mHWData->mFirmwareType = data.firmwareType;
         mHWData->mPointingHIDType = data.pointingHIDType;
@@ -9187,9 +8898,13 @@
         if (FAILED(rc)) return rc;
 
+        /* Capture settings */
+        rc = mCaptureSettings->i_loadSettings(data.captureSettings);
+        if (FAILED(rc)) return rc;
+
         // Bandwidth control (must come before network adapters)
         rc = mBandwidthControl->i_loadSettings(data.ioSettings);
         if (FAILED(rc)) return rc;
 
-        /* Shared folders */
+        /* USB controllers */
         for (settings::USBControllerList::const_iterator
              it = data.usbSettings.llUSBControllers.begin();
@@ -10493,19 +10208,4 @@
         data.fAccelerate3D = !!mHWData->mAccelerate3DEnabled;
         data.fAccelerate2DVideo = !!mHWData->mAccelerate2DVideoEnabled;
-        data.ulVideoCaptureHorzRes = mHWData->mVideoCaptureWidth;
-        data.ulVideoCaptureVertRes = mHWData->mVideoCaptureHeight;
-        data.ulVideoCaptureRate = mHWData->mVideoCaptureRate;
-        data.ulVideoCaptureFPS = mHWData->mVideoCaptureFPS;
-        data.fVideoCaptureEnabled  = !!mHWData->mVideoCaptureEnabled;
-        for (unsigned i = 0; i < sizeof(data.u64VideoCaptureScreens) * 8; ++i)
-        {
-            if (mHWData->maVideoCaptureScreens[i])
-                ASMBitSet(&data.u64VideoCaptureScreens, i);
-            else
-                ASMBitClear(&data.u64VideoCaptureScreens, i);
-        }
-        /* store relative video capture file if possible */
-        i_copyPathRelativeToMachine(mHWData->mVideoCaptureFile, data.strVideoCaptureFile);
-        data.strVideoCaptureOptions = mHWData->mVideoCaptureOptions;
 
         /* VRDEServer settings (optional) */
@@ -10513,6 +10213,10 @@
         if (FAILED(rc)) throw rc;
 
-        /* BIOS (required) */
+        /* BIOS settings (required) */
         rc = mBIOSSettings->i_saveSettings(data.biosSettings);
+        if (FAILED(rc)) throw rc;
+
+        /* Capture settings (required) */
+        rc = mCaptureSettings->i_saveSettings(data.captureSettings);
         if (FAILED(rc)) throw rc;
 
@@ -12019,4 +11723,7 @@
         mBIOSSettings->i_rollback();
 
+    if (mCaptureSettings && (mData->flModifications & IsModified_Capture))
+        mCaptureSettings->i_rollback();
+
     if (mVRDEServer && (mData->flModifications & IsModified_VRDEServer))
         mVRDEServer->i_rollback();
@@ -12129,4 +11836,5 @@
 
     mBIOSSettings->i_commit();
+    mCaptureSettings->i_commit();
     mVRDEServer->i_commit();
     mAudioAdapter->i_commit();
@@ -12381,4 +12089,5 @@
 
     mBIOSSettings->i_copyFrom(aThat->mBIOSSettings);
+    mCaptureSettings->i_copyFrom(aThat->mCaptureSettings);
     mVRDEServer->i_copyFrom(aThat->mVRDEServer);
     mAudioAdapter->i_copyFrom(aThat->mAudioAdapter);
@@ -12754,4 +12463,6 @@
     unconst(mBIOSSettings).createObject();
     mBIOSSettings->init(this, aMachine->mBIOSSettings);
+    unconst(mCaptureSettings).createObject();
+    mCaptureSettings->init(this, aMachine->mCaptureSettings);
     /* create another VRDEServer object that will be mutable */
     unconst(mVRDEServer).createObject();
@@ -14387,5 +14098,5 @@
  * @note Locks this object for reading.
  */
-HRESULT SessionMachine::i_onVideoCaptureChange()
+HRESULT SessionMachine::i_onCaptureChange()
 {
     LogFlowThisFunc(("\n"));
@@ -14405,5 +14116,5 @@
         return S_OK;
 
-    return directControl->OnVideoCaptureChange();
+    return directControl->OnCaptureChange();
 }
 
@@ -15339,4 +15050,7 @@
     mBIOSSettings->i_applyDefaults(osType);
 
+    /* Initialize default capture settings. */
+    mCaptureSettings->i_applyDefaults();
+
     /* Initialize default BIOS settings here */
     mHWData->mAPIC = osType->i_recommendedIOAPIC();
Index: /trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/Settings.cpp	(revision 75250)
+++ /trunk/src/VBox/Main/xml/Settings.cpp	(revision 75251)
@@ -2371,4 +2371,168 @@
 }
 
+CaptureScreenSettings::CaptureScreenSettings(void)
+{
+    applyDefaults();
+}
+
+CaptureScreenSettings::~CaptureScreenSettings()
+{
+
+}
+
+void CaptureScreenSettings::applyDefaults(void)
+{
+    /*
+     * Set sensible defaults.
+     */
+
+    fEnabled            = true;
+    enmDest             = CaptureDestination_File;
+    ulMaxTimeS          = 0;
+    strOptions          = "";
+    File.ulMaxSizeMB    = 0;
+    Video.enmCodec      = CaptureVideoCodec_VP8;
+    Video.ulWidth       = 1024;
+    Video.ulHeight      = 768;
+    Video.ulRate        = 512;
+    Video.ulFPS         = 25;
+    Audio.enmAudioCodec = CaptureAudioCodec_Opus;
+    Audio.cBits         = 16;
+    Audio.cChannels     = 2;
+    Audio.uHz           = 22050;
+
+    featureMap[CaptureFeature_Video] = true;
+    featureMap[CaptureFeature_Audio] = false;
+
+    //i_calculateFullPath
+}
+
+/**
+ * Check if all settings have default values.
+ */
+bool CaptureScreenSettings::areDefaultSettings(void) const
+{
+    const bool fDefault =    fEnabled            == true
+                          && enmDest             == CaptureDestination_File
+                          && ulMaxTimeS          == 0
+                          && strOptions          == ""
+                          && File.ulMaxSizeMB    == 0
+                          && Video.enmCodec      == CaptureVideoCodec_VP8
+                          && Video.ulWidth       == 1024
+                          && Video.ulHeight      == 768
+                          && Video.ulRate        == 512
+                          && Video.ulFPS         == 25
+                          && Audio.enmAudioCodec == CaptureAudioCodec_Opus
+                          && Audio.cBits         == 16
+                          && Audio.cChannels     == 2
+                          && Audio.uHz           == 22050;
+
+    return fDefault;
+}
+
+bool CaptureScreenSettings::isFeatureEnabled(CaptureFeature_T enmFeature) const
+{
+    CaptureFeatureMap::const_iterator itFeature = featureMap.find(enmFeature);
+    if (itFeature != featureMap.end())
+        return itFeature->second;
+
+    return false;
+}
+
+/**
+ * Comparison operator. This gets called from MachineConfigFile::operator==,
+ * which in turn gets called from Machine::saveSettings to figure out whether
+ * machine settings have really changed and thus need to be written out to disk.
+ */
+bool CaptureScreenSettings::operator==(const CaptureScreenSettings &d) const
+{
+    return    fEnabled            == d.fEnabled
+           && enmDest             == d.enmDest
+           && featureMap          == d.featureMap
+           && ulMaxTimeS          == d.ulMaxTimeS
+           && strOptions          == d.strOptions
+           && File.ulMaxSizeMB    == d.File.ulMaxSizeMB
+           && Video.enmCodec      == d.Video.enmCodec
+           && Video.ulWidth       == d.Video.ulWidth
+           && Video.ulHeight      == d.Video.ulHeight
+           && Video.ulRate        == d.Video.ulRate
+           && Video.ulFPS         == d.Video.ulFPS
+           && Audio.enmAudioCodec == d.Audio.enmAudioCodec
+           && Audio.cBits         == d.Audio.cBits
+           && Audio.cChannels     == d.Audio.cChannels
+           && Audio.uHz           == d.Audio.uHz;
+}
+
+/**
+ * Constructor. Needs to set sane defaults which stand the test of time.
+ */
+CaptureSettings::CaptureSettings()
+{
+    applyDefaults();
+}
+
+void CaptureSettings::applyDefaults(void)
+{
+    fEnabled = false;
+
+    mapScreens.clear();
+
+    CaptureScreenSettings screenSettings; /* Apply default settings. */
+    for (unsigned long l = 0; l < SchemaDefs::MaxGuestMonitors; l++)
+    {
+        mapScreens[l] = screenSettings;
+    }
+}
+
+/**
+ * Check if all settings have default values.
+ */
+bool CaptureSettings::areDefaultSettings() const
+{
+    CaptureScreenMap::const_iterator itScreen = mapScreens.begin();
+    while (itScreen != mapScreens.end())
+    {
+        if (!itScreen->second.areDefaultSettings())
+            return false;
+
+        ++itScreen;
+    }
+
+    return true;
+}
+
+/**
+ * Comparison operator. This gets called from MachineConfigFile::operator==,
+ * which in turn gets called from Machine::saveSettings to figure out whether
+ * machine settings have really changed and thus need to be written out to disk.
+ */
+bool CaptureSettings::operator==(const CaptureSettings &d) const
+{
+    if (this == &d)
+        return true;
+
+    if (   fEnabled          != d.fEnabled
+        || mapScreens.size() != d.mapScreens.size())
+        return false;
+
+    CaptureScreenMap::const_iterator itScreen = mapScreens.begin();
+    size_t i = 0;
+    while (itScreen != mapScreens.end())
+    {
+        CaptureScreenMap::const_iterator itScreenThat = d.mapScreens.find(i);
+        if (itScreen->second == itScreenThat->second)
+        {
+            /* Nothing to do in here (yet). */
+        }
+        else
+            return false;
+
+        ++itScreen;
+        ++i;
+    }
+
+    return true;
+}
+
 /**
  * Constructor. Needs to set sane defaults which stand the test of time.
@@ -2901,13 +3065,4 @@
     fAccelerate3D(false),
     fAccelerate2DVideo(false),
-    ulVideoCaptureHorzRes(1024),
-    ulVideoCaptureVertRes(768),
-    ulVideoCaptureRate(512),
-    ulVideoCaptureFPS(25),
-    ulVideoCaptureMaxTime(0),
-    ulVideoCaptureMaxSize(0),
-    fVideoCaptureEnabled(false),
-    u64VideoCaptureScreens(UINT64_C(0xffffffffffffffff)),
-    strVideoCaptureFile(""),
     firmwareType(FirmwareType_BIOS),
     pointingHIDType(PointingHIDType_PS2Mouse),
@@ -2986,21 +3141,4 @@
         && !fAccelerate3D
         && !fAccelerate2DVideo;
-}
-
-/**
- * Check if all Video Capture settings have default values.
- */
-bool Hardware::areVideoCaptureDefaultSettings() const
-{
-    return    !fVideoCaptureEnabled
-           && u64VideoCaptureScreens == UINT64_C(0xffffffffffffffff)
-           && strVideoCaptureFile.isEmpty()
-           && ulVideoCaptureHorzRes == 1024
-           && ulVideoCaptureVertRes == 768
-           && ulVideoCaptureRate == 512
-           && ulVideoCaptureFPS == 25
-           && ulVideoCaptureMaxTime == 0
-           && ulVideoCaptureMaxSize == 0
-           && strVideoCaptureOptions.isEmpty();
 }
 
@@ -3062,14 +3200,4 @@
             && fAccelerate3D             == h.fAccelerate3D
             && fAccelerate2DVideo        == h.fAccelerate2DVideo
-            && fVideoCaptureEnabled      == h.fVideoCaptureEnabled
-            && u64VideoCaptureScreens    == h.u64VideoCaptureScreens
-            && strVideoCaptureFile       == h.strVideoCaptureFile
-            && ulVideoCaptureHorzRes     == h.ulVideoCaptureHorzRes
-            && ulVideoCaptureVertRes     == h.ulVideoCaptureVertRes
-            && ulVideoCaptureRate        == h.ulVideoCaptureRate
-            && ulVideoCaptureFPS         == h.ulVideoCaptureFPS
-            && ulVideoCaptureMaxTime     == h.ulVideoCaptureMaxTime
-            && ulVideoCaptureMaxSize     == h.ulVideoCaptureMaxTime
-            && strVideoCaptureOptions    == h.strVideoCaptureOptions
             && firmwareType              == h.firmwareType
             && pointingHIDType           == h.pointingHIDType
@@ -4276,14 +4404,32 @@
         else if (pelmHwChild->nameEquals("VideoCapture"))
         {
-            pelmHwChild->getAttributeValue("enabled",   hw.fVideoCaptureEnabled);
-            pelmHwChild->getAttributeValue("screens",   hw.u64VideoCaptureScreens);
-            pelmHwChild->getAttributeValuePath("file",  hw.strVideoCaptureFile);
-            pelmHwChild->getAttributeValue("horzRes",   hw.ulVideoCaptureHorzRes);
-            pelmHwChild->getAttributeValue("vertRes",   hw.ulVideoCaptureVertRes);
-            pelmHwChild->getAttributeValue("rate",      hw.ulVideoCaptureRate);
-            pelmHwChild->getAttributeValue("fps",       hw.ulVideoCaptureFPS);
-            pelmHwChild->getAttributeValue("maxTime",   hw.ulVideoCaptureMaxTime);
-            pelmHwChild->getAttributeValue("maxSize",   hw.ulVideoCaptureMaxSize);
-            pelmHwChild->getAttributeValue("options",   hw.strVideoCaptureOptions);
+            pelmHwChild->getAttributeValue("enabled",   hw.captureSettings.fEnabled);
+
+            /* Right now I don't want to bump the settings version, so just convert the enabled
+             * screens to the former uint6t_t bit array and vice versa. */
+            uint64_t u64VideoCaptureScreens;
+            pelmHwChild->getAttributeValue("screens",   u64VideoCaptureScreens);
+
+            /* At the moment we only support one capturing configuration, that is, all screens
+             * have the same configuration. So load/save to/from screen 0. */
+            CaptureScreenSettings &screen0Settings = hw.captureSettings.mapScreens[0];
+
+            pelmHwChild->getAttributeValue("maxTime",   screen0Settings.ulMaxTimeS);
+            pelmHwChild->getAttributeValue("options",   screen0Settings.strOptions);
+            pelmHwChild->getAttributeValuePath("file",  screen0Settings.File.strName);
+            pelmHwChild->getAttributeValue("maxSize",   screen0Settings.File.ulMaxSizeMB);
+            pelmHwChild->getAttributeValue("horzRes",   screen0Settings.Video.ulWidth);
+            pelmHwChild->getAttributeValue("vertRes",   screen0Settings.Video.ulHeight);
+            pelmHwChild->getAttributeValue("rate",      screen0Settings.Video.ulRate);
+            pelmHwChild->getAttributeValue("fps",       screen0Settings.Video.ulFPS);
+
+            for (unsigned i = 0; i < 64; i++)
+            {
+                if (u64VideoCaptureScreens & RT_BIT(i)) /* Screen i enabled? */
+                {
+                    hw.captureSettings.mapScreens[i] = screen0Settings;
+                    hw.captureSettings.mapScreens[i].fEnabled = true;
+                }
+            }
         }
         else if (pelmHwChild->nameEquals("RemoteDisplay"))
@@ -5668,28 +5814,50 @@
     }
 
-    if (m->sv >= SettingsVersion_v1_14 && !hw.areVideoCaptureDefaultSettings())
+    if (m->sv >= SettingsVersion_v1_14 && !hw.captureSettings.areDefaultSettings())
     {
         xml::ElementNode *pelmVideoCapture = pelmHardware->createChild("VideoCapture");
-        if (hw.fVideoCaptureEnabled)
-            pelmVideoCapture->setAttribute("enabled",      hw.fVideoCaptureEnabled);
-        if (hw.u64VideoCaptureScreens != UINT64_C(0xffffffffffffffff))
-            pelmVideoCapture->setAttribute("screens",      hw.u64VideoCaptureScreens);
-        if (!hw.strVideoCaptureFile.isEmpty())
-            pelmVideoCapture->setAttributePath("file",     hw.strVideoCaptureFile);
-        if (hw.ulVideoCaptureHorzRes != 1024 || hw.ulVideoCaptureVertRes != 768)
-        {
-            pelmVideoCapture->setAttribute("horzRes",      hw.ulVideoCaptureHorzRes);
-            pelmVideoCapture->setAttribute("vertRes",      hw.ulVideoCaptureVertRes);
-        }
-        if (hw.ulVideoCaptureRate != 512)
-            pelmVideoCapture->setAttribute("rate",         hw.ulVideoCaptureRate);
-        if (hw.ulVideoCaptureFPS)
-            pelmVideoCapture->setAttribute("fps",          hw.ulVideoCaptureFPS);
-        if (hw.ulVideoCaptureMaxTime)
-            pelmVideoCapture->setAttribute("maxTime",      hw.ulVideoCaptureMaxTime);
-        if (hw.ulVideoCaptureMaxSize)
-            pelmVideoCapture->setAttribute("maxSize",      hw.ulVideoCaptureMaxSize);
-        if (!hw.strVideoCaptureOptions.isEmpty())
-            pelmVideoCapture->setAttributePath("options",  hw.strVideoCaptureOptions);
+
+        if (hw.captureSettings.fEnabled)
+            pelmVideoCapture->setAttribute("enabled", hw.captureSettings.fEnabled);
+
+        /* Right now I don't want to bump the settings version, so just convert the enabled
+         * screens to the former uint6t_t bit array and vice versa. */
+        uint64_t u64VideoCaptureScreens = 0;
+        CaptureScreenMap::const_iterator itScreen = hw.captureSettings.mapScreens.begin();
+        while (itScreen != hw.captureSettings.mapScreens.end())
+        {
+            if (itScreen->second.fEnabled)
+               u64VideoCaptureScreens |= RT_BIT(itScreen->first);
+            ++itScreen;
+        }
+
+        if (u64VideoCaptureScreens)
+            pelmVideoCapture->setAttribute("screens",      u64VideoCaptureScreens);
+
+        /* At the moment we only support one capturing configuration, that is, all screens
+         * have the same configuration. So load/save to/from screen 0. */
+        Assert(hw.captureSettings.mapScreens.size());
+        const CaptureScreenMap::const_iterator itScreen0Settings = hw.captureSettings.mapScreens.find(0);
+
+        if (itScreen0Settings->second.ulMaxTimeS)
+            pelmVideoCapture->setAttribute("maxTime",      itScreen0Settings->second.ulMaxTimeS);
+        if (itScreen0Settings->second.strOptions.isNotEmpty())
+            pelmVideoCapture->setAttributePath("options",  itScreen0Settings->second.strOptions);
+
+        if (!itScreen0Settings->second.File.strName.isEmpty())
+            pelmVideoCapture->setAttributePath("file",     itScreen0Settings->second.File.strName);
+        if (itScreen0Settings->second.File.ulMaxSizeMB)
+            pelmVideoCapture->setAttribute("maxSize",      itScreen0Settings->second.File.ulMaxSizeMB);
+
+        if (   itScreen0Settings->second.Video.ulWidth  != 1024
+            || itScreen0Settings->second.Video.ulHeight != 768)
+        {
+            pelmVideoCapture->setAttribute("horzRes",      itScreen0Settings->second.Video.ulWidth);
+            pelmVideoCapture->setAttribute("vertRes",      itScreen0Settings->second.Video.ulHeight);
+        }
+        if (itScreen0Settings->second.Video.ulRate != 512)
+            pelmVideoCapture->setAttribute("rate",         itScreen0Settings->second.Video.ulRate);
+        if (itScreen0Settings->second.Video.ulFPS)
+            pelmVideoCapture->setAttribute("fps",          itScreen0Settings->second.Video.ulFPS);
     }
 
@@ -7262,10 +7430,10 @@
     {
         // VirtualBox 4.3 adds default frontend setting, graphics controller
-        // setting, explicit long mode setting, video capturing and NAT networking.
+        // setting, explicit long mode setting, (video) capturing and NAT networking.
         if (   !hardwareMachine.strDefaultFrontend.isEmpty()
             || hardwareMachine.graphicsControllerType != GraphicsControllerType_VBoxVGA
             || hardwareMachine.enmLongMode != Hardware::LongMode_Legacy
             || machineUserData.ovIcon.size() > 0
-            || hardwareMachine.fVideoCaptureEnabled)
+            || hardwareMachine.captureSettings.fEnabled)
         {
             m->sv = SettingsVersion_v1_14;
