VirtualBox

Changeset 75441 in vbox


Ignore:
Timestamp:
Nov 14, 2018 9:08:51 AM (6 years ago)
Author:
vboxsync
Message:

Recording/Main: Various fixes to make the code more error resilient.

Location:
trunk/src/VBox/Main
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/Recording.h

    r75361 r75441  
    118118     *  Per VM screen (display) one recording stream is being used. */
    119119    RecordingStreams          vecStreams;
     120    /** Number of streams in vecStreams which currently are enabled for recording. */
     121    uint16_t                  cStreamsEnabled;
    120122    /** Timestamp (in ms) of when recording has been started. */
    121123    uint64_t                  tsStartMs;
  • trunk/src/VBox/Main/include/RecordingInternals.h

    r75354 r75441  
    1919#define ____H_RECORDING_INTERNALS
    2020
     21#include <iprt/assert.h>
    2122#include <iprt/types.h> /* drag in stdint.h before vpx does it. */
    2223#include <list>
     
    115116} RECORDINGBLOCKTYPE;
    116117
     118#ifdef VBOX_WITH_AUDIO_RECORDING
     119void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame);
     120#endif
     121void RecordingVideoFrameFree(PRECORDINGVIDEOFRAME pFrame);
     122
    117123/**
    118124 * Generic structure for keeping a single video recording (data) block.
    119125 */
    120 typedef struct RECORDINGBLOCK
     126struct RecordingBlock
    121127{
     128    RecordingBlock()
     129        : enmType(RECORDINGBLOCKTYPE_UNKNOWN)
     130        , cRefs(0)
     131        , pvData(NULL)
     132        , cbData(0) { }
     133
     134    virtual ~RecordingBlock()
     135    {
     136        Reset();
     137    }
     138
     139    void Reset(void)
     140    {
     141        switch (enmType)
     142        {
     143            case RECORDINGBLOCKTYPE_UNKNOWN:
     144                break;
     145
     146            case RECORDINGBLOCKTYPE_VIDEO:
     147                RecordingVideoFrameFree((PRECORDINGVIDEOFRAME)pvData);
     148                break;
     149
     150#ifdef VBOX_WITH_AUDIO_RECORDING
     151            case RECORDINGBLOCKTYPE_AUDIO:
     152                RecordingAudioFrameFree((PRECORDINGAUDIOFRAME)pvData);
     153                break;
     154#endif
     155            default:
     156                AssertFailed();
     157                break;
     158        }
     159
     160        enmType = RECORDINGBLOCKTYPE_UNKNOWN;
     161        cRefs   = 0;
     162        pvData  = NULL;
     163        cbData  = 0;
     164    }
     165
    122166    /** The block's type. */
    123167    RECORDINGBLOCKTYPE enmType;
     
    130174    /** Size (in bytes) of the (opaque) data block. */
    131175    size_t             cbData;
    132 } RECORDINGBLOCK, *PRECORDINGBLOCK;
     176};
    133177
    134178/** List for keeping video recording (data) blocks. */
    135 typedef std::list<PRECORDINGBLOCK> RECORDINGBLOCKList;
    136 
    137 void RecordingBlockFree(PRECORDINGBLOCK pBlock);
    138 #ifdef VBOX_WITH_AUDIO_RECORDING
    139 void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame);
    140 #endif
    141 void RecordingVideoFrameFree(PRECORDINGVIDEOFRAME pFrame);
     179typedef std::list<RecordingBlock *> RecordingBlockList;
    142180
    143181#endif /* ____H_RECORDING_INTERNALS */
  • trunk/src/VBox/Main/include/RecordingStream.h

    r75417 r75441  
    5151        while (!List.empty())
    5252        {
    53             PRECORDINGBLOCK pBlock = List.front();
    54             RecordingBlockFree(pBlock);
     53            RecordingBlock *pBlock = List.front();
    5554            List.pop_front();
     55            delete pBlock;
    5656        }
    5757
     
    6060
    6161    /** The actual block list for this timecode. */
    62     RECORDINGBLOCKList List;
     62    RecordingBlockList List;
    6363};
    6464
     
    125125
    126126    const settings::RecordingScreenSettings &GetConfig(void) const;
     127    uint16_t GetID(void) const { return this->uScreenID; };
    127128    bool IsLimitReached(uint64_t tsNowMs) const;
    128129    bool IsReady(void) const;
     
    167168
    168169    /** Recording context this stream is associated to. */
    169     RecordingContext         *pCtx;
     170    RecordingContext       *pCtx;
    170171    /** The current state. */
    171172    RECORDINGSTREAMSTATE    enmState;
     
    206207    /** Common set of recording (data) blocks, needed for
    207208     *  multiplexing to all recording streams. */
    208     RecordingBlockSet              Blocks;
     209    RecordingBlockSet                 Blocks;
    209210};
    210211
  • trunk/src/VBox/Main/src-client/Recording.cpp

    r75392 r75441  
    9292RecordingContext::RecordingContext(Console *a_pConsole)
    9393    : pConsole(a_pConsole)
    94     , enmState(RECORDINGSTS_UNINITIALIZED) { }
     94    , enmState(RECORDINGSTS_UNINITIALIZED)
     95    , cStreamsEnabled(0) { }
    9596
    9697RecordingContext::RecordingContext(Console *a_pConsole, const settings::RecordingSettings &a_Settings)
    9798    : pConsole(a_pConsole)
    9899    , enmState(RECORDINGSTS_UNINITIALIZED)
     100    , cStreamsEnabled(0)
    99101{
    100102    int rc = RecordingContext::createInternal(a_Settings);
     
    139141            rc = pStream->Process(pThis->mapBlocksCommon);
    140142            if (RT_FAILURE(rc))
     143            {
     144                LogRel(("Recording: Processing stream #%RU16 failed (%Rrc)\n", pStream->GetID(), rc));
    141145                break;
     146            }
    142147
    143148            ++itStream;
     
    191196            pStream = new RecordingStream(this, itScreen->first /* Screen ID */, itScreen->second);
    192197            this->vecStreams.push_back(pStream);
     198            if (itScreen->second.fEnabled)
     199                this->cStreamsEnabled++;
    193200        }
    194201        catch (std::bad_alloc &)
     
    533540     * audio data at the same given point in time.
    534541     */
    535     PRECORDINGBLOCK pBlock = (PRECORDINGBLOCK)RTMemAlloc(sizeof(RECORDINGBLOCK));
    536     AssertPtrReturn(pBlock, VERR_NO_MEMORY);
     542    RecordingBlock *pBlock = new RecordingBlock();
    537543    pBlock->enmType = RECORDINGBLOCKTYPE_AUDIO;
    538544
     
    548554    pBlock->pvData       = pFrame;
    549555    pBlock->cbData       = sizeof(RECORDINGAUDIOFRAME) + cbData;
    550     pBlock->cRefs        = (uint16_t)this->vecStreams.size(); /* All streams need the same audio data. */
     556    pBlock->cRefs        = this->cStreamsEnabled;
    551557    pBlock->uTimeStampMs = uTimeStampMs;
    552558
  • trunk/src/VBox/Main/src-client/RecordingInternals.cpp

    r75356 r75441  
    6161}
    6262
    63 /**
    64  * Frees a recording (data) block.
    65  *
    66  * @returns IPRT status code.
    67  * @param   pBlock              Recording (data) block to free. The pointer will be invalid after return.
    68  */
    69 void RecordingBlockFree(PRECORDINGBLOCK pBlock)
    70 {
    71     if (!pBlock)
    72         return;
    73 
    74     switch (pBlock->enmType)
    75     {
    76         case RECORDINGBLOCKTYPE_VIDEO:
    77             RecordingVideoFrameFree((PRECORDINGVIDEOFRAME)pBlock->pvData);
    78             break;
    79 
    80 #ifdef VBOX_WITH_AUDIO_RECORDING
    81         case RECORDINGBLOCKTYPE_AUDIO:
    82             RecordingAudioFrameFree((PRECORDINGAUDIOFRAME)pBlock->pvData);
    83             break;
    84 #endif
    85         default:
    86             AssertFailed();
    87             break;
    88     }
    89 
    90     RTMemFree(pBlock);
    91     pBlock = NULL;
    92 }
    93 
  • trunk/src/VBox/Main/src-client/RecordingStream.cpp

    r75417 r75441  
    276276        && tsNowMs >= this->tsStartMs + (this->ScreenSettings.ulMaxTimeS * RT_MS_1SEC))
    277277    {
     278        LogRel(("Recording: Time limit for stream #%RU16 has been reached (%RU32s)\n",
     279                this->uScreenID, this->ScreenSettings.ulMaxTimeS));
    278280        return true;
    279281    }
     
    281283    if (this->ScreenSettings.enmDest == RecordingDestination_File)
    282284    {
    283 
    284285        if (this->ScreenSettings.File.ulMaxSizeMB)
    285286        {
    286287            uint64_t sizeInMB = this->File.pWEBM->GetFileSize() / _1M;
    287288            if(sizeInMB >= this->ScreenSettings.File.ulMaxSizeMB)
     289            {
     290                LogRel(("Recording: File size limit for stream #%RU16 has been reached (%RU64MB)\n",
     291                        this->uScreenID, this->ScreenSettings.File.ulMaxSizeMB));
    288292                return true;
     293            }
    289294        }
    290295
     
    293298            && this->File.pWEBM->GetAvailableSpace() < 0x100000) /** @todo r=andy WTF? Fix this. */
    294299        {
    295             LogRel(("Recording: Not enough free storage space available, stopping video capture\n"));
     300            LogRel(("Recording: Not enough free storage space available, stopping recording\n"));
    296301            return true;
    297302        }
     
    321326int RecordingStream::Process(RecordingBlockMap &mapBlocksCommon)
    322327{
     328    LogFlowFuncEnter();
     329
    323330    lock();
    324331
     
    341348        while (!pBlocks->List.empty())
    342349        {
    343             PRECORDINGBLOCK pBlock = pBlocks->List.front();
     350            RecordingBlock *pBlock = pBlocks->List.front();
    344351            AssertPtr(pBlock);
    345352
     
    349356                PRECORDINGVIDEOFRAME pVideoFrame  = (PRECORDINGVIDEOFRAME)pBlock->pvData;
    350357
    351                 rc = RecordingUtilsRGBToYUV(pVideoFrame->uPixelFormat,
    352                                             /* Destination */
    353                                             this->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight,
    354                                             /* Source */
    355                                             pVideoFrame->pu8RGBBuf, this->ScreenSettings.Video.ulWidth, this->ScreenSettings.Video.ulHeight);
    356                 if (RT_SUCCESS(rc))
     358                int rc2 = RecordingUtilsRGBToYUV(pVideoFrame->uPixelFormat,
     359                                                 /* Destination */
     360                                                 this->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight,
     361                                                 /* Source */
     362                                                 pVideoFrame->pu8RGBBuf, this->ScreenSettings.Video.ulWidth, this->ScreenSettings.Video.ulHeight);
     363                if (RT_SUCCESS(rc2))
    357364                {
    358                     rc = writeVideoVPX(uTimeStampMs, pVideoFrame);
     365                    rc2 = writeVideoVPX(uTimeStampMs, pVideoFrame);
     366                    AssertRC(rc2);
     367                    if (RT_SUCCESS(rc))
     368                        rc = rc2;
    359369                }
    360                 else
    361                     break;
    362             }
    363 #endif
    364             RecordingBlockFree(pBlock);
    365             pBlock = NULL;
    366 
     370            }
     371#endif
    367372            pBlocks->List.pop_front();
    368         }
    369 
    370         ++itStreamBlocks;
     373            delete pBlock;
     374        }
     375
     376        Blocks.Map.erase(itStreamBlocks);
     377        itStreamBlocks = Blocks.Map.begin();
    371378    }
    372379
     
    379386    while (itCommonBlocks != mapBlocksCommon.end())
    380387    {
    381         RECORDINGBLOCKList::iterator itBlock = itCommonBlocks->second->List.begin();
     388        RecordingBlockList::iterator itBlock = itCommonBlocks->second->List.begin();
    382389        while (itBlock != itCommonBlocks->second->List.end())
    383390        {
    384             PRECORDINGBLOCK pBlockCommon = (PRECORDINGBLOCK)(*itBlock);
     391            RecordingBlock *pBlockCommon = (RecordingBlock *)(*itBlock);
    385392            switch (pBlockCommon->enmType)
    386393            {
     
    395402                                                             pBlockCommon->uTimeStampMs };
    396403                    AssertPtr(this->File.pWEBM);
    397                     rc = this->File.pWEBM->WriteBlock(this->uTrackAudio, &blockData, sizeof(blockData));
     404                    int rc2 = this->File.pWEBM->WriteBlock(this->uTrackAudio, &blockData, sizeof(blockData));
     405                    AssertRC(rc2);
     406                    if (RT_SUCCESS(rc))
     407                        rc = rc2;
    398408                    break;
    399409                }
     
    404414            }
    405415
    406             if (RT_FAILURE(rc))
    407                 break;
    408 
    409416            Assert(pBlockCommon->cRefs);
    410417            pBlockCommon->cRefs--;
    411418            if (pBlockCommon->cRefs == 0)
    412419            {
    413                 RecordingBlockFree(pBlockCommon);
    414420                itCommonBlocks->second->List.erase(itBlock);
     421                delete pBlockCommon;
    415422                itBlock = itCommonBlocks->second->List.begin();
    416423            }
     
    430437
    431438        LogFunc(("Common blocks: %zu\n", mapBlocksCommon.size()));
    432 
    433         if (RT_FAILURE(rc))
    434             break;
    435439    }
    436440#endif
     
    438442    unlock();
    439443
     444    LogFlowFuncLeaveRC(rc);
    440445    return rc;
    441446}
     
    637642    if (rc == VINF_SUCCESS) /* Note: Also could be VINF_TRY_AGAIN. */
    638643    {
    639         PRECORDINGBLOCK pBlock = (PRECORDINGBLOCK)RTMemAlloc(sizeof(RECORDINGBLOCK));
     644        RecordingBlock *pBlock = new RecordingBlock();
    640645        if (pBlock)
    641646        {
     
    680685 * @param   a_pCtx              Pointer to recording context.
    681686 * @param   uScreen             Screen number to use for this recording stream.
    682  * @param   Settings            Capturing configuration to use for initialization.
     687 * @param   Settings            Recording screen configuration to use for initialization.
    683688 */
    684689int RecordingStream::Init(RecordingContext *a_pCtx, uint32_t uScreen, const settings::RecordingScreenSettings &Settings)
     
    693698 * @param   a_pCtx              Pointer to recording context.
    694699 * @param   uScreen             Screen number to use for this recording stream.
    695  * @param   Settings            Capturing configuration to use for initialization.
     700 * @param   Settings            Recording screen configuration to use for initialization.
    696701 */
    697702int RecordingStream::initInternal(RecordingContext *a_pCtx, uint32_t uScreen, const settings::RecordingScreenSettings &Settings)
     
    701706    this->ScreenSettings = Settings;
    702707
    703     int rc = parseOptionsString(Settings.strOptions);
     708    int rc = parseOptionsString(this->ScreenSettings.strOptions);
    704709    if (RT_FAILURE(rc))
    705710        return rc;
     711
     712    const settings::RecordingScreenSettings *pSettings = &this->ScreenSettings;
    706713
    707714    rc = RTCritSectInit(&this->CritSect);
     
    709716        return rc;
    710717
    711     rc = open(Settings);
     718    rc = open(this->ScreenSettings);
    712719    if (RT_FAILURE(rc))
    713720        return rc;
    714721
    715     const bool fVideoEnabled = Settings.isFeatureEnabled(RecordingFeature_Video);
    716     const bool fAudioEnabled = Settings.isFeatureEnabled(RecordingFeature_Audio);
     722    const bool fVideoEnabled = pSettings->isFeatureEnabled(RecordingFeature_Video);
     723    const bool fAudioEnabled = pSettings->isFeatureEnabled(RecordingFeature_Audio);
    717724
    718725    if (fVideoEnabled)
     
    734741        case RecordingDestination_File:
    735742        {
    736             Assert(this->ScreenSettings.File.strName.isNotEmpty());
    737             const char *pszFile = this->ScreenSettings.File.strName.c_str();
     743            Assert(pSettings->File.strName.isNotEmpty());
     744            const char *pszFile = pSettings->File.strName.c_str();
    738745
    739746            AssertPtr(File.pWEBM);
    740747            rc = File.pWEBM->OpenEx(pszFile, &this->File.hFile,
    741748#ifdef VBOX_WITH_AUDIO_RECORDING
    742                                       Settings.isFeatureEnabled(RecordingFeature_Audio)
    743                                     ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None,
     749                                   fAudioEnabled ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None,
    744750#else
    745                                       WebMWriter::AudioCodec_None,
    746 #endif
    747                                       Settings.isFeatureEnabled(RecordingFeature_Video)
    748                                     ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None);
     751                                   WebMWriter::AudioCodec_None,
     752#endif
     753                                   fVideoEnabled ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None);
    749754            if (RT_FAILURE(rc))
    750755            {
     
    755760            if (fVideoEnabled)
    756761            {
    757                 rc = this->File.pWEBM->AddVideoTrack(Settings.Video.ulWidth, Settings.Video.ulHeight,
    758                                                      Settings.Video.ulFPS, &this->uTrackVideo);
     762                rc = this->File.pWEBM->AddVideoTrack(pSettings->Video.ulWidth, pSettings->Video.ulHeight, pSettings->Video.ulFPS,
     763                                                     &this->uTrackVideo);
    759764                if (RT_FAILURE(rc))
    760765                {
     
    764769
    765770                LogRel(("Recording: Recording video of screen #%u with %RU32x%RU32 @ %RU32 kbps, %RU32 FPS (track #%RU8)\n",
    766                         this->uScreenID, Settings.Video.ulWidth, Settings.Video.ulHeight, Settings.Video.ulRate,
    767                         Settings.Video.ulFPS, this->uTrackVideo));
     771                        this->uScreenID, pSettings->Video.ulWidth, pSettings->Video.ulHeight,
     772                        pSettings->Video.ulRate, pSettings->Video.ulFPS, this->uTrackVideo));
    768773            }
    769774
     
    771776            if (fAudioEnabled)
    772777            {
    773                 rc = this->File.pWEBM->AddAudioTrack(Settings.Audio.uHz, Settings.Audio.cChannels, Settings.Audio.cBits,
     778                rc = this->File.pWEBM->AddAudioTrack(pSettings->Audio.uHz, pSettings->Audio.cChannels, pSettings->Audio.cBits,
    774779                                                     &this->uTrackAudio);
    775780                if (RT_FAILURE(rc))
     
    780785
    781786                LogRel(("Recording: Recording audio of screen #%u in %RU16Hz, %RU8 bit, %RU8 %s (track #%RU8)\n",
    782                         this->uScreenID, Settings.Audio.uHz, Settings.Audio.cBits, Settings.Audio.cChannels,
    783                         Settings.Audio.cChannels ? "channels" : "channel", this->uTrackAudio));
     787                        this->uScreenID, pSettings->Audio.uHz, pSettings->Audio.cBits, pSettings->Audio.cChannels,
     788                        pSettings->Audio.cChannels ? "channels" : "channel", this->uTrackAudio));
    784789            }
    785790#endif
     
    990995
    991996    this->Video.cFailedEncodingFrames = 0;
    992     this->Video.uDelayMs = RT_MS_1SEC / this->ScreenSettings.Video.ulFPS;
     997    this->Video.uLastTimeStampMs      = 0;
     998    this->Video.uDelayMs              = RT_MS_1SEC / this->ScreenSettings.Video.ulFPS;
    993999
    9941000    int rc;
     
    9981004    rc = initVideoVPX();
    9991005#else
    1000     rc = VINF_SUCCESS;
     1006    rc = VERR_NOT_SUPPORTED;
    10011007#endif
    10021008
  • trunk/src/VBox/Main/src-server/RecordingScreenSettingsImpl.cpp

    r75418 r75441  
    810810    Assert(m);
    811811
    812     int rc = VINF_SUCCESS;
     812    int rc = i_parseOptionsString(m->bd->strOptions, *m->bd.data());
     813    if (RT_FAILURE(rc))
     814        return rc;
    813815
    814816    switch (m->bd->enmDest)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette