mfreerdp-server: rdpsnd basic functionality

This commit is contained in:
C-o-r-E 2013-01-24 19:21:56 -05:00
parent cd4ba385df
commit d9968bae7f
3 changed files with 192 additions and 2 deletions

View File

@ -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}

View File

@ -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);
}

View File

@ -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 */