summaryrefslogtreecommitdiffstats
path: root/plugins/pluginWinMF/plugin_win_mf_producer_audio.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pluginWinMF/plugin_win_mf_producer_audio.cxx')
-rwxr-xr-xplugins/pluginWinMF/plugin_win_mf_producer_audio.cxx425
1 files changed, 210 insertions, 215 deletions
diff --git a/plugins/pluginWinMF/plugin_win_mf_producer_audio.cxx b/plugins/pluginWinMF/plugin_win_mf_producer_audio.cxx
index 2a3c314..5745b24 100755
--- a/plugins/pluginWinMF/plugin_win_mf_producer_audio.cxx
+++ b/plugins/pluginWinMF/plugin_win_mf_producer_audio.cxx
@@ -1,18 +1,18 @@
/* Copyright (C) 2013 Mamadou DIOP
* Copyright (C) 2013 Doubango Telecom <http://www.doubango.org>
-*
+*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*/
@@ -28,12 +28,11 @@
static void* TSK_STDCALL RunSessionThread(void *pArg);
-typedef struct plugin_win_mf_producer_audio_s
-{
- TDAV_DECLARE_PRODUCER_AUDIO;
+typedef struct plugin_win_mf_producer_audio_s {
+ TDAV_DECLARE_PRODUCER_AUDIO;
- bool bStarted;
- tsk_thread_handle_t* ppTread[1];
+ bool bStarted;
+ tsk_thread_handle_t* ppTread[1];
DeviceListAudio* pDeviceList;
@@ -48,162 +47,162 @@ plugin_win_mf_producer_audio_t;
/* ============ Media Producer Interface ================= */
static int plugin_win_mf_producer_audio_set(tmedia_producer_t* self, const tmedia_param_t* param)
-{
- plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
- if(param->plugin_type == tmedia_ppt_producer){
- }
- return tdav_producer_audio_set(TDAV_PRODUCER_AUDIO(pSelf), param);
+{
+ plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
+ if(param->plugin_type == tmedia_ppt_producer) {
+ }
+ return tdav_producer_audio_set(TDAV_PRODUCER_AUDIO(pSelf), param);
}
static int plugin_win_mf_producer_audio_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
{
- plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
-
- if(!pSelf || !codec){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- TMEDIA_PRODUCER(pSelf)->audio.channels = TMEDIA_CODEC_CHANNELS_AUDIO_ENCODING(codec);
- TMEDIA_PRODUCER(pSelf)->audio.rate = TMEDIA_CODEC_RATE_ENCODING(codec);
- TMEDIA_PRODUCER(pSelf)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_ENCODING(codec);
-
- TSK_DEBUG_INFO("MF audio producer: channels=%d, rate=%d, ptime=%d",
- TMEDIA_PRODUCER(pSelf)->audio.channels,
- TMEDIA_PRODUCER(pSelf)->audio.rate,
- TMEDIA_PRODUCER(pSelf)->audio.ptime
- );
-
- HRESULT hr = S_OK;
-
- // create device list object
- if(!pSelf->pDeviceList && !(pSelf->pDeviceList = new DeviceListAudio())){
- TSK_DEBUG_ERROR("Failed to create device list");
- hr = E_OUTOFMEMORY;
- goto bail;
- }
- // enumerate devices
- hr = pSelf->pDeviceList->EnumerateDevices();
- if(!SUCCEEDED(hr)){
- goto bail;
- }
-
- // check if we have at least one MF video source connected to the PC
- if(pSelf->pDeviceList->Count() == 0){
- TSK_DEBUG_WARN("No MF video source could be found...no video will be sent");
- // do not break the negotiation as one-way video connection is a valid use-case
- }
- else{
- IMFActivate* pActivate = NULL;
- // Get best MF audio source
- hr = pSelf->pDeviceList->GetDeviceBest(&pActivate);
- if(!SUCCEEDED(hr) || !pActivate){
- TSK_DEBUG_ERROR("Failed to get best MF audio source");
- if(!pActivate){
- hr = E_OUTOFMEMORY;
- }
- goto bail;
- }
-
- // Create the media source for the device.
- hr = pActivate->ActivateObject(
- __uuidof(IMFMediaSource),
- (void**)&pSelf->pSource
- );
- SafeRelease(&pActivate);
- if(!SUCCEEDED(hr)){
- TSK_DEBUG_ERROR("ActivateObject(MF audio source) failed");
- goto bail;
- }
-
- // Create and configure the media type
- CHECK_HR(hr = MFCreateMediaType(&pSelf->pType));
- CHECK_HR(hr = pSelf->pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
- CHECK_HR(hr = pSelf->pType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM));
- CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, TMEDIA_PRODUCER(pSelf)->audio.channels));
- CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, TMEDIA_PRODUCER(pSelf)->audio.rate));
- CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, TMEDIA_PRODUCER(pSelf)->audio.bits_per_sample));
- CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); // because uncompressed media type
- CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE));
- UINT32 nBlockAlign = TMEDIA_PRODUCER(pSelf)->audio.channels * (TMEDIA_PRODUCER(pSelf)->audio.bits_per_sample >> 3);
- UINT32 nAvgBytesPerSec = (nBlockAlign * TMEDIA_PRODUCER(pSelf)->audio.rate);
- CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, nBlockAlign));
- CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, nAvgBytesPerSec));
-
- // Create the sample grabber sink.
- CHECK_HR(hr = SampleGrabberCB::CreateInstance(TMEDIA_PRODUCER(pSelf), &pSelf->pCallback));
- CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pSelf->pType, pSelf->pCallback, &pSelf->pSinkActivate));
-
- // To run as fast as possible, set this attribute (requires Windows 7):
- CHECK_HR(hr = pSelf->pSinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE));
-
- // Create the Media Session.
- CHECK_HR(hr = MFCreateMediaSession(NULL, &pSelf->pSession));
-
- // Create the topology.
- CHECK_HR(hr = MFUtils::CreateTopology(pSelf->pSource, NULL/*NO ENCODER*/, pSelf->pSinkActivate, NULL/*Preview*/, pSelf->pType, &pSelf->pTopology));
- }
+ plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
+
+ if(!pSelf || !codec) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ TMEDIA_PRODUCER(pSelf)->audio.channels = TMEDIA_CODEC_CHANNELS_AUDIO_ENCODING(codec);
+ TMEDIA_PRODUCER(pSelf)->audio.rate = TMEDIA_CODEC_RATE_ENCODING(codec);
+ TMEDIA_PRODUCER(pSelf)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_ENCODING(codec);
+
+ TSK_DEBUG_INFO("MF audio producer: channels=%d, rate=%d, ptime=%d",
+ TMEDIA_PRODUCER(pSelf)->audio.channels,
+ TMEDIA_PRODUCER(pSelf)->audio.rate,
+ TMEDIA_PRODUCER(pSelf)->audio.ptime
+ );
+
+ HRESULT hr = S_OK;
+
+ // create device list object
+ if(!pSelf->pDeviceList && !(pSelf->pDeviceList = new DeviceListAudio())) {
+ TSK_DEBUG_ERROR("Failed to create device list");
+ hr = E_OUTOFMEMORY;
+ goto bail;
+ }
+ // enumerate devices
+ hr = pSelf->pDeviceList->EnumerateDevices();
+ if(!SUCCEEDED(hr)) {
+ goto bail;
+ }
+
+ // check if we have at least one MF video source connected to the PC
+ if(pSelf->pDeviceList->Count() == 0) {
+ TSK_DEBUG_WARN("No MF video source could be found...no video will be sent");
+ // do not break the negotiation as one-way video connection is a valid use-case
+ }
+ else {
+ IMFActivate* pActivate = NULL;
+ // Get best MF audio source
+ hr = pSelf->pDeviceList->GetDeviceBest(&pActivate);
+ if(!SUCCEEDED(hr) || !pActivate) {
+ TSK_DEBUG_ERROR("Failed to get best MF audio source");
+ if(!pActivate) {
+ hr = E_OUTOFMEMORY;
+ }
+ goto bail;
+ }
+
+ // Create the media source for the device.
+ hr = pActivate->ActivateObject(
+ __uuidof(IMFMediaSource),
+ (void**)&pSelf->pSource
+ );
+ SafeRelease(&pActivate);
+ if(!SUCCEEDED(hr)) {
+ TSK_DEBUG_ERROR("ActivateObject(MF audio source) failed");
+ goto bail;
+ }
+
+ // Create and configure the media type
+ CHECK_HR(hr = MFCreateMediaType(&pSelf->pType));
+ CHECK_HR(hr = pSelf->pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
+ CHECK_HR(hr = pSelf->pType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM));
+ CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, TMEDIA_PRODUCER(pSelf)->audio.channels));
+ CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, TMEDIA_PRODUCER(pSelf)->audio.rate));
+ CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, TMEDIA_PRODUCER(pSelf)->audio.bits_per_sample));
+ CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); // because uncompressed media type
+ CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE));
+ UINT32 nBlockAlign = TMEDIA_PRODUCER(pSelf)->audio.channels * (TMEDIA_PRODUCER(pSelf)->audio.bits_per_sample >> 3);
+ UINT32 nAvgBytesPerSec = (nBlockAlign * TMEDIA_PRODUCER(pSelf)->audio.rate);
+ CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, nBlockAlign));
+ CHECK_HR(hr = pSelf->pType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, nAvgBytesPerSec));
+
+ // Create the sample grabber sink.
+ CHECK_HR(hr = SampleGrabberCB::CreateInstance(TMEDIA_PRODUCER(pSelf), &pSelf->pCallback));
+ CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pSelf->pType, pSelf->pCallback, &pSelf->pSinkActivate));
+
+ // To run as fast as possible, set this attribute (requires Windows 7):
+ CHECK_HR(hr = pSelf->pSinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE));
+
+ // Create the Media Session.
+ CHECK_HR(hr = MFCreateMediaSession(NULL, &pSelf->pSession));
+
+ // Create the topology.
+ CHECK_HR(hr = MFUtils::CreateTopology(pSelf->pSource, NULL/*NO ENCODER*/, pSelf->pSinkActivate, NULL/*Preview*/, pSelf->pType, &pSelf->pTopology));
+ }
bail:
- return SUCCEEDED(hr) ? 0 : -1;
+ return SUCCEEDED(hr) ? 0 : -1;
}
static int plugin_win_mf_producer_audio_start(tmedia_producer_t* self)
{
- plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
-
- if(!pSelf){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(pSelf->bStarted){
- TSK_DEBUG_INFO("MF audio producer already started");
- return 0;
- }
-
- HRESULT hr = S_OK;
-
- // Run the media session.
- CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopology));
-
- // Start asynchronous watcher thread
- pSelf->bStarted = true;
- int ret = tsk_thread_create(&pSelf->ppTread[0], RunSessionThread, pSelf);
- if(ret != 0) {
- TSK_DEBUG_ERROR("Failed to create thread");
- hr = E_FAIL;
- pSelf->bStarted = false;
- if(pSelf->ppTread[0]){
- tsk_thread_join(&pSelf->ppTread[0]);
- }
- MFUtils::ShutdownSession(pSelf->pSession, pSelf->pSource);
- goto bail;
- }
+ plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
+
+ if(!pSelf) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(pSelf->bStarted) {
+ TSK_DEBUG_INFO("MF audio producer already started");
+ return 0;
+ }
+
+ HRESULT hr = S_OK;
+
+ // Run the media session.
+ CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopology));
+
+ // Start asynchronous watcher thread
+ pSelf->bStarted = true;
+ int ret = tsk_thread_create(&pSelf->ppTread[0], RunSessionThread, pSelf);
+ if(ret != 0) {
+ TSK_DEBUG_ERROR("Failed to create thread");
+ hr = E_FAIL;
+ pSelf->bStarted = false;
+ if(pSelf->ppTread[0]) {
+ tsk_thread_join(&pSelf->ppTread[0]);
+ }
+ MFUtils::ShutdownSession(pSelf->pSession, pSelf->pSource);
+ goto bail;
+ }
bail:
- return SUCCEEDED(hr) ? 0 : -1;
+ return SUCCEEDED(hr) ? 0 : -1;
}
static int plugin_win_mf_producer_audio_pause(tmedia_producer_t* self)
{
- plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
+ plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
- if(!pSelf){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!pSelf) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- HRESULT hr = MFUtils::PauseSession(pSelf->pSession);
+ HRESULT hr = MFUtils::PauseSession(pSelf->pSession);
- return SUCCEEDED(hr) ? 0 : -1;
+ return SUCCEEDED(hr) ? 0 : -1;
}
static int plugin_win_mf_producer_audio_stop(tmedia_producer_t* self)
{
- plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
-
- if(!pSelf){
+ plugin_win_mf_producer_audio_t* pSelf = (plugin_win_mf_producer_audio_t*)self;
+
+ if(!pSelf) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -213,7 +212,7 @@ static int plugin_win_mf_producer_audio_stop(tmedia_producer_t* self)
// for the thread
pSelf->bStarted = false;
hr = MFUtils::ShutdownSession(pSelf->pSession, NULL); // stop session to wakeup the asynchronous thread
- if(pSelf->ppTread[0]){
+ if(pSelf->ppTread[0]) {
tsk_thread_join(&pSelf->ppTread[0]);
}
hr = MFUtils::ShutdownSession(NULL, pSelf->pSource); // stop source to release the camera
@@ -228,37 +227,37 @@ static int plugin_win_mf_producer_audio_stop(tmedia_producer_t* self)
/* constructor */
static tsk_object_t* plugin_win_mf_producer_audio_ctor(tsk_object_t * self, va_list * app)
{
- MFUtils::Startup();
-
- plugin_win_mf_producer_audio_t *pSelf = (plugin_win_mf_producer_audio_t*)self;
- if(pSelf){
- /* init base */
- tdav_producer_audio_init(TDAV_PRODUCER_AUDIO(pSelf));
- /* init self */
-
- }
- return self;
+ MFUtils::Startup();
+
+ plugin_win_mf_producer_audio_t *pSelf = (plugin_win_mf_producer_audio_t*)self;
+ if(pSelf) {
+ /* init base */
+ tdav_producer_audio_init(TDAV_PRODUCER_AUDIO(pSelf));
+ /* init self */
+
+ }
+ return self;
}
/* destructor */
static tsk_object_t* plugin_win_mf_producer_audio_dtor(tsk_object_t * self)
-{
- plugin_win_mf_producer_audio_t *pSelf = (plugin_win_mf_producer_audio_t *)self;
- if(pSelf){
- /* stop */
- if(pSelf->bStarted){
- plugin_win_mf_producer_audio_stop(TMEDIA_PRODUCER(pSelf));
- }
-
- /* deinit base */
- tdav_producer_audio_deinit(TDAV_PRODUCER_AUDIO(pSelf));
- /* deinit self */
- if(pSelf->pDeviceList){
- delete pSelf->pDeviceList, pSelf->pDeviceList = NULL;
+{
+ plugin_win_mf_producer_audio_t *pSelf = (plugin_win_mf_producer_audio_t *)self;
+ if(pSelf) {
+ /* stop */
+ if(pSelf->bStarted) {
+ plugin_win_mf_producer_audio_stop(TMEDIA_PRODUCER(pSelf));
}
- if(pSelf->pSource){
- pSelf->pSource->Shutdown();
+
+ /* deinit base */
+ tdav_producer_audio_deinit(TDAV_PRODUCER_AUDIO(pSelf));
+ /* deinit self */
+ if(pSelf->pDeviceList) {
+ delete pSelf->pDeviceList, pSelf->pDeviceList = NULL;
+ }
+ if(pSelf->pSource) {
+ pSelf->pSource->Shutdown();
}
- if(pSelf->pSession){
+ if(pSelf->pSession) {
pSelf->pSession->Shutdown();
}
@@ -268,31 +267,29 @@ static tsk_object_t* plugin_win_mf_producer_audio_dtor(tsk_object_t * self)
SafeRelease(&pSelf->pSinkActivate);
SafeRelease(&pSelf->pTopology);
SafeRelease(&pSelf->pType);
- }
+ }
- return self;
+ return self;
}
/* object definition */
-static const tsk_object_def_t plugin_win_mf_producer_audio_def_s =
-{
- sizeof(plugin_win_mf_producer_audio_t),
- plugin_win_mf_producer_audio_ctor,
- plugin_win_mf_producer_audio_dtor,
- tdav_producer_audio_cmp,
+static const tsk_object_def_t plugin_win_mf_producer_audio_def_s = {
+ sizeof(plugin_win_mf_producer_audio_t),
+ plugin_win_mf_producer_audio_ctor,
+ plugin_win_mf_producer_audio_dtor,
+ tdav_producer_audio_cmp,
};
/* plugin definition*/
-static const tmedia_producer_plugin_def_t plugin_win_mf_producer_audio_plugin_def_s =
-{
- &plugin_win_mf_producer_audio_def_s,
-
- tmedia_audio,
- "Media Foundation audio producer",
-
- plugin_win_mf_producer_audio_set,
- plugin_win_mf_producer_audio_prepare,
- plugin_win_mf_producer_audio_start,
- plugin_win_mf_producer_audio_pause,
- plugin_win_mf_producer_audio_stop
+static const tmedia_producer_plugin_def_t plugin_win_mf_producer_audio_plugin_def_s = {
+ &plugin_win_mf_producer_audio_def_s,
+
+ tmedia_audio,
+ "Media Foundation audio producer",
+
+ plugin_win_mf_producer_audio_set,
+ plugin_win_mf_producer_audio_prepare,
+ plugin_win_mf_producer_audio_start,
+ plugin_win_mf_producer_audio_pause,
+ plugin_win_mf_producer_audio_stop
};
const tmedia_producer_plugin_def_t *plugin_win_mf_producer_audio_plugin_def_t = &plugin_win_mf_producer_audio_plugin_def_s;
@@ -300,34 +297,32 @@ const tmedia_producer_plugin_def_t *plugin_win_mf_producer_audio_plugin_def_t =
// Run session async thread
static void* TSK_STDCALL RunSessionThread(void *pArg)
{
- plugin_win_mf_producer_audio_t *pSelf = (plugin_win_mf_producer_audio_t *)pArg;
- HRESULT hrStatus = S_OK;
- HRESULT hr = S_OK;
- IMFMediaEvent *pEvent = NULL;
- MediaEventType met;
-
- TSK_DEBUG_INFO("RunSessionThread (audio) - ENTER");
-
- while(pSelf->bStarted){
- CHECK_HR(hr = pSelf->pSession->GetEvent(0, &pEvent));
- CHECK_HR(hr = pEvent->GetStatus(&hrStatus));
- CHECK_HR(hr = pEvent->GetType(&met));
-
- if (FAILED(hrStatus))
- {
- TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met);
- hr = hrStatus;
- goto bail;
- }
- if (met == MESessionEnded)
- {
- break;
- }
- SafeRelease(&pEvent);
- }
+ plugin_win_mf_producer_audio_t *pSelf = (plugin_win_mf_producer_audio_t *)pArg;
+ HRESULT hrStatus = S_OK;
+ HRESULT hr = S_OK;
+ IMFMediaEvent *pEvent = NULL;
+ MediaEventType met;
+
+ TSK_DEBUG_INFO("RunSessionThread (audio) - ENTER");
+
+ while(pSelf->bStarted) {
+ CHECK_HR(hr = pSelf->pSession->GetEvent(0, &pEvent));
+ CHECK_HR(hr = pEvent->GetStatus(&hrStatus));
+ CHECK_HR(hr = pEvent->GetType(&met));
+
+ if (FAILED(hrStatus)) {
+ TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met);
+ hr = hrStatus;
+ goto bail;
+ }
+ if (met == MESessionEnded) {
+ break;
+ }
+ SafeRelease(&pEvent);
+ }
bail:
- TSK_DEBUG_INFO("RunSessionThread (audio) - EXIT");
+ TSK_DEBUG_INFO("RunSessionThread (audio) - EXIT");
- return NULL;
+ return NULL;
}
OpenPOWER on IntegriCloud