mfreerdp-server: rdpsnd basic functionality
This commit is contained in:
parent
cd4ba385df
commit
d9968bae7f
@ -18,6 +18,8 @@
|
||||
set(MODULE_NAME "mfreerdp-server")
|
||||
set(MODULE_PREFIX "FREERDP_SERVER_MAC")
|
||||
|
||||
FIND_LIBRARY(AUDIO_TOOL AudioToolbox)
|
||||
FIND_LIBRARY(CORE_AUDIO CoreAudio)
|
||||
FIND_LIBRARY(CORE_VIDEO CoreVideo)
|
||||
FIND_LIBRARY(CORE_GRAPHICS CoreGraphics)
|
||||
FIND_LIBRARY(APP_SERVICES ApplicationServices)
|
||||
@ -55,7 +57,9 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||
freerdp-server
|
||||
${CORE_VIDEO}
|
||||
${AUDIO_TOOL}
|
||||
${CORE_AUDIO}
|
||||
${CORE_VIDEO}
|
||||
${CORE_GRAPHICS}
|
||||
${APP_SERVICES}
|
||||
${IOKIT}
|
||||
|
@ -23,8 +23,11 @@
|
||||
|
||||
#include <freerdp/server/audin.h>
|
||||
|
||||
#include "mf_info.h"
|
||||
#include "mf_rdpsnd.h"
|
||||
|
||||
AQRecorderState recorderState;
|
||||
|
||||
static const rdpsndFormat audio_formats[] =
|
||||
{
|
||||
{ 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */
|
||||
@ -42,11 +45,82 @@ static const rdpsndFormat audio_formats[] =
|
||||
static void mf_peer_rdpsnd_activated(rdpsnd_server_context* context)
|
||||
{
|
||||
printf("RDPSND Activated\n");
|
||||
|
||||
|
||||
|
||||
printf("Let's create an audio queue for input!\n");
|
||||
|
||||
OSStatus status;
|
||||
|
||||
recorderState.dataFormat.mSampleRate = 44100.0;
|
||||
recorderState.dataFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
recorderState.dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||
recorderState.dataFormat.mBytesPerPacket = 4;
|
||||
recorderState.dataFormat.mFramesPerPacket = 1;
|
||||
recorderState.dataFormat.mBytesPerFrame = 4;
|
||||
recorderState.dataFormat.mChannelsPerFrame = 2;
|
||||
recorderState.dataFormat.mBitsPerChannel = 16;
|
||||
|
||||
recorderState.snd_context = context;
|
||||
|
||||
status = AudioQueueNewInput(&recorderState.dataFormat,
|
||||
mf_peer_rdpsnd_input_callback,
|
||||
&recorderState,
|
||||
NULL,
|
||||
kCFRunLoopCommonModes,
|
||||
0,
|
||||
&recorderState.queue);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
printf("Failed to create a new Audio Queue. Status code: %d\n", status);
|
||||
}
|
||||
|
||||
|
||||
UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
|
||||
|
||||
AudioQueueGetProperty(recorderState.queue,
|
||||
kAudioConverterCurrentInputStreamDescription,
|
||||
&recorderState.dataFormat,
|
||||
&dataFormatSize);
|
||||
|
||||
|
||||
mf_rdpsnd_derive_buffer_size(recorderState.queue, &recorderState.dataFormat, 0.5, &recorderState.bufferByteSize);
|
||||
|
||||
|
||||
printf("Preparing a set of buffers...");
|
||||
|
||||
for (int i = 0; i < snd_numBuffers; ++i)
|
||||
{
|
||||
AudioQueueAllocateBuffer(recorderState.queue,
|
||||
recorderState.bufferByteSize,
|
||||
&recorderState.buffers[i]);
|
||||
|
||||
AudioQueueEnqueueBuffer(recorderState.queue,
|
||||
recorderState.buffers[i],
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
printf("done\n");
|
||||
|
||||
printf("recording...\n");
|
||||
|
||||
|
||||
|
||||
recorderState.currentPacket = 0;
|
||||
recorderState.isRunning = true;
|
||||
|
||||
context->SelectFormat(context, 4);
|
||||
context->SetVolume(context, 0x7FFF, 0x7FFF);
|
||||
|
||||
AudioQueueStart (recorderState.queue, NULL);
|
||||
|
||||
}
|
||||
|
||||
BOOL mf_peer_rdpsnd_init(mfPeerContext* context)
|
||||
{
|
||||
printf("RDPSND INIT\n");
|
||||
//printf("RDPSND INIT\n");
|
||||
context->rdpsnd = rdpsnd_server_context_new(context->vcm);
|
||||
context->rdpsnd->data = context;
|
||||
|
||||
@ -64,3 +138,84 @@ BOOL mf_peer_rdpsnd_init(mfPeerContext* context)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void mf_peer_rdpsnd_input_callback (void *inUserData,
|
||||
AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer,
|
||||
const AudioTimeStamp *inStartTime,
|
||||
UInt32 inNumberPacketDescriptions,
|
||||
const AudioStreamPacketDescription *inPacketDescs)
|
||||
{
|
||||
OSStatus status;
|
||||
AQRecorderState * rState;
|
||||
rState = inUserData;
|
||||
|
||||
|
||||
if (inNumberPacketDescriptions == 0 && rState->dataFormat.mBytesPerPacket != 0)
|
||||
{
|
||||
inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / rState->dataFormat.mBytesPerPacket;
|
||||
}
|
||||
|
||||
/*write to disc
|
||||
|
||||
status = AudioFileWritePackets(
|
||||
rState->audioFile,
|
||||
false,
|
||||
rState->bufferByteSize,
|
||||
NULL,
|
||||
rState->currentPacket,
|
||||
&inNumberPacketDescriptions,
|
||||
inBuffer->mAudioData);
|
||||
|
||||
if (status == noErr) {
|
||||
rState->currentPacket += inNumberPacketDescriptions;
|
||||
}
|
||||
*/
|
||||
|
||||
//rState->snd_context->SendSamples(rState->snd_context, inBuffer->mAudioData, rState->bufferByteSize/4);
|
||||
|
||||
rState->snd_context->SendSamples(rState->snd_context, inBuffer->mAudioData, inBuffer->mAudioDataByteSize/4);
|
||||
|
||||
if (rState->isRunning == 0)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
status = AudioQueueEnqueueBuffer(
|
||||
rState->queue,
|
||||
inBuffer,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
printf("AudioQueueEnqueueBuffer() returned status = %d\n", status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue,
|
||||
AudioStreamBasicDescription *ASBDescription,
|
||||
Float64 seconds,
|
||||
UInt32 *outBufferSize)
|
||||
{
|
||||
static const int maxBufferSize = 0x50000;
|
||||
|
||||
int maxPacketSize = ASBDescription->mBytesPerPacket;
|
||||
if (maxPacketSize == 0)
|
||||
{
|
||||
UInt32 maxVBRPacketSize = sizeof(maxPacketSize);
|
||||
AudioQueueGetProperty (audioQueue,
|
||||
kAudioQueueProperty_MaximumOutputPacketSize,
|
||||
// in Mac OS X v10.5, instead use
|
||||
// kAudioConverterPropertyMaximumOutputPacketSize
|
||||
&maxPacketSize,
|
||||
&maxVBRPacketSize
|
||||
);
|
||||
}
|
||||
|
||||
Float64 numBytesForTime =
|
||||
ASBDescription->mSampleRate * maxPacketSize * seconds;
|
||||
*outBufferSize = (UInt32) (numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
#ifndef MF_RDPSND_H
|
||||
#define MF_RDPSND_H
|
||||
|
||||
#include <CoreAudio/CoreAudio.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/listener.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
@ -27,7 +30,35 @@
|
||||
#include "mf_interface.h"
|
||||
#include "mfreerdp.h"
|
||||
|
||||
void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue,
|
||||
AudioStreamBasicDescription *ASBDescription,
|
||||
Float64 seconds,
|
||||
UInt32 *outBufferSize);
|
||||
|
||||
void mf_peer_rdpsnd_input_callback (void *inUserData,
|
||||
AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer,
|
||||
const AudioTimeStamp *inStartTime,
|
||||
UInt32 inNumberPacketDescriptions,
|
||||
const AudioStreamPacketDescription *inPacketDescs);
|
||||
|
||||
BOOL mf_peer_rdpsnd_init(mfPeerContext* context);
|
||||
|
||||
static const int snd_numBuffers = 3;
|
||||
struct _AQRecorderState
|
||||
{
|
||||
AudioStreamBasicDescription dataFormat;
|
||||
AudioQueueRef queue;
|
||||
AudioQueueBufferRef buffers[snd_numBuffers];
|
||||
AudioFileID audioFile;
|
||||
UInt32 bufferByteSize;
|
||||
SInt64 currentPacket;
|
||||
bool isRunning;
|
||||
rdpsnd_server_context* snd_context;
|
||||
|
||||
};
|
||||
|
||||
typedef struct _AQRecorderState AQRecorderState;
|
||||
|
||||
#endif /* MF_RDPSND_H */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user