Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 75487)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 75488)
@@ -20685,5 +20685,5 @@
   <interface
     name="IInternalSessionControl" extends="$unknown"
-    uuid="DE773CFC-B679-4225-8EAE-938D294B73D2"
+    uuid="B1C3994E-F8CD-4D02-94D0-1AAF884751ED"
     internal="yes"
     wsmap="suppress"
@@ -20989,4 +20989,7 @@
         Triggered when recording settings have changed.
       </desc>
+      <param name="enable" type="boolean" dir="in">
+        <desc>TODO</desc>
+      </param>
     </method>
 
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 75487)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 75488)
@@ -146,6 +146,6 @@
     int i_recordingEnable(BOOL fEnable, util::AutoWriteLock *pAutoLock);
     int i_recordingGetSettings(settings::RecordingSettings &Settings);
-    int i_recordingStart(void);
-    int i_recordingStop(void);
+    int i_recordingStart(util::AutoWriteLock *pAutoLock = NULL);
+    int i_recordingStop(util::AutoWriteLock *pAutoLock = NULL);
     AudioVideoRec *i_recordingGetAudioDrv(void) const { return Recording.mAudioRec; }
     RecordingContext *i_recordingGetContext(void) const { return Recording.mpCtx; }
@@ -179,5 +179,5 @@
     HRESULT i_onDnDModeChange(DnDMode_T aDnDMode);
     HRESULT i_onVRDEServerChange(BOOL aRestart);
-    HRESULT i_onRecordingChange();
+    HRESULT i_onRecordingChange(BOOL fEnable);
     HRESULT i_onUSBControllerChange();
     HRESULT i_onSharedFolderChange(BOOL aGlobal);
@@ -1042,5 +1042,5 @@
 
         /** The recording context. */
-        RecordingContext       *mpCtx;
+        RecordingContext     *mpCtx;
 # ifdef VBOX_WITH_AUDIO_RECORDING
         /** Pointer to capturing audio backend. */
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 75487)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 75488)
@@ -524,5 +524,5 @@
     virtual HRESULT i_onStorageDeviceChange(IMediumAttachment * /* mediumAttachment */, BOOL /* remove */,
                                             BOOL /* silent */) { return S_OK; }
-    virtual HRESULT i_onRecordingChange() { return S_OK; }
+    virtual HRESULT i_onRecordingChange(BOOL /* aEnable */) { return S_OK; }
 
     HRESULT i_saveRegistryEntry(settings::MachineRegistryEntry &data);
@@ -1327,5 +1327,5 @@
     HRESULT i_onCPUChange(ULONG aCPU, BOOL aRemove);
     HRESULT i_onVRDEServerChange(BOOL aRestart);
