VirtualBox

Changeset 52200 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Jul 25, 2014 8:00:49 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95260
Message:

Main,Frontends: TakeScreenShot API cleanup.

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

Legend:

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

    r52117 r52200  
    27132713}
    27142714
    2715 HRESULT Display::takeScreenShot(ULONG aScreenId, BYTE *aAddress, ULONG aWidth, ULONG aHeight)
    2716 {
    2717     /// @todo (r=dmik) this function may take too long to complete if the VM
    2718     //  is doing something like saving state right now. Which, in case if it
    2719     //  is called on the GUI thread, will make it unresponsive. We should
    2720     //  check the machine state here (by enclosing the check and VMRequCall
    2721     //  within the Console lock to make it atomic).
    2722 
    2723     LogRelFlowFunc(("address=%p, width=%d, height=%d\n",
    2724                     aAddress, aWidth, aHeight));
    2725 
    2726     CheckComArgExpr(aWidth, aWidth != 0);
    2727     CheckComArgExpr(aHeight, aHeight != 0);
    2728 
    2729     /* Do not allow too large screenshots. This also filters out negative
    2730      * values passed as either 'width' or 'height'.
     2715HRESULT Display::takeScreenShotWorker(ULONG aScreenId,
     2716                                      BYTE *aAddress,
     2717                                      ULONG aWidth,
     2718                                      ULONG aHeight,
     2719                                      BitmapFormat_T aBitmapFormat,
     2720                                      ULONG *pcbOut)
     2721{
     2722    HRESULT rc = S_OK;
     2723
     2724    /* Do not allow too small and too large screenshots. This also filters out negative
     2725     * values passed as either 'aWidth' or 'aHeight'.
    27312726     */
    2732     CheckComArgExpr(aWidth, aWidth <= 32767);
    2733     CheckComArgExpr(aHeight, aHeight <= 32767);
    2734 
    2735     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2736 
    2737     if (!mpDrv)
    2738         return E_FAIL;
     2727    CheckComArgExpr(aWidth, aWidth != 0 && aWidth <= 32767);
     2728    CheckComArgExpr(aHeight, aHeight != 0 && aHeight <= 32767);
     2729
     2730    if (   aBitmapFormat != BitmapFormat_BGR0
     2731        && aBitmapFormat != BitmapFormat_BGRA
     2732        && aBitmapFormat != BitmapFormat_RGBA
     2733        && aBitmapFormat != BitmapFormat_PNG)
     2734    {
     2735        return setError(E_NOTIMPL,
     2736                        tr("Unsupported screenshot format 0x%08X"), aBitmapFormat);
     2737    }
    27392738
    27402739    Console::SafeVMPtr ptrVM(mParent);
     
    27422741        return ptrVM.rc();
    27432742
    2744     HRESULT rc = S_OK;
    2745 
    2746     LogRelFlowFunc(("Sending SCREENSHOT request\n"));
    2747 
    2748     /* Release lock because other thread (EMT) is called and it may initiate a resize
    2749      * which also needs lock.
    2750      *
    2751      * This method does not need the lock anymore.
    2752      */
    2753     alock.release();
    2754 
    27552743    int vrc = i_displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, aAddress, aWidth, aHeight);
    27562744
    2757     if (vrc == VERR_NOT_IMPLEMENTED)
    2758         rc = setError(E_NOTIMPL,
    2759                       tr("This feature is not implemented"));
     2745    if (RT_SUCCESS(vrc))
     2746    {
     2747        const size_t cbData = aWidth * 4 * aHeight;
     2748
     2749        /* Most of uncompressed formats. */
     2750        *pcbOut = (ULONG)cbData;
     2751
     2752        if (aBitmapFormat == BitmapFormat_BGR0)
     2753        {
     2754            /* Do nothing. */
     2755        }
     2756        else if (aBitmapFormat == BitmapFormat_BGRA)
     2757        {
     2758            uint32_t *pu32 = (uint32_t *)aAddress;
     2759            size_t cPixels = aWidth * aHeight;
     2760            while (cPixels--)
     2761            {
     2762                *pu32++ |= UINT32_C(0xFF000000);
     2763            }
     2764        }
     2765        else if (aBitmapFormat == BitmapFormat_RGBA)
     2766        {
     2767            uint8_t *pu8 = aAddress;
     2768            size_t cPixels = aWidth * aHeight;
     2769            while (cPixels--)
     2770            {
     2771                uint8_t u8 = pu8[0];
     2772                pu8[0] = pu8[2];
     2773                pu8[2] = u8;
     2774                pu8[3] = 0xFF;
     2775
     2776                pu8 += 4;
     2777            }
     2778        }
     2779        else if (aBitmapFormat == BitmapFormat_PNG)
     2780        {
     2781            uint8_t *pu8PNG = NULL;
     2782            uint32_t cbPNG = 0;
     2783            uint32_t cxPNG = 0;
     2784            uint32_t cyPNG = 0;
     2785
     2786            vrc = DisplayMakePNG(aAddress, aWidth, aHeight, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 0);
     2787            if (RT_SUCCESS(vrc))
     2788            {
     2789                if (cbPNG <= cbData)
     2790                {
     2791                    memcpy(aAddress, pu8PNG, cbPNG);
     2792                    *pcbOut = cbPNG;
     2793                }
     2794                else
     2795                {
     2796                    rc = setError(E_FAIL,
     2797                                  tr("PNG is larger than 32bpp bitmap"));
     2798                }
     2799            }
     2800            else
     2801            {
     2802                rc = setError(VBOX_E_IPRT_ERROR,
     2803                              tr("Could not convert screenshot to PNG (%Rrc)"), vrc);
     2804            }
     2805            RTMemFree(pu8PNG);
     2806        }
     2807    }
    27602808    else if (vrc == VERR_TRY_AGAIN)
    27612809        rc = setError(E_UNEXPECTED,
    2762                       tr("This feature is not available at this time"));
     2810                      tr("Screenshot is not available at this time"));
    27632811    else if (RT_FAILURE(vrc))
    27642812        rc = setError(VBOX_E_IPRT_ERROR,
    27652813                      tr("Could not take a screenshot (%Rrc)"), vrc);
    27662814
    2767     LogRelFlowFunc(("rc=%Rhrc\n", rc));
    27682815    return rc;
    27692816}
    27702817
    2771 HRESULT Display::takeScreenShotToArray(ULONG aScreenId, ULONG aWidth, ULONG aHeight, std::vector<BYTE> &aScreenData)
    2772 
    2773 {
    2774     LogRelFlowFunc(("width=%d, height=%d\n", aWidth, aHeight));
    2775 
    2776     CheckComArgExpr(aWidth, aWidth != 0);
    2777     CheckComArgExpr(raHeight, aHeight != 0);
    2778 
    2779     /* Do not allow too large screenshots. This also filters out negative
    2780      * values passed as either 'width' or 'height'.
     2818HRESULT Display::takeScreenShot(ULONG aScreenId,
     2819                                BYTE *aAddress,
     2820                                ULONG aWidth,
     2821                                ULONG aHeight,
     2822                                BitmapFormat_T aBitmapFormat)
     2823{
     2824    HRESULT rc = S_OK;
     2825
     2826    LogRelFlowFunc(("[%d] address=%p, width=%d, height=%d, format 0x%08X\n",
     2827                     aScreenId, aAddress, aWidth, aHeight, aBitmapFormat));
     2828
     2829    ULONG cbOut = 0;
     2830    rc = takeScreenShotWorker(aScreenId, aAddress, aWidth, aHeight, aBitmapFormat, &cbOut);
     2831    NOREF(cbOut);
     2832
     2833    LogRelFlowFunc(("%Rhrc\n", rc));
     2834    return rc;
     2835}
     2836
     2837HRESULT Display::takeScreenShotToArray(ULONG aScreenId,
     2838                                       ULONG aWidth,
     2839                                       ULONG aHeight,
     2840                                       BitmapFormat_T aBitmapFormat,
     2841                                       std::vector<BYTE> &aScreenData)
     2842{
     2843    HRESULT rc = S_OK;
     2844
     2845    LogRelFlowFunc(("[%d] width=%d, height=%d, format 0x%08X\n",
     2846                     aScreenId, aWidth, aHeight, aBitmapFormat));
     2847
     2848    /* Do not allow too small and too large screenshots. This also filters out negative
     2849     * values passed as either 'aWidth' or 'aHeight'.
    27812850     */
    2782     CheckComArgExpr(aWidth, aWidth <= 32767);
    2783     CheckComArgExpr(aHeight, aHeight <= 32767);
    2784 
    2785     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2786 
    2787     if (!mpDrv)
    2788         return E_FAIL;
    2789 
    2790     Console::SafeVMPtr ptrVM(mParent);
    2791     if (!ptrVM.isOk())
    2792         return ptrVM.rc();
    2793 
    2794     HRESULT rc = S_OK;
    2795 
    2796     LogRelFlowFunc(("Sending SCREENSHOT request\n"));
    2797 
    2798     /* Release lock because other thread (EMT) is called and it may initiate a resize
    2799      * which also needs lock.
    2800      *
    2801      * This method does not need the lock anymore.
    2802      */
    2803     alock.release();
    2804 
    2805     size_t cbData = aWidth * 4 * aHeight;
    2806     uint8_t *pu8Data = (uint8_t *)RTMemAlloc(cbData);
    2807 
    2808     if (!pu8Data)
    2809         return E_OUTOFMEMORY;
    2810 
    2811     int vrc = i_displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, pu8Data, aWidth, aHeight);
    2812 
    2813     if (RT_SUCCESS(vrc))
    2814     {
    2815         aScreenData.resize(cbData);
    2816 
    2817         /* Convert pixels to format expected by the API caller: [0] R, [1] G, [2] B, [3] A
    2818          * and copy to the output buffer.
    2819          */
    2820         size_t i = 0;
    2821         uint8_t *pu8 = pu8Data;
    2822         unsigned cPixels = aWidth * aHeight;
    2823         while (cPixels)
    2824         {
    2825             aScreenData[i++] = pu8[2];
    2826             aScreenData[i++] = pu8[1];
    2827             aScreenData[i++] = pu8[0];
    2828             aScreenData[i++] = 0xff;
    2829 
    2830             cPixels--;
    2831             pu8 += 4;
    2832         }
    2833     }
    2834     else if (vrc == VERR_NOT_IMPLEMENTED)
    2835         rc = setError(E_NOTIMPL,
    2836                       tr("This feature is not implemented"));
    2837     else
    2838         rc = setError(VBOX_E_IPRT_ERROR,
    2839                       tr("Could not take a screenshot (%Rrc)"), vrc);
    2840 
    2841     RTMemFree(pu8Data);
    2842 
    2843     LogRelFlowFunc(("rc=%Rhrc\n", rc));
    2844     return rc;
    2845 }
    2846 
    2847 HRESULT Display::takeScreenShotPNGToArray(ULONG aScreenId, ULONG aWidth, ULONG aHeight, std::vector<BYTE> &aScreenData)
    2848 {
    2849     LogRelFlowFunc(("width=%d, height=%d\n", aWidth, aHeight));
    2850 
    2851     CheckComArgExpr(aWidth, aWidth != 0);
    2852     CheckComArgExpr(aHeight, aHeight != 0);
    2853 
    2854     /* Do not allow too large screenshots. This also filters out negative
    2855      * values passed as either 'width' or 'height'.
    2856      */
    2857     CheckComArgExpr(aWidth, aWidth <= 32767);
    2858     CheckComArgExpr(aHeight, aHeight <= 32767);
    2859 
    2860     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2861 
    2862     CHECK_CONSOLE_DRV(mpDrv);
    2863 
    2864     Console::SafeVMPtr ptrVM(mParent);
    2865     if (!ptrVM.isOk())
    2866         return ptrVM.rc();
    2867 
    2868     HRESULT rc = S_OK;
    2869 
    2870     LogRelFlowFunc(("Sending SCREENSHOT request\n"));
    2871 
    2872     /* Release lock because other thread (EMT) is called and it may initiate a resize
    2873      * which also needs lock.
    2874      *
    2875      * This method does not need the lock anymore.
    2876      */
    2877     alock.release();
    2878 
    2879     size_t cbData = aWidth * 4 * aHeight;
    2880     uint8_t *pu8Data = (uint8_t *)RTMemAlloc(cbData);
    2881 
    2882     if (!pu8Data)
    2883         return E_OUTOFMEMORY;
    2884 
    2885     int vrc = i_displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, pu8Data, aWidth, aHeight);
    2886 
    2887     if (RT_SUCCESS(vrc))
    2888     {
    2889         uint8_t *pu8PNG = NULL;
    2890         uint32_t cbPNG = 0;
    2891         uint32_t cxPNG = 0;
    2892         uint32_t cyPNG = 0;
    2893 
    2894         vrc = DisplayMakePNG(pu8Data, aWidth, aHeight, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 0);
    2895         if (RT_SUCCESS(vrc))
    2896         {
    2897             aScreenData.resize(cbPNG);
    2898             memcpy(&aScreenData.front(), pu8PNG, cbPNG);
    2899             if (pu8PNG)
    2900                 RTMemFree(pu8PNG);
    2901         }
    2902         else
    2903         {
    2904             if (pu8PNG)
    2905                 RTMemFree(pu8PNG);
    2906             rc = setError(VBOX_E_IPRT_ERROR,
    2907                           tr("Could not convert screenshot to PNG (%Rrc)"), vrc);
    2908         }
    2909     }
    2910     else if (vrc == VERR_NOT_IMPLEMENTED)
    2911         rc = setError(E_NOTIMPL,
    2912                       tr("This feature is not implemented"));
    2913     else
    2914         rc = setError(VBOX_E_IPRT_ERROR,
    2915                       tr("Could not take a screenshot (%Rrc)"), vrc);
    2916 
    2917     RTMemFree(pu8Data);
    2918 
    2919     LogRelFlowFunc(("rc=%Rhrc\n", rc));
     2851    CheckComArgExpr(aWidth, aWidth != 0 && aWidth <= 32767);
     2852    CheckComArgExpr(aHeight, aHeight != 0 && aHeight <= 32767);
     2853
     2854    const size_t cbData = aWidth * 4 * aHeight;
     2855    aScreenData.resize(cbData);
     2856
     2857    ULONG cbOut = 0;
     2858    rc = takeScreenShotWorker(aScreenId, &aScreenData.front(), aWidth, aHeight, aBitmapFormat, &cbOut);
     2859    if (FAILED(rc))
     2860        cbOut = 0;
     2861
     2862    aScreenData.resize(cbOut);
     2863
     2864    LogRelFlowFunc(("%Rhrc\n", rc));
    29202865    return rc;
    29212866}
     
    38473792                    {
    38483793                        rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
    3849                                                   FramebufferPixelFormat_FOURCC_RGB,
     3794                                                  BitmapFormat_BGR,
    38503795                                                  pFBInfo->u16BitsPerPixel,
    38513796                                                  pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h,
     
    38553800                    {
    38563801                        rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
    3857                                                   FramebufferPixelFormat_FOURCC_RGB,
     3802                                                  BitmapFormat_BGR,
    38583803                                                  pDrv->IConnector.cBits,
    38593804                                                  pDrv->IConnector.cbScanline, pDrv->IConnector.cx,
     
    44684413    Display *pDisplay = (Display *)pvCtx;
    44694414    pDisplay->i_handleCrVRecScreenshotPerform(uScreen,
    4470                                               x, y, FramebufferPixelFormat_FOURCC_RGB, uBitsPerPixel,
     4415                                              x, y, BitmapFormat_BGR, uBitsPerPixel,
    44714416                                              uBytesPerLine, uGuestWidth, uGuestHeight,
    44724417                                              pu8BufferAddress, u64TimeStamp);
  • trunk/src/VBox/Main/src-client/VideoRec.cpp

    r50314 r52200  
    823823        /* Calculate bytes per pixel */
    824824        uint32_t bpp = 1;
    825         if (uPixelFormat == FramebufferPixelFormat_FOURCC_RGB)
     825        if (uPixelFormat == BitmapFormat_BGR)
    826826        {
    827827            switch (uBitsPerPixel)
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