VirtualBox

Changeset 65173 in vbox for trunk/src


Ignore:
Timestamp:
Jan 6, 2017 10:00:01 AM (8 years ago)
Author:
vboxsync
Message:

VideoRec: Revamped stream context allocation / structure handling by using a vector now.

Location:
trunk/src/VBox/Main/src-client
Files:
3 edited

Legend:

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

    r65120 r65173  
    22932293        return VINF_SUCCESS;
    22942294
    2295     int rc = VideoRecContextCreate(&mpVideoRecCtx, mcMonitors);
     2295    int rc = VideoRecContextCreate(mcMonitors, &mpVideoRecCtx);
    22962296    if (RT_FAILURE(rc))
    22972297    {
     
    23552355        if (RT_SUCCESS(rc))
    23562356        {
    2357             rc = VideoRecStrmInit(mpVideoRecCtx, uScreen,
    2358                                   pszName, ulWidth, ulHeight,
    2359                                   ulRate, ulFPS, ulMaxTime,
    2360                                   ulMaxSize, com::Utf8Str(strOptions).c_str());
     2357            rc = VideoRecStreamInit(mpVideoRecCtx, uScreen,
     2358                                    pszName, ulWidth, ulHeight,
     2359                                    ulRate, ulFPS, ulMaxTime,
     2360                                    ulMaxSize, com::Utf8Str(strOptions).c_str());
    23612361            if (rc == VERR_ALREADY_EXISTS)
    23622362            {
     
    23752375                                      pszSuff);
    23762376                if (RT_SUCCESS(rc))
    2377                     rc = VideoRecStrmInit(mpVideoRecCtx, uScreen,
    2378                                           pszName, ulWidth, ulHeight, ulRate,
    2379                                           ulFPS, ulMaxTime,
    2380                                           ulMaxSize, com::Utf8Str(strOptions).c_str());
     2377                    rc = VideoRecStreamInit(mpVideoRecCtx, uScreen,
     2378                                            pszName, ulWidth, ulHeight, ulRate,
     2379                                            ulFPS, ulMaxTime,
     2380                                            ulMaxSize, com::Utf8Str(strOptions).c_str());
    23812381            }
    23822382        }
     
    24092409    if (VideoRecIsEnabled(mpVideoRecCtx))
    24102410        LogRel(("Display::VideoCaptureStop: WebM/VP8 video recording stopped\n"));
    2411     VideoRecContextClose(mpVideoRecCtx);
     2411    VideoRecContextDestroy(mpVideoRecCtx);
    24122412    mpVideoRecCtx = NULL;
    24132413
     
    43944394    HRESULT hrc = pMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled);
    43954395    AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
     4396
     4397#ifdef DEBUG_andy
     4398    fEnabled = true;
     4399#endif
     4400
    43964401    if (fEnabled)
    43974402    {
  • trunk/src/VBox/Main/src-client/VideoRec.cpp

    r65088 r65173  
    55
    66/*
    7  * Copyright (C) 2012-2016 Oracle Corporation
     7 * Copyright (C) 2012-2017 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1717
    1818#define LOG_GROUP LOG_GROUP_MAIN
     19
     20#include <vector>
     21
    1922#include <VBox/log.h>
    2023#include <iprt/asm.h>
     
    3538#include <vpx/vpx_image.h>
    3639
    37 /** Default VPX codec to use */
     40/** Default VPX codec to use. */
    3841#define DEFAULTCODEC (vpx_codec_vp8_cx())
    3942
     
    4144static int videoRecRGBToYUV(PVIDEORECSTREAM pStrm);
    4245
    43 /* state to synchronized between threads */
     46/**
     47 * Enumeration for a video recording state.
     48 */
    4449enum
    4550{
     51    /** Not initialized. */
    4652    VIDREC_UNINITIALIZED = 0,
    47     /* initialized, idle */
     53    /** Initialized, idle. */
    4854    VIDREC_IDLE = 1,
    49     /* currently in VideoRecCopyToIntBuf(), delay termination */
     55    /** Currently in VideoRecCopyToIntBuf(), delay termination. */
    5056    VIDREC_COPYING = 2,
    51     /* signal that we are terminating */
     57    /** Signal that we are terminating. */
    5258    VIDREC_TERMINATING = 3
    5359};
     
    5662static uint32_t g_enmState = VIDREC_UNINITIALIZED;
    5763
    58 
     64/**
     65 * Strucutre for maintaining a video recording stream.
     66 */
    5967typedef struct VIDEORECSTREAM
    6068{
    61     /* container context */
    62     WebMWriter          Ebml;
    63     /* VPX codec context */
     69    /** Container context. */
     70    WebMWriter         *pEBML;
     71    /** VPX codec context. */
    6472    vpx_codec_ctx_t     VpxCodec;
    65     /* VPX configuration */
     73    /** VPX configuration. */
    6674    vpx_codec_enc_cfg_t VpxConfig;
    67     /* X resolution */
     75    /** Target X resolution (in pixels). */
    6876    uint32_t            uTargetWidth;
    69     /* Y resolution */
     77    /** Target Y resolution (in pixels). */
    7078    uint32_t            uTargetHeight;
    71     /* X resolution of the last encoded picture */
     79    /** X resolution of the last encoded frame. */
    7280    uint32_t            uLastSourceWidth;
    73     /* Y resolution of the last encoded picture */
     81    /** Y resolution of the last encoded frame. */
    7482    uint32_t            uLastSourceHeight;
    75     /* current frame number */
    76     uint32_t            cFrame;
    77     /* RGB buffer containing the most recent frame of the framebuffer */
    78     uint8_t             *pu8RgbBuf;
    79     /* YUV buffer the encode function fetches the frame from */
    80     uint8_t             *pu8YuvBuf;
    81     /* VPX image context */
     83    /** Current frame number. */
     84    uint64_t            cFrame;
     85    /** RGB buffer containing the most recent frame of the framebuffer. */
     86    uint8_t            *pu8RgbBuf;
     87    /** YUV buffer the encode function fetches the frame from. */
     88    uint8_t            *pu8YuvBuf;
     89    /** VPX image context. */
    8290    vpx_image_t         VpxRawImage;
    83     /* true if video recording is enabled */
     91    /** Whether video recording is enabled or not. */
    8492    bool                fEnabled;
    85     /* true if the RGB buffer is filled */
     93    /** Whether the RGB buffer is filled or not. */
    8694    bool                fRgbFilled;
    87     /* pixel format of the current frame */
     95    /** Pixel format of the current frame. */
    8896    uint32_t            u32PixelFormat;
    89     /* minimal delay between two frames */
     97    /** Minimal delay between two frames. */
    9098    uint32_t            uDelay;
    91     /* time stamp of the last frame we encoded */
     99    /** Time stamp of the last frame we encoded. */
    92100    uint64_t            u64LastTimeStamp;
    93     /* time stamp of the current frame */
     101    /** Time stamp of the current frame. */
    94102    uint64_t            u64TimeStamp;
    95     /* encoder deadline */
     103    /** Encoder deadline. */
    96104    unsigned int        uEncoderDeadline;
    97 } VIDEORECSTREAM;
    98 
     105} VIDEORECSTREAM, *PVIDEORECSTREAM;
     106
     107/** Vector of video recording streams. */
     108typedef std::vector <PVIDEORECSTREAM> VideoRecStreams;
     109
     110/**
     111 * Structure for keeping a video recording context.
     112 */
    99113typedef struct VIDEORECCONTEXT
    100114{
    101     /* semaphore to signal the encoding worker thread */
     115    /** Semaphore to signal the encoding worker thread. */
    102116    RTSEMEVENT          WaitEvent;
    103     /* semaphore required during termination */
     117    /** Semaphore required during termination. */
    104118    RTSEMEVENT          TermEvent;
    105     /* true if video recording is enabled */
     119    /** Whether video recording is enabled or not. */
    106120    bool                fEnabled;
    107     /* worker thread */
     121    /** Worker thread. */
    108122    RTTHREAD            Thread;
    109     /* number of stream contexts */
     123    /** Number of stream contexts */
    110124    uint32_t            cScreens;
    111     /* maximal time stamp */
     125    /** Maximal time stamp. */
    112126    uint64_t            u64MaxTimeStamp;
    113     /* maximal file size in MB */
     127    /** Maximal file size in MB. */
    114128    uint32_t            uMaxFileSize;
    115     /* video recording stream contexts */
    116     VIDEORECSTREAM      Strm[1];
    117 } VIDEORECCONTEXT;
     129    /** Vector of current video recording stream contexts. */
     130    VideoRecStreams     lstStreams;
     131} VIDEORECCONTEXT, *PVIDEORECCONTEXT;
    118132
    119133
     
    382396
    383397/**
    384  * Worker thread for all streams.
    385  *
    386  * RGB/YUV conversion and encoding.
     398 * Worker thread for all streams of a video recording context.
     399 *
     400 * Does RGB/YUV conversion and encoding.
    387401 */
    388402static DECLCALLBACK(int) videoRecThread(RTTHREAD hThreadSelf, void *pvUser)
     
    397411        if (ASMAtomicReadU32(&g_enmState) == VIDREC_TERMINATING)
    398412            break;
    399         for (unsigned uScreen = 0; uScreen < pCtx->cScreens; uScreen++)
    400         {
    401             PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];
    402             if (   pStrm->fEnabled
    403                 && ASMAtomicReadBool(&pStrm->fRgbFilled))
     413
     414        for (VideoRecStreams::iterator it = pCtx->lstStreams.begin(); it != pCtx->lstStreams.end(); it++)
     415        {
     416            PVIDEORECSTREAM pStream = (*it);
     417
     418            if (   pStream->fEnabled
     419                && ASMAtomicReadBool(&pStream->fRgbFilled))
    404420            {
    405                 rc = videoRecRGBToYUV(pStrm);
    406                 ASMAtomicWriteBool(&pStrm->fRgbFilled, false);
     421                rc = videoRecRGBToYUV(pStream);
     422
     423                ASMAtomicWriteBool(&pStream->fRgbFilled, false);
     424
    407425                if (RT_SUCCESS(rc))
    408                     rc = videoRecEncodeAndWrite(pStrm);
     426                    rc = videoRecEncodeAndWrite(pStream);
     427
    409428                if (RT_FAILURE(rc))
    410429                {
     
    424443
    425444/**
    426  * VideoRec utility function to create video recording context.
     445 * Creates a video recording context.
    427446 *
    428447 * @returns IPRT status code.
    429  * @param   ppCtx            Video recording context
    430  * @param   cScreens         Number of screens.
    431  */
    432 int VideoRecContextCreate(PVIDEORECCONTEXT *ppCtx, uint32_t cScreens)
    433 {
     448 * @param   cScreens         Number of screens to create context for.
     449 * @param   ppCtx            Pointer to created video recording context on success.
     450 */
     451int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCONTEXT *ppCtx)
     452{
     453    AssertReturn(cScreens, VERR_INVALID_PARAMETER);
     454    AssertPtrReturn(ppCtx, VERR_INVALID_POINTER);
     455
    434456    Assert(ASMAtomicReadU32(&g_enmState) == VIDREC_UNINITIALIZED);
    435457
    436     PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)RTMemAllocZ(RT_OFFSETOF(VIDEORECCONTEXT, Strm[cScreens]));
    437     *ppCtx = pCtx;
    438     AssertPtrReturn(pCtx, VERR_NO_MEMORY);
    439 
    440     pCtx->cScreens = cScreens;
    441     for (unsigned uScreen = 0; uScreen < cScreens; uScreen++)
    442     {
    443         /* Since we allocate without using standard C++ new mechanism
    444          * it is required to call placement new for correct initialization
    445          * of the object. */
    446         new (&pCtx->Strm[uScreen] + RT_OFFSETOF(VIDEORECSTREAM, Ebml)) WebMWriter();
    447     }
    448 
    449     int rc = RTSemEventCreate(&pCtx->WaitEvent);
    450     AssertRCReturn(rc, rc);
    451 
    452     rc = RTSemEventCreate(&pCtx->TermEvent);
    453     AssertRCReturn(rc, rc);
    454 
    455     rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void*)pCtx, 0,
    456                         RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec");
    457     AssertRCReturn(rc, rc);
    458 
    459     ASMAtomicWriteU32(&g_enmState, VIDREC_IDLE);
    460     return VINF_SUCCESS;
     458    int rc = VINF_SUCCESS;
     459
     460    PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)RTMemAllocZ(sizeof(VIDEORECCONTEXT));
     461    if (!pCtx)
     462        return VERR_NO_MEMORY;
     463
     464    for (uint32_t uScreen = 0; uScreen < cScreens; uScreen++)
     465    {
     466        PVIDEORECSTREAM pStream = (PVIDEORECSTREAM)RTMemAllocZ(sizeof(VIDEORECSTREAM));
     467        if (!pStream)
     468        {
     469            rc = VERR_NO_MEMORY;
     470            break;
     471        }
     472
     473        try
     474        {
     475            pCtx->lstStreams.push_back(pStream);
     476
     477            pStream->pEBML = new WebMWriter();
     478        }
     479        catch (std::bad_alloc)
     480        {
     481            rc = VERR_NO_MEMORY;
     482            break;
     483        }
     484    }
     485
     486    if (RT_SUCCESS(rc))
     487    {
     488        pCtx->cScreens = cScreens;
     489
     490        rc = RTSemEventCreate(&pCtx->WaitEvent);
     491        AssertRCReturn(rc, rc);
     492
     493        rc = RTSemEventCreate(&pCtx->TermEvent);
     494        AssertRCReturn(rc, rc);
     495
     496        rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void*)pCtx, 0,
     497                            RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec");
     498        AssertRCReturn(rc, rc);
     499
     500        ASMAtomicWriteU32(&g_enmState, VIDREC_IDLE);
     501
     502        if (ppCtx)
     503            *ppCtx = pCtx;
     504    }
     505    else
     506    {
     507        /* Roll back allocations on error. */
     508        VideoRecStreams::iterator it = pCtx->lstStreams.begin();
     509        while (it != pCtx->lstStreams.end())
     510        {
     511            PVIDEORECSTREAM pStream = (*it);
     512
     513            if (pStream->pEBML)
     514                delete pStream->pEBML;
     515
     516            RTMemFree(pStream);
     517            pStream = NULL;
     518
     519            it = pCtx->lstStreams.erase(it);
     520        }
     521
     522        Assert(pCtx->lstStreams.empty());
     523    }
     524
     525    return rc;
     526}
     527
     528/**
     529 * Destroys a video recording context.
     530 *
     531 * @param pCtx                  Video recording context to destroy.
     532 */
     533void VideoRecContextDestroy(PVIDEORECCONTEXT pCtx)
     534{
     535    if (!pCtx)
     536        return;
     537
     538    uint32_t enmState = VIDREC_IDLE;
     539
     540    for (;;) /** @todo r=andy Remove busy waiting! */
     541    {
     542        if (ASMAtomicCmpXchgExU32(&g_enmState, VIDREC_TERMINATING, enmState, &enmState))
     543            break;
     544        if (enmState == VIDREC_UNINITIALIZED)
     545            return;
     546    }
     547
     548    if (enmState == VIDREC_COPYING)
     549    {
     550        int rc = RTSemEventWait(pCtx->TermEvent, RT_INDEFINITE_WAIT);
     551        AssertRC(rc);
     552    }
     553
     554    RTSemEventSignal(pCtx->WaitEvent);
     555    RTThreadWait(pCtx->Thread, 10 * 1000, NULL);
     556    RTSemEventDestroy(pCtx->WaitEvent);
     557    RTSemEventDestroy(pCtx->TermEvent);
     558
     559    for (VideoRecStreams::iterator it = pCtx->lstStreams.begin(); it != pCtx->lstStreams.end(); it++)
     560    {
     561        PVIDEORECSTREAM pStream = (*it);
     562
     563        if (pStream->fEnabled)
     564        {
     565            AssertPtr(pStream->pEBML);
     566            int rc = pStream->pEBML->writeFooter(0);
     567            AssertRC(rc);
     568
     569            pStream->pEBML->close();
     570
     571            vpx_img_free(&pStream->VpxRawImage);
     572            vpx_codec_err_t rcv = vpx_codec_destroy(&pStream->VpxCodec);
     573            Assert(rcv == VPX_CODEC_OK); RT_NOREF(rcv);
     574
     575            if (pStream->pu8RgbBuf)
     576            {
     577                RTMemFree(pStream->pu8RgbBuf);
     578                pStream->pu8RgbBuf = NULL;
     579            }
     580        }
     581
     582        delete pStream->pEBML;
     583    }
     584
     585    RTMemFree(pCtx);
     586
     587    ASMAtomicWriteU32(&g_enmState, VIDREC_UNINITIALIZED);
    461588}
    462589
     
    476603 * @param   pszOptions
    477604 */
    478 int VideoRecStrmInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile,
    479                      uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps,
    480                      uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions)
    481 {
    482     AssertPtrReturn(pCtx, VERR_INVALID_PARAMETER);
     605int VideoRecStreamInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile,
     606                       uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps,
     607                       uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions)
     608{
     609    AssertPtrReturn(pCtx,                  VERR_INVALID_PARAMETER);
    483610    AssertReturn(uScreen < pCtx->cScreens, VERR_INVALID_PARAMETER);
    484611
     
    486613    pCtx->uMaxFileSize = uMaxFileSize;
    487614
    488     PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];
    489     pStrm->uTargetWidth  = uWidth;
    490     pStrm->uTargetHeight = uHeight;
    491     pStrm->pu8RgbBuf = (uint8_t *)RTMemAllocZ(uWidth * uHeight * 4);
    492     AssertReturn(pStrm->pu8RgbBuf, VERR_NO_MEMORY);
    493     pStrm->uEncoderDeadline = VPX_DL_REALTIME;
     615    PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen);
     616
     617    pStream->uTargetWidth  = uWidth;
     618    pStream->uTargetHeight = uHeight;
     619    pStream->pu8RgbBuf = (uint8_t *)RTMemAllocZ(uWidth * uHeight * 4);
     620    AssertReturn(pStream->pu8RgbBuf, VERR_NO_MEMORY);
     621    pStream->uEncoderDeadline = VPX_DL_REALTIME;
    494622
    495623    /* Play safe: the file must not exist, overwriting is potentially
     
    497625     * other important file, causing unintentional data loss. */
    498626
    499     int rc = pStrm->Ebml.create(pszFile);
     627    int rc = pStream->pEBML->create(pszFile);
    500628    if (RT_FAILURE(rc))
    501629    {
     
    504632    }
    505633
    506     vpx_codec_err_t rcv = vpx_codec_enc_config_default(DEFAULTCODEC, &pStrm->VpxConfig, 0);
     634    vpx_codec_err_t rcv = vpx_codec_enc_config_default(DEFAULTCODEC, &pStream->VpxConfig, 0);
    507635    if (rcv != VPX_CODEC_OK)
    508636    {
     
    523651            if (value == "realtime")
    524652            {
    525                 pStrm->uEncoderDeadline = VPX_DL_REALTIME;
     653                pStream->uEncoderDeadline = VPX_DL_REALTIME;
    526654            }
    527655            else if (value == "good")
    528656            {
    529                 pStrm->uEncoderDeadline = 1000000 / uFps;
     657                pStream->uEncoderDeadline = 1000000 / uFps;
    530658            }
    531659            else if (value == "best")
    532660            {
    533                 pStrm->uEncoderDeadline = VPX_DL_BEST_QUALITY;
     661                pStream->uEncoderDeadline = VPX_DL_BEST_QUALITY;
    534662            }
    535663            else
    536664            {
    537665                LogRel(("Settings quality deadline to = %s\n", value.c_str()));
    538                 pStrm->uEncoderDeadline = value.toUInt32();
     666                pStream->uEncoderDeadline = value.toUInt32();
    539667            }
    540668        }
     
    544672
    545673    /* target bitrate in kilobits per second */
    546     pStrm->VpxConfig.rc_target_bitrate = uRate;
     674    pStream->VpxConfig.rc_target_bitrate = uRate;
    547675    /* frame width */
    548     pStrm->VpxConfig.g_w = uWidth;
     676    pStream->VpxConfig.g_w = uWidth;
    549677    /* frame height */
    550     pStrm->VpxConfig.g_h = uHeight;
     678    pStream->VpxConfig.g_h = uHeight;
    551679    /* 1ms per frame */
    552     pStrm->VpxConfig.g_timebase.num = 1;
    553     pStrm->VpxConfig.g_timebase.den = 1000;
     680    pStream->VpxConfig.g_timebase.num = 1;
     681    pStream->VpxConfig.g_timebase.den = 1000;
    554682    /* disable multithreading */
    555     pStrm->VpxConfig.g_threads = 0;
    556 
    557     pStrm->uDelay = 1000 / uFps;
     683    pStream->VpxConfig.g_threads = 0;
     684
     685    pStream->uDelay = 1000 / uFps;
    558686
    559687    struct vpx_rational arg_framerate = { (int)uFps, 1 };
    560     rc = pStrm->Ebml.writeHeader(&pStrm->VpxConfig, &arg_framerate);
     688    rc = pStream->pEBML->writeHeader(&pStream->VpxConfig, &arg_framerate);
    561689    AssertRCReturn(rc, rc);
    562690
    563691    /* Initialize codec */
    564     rcv = vpx_codec_enc_init(&pStrm->VpxCodec, DEFAULTCODEC, &pStrm->VpxConfig, 0);
     692    rcv = vpx_codec_enc_init(&pStream->VpxCodec, DEFAULTCODEC, &pStream->VpxConfig, 0);
    565693    if (rcv != VPX_CODEC_OK)
    566694    {
     
    569697    }
    570698
    571     if (!vpx_img_alloc(&pStrm->VpxRawImage, VPX_IMG_FMT_I420, uWidth, uHeight, 1))
     699    if (!vpx_img_alloc(&pStream->VpxRawImage, VPX_IMG_FMT_I420, uWidth, uHeight, 1))
    572700    {
    573701        LogFlow(("Failed to allocate image %dx%d", uWidth, uHeight));
    574702        return VERR_NO_MEMORY;
    575703    }
    576     pStrm->pu8YuvBuf = pStrm->VpxRawImage.planes[0];
     704    pStream->pu8YuvBuf = pStream->VpxRawImage.planes[0];
    577705
    578706    pCtx->fEnabled = true;
    579     pStrm->fEnabled = true;
     707    pStream->fEnabled = true;
    580708    return VINF_SUCCESS;
    581709}
    582710
    583711/**
    584  * VideoRec utility function to close the video recording context.
    585  *
    586  * @param   pCtx   Pointer to video recording context.
    587  */
    588 void VideoRecContextClose(PVIDEORECCONTEXT pCtx)
    589 {
    590     if (!pCtx)
    591         return;
    592 
    593     uint32_t enmState = VIDREC_IDLE;
    594     for (;;)
    595     {
    596         if (ASMAtomicCmpXchgExU32(&g_enmState, VIDREC_TERMINATING, enmState, &enmState))
    597             break;
    598         if (enmState == VIDREC_UNINITIALIZED)
    599             return;
    600     }
    601     if (enmState == VIDREC_COPYING)
    602     {
    603         int rc = RTSemEventWait(pCtx->TermEvent, RT_INDEFINITE_WAIT);
    604         AssertRC(rc);
    605     }
    606 
    607     RTSemEventSignal(pCtx->WaitEvent);
    608     RTThreadWait(pCtx->Thread, 10000, NULL);
    609     RTSemEventDestroy(pCtx->WaitEvent);
    610     RTSemEventDestroy(pCtx->TermEvent);
    611 
    612     for (unsigned uScreen = 0; uScreen < pCtx->cScreens; uScreen++)
    613     {
    614         PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];
    615         if (pStrm->fEnabled)
    616         {
    617             int rc = pStrm->Ebml.writeFooter(0);
    618             AssertRC(rc);
    619             pStrm->Ebml.close();
    620             vpx_img_free(&pStrm->VpxRawImage);
    621             vpx_codec_err_t rcv = vpx_codec_destroy(&pStrm->VpxCodec);
    622             Assert(rcv == VPX_CODEC_OK); RT_NOREF(rcv);
    623             RTMemFree(pStrm->pu8RgbBuf);
    624             pStrm->pu8RgbBuf = NULL;
    625         }
    626         /* Explicitly deinitilize Ebml object since it was created using placement new. */
    627         pStrm->Ebml.~WebMWriter();
    628     }
    629 
    630     RTMemFree(pCtx);
    631 
    632     ASMAtomicWriteU32(&g_enmState, VIDREC_UNINITIALIZED);
    633 }
    634 
    635 /**
    636712 * VideoRec utility function to check if recording is enabled.
    637713 *
    638714 * @returns true if recording is enabled
    639  * @param   pCtx   Pointer to video recording context.
     715 * @param   pCtx                Pointer to video recording context.
    640716 */
    641717bool VideoRecIsEnabled(PVIDEORECCONTEXT pCtx)
     
    652728 *
    653729 * @returns true if recording engine is ready
    654  * @param   pCtx   Pointer to video recording context.
    655  * @param   uScreen screen id.
    656  * @param   u64TimeStamp current time stamp
     730 * @param   pCtx                Pointer to video recording context.
     731 * @param   uScreen             Screen ID.
     732 * @param   u64TimeStamp        Current time stamp.
    657733 */
    658734bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp)
     
    662738        return false;
    663739
    664     PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];
    665     if (!pStrm->fEnabled)
     740    PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen);
     741    if (!pStream->fEnabled)
    666742        return false;
    667743
    668     if (u64TimeStamp < pStrm->u64LastTimeStamp + pStrm->uDelay)
     744    if (u64TimeStamp < pStream->u64LastTimeStamp + pStream->uDelay)
    669745        return false;
    670746
    671     if (ASMAtomicReadBool(&pStrm->fRgbFilled))
     747    if (ASMAtomicReadBool(&pStream->fRgbFilled))
    672748        return false;
    673749
     
    679755 * specified limits (if any).
    680756 *
    681  * @returns true if any limit has been reached
    682  * @param   pCtx Pointer to video recording context
    683  * @param   uScreen screen id
    684  * @param   u64TimeStamp current time stamp
     757 * @returns true if any limit has been reached.
     758 * @param   pCtx                Pointer to video recording context.
     759 * @param   uScreen             Screen ID.
     760 * @param   u64TimeStamp        Current time stamp.
    685761 */
    686762
    687763bool VideoRecIsFull(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp)
    688764{
    689     PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];
    690     if(!pStrm->fEnabled)
     765    PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen);
     766    if(!pStream->fEnabled)
    691767        return false;
    692768
     
    696772    if (pCtx->uMaxFileSize > 0)
    697773    {
    698         uint64_t sizeInMB = pStrm->Ebml.getFileSize() / (1024 * 1024);
     774        uint64_t sizeInMB = pStream->pEBML->getFileSize() / (1024 * 1024);
    699775        if(sizeInMB >= pCtx->uMaxFileSize)
    700776            return true;
    701777    }
    702778    /* Check for available free disk space */
    703     if (pStrm->Ebml.getAvailableSpace() < 0x100000)
     779    if (pStream->pEBML->getAvailableSpace() < 0x100000)
    704780    {
    705781        LogRel(("Storage has not enough free space available, stopping video capture\n"));
     
    715791 *
    716792 * @returns IPRT status code.
    717  * @param   pStrm             Stream.
    718  */
    719 static int videoRecEncodeAndWrite(PVIDEORECSTREAM pStrm)
     793 * @param   pStream             Stream to encode and write.
     794 */
     795static int videoRecEncodeAndWrite(PVIDEORECSTREAM pStream)
    720796{
    721797    /* presentation time stamp */
    722     vpx_codec_pts_t pts = pStrm->u64TimeStamp;
    723     vpx_codec_err_t rcv = vpx_codec_encode(&pStrm->VpxCodec,
    724                                            &pStrm->VpxRawImage,
     798    vpx_codec_pts_t pts = pStream->u64TimeStamp;
     799    vpx_codec_err_t rcv = vpx_codec_encode(&pStream->VpxCodec,
     800                                           &pStream->VpxRawImage,
    725801                                           pts /* time stamp */,
    726                                            pStrm->uDelay  /* how long to show this frame */,
     802                                           pStream->uDelay  /* how long to show this frame */,
    727803                                           0   /* flags */,
    728                                            pStrm->uEncoderDeadline /* quality setting */);
     804                                           pStream->uEncoderDeadline /* quality setting */);
    729805    if (rcv != VPX_CODEC_OK)
    730806    {
     
    737813    for (;;)
    738814    {
    739         const vpx_codec_cx_pkt_t *pkt = vpx_codec_get_cx_data(&pStrm->VpxCodec, &iter);
     815        const vpx_codec_cx_pkt_t *pkt = vpx_codec_get_cx_data(&pStream->VpxCodec, &iter);
    740816        if (!pkt)
    741817            break;
     
    743819        {
    744820            case VPX_CODEC_CX_FRAME_PKT:
    745                 rc = pStrm->Ebml.writeBlock(&pStrm->VpxConfig, pkt);
     821                rc = pStream->pEBML->writeBlock(&pStream->VpxConfig, pkt);
    746822                break;
    747823            default:
     
    751827    }
    752828
    753     pStrm->cFrame++;
     829    pStream->cFrame++;
    754830    return rc;
    755831}
     
    831907        AssertBreakStmt(uScreen < pCtx->cScreens, rc = VERR_INVALID_PARAMETER);
    832908
    833         PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];
    834         if (!pStrm->fEnabled)
     909        PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen);
     910        if (!pStream->fEnabled)
    835911        {
    836912            rc = VINF_TRY_AGAIN; /* not (yet) enabled */
    837913            break;
    838914        }
    839         if (u64TimeStamp < pStrm->u64LastTimeStamp + pStrm->uDelay)
     915        if (u64TimeStamp < pStream->u64LastTimeStamp + pStream->uDelay)
    840916        {
    841917            rc = VINF_TRY_AGAIN; /* respect maximum frames per second */
    842918            break;
    843919        }
    844         if (ASMAtomicReadBool(&pStrm->fRgbFilled))
     920        if (ASMAtomicReadBool(&pStream->fRgbFilled))
    845921        {
    846922            rc = VERR_TRY_AGAIN; /* previous frame not yet encoded */
     
    848924        }
    849925
    850         pStrm->u64LastTimeStamp = u64TimeStamp;
    851 
    852         int xDiff = ((int)pStrm->uTargetWidth - (int)uSourceWidth) / 2;
     926        pStream->u64LastTimeStamp = u64TimeStamp;
     927
     928        int xDiff = ((int)pStream->uTargetWidth - (int)uSourceWidth) / 2;
    853929        uint32_t w = uSourceWidth;
    854930        if ((int)w + xDiff + (int)x <= 0)  /* nothing visible */
     
    869945
    870946        uint32_t h = uSourceHeight;
    871         int yDiff = ((int)pStrm->uTargetHeight - (int)uSourceHeight) / 2;
     947        int yDiff = ((int)pStream->uTargetHeight - (int)uSourceHeight) / 2;
    872948        if ((int)h + yDiff + (int)y <= 0)  /* nothing visible */
    873949        {
     
    886962            destY = y + yDiff;
    887963
    888         if (   destX > pStrm->uTargetWidth
    889             || destY > pStrm->uTargetHeight)
     964        if (   destX > pStream->uTargetWidth
     965            || destY > pStream->uTargetHeight)
    890966        {
    891967            rc = VERR_INVALID_PARAMETER;  /* nothing visible */
     
    893969        }
    894970
    895         if (destX + w > pStrm->uTargetWidth)
    896             w = pStrm->uTargetWidth - destX;
    897 
    898         if (destY + h > pStrm->uTargetHeight)
    899             h = pStrm->uTargetHeight - destY;
     971        if (destX + w > pStream->uTargetWidth)
     972            w = pStream->uTargetWidth - destX;
     973
     974        if (destY + h > pStream->uTargetHeight)
     975            h = pStream->uTargetHeight - destY;
    900976
    901977        /* Calculate bytes per pixel */
     
    906982            {
    907983                case 32:
    908                     pStrm->u32PixelFormat = VPX_IMG_FMT_RGB32;
     984                    pStream->u32PixelFormat = VPX_IMG_FMT_RGB32;
    909985                    bpp = 4;
    910986                    break;
    911987                case 24:
    912                     pStrm->u32PixelFormat = VPX_IMG_FMT_RGB24;
     988                    pStream->u32PixelFormat = VPX_IMG_FMT_RGB24;
    913989                    bpp = 3;
    914990                    break;
    915991                case 16:
    916                     pStrm->u32PixelFormat = VPX_IMG_FMT_RGB565;
     992                    pStream->u32PixelFormat = VPX_IMG_FMT_RGB565;
    917993                    bpp = 2;
    918994                    break;
     
    9271003        /* One of the dimensions of the current frame is smaller than before so
    9281004         * clear the entire buffer to prevent artifacts from the previous frame */
    929         if (   uSourceWidth  < pStrm->uLastSourceWidth
    930             || uSourceHeight < pStrm->uLastSourceHeight)
    931             memset(pStrm->pu8RgbBuf, 0, pStrm->uTargetWidth * pStrm->uTargetHeight * 4);
    932 
    933         pStrm->uLastSourceWidth  = uSourceWidth;
    934         pStrm->uLastSourceHeight = uSourceHeight;
     1005        if (   uSourceWidth  < pStream->uLastSourceWidth
     1006            || uSourceHeight < pStream->uLastSourceHeight)
     1007            memset(pStream->pu8RgbBuf, 0, pStream->uTargetWidth * pStream->uTargetHeight * 4);
     1008
     1009        pStream->uLastSourceWidth  = uSourceWidth;
     1010        pStream->uLastSourceHeight = uSourceHeight;
    9351011
    9361012        /* Calculate start offset in source and destination buffers */
    9371013        uint32_t offSrc = y * uBytesPerLine + x * bpp;
    938         uint32_t offDst = (destY * pStrm->uTargetWidth + destX) * bpp;
     1014        uint32_t offDst = (destY * pStream->uTargetWidth + destX) * bpp;
    9391015        /* do the copy */
    9401016        for (unsigned int i = 0; i < h; i++)
     
    9421018            /* Overflow check */
    9431019            Assert(offSrc + w * bpp <= uSourceHeight * uBytesPerLine);
    944             Assert(offDst + w * bpp <= pStrm->uTargetHeight * pStrm->uTargetWidth * bpp);
    945             memcpy(pStrm->pu8RgbBuf + offDst, pu8BufAddr + offSrc, w * bpp);
     1020            Assert(offDst + w * bpp <= pStream->uTargetHeight * pStream->uTargetWidth * bpp);
     1021            memcpy(pStream->pu8RgbBuf + offDst, pu8BufAddr + offSrc, w * bpp);
    9461022            offSrc += uBytesPerLine;
    947             offDst += pStrm->uTargetWidth * bpp;
    948         }
    949 
    950         pStrm->u64TimeStamp = u64TimeStamp;
    951 
    952         ASMAtomicWriteBool(&pStrm->fRgbFilled, true);
     1023            offDst += pStream->uTargetWidth * bpp;
     1024        }
     1025
     1026        pStream->u64TimeStamp = u64TimeStamp;
     1027
     1028        ASMAtomicWriteBool(&pStream->fRgbFilled, true);
    9531029        RTSemEventSignal(pCtx->WaitEvent);
    9541030    } while (0);
  • trunk/src/VBox/Main/src-client/VideoRec.h

    r62485 r65173  
    55
    66/*
    7  * Copyright (C) 2012-2016 Oracle Corporation
     7 * Copyright (C) 2012-2017 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2525typedef struct VIDEORECSTREAM *PVIDEORECSTREAM;
    2626
    27 int  VideoRecContextCreate(PVIDEORECCONTEXT *ppCtx, uint32_t cScreens);
    28 int  VideoRecStrmInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile,
    29                       uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps,
    30                       uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions);
    31 void VideoRecContextClose(PVIDEORECCONTEXT pCtx);
     27int  VideoRecContextCreate(uint32_t cScreens, PVIDEORECCONTEXT *ppCtx);
     28void VideoRecContextDestroy(PVIDEORECCONTEXT pCtx);
     29
     30int  VideoRecStreamInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile,
     31                        uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps,
     32                        uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions);
     33
    3234bool VideoRecIsEnabled(PVIDEORECCONTEXT pCtx);
    3335int  VideoRecCopyToIntBuf(PVIDEORECCONTEXT pCtx, uint32_t uScreen,
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