-    HRESULT i_onRecordingChange();
+    HRESULT i_onRecordingChange(BOOL aEnable);
     HRESULT i_onUSBControllerChange();
     HRESULT i_onUSBDeviceAttach(IUSBDevice *aDevice,
Index: /trunk/src/VBox/Main/include/Recording.h
===================================================================
--- /trunk/src/VBox/Main/include/Recording.h	(revision 75487)
+++ /trunk/src/VBox/Main/include/Recording.h	(revision 75488)
@@ -39,6 +39,4 @@
 public:
 
-    RecordingContext(Console *pConsole);
-
     RecordingContext(Console *pConsole, const settings::RecordingSettings &a_Settings);
 
@@ -64,9 +62,12 @@
 public:
 
-    bool IsFeatureEnabled(RecordingFeature_T enmFeature) const;
+    bool IsFeatureEnabled(RecordingFeature_T enmFeature);
     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;
+    bool IsReady(uint32_t uScreen, uint64_t uTimeStampMs);
+    bool IsStarted(void);
+    bool IsLimitReached(void);
+    bool IsLimitReached(uint32_t uScreen, uint64_t uTimeStampMs);
+
+    DECLCALLBACK(int) OnLimitReached(uint32_t uScreen, int rc);
 
 protected:
@@ -79,4 +80,7 @@
 
     RecordingStream *getStreamInternal(unsigned uScreen) const;
+
+    int lock(void);
+    int unlock(void);
 
     static DECLCALLBACK(int) threadMain(RTTHREAD hThreadSelf, void *pvUser);
@@ -102,24 +106,24 @@
 
     /** Pointer to the console object. */
-    Console                  *pConsole;
+    Console                     *pConsole;
     /** Used recording configuration. */
     settings::RecordingSettings  Settings;
     /** The current state. */
-    RECORDINGSTS              enmState;
+    RECORDINGSTS                 enmState;
     /** Critical section to serialize access. */
-    RTCRITSECT                CritSect;
+    RTCRITSECT                   CritSect;
     /** Semaphore to signal the encoding worker thread. */
-    RTSEMEVENT                WaitEvent;
+    RTSEMEVENT                   WaitEvent;
     /** 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. */
-    RecordingStreams          vecStreams;
+    RecordingStreams             vecStreams;
     /** Number of streams in vecStreams which currently are enabled for recording. */
-    uint16_t                  cStreamsEnabled;
+    uint16_t                     cStreamsEnabled;
     /** 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
@@ -129,5 +133,5 @@
      *  For now this only affects audio, e.g. all recording streams
      *  need to have the same audio data at a specific point in time. */
-    RecordingBlockMap         mapBlocksCommon;
+    RecordingBlockMap            mapBlocksCommon;
 };
 #endif /* !____H_RECORDING */
Index: /trunk/src/VBox/Main/include/RecordingInternals.h
===================================================================
--- /trunk/src/VBox/Main/include/RecordingInternals.h	(revision 75487)
+++ /trunk/src/VBox/Main/include/RecordingInternals.h	(revision 75488)
@@ -48,4 +48,7 @@
             /** Pointer to the codec's internal YUV buffer. */
             uint8_t            *pu8YuvBuf;
+            /** The encoder's deadline (in ms).
+             *  The more time the encoder is allowed to spend encoding, the better the encoded
+             *  result, in exchange for higher CPU usage and time spent encoding. */
             unsigned int        uEncoderDeadline;
         } VPX;
Index: /trunk/src/VBox/Main/include/RecordingStream.h
===================================================================
--- /trunk/src/VBox/Main/include/RecordingStream.h	(revision 75487)
+++ /trunk/src/VBox/Main/include/RecordingStream.h	(revision 75488)
@@ -126,5 +126,5 @@
     const settings::RecordingScreenSettings &GetConfig(void) const;
     uint16_t GetID(void) const { return this->uScreenID; };
-    bool IsLimitReached(uint64_t tsNowMs) const;
+    bool IsLimitReached(uint64_t uTimeStampMs) const;
     bool IsReady(void) const;
 
@@ -141,4 +141,7 @@
 
     int initAudio(void);
+
+    bool isLimitReachedInternal(uint64_t uTimeStampMs) const;
+    int iterateInternal(uint64_t uTimeStampMs);
 
 #ifdef VBOX_WITH_LIBVPX
Index: /trunk/src/VBox/Main/include/SessionImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/SessionImpl.h	(revision 75487)
+++ /trunk/src/VBox/Main/include/SessionImpl.h	(revision 75488)
@@ -102,5 +102,5 @@
     HRESULT onCPUExecutionCapChange(ULONG aExecutionCap);
     HRESULT onVRDEServerChange(BOOL aRestart);
-    HRESULT onRecordingChange();
+    HRESULT onRecordingChange(BOOL aEnable);
     HRESULT onUSBControllerChange();
     HRESULT onSharedFolderChange(BOOL aGlobal);
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 75487)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 75488)
@@ -5641,6 +5641,4 @@
             LogRel(("Recording: %s\n", fEnable ? "Enabling" : "Disabling"));
 
