VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/RecordingInternals.cpp@ 106061

Last change on this file since 106061 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.6 KB
Line 
1/* $Id: RecordingInternals.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Recording internals code.
4 */
5
6/*
7 * Copyright (C) 2012-2024 Oracle and/or its affiliates.
8 *
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
26 */
27
28#include "RecordingInternals.h"
29#include "RecordingUtils.h"
30
31#include <iprt/assert.h>
32#include <iprt/mem.h>
33
34#ifdef DEBUG
35# include <math.h>
36# include <iprt/file.h>
37# include <iprt/formats/bmp.h>
38#endif
39
40
41/*********************************************************************************************************************************
42* Prototypes *
43*********************************************************************************************************************************/
44DECLINLINE(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
48/**
49 * Allocates an empty video frame, inline version.
50 *
51 * @returns Allocated video frame on success, or NULL on failure.
52 */
53DECLINLINE(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 */
63PRECORDINGVIDEOFRAME 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 */
85PRECORDINGVIDEOFRAME 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);
90 int vrc = recordingVideoFrameInit(pFrame, RECORDINGVIDEOFRAME_F_VISIBLE, w, h, x, y, uBPP, enmFmt);
91 AssertRCReturn(vrc, NULL);
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 */
102void 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.
116 * @param pFrame Pointer to video frame to initialize.
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.
122 * @param uBPP Bits per pixel (BPP).
123 * @param enmFmt Pixel format to use.
124 */
125DECLINLINE(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)
127{
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
133 /* Calculate bytes per pixel and set pixel format. */
134 const unsigned uBytesPerPixel = uBPP / 8;
135
136 /* Calculate bytes per pixel and set pixel format. */
137 const size_t cbRGBBuf = uWidth * uHeight * uBytesPerPixel;
138 AssertReturn(cbRGBBuf, VERR_INVALID_PARAMETER);
139
140 pFrame->pau8Buf = (uint8_t *)RTMemAlloc(cbRGBBuf);
141 AssertPtrReturn(pFrame->pau8Buf, VERR_NO_MEMORY);
142 pFrame->cbBuf = cbRGBBuf;
143
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;
152
153 return VINF_SUCCESS;
154}
155
156/**
157 * Initializes a recording frame.
158 *
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.
167 */
168int RecordingVideoFrameInit(PRECORDINGVIDEOFRAME pFrame, uint32_t fFlags, uint32_t uWidth, uint32_t uHeight, uint32_t uPosX, uint32_t uPosY,
169 uint8_t uBPP, RECORDINGPIXELFMT enmFmt)
170{
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 */
179void RecordingVideoFrameDestroy(PRECORDINGVIDEOFRAME pFrame)
180{
181 if (!pFrame)
182 return;
183
184 if (pFrame->pau8Buf)
185 {
186 Assert(pFrame->cbBuf);
187 RTMemFree(pFrame->pau8Buf);
188 pFrame->pau8Buf = NULL;
189 pFrame->cbBuf = 0;
190 }
191}
192
193/**
194 * Duplicates a video frame.
195 *
196 * @returns Pointer to duplicated frame on success, or NULL on failure.
197 * @param pFrame Video frame to duplicate.
198 */
199PRECORDINGVIDEOFRAME RecordingVideoFrameDup(PRECORDINGVIDEOFRAME pFrame)
200{
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);
205
206 return pFrameDup;
207}
208
209/**
210 * Clears the content of a video recording frame, inlined version.
211 *
212 * @param pFrame Video recording frame to clear content for.
213 */
214DECLINLINE(void) recordingVideoFrameClear(PRECORDINGVIDEOFRAME pFrame)
215{
216 RT_BZERO(pFrame->pau8Buf, pFrame->cbBuf);
217}
218
219/**
220 * Clears the content of a video recording frame.
221 *
222 * @param pFrame Video recording frame to clear content for.
223 */
224void RecordingVideoFrameClear(PRECORDINGVIDEOFRAME pFrame)
225{
226 recordingVideoFrameClear(pFrame);
227}
228
229/**
230 * Simple blitting function for raw image data, inlined version.
231 *
232 * @returns VBox status code.
233 * @param pu8Dst Destination buffer.
234 * @param cbDst Size (in bytes) of \a pu8Dst.
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.
249 */
250DECLINLINE(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)
254{
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++)
264 {
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);
274 }
275
276 return VINF_SUCCESS;
277}
278
279int 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
288/**
289 * Simple blitting function for raw image data with alpha channel, inlined version.
290 *
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.
304 */
305DECLINLINE(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)
308{
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 */
373int 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{
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);
382}
383
384/**
385 * Simple blitting function for raw image data with alpha channel.
386 *
387 * @returns VBox status code.
388 * @param pDstFrame Destination frame.
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 */
401int RecordingVideoFrameBlitRawAlpha(PRECORDINGVIDEOFRAME pDstFrame, uint32_t uDstX, uint32_t uDstY,
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{
405 return recordingVideoFrameBlitRawAlpha(pDstFrame, uDstX, uDstY,
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 */
424int 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{
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);
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 */
441DECLINLINE(void) recordingAudioFrameDestroy(PRECORDINGAUDIOFRAME pFrame)
442{
443 if (!pFrame)
444 return;
445
446 if (pFrame->pvBuf)
447 {
448 Assert(pFrame->cbBuf);
449 RTMemFree(pFrame->pvBuf);
450 pFrame->pvBuf = NULL;
451 pFrame->cbBuf = 0;
452 }
453}
454
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 */
460void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame)
461{
462 if (!pFrame)
463 return;
464
465 recordingAudioFrameDestroy(pFrame);
466
467 RTMemFree(pFrame);
468 pFrame = NULL;
469}
470#endif /* VBOX_WITH_AUDIO_RECORDING */
471
472/**
473 * Frees a recording frame.
474 *
475 * @param pFrame Pointer to recording frame to free.
476 * The pointer will be invalid after return.
477 */
478void RecordingFrameFree(PRECORDINGFRAME pFrame)
479{
480 if (!pFrame)
481 return;
482
483 switch (pFrame->enmType)
484 {
485#ifdef VBOX_WITH_AUDIO_RECORDING
486 case RECORDINGFRAME_TYPE_AUDIO:
487 recordingAudioFrameDestroy(&pFrame->u.Audio);
488 break;
489#endif
490 case RECORDINGFRAME_TYPE_VIDEO:
491 RecordingVideoFrameDestroy(&pFrame->u.Video);
492 break;
493
494 case RECORDINGFRAME_TYPE_CURSOR_SHAPE:
495 RecordingVideoFrameDestroy(&pFrame->u.CursorShape);
496 break;
497
498 default:
499 /* Nothing to do here. */
500 break;
501 }
502
503 RTMemFree(pFrame);
504 pFrame = NULL;
505}
506
Note: See TracBrowser for help on using the repository browser.

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