VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp@ 51092

最後變更 在這個檔案從51092是 51092,由 vboxsync 提交於 11 年 前

6813 src-client/MachineDebuggerImpl.cpp + various formatting changes

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 35.1 KB
 
1/* $Id: DrvAudioVRDE.cpp 51092 2014-04-16 17:57:25Z vboxsync $ */
2/** @file
3 *
4 * VBox Audio VRDE backend
5 */
6
7/*
8 * Copyright (C) 2006-2010 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.alldomusa.eu.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#include "DrvAudioVRDE.h"
19#include "ConsoleImpl.h"
20#include "ConsoleVRDPServer.h"
21
22#include "Logging.h"
23
24#include <VBox/vmm/pdmaudioifs.h>
25#include <VBox/vmm/pdmdrv.h>
26#include <VBox/RemoteDesktop/VRDE.h>
27#include <VBox/vmm/cfgm.h>
28#include <VBox/err.h>
29#include <iprt/mem.h>
30#include <iprt/cdefs.h>
31
32
33/*******************************************************************************
34 *
35 * IO Ring Buffer section
36 *
37 ******************************************************************************/
38
39/* Implementation of a lock free ring buffer which could be used in a multi
40 * threaded environment. Note that only the acquire, release and getter
41 * functions are threading aware. So don't use reset if the ring buffer is
42 * still in use. */
43typedef struct IORINGBUFFER
44{
45 /* The current read position in the buffer */
46 uint32_t uReadPos;
47 /* The current write position in the buffer */
48 uint32_t uWritePos;
49 /* How much space of the buffer is currently in use */
50 volatile uint32_t cBufferUsed;
51 /* How big is the buffer */
52 uint32_t cBufSize;
53 /* The buffer itself */
54 char *pBuffer;
55} IORINGBUFFER;
56/* Pointer to an ring buffer structure */
57typedef IORINGBUFFER* PIORINGBUFFER;
58
59PPDMDRVINS gpDrvIns; //@todo handle this bad programming;
60
61static void IORingBufferCreate(PIORINGBUFFER *ppBuffer, uint32_t cSize)
62{
63 PIORINGBUFFER pTmpBuffer;
64
65 AssertPtr(ppBuffer);
66
67 *ppBuffer = NULL;
68 pTmpBuffer = RTMemAllocZ(sizeof(IORINGBUFFER));
69 if (pTmpBuffer)
70 {
71 pTmpBuffer->pBuffer = RTMemAlloc(cSize);
72 if(pTmpBuffer->pBuffer)
73 {
74 pTmpBuffer->cBufSize = cSize;
75 *ppBuffer = pTmpBuffer;
76 }
77 else
78 RTMemFree(pTmpBuffer);
79 }
80}
81
82static void IORingBufferDestroy(PIORINGBUFFER pBuffer)
83{
84 if (pBuffer)
85 {
86 if (pBuffer->pBuffer)
87 RTMemFree(pBuffer->pBuffer);
88 RTMemFree(pBuffer);
89 }
90}
91
92DECL_FORCE_INLINE(void) IORingBufferReset(PIORINGBUFFER pBuffer)
93{
94 AssertPtr(pBuffer);
95
96 pBuffer->uReadPos = 0;
97 pBuffer->uWritePos = 0;
98 pBuffer->cBufferUsed = 0;
99}
100
101DECL_FORCE_INLINE(uint32_t) IORingBufferFree(PIORINGBUFFER pBuffer)
102{
103 AssertPtr(pBuffer);
104 return pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed);
105}
106
107DECL_FORCE_INLINE(uint32_t) IORingBufferUsed(PIORINGBUFFER pBuffer)
108{
109 AssertPtr(pBuffer);
110 return ASMAtomicReadU32(&pBuffer->cBufferUsed);
111}
112
113DECL_FORCE_INLINE(uint32_t) IORingBufferSize(PIORINGBUFFER pBuffer)
114{
115 AssertPtr(pBuffer);
116 return pBuffer->cBufSize;
117}
118
119static void IORingBufferAquireReadBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
120{
121 uint32_t uUsed = 0;
122 uint32_t uSize = 0;
123
124 AssertPtr(pBuffer);
125
126 *ppStart = 0;
127 *pcSize = 0;
128
129 /* How much is in use? */
130 uUsed = ASMAtomicReadU32(&pBuffer->cBufferUsed);
131 if (uUsed > 0)
132 {
133 /* Get the size out of the requested size, the read block till the end
134 * of the buffer & the currently used size. */
135 uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uReadPos, uUsed));
136 if (uSize > 0)
137 {
138 /* Return the pointer address which point to the current read
139 * position. */
140 *ppStart = pBuffer->pBuffer + pBuffer->uReadPos;
141 *pcSize = uSize;
142 }
143 }
144}
145
146DECL_FORCE_INLINE(void) IORingBufferReleaseReadBlock(PIORINGBUFFER pBuffer, uint32_t cSize)
147{
148 AssertPtr(pBuffer);
149
150 /* Split at the end of the buffer. */
151 pBuffer->uReadPos = (pBuffer->uReadPos + cSize) % pBuffer->cBufSize;
152 ASMAtomicSubU32(&pBuffer->cBufferUsed, cSize);
153}
154
155static void IORingBufferAquireWriteBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
156{
157 uint32_t uFree;
158 uint32_t uSize;
159
160 AssertPtr(pBuffer);
161
162 *ppStart = 0;
163 *pcSize = 0;
164
165 /* How much is free? */
166 uFree = pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed);
167 if (uFree > 0)
168 {
169 /* Get the size out of the requested size, the write block till the end
170 * of the buffer & the currently free size. */
171 uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uWritePos, uFree));
172 if (uSize > 0)
173 {
174 /* Return the pointer address which point to the current write
175 * position. */
176 *ppStart = pBuffer->pBuffer + pBuffer->uWritePos;
177 *pcSize = uSize;
178 }
179 }
180}
181
182DECL_FORCE_INLINE(void) IORingBufferReleaseWriteBlock(PIORINGBUFFER pBuffer, uint32_t cSize)
183{
184 AssertPtr(pBuffer);
185
186 /* Split at the end of the buffer. */
187 pBuffer->uWritePos = (pBuffer->uWritePos + cSize) % pBuffer->cBufSize;
188
189 ASMAtomicAddU32(&pBuffer->cBufferUsed, cSize);
190}
191
192/****************** Ring Buffer Function Ends *****************/
193
194//@todo need to see if they need to move to pdmifs.h
195#define AUDIO_HOST_ENDIANNESS 0
196#define VOICE_ENABLE 1
197#define VOICE_DISABLE 2
198
199
200/* Initialization status indicator used for the recreation of the AudioUnits. */
201#define CA_STATUS_UNINIT UINT32_C(0) /* The device is uninitialized */
202#define CA_STATUS_IN_INIT UINT32_C(1) /* The device is currently initializing */
203#define CA_STATUS_INIT UINT32_C(2) /* The device is initialized */
204#define CA_STATUS_IN_UNINIT UINT32_C(3) /* The device is currently uninitializing */
205
206//@todo move t_sample as a PDM interface
207//typedef struct { int mute; uint32_t r; uint32_t l; } volume_t;
208
209#define INT_MAX 0x7fffffff
210volume_t nominal_volume = {
211 0,
212 INT_MAX,
213 INT_MAX
214};
215
216/* The desired buffer length in milliseconds. Will be the target total stream
217 * latency on newer version of pulse. Apparent latency can be less (or more.)
218 * In case its need to be used. Currently its not used.
219 */
220#if 0
221static struct
222{
223 int buffer_msecs_out;
224 int buffer_msecs_in;
225} confAudioVRDE
226=
227{
228 INIT_FIELD (.buffer_msecs_out = ) 100,
229 INIT_FIELD (.buffer_msecs_in = ) 100,
230};
231#endif
232/**
233 * Audio VRDE driver instance data.
234 *
235 * @extends PDMIAUDIOSNIFFERCONNECTOR
236 */
237typedef struct DRVAUDIOVRDE
238{
239 /** Pointer to audio VRDE object */
240 AudioVRDE *pAudioVRDE;
241 PPDMDRVINS pDrvIns;
242 /** Pointer to the driver instance structure. */
243 PDMIHOSTAUDIO IHostAudioR3;
244 ConsoleVRDPServer *pConsoleVRDPServer;
245 /** Pointer to the DrvAudio port interface that is above it. */
246 PPDMIAUDIOCONNECTOR pUpPort;
247} DRVAUDIOVRDE, *PDRVAUDIOVRDE;
248typedef struct PDMHOSTVOICEOUT PDMHOSTVOICEOUT;
249typedef PDMHOSTVOICEOUT *PPDMHOSTVOICEOUT;
250
251typedef struct VRDEVoice
252{
253 /* Audio and audio details for recording */
254 PDMHOSTVOICEIN pHostVoiceIn;
255 void * pvUserCtx;
256 /* Number of bytes per frame (bitsPerSample * channels) of the actual input format. */
257 uint32_t cBytesPerFrame;
258 /* Frequency of the actual audio format. */
259 uint32_t uFrequency;
260 /* If the actual format frequence differs from the requested format, this is not NULL. */
261 void *rate;
262 /* Temporary buffer for st_sample_t representation of the input audio data. */
263 void *pvSamplesBuffer;
264 /* buffer for bytes of samples (not rate converted) */
265 uint32_t cbSamplesBufferAllocated;
266 /* Temporary buffer for frequency conversion. */
267 void *pvRateBuffer;
268 /* buffer for bytes rate converted samples */
269 uint32_t cbRateBufferAllocated;
270 /* A ring buffer for transferring data to the playback thread */
271 PIORINGBUFFER pRecordedVoiceBuf;
272 t_sample * convAudioDevFmtToStSampl;
273 uint32_t fIsInit;
274 uint32_t status;
275};
276typedef VRDEVoice *PVRDEVoice;
277
278typedef struct VRDEVoiceOut
279{
280 PDMHOSTVOICEOUT pHostVoiceOut;
281 uint64_t old_ticks;
282 uint64_t cSamplesSentPerSec;
283};
284typedef VRDEVoiceOut * PVRDEVoiceOut;
285
286/** Makes a PDRVBLOCK out of a PPDMIBLOCK. */
287#define PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface) ( (PDRVAUDIOVRDE)((uintptr_t)pInterface - RT_OFFSETOF(DRVAUDIOVRDE, IHostAudioR3)) )
288
289AudioVRDE::AudioVRDE(Console *console)
290 : mpDrv(NULL),
291 mParent(console)
292{
293}
294
295AudioVRDE::~AudioVRDE()
296{
297 if (mpDrv)
298 {
299 mpDrv->pAudioVRDE = NULL;
300 mpDrv = NULL;
301 }
302}
303
304PPDMIAUDIOCONNECTOR AudioVRDE::getDrvAudioPort()
305{
306 Assert(mpDrv);
307 return mpDrv->pUpPort;
308}
309
310void AudioVRDE::handleVRDESvrCmdAudioInputIntercept(bool fIntercept)
311{
312 LogFlow(("AudioVRDE: handleVRDPCmdInputIntercept\n"));
313}
314
315static DECLCALLBACK(void *) drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface)
316{
317 LogFlow(("drvAudioVRDEInit \n"));
318 return 1;
319}
320
321static void drvAudioVRDEPcmInitInfo(PDMPCMPROPERTIES * pProps, audsettings_t *as)
322{
323 int bits = 8, sign = 0, shift = 0;
324 LogFlow(("AudioVRDE: PcmInitInfo \n"));
325
326 switch (as->fmt) {
327 case AUD_FMT_S8:
328 sign = 1;
329 case AUD_FMT_U8:
330 break;
331
332 case AUD_FMT_S16:
333 sign = 1;
334 case AUD_FMT_U16:
335 bits = 16;
336 shift = 1;
337 break;
338
339 case AUD_FMT_S32:
340 sign = 1;
341 case AUD_FMT_U32:
342 bits = 32;
343 shift = 2;
344 break;
345 }
346
347 pProps->uFrequency = as->freq;
348 pProps->cBits = bits;
349 pProps->fSigned = sign;
350 pProps->cChannels = as->nchannels;
351 pProps->cShift = (as->nchannels == 2) + shift;
352 pProps->fAlign = (1 << pProps->cShift) - 1;
353 pProps->cbPerSec = pProps->uFrequency << pProps->cShift;
354 pProps->fSwapEndian = (as->endianness != AUDIO_HOST_ENDIANNESS);
355}
356
357/*
358 * Hard voice (playback)
359 */
360static int audio_pcm_hw_find_min_out (PPDMHOSTVOICEOUT hw, int *nb_livep)
361{
362 PPDMGSTVOICEOUT sw;
363 PPDMGSTVOICEOUT pIter;
364 int m = INT_MAX;
365 int nb_live = 0;
366 LogFlow(("Hard Voice Playback \n"));
367
368 RTListForEach(&hw->HeadGstVoiceOut, pIter, PDMGSTVOICEOUT, ListGstVoiceOut)
369 {
370 sw = pIter;
371 if (sw->State.fActive || !sw->State.fEmpty)
372 {
373 m = audio_MIN (m, sw->cSamplesMixed);
374 nb_live += 1;
375 }
376 }
377
378 *nb_livep = nb_live;
379 return m;
380}
381
382int audio_pcm_hw_get_live_out2 (PPDMHOSTVOICEOUT hw, int *nb_live)
383{
384 int smin;
385
386 smin = audio_pcm_hw_find_min_out (hw, nb_live);
387
388 if (!*nb_live) {
389 return 0;
390 }
391 else
392 {
393 int live = smin;
394
395 if (live < 0 || live > hw->cSamples)
396 {
397 LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
398 return 0;
399 }
400 return live;
401 }
402}
403
404
405int audio_pcm_hw_get_live_out (PPDMHOSTVOICEOUT hw)
406{
407 int nb_live;
408 int live;
409
410 live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
411 if (live < 0 || live > hw->cSamples)
412 {
413 LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
414 return 0;
415 }
416 return live;
417}
418
419/*
420 * Hard voice (capture)
421 */
422static int audio_pcm_hw_find_min_in (PPDMHOSTVOICEIN hw)
423{
424 PPDMGSTVOICEIN pIter;
425 int m = hw->cSamplesCaptured;
426
427 RTListForEach(&hw->HeadGstVoiceIn, pIter, PDMGSTVOICEIN, ListGstVoiceIn)
428 {
429 if (pIter->State.fActive)
430 {
431 m = audio_MIN (m, pIter->cHostSamplesAcquired);
432 }
433 }
434 return m;
435}
436
437int audio_pcm_hw_get_live_in (PPDMHOSTVOICEIN hw)
438{
439 int live = hw->cSamplesCaptured - audio_pcm_hw_find_min_in (hw);
440 if (live < 0 || live > hw->cSamples)
441 {
442 LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
443 return 0;
444 }
445 return live;
446}
447
448static inline void *advance (void *p, int incr)
449{
450 uint8_t *d = (uint8_t*)p;
451 return (d + incr);
452}
453
454uint64_t audio_get_ticks_per_sec (void)
455{
456 return PDMDrvHlpTMGetVirtualFreq (gpDrvIns);
457}
458
459uint64_t audio_get_clock (void)
460{
461 return PDMDrvHlpTMGetVirtualTime (gpDrvIns);
462}
463
464void VRDEReallocSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples)
465{
466 uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE);
467 if (cbBuffer > pVRDEVoice->cbSamplesBufferAllocated)
468 {
469 if (pVRDEVoice->pvSamplesBuffer)
470 {
471 RTMemFree(pVRDEVoice->pvSamplesBuffer);
472 pVRDEVoice->pvSamplesBuffer = NULL;
473 }
474 pVRDEVoice->pvSamplesBuffer = RTMemAlloc(cbBuffer);
475 if (pVRDEVoice->pvSamplesBuffer)
476 pVRDEVoice->cbSamplesBufferAllocated = cbBuffer;
477 else
478 pVRDEVoice->cbSamplesBufferAllocated = 0;
479 }
480
481}
482
483void VRDEReallocRateAdjSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples)
484{
485 uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE);
486 if (cbBuffer > pVRDEVoice->cbRateBufferAllocated)
487 {
488 RTMemFree(pVRDEVoice->pvRateBuffer);
489 pVRDEVoice->pvRateBuffer = RTMemAlloc(cbBuffer);
490 if (pVRDEVoice->pvRateBuffer)
491 pVRDEVoice->cbRateBufferAllocated = cbBuffer;
492 else
493 pVRDEVoice->cbRateBufferAllocated = 0;
494 }
495}
496
497/*******************************************************************************
498 *
499 * AudioVRDE input section
500 *
501 ******************************************************************************/
502
503/*
504 * Callback to feed audio input buffer. Samples format is be the same as
505 * in the voice. The caller prepares st_sample_t.
506 *
507 * @param cbSamples Size of pvSamples array in bytes.
508 * @param pvSamples Points to an array of samples.
509 *
510 * @return IPRT status code.
511 */
512static int fltRecordingCallback(PVRDEVoice pVRDEVoice, uint32_t cbSamples, const void *pvSamples)
513{
514 int rc = VINF_SUCCESS;
515 uint32_t csAvail = 0;
516 uint32_t csToWrite = 0;
517 uint32_t cbToWrite = 0;
518 uint32_t csWritten = 0;
519 char *pcDst = NULL;
520
521 LogFlow(("audio-filter: fltRecordingCallback\n"));
522
523 Assert((cbSamples % sizeof(PDMHOSTSTEREOSAMPLE)) == 0);
524
525 if (!pVRDEVoice->fIsInit)
526 return VINF_SUCCESS;
527
528 /* If nothing is pending return immediately. */
529 if (cbSamples == 0)
530 return VINF_SUCCESS;
531
532 /* How much space is free in the ring buffer? */
533 PPDMHOSTSTEREOSAMPLE psSrc;
534 csAvail = IORingBufferFree(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE); /* bytes -> samples */
535
536 /* How much space is used in the audio buffer. Use the smaller size of the too. */
537 csAvail = RT_MIN(csAvail, cbSamples / sizeof(PDMHOSTSTEREOSAMPLE));
538
539 /* Iterate as long as data is available */
540 while(csWritten < csAvail)
541 {
542 /* How much is left? */
543 csToWrite = csAvail - csWritten;
544 cbToWrite = csToWrite * sizeof(PDMHOSTSTEREOSAMPLE);
545
546 /* Try to acquire the necessary space from the ring buffer. */
547 IORingBufferAquireWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite, &pcDst, &cbToWrite);
548
549 /* How much do we get? */
550 csToWrite = cbToWrite / sizeof(PDMHOSTSTEREOSAMPLE);
551
552 /* Break if nothing is free anymore. */
553 if (RT_UNLIKELY(csToWrite == 0))
554 break;
555
556 /* Copy the data from the audio buffer to the ring buffer in PVRDEVoice. */
557 memcpy(pcDst, (uint8_t *)pvSamples + (csWritten * sizeof(PDMHOSTSTEREOSAMPLE)), cbToWrite);
558
559 /* Release the ring buffer, so the main thread could start reading this data. */
560 IORingBufferReleaseWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite);
561
562 csWritten += csToWrite;
563 }
564
565 LogFlow(("AudioVRDE: [Input] Finished writing buffer with %RU32 samples (%RU32 bytes)\n",
566 csWritten, csWritten * sizeof(PDMHOSTSTEREOSAMPLE)));
567
568 return rc;
569}
570
571
572STDMETHODIMP AudioVRDE::handleVRDESvrCmdAudioInputEventBegin(void *pvContext, int iSampleHz, int cChannels,
573 int cBits, bool fUnsigned)
574{
575 int bitIdx;
576 PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
577 LogFlow(("AudioVRDE: handleVRDPCmdInputEventBegin\n"));
578 /* Prepare a format convertion for the actually used format. */
579 pVRDEVoice->cBytesPerFrame = ((cBits + 7) / 8) * cChannels;
580 if (cBits == 16)
581 {
582 bitIdx = 1;
583 }
584 else if (cBits == 32)
585 {
586 bitIdx = 2;
587 }
588 else
589 {
590 bitIdx = 0;
591 }
592 //PPDMIAUDIOCONNECTOR pPort = server->mConsole->getAudioVRDE()->getDrvAudioPort();
593 /* Call DrvAudio interface to get the t_sample type conversion function */
594 pVRDEVoice->convAudioDevFmtToStSampl = mpDrv->pUpPort->pfnConvDevFmtToStSample(mpDrv->pUpPort,
595 (cChannels == 2) ? 1 : 0,
596 !fUnsigned, 0, bitIdx
597 );
598 if (pVRDEVoice->convAudioDevFmtToStSampl)
599 {
600 LogFlow(("AudioVRDE: Failed to get the conversion function \n"));
601 }
602 LogFlow(("AudioVRDE: Required freq as requested by VRDP Server = %d\n", iSampleHz));
603 //if (iSampleHz && iSampleHz != pVRDEVoice->pHostVoiceIn.Props.uFrequency)
604 {
605 /* @todo if the above condition is false then pVRDEVoice->uFrequency will remain 0 */
606 pVRDEVoice->rate = mpDrv->pUpPort->pfnPrepareAudioConversion(mpDrv->pUpPort, iSampleHz,
607 pVRDEVoice->pHostVoiceIn.Props.uFrequency);
608 pVRDEVoice->uFrequency = iSampleHz;
609 LogFlow(("AudioVRDE: pVRDEVoice assigned requested freq =%d\n", pVRDEVoice->uFrequency));
610 }
611 return VINF_SUCCESS;
612}
613
614/*
615 * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
616 * drvAudioVRDEDisableEnableIn VOICE_ENABLE case.
617 */
618void AudioVRDE::handleVRDESvrCmdAudioInputEventData(void *pvContext, const void *pvData, uint32_t cbData)
619{
620 PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
621 PPDMHOSTSTEREOSAMPLE pHostStereoSampleBuf; /* target sample buffer */
622 PPDMHOSTSTEREOSAMPLE pConvertedSampleBuf; /* samples adjusted for rate */
623 uint32_t cSamples = cbData / pVRDEVoice->cBytesPerFrame; /* Count of samples */
624 void * pTmpSampleBuf = NULL;
625 uint32_t cConvertedSamples; /* samples adjusted for rate */
626 uint32_t cbSamples; /* count of bytes occupied by samples */
627 uint32_t rc;
628 LogFlow(("AudioVRDE: handleVRDPCmdInputEventData cbData = %d, bytesperfram=%d\n",
629 cbData, pVRDEVoice->cBytesPerFrame));
630
631 VRDEReallocSampleBuf(pVRDEVoice, cSamples);
632 pHostStereoSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvSamplesBuffer;
633 pVRDEVoice->convAudioDevFmtToStSampl(pHostStereoSampleBuf, pvData, cSamples, &nominal_volume);
634
635 /* count of rate adjusted samples */
636 pVRDEVoice->uFrequency = 22100; /* @todo handle this. How pVRDEVoice will get proper value */
637 cConvertedSamples = (cSamples * pVRDEVoice->pHostVoiceIn.Props.uFrequency) / pVRDEVoice->uFrequency;
638 VRDEReallocRateAdjSampleBuf(pVRDEVoice, cConvertedSamples);
639
640 pConvertedSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvRateBuffer;
641
642 if (pConvertedSampleBuf)
643 {
644 uint32_t cSampleSrc = cSamples;
645 uint32_t cSampleDst = cConvertedSamples;
646 mpDrv->pUpPort->pfnDoRateConversion(mpDrv->pUpPort, pVRDEVoice->rate, pHostStereoSampleBuf,
647 pConvertedSampleBuf, &cSampleSrc, &cConvertedSamples);
648 pTmpSampleBuf = pConvertedSampleBuf;
649 cbSamples = cConvertedSamples * sizeof(PDMHOSTSTEREOSAMPLE);
650 }
651
652 if (cbSamples)
653 {
654 rc = fltRecordingCallback(pVRDEVoice, cbSamples, pTmpSampleBuf);
655 }
656}
657
658/*
659 * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
660 * drvAudioVRDEDisableEnableIn VOICE_ENABLE case.
661 */
662void AudioVRDE::handleVRDESvrCmdAudioInputEventEnd(void *pvContext)
663{
664 PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
665 LogFlow(("AudioVRDE: handleVRDPCmdInputEventEnd\n"));
666 /* The caller will not use this context anymore. */
667 if (pVRDEVoice->rate)
668 {
669 mpDrv->pUpPort->pfnEndAudioConversion(mpDrv->pUpPort, pVRDEVoice->rate);
670 }
671
672 if (pVRDEVoice->pvSamplesBuffer)
673 {
674 RTMemFree(pVRDEVoice->pvSamplesBuffer);
675 pVRDEVoice->pvSamplesBuffer = NULL;
676 }
677 if(pVRDEVoice->pvRateBuffer)
678 {
679 RTMemFree(pVRDEVoice->pvRateBuffer);
680 pVRDEVoice->pvRateBuffer = NULL;
681 }
682}
683
684static DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut, audsettings_t *as)
685{
686 PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
687 PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut;
688 LogFlow(("DrvAudioVRDEInitOut: audio input begin cShift=%d\n", pHostVoiceOut->Props.cShift));
689 pHostVoiceOut->cSamples = 6174;
690 drvAudioVRDEPcmInitInfo(&pVRDEVoiceOut->pHostVoiceOut.Props, as);
691 return VINF_SUCCESS;
692
693}
694
695static DECLCALLBACK(int) drvAudioVRDEInitIn (PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, audsettings_t *as)
696{
697 LogFlow(("DrvAudioVRDE: drvAudioVRDEInitIn \n"));
698 PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
699 PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
700 pHostVoiceIn->cSamples = 6174;
701 drvAudioVRDEPcmInitInfo(&pVRDEVoice->pHostVoiceIn.Props, as);
702 return VINF_SUCCESS;
703}
704
705static DECLCALLBACK(int) drvAudioVRDEPlayIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn)
706{
707 uint32_t cbAvlblRingBuffer = 0;
708 uint32_t cSamplesRingBuffer = 0;
709 uint32_t cSamplesToRead = 0;
710 uint32_t cSamplesRead = 0;
711 uint32_t cbToRead;
712 char *pcSrc;
713 PDMHOSTSTEREOSAMPLE * psDst;
714 //@todo take care of the size of the buffer allocated to pHostVoiceIn
715 PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
716 LogFlow(("DrvAudioVRDE: drvAudioVRDEPlayIn \n"));
717
718 /* use this from DrvHostCoreAudio.c */
719 if (ASMAtomicReadU32(&pVRDEVoice->status) != CA_STATUS_INIT)
720 {
721 LogFlow(("AudioVRDE: VRDE voice not initialized \n"));
722 return 0;
723 }
724
725 /* how much space is used in the ring buffer in pRecordedVocieBuf with pAudioVRDE . Bytes-> samples*/
726 cSamplesRingBuffer = IORingBufferUsed(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE);
727
728 /* How much space is available in the mix buffer. Use the smaller size of the too. */
729 cSamplesRingBuffer = RT_MIN(cSamplesRingBuffer, (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples -
730 audio_pcm_hw_get_live_in (&pVRDEVoice->pHostVoiceIn)));
731 LogFlow(("AudioVRDE: [Input] Start reading buffer with %d samples (%d bytes)\n", cSamplesRingBuffer,
732 cSamplesRingBuffer * sizeof(PDMHOSTSTEREOSAMPLE)));
733
734 /* Iterate as long as data is available */
735 while (cSamplesRead < cSamplesRingBuffer)
736 {
737 /* How much is left? Split request at the end of our samples buffer. */
738 cSamplesToRead = RT_MIN(cSamplesRingBuffer - cSamplesRead,
739 (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples - pVRDEVoice->pHostVoiceIn.offWrite));
740 cbToRead = cSamplesToRead * sizeof(PDMHOSTSTEREOSAMPLE);
741 LogFlow(("AudioVRDE: [Input] Try reading %RU32 samples (%RU32 bytes)\n", cSamplesToRead, cbToRead));
742
743 /* Try to acquire the necessary block from the ring buffer. Remeber in fltRecrodCallback we
744 * we are filling this buffer with the audio data available from VRDP. Here we are reading it
745 */
746 /*todo do I need to introduce a thread to fill the buffer in fltRecordcallback. So that
747 * filling is in separate thread and the reading of that buffer is in separate thread
748 */
749 IORingBufferAquireReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead, &pcSrc, &cbToRead);
750
751 /* How much to we get? */
752 cSamplesToRead = cbToRead / sizeof(PDMHOSTSTEREOSAMPLE);
753 LogFlow(("AuderVRDE: [Input] There are %d samples (%d bytes) available\n", cSamplesToRead, cbToRead));
754
755 /* Break if nothing is used anymore. */
756 if (cSamplesToRead == 0)
757 {
758 LogFlow(("AudioVRDE: Nothing to read \n"));
759 break;
760 }
761
762 /* Copy the data from our ring buffer to the mix buffer. */
763 psDst = pVRDEVoice->pHostVoiceIn.pConversionBuf + pVRDEVoice->pHostVoiceIn.offWrite;
764 memcpy(psDst, pcSrc, cbToRead);
765
766 /* Release the read buffer, so it could be used for new data. */
767 IORingBufferReleaseReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead);
768
769 pVRDEVoice->pHostVoiceIn.offWrite = (pVRDEVoice->pHostVoiceIn.offWrite + cSamplesToRead)
770 % pVRDEVoice->pHostVoiceIn.cSamples;
771
772 /* How much have we reads so far. */
773 cSamplesRead += cSamplesToRead;
774 }
775 LogFlow(("AudioVRDE: [Input] Finished reading buffer with %d samples (%d bytes)\n",
776 cSamplesRead, cSamplesRead * sizeof(PDMHOSTSTEREOSAMPLE)));
777
778 return cSamplesRead;
779}
780
781static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
782{
783 PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
784 PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut;
785 int live;
786 uint8_t *pu8Dst;
787 int cSamplesPlayed;
788 int cSamplesToSend = 0;
789 /*
790 * Just call the VRDP server with the data.
791 */
792 live = audio_pcm_hw_get_live_out (pHostVoiceOut);
793 uint64_t now = audio_get_clock();
794 uint64_t ticks = now - pVRDEVoiceOut->old_ticks;
795 uint64_t ticks_per_second = audio_get_ticks_per_sec();
796 cSamplesPlayed = (int)((2 * ticks * pHostVoiceOut->Props.uFrequency + ticks_per_second) / ticks_per_second / 2);
797 if (cSamplesPlayed < 0)
798 cSamplesPlayed = live;
799 pHostVoiceOut->Props.cBits = 128;
800 VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHostVoiceOut->Props.uFrequency,
801 pHostVoiceOut->Props.cChannels,
802 pHostVoiceOut->Props.cBits, /* bits per sample */
803 !pHostVoiceOut->Props.fSigned);
804 LogFlow(("DrvAudioVRDE: send audio sample freq=%d, chan=%d, cBits = %d, fsigned = %d, cSamples=%d format=%d \n",
805 pHostVoiceOut->Props.uFrequency, pHostVoiceOut->Props.cChannels,
806 pHostVoiceOut->Props.cBits, pHostVoiceOut->Props.fSigned,
807 pHostVoiceOut->cSamples, format)
808 );
809 pVRDEVoiceOut->old_ticks = now;
810 cSamplesToSend = RT_MIN(live, cSamplesPlayed);
811 if (pHostVoiceOut->offRead + cSamplesToSend > pHostVoiceOut->cSamples)
812 {
813 /* send the samples till the end of pHostStereoSampleBuf */
814 pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
815 (pHostVoiceOut->cSamples - pHostVoiceOut->offRead), format);
816 /*pHostStereoSampleBuff already has the samples which exceeded its space. They have overwriten the old
817 * played sampled starting from offset 0. So based on the number of samples that we had to play,
818 * read the number of samples from offset 0 .
819 */
820 pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[0],
821 (cSamplesToSend - (pHostVoiceOut->cSamples -
822 pHostVoiceOut->offRead)),
823 format);
824 }
825 else
826 {
827 pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
828 cSamplesToSend, format);
829 }
830 pHostVoiceOut->offRead = (pHostVoiceOut->offRead + cSamplesToSend) % pHostVoiceOut->cSamples;
831 return cSamplesToSend;
832}
833
834static DECLCALLBACK(void) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN hw)
835{
836 PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
837 LogFlow(("DrvAudioVRDE: drvAudioVRDEFiniIn \n"));
838 pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
839}
840
841static DECLCALLBACK(void) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
842{
843 PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
844 LogFlow(("DrvAudioVRDE: audio input end\n"));
845}
846
847static DECLCALLBACK(int) drvAudioVRDEDisableEnableOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT hw, int cmd)
848{
849 LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableOut \n"));
850 return VINF_SUCCESS;
851}
852
853static DECLCALLBACK(int) drvAudioVRDEDisableEnableIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, int cmd)
854{
855 PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
856
857 /* Initialize VRDEVoice and return to VRDP server which returns this struct back to us
858 * in the form void * pvContext
859 */
860 PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
861 LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableIn \n"));
862 /* initialize only if not already done */
863 if (cmd == VOICE_ENABLE)
864 {
865 //@todo if (!pVRDEVoice->fIsInit)
866 // IORingBufferReset(pVRDEVoice->pRecordedVoiceBuf);
867 LogFlow(("DrvAudioVRDE: Intializing the VRDE params and buffer \n"));
868 pVRDEVoice->fIsInit = 1;
869 pVRDEVoice->pHostVoiceIn = *pHostVoiceIn;
870 pVRDEVoice->cBytesPerFrame =1 ;
871 pVRDEVoice->uFrequency = 0;
872 pVRDEVoice->rate = NULL;
873 pVRDEVoice->cbSamplesBufferAllocated = 0;
874 pVRDEVoice->pvRateBuffer = NULL;
875 pVRDEVoice->cbRateBufferAllocated = 0;
876
877 pVRDEVoice->pHostVoiceIn.cSamples = 2048;
878 /* Initialize the hardware info section with the audio settings */
879
880 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_INIT);
881
882 /* Create the internal ring buffer. */
883 IORingBufferCreate(&pVRDEVoice->pRecordedVoiceBuf,
884 pVRDEVoice->pHostVoiceIn.cSamples * sizeof(PDMHOSTSTEREOSAMPLE));
885
886 if (!RT_VALID_PTR(pVRDEVoice->pRecordedVoiceBuf))
887 {
888 LogRel(("AudioVRDE: [Input] Failed to create internal ring buffer\n"));
889 return VERR_NO_MEMORY;
890 }
891
892 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_INIT);
893 return pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEVoice, pHostVoiceIn->cSamples,
894 pHostVoiceIn->Props.uFrequency,
895 pHostVoiceIn->Props.cChannels, pHostVoiceIn->Props.cBits);
896 }
897 else if (cmd == VOICE_DISABLE)
898 {
899 LogFlow(("DrvAudioVRDE: Cmd to disable VRDE \n"));
900 pVRDEVoice->fIsInit = 0;
901 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_UNINIT);
902 IORingBufferDestroy(pVRDEVoice->pRecordedVoiceBuf);
903 pVRDEVoice->pRecordedVoiceBuf = NULL;
904 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_UNINIT);
905 pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
906 }
907 return VINF_SUCCESS;
908}
909
910static DECLCALLBACK(void) drvAudioVRDEGetConf(PPDMIBASE pInterface, PPDMAUDIOCONF pAudioConf)
911{
912 LogFlow(("drvAudioVRDE: drvAudioVRDEGetConf \n"));
913 /* @todo check if szHostVoiceOut = sizeof VRDEVoice works. VRDEVoice doesn't contain HOSTVOICEOUT. */
914 pAudioConf->szHostVoiceOut = sizeof(VRDEVoice);
915 pAudioConf->szHostVoiceIn = sizeof(VRDEVoice);
916 pAudioConf->MaxHostVoicesOut = 1;
917 pAudioConf->MaxHostVoicesIn = 1;
918}
919
920/**
921 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
922 */
923static DECLCALLBACK(void *) drvAudioVRDEQueryInterface(PPDMIBASE pInterface, const char *pszIID)
924{
925 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
926 PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
927 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
928 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudioR3);
929 return NULL;
930}
931
932
933static DECLCALLBACK(void) drvAudioVRDEDestruct(PPDMDRVINS pDrvIns)
934{
935}
936
937/**
938 * Construct a DirectSound Audio driver instance.
939 *
940 * @copydoc FNPDMDRVCONSTRUCT
941 */
942DECLCALLBACK(int) AudioVRDE::drvAudioVRDEConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
943{
944 PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
945 LogRel(("drvAudioVRDEConstruct\n"));
946
947 /* we save the address of AudioVRDE in Object node in CFGM tree and address of VRDP server in
948 * ObjectVRDPServer node. So presence of both is necessary.
949 */
950 //if (!CFGMR3AreValuesValid(pCfg, "Object\0") || !CFGMR3AreValuesValid(pCfg, "ObjectVRDPServer\0"))
951 // return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
952 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
953 ("Configuration error: Not possible to attach anything to this driver!\n"),
954 VERR_PDM_DRVINS_NO_ATTACH);
955
956 /*
957 * Init the static parts.
958 */
959 pThis->pDrvIns = pDrvIns;
960 gpDrvIns = pDrvIns;
961 /* IBase */
962 pDrvIns->IBase.pfnQueryInterface = drvAudioVRDEQueryInterface;
963 pThis->IHostAudioR3.pfnInitIn = drvAudioVRDEInitIn;
964 pThis->IHostAudioR3.pfnInitOut = drvAudioVRDEInitOut;
965 pThis->IHostAudioR3.pfnDisableEnableOut = drvAudioVRDEDisableEnableOut;
966 pThis->IHostAudioR3.pfnDisableEnableIn = drvAudioVRDEDisableEnableIn;
967 pThis->IHostAudioR3.pfnFiniIn = drvAudioVRDEFiniIn;
968 pThis->IHostAudioR3.pfnFiniOut = drvAudioVRDEFiniOut;
969 pThis->IHostAudioR3.pfnPlayIn = drvAudioVRDEPlayIn;
970 pThis->IHostAudioR3.pfnPlayOut = drvAudioVRDEPlayOut;
971 pThis->IHostAudioR3.pfnGetConf = drvAudioVRDEGetConf;
972 pThis->IHostAudioR3.pfnInit = drvAudioVRDEInit;
973
974 /* Get VRDPServer pointer */
975 void *pv;
976 int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pv);
977 if (RT_FAILURE(rc))
978 {
979 AssertMsgFailed(("DrvAudioVRDE Confguration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
980 return rc;
981 }
982 /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE */
983 pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pv;
984 pv = NULL;
985
986 rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
987 if (RT_FAILURE(rc))
988 {
989 AssertMsgFailed(("DrvAudioVRDE Confguration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
990 return rc;
991 }
992 pThis->pAudioVRDE = (AudioVRDE *)pv;
993 pThis->pAudioVRDE->mpDrv = pThis;
994 /*
995 * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls .
996 * Described in CFGM tree.
997 */
998 pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
999 if (!pThis->pUpPort)
1000 {
1001 AssertMsgFailed(("Configuration error: No Audio Sniffer port interface above!\n"));
1002 return VERR_PDM_MISSING_INTERFACE_ABOVE;
1003 }
1004
1005 return VINF_SUCCESS;
1006}
1007
1008
1009/**
1010 * Char driver registration record.
1011 */
1012const PDMDRVREG g_DrvAudioVRDE =
1013{
1014 PDM_DRVREG_VERSION,
1015 /* szName */
1016 "AudioVRDE",
1017 /* szRCMod */
1018 "",
1019 /* szR0Mod */
1020 "",
1021 /* pszDescription */
1022 "Audio VRDE",
1023 /* fFlags */
1024 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
1025 /* fClass. */
1026 PDM_DRVREG_CLASS_AUDIO,
1027 /* cMaxInstances */
1028 ~0U,
1029 /* cbInstance */
1030 sizeof(DRVAUDIOVRDE),
1031 /* pfnConstruct */
1032 AudioVRDE::drvAudioVRDEConstruct,
1033 /* pfnDestruct */
1034 drvAudioVRDEDestruct,
1035 /* pfnRelocate */
1036 NULL,
1037 /* pfnIOCtl */
1038 NULL,
1039 /* pfnPowerOn */
1040 NULL,
1041 /* pfnReset */
1042 NULL,
1043 /* pfnSuspend */
1044 NULL,
1045 /* pfnResume */
1046 NULL,
1047 /* pfnAttach */
1048 NULL,
1049 /* pfnDetach */
1050 NULL,
1051 /* pfnPowerOff */
1052 NULL,
1053 /* pfnSoftReset */
1054 NULL,
1055 /* u32EndVersion */
1056 PDM_DRVREG_VERSION
1057};
1058
1059
1060
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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