From 235dafb046de42ab9388031ac2e8c104740cfe38 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Thu, 4 Apr 2024 21:05:00 +0900 Subject: [PATCH] fixup! Reset dump values when pause function is called refactor code to handle internal cork scenario due to empty-pop-timeout Change-Id: Ief7fad657bc78a34f4835ace504ffd6d1fa9ee8c --- include/CAudioIO.h | 1 + include/CAudioIODef.h | 2 +- include/CAudioOutput.h | 5 ++- include/CPulseAudioClient.h | 6 ++- include/IPulseStreamListener.h | 1 + packaging/capi-media-audio-io.spec | 2 +- src/cpp/CAudioIO.cpp | 7 ++++ src/cpp/CAudioOutput.cpp | 22 +++++++++-- src/cpp/CPulseAudioClient.cpp | 79 ++++++++++++++++++++++++++++---------- 9 files changed, 96 insertions(+), 29 deletions(-) diff --git a/include/CAudioIO.h b/include/CAudioIO.h index 4cb769e..36eabfc 100644 --- a/include/CAudioIO.h +++ b/include/CAudioIO.h @@ -71,6 +71,7 @@ namespace tizen_media_audio { virtual void onStream(CPulseAudioClient* pClient, size_t length); virtual void onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy); virtual void onStateChanged(CAudioInfo::EAudioIOState state); + virtual void onCorked(CPulseAudioClient* pClient, bool corked); /* Methods */ virtual void initialize(); diff --git a/include/CAudioIODef.h b/include/CAudioIODef.h index 1fffbb7..b431bdf 100644 --- a/include/CAudioIODef.h +++ b/include/CAudioIODef.h @@ -20,7 +20,7 @@ #ifdef __cplusplus - +#include #include #include diff --git a/include/CAudioOutput.h b/include/CAudioOutput.h index da44f63..8b9b0bc 100644 --- a/include/CAudioOutput.h +++ b/include/CAudioOutput.h @@ -37,6 +37,7 @@ namespace tizen_media_audio { /* Overridden Handler */ void onStream(CPulseAudioClient* pClient, size_t length) override; + void onCorked(CPulseAudioClient* pClient, bool corked) override; /* Implemented Methods */ void initialize() override; @@ -67,8 +68,8 @@ namespace tizen_media_audio { bool __mIsUsedSyncWrite {}; bool __mIsInit {}; - uint64_t __mTotalWrittenCount {}; - uint64_t __mTotalWrittenBytes {}; + std::atomic __mTotalWrittenCount {}; + std::atomic __mTotalWrittenBytes {}; }; diff --git a/include/CPulseAudioClient.h b/include/CPulseAudioClient.h index 631362a..7e1ce1e 100644 --- a/include/CPulseAudioClient.h +++ b/include/CPulseAudioClient.h @@ -102,6 +102,8 @@ namespace tizen_media_audio { /* Private Method */ void resetStreamCallbacks(); void resetInternalObjects(); + bool streamCork(bool cork, pa_stream_success_cb_t cb, void* user_data); + void notifyCorkStatus(); /* Private Callback Method */ static void __contextStateChangeCb(pa_context* c, void* user_data); @@ -112,8 +114,10 @@ namespace tizen_media_audio { static void __streamStartedCb(pa_stream* s, void* user_data); static void __streamUnderflowCb(pa_stream* s, void* user_data); static void __streamOverflowCb(pa_stream* s, void* user_data); - static void __streamEventCb(pa_stream* s, const char *name, pa_proplist *pl, void *user_data); + static void __streamEventCb(pa_stream* s, const char* name, pa_proplist* pl, void* user_data); static void __successStreamCb(pa_stream* s, int success, void* user_data); + static void __successCorkCb(pa_stream* s, int success, void* user_data); + static void __successCorkCbSignal(pa_stream* s, int success, void* user_data); static void __successDrainCb(pa_stream* s, int success, void* user_data); static void __successDrainCbInThread(pa_stream* s, int success, void* user_data); static void __successVolumeCb(pa_context* c, int success, void* user_data); diff --git a/include/IPulseStreamListener.h b/include/IPulseStreamListener.h index 76b4288..90521c7 100644 --- a/include/IPulseStreamListener.h +++ b/include/IPulseStreamListener.h @@ -37,6 +37,7 @@ namespace tizen_media_audio { virtual void onStateChanged(CAudioInfo::EAudioIOState state) = 0; virtual void onStateChanged(CAudioInfo::EAudioIOState state, bool policy) = 0; virtual void setState(CAudioInfo::EAudioIOState state) = 0; + virtual void onCorked(CPulseAudioClient* pClient, bool corked) = 0; }; diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index 8c46590..80df104 100644 --- a/packaging/capi-media-audio-io.spec +++ b/packaging/capi-media-audio-io.spec @@ -1,6 +1,6 @@ Name: capi-media-audio-io Summary: An Audio Input & Audio Output library in Tizen Native API -Version: 0.5.67 +Version: 0.5.68 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/cpp/CAudioIO.cpp b/src/cpp/CAudioIO.cpp index fac712a..04ceb05 100644 --- a/src/cpp/CAudioIO.cpp +++ b/src/cpp/CAudioIO.cpp @@ -220,3 +220,10 @@ void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) { getAudioInfo().setEffectMethodWithReference(method_reference, device_id); } } + +void CAudioIO::onCorked(CPulseAudioClient* pClient, bool corked) { + assert(__mIsInit); + assert(pClient); + + AUDIO_IO_LOGD("pClient(%p), corked(%d)", pClient, corked); +} diff --git a/src/cpp/CAudioOutput.cpp b/src/cpp/CAudioOutput.cpp index d50762a..7a5c3ad 100644 --- a/src/cpp/CAudioOutput.cpp +++ b/src/cpp/CAudioOutput.cpp @@ -218,9 +218,6 @@ void CAudioOutput::pause() { CAudioIO::pause(); CAudioIO::setState(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); - __mTotalWrittenCount = 0; - __mTotalWrittenBytes = 0; - locker.unlock(); CAudioIO::onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED); @@ -388,7 +385,8 @@ size_t CAudioOutput::write(const void* buffer, size_t length) { void CAudioOutput::__dumpStat() noexcept { AUDIO_IO_LOGD("pClient[%p] : total written %5" PRIu64 " times, %10" PRIu64 " bytes, %7zu ms", - mpPulseAudioClient, __mTotalWrittenCount, __mTotalWrittenBytes, mAudioInfo.bytesToMs(__mTotalWrittenBytes)); + mpPulseAudioClient, __mTotalWrittenCount.load(), __mTotalWrittenBytes.load(), + mAudioInfo.bytesToMs(__mTotalWrittenBytes.load())); } void CAudioOutput::__dumpStat(size_t length) noexcept { @@ -403,3 +401,19 @@ void CAudioOutput::__dumpStat(size_t length) noexcept { writtenBytes = 0; } } + +void CAudioOutput::onCorked(CPulseAudioClient* pClient, bool corked) { + assert(pClient); + + AUDIO_IO_LOGD("pClient:[%p], corked:[%d]", pClient, corked); + + if (!corked) + return; + + __dumpStat(); + + AUDIO_IO_LOGW("Now reset previous written count/bytes due to corked!"); + + __mTotalWrittenCount = 0; + __mTotalWrittenBytes = 0; +} \ No newline at end of file diff --git a/src/cpp/CPulseAudioClient.cpp b/src/cpp/CPulseAudioClient.cpp index d143d94..e18c69e 100644 --- a/src/cpp/CPulseAudioClient.cpp +++ b/src/cpp/CPulseAudioClient.cpp @@ -281,17 +281,50 @@ void CPulseAudioClient::__streamEventCb(pa_stream* s, const char* name, pa_propl AUDIO_IO_LOGW("pClient[%p] pa_stream[%p] : name[%s], proplist[%p]", pClient, s, name, pl); - if (strcmp(name, PA_STREAM_EVENT_POP_TIMEOUT) == 0) { - pa_operation* o = pa_stream_cork(pClient->__mpStream, 1, NULL, NULL); - if (!o) { - AUDIO_IO_LOGE("pa_stream[%p] : cork failed", pClient->__mpStream); - return; - } - pa_operation_unref(o); - } + if (strcmp(name, PA_STREAM_EVENT_POP_TIMEOUT) != 0) + return; + + if (!pClient->streamCork(true, __successCorkCb, pClient)) + AUDIO_IO_LOGE("pa_stream[%p] : cork failed", pClient->__mpStream); } //LCOV_EXCL_STOP +void CPulseAudioClient::notifyCorkStatus() { + assert(__mpListener); + assert(__mpStream); + + __mpListener->onCorked(this, static_cast(pa_stream_is_corked(__mpStream))); +} + +void CPulseAudioClient::__successCorkCb(pa_stream* s, int success, void* user_data) { + assert(s); + assert(user_data); + + auto pClient = static_cast(user_data); + + AUDIO_IO_LOGD("pClient[%p] pa_stream[%p] success[%d] user_data[%p]", pClient, s, success, user_data); + + if (success) + pClient->notifyCorkStatus(); +} + +void CPulseAudioClient::__successCorkCbSignal(pa_stream* s, int success, void* user_data) { + assert(s); + assert(user_data); + + auto pClient = static_cast(user_data); + + AUDIO_IO_LOGD("pClient[%p] pa_stream[%p] success[%d] user_data[%p]", pClient, s, success, user_data); + + if (success) + pClient->notifyCorkStatus(); + + pClient->__mIsOperationSuccess = static_cast(success); + + /* FIXME : verify following action without any waiting */ + pa_threaded_mainloop_signal(pClient->__mpMainloop, 0); +} + void CPulseAudioClient::__successStreamCb(pa_stream* s, int success, void* user_data) { assert(s); assert(user_data); @@ -747,11 +780,8 @@ int CPulseAudioClient::write(const void* data, size_t length) { CPulseThreadLocker locker{__mpMainloop}; if (pa_stream_is_corked(__mpStream)) { AUDIO_IO_LOGW("pa_stream[%p] is corked...do uncork here first!!!!", __mpStream); - pa_operation* o = pa_stream_cork(__mpStream, 0, NULL, NULL); - if (!o) + if (!streamCork(false, __successCorkCb, this)) AUDIO_IO_LOGE("pa_stream[%p] : uncork failed", __mpStream); - else - pa_operation_unref(o); } ret = pa_stream_write(__mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE); @@ -759,11 +789,9 @@ int CPulseAudioClient::write(const void* data, size_t length) { // LCOV_EXCL_START if (pa_stream_is_corked(__mpStream)) { AUDIO_IO_LOGW("pa_stream[%p] is corked...do uncork here first!!!!", __mpStream); - pa_operation* o = pa_stream_cork(__mpStream, 0, NULL, NULL); - if (!o) + + if (!streamCork(false, __successCorkCb, this)) AUDIO_IO_LOGE("pa_stream[%p] : uncork failed", __mpStream); - else - pa_operation_unref(o); } if (__mIsFirstStream) { @@ -788,6 +816,15 @@ int CPulseAudioClient::write(const void* data, size_t length) { return ret; } +bool CPulseAudioClient::streamCork(bool cork, pa_stream_success_cb_t cb, void* user_data) { + pa_operation* o = pa_stream_cork(__mpStream, static_cast(cork), cb, user_data); + if (!o) + return false; + pa_operation_unref(o); + + return true; +} + void CPulseAudioClient::cork(bool cork) { AUDIO_IO_LOGD("cork[%d]", cork); @@ -806,13 +843,15 @@ void CPulseAudioClient::cork(bool cork) { CPulseThreadLocker locker{__mpMainloop}; /* FIXME: wait for completion like drain? */ - pa_operation* o = pa_stream_cork(__mpStream, static_cast(cork), __successStreamCb, this); - if (!o) { + if (!streamCork(cork, __successCorkCbSignal, this)) { AUDIO_IO_LOGE("pa_stream[%p] : cork[%d] failed", __mpStream, cork); return; } - pa_operation_unref(o); - AUDIO_IO_LOGD("cork[%d] done", cork); + + AUDIO_IO_LOGD("cork[%d] requested, is-stream-started[%d]", cork, __mIsStarted); + + /* FIXME: need to consider manual pa_stream_trigger() when uncorking but stream is not started yet, + because even uncorked here, it is still prebuf state so, empty-pop will not be checked in this situation */ } bool CPulseAudioClient::isCorked() { -- 2.7.4