[74992] | 1 | /* $Id: RecordingInternals.cpp 105095 2024-07-02 10:06:48Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
[75344] | 3 | * Recording internals code.
|
---|
[74992] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2012-2023 Oracle and/or its affiliates.
|
---|
[74992] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[74992] | 26 | */
|
---|
| 27 |
|
---|
[75344] | 28 | #include "RecordingInternals.h"
|
---|
[105006] | 29 | #include "RecordingUtils.h"
|
---|
[74992] | 30 |
|
---|
| 31 | #include <iprt/assert.h>
|
---|
| 32 | #include <iprt/mem.h>
|
---|
| 33 |
|
---|
[105006] | 34 | #ifdef DEBUG
|
---|
| 35 | # include <math.h>
|
---|
| 36 | # include <iprt/file.h>
|
---|
| 37 | # include <iprt/formats/bmp.h>
|
---|
| 38 | #endif
|
---|
[99739] | 39 |
|
---|
[105006] | 40 |
|
---|
| 41 | /*********************************************************************************************************************************
|
---|
| 42 | * Prototypes *
|
---|
| 43 | *********************************************************************************************************************************/
|
---|
| 44 | DECLINLINE(int) recordingVideoFrameInit(PRECORDINGVIDEOFRAME pFrame, uint32_t fFlags, uint32_t uWidth, uint32_t uHeight, uint32_t uPosX, uint32_t uPosY,
|
---|
| 45 | uint8_t uBPP, RECORDINGPIXELFMT enmFmt);
|
---|
| 46 |
|
---|
| 47 |
|
---|
[74992] | 48 | /**
|
---|
[105006] | 49 | * Allocates an empty video frame, inline version.
|
---|
[96481] | 50 | *
|
---|
[105006] | 51 | * @returns Allocated video frame on success, or NULL on failure.
|
---|
| 52 | */
|
---|
| 53 | DECLINLINE(PRECORDINGVIDEOFRAME) recordingVideoFrameAlloc(void)
|
---|
| 54 | {
|
---|
| 55 | return (PRECORDINGVIDEOFRAME)RTMemAlloc(sizeof(RECORDINGVIDEOFRAME));
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | /**
|
---|
| 59 | * Allocates an empty video frame.
|
---|
| 60 | *
|
---|
| 61 | * @returns Allocated video frame on success, or NULL on failure.
|
---|
| 62 | */
|
---|
| 63 | PRECORDINGVIDEOFRAME RecordingVideoFrameAlloc(void)
|
---|
| 64 | {
|
---|
| 65 | PRECORDINGVIDEOFRAME pFrame = recordingVideoFrameAlloc();
|
---|
| 66 | AssertPtrReturn(pFrame, NULL);
|
---|
| 67 | RT_BZERO(pFrame, sizeof(RECORDINGVIDEOFRAME));
|
---|
| 68 | return pFrame;
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | /**
|
---|
| 72 | * Returns an allocated video frame from given image data.
|
---|
| 73 | *
|
---|
| 74 | * @returns Allocated video frame on success, or NULL on failure.
|
---|
| 75 | * @param pvData Pointer to image data to use.
|
---|
| 76 | * @param x X location hint (in pixel) to use for allocated frame.
|
---|
| 77 | * This is *not* the offset within \a pvData!
|
---|
| 78 | * @param y X location hint (in pixel) to use for allocated frame.
|
---|
| 79 | * This is *not* the offset within \a pvData!
|
---|
| 80 | * @param w Width (in pixel) of \a pvData image data.
|
---|
| 81 | * @param h Height (in pixel) of \a pvData image data.
|
---|
| 82 | * @param uBPP Bits per pixel) of \a pvData image data.
|
---|
| 83 | * @param enmFmt Pixel format of \a pvData image data.
|
---|
| 84 | */
|
---|
| 85 | PRECORDINGVIDEOFRAME RecordingVideoFrameAllocEx(const void *pvData, uint32_t x, uint32_t y, uint32_t w, uint32_t h,
|
---|
| 86 | uint8_t uBPP, RECORDINGPIXELFMT enmFmt)
|
---|
| 87 | {
|
---|
| 88 | PRECORDINGVIDEOFRAME pFrame = recordingVideoFrameAlloc();
|
---|
| 89 | AssertPtrReturn(pFrame, NULL);
|
---|
[105011] | 90 | int vrc = recordingVideoFrameInit(pFrame, RECORDINGVIDEOFRAME_F_VISIBLE, w, h, x, y, uBPP, enmFmt);
|
---|
| 91 | AssertRCReturn(vrc, NULL);
|
---|
[105006] | 92 | memcpy(pFrame->pau8Buf, pvData, pFrame->cbBuf);
|
---|
| 93 |
|
---|
| 94 | return VINF_SUCCESS;
|
---|
| 95 | }
|
---|
| 96 |
|
---|
| 97 | /**
|
---|
| 98 | * Frees a recording video frame.
|
---|
| 99 | *
|
---|
| 100 | * @param pFrame Pointer to video frame to free. The pointer will be invalid after return.
|
---|
| 101 | */
|
---|
| 102 | void RecordingVideoFrameFree(PRECORDINGVIDEOFRAME pFrame)
|
---|
| 103 | {
|
---|
| 104 | if (!pFrame)
|
---|
| 105 | return;
|
---|
| 106 |
|
---|
| 107 | RecordingVideoFrameDestroy(pFrame);
|
---|
| 108 |
|
---|
| 109 | RTMemFree(pFrame);
|
---|
| 110 | }
|
---|
| 111 |
|
---|
| 112 | /**
|
---|
| 113 | * Initializes a recording frame, inline version.
|
---|
| 114 | *
|
---|
| 115 | * @returns VBox status code.
|
---|
[96481] | 116 | * @param pFrame Pointer to video frame to initialize.
|
---|
[105006] | 117 | * @param fFlags Flags of type RECORDINGVIDEOFRAME_F_XXX.
|
---|
| 118 | * @param uWidth Width (in pixel) of video frame.
|
---|
| 119 | * @param uHeight Height (in pixel) of video frame.
|
---|
| 120 | * @param uPosX X positioning hint.
|
---|
| 121 | * @param uPosY Y positioning hint.
|
---|
[96481] | 122 | * @param uBPP Bits per pixel (BPP).
|
---|
[105006] | 123 | * @param enmFmt Pixel format to use.
|
---|
[96481] | 124 | */
|
---|
[105006] | 125 | DECLINLINE(int) recordingVideoFrameInit(PRECORDINGVIDEOFRAME pFrame, uint32_t fFlags, uint32_t uWidth, uint32_t uHeight,
|
---|
| 126 | uint32_t uPosX, uint32_t uPosY, uint8_t uBPP, RECORDINGPIXELFMT enmFmt)
|
---|
[96481] | 127 | {
|
---|
[105006] | 128 | AssertPtrReturn(pFrame, VERR_INVALID_POINTER);
|
---|
| 129 | AssertReturn(uWidth, VERR_INVALID_PARAMETER);
|
---|
| 130 | AssertReturn(uHeight, VERR_INVALID_PARAMETER);
|
---|
| 131 | AssertReturn(uBPP && uBPP % 8 == 0, VERR_INVALID_PARAMETER);
|
---|
| 132 |
|
---|
[96481] | 133 | /* Calculate bytes per pixel and set pixel format. */
|
---|
| 134 | const unsigned uBytesPerPixel = uBPP / 8;
|
---|
[105006] | 135 |
|
---|
| 136 | /* Calculate bytes per pixel and set pixel format. */
|
---|
| 137 | const size_t cbRGBBuf = uWidth * uHeight * uBytesPerPixel;
|
---|
[96481] | 138 | AssertReturn(cbRGBBuf, VERR_INVALID_PARAMETER);
|
---|
| 139 |
|
---|
[105006] | 140 | pFrame->pau8Buf = (uint8_t *)RTMemAlloc(cbRGBBuf);
|
---|
| 141 | AssertPtrReturn(pFrame->pau8Buf, VERR_NO_MEMORY);
|
---|
| 142 | pFrame->cbBuf = cbRGBBuf;
|
---|
[96481] | 143 |
|
---|
[105006] | 144 | pFrame->fFlags = fFlags;
|
---|
| 145 | pFrame->Info.uWidth = uWidth;
|
---|
| 146 | pFrame->Info.uHeight = uHeight;
|
---|
| 147 | pFrame->Info.uBPP = uBPP;
|
---|
| 148 | pFrame->Info.enmPixelFmt = enmFmt;
|
---|
| 149 | pFrame->Info.uBytesPerLine = uWidth * uBytesPerPixel;
|
---|
| 150 | pFrame->Pos.x = uPosX;
|
---|
| 151 | pFrame->Pos.y = uPosY;
|
---|
[96481] | 152 |
|
---|
| 153 | return VINF_SUCCESS;
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 | /**
|
---|
[105006] | 157 | * Initializes a recording frame.
|
---|
[96481] | 158 | *
|
---|
[105006] | 159 | * @param pFrame Pointer to video frame to initialize.
|
---|
| 160 | * @param fFlags Flags of type RECORDINGVIDEOFRAME_F_XXX.
|
---|
| 161 | * @param uWidth Width (in pixel) of video frame.
|
---|
| 162 | * @param uHeight Height (in pixel) of video frame.
|
---|
| 163 | * @param uPosX X positioning hint.
|
---|
| 164 | * @param uPosY Y positioning hint.
|
---|
| 165 | * @param uBPP Bits per pixel (BPP).
|
---|
| 166 | * @param enmFmt Pixel format to use.
|
---|
[96481] | 167 | */
|
---|
[105006] | 168 | int RecordingVideoFrameInit(PRECORDINGVIDEOFRAME pFrame, uint32_t fFlags, uint32_t uWidth, uint32_t uHeight, uint32_t uPosX, uint32_t uPosY,
|
---|
| 169 | uint8_t uBPP, RECORDINGPIXELFMT enmFmt)
|
---|
[96481] | 170 | {
|
---|
[105006] | 171 | return recordingVideoFrameInit(pFrame, fFlags, uWidth, uHeight, uPosX, uPosY, uBPP, enmFmt);
|
---|
| 172 | }
|
---|
| 173 |
|
---|
| 174 | /**
|
---|
| 175 | * Destroys a recording video frame.
|
---|
| 176 | *
|
---|
| 177 | * @param pFrame Pointer to video frame to destroy.
|
---|
| 178 | */
|
---|
| 179 | void RecordingVideoFrameDestroy(PRECORDINGVIDEOFRAME pFrame)
|
---|
| 180 | {
|
---|
| 181 | if (!pFrame)
|
---|
| 182 | return;
|
---|
| 183 |
|
---|
| 184 | if (pFrame->pau8Buf)
|
---|
[96481] | 185 | {
|
---|
| 186 | Assert(pFrame->cbBuf);
|
---|
[105006] | 187 | RTMemFree(pFrame->pau8Buf);
|
---|
| 188 | pFrame->pau8Buf = NULL;
|
---|
| 189 | pFrame->cbBuf = 0;
|
---|
[96481] | 190 | }
|
---|
| 191 | }
|
---|
| 192 |
|
---|
| 193 | /**
|
---|
[105006] | 194 | * Duplicates a video frame.
|
---|
[74992] | 195 | *
|
---|
[105006] | 196 | * @returns Pointer to duplicated frame on success, or NULL on failure.
|
---|
| 197 | * @param pFrame Video frame to duplicate.
|
---|
[74992] | 198 | */
|
---|
[105006] | 199 | PRECORDINGVIDEOFRAME RecordingVideoFrameDup(PRECORDINGVIDEOFRAME pFrame)
|
---|
[74992] | 200 | {
|
---|
[105006] | 201 | PRECORDINGVIDEOFRAME pFrameDup = (PRECORDINGVIDEOFRAME)RTMemDup(pFrame, sizeof(RECORDINGVIDEOFRAME));
|
---|
| 202 | AssertPtrReturn(pFrameDup, NULL);
|
---|
| 203 | pFrameDup->pau8Buf = (uint8_t *)RTMemDup(pFrame->pau8Buf, pFrame->cbBuf);
|
---|
| 204 | AssertPtrReturnStmt(pFrameDup, RTMemFree(pFrameDup), NULL);
|
---|
[74992] | 205 |
|
---|
[105006] | 206 | return pFrameDup;
|
---|
| 207 | }
|
---|
[96481] | 208 |
|
---|
[105006] | 209 | /**
|
---|
| 210 | * Clears the content of a video recording frame, inlined version.
|
---|
| 211 | *
|
---|
| 212 | * @param pFrame Video recording frame to clear content for.
|
---|
| 213 | */
|
---|
| 214 | DECLINLINE(void) recordingVideoFrameClear(PRECORDINGVIDEOFRAME pFrame)
|
---|
| 215 | {
|
---|
| 216 | RT_BZERO(pFrame->pau8Buf, pFrame->cbBuf);
|
---|
[74992] | 217 | }
|
---|
| 218 |
|
---|
[105006] | 219 | /**
|
---|
| 220 | * Clears the content of a video recording frame.
|
---|
| 221 | *
|
---|
| 222 | * @param pFrame Video recording frame to clear content for.
|
---|
| 223 | */
|
---|
| 224 | void RecordingVideoFrameClear(PRECORDINGVIDEOFRAME pFrame)
|
---|
| 225 | {
|
---|
| 226 | recordingVideoFrameClear(pFrame);
|
---|
| 227 | }
|
---|
[99739] | 228 |
|
---|
[74992] | 229 | /**
|
---|
[105006] | 230 | * Simple blitting function for raw image data, inlined version.
|
---|
[96481] | 231 | *
|
---|
[105006] | 232 | * @returns VBox status code.
|
---|
[105010] | 233 | * @param pu8Dst Destination buffer.
|
---|
| 234 | * @param cbDst Size (in bytes) of \a pu8Dst.
|
---|
[105006] | 235 | * @param uDstX X destination (in pixel) within destination frame.
|
---|
| 236 | * @param uDstY Y destination (in pixel) within destination frame.
|
---|
| 237 | * @param uDstBytesPerLine Bytes per line in destination buffer.
|
---|
| 238 | * @param uDstBPP BPP of destination buffer.
|
---|
| 239 | * @param enmDstFmt Pixel format of source data. Must match \a pFrame.
|
---|
| 240 | * @param pu8Src Source data to blit. Must be in the same pixel format as \a pFrame.
|
---|
| 241 | * @param cbSrc Size (in bytes) of \a pu8Src.
|
---|
| 242 | * @param uSrcX X start (in pixel) within source data.
|
---|
| 243 | * @param uSrcY Y start (in pixel) within source data.
|
---|
| 244 | * @param uSrcWidth Width (in pixel) to blit from source data.
|
---|
| 245 | * @param uSrcHeight Height (in pixel) to blit from data.
|
---|
| 246 | * @param uSrcBytesPerLine Bytes per line in source data.
|
---|
| 247 | * @param uSrcBPP BPP of source data. Must match \a pFrame.
|
---|
| 248 | * @param enmSrcFmt Pixel format of source data. Must match \a pFrame.
|
---|
[96481] | 249 | */
|
---|
[105095] | 250 | DECLINLINE(int) recordingVideoBlitRaw(uint8_t *pu8Dst, size_t cbDst, uint32_t uDstX, uint32_t uDstY,
|
---|
| 251 | uint32_t uDstBytesPerLine, uint8_t uDstBPP, RECORDINGPIXELFMT enmDstFmt,
|
---|
| 252 | const uint8_t *pu8Src, size_t cbSrc, uint32_t uSrcX, uint32_t uSrcY, uint32_t uSrcWidth, uint32_t uSrcHeight,
|
---|
| 253 | uint32_t uSrcBytesPerLine, uint8_t uSrcBPP, RECORDINGPIXELFMT enmSrcFmt)
|
---|
[96481] | 254 | {
|
---|
[105006] | 255 | RT_NOREF(enmDstFmt, enmSrcFmt);
|
---|
| 256 |
|
---|
| 257 | uint8_t const uDstBytesPerPixel = uDstBPP / 8;
|
---|
| 258 | uint8_t const uSrcBytesPerPixel = uSrcBPP / 8;
|
---|
| 259 |
|
---|
| 260 | size_t offSrc = RT_MIN(uSrcY * uSrcBytesPerLine + uSrcX * uSrcBytesPerPixel, cbSrc);
|
---|
| 261 | size_t offDst = RT_MIN(uDstY * uDstBytesPerLine + uDstX * uDstBytesPerPixel, cbDst);
|
---|
| 262 |
|
---|
| 263 | for (uint32_t y = 0; y < uSrcHeight; y++)
|
---|
[96481] | 264 | {
|
---|
[105006] | 265 | size_t const cbToCopy = RT_MIN(cbDst - offDst,
|
---|
| 266 | RT_MIN(uSrcWidth * uSrcBytesPerPixel, cbSrc - offSrc));
|
---|
| 267 | if (!cbToCopy)
|
---|
| 268 | break;
|
---|
| 269 | memcpy(pu8Dst + offDst, (const uint8_t *)pu8Src + offSrc, cbToCopy);
|
---|
| 270 | offDst = RT_MIN(offDst + uDstBytesPerLine, cbDst);
|
---|
| 271 | Assert(offDst <= cbDst);
|
---|
| 272 | offSrc = RT_MIN(offSrc + uSrcBytesPerLine, cbSrc);
|
---|
| 273 | Assert(offSrc <= cbSrc);
|
---|
[96481] | 274 | }
|
---|
[105006] | 275 |
|
---|
| 276 | return VINF_SUCCESS;
|
---|
[96481] | 277 | }
|
---|
| 278 |
|
---|
[105095] | 279 | int RecordingVideoBlitRaw(uint8_t *pu8Dst, size_t cbDst, uint32_t uDstX, uint32_t uDstY,
|
---|
| 280 | uint32_t uDstBytesPerLine, uint8_t uDstBPP, RECORDINGPIXELFMT enmDstFmt,
|
---|
| 281 | const uint8_t *pu8Src, size_t cbSrc, uint32_t uSrcX, uint32_t uSrcY, uint32_t uSrcWidth, uint32_t uSrcHeight,
|
---|
| 282 | uint32_t uSrcBytesPerLine, uint8_t uSrcBPP, RECORDINGPIXELFMT enmSrcFmt)
|
---|
| 283 | {
|
---|
| 284 | return recordingVideoBlitRaw(pu8Dst, cbDst, uDstX, uDstY, uDstBytesPerLine,uDstBPP, enmDstFmt,
|
---|
| 285 | pu8Src, cbSrc, uSrcX, uSrcY, uSrcWidth, uSrcHeight,uSrcBytesPerLine, uSrcBPP, enmSrcFmt);
|
---|
| 286 | }
|
---|
| 287 |
|
---|
[96481] | 288 | /**
|
---|
[105006] | 289 | * Simple blitting function for raw image data with alpha channel, inlined version.
|
---|
[74992] | 290 | *
|
---|
[105006] | 291 | * @returns VBox status code.
|
---|
| 292 | * @param pFrame Destination frame.
|
---|
| 293 | * @param uDstX X destination (in pixel) within destination frame.
|
---|
| 294 | * @param uDstY Y destination (in pixel) within destination frame.
|
---|
| 295 | * @param pu8Src Source data to blit. Must be in the same pixel format as \a pFrame.
|
---|
| 296 | * @param cbSrc Size (in bytes) of \a pu8Src.
|
---|
| 297 | * @param uSrcX X start (in pixel) within source data.
|
---|
| 298 | * @param uSrcY Y start (in pixel) within source data.
|
---|
| 299 | * @param uSrcWidth Width (in pixel) to blit from source data.
|
---|
| 300 | * @param uSrcHeight Height (in pixel) to blit from data.
|
---|
| 301 | * @param uSrcBytesPerLine Bytes per line in source data.
|
---|
| 302 | * @param uSrcBPP BPP of source data. Must match \a pFrame.
|
---|
| 303 | * @param enmFmt Pixel format of source data. Must match \a pFrame.
|
---|
[74992] | 304 | */
|
---|
[105006] | 305 | DECLINLINE(int) recordingVideoFrameBlitRawAlpha(PRECORDINGVIDEOFRAME pFrame, uint32_t uDstX, uint32_t uDstY,
|
---|
| 306 | const uint8_t *pu8Src, size_t cbSrc, uint32_t uSrcX, uint32_t uSrcY, uint32_t uSrcWidth, uint32_t uSrcHeight,
|
---|
| 307 | uint32_t uSrcBytesPerLine, uint8_t uSrcBPP, RECORDINGPIXELFMT enmFmt)
|
---|
[74992] | 308 | {
|
---|
[105006] | 309 | AssertReturn(pFrame->Info.enmPixelFmt == enmFmt, VERR_NOT_SUPPORTED);
|
---|
| 310 | AssertReturn(pFrame->Info.uBPP == uSrcBPP, VERR_NOT_SUPPORTED);
|
---|
| 311 |
|
---|
| 312 | RT_NOREF(uDstX, uDstY, cbSrc, uSrcX, uSrcY, uSrcBytesPerLine);
|
---|
| 313 | uint8_t const uDstBytesPerPixel = pFrame->Info.uBPP / 8;
|
---|
| 314 | uint8_t const uSrcBytesPerPixel = uSrcBPP / 8;
|
---|
| 315 |
|
---|
| 316 | for (uint32_t y = 0; y < uSrcHeight; y++)
|
---|
| 317 | {
|
---|
| 318 | size_t offSrc = RT_MIN((uSrcY + y) * uSrcBytesPerLine + uSrcX * uSrcBytesPerPixel, cbSrc);
|
---|
| 319 | size_t offDst = RT_MIN((uDstY + y) * pFrame->Info.uBytesPerLine + uDstX * uDstBytesPerPixel, pFrame->cbBuf);
|
---|
| 320 |
|
---|
| 321 | for (uint32_t x = 0; x < uSrcWidth; x++)
|
---|
| 322 | {
|
---|
| 323 | /* BGRA */
|
---|
| 324 | int const idx_b = 0;
|
---|
| 325 | int const idx_g = 1;
|
---|
| 326 | int const idx_r = 2;
|
---|
| 327 | int const idx_a = 3;
|
---|
| 328 |
|
---|
| 329 | unsigned int const alpha = pu8Src[offSrc + idx_a] + 1;
|
---|
| 330 | unsigned int const inv_alpha = 256 - pu8Src[offSrc + idx_a];
|
---|
| 331 | if (pu8Src[offSrc + idx_a])
|
---|
| 332 | {
|
---|
| 333 | pFrame->pau8Buf[offDst + idx_r] = (unsigned char)((alpha * pu8Src[offSrc + idx_r] + inv_alpha * pFrame->pau8Buf[offDst + idx_r]) >> 8);
|
---|
| 334 | pFrame->pau8Buf[offDst + idx_g] = (unsigned char)((alpha * pu8Src[offSrc + idx_g] + inv_alpha * pFrame->pau8Buf[offDst + idx_g]) >> 8);
|
---|
| 335 | pFrame->pau8Buf[offDst + idx_b] = (unsigned char)((alpha * pu8Src[offSrc + idx_b] + inv_alpha * pFrame->pau8Buf[offDst + idx_b]) >> 8);
|
---|
| 336 | pFrame->pau8Buf[offDst + idx_a] = 0xff;
|
---|
| 337 | }
|
---|
| 338 |
|
---|
| 339 | offSrc = RT_MIN(offSrc + uSrcBytesPerPixel, cbSrc);
|
---|
| 340 | if (offSrc >= cbSrc)
|
---|
| 341 | break;
|
---|
| 342 | offDst = RT_MIN(offDst + uDstBytesPerPixel, pFrame->cbBuf);
|
---|
| 343 | if (offDst >= pFrame->cbBuf)
|
---|
| 344 | break;
|
---|
| 345 | }
|
---|
| 346 | }
|
---|
| 347 |
|
---|
| 348 | #if 0
|
---|
| 349 | RecordingUtilsDbgDumpImageData(pu8Src, cbSrc, "/tmp", "cursor-src", uSrcWidth, uSrcHeight, uSrcBytesPerLine, 32);
|
---|
| 350 | RecordingUtilsDbgDumpVideoFrameEx(pFrame, "/tmp", "cursor-dst");
|
---|
| 351 | #endif
|
---|
| 352 |
|
---|
| 353 | return VINF_SUCCESS;
|
---|
| 354 | }
|
---|
| 355 |
|
---|
| 356 | /**
|
---|
| 357 | * Simple blitting function for raw image data.
|
---|
| 358 | *
|
---|
| 359 | * @returns VBox status code.
|
---|
| 360 | * @param pDstFrame Destination frame.
|
---|
| 361 | * @param uDstX X destination (in pixel) within destination frame.
|
---|
| 362 | * @param uDstY Y destination (in pixel) within destination frame.
|
---|
| 363 | * @param pu8Src Source data to blit. Must be in the same pixel format as \a pFrame.
|
---|
| 364 | * @param cbSrc Size (in bytes) of \a pu8Src.
|
---|
| 365 | * @param uSrcX X start (in pixel) within source data.
|
---|
| 366 | * @param uSrcY Y start (in pixel) within source data.
|
---|
| 367 | * @param uSrcWidth Width (in pixel) to blit from source data.
|
---|
| 368 | * @param uSrcHeight Height (in pixel) to blit from data.
|
---|
| 369 | * @param uSrcBytesPerLine Bytes per line in source data.
|
---|
| 370 | * @param uSrcBPP BPP of source data. Must match \a pFrame.
|
---|
| 371 | * @param enmFmt Pixel format of source data. Must match \a pFrame.
|
---|
| 372 | */
|
---|
| 373 | int RecordingVideoFrameBlitRaw(PRECORDINGVIDEOFRAME pDstFrame, uint32_t uDstX, uint32_t uDstY,
|
---|
| 374 | const uint8_t *pu8Src, size_t cbSrc, uint32_t uSrcX, uint32_t uSrcY, uint32_t uSrcWidth, uint32_t uSrcHeight,
|
---|
| 375 | uint32_t uSrcBytesPerLine, uint8_t uSrcBPP, RECORDINGPIXELFMT enmFmt)
|
---|
| 376 | {
|
---|
[105095] | 377 | return recordingVideoBlitRaw(/* Destination */
|
---|
| 378 | pDstFrame->pau8Buf, pDstFrame->cbBuf, uDstX, uDstY,
|
---|
| 379 | pDstFrame->Info.uBytesPerLine, pDstFrame->Info.uBPP, pDstFrame->Info.enmPixelFmt,
|
---|
| 380 | /* Source */
|
---|
| 381 | pu8Src, cbSrc, uSrcX, uSrcY, uSrcWidth, uSrcHeight, uSrcBytesPerLine, uSrcBPP, enmFmt);
|
---|
[105006] | 382 | }
|
---|
| 383 |
|
---|
| 384 | /**
|
---|
| 385 | * Simple blitting function for raw image data with alpha channel.
|
---|
| 386 | *
|
---|
| 387 | * @returns VBox status code.
|
---|
[105095] | 388 | * @param pDstFrame Destination frame.
|
---|
[105006] | 389 | * @param uDstX X destination (in pixel) within destination frame.
|
---|
| 390 | * @param uDstY Y destination (in pixel) within destination frame.
|
---|
| 391 | * @param pu8Src Source data to blit. Must be in the same pixel format as \a pFrame.
|
---|
| 392 | * @param cbSrc Size (in bytes) of \a pu8Src.
|
---|
| 393 | * @param uSrcX X start (in pixel) within source data.
|
---|
| 394 | * @param uSrcY Y start (in pixel) within source data.
|
---|
| 395 | * @param uSrcWidth Width (in pixel) to blit from source data.
|
---|
| 396 | * @param uSrcHeight Height (in pixel) to blit from data.
|
---|
| 397 | * @param uSrcBytesPerLine Bytes per line in source data.
|
---|
| 398 | * @param uSrcBPP BPP of source data. Must match \a pFrame.
|
---|
| 399 | * @param enmFmt Pixel format of source data. Must match \a pFrame.
|
---|
| 400 | */
|
---|
[105095] | 401 | int RecordingVideoFrameBlitRawAlpha(PRECORDINGVIDEOFRAME pDstFrame, uint32_t uDstX, uint32_t uDstY,
|
---|
[105006] | 402 | const uint8_t *pu8Src, size_t cbSrc, uint32_t uSrcX, uint32_t uSrcY, uint32_t uSrcWidth, uint32_t uSrcHeight,
|
---|
| 403 | uint32_t uSrcBytesPerLine, uint8_t uSrcBPP, RECORDINGPIXELFMT enmFmt)
|
---|
| 404 | {
|
---|
[105095] | 405 | return recordingVideoFrameBlitRawAlpha(pDstFrame, uDstX, uDstY,
|
---|
[105006] | 406 | pu8Src, cbSrc, uSrcX, uSrcY, uSrcWidth, uSrcHeight, uSrcBytesPerLine, uSrcBPP, enmFmt);
|
---|
| 407 | }
|
---|
| 408 |
|
---|
| 409 | /**
|
---|
| 410 | * Simple blitting function for video frames.
|
---|
| 411 | *
|
---|
| 412 | * @returns VBox status code.
|
---|
| 413 | * @param pDstFrame Destination frame.
|
---|
| 414 | * @param uDstX X destination (in pixel) within destination frame.
|
---|
| 415 | * @param uDstY Y destination (in pixel) within destination frame.
|
---|
| 416 | * @param pSrcFrame Source frame.
|
---|
| 417 | * @param uSrcX X start (in pixel) within source frame.
|
---|
| 418 | * @param uSrcY Y start (in pixel) within source frame.
|
---|
| 419 | * @param uSrcWidth Width (in pixel) to blit from source frame.
|
---|
| 420 | * @param uSrcHeight Height (in pixel) to blit from frame.
|
---|
| 421 | *
|
---|
| 422 | * @note Does NOT check for limits, so use with care!
|
---|
| 423 | */
|
---|
| 424 | int RecordingVideoFrameBlitFrame(PRECORDINGVIDEOFRAME pDstFrame, uint32_t uDstX, uint32_t uDstY,
|
---|
| 425 | PRECORDINGVIDEOFRAME pSrcFrame, uint32_t uSrcX, uint32_t uSrcY, uint32_t uSrcWidth, uint32_t uSrcHeight)
|
---|
| 426 | {
|
---|
[105095] | 427 | return recordingVideoBlitRaw(/* Dest */
|
---|
| 428 | pDstFrame->pau8Buf, pDstFrame->cbBuf, uDstX, uDstY,
|
---|
| 429 | pDstFrame->Info.uBytesPerLine, pDstFrame->Info.uBPP, pDstFrame->Info.enmPixelFmt,
|
---|
| 430 | /* Source */
|
---|
| 431 | pSrcFrame->pau8Buf, pSrcFrame->cbBuf, uSrcX, uSrcY, uSrcWidth, uSrcHeight,
|
---|
| 432 | pSrcFrame->Info.uBytesPerLine, pSrcFrame->Info.uBPP, pSrcFrame->Info.enmPixelFmt);
|
---|
[105006] | 433 | }
|
---|
| 434 |
|
---|
| 435 | #ifdef VBOX_WITH_AUDIO_RECORDING
|
---|
| 436 | /**
|
---|
| 437 | * Destroys a recording audio frame.
|
---|
| 438 | *
|
---|
| 439 | * @param pFrame Pointer to audio frame to destroy.
|
---|
| 440 | */
|
---|
| 441 | DECLINLINE(void) recordingAudioFrameDestroy(PRECORDINGAUDIOFRAME pFrame)
|
---|
| 442 | {
|
---|
[74992] | 443 | if (!pFrame)
|
---|
| 444 | return;
|
---|
| 445 |
|
---|
[105006] | 446 | if (pFrame->pvBuf)
|
---|
| 447 | {
|
---|
| 448 | Assert(pFrame->cbBuf);
|
---|
| 449 | RTMemFree(pFrame->pvBuf);
|
---|
| 450 | pFrame->pvBuf = NULL;
|
---|
| 451 | pFrame->cbBuf = 0;
|
---|
| 452 | }
|
---|
| 453 | }
|
---|
[96481] | 454 |
|
---|
[105006] | 455 | /**
|
---|
| 456 | * Frees a previously allocated recording audio frame.
|
---|
| 457 | *
|
---|
| 458 | * @param pFrame Audio frame to free. The pointer will be invalid after return.
|
---|
| 459 | */
|
---|
| 460 | void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame)
|
---|
| 461 | {
|
---|
| 462 | if (!pFrame)
|
---|
| 463 | return;
|
---|
| 464 |
|
---|
| 465 | recordingAudioFrameDestroy(pFrame);
|
---|
| 466 |
|
---|
[96481] | 467 | RTMemFree(pFrame);
|
---|
[105006] | 468 | pFrame = NULL;
|
---|
[96481] | 469 | }
|
---|
[105006] | 470 | #endif /* VBOX_WITH_AUDIO_RECORDING */
|
---|
[96481] | 471 |
|
---|
| 472 | /**
|
---|
| 473 | * Frees a recording frame.
|
---|
| 474 | *
|
---|
[105006] | 475 | * @param pFrame Pointer to recording frame to free.
|
---|
| 476 | * The pointer will be invalid after return.
|
---|
[96481] | 477 | */
|
---|
| 478 | void RecordingFrameFree(PRECORDINGFRAME pFrame)
|
---|
| 479 | {
|
---|
| 480 | if (!pFrame)
|
---|
| 481 | return;
|
---|
| 482 |
|
---|
| 483 | switch (pFrame->enmType)
|
---|
[74992] | 484 | {
|
---|
[97404] | 485 | #ifdef VBOX_WITH_AUDIO_RECORDING
|
---|
[96481] | 486 | case RECORDINGFRAME_TYPE_AUDIO:
|
---|
[105006] | 487 | recordingAudioFrameDestroy(&pFrame->u.Audio);
|
---|
[96481] | 488 | break;
|
---|
[97404] | 489 | #endif
|
---|
[96481] | 490 | case RECORDINGFRAME_TYPE_VIDEO:
|
---|
[105006] | 491 | RecordingVideoFrameDestroy(&pFrame->u.Video);
|
---|
[96481] | 492 | break;
|
---|
| 493 |
|
---|
[105006] | 494 | case RECORDINGFRAME_TYPE_CURSOR_SHAPE:
|
---|
| 495 | RecordingVideoFrameDestroy(&pFrame->u.CursorShape);
|
---|
| 496 | break;
|
---|
| 497 |
|
---|
[96481] | 498 | default:
|
---|
[105006] | 499 | /* Nothing to do here. */
|
---|
[96481] | 500 | break;
|
---|
[74992] | 501 | }
|
---|
[96481] | 502 |
|
---|
[74992] | 503 | RTMemFree(pFrame);
|
---|
[96481] | 504 | pFrame = NULL;
|
---|
[74992] | 505 | }
|
---|
| 506 |
|
---|