VirtualBox

source: vbox/trunk/src/VBox/Main/include/RecordingInternals.h@ 96237

Last change on this file since 96237 was 96229, checked in by vboxsync, 3 years ago

Recording/Main: Decoupled the WebM writer class from codec dependencies. Various bugfixes. bugref:10275

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.9 KB
Line 
1/* $Id: RecordingInternals.h 96229 2022-08-16 15:41:39Z vboxsync $ */
2/** @file
3 * Recording internals header.
4 */
5
6/*
7 * Copyright (C) 2012-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef MAIN_INCLUDED_RecordingInternals_h
19#define MAIN_INCLUDED_RecordingInternals_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include <list>
25
26#include <iprt/assert.h>
27#include <iprt/types.h> /* drag in stdint.h before vpx does it. */
28
29#include "VBox/com/string.h"
30#include "VBox/com/VirtualBox.h"
31#include "VBox/settings.h"
32#include <VBox/vmm/pdmaudioifs.h>
33
34#ifdef VBOX_WITH_LIBVPX
35# define VPX_CODEC_DISABLE_COMPAT 1
36# include "vpx/vp8cx.h"
37# include "vpx/vpx_image.h"
38# include "vpx/vpx_encoder.h"
39#endif /* VBOX_WITH_LIBVPX */
40
41#ifdef VBOX_WITH_LIBOPUS
42# include <opus.h>
43#endif
44
45#ifdef VBOX_WITH_LIBVORBIS
46# include "vorbis/vorbisenc.h"
47#endif
48
49
50/*********************************************************************************************************************************
51* Defines *
52*********************************************************************************************************************************/
53#define VBOX_RECORDING_OPUS_HZ_MAX 48000 /**< Maximum sample rate (in Hz) Opus can handle. */
54#define VBOX_RECORDING_OPUS_FRAME_MS_DEFAULT 20 /**< Default Opus frame size (in ms). */
55
56#define VBOX_RECORDING_VORBIS_HZ_MAX 48000 /**< Maximum sample rate (in Hz) Vorbis can handle. */
57#define VBOX_RECORDING_VORBIS_FRAME_MS_DEFAULT 20 /**< Default Vorbis frame size (in ms). */
58
59
60/*********************************************************************************************************************************
61* Prototypes *
62*********************************************************************************************************************************/
63struct RECORDINGCODEC;
64typedef RECORDINGCODEC *PRECORDINGCODEC;
65
66struct RECORDINGFRAME;
67typedef RECORDINGFRAME *PRECORDINGFRAME;
68
69
70/*********************************************************************************************************************************
71* Internal structures, defines and APIs *
72*********************************************************************************************************************************/
73
74/**
75 * Enumeration for specifying a (generic) codec type.
76 */
77typedef enum RECORDINGCODECTYPE
78{
79 /** Invalid codec type. Do not use. */
80 RECORDINGCODECTYPE_INVALID = 0,
81 /** Video codec. */
82 RECORDINGCODECTYPE_VIDEO,
83 /** Audio codec. */
84 RECORDINGCODECTYPE_AUDIO
85} RECORDINGCODECTYPE;
86
87/**
88 * Structure for keeping a codec operations table.
89 */
90typedef struct RECORDINGCODECOPS
91{
92 /**
93 * Initializes a codec.
94 *
95 * @returns VBox status code.
96 * @param pCodec Codec instance to initialize.
97 */
98 DECLCALLBACKMEMBER(int, pfnInit, (PRECORDINGCODEC pCodec));
99
100 /**
101 * Destroys a codec.
102 *
103 * @returns VBox status code.
104 * @param pCodec Codec instance to destroy.
105 */
106 DECLCALLBACKMEMBER(int, pfnDestroy, (PRECORDINGCODEC pCodec));
107
108 /**
109 * Parses an options string to configure advanced / hidden / experimental features of a recording stream.
110 * Unknown values will be skipped. Optional.
111 *
112 * @returns VBox status code.
113 * @param pCodec Codec instance to parse options for.
114 * @param strOptions Options string to parse.
115 */
116 DECLCALLBACKMEMBER(int, pfnParseOptions, (PRECORDINGCODEC pCodec, const com::Utf8Str &strOptions));
117
118 /**
119 * Feeds the codec encoder with data to encode.
120 *
121 * @returns VBox status code.
122 * @param pCodec Codec instance to use.
123 * @param pFrame Pointer to frame data to encode.
124 * @param pcEncoded Where to return the number of encoded blocks in \a pvDst on success. Optional.
125 * @param pcbEncoded Where to return the number of encoded bytes in \a pvDst on success. Optional.
126 */
127 DECLCALLBACKMEMBER(int, pfnEncode, (PRECORDINGCODEC pCodec, const PRECORDINGFRAME pFrame, size_t *pcEncoded, size_t *pcbEncoded));
128
129 /**
130 * Tells the codec to finalize the current stream. Optional.
131 *
132 * @returns VBox status code.
133 * @param pCodec Codec instance to finalize stream for.
134 */
135 DECLCALLBACKMEMBER(int, pfnFinalize, (PRECORDINGCODEC pCodec));
136} RECORDINGCODECOPS, *PRECORDINGCODECOPS;
137
138/** No encoding flags set. */
139#define RECORDINGCODEC_ENC_F_NONE UINT32_C(0)
140/** Data block is a key block. */
141#define RECORDINGCODEC_ENC_F_BLOCK_IS_KEY RT_BIT_32(0)
142/** Data block is invisible. */
143#define RECORDINGCODEC_ENC_F_BLOCK_IS_INVISIBLE RT_BIT_32(1)
144/** Encoding flags valid mask. */
145#define RECORDINGCODEC_ENC_F_VALID_MASK 0x1
146
147/**
148 * Structure for keeping a codec callback table.
149 */
150typedef struct RECORDINGCODECCALLBACKS
151{
152 /**
153 * Callback for notifying that encoded data has been written.
154 *
155 * @returns VBox status code.
156 * @param pCodec Pointer to codec instance which has written the data.
157 * @param pvData Pointer to written data (encoded).
158 * @param cbData Size (in bytes) of \a pvData.
159 * @param msAbsPTS Absolute PTS (in ms) of the written data.
160 * @param uFlags Encoding flags of type RECORDINGCODEC_ENC_F_XXX.
161 * @param pvUser User-supplied pointer.
162 */
163 DECLCALLBACKMEMBER(int, pfnWriteData, (PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags, void *pvUser));
164 /** User-supplied data pointer. */
165 void *pvUser;
166} RECORDINGCODECCALLBACKS, *PRECORDINGCODECCALLBACKS;
167
168/**
169 * Structure for keeping generic codec parameters.
170 */
171typedef struct RECORDINGCODECPARMS
172{
173 /** The generic codec type. */
174 RECORDINGCODECTYPE enmType;
175 /** The specific codec type, based on \a enmType. */
176 union
177 {
178 /** The container's video codec to use. */
179 RecordingVideoCodec_T enmVideoCodec;
180 /** The container's audio codec to use. */
181 RecordingAudioCodec_T enmAudioCodec;
182 };
183 union
184 {
185 struct
186 {
187 /** Frames per second. */
188 uint8_t uFPS;
189 /** Target width (in pixels) of encoded video image. */
190 uint16_t uWidth;
191 /** Target height (in pixels) of encoded video image. */
192 uint16_t uHeight;
193 /** Minimal delay (in ms) between two video frames.
194 * This value is based on the configured FPS rate. */
195 uint32_t uDelayMs;
196 } Video;
197 struct
198 {
199 /** The codec's used PCM properties. */
200 PDMAUDIOPCMPROPS PCMProps;
201 } Audio;
202 };
203 /** Desired (average) bitrate (in kbps) to use, for codecs which support bitrate management.
204 * Set to 0 to use a variable bit rate (VBR) (if available, otherwise fall back to CBR). */
205 uint32_t uBitrate;
206 /** Time (in ms) the encoder expects us to send data to encode.
207 *
208 * For Opus, valid frame sizes are:
209 * ms Frame size
210 * 2.5 120
211 * 5 240
212 * 10 480
213 * 20 (Default) 960
214 * 40 1920
215 * 60 2880
216 *
217 * For Vorbis, valid frame sizes are powers of two from 64 to 8192 bytes.
218 */
219 uint32_t msFrame;
220 /** The frame size in bytes (based on \a msFrame). */
221 uint32_t cbFrame;
222 /** The frame size in samples per frame (based on \a msFrame). */
223 uint32_t csFrame;
224} RECORDINGCODECPARMS, *PRECORDINGCODECPARMS;
225
226#ifdef VBOX_WITH_LIBVPX
227/**
228 * VPX encoder state (needs libvpx).
229 */
230typedef struct RECORDINGCODECVPX
231{
232 /** VPX codec context. */
233 vpx_codec_ctx_t Ctx;
234 /** VPX codec configuration. */
235 vpx_codec_enc_cfg_t Cfg;
236 /** VPX image context. */
237 vpx_image_t RawImage;
238 /** Pointer to the codec's internal YUV buffer. */
239 uint8_t *pu8YuvBuf;
240 /** The encoder's deadline (in ms).
241 * The more time the encoder is allowed to spend encoding, the better the encoded
242 * result, in exchange for higher CPU usage and time spent encoding. */
243 unsigned int uEncoderDeadline;
244} RECORDINGCODECVPX;
245/** Pointer to a VPX encoder state. */
246typedef RECORDINGCODECVPX *PRECORDINGCODECVPX;
247#endif /* VBOX_WITH_LIBVPX */
248
249#ifdef VBOX_WITH_LIBOPUS
250/**
251 * Opus encoder state (needs libvorbis).
252 */
253typedef struct RECORDINGCODECOPUS
254{
255 /** Encoder we're going to use. */
256 OpusEncoder *pEnc;
257} RECORDINGCODECOPUS;
258/** Pointer to an Opus encoder state. */
259typedef RECORDINGCODECOPUS *PRECORDINGCODECOPUS;
260#endif /* VBOX_WITH_LIBOPUS */
261
262#ifdef VBOX_WITH_LIBVORBIS
263/**
264 * Vorbis encoder state (needs libvorbis + libogg).
265 */
266typedef struct RECORDINGCODECVORBIS
267{
268 /** Basic information about the audio in a Vorbis bitstream. */
269 vorbis_info info;
270 /** Encoder state. */
271 vorbis_dsp_state dsp_state;
272 /** Current block being worked on. */
273 vorbis_block block_cur;
274} RECORDINGCODECVORBIS;
275/** Pointer to a Vorbis encoder state. */
276typedef RECORDINGCODECVORBIS *PRECORDINGCODECVORBIS;
277#endif /* VBOX_WITH_LIBVORBIS */
278
279/**
280 * Structure for keeping a codec's internal state.
281 */
282typedef struct RECORDINGCODECSTATE
283{
284 /** Timestamp (in ms, absolute) of the last frame was encoded. */
285 uint64_t tsLastWrittenMs;
286 /** Number of encoding errors. */
287 uint64_t cEncErrors;
288} RECORDINGCODECSTATE;
289/** Pointer to an internal encoder state. */
290typedef RECORDINGCODECSTATE *PRECORDINGCODECSTATE;
291
292/**
293 * Structure for keeping codec-specific data.
294 */
295typedef struct RECORDINGCODEC
296{
297 /** Callback table for codec operations. */
298 RECORDINGCODECOPS Ops;
299 /** Table for user-supplied callbacks. */
300 RECORDINGCODECCALLBACKS Callbacks;
301 /** Generic codec parameters. */
302 RECORDINGCODECPARMS Parms;
303 /** Generic codec parameters. */
304 RECORDINGCODECSTATE State;
305
306#ifdef VBOX_WITH_LIBVPX
307 union
308 {
309 RECORDINGCODECVPX VPX;
310 } Video;
311#endif
312
313#ifdef VBOX_WITH_AUDIO_RECORDING
314 union
315 {
316# ifdef VBOX_WITH_LIBOPUS
317 RECORDINGCODECOPUS Opus;
318# endif /* VBOX_WITH_LIBOPUS */
319# ifdef VBOX_WITH_LIBVORBIS
320 RECORDINGCODECVORBIS Vorbis;
321# endif /* VBOX_WITH_LIBVORBIS */
322 } Audio;
323#endif /* VBOX_WITH_AUDIO_RECORDING */
324
325 /** Internal scratch buffer for en-/decoding steps. */
326 void *pvScratch;
327 /** Size (in bytes) of \a pvScratch. */
328 uint32_t cbScratch;
329
330#ifdef VBOX_WITH_STATISTICS /** @todo Register these values with STAM. */
331 struct
332 {
333 /** Number of frames encoded. */
334 uint64_t cEncBlocks;
335 /** Total time (in ms) of already encoded audio data. */
336 uint64_t msEncTotal;
337 } STAM;
338#endif
339} RECORDINGCODEC, *PRECORDINGCODEC;
340
341/**
342 * Enumeration for supported pixel formats.
343 */
344enum RECORDINGPIXELFMT
345{
346 /** Unknown pixel format. */
347 RECORDINGPIXELFMT_UNKNOWN = 0,
348 /** RGB 24. */
349 RECORDINGPIXELFMT_RGB24 = 1,
350 /** RGB 24. */
351 RECORDINGPIXELFMT_RGB32 = 2,
352 /** RGB 565. */
353 RECORDINGPIXELFMT_RGB565 = 3,
354 /** The usual 32-bit hack. */
355 RECORDINGPIXELFMT_32BIT_HACK = 0x7fffffff
356};
357
358/**
359 * Structure for keeping a single recording video frame.
360 */
361typedef struct RECORDINGVIDEOFRAME
362{
363 /** X resolution of this frame. */
364 uint32_t uWidth;
365 /** Y resolution of this frame. */
366 uint32_t uHeight;
367 /** Pixel format of this frame. */
368 uint32_t uPixelFormat;
369 /** RGB buffer containing the unmodified frame buffer data from Main's display. */
370 uint8_t *pu8RGBBuf;
371 /** Size (in bytes) of the RGB buffer. */
372 size_t cbRGBBuf;
373} RECORDINGVIDEOFRAME, *PRECORDINGVIDEOFRAME;
374
375#ifdef VBOX_WITH_AUDIO_RECORDING
376/**
377 * Structure for keeping a single recording audio frame.
378 */
379typedef struct RECORDINGAUDIOFRAME
380{
381 /** Pointer to audio data. */
382 uint8_t *pvBuf;
383 /** Size (in bytes) of audio data. */
384 size_t cbBuf;
385} RECORDINGAUDIOFRAME, *PRECORDINGAUDIOFRAME;
386#endif /* VBOX_WITH_AUDIO_RECORDING */
387
388/**
389 * Structure for keeping a single recording audio frame.
390 */
391typedef struct RECORDINGFRAME
392{
393 uint64_t msTimestamp;
394 union
395 {
396#ifdef VBOX_WITH_AUDIO_RECORDING
397 RECORDINGAUDIOFRAME Audio;
398#endif
399 RECORDINGVIDEOFRAME Video;
400 RECORDINGVIDEOFRAME *VideoPtr;
401 };
402} RECORDINGFRAME, *PRECORDINGFRAME;
403
404/**
405 * Enumeration for specifying a video recording block type.
406 */
407typedef enum RECORDINGBLOCKTYPE
408{
409 /** Uknown block type, do not use. */
410 RECORDINGBLOCKTYPE_UNKNOWN = 0,
411 /** The block is a video frame. */
412 RECORDINGBLOCKTYPE_VIDEO,
413#ifdef VBOX_WITH_AUDIO_RECORDING
414 /** The block is an audio frame. */
415 RECORDINGBLOCKTYPE_AUDIO
416#endif
417} RECORDINGBLOCKTYPE;
418
419#ifdef VBOX_WITH_AUDIO_RECORDING
420void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame);
421#endif
422void RecordingVideoFrameFree(PRECORDINGVIDEOFRAME pFrame);
423
424/**
425 * Generic structure for keeping a single video recording (data) block.
426 */
427struct RecordingBlock
428{
429 RecordingBlock()
430 : enmType(RECORDINGBLOCKTYPE_UNKNOWN)
431 , cRefs(0)
432 , uFlags(RECORDINGCODEC_ENC_F_NONE)
433 , pvData(NULL)
434 , cbData(0) { }
435
436 virtual ~RecordingBlock()
437 {
438 Reset();
439 }
440
441 void Reset(void)
442 {
443 switch (enmType)
444 {
445 case RECORDINGBLOCKTYPE_UNKNOWN:
446 break;
447
448 case RECORDINGBLOCKTYPE_VIDEO:
449 RecordingVideoFrameFree((PRECORDINGVIDEOFRAME)pvData);
450 break;
451
452#ifdef VBOX_WITH_AUDIO_RECORDING
453 case RECORDINGBLOCKTYPE_AUDIO:
454 RecordingAudioFrameFree((PRECORDINGAUDIOFRAME)pvData);
455 break;
456#endif
457 default:
458 AssertFailed();
459 break;
460 }
461
462 enmType = RECORDINGBLOCKTYPE_UNKNOWN;
463 cRefs = 0;
464 pvData = NULL;
465 cbData = 0;
466 }
467
468 /** The block's type. */
469 RECORDINGBLOCKTYPE enmType;
470 /** Number of references held of this block. */
471 uint16_t cRefs;
472 /** Block flags of type RECORDINGCODEC_ENC_F_XXX. */
473 uint64_t uFlags;
474 /** The (absolute) timestamp (in ms, PTS) of this block. */
475 uint64_t msTimestamp;
476 /** Opaque data block to the actual block data, depending on the block's type. */
477 void *pvData;
478 /** Size (in bytes) of the (opaque) data block. */
479 size_t cbData;
480};
481
482/** List for keeping video recording (data) blocks. */
483typedef std::list<RecordingBlock *> RecordingBlockList;
484
485int recordingCodecCreateAudio(PRECORDINGCODEC pCodec, RecordingAudioCodec_T enmAudioCodec);
486int recordingCodecCreateVideo(PRECORDINGCODEC pCodec, RecordingVideoCodec_T enmVideoCodec);
487int recordingCodecInit(const PRECORDINGCODEC pCodec, const PRECORDINGCODECCALLBACKS pCallbacks, const settings::RecordingScreenSettings &Settings);
488int recordingCodecDestroy(PRECORDINGCODEC pCodec);
489int recordingCodecEncode(PRECORDINGCODEC pCodec, const PRECORDINGFRAME pFrame, size_t *pcEncoded, size_t *pcbEncoded);
490int recordingCodecFinalize(PRECORDINGCODEC pCodec);
491#endif /* !MAIN_INCLUDED_RecordingInternals_h */
492
Note: See TracBrowser for help on using the repository browser.

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