Commit 55679b23 authored by Ghislain MARY's avatar Ghislain MARY

Import changes made to the code while it was located in mediastreamer2.

parent 22339edb
......@@ -45,7 +45,7 @@ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
*****************************************************************************/
static void ms_wasapi_read_init(MSFilter *f) {
MSWASAPIReaderPtr r = MSWASAPIReaderNew();
MSWASAPIReaderPtr r = MSWASAPIReaderNew(f);
f->data = r;
}
......@@ -495,6 +495,7 @@ static MSSndCard *ms_wasapi_snd_card_new(LPWSTR id, const char *name, uint8_t ca
WasapiSndCard *wasapicard = static_cast<WasapiSndCard *>(card->data);
card->name = ms_strdup(name);
card->capabilities = capabilities;
card->latency = (capabilities & MS_SND_CARD_CAP_CAPTURE) ? 70 : 0;
wasapicard->id_vector = new std::vector<wchar_t>(wcslen(id) + 1);
wcscpy_s(&wasapicard->id_vector->front(), wasapicard->id_vector->size(), id);
wasapicard->id = &wasapicard->id_vector->front();
......@@ -513,7 +514,7 @@ static void add_or_update_card(MSSndCardManager *m, bctbx_list_t **l, LPWSTR id,
inputlen = wcslen(wname);
returnlen = inputlen * 2;
name = (char *)ms_malloc(returnlen);
if ((err = WideCharToMultiByte(CP_UTF8, 0, wname, -1, name, (int)returnlen, NULL, NULL)) == 0) {
if ((err = WideCharToMultiByte(CP_ACP, 0, wname, -1, name, (int)returnlen, NULL, NULL)) == 0) {
ms_error("mswasapi: Cannot convert card name to multi-byte string.");
return;
}
......@@ -632,7 +633,7 @@ static MSFilter *ms_wasapi_snd_card_create_writer(MSSndCard *card) {
MSFilter *f = ms_factory_create_filter_from_desc(ms_snd_card_get_factory(card), &ms_wasapi_write_desc);
WasapiSndCard *wasapicard = static_cast<WasapiSndCard *>(card->data);
MSWASAPIWriterType writer = MSWASAPI_WRITER(f->data);
writer->init(wasapicard->id);
writer->init(wasapicard->id, f);
return f;
}
......
......@@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#pragma once
#include <mediastreamer2/mscommon.h>
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/mssndcard.h>
#include <vector>
#include <objbase.h>
......@@ -75,3 +77,7 @@ extern const IID IID_ISimpleAudioVolume;
extern const CLSID CLSID_MMDeviceEnumerator;
extern const IID IID_IMMDeviceEnumerator;
#endif
extern "C" MSFilterDesc ms_wasapi_read_desc;
extern "C" MSFilterDesc ms_wasapi_write_desc;
extern "C" MSSndCardDesc ms_wasapi_snd_card_desc;
......@@ -48,9 +48,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
bool MSWASAPIReader::smInstantiated = false;
MSWASAPIReader::MSWASAPIReader()
: mAudioClient(NULL), mAudioCaptureClient(NULL), mVolumeControler(NULL), mBufferFrameCount(0), mIsInitialized(false), mIsActivated(false), mIsStarted(false)
MSWASAPIReader::MSWASAPIReader(MSFilter *filter)
: mAudioClient(NULL), mAudioCaptureClient(NULL), mVolumeControler(NULL), mBufferFrameCount(0), mIsInitialized(false), mIsActivated(false), mIsStarted(false), mFilter(filter)
{
mTickerSynchronizer = ms_ticker_synchronizer_new();
#ifdef MS2_WINDOWS_UNIVERSAL
mActivationEvent = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
if (!mActivationEvent) {
......@@ -72,6 +73,7 @@ MSWASAPIReader::~MSWASAPIReader()
mActivationEvent = INVALID_HANDLE_VALUE;
}
#endif
ms_ticker_synchronizer_destroy(mTickerSynchronizer);
smInstantiated = false;
}
......@@ -164,6 +166,8 @@ int MSWASAPIReader::activate()
if (!mIsInitialized) goto error;
ms_ticker_set_synchronizer(mFilter->ticker, mTickerSynchronizer);
#ifdef MS2_WINDOWS_PHONE
flags = AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED | AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE | AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED;
#endif
......@@ -213,6 +217,7 @@ int MSWASAPIReader::deactivate()
{
RELEASE_CLIENT(mAudioCaptureClient);
RELEASE_CLIENT(mVolumeControler);
ms_ticker_set_synchronizer(mFilter->ticker, nullptr);
mIsActivated = false;
return 0;
}
......@@ -279,6 +284,8 @@ int MSWASAPIReader::feed(MSFilter *f)
REPORT_ERROR("Could not release buffer of the MSWASAPI audio input interface [%x]", result);
m->b_wptr += numFramesAvailable * bytesPerFrame;
mReadFrames += numFramesAvailable;
ms_ticker_synchronizer_update(mTickerSynchronizer, mReadFrames, (unsigned int)mRate);
ms_queue_put(f->outputs[0], m);
result = mAudioCaptureClient->GetNextPacketSize(&numFramesInNextPacket);
......@@ -374,9 +381,9 @@ exit:
}
MSWASAPIReaderPtr MSWASAPIReaderNew()
MSWASAPIReaderPtr MSWASAPIReaderNew(MSFilter *f)
{
MSWASAPIReaderPtr r = new MSWASAPIReaderWrapper();
MSWASAPIReaderPtr r = new MSWASAPIReaderWrapper(f);
r->reader = Make<MSWASAPIReader>();
return r;
}
......@@ -387,9 +394,9 @@ void MSWASAPIReaderDelete(MSWASAPIReaderPtr ptr)
delete ptr;
}
#else
MSWASAPIReaderPtr MSWASAPIReaderNew()
MSWASAPIReaderPtr MSWASAPIReaderNew(MSFilter *f)
{
return (MSWASAPIReaderPtr) new MSWASAPIReader();
return (MSWASAPIReaderPtr) new MSWASAPIReader(f);
}
void MSWASAPIReaderDelete(MSWASAPIReaderPtr ptr)
{
......
......@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msticker.h"
#include "mswasapi.h"
......@@ -35,7 +36,7 @@ class MSWASAPIReader
#endif
{
public:
MSWASAPIReader();
MSWASAPIReader(MSFilter *filter);
virtual ~MSWASAPIReader();
void init(LPCWSTR id);
......@@ -80,6 +81,9 @@ private:
bool mIsStarted;
int mRate;
int mNChannels;
MSFilter *mFilter;
MSTickerSynchronizer *mTickerSynchronizer;
uint64_t mReadFrames;
};
......@@ -99,5 +103,5 @@ typedef MSWASAPIReader* MSWASAPIReaderPtr;
typedef MSWASAPIReader* MSWASAPIReaderType;
#endif
MSWASAPIReaderPtr MSWASAPIReaderNew();
MSWASAPIReaderPtr MSWASAPIReaderNew(MSFilter *f);
void MSWASAPIReaderDelete(MSWASAPIReaderPtr ptr);
......@@ -25,8 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mswasapi_writer.h"
#define REFTIME_250MS 2500000
#define REPORT_ERROR(msg, result) \
if (result != S_OK) { \
ms_error(msg, result); \
......@@ -44,12 +42,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
}
static const int flowControlInterval = 5000; // ms
static const int flowControlThreshold = 40; // ms
bool MSWASAPIWriter::smInstantiated = false;
MSWASAPIWriter::MSWASAPIWriter()
: mAudioClient(NULL), mAudioRenderClient(NULL), mVolumeControler(NULL), mBufferFrameCount(0), mIsInitialized(false), mIsActivated(false), mIsStarted(false)
: mThread(0), mAudioClient(NULL), mAudioRenderClient(NULL), mVolumeControler(NULL), mBufferFrameCount(0), mIsInitialized(false), mIsActivated(false), mIsStarted(false), mIsReadyToWrite(false), mBufferizer(NULL)
{
mSamplesRequestedEvent = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
if (!mSamplesRequestedEvent) {
ms_error("Could not create samples requested event of the MSWASAPI audio output interface [%i]", GetLastError());
return;
}
ms_mutex_init(&mThreadMutex, NULL);
#ifdef MS2_WINDOWS_UNIVERSAL
mActivationEvent = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
if (!mActivationEvent) {
......@@ -71,11 +78,17 @@ MSWASAPIWriter::~MSWASAPIWriter()
mActivationEvent = INVALID_HANDLE_VALUE;
}
#endif
ms_mutex_destroy(&mThreadMutex);
if (mSamplesRequestedEvent != INVALID_HANDLE_VALUE) {
CloseHandle(mSamplesRequestedEvent);
mSamplesRequestedEvent = INVALID_HANDLE_VALUE;
}
if (mBufferizer) ms_flow_controlled_bufferizer_destroy(mBufferizer);
smInstantiated = false;
}
void MSWASAPIWriter::init(LPCWSTR id) {
void MSWASAPIWriter::init(LPCWSTR id, MSFilter *f) {
HRESULT result;
WAVEFORMATEX *pWfx = NULL;
#if defined(MS2_WINDOWS_PHONE) || defined(MS2_WINDOWS_UNIVERSAL)
......@@ -142,19 +155,20 @@ void MSWASAPIWriter::init(LPCWSTR id) {
FREE_PTR(pWfx);
mIsInitialized = true;
smInstantiated = true;
createBufferizer(f);
return;
error:
// Initialize the frame rate and the number of channels to prevent configure a resampler with crappy parameters.
mRate = 8000;
mNChannels = 1;
createBufferizer(f);
return;
}
int MSWASAPIWriter::activate()
{
HRESULT result;
REFERENCE_TIME requestedDuration = REFTIME_250MS;
WAVEFORMATPCMEX proposedWfx;
WAVEFORMATEX *pUsedWfx = NULL;
WAVEFORMATEX *pSupportedWfx = NULL;
......@@ -183,10 +197,12 @@ int MSWASAPIWriter::activate()
} else {
REPORT_ERROR("Audio format not supported by the MSWASAPI audio output interface [%x]", result);
}
result = mAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST, requestedDuration, 0, pUsedWfx, NULL);
result = mAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, 0, 0, pUsedWfx, NULL);
if ((result != S_OK) && (result != AUDCLNT_E_ALREADY_INITIALIZED)) {
REPORT_ERROR("Could not initialize the MSWASAPI audio output interface [%x]", result);
}
result = mAudioClient->SetEventHandle(mSamplesRequestedEvent);
REPORT_ERROR("SetEventHandle for MSWASAPI audio output interface failed [%x]", result)
result = mAudioClient->GetBufferSize(&mBufferFrameCount);
REPORT_ERROR("Could not get buffer size for the MSWASAPI audio output interface [%x]", result);
ms_message("MSWASAPI audio output interface buffer size: %i", mBufferFrameCount);
......@@ -215,6 +231,7 @@ void MSWASAPIWriter::start()
if (!isStarted() && mIsActivated) {
mIsStarted = true;
ms_thread_create(&mThread, NULL, MSWASAPIWriter::feedThread, this);
result = mAudioClient->Start();
if (result != S_OK) {
ms_error("Could not start playback on the MSWASAPI audio output interface [%x]", result);
......@@ -232,25 +249,40 @@ void MSWASAPIWriter::stop()
if (result != S_OK) {
ms_error("Could not stop playback on the MSWASAPI audio output interface [%x]", result);
}
if (mThread != 0) {
ms_thread_join(mThread, NULL);
mThread = 0;
}
}
}
int MSWASAPIWriter::feed(MSFilter *f)
void * MSWASAPIWriter::feedThread(void *p)
{
MSWASAPIWriter *writer = (MSWASAPIWriter *)p;
return writer->feedThread();
}
void * MSWASAPIWriter::feedThread()
{
HRESULT result;
BYTE *buffer;
UINT32 numFramesPadding;
UINT32 numFramesAvailable;
UINT32 numFramesFed;
mblk_t *im;
int msBufferSizeAvailable;
size_t msBufferSizeAvailable;
int msNumFramesAvailable;
int bytesPerFrame = (16 * mNChannels / 8);
if (isStarted()) {
while ((im = ms_queue_get(f->inputs[0])) != NULL) {
msBufferSizeAvailable = (int)msgdsize(im);
msNumFramesAvailable = msBufferSizeAvailable / bytesPerFrame;
int bytesPerFrame;
while (mIsStarted) {
WaitForSingleObjectEx(mSamplesRequestedEvent, INFINITE, false);
mIsReadyToWrite = true;
bytesPerFrame = (16 * mNChannels / 8);
numFramesFed = 0;
ms_mutex_lock(&mThreadMutex);
msBufferSizeAvailable = ms_flow_controlled_bufferizer_get_avail(mBufferizer);
if (msBufferSizeAvailable > 0) {
msNumFramesAvailable = (int)(msBufferSizeAvailable / (size_t)bytesPerFrame);
if (msNumFramesAvailable > 0) {
// Calculate the number of frames to pass to the Audio Render Client
result = mAudioClient->GetCurrentPadding(&numFramesPadding);
......@@ -268,20 +300,41 @@ int MSWASAPIWriter::feed(MSFilter *f)
if (numFramesFed > 0) {
result = mAudioRenderClient->GetBuffer(numFramesFed, &buffer);
REPORT_ERROR("Could not get buffer from the MSWASAPI audio output interface [%x]", result);
memcpy(buffer, im->b_rptr, numFramesFed * bytesPerFrame);
ms_flow_controlled_bufferizer_read(mBufferizer, buffer, numFramesFed * bytesPerFrame);
result = mAudioRenderClient->ReleaseBuffer(numFramesFed, 0);
REPORT_ERROR("Could not release buffer of the MSWASAPI audio output interface [%x]", result);
}
}
freemsg(im);
} else {
result = mAudioClient->GetCurrentPadding(&numFramesPadding);
REPORT_ERROR("Could not get current buffer padding for the MSWASAPI audio output interface [%x]", result);
numFramesAvailable = mBufferFrameCount - numFramesPadding;
result = mAudioRenderClient->GetBuffer(numFramesAvailable, &buffer);
REPORT_ERROR("Could not get buffer from the MSWASAPI audio output interface [%x]", result);
memset(buffer, 0, numFramesAvailable * bytesPerFrame);
result = mAudioRenderClient->ReleaseBuffer(numFramesAvailable, 0);
REPORT_ERROR("Could not release buffer of the MSWASAPI audio output interface [%x]", result);
}
ms_mutex_unlock(&mThreadMutex);
};
return nullptr;
error:
ms_mutex_unlock(&mThreadMutex);
return nullptr;
}
int MSWASAPIWriter::feed(MSFilter *f)
{
if (isStarted() && mIsReadyToWrite) {
ms_mutex_lock(&mThreadMutex);
ms_flow_controlled_bufferizer_put_from_queue(mBufferizer, f->inputs[0]);
ms_mutex_unlock(&mThreadMutex);
} else {
drop(f);
}
return 0;
error:
return -1;
}
float MSWASAPIWriter::getVolumeLevel() {
......@@ -314,6 +367,12 @@ error:
return;
}
void MSWASAPIWriter::createBufferizer(MSFilter *f) {
mBufferizer = ms_flow_controlled_bufferizer_new(f, mRate, mNChannels);
ms_flow_controlled_bufferizer_set_max_size_ms(mBufferizer, flowControlThreshold);
ms_flow_controlled_bufferizer_set_flow_control_interval_ms(mBufferizer, flowControlInterval);
}
void MSWASAPIWriter::drop(MSFilter *f) {
mblk_t *im;
......
......@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msqueue.h"
#include "mswasapi.h"
......@@ -38,7 +39,7 @@ public:
MSWASAPIWriter();
virtual ~MSWASAPIWriter();
void init(LPCWSTR id);
void init(LPCWSTR id, MSFilter *f);
int activate();
int deactivate();
bool isStarted() { return mIsStarted; }
......@@ -59,10 +60,16 @@ public:
#endif
private:
static void * feedThread(void *p);
void * feedThread();
void createBufferizer(MSFilter *f);
void drop(MSFilter *f);
HRESULT configureAudioClient();
static bool smInstantiated;
HANDLE mSamplesRequestedEvent;
ms_thread_t mThread;
ms_mutex_t mThreadMutex;
#ifdef MS2_WINDOWS_UNIVERSAL
Platform::String^ mRenderId;
HANDLE mActivationEvent;
......@@ -76,10 +83,12 @@ private:
#endif
IAudioRenderClient *mAudioRenderClient;
ISimpleAudioVolume *mVolumeControler;
MSFlowControlledBufferizer *mBufferizer;
UINT32 mBufferFrameCount;
bool mIsInitialized;
bool mIsActivated;
bool mIsStarted;
bool mIsReadyToWrite;
int mRate;
int mNChannels;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment