Changeset 52200 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Jul 25, 2014 8:00:49 PM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 95260
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/DisplayImpl.cpp
r52117 r52200 2713 2713 } 2714 2714 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'. 2715 HRESULT 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'. 2731 2726 */ 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 } 2739 2738 2740 2739 Console::SafeVMPtr ptrVM(mParent); … … 2742 2741 return ptrVM.rc(); 2743 2742 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 resize2749 * which also needs lock.2750 *2751 * This method does not need the lock anymore.2752 */2753 alock.release();2754 2755 2743 int vrc = i_displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, aAddress, aWidth, aHeight); 2756 2744 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 } 2760 2808 else if (vrc == VERR_TRY_AGAIN) 2761 2809 rc = setError(E_UNEXPECTED, 2762 tr(" This featureis not available at this time"));2810 tr("Screenshot is not available at this time")); 2763 2811 else if (RT_FAILURE(vrc)) 2764 2812 rc = setError(VBOX_E_IPRT_ERROR, 2765 2813 tr("Could not take a screenshot (%Rrc)"), vrc); 2766 2814 2767 LogRelFlowFunc(("rc=%Rhrc\n", rc));2768 2815 return rc; 2769 2816 } 2770 2817 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'. 2818 HRESULT 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 2837 HRESULT 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'. 2781 2850 */ 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)); 2920 2865 return rc; 2921 2866 } … … 3847 3792 { 3848 3793 rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0, 3849 FramebufferPixelFormat_FOURCC_RGB,3794 BitmapFormat_BGR, 3850 3795 pFBInfo->u16BitsPerPixel, 3851 3796 pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h, … … 3855 3800 { 3856 3801 rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0, 3857 FramebufferPixelFormat_FOURCC_RGB,3802 BitmapFormat_BGR, 3858 3803 pDrv->IConnector.cBits, 3859 3804 pDrv->IConnector.cbScanline, pDrv->IConnector.cx, … … 4468 4413 Display *pDisplay = (Display *)pvCtx; 4469 4414 pDisplay->i_handleCrVRecScreenshotPerform(uScreen, 4470 x, y, FramebufferPixelFormat_FOURCC_RGB, uBitsPerPixel,4415 x, y, BitmapFormat_BGR, uBitsPerPixel, 4471 4416 uBytesPerLine, uGuestWidth, uGuestHeight, 4472 4417 pu8BufferAddress, u64TimeStamp); -
trunk/src/VBox/Main/src-client/VideoRec.cpp
r50314 r52200 823 823 /* Calculate bytes per pixel */ 824 824 uint32_t bpp = 1; 825 if (uPixelFormat == FramebufferPixelFormat_FOURCC_RGB)825 if (uPixelFormat == BitmapFormat_BGR) 826 826 { 827 827 switch (uBitsPerPixel)
Note:
See TracChangeset
for help on using the changeset viewer.