-            pDisplay->i_recordingInvalidate();
-
             if (fEnable)
             {
@@ -5661,13 +5659,19 @@
                         && Recording.mpCtx->IsReady()) /* Any video recording (audio and/or video) feature enabled? */
                     {
-                        vrc = i_recordingStart();
+                        vrc = pDisplay->i_recordingInvalidate();
+                        if (RT_SUCCESS(vrc))
+                            vrc = i_recordingStart(pAutoLock);
                     }
                 }
+
+                if (RT_FAILURE(vrc))
+                    LogRel(("Recording: Failed to enable with %Rrc\n", vrc));
             }
             else
             {
-                i_recordingStop();
+                i_recordingStop(pAutoLock);
 # ifdef VBOX_WITH_AUDIO_RECORDING
-                Recording.mAudioRec->doDetachDriverViaEmt(mpUVM, pAutoLock);
+                if (Recording.mAudioRec)
+                    Recording.mAudioRec->doDetachDriverViaEmt(mpUVM, pAutoLock);
 # endif
                 i_recordingDestroy();
@@ -5685,5 +5689,8 @@
 #endif /* VBOX_WITH_RECORDING */
 
-HRESULT Console::i_onRecordingChange()
+/**
+ * Called by IInternalSessionControl::OnRecordingChange().
+ */
+HRESULT Console::i_onRecordingChange(BOOL fEnabled)
 {
     AutoCaller autoCaller(this);
@@ -5698,11 +5705,5 @@
     if (ptrVM.isOk())
     {
-        ComPtr<IRecordingSettings> recordingSettings;
-        rc = mMachine->COMGETTER(RecordingSettings)(recordingSettings.asOutParam());
-        AssertComRCReturnRC(rc);
-
-        BOOL fEnabled;
-        rc = recordingSettings->COMGETTER(Enabled)(&fEnabled);
-        AssertComRCReturnRC(rc);
+        LogFlowThisFunc(("fEnabled=%RTbool\n", RT_BOOL(fEnabled)));
 
         int vrc = i_recordingEnable(fEnabled, &alock);
@@ -6974,25 +6975,20 @@
     AssertReturn(Recording.mpCtx == NULL, VERR_WRONG_ORDER);
 
-    int rc = VINF_SUCCESS;
-
-    try
-    {
-        Recording.mpCtx = new RecordingContext(this);
-    }
-    catch (std::bad_alloc &)
-    {
-        return VERR_NO_MEMORY;
-    }
-    catch (int &rc2)
-    {
-        return rc2;
-    }
-
-    settings::RecordingSettings Settings;
-    rc = i_recordingGetSettings(Settings);
+    settings::RecordingSettings recordingSettings;
+    int rc = i_recordingGetSettings(recordingSettings);
     if (RT_SUCCESS(rc))
     {
-        AssertPtr(Recording.mpCtx);
-        rc = Recording.mpCtx->Create(Settings);
+        try
+        {
+            Recording.mpCtx = new RecordingContext(this /* pConsole */, recordingSettings);
+        }
+        catch (std::bad_alloc &)
+        {
+            return VERR_NO_MEMORY;
+        }
+        catch (int &rc2)
+        {
+            return rc2;
+        }
     }
 
@@ -7020,6 +7016,7 @@
  * @returns IPRT status code.
  */
-int Console::i_recordingStart(void)
-{
+int Console::i_recordingStart(util::AutoWriteLock *pAutoLock /* = NULL */)
+{
+    RT_NOREF(pAutoLock);
     AssertPtrReturn(Recording.mpCtx, VERR_WRONG_ORDER);
 
@@ -7043,5 +7040,5 @@
  * Stops recording. Does nothing if recording is not active.
  */
-int Console::i_recordingStop(void)
+int Console::i_recordingStop(util::AutoWriteLock *pAutoLock /* = NULL */)
 {
     if (   !Recording.mpCtx
@@ -7058,9 +7055,15 @@
             mDisplay->i_recordingScreenChanged(uScreen);
 
+        if (pAutoLock)
+            pAutoLock->release();
+
         ComPtr<IRecordingSettings> pRecordSettings;
         HRESULT hrc = mMachine->COMGETTER(RecordingSettings)(pRecordSettings.asOutParam());
         ComAssertComRC(hrc);
-        hrc = pRecordSettings->COMSETTER(Enabled)(false);
+        hrc = pRecordSettings->COMSETTER(Enabled)(FALSE);
         ComAssertComRC(hrc);
+
+        if (pAutoLock)
+            pAutoLock->acquire();
     }
 
Index: /trunk/src/VBox/Main/src-client/DisplayImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 75487)
+++ /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 75488)
@@ -3432,4 +3432,12 @@
 # endif /* VBOX_WITH_HGCM && VBOX_WITH_CROGL */
 
+            /* If the recording context has reached the configured recording
+             * limit, disable recording. */
+            if (pCtx->IsLimitReached())
+            {
+                pDisplay->mParent->i_onRecordingChange(FALSE /* Disable */);
+                break;
+            }
+
             uint64_t tsNowMs = RTTimeProgramMilliTS();
             for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
@@ -3437,10 +3445,4 @@
                 if (!pDisplay->maRecordingEnabled[uScreenId])
                     continue;
-
-                if (pCtx->IsLimitReached(uScreenId, tsNowMs))
-                {
-                    pDisplay->mParent->i_recordingStop();
-                    break;
-                }
 
                 DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
Index: /trunk/src/VBox/Main/src-client/Recording.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/Recording.cpp	(revision 75487)
+++ /trunk/src/VBox/Main/src-client/Recording.cpp	(revision 75488)
@@ -90,9 +90,4 @@
 
 
-RecordingContext::RecordingContext(Console *a_pConsole)
-    : pConsole(a_pConsole)
-    , enmState(RECORDINGSTS_UNINITIALIZED)
-    , cStreamsEnabled(0) { }
-
 RecordingContext::RecordingContext(Console *a_pConsole, const settings::RecordingSettings &a_Settings)
     : pConsole(a_pConsole)
@@ -373,4 +368,18 @@
 }
 
+int RecordingContext::lock(void)
+{
+    int rc = RTCritSectEnter(&this->CritSect);
+    AssertRC(rc);
+    return rc;
+}
+
+int RecordingContext::unlock(void)
+{
+    int rc = RTCritSectLeave(&this->CritSect);
+    AssertRC(rc);
+    return rc;
+}
+
 /**
  * Retrieves a specific recording stream of a recording context.
@@ -440,13 +449,20 @@
  * @param   enmFeature          Recording feature to check for.
  */
-bool RecordingContext::IsFeatureEnabled(RecordingFeature_T enmFeature) const
-{
+bool RecordingContext::IsFeatureEnabled(RecordingFeature_T enmFeature)
+{
+    lock();
+
     RecordingStreams::const_iterator itStream = this->vecStreams.begin();
     while (itStream != this->vecStreams.end())
     {
         if ((*itStream)->GetConfig().isFeatureEnabled(enmFeature))
+        {
+            unlock();
             return true;
+        }
         ++itStream;
     }
+
+    unlock();
 
     return false;
@@ -470,20 +486,24 @@
  * @param   uTimeStampMs        Current time stamp (in ms). Currently not being used.
  */
-bool RecordingContext::IsReady(uint32_t uScreen, uint64_t uTimeStampMs) const
+bool RecordingContext::IsReady(uint32_t uScreen, uint64_t uTimeStampMs)
 {
     RT_NOREF(uTimeStampMs);
 
+    lock();
+
+    bool fIsReady = false;
+
     if (this->enmState != RECORDINGSTS_STARTED)
-        return false;
-
-    bool fIsReady = false;
-
-    const RecordingStream *pStream = GetStream(uScreen);
-    if (pStream)
-        fIsReady = pStream->IsReady();
-
-    /* Note: Do not check for other constraints like the video FPS rate here,
-     *       as this check then also would affect other (non-FPS related) stuff
-     *       like audio data. */
+    {
+        const RecordingStream *pStream = GetStream(uScreen);
+        if (pStream)
+            fIsReady = pStream->IsReady();
+
+        /* Note: Do not check for other constraints like the video FPS rate here,
+         *       as this check then also would affect other (non-FPS related) stuff
+         *       like audio data. */
+    }
+
+    unlock();
 
     return fIsReady;
@@ -495,7 +515,31 @@
  * @returns true if active, false if not.
  */
-bool RecordingContext::IsStarted(void) const
-{
-    return (this->enmState == RECORDINGSTS_STARTED);
+bool RecordingContext::IsStarted(void)
+{
+    lock();
+
+    const bool fIsStarted = this->enmState == RECORDINGSTS_STARTED;
+
+    unlock();
+
+    return fIsStarted;
+}
+
+/**
+ * Checks if a specified limit for recording has been reached.
+ *
+ * @returns true if any limit has been reached.
+ */
+bool RecordingContext::IsLimitReached(void)
+{
+    lock();
+
+    LogFlowThisFunc(("cStreamsEnabled=%RU16\n", this->cStreamsEnabled));
+
+    const bool fLimitReached = this->cStreamsEnabled == 0;
+
+    unlock();
+
+    return fLimitReached;
 }
 
@@ -505,16 +549,39 @@
  * @returns true if any limit has been reached.
  * @param   uScreen             Screen ID.
- * @param   tsNowMs             Current time stamp (in ms).
- */
-bool RecordingContext::IsLimitReached(uint32_t uScreen, uint64_t tsNowMs) const
-{
-    const RecordingStream *pStream = GetStream(uScreen);
+ * @param   uTimeStampMs        Timestamp (in ms) to check for.
+ */
+bool RecordingContext::IsLimitReached(uint32_t uScreen, uint64_t uTimeStampMs)
+{
+    lock();
+
+    bool fLimitReached = false;
+
+    const RecordingStream *pStream = getStreamInternal(uScreen);
     if (   !pStream
-        || pStream->IsLimitReached(tsNowMs))
-    {
-        return true;
-    }
-
-    return false;
+        || pStream->IsLimitReached(uTimeStampMs))
+    {
+        fLimitReached = true;
+    }
+
+    unlock();
+
+    return fLimitReached;
+}
+
+DECLCALLBACK(int) RecordingContext::OnLimitReached(uint32_t uScreen, int rc)
+{
+    RT_NOREF(uScreen);
+    LogFlowThisFunc(("Stream %RU32 has reached its limit (%Rrc)\n", uScreen, rc));
+
+    lock();
+
+    Assert(this->cStreamsEnabled);
+    this->cStreamsEnabled--;
+
+    LogFlowThisFunc(("cStreamsEnabled=%RU16\n", cStreamsEnabled));
+
+    unlock();
+
+    return VINF_SUCCESS;
 }
 
@@ -629,4 +696,5 @@
         AssertRC(rc);
 
+        AssertFailed();
         return VERR_NOT_FOUND;
     }
@@ -638,5 +706,5 @@
 
     if (   RT_SUCCESS(rc)
-        && rc != VINF_TRY_AGAIN) /* Only signal the thread if operation was successful. */
+        && rc != VINF_RECORDING_THROTTLED) /* Only signal the thread if operation was successful. */
     {
         threadNotify();
Index: /trunk/src/VBox/Main/src-client/RecordingStream.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/RecordingStream.cpp	(revision 75487)
+++ /trunk/src/VBox/Main/src-client/RecordingStream.cpp	(revision 75488)
@@ -263,16 +263,16 @@
 
 /**
- * Checks if a specified limit for a recording stream has been reached.
+ * Checks if a specified limit for a recording stream has been reached, internal version.
  *
  * @returns true if any limit has been reached.
- * @param   tsNowMs             Current time stamp (in ms).
- */
-bool RecordingStream::IsLimitReached(uint64_t tsNowMs) const
-{
-    if (!IsReady())
-        return true;
+ * @param   uTimeStampMs        Timestamp (in ms) to check for.
+ */
+bool RecordingStream::isLimitReachedInternal(uint64_t uTimeStampMs) const
+{
+    LogFlowThisFunc(("uTimeStampMs=%RU64, ulMaxTimeS=%RU32, tsStartMs=%RU64\n",
+                     uTimeStampMs, this->ScreenSettings.ulMaxTimeS, this->tsStartMs));
 
     if (   this->ScreenSettings.ulMaxTimeS
-        && tsNowMs >= this->tsStartMs + (this->ScreenSettings.ulMaxTimeS * RT_MS_1SEC))
+        && uTimeStampMs >= this->tsStartMs + (this->ScreenSettings.ulMaxTimeS * RT_MS_1SEC))
     {
         LogRel(("Recording: Time limit for stream #%RU16 has been reached (%RU32s)\n",
@@ -304,4 +304,60 @@
 
     return false;
+}
+
+/**
+ * Internal iteration main loop.
+ * Does housekeeping and recording context notification.
+ *
+ * @returns IPRT status code.
+ * @param   uTimeStampMs        Current timestamp (in ms).
+ */
+int RecordingStream::iterateInternal(uint64_t uTimeStampMs)
+{
+    if (!this->fEnabled)
+        return VINF_SUCCESS;
+
+    int rc;
+
+    if (isLimitReachedInternal(uTimeStampMs))
+    {
+        rc = VINF_RECORDING_LIMIT_REACHED;
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    AssertPtr(this->pCtx);
+
+    switch (rc)
+    {
+        case VINF_RECORDING_LIMIT_REACHED:
+        {
+            this->fEnabled = false;
+
+            int rc2 = this->pCtx->OnLimitReached(this->uScreenID, VINF_SUCCESS /* rc */);
+            AssertRC(rc2);
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+/**
+ * Checks if a specified limit for a recording stream has been reached.
+ *
+ * @returns true if any limit has been reached.
+ * @param   uTimeStampMs        Timestamp (in ms) to check for.
+ */
+bool RecordingStream::IsLimitReached(uint64_t uTimeStampMs) const
+{
+    if (!IsReady())
+        return true;
+
+    return isLimitReachedInternal(uTimeStampMs);
 }
 
@@ -449,5 +505,7 @@
  * Sends a raw (e.g. not yet encoded) video frame to the recording stream.
  *
- * @returns IPRT status code.
+ * @returns IPRT status code. Will return VINF_RECORDING_LIMIT_REACHED if the stream's recording
+ *          limit has been reached or VINF_RECORDING_THROTTLED if the frame is too early for the current
+ *          FPS setting.
  * @param   x                   Upper left (X) coordinate where the video frame starts.
  * @param   y                   Upper left (Y) coordinate where the video frame starts.
@@ -465,19 +523,20 @@
     lock();
 
+    LogFlowFunc(("uTimeStampMs=%RU64\n", uTimeStampMs));
+
     PRECORDINGVIDEOFRAME pFrame = NULL;
 
-    int rc = VINF_SUCCESS;
+    int rc = iterateInternal(uTimeStampMs);
+    if (rc != VINF_SUCCESS) /* Can return VINF_RECORDING_LIMIT_REACHED. */
+    {
+        unlock();
+        return rc;
+    }
 
     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. */
+            rc = VINF_RECORDING_THROTTLED; /* Respect maximum frames per second. */
             break;
         }
@@ -710,5 +769,5 @@
         return rc;
 
-    const settings::RecordingScreenSettings *pSettings = &this->ScreenSettings;
+    settings::RecordingScreenSettings *pSettings = &this->ScreenSettings;
 
     rc = RTCritSectInit(&this->CritSect);
@@ -823,5 +882,5 @@
         this->enmState  = RECORDINGSTREAMSTATE_INITIALIZED;
         this->fEnabled  = true;
-        this->tsStartMs = RTTimeMilliTS();
+        this->tsStartMs = RTTimeProgramMilliTS();
     }
     else
@@ -846,24 +905,21 @@
     int rc = VINF_SUCCESS;
 
-    if (this->fEnabled)
-    {
-        switch (this->ScreenSettings.enmDest)
-        {
-            case RecordingDestination_File:
-            {
-                if (this->File.pWEBM)
-                    rc = this->File.pWEBM->Close();
-                break;
-            }
-
-            default:
-                AssertFailed(); /* Should never happen. */
-                break;
-        }
-
-        this->Blocks.Clear();
-
-        LogRel(("Recording: Recording screen #%u stopped\n", this->uScreenID));
-    }
+    switch (this->ScreenSettings.enmDest)
+    {
+        case RecordingDestination_File:
+        {
+            if (this->File.pWEBM)
+                rc = this->File.pWEBM->Close();
+            break;
+        }
+
+        default:
+            AssertFailed(); /* Should never happen. */
+            break;
+    }
+
+    this->Blocks.Clear();
+
+    LogRel(("Recording: Recording screen #%u stopped\n", this->uScreenID));
 
     if (RT_FAILURE(rc))
Index: /trunk/src/VBox/Main/src-client/SessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 75487)
+++ /trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 75488)
@@ -725,15 +725,15 @@
 }
 
-HRESULT Session::onRecordingChange()
-{
-    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_onRecordingChange();
+HRESULT Session::onRecordingChange(BOOL aEnable)
+{
+    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_onRecordingChange(aEnable);
 #else
     return S_OK;
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 75487)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 75488)
@@ -14102,5 +14102,5 @@
  * @note Locks this object for reading.
  */
-HRESULT SessionMachine::i_onRecordingChange()
+HRESULT SessionMachine::i_onRecordingChange(BOOL aEnable)
 {
     LogFlowThisFunc(("\n"));
@@ -14120,5 +14120,5 @@
         return S_OK;
 
-    return directControl->OnRecordingChange();
+    return directControl->OnRecordingChange(aEnable);
 }
 
Index: /trunk/src/VBox/Main/src-server/RecordingSettingsImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/RecordingSettingsImpl.cpp	(revision 75487)
+++ /trunk/src/VBox/Main/src-server/RecordingSettingsImpl.cpp	(revision 75488)
@@ -46,5 +46,4 @@
     ComObjPtr<RecordingSettings> pPeer;
     RecordScreenSettingsMap      mapScreenObj;
-    bool                         fHasMachineLock;
 
     // use the XML settings structure in the members for simplicity
@@ -87,5 +86,4 @@
 
     m->bd.allocate();
-    m->fHasMachineLock = false;
 
     autoInitSpan.setSucceeded();
@@ -123,5 +121,4 @@
     m->bd.share(that->m->bd);
     m->mapScreenObj = that->m->mapScreenObj;
-    m->fHasMachineLock = false;
 
     autoInitSpan.setSucceeded();
@@ -156,5 +153,4 @@
     m->bd.attachCopy(that->m->bd);
     m->mapScreenObj = that->m->mapScreenObj;
-    m->fHasMachineLock = false;
 
     autoInitSpan.setSucceeded();
@@ -219,5 +215,5 @@
 
         alock.release();
-        rc = m->pMachine->i_onRecordingChange();
+        rc = m->pMachine->i_onRecordingChange(enable);
         if (FAILED(rc))
         {
@@ -236,13 +232,7 @@
             m->pMachine->i_setModified(Machine::IsModified_Recording);
 
-            /* We need to indicate here that we just took the machine lock, as Machine::i_saveSettings() will
-             * call i_commit(), which in turn also wants to lock the machine for writing. */
-            m->fHasMachineLock = true;
-
             /** Save settings if online - @todo why is this required? -- @bugref{6818} */
             if (Global::IsOnline(m->pMachine->i_getMachineState()))
                 rc = m->pMachine->i_saveSettings(NULL);
-
-            m->fHasMachineLock = false;
         }
     }
