VirtualBox

Ignore:
Timestamp:
Oct 24, 2018 1:54:50 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
126083
Message:

VideoRec/Main: Factored out the stream processing code into an own function VideoRecStreamProcess() and made it more resilient against errors.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/VideoRecStream.cpp

    r74999 r75040  
    3838#include "VideoRec.h"
    3939#include "VideoRecStream.h"
     40#include "VideoRecUtils.h"
    4041#include "WebMWriter.h"
    4142
     
    193194
    194195    LogFlowFuncLeaveRC(rc);
     196    return rc;
     197}
     198
     199/**
     200 * Processes a recording stream.
     201 * This function takes care of the actual encoding and writing of a certain stream.
     202 * As this can be very CPU intensive, this function usually is called from a separate thread.
     203 *
     204 * @returns IPRT status code.
     205 * @param   pStream             Recording stream to process.
     206 */
     207int VideoRecStreamProcess(PVIDEORECSTREAM pStream)
     208{
     209    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     210
     211    videoRecStreamLock(pStream);
     212
     213    if (!pStream->fEnabled)
     214    {
     215        videoRecStreamUnlock(pStream);
     216        return VINF_SUCCESS;
     217    }
     218
     219    int rc = VINF_SUCCESS;
     220
     221    const PVIDEORECCONTEXT pCtx = pStream->pCtx;
     222    AssertPtr(pCtx);
     223
     224    VideoRecBlockMap::iterator itStreamBlocks = pStream->Blocks.Map.begin();
     225    while (itStreamBlocks != pStream->Blocks.Map.end())
     226    {
     227        const uint64_t        uTimeStampMs = itStreamBlocks->first;
     228              VideoRecBlocks *pBlocks      = itStreamBlocks->second;
     229
     230        AssertPtr(pBlocks);
     231
     232        while (!pBlocks->List.empty())
     233        {
     234            PVIDEORECBLOCK pBlock = pBlocks->List.front();
     235            AssertPtr(pBlock);
     236
     237#ifdef VBOX_WITH_LIBVPX
     238            if (pBlock->enmType == VIDEORECBLOCKTYPE_VIDEO)
     239            {
     240                PVIDEORECVIDEOFRAME pVideoFrame  = (PVIDEORECVIDEOFRAME)pBlock->pvData;
     241
     242                rc = videoRecRGBToYUV(pVideoFrame->uPixelFormat,
     243                                      /* Destination */
     244                                      pStream->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight,
     245                                      /* Source */
     246                                      pVideoFrame->pu8RGBBuf, pStream->Video.uWidth, pStream->Video.uHeight);
     247                if (RT_SUCCESS(rc))
     248                {
     249                    rc = videoRecStreamWriteVideoVPX(pStream, uTimeStampMs, pVideoFrame);
     250                }
     251                else
     252                    break;
     253            }
     254#endif
     255            VideoRecBlockFree(pBlock);
     256            pBlock = NULL;
     257
     258            pBlocks->List.pop_front();
     259        }
     260
     261        ++itStreamBlocks;
     262    }
     263
     264#ifdef VBOX_WITH_AUDIO_VIDEOREC
     265    /* As each (enabled) screen has to get the same audio data, look for common (audio) data which needs to be
     266     * written to the screen's assigned recording stream. */
     267    VideoRecBlockMap::iterator itCommonBlocks = pCtx->mapBlocksCommon.begin();
     268    while (itCommonBlocks != pCtx->mapBlocksCommon.end())
     269    {
     270        VideoRecBlockList::iterator itBlock = itCommonBlocks->second->List.begin();
     271        while (itBlock != itCommonBlocks->second->List.end())
     272        {
     273            PVIDEORECBLOCK pBlockCommon = (PVIDEORECBLOCK)(*itBlock);
     274            switch (pBlockCommon->enmType)
     275            {
     276                case VIDEORECBLOCKTYPE_AUDIO:
     277                {
     278                    PVIDEORECAUDIOFRAME pAudioFrame = (PVIDEORECAUDIOFRAME)pBlockCommon->pvData;
     279                    AssertPtr(pAudioFrame);
     280                    AssertPtr(pAudioFrame->pvBuf);
     281                    Assert(pAudioFrame->cbBuf);
     282
     283                    WebMWriter::BlockData_Opus blockData = { pAudioFrame->pvBuf, pAudioFrame->cbBuf,
     284                                                             pBlockCommon->uTimeStampMs };
     285                    AssertPtr(pStream->File.pWEBM);
     286                    rc = pStream->File.pWEBM->WriteBlock(pStream->uTrackAudio, &blockData, sizeof(blockData));
     287                    break;
     288                }
     289
     290                default:
     291                    AssertFailed();
     292                    break;
     293            }
     294
     295            if (RT_FAILURE(rc))
     296                break;
     297
     298            Assert(pBlockCommon->cRefs);
     299            pBlockCommon->cRefs--;
     300            if (pBlockCommon->cRefs == 0)
     301            {
     302                VideoRecBlockFree(pBlockCommon);
     303                itCommonBlocks->second->List.erase(itBlock);
     304                itBlock = itCommonBlocks->second->List.begin();
     305            }
     306            else
     307                ++itBlock;
     308        }
     309
     310        /* If no entries are left over in the block map, remove it altogether. */
     311        if (itCommonBlocks->second->List.empty())
     312        {
     313            delete itCommonBlocks->second;
     314            pCtx->mapBlocksCommon.erase(itCommonBlocks);
     315            itCommonBlocks = pCtx->mapBlocksCommon.begin();
     316        }
     317        else
     318            ++itCommonBlocks;
     319
     320        LogFunc(("Common blocks: %zu\n", pCtx->mapBlocksCommon.size()));
     321
     322        if (RT_FAILURE(rc))
     323            break;
     324    }
     325#endif
     326
     327    videoRecStreamUnlock(pStream);
     328
    195329    return rc;
    196330}
Note: See TracChangeset for help on using the changeset viewer.

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