OnStateChange implementation

Signed-off-by: Vaidegi B <vaidegi.b1@huawei.com>
This commit is contained in:
Vaidegi B 2022-02-11 01:33:44 +05:30
parent 890cf58f00
commit a903e10269
30 changed files with 1006 additions and 299 deletions

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef AUDIO_CAPTURER_CALLBACK_NAPI_H_
#define AUDIO_CAPTURER_CALLBACK_NAPI_H_
#include "audio_common_napi.h"
#include "audio_capturer.h"
#include "napi/native_api.h"
#include "napi/native_node_api.h"
namespace OHOS {
namespace AudioStandard {
class AudioCapturerCallbackNapi : public AudioCapturerCallback {
public:
explicit AudioCapturerCallbackNapi(napi_env env);
virtual ~AudioCapturerCallbackNapi();
void SaveCallbackReference(const std::string &callbackName, napi_value callback);
void OnStateChange(const CapturerState state) override;
private:
struct AudioCapturerJsCallback {
std::shared_ptr<AutoRef> callback = nullptr;
std::string callbackName = "unknown";
CapturerState state;
};
void OnJsCallbackStateChange(std::unique_ptr<AudioCapturerJsCallback> &jsCb);
std::mutex mutex_;
napi_env env_ = nullptr;
std::shared_ptr<AutoRef> stateChangeCallback_ = nullptr;
};
} // namespace AudioStandard
} // namespace OHOS
#endif // AUDIO_CAPTURER_CALLBACK_NAPI_H_

View File

@ -0,0 +1,120 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "audio_capturer_callback_napi.h"
#include <uv.h>
#include "audio_errors.h"
#include "media_log.h"
namespace OHOS {
namespace AudioStandard {
AudioCapturerCallbackNapi::AudioCapturerCallbackNapi(napi_env env)
: env_(env)
{
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: instance create");
}
AudioCapturerCallbackNapi::~AudioCapturerCallbackNapi()
{
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: instance destroy");
}
void AudioCapturerCallbackNapi::SaveCallbackReference(const std::string &callbackName, napi_value args)
{
std::lock_guard<std::mutex> lock(mutex_);
napi_ref callback = nullptr;
const int32_t refCount = 1;
napi_status status = napi_create_reference(env_, args, refCount, &callback);
CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
"AudioCapturerCallbackNapi: creating reference for callback fail");
std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
if (callbackName == STATE_CHANGE_CALLBACK_NAME) {
stateChangeCallback_ = cb;
} else {
MEDIA_ERR_LOG("AudioCapturerCallbackNapi: Unknown callback type: %{public}s", callbackName.c_str());
}
}
void AudioCapturerCallbackNapi::OnStateChange(const CapturerState state)
{
std::lock_guard<std::mutex> lock(mutex_);
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: OnStateChange is called");
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: state: %{public}d", state);
CHECK_AND_RETURN_LOG(stateChangeCallback_ != nullptr, "Cannot find the reference of stateChange callback");
std::unique_ptr<AudioCapturerJsCallback> cb = std::make_unique<AudioCapturerJsCallback>();
CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
cb->callback = stateChangeCallback_;
cb->callbackName = STATE_CHANGE_CALLBACK_NAME;
cb->state = state;
return OnJsCallbackStateChange(cb);
}
void AudioCapturerCallbackNapi::OnJsCallbackStateChange(std::unique_ptr<AudioCapturerJsCallback> &jsCb)
{
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(env_, &loop);
if (loop == nullptr) {
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
MEDIA_ERR_LOG("AudioCapturerCallbackNapi: OnJsCallbackStateChange: No memory");
return;
}
work->data = reinterpret_cast<void *>(jsCb.get());
int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
// Js Thread
AudioCapturerJsCallback *event = reinterpret_cast<AudioCapturerJsCallback *>(work->data);
std::string request = event->callbackName;
napi_env env = event->callback->env_;
napi_ref callback = event->callback->cb_;
MEDIA_DEBUG_LOG("AudioCapturerCallbackNapi: JsCallBack %{public}s, uv_queue_work start", request.c_str());
do {
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s cancelled", request.c_str());
napi_value jsCallback = nullptr;
napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
request.c_str());
// Call back function
napi_value args[1] = { nullptr };
nstatus = napi_create_int32(env, event->state, &args[0]);
CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
"%{public}s fail to create Interrupt callback", request.c_str());
const size_t argCount = 1;
napi_value result = nullptr;
nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call Interrupt callback", request.c_str());
} while (0);
delete event;
delete work;
});
if (ret != 0) {
MEDIA_ERR_LOG("Failed to execute libuv work queue");
delete work;
} else {
jsCb.release();
}
}
} // namespace AudioStandard
} // namespace OHOS

View File

@ -14,13 +14,15 @@
*/
#include "audio_capturer_napi.h"
#include "audio_capturer_callback_napi.h"
#include "audio_errors.h"
#include "audio_manager_napi.h"
#include "audio_parameters_napi.h"
#include "capturer_period_position_callback_napi.h"
#include "capturer_position_callback_napi.h"
#include "hilog/log.h"
#include "media_log.h"
#include "securec.h"
using namespace std;
@ -42,9 +44,6 @@ namespace {
const int PARAM1 = 1;
const int PARAM2 = 2;
const int ERROR = -1;
const int SUCCESS = 0;
constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioCapturerNapi"};
const std::string MARK_REACH_CALLBACK_NAME = "markReach";
@ -208,23 +207,25 @@ napi_value AudioCapturerNapi::Construct(napi_env env, napi_callback_info info)
GET_PARAMS(env, info, ARGS_TWO);
unique_ptr<AudioCapturerNapi> obj = make_unique<AudioCapturerNapi>();
if (obj != nullptr) {
obj->env_ = env;
obj->sourceType_ = sAudioCapturerOptions_->capturerInfo.sourceType;
obj->capturerFlags_ = sAudioCapturerOptions_->capturerInfo.capturerFlags;
obj->audioCapturer_ = AudioCapturer::Create(*sAudioCapturerOptions_);
if (obj->audioCapturer_ == nullptr) {
HiLog::Error(LABEL, "Failed to create capturer object from native");
return result;
}
unique_ptr<AudioCapturerNapi> capturerNapi = make_unique<AudioCapturerNapi>();
CHECK_AND_RETURN_RET_LOG(capturerNapi != nullptr, result, "No memory");
capturerNapi->env_ = env;
capturerNapi->sourceType_ = sAudioCapturerOptions_->capturerInfo.sourceType;
capturerNapi->capturerFlags_ = sAudioCapturerOptions_->capturerInfo.capturerFlags;
status = napi_wrap(env, thisVar, static_cast<void*>(obj.get()),
AudioCapturerNapi::Destructor, nullptr, &(obj->wrapper_));
if (status == napi_ok) {
obj.release();
return thisVar;
}
capturerNapi->audioCapturer_ = AudioCapturer::Create(*sAudioCapturerOptions_);
CHECK_AND_RETURN_RET_LOG(capturerNapi->audioCapturer_ != nullptr, result, "Capturer Create failed");
if (capturerNapi->callbackNapi_ == nullptr) {
capturerNapi->callbackNapi_ = std::make_shared<AudioCapturerCallbackNapi>(env);
(void)capturerNapi->audioCapturer_->SetCapturerCallback(capturerNapi->callbackNapi_);
}
status = napi_wrap(env, thisVar, static_cast<void*>(capturerNapi.get()),
AudioCapturerNapi::Destructor, nullptr, &(capturerNapi->wrapper_));
if (status == napi_ok) {
capturerNapi.release();
return thisVar;
}
HiLog::Error(LABEL, "Failed in AudioCapturerNapi::Construct()!");
@ -432,7 +433,7 @@ void AudioCapturerNapi::VoidAsyncCallbackComplete(napi_env env, napi_status stat
}
CommonCallbackRoutine(env, asyncContext, valueParam);
} else {
HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
}
}
@ -916,43 +917,29 @@ napi_value AudioCapturerNapi::Release(napi_env env, napi_callback_info info)
return result;
}
// Function to read string argument from napi_value
static string GetStringArgument(napi_env env, napi_value value)
{
napi_status status;
string strValue = "";
size_t bufLength = 0;
char *buffer = nullptr;
status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
if (status == napi_ok && bufLength > 0) {
buffer = (char *)malloc((bufLength + 1) * sizeof(char));
if (buffer != nullptr) {
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
if (status == napi_ok) {
strValue = buffer;
}
free(buffer);
buffer = nullptr;
}
}
return strValue;
}
napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
{
napi_value undefinedResult = nullptr;
napi_get_undefined(env, &undefinedResult);
const size_t minArgCount = 3;
size_t argCount = minArgCount;
napi_value args[minArgCount] = { nullptr, nullptr, nullptr };
const size_t maxArgCount = 3;
size_t argCount = maxArgCount;
napi_value args[maxArgCount] = { nullptr, nullptr, nullptr };
napi_value jsThis = nullptr;
napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr ||
args[PARAM2] == nullptr) {
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
if (argCount == maxArgCount - 1) { // 2 args on api
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr) {
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
return undefinedResult;
}
} else if (argCount == maxArgCount) { // mark/position reach
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr ||
args[PARAM2] == nullptr) {
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
return undefinedResult;
}
} else {
MEDIA_DEBUG_LOG("AudioCapturerNapi:: on called with wrong number of args");
return undefinedResult;
}
@ -963,16 +950,21 @@ napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
napi_valuetype valueType0 = napi_undefined;
napi_valuetype valueType1 = napi_undefined;
napi_valuetype valueType2 = napi_undefined;
if (napi_typeof(env, args[PARAM0], &valueType0) != napi_ok || valueType0 != napi_string
|| napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
// Check value type of PARAM0
if (napi_typeof(env, args[PARAM0], &valueType0) != napi_ok || valueType0 != napi_string) {
return undefinedResult;
}
std::string callbackName = GetStringArgument(env, args[0]);
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
HiLog::Info(LABEL, "AudioCapturerNapi: callbackName: %{public}s", callbackName.c_str());
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
napi_valuetype valueType2 = napi_undefined;
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
return undefinedResult;
}
int64_t markPosition = 0;
napi_get_value_int64(env, args[PARAM1], &markPosition);
if (markPosition <= 0) {
@ -995,7 +987,15 @@ napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
std::static_pointer_cast<CapturerPositionCallbackNapi>(capturerNapi->positionCBNapi_);
cb->SaveCallbackReference(callbackName, args[PARAM2]);
}
return undefinedResult;
} else if (!callbackName.compare(PERIOD_REACH_CALLBACK_NAME)) {
napi_valuetype valueType2 = napi_undefined;
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
return undefinedResult;
}
int64_t frameCount = 0;
napi_get_value_int64(env, args[PARAM1], &frameCount);
if (frameCount <= 0) {
@ -1018,6 +1018,28 @@ napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
std::static_pointer_cast<CapturerPeriodPositionCallbackNapi>(capturerNapi->periodPositionCBNapi_);
cb->SaveCallbackReference(callbackName, args[PARAM2]);
}
return undefinedResult;
}
// Two args on api call
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_function) {
return undefinedResult;
}
CHECK_AND_RETURN_RET_LOG(capturerNapi->callbackNapi_ != nullptr, undefinedResult,
"AudioCapturerNapi: callbackNapi_ is nullptr");
std::shared_ptr<AudioCapturerCallbackNapi> cb =
std::static_pointer_cast<AudioCapturerCallbackNapi>(capturerNapi->callbackNapi_);
cb->SaveCallbackReference(callbackName, args[PARAM1]);
if (!callbackName.compare(STATE_CHANGE_CALLBACK_NAME)) {
if (capturerNapi->audioCapturer_ != nullptr) {
CapturerState state = capturerNapi->audioCapturer_->GetStatus();
if (state == CAPTURER_PREPARED) {
capturerNapi->callbackNapi_->OnStateChange(state);
}
}
}
return undefinedResult;
@ -1048,7 +1070,7 @@ napi_value AudioCapturerNapi::Off(napi_env env, napi_callback_info info)
return undefinedResult;
}
std::string callbackName = GetStringArgument(env, args[0]);
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
HiLog::Info(LABEL, "AudioCapturerNapi: callbackName: %{public}s", callbackName.c_str());
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
if (capturerNapi->positionCBNapi_ != nullptr) {
@ -1240,7 +1262,7 @@ napi_value AudioCapturerNapi::CreateAudioCapturerWrapper(napi_env env, unique_pt
return result;
}
}
HiLog::Error(LABEL, "Failed in CreateAudioRendererWrapper, %{public}d", status);
HiLog::Error(LABEL, "Failed in CreateAudioCapturerWrapper, %{public}d", status);
}
napi_get_undefined(env, &result);

View File

@ -21,6 +21,18 @@
namespace OHOS {
namespace AudioStandard {
namespace {
const std::string INTERRUPT_CALLBACK_NAME = "interrupt";
const std::string STATE_CHANGE_CALLBACK_NAME = "stateChange";
}
class AudioCommonNapi {
public:
AudioCommonNapi() = delete;
~AudioCommonNapi() = delete;
static std::string GetStringArgument(napi_env env, napi_value value);
};
struct AutoRef {
AutoRef(napi_env env, napi_ref cb)
: env_(env), cb_(cb)

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "audio_common_napi.h"
#include "media_log.h"
namespace OHOS {
namespace AudioStandard {
std::string AudioCommonNapi::GetStringArgument(napi_env env, napi_value value)
{
std::string strValue = "";
size_t bufLength = 0;
napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
if (status == napi_ok && bufLength > 0 && bufLength < PATH_MAX) {
char *buffer = (char *)malloc((bufLength + 1) * sizeof(char));
CHECK_AND_RETURN_RET_LOG(buffer != nullptr, strValue, "no memory");
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
if (status == napi_ok) {
MEDIA_DEBUG_LOG("argument = %{public}s", buffer);
strValue = buffer;
}
free(buffer);
buffer = nullptr;
}
return strValue;
}
} // namespace AudioStandard
} // namespace OHOS

View File

@ -16,6 +16,7 @@
#include "audio_manager_napi.h"
#include "audio_capturer_napi.h"
#include "audio_common_napi.h"
#include "audio_device_descriptor_napi.h"
#include "audio_errors.h"
#include "audio_parameters_napi.h"
@ -673,30 +674,6 @@ napi_value AudioManagerNapi::GetAudioManager(napi_env env, napi_callback_info in
return AudioManagerNapi::CreateAudioManagerWrapper(env);
}
// Function to read string argument from napi_value
static string GetStringArgument(napi_env env, napi_value value)
{
napi_status status;
string strValue = "";
size_t bufLength = 0;
char *buffer = nullptr;
status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
if (status == napi_ok && bufLength > 0) {
buffer = (char *)malloc((bufLength + 1) * sizeof(char));
if (buffer != nullptr) {
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
if (status == napi_ok) {
strValue = buffer;
}
free(buffer);
buffer = nullptr;
}
}
return strValue;
}
static void CommonCallbackRoutine(napi_env env, AudioManagerAsyncContext* &asyncContext, const napi_value &valueParam)
{
napi_value result[ARGS_TWO] = {0};
@ -1463,9 +1440,9 @@ napi_value AudioManagerNapi::SetAudioParameter(napi_env env, napi_callback_info
napi_typeof(env, argv[i], &valueType);
if (i == PARAM0 && valueType == napi_string) {
asyncContext->key = GetStringArgument(env, argv[i]);
asyncContext->key = AudioCommonNapi::GetStringArgument(env, argv[i]);
} else if (i == PARAM1 && valueType == napi_string) {
asyncContext->valueStr = GetStringArgument(env, argv[i]);
asyncContext->valueStr = AudioCommonNapi::GetStringArgument(env, argv[i]);
} else if (i == PARAM2 && valueType == napi_function) {
napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
break;
@ -1524,7 +1501,7 @@ napi_value AudioManagerNapi::GetAudioParameter(napi_env env, napi_callback_info
napi_typeof(env, argv[i], &valueType);
if (i == PARAM0 && valueType == napi_string) {
asyncContext->key = GetStringArgument(env, argv[i]);
asyncContext->key = AudioCommonNapi::GetStringArgument(env, argv[i]);
} else if (i == PARAM1 && valueType == napi_function) {
napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
break;
@ -1934,8 +1911,8 @@ napi_value AudioManagerNapi::On(napi_env env, napi_callback_info info)
return undefinedResult;
}
std::string callbackName = GetStringArgument(env, args[0]);
MEDIA_INFO_LOG("AudioManagerNapi: callbackName: %{public}s", callbackName.c_str());
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
MEDIA_DEBUG_LOG("AudioManagerNapi: callbackName: %{public}s", callbackName.c_str());
if (!callbackName.compare(RINGERMODE_CALLBACK_NAME)) {
if (managerNapi->ringerModecallbackNapi_ == nullptr) {
managerNapi->ringerModecallbackNapi_ = std::make_shared<AudioRingerModeCallbackNapi>(env);

View File

@ -13,8 +13,8 @@
* limitations under the License.
*/
#ifndef AUDIO_MANAGER_CALLBACK_NAPI_H_
#define AUDIO_MANAGER_CALLBACK_NAPI_H_
#ifndef AUDIO_RENDERER_CALLBACK_NAPI_H_
#define AUDIO_RENDERER_CALLBACK_NAPI_H_
#include "audio_common_napi.h"
#include "audio_renderer.h"
@ -29,20 +29,23 @@ public:
virtual ~AudioRendererCallbackNapi();
void SaveCallbackReference(const std::string &callbackName, napi_value callback);
void OnInterrupt(const InterruptEvent &interruptEvent) override;
void OnStateChange(const RendererState state) override;
private:
struct AudioRendererJsCallback {
std::shared_ptr<AutoRef> callback = nullptr;
std::string callbackName = "unknown";
InterruptEvent interruptEvent;
RendererState state;
};
void OnJsCallbackInterrupt(std::unique_ptr<AudioRendererJsCallback> &jsCb);
void OnJsCallbackStateChange(std::unique_ptr<AudioRendererJsCallback> &jsCb);
std::mutex mutex_;
napi_env env_ = nullptr;
std::shared_ptr<AutoRef> interruptCallback_ = nullptr;
std::shared_ptr<AutoRef> stateChangeCallback_ = nullptr;
};
} // namespace AudioStandard
} // namespace OHOS
#endif // AUDIO_MANAGER_CALLBACK_NAPI_H_
#endif // AUDIO_RENDERER_CALLBACK_NAPI_H_

View File

@ -20,10 +20,6 @@
#include "audio_errors.h"
#include "media_log.h"
namespace {
const std::string INTERRUPT_CALLBACK_NAME = "interrupt";
}
namespace OHOS {
namespace AudioStandard {
AudioRendererCallbackNapi::AudioRendererCallbackNapi(napi_env env)
@ -49,6 +45,8 @@ void AudioRendererCallbackNapi::SaveCallbackReference(const std::string &callbac
std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
if (callbackName == INTERRUPT_CALLBACK_NAME) {
interruptCallback_ = cb;
} else if (callbackName == STATE_CHANGE_CALLBACK_NAME) {
stateChangeCallback_ = cb;
} else {
MEDIA_ERR_LOG("AudioRendererCallbackNapi: Unknown callback type: %{public}s", callbackName.c_str());
}
@ -108,7 +106,7 @@ void AudioRendererCallbackNapi::OnJsCallbackInterrupt(std::unique_ptr<AudioRende
napi_ref callback = event->callback->cb_;
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: JsCallBack %{public}s, uv_queue_work start", request.c_str());
do {
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s cancelled", request.c_str());
napi_value jsCallback = nullptr;
napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
@ -136,5 +134,72 @@ void AudioRendererCallbackNapi::OnJsCallbackInterrupt(std::unique_ptr<AudioRende
jsCb.release();
}
}
void AudioRendererCallbackNapi::OnStateChange(const RendererState state)
{
std::lock_guard<std::mutex> lock(mutex_);
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: OnStateChange is called");
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: state: %{public}d", state);
CHECK_AND_RETURN_LOG(stateChangeCallback_ != nullptr, "Cannot find the reference of stateChange callback");
std::unique_ptr<AudioRendererJsCallback> cb = std::make_unique<AudioRendererJsCallback>();
CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
cb->callback = stateChangeCallback_;
cb->callbackName = STATE_CHANGE_CALLBACK_NAME;
cb->state = state;
return OnJsCallbackStateChange(cb);
}
void AudioRendererCallbackNapi::OnJsCallbackStateChange(std::unique_ptr<AudioRendererJsCallback> &jsCb)
{
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(env_, &loop);
if (loop == nullptr) {
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
MEDIA_ERR_LOG("AudioRendererCallbackNapi: OnJsCallbackStateChange: No memory");
return;
}
work->data = reinterpret_cast<void *>(jsCb.get());
int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
// Js Thread
AudioRendererJsCallback *event = reinterpret_cast<AudioRendererJsCallback *>(work->data);
std::string request = event->callbackName;
napi_env env = event->callback->env_;
napi_ref callback = event->callback->cb_;
MEDIA_DEBUG_LOG("AudioRendererCallbackNapi: JsCallBack %{public}s, uv_queue_work start", request.c_str());
do {
CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s cancelled", request.c_str());
napi_value jsCallback = nullptr;
napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
request.c_str());
// Call back function
napi_value args[1] = { nullptr };
nstatus = napi_create_int32(env, event->state, &args[0]);
CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
"%{public}s fail to create Interrupt callback", request.c_str());
const size_t argCount = 1;
napi_value result = nullptr;
nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call Interrupt callback", request.c_str());
} while (0);
delete event;
delete work;
});
if (ret != 0) {
MEDIA_ERR_LOG("Failed to execute libuv work queue");
delete work;
} else {
jsCb.release();
}
}
} // namespace AudioStandard
} // namespace OHOS

View File

@ -18,6 +18,7 @@
#include "renderer_period_position_callback_napi.h"
#include "renderer_position_callback_napi.h"
#include "audio_common_napi.h"
#include "audio_errors.h"
#include "audio_manager_napi.h"
#include "audio_parameters_napi.h"
@ -51,7 +52,6 @@ namespace {
constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioRendererNapi"};
const std::string INTERRUPT_CALLBACK_NAME = "interrupt";
const std::string MARK_REACH_CALLBACK_NAME = "markReach";
const std::string PERIOD_REACH_CALLBACK_NAME = "periodReach";
@ -422,11 +422,12 @@ napi_value AudioRendererNapi::Construct(napi_env env, napi_callback_info info)
{
napi_status status;
napi_value result = nullptr;
napi_get_undefined(env, &result);
GET_PARAMS(env, info, ARGS_TWO);
unique_ptr<AudioRendererNapi> rendererNapi = make_unique<AudioRendererNapi>();
CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, nullptr, "No memory");
CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, result, "No memory");
rendererNapi->env_ = env;
rendererNapi->contentType_ = sAudioRendererOptions_->rendererInfo.contentType;
@ -434,7 +435,7 @@ napi_value AudioRendererNapi::Construct(napi_env env, napi_callback_info info)
rendererNapi->rendererFlags_ = sAudioRendererOptions_->rendererInfo.rendererFlags;
rendererNapi->audioRenderer_ = AudioRenderer::Create(*sAudioRendererOptions_);
CHECK_AND_RETURN_RET_LOG(rendererNapi->audioRenderer_ != nullptr, nullptr, "No memory");
CHECK_AND_RETURN_RET_LOG(rendererNapi->audioRenderer_ != nullptr, result, "Renderer Create failed");
if (rendererNapi->callbackNapi_ == nullptr) {
rendererNapi->callbackNapi_ = std::make_shared<AudioRendererCallbackNapi>(env);
@ -1646,30 +1647,6 @@ napi_value AudioRendererNapi::GetState(napi_env env, napi_callback_info info)
return jsResult;
}
// Function to read string argument from napi_value
static string GetStringArgument(napi_env env, napi_value value)
{
napi_status status;
string strValue = "";
size_t bufLength = 0;
char *buffer = nullptr;
status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
if (status == napi_ok && bufLength > 0) {
buffer = (char *)malloc((bufLength + 1) * sizeof(char));
if (buffer != nullptr) {
status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
if (status == napi_ok) {
strValue = buffer;
}
free(buffer);
buffer = nullptr;
}
}
return strValue;
}
napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
{
napi_value undefinedResult = nullptr;
@ -1680,17 +1657,20 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
napi_value args[maxArgCount] = { nullptr, nullptr, nullptr };
napi_value jsThis = nullptr;
napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
if (argCount == maxArgCount - 1) { // onInterrupt
if (argCount == maxArgCount - 1) { // 2 args on api
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr) {
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
return undefinedResult;
}
} else { // mark/position reach
} else if (argCount == maxArgCount) { // mark/position reach
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr || args[PARAM1] == nullptr ||
args[PARAM2] == nullptr) {
HiLog::Error(LABEL, "On fail to napi_get_cb_info");
return undefinedResult;
}
} else {
MEDIA_DEBUG_LOG("AudioRendererNapi:: on called with wrong number of args");
return undefinedResult;
}
AudioRendererNapi *rendererNapi = nullptr;
@ -1699,29 +1679,19 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
NAPI_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, "audio renderer instance is null.");
napi_valuetype valueType0 = napi_undefined;
napi_valuetype valueType1 = napi_undefined;
// Check value type of PARAM0
if (napi_typeof(env, args[PARAM0], &valueType0) != napi_ok || valueType0 != napi_string) {
return undefinedResult;
}
std::string callbackName = GetStringArgument(env, args[0]);
MEDIA_DEBUG_LOG("AudioRenderNapi: callbackName: %{public}s", callbackName.c_str());
if (!callbackName.compare(INTERRUPT_CALLBACK_NAME)) {
napi_valuetype valueType1 = napi_undefined;
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_function) {
return undefinedResult;
}
CHECK_AND_RETURN_RET_LOG(rendererNapi->callbackNapi_ != nullptr, undefinedResult,
"AudioRendererNapi: callbackNapi_ is nullptr");
std::shared_ptr<AudioRendererCallbackNapi> cb =
std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
cb->SaveCallbackReference(callbackName, args[PARAM1]);
} else if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
napi_valuetype valueType1 = napi_undefined;
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
HiLog::Info(LABEL, "AudioRendererNapi: callbackName: %{public}s", callbackName.c_str());
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
napi_valuetype valueType2 = napi_undefined;
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
MEDIA_DEBUG_LOG("AudioRenderNapi: On wrong parameters");
return undefinedResult;
}
@ -1733,23 +1703,23 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
}
if (rendererNapi->positionCBNapi_ == nullptr) {
MEDIA_DEBUG_LOG("AudioRenderNapi: positionCBNapi_ is null");
rendererNapi->positionCBNapi_ = std::make_shared<RendererPositionCallbackNapi>(env);
int32_t ret = rendererNapi->audioRenderer_->SetRendererPositionCallback(markPosition,
rendererNapi->positionCBNapi_);
if (ret) {
MEDIA_ERR_LOG("AudioRendererNapi: SetRendererPositionCallback Failed");
HiLog::Error(LABEL, "AudioRendererNapi: SetRendererPositionCallback Failed");
return undefinedResult;
} else {
MEDIA_DEBUG_LOG("AudioRendererNapi: SetRendererPositionCallback Success");
HiLog::Debug(LABEL, "AudioRendererNapi: SetRendererPositionCallback Success");
}
std::shared_ptr<RendererPositionCallbackNapi> cb =
std::static_pointer_cast<RendererPositionCallbackNapi>(rendererNapi->positionCBNapi_);
cb->SaveCallbackReference(callbackName, args[PARAM2]);
}
return undefinedResult;
} else if (!callbackName.compare(PERIOD_REACH_CALLBACK_NAME)) {
napi_valuetype valueType1 = napi_undefined;
napi_valuetype valueType2 = napi_undefined;
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_number
|| napi_typeof(env, args[PARAM2], &valueType2) != napi_ok || valueType2 != napi_function) {
@ -1768,29 +1738,52 @@ napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
int32_t ret = rendererNapi->audioRenderer_->SetRendererPeriodPositionCallback(frameCount,
rendererNapi->periodPositionCBNapi_);
if (ret) {
MEDIA_ERR_LOG("AudioRendererNapi: SetRendererPeriodPositionCallback Failed");
HiLog::Error(LABEL, "AudioRendererNapi: SetRendererPeriodPositionCallback Failed");
return undefinedResult;
} else {
MEDIA_DEBUG_LOG("AudioRendererNapi: SetRendererPeriodPositionCallback Success");
HiLog::Debug(LABEL, "AudioRendererNapi: SetRendererPeriodPositionCallback Success");
}
std::shared_ptr<RendererPeriodPositionCallbackNapi> cb =
std::static_pointer_cast<RendererPeriodPositionCallbackNapi>(rendererNapi->periodPositionCBNapi_);
cb->SaveCallbackReference(callbackName, args[PARAM2]);
}
return undefinedResult;
}
// Two args on api call
if (napi_typeof(env, args[PARAM1], &valueType1) != napi_ok || valueType1 != napi_function) {
return undefinedResult;
}
CHECK_AND_RETURN_RET_LOG(rendererNapi->callbackNapi_ != nullptr, undefinedResult,
"AudioRendererNapi: callbackNapi_ is nullptr");
std::shared_ptr<AudioRendererCallbackNapi> cb =
std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
cb->SaveCallbackReference(callbackName, args[PARAM1]);
if (!callbackName.compare(STATE_CHANGE_CALLBACK_NAME)) {
if (rendererNapi->audioRenderer_ != nullptr) {
RendererState state = rendererNapi->audioRenderer_->GetStatus();
if (state == RENDERER_PREPARED) {
rendererNapi->callbackNapi_->OnStateChange(state);
}
}
}
return undefinedResult;
}
napi_value AudioRendererNapi::Off(napi_env env, napi_callback_info info)
{
napi_value undefinedResult = nullptr;
napi_get_undefined(env, &undefinedResult);
const size_t maxArgCount = 1;
size_t argCount = maxArgCount;
napi_value args[maxArgCount] = { nullptr };
const size_t minArgCount = 1;
size_t argCount = minArgCount;
napi_value args[minArgCount] = { nullptr };
napi_value jsThis = nullptr;
napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
if (status != napi_ok || jsThis == nullptr || args[PARAM0] == nullptr) {
@ -1808,7 +1801,7 @@ napi_value AudioRendererNapi::Off(napi_env env, napi_callback_info info)
return undefinedResult;
}
std::string callbackName = GetStringArgument(env, args[0]);
std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
if (!callbackName.compare(MARK_REACH_CALLBACK_NAME)) {
if (rendererNapi->positionCBNapi_ != nullptr) {
MEDIA_DEBUG_LOG("AudioRenderNapi: positionCBNapi_ is not null");

View File

@ -25,6 +25,7 @@ class AudioCapturerPrivate : public AudioCapturer {
public:
int32_t GetFrameCount(uint32_t &frameCount) const override;
int32_t SetParams(const AudioCapturerParams params) const override;
int32_t SetCapturerCallback(const std::shared_ptr<AudioCapturerCallback> &callback) override;
int32_t GetParams(AudioCapturerParams &params) const override;
int32_t GetCapturerInfo(AudioCapturerInfo &capturerInfo) const override;
int32_t GetStreamInfo(AudioStreamInfo &streamInfo) const override;
@ -43,11 +44,23 @@ public:
const std::shared_ptr<CapturerPeriodPositionCallback> &callback) override;
void UnsetCapturerPeriodPositionCallback() override;
std::unique_ptr<AudioStream> audioCapturer;
std::shared_ptr<AudioStream> audioStream_;
AudioCapturerInfo capturerInfo_ = {};
explicit AudioCapturerPrivate(AudioStreamType audioStreamType);
virtual ~AudioCapturerPrivate();
private:
std::shared_ptr<AudioStreamCallback> audioStreamCallback_ = nullptr;
};
class AudioStreamCallbackCapturer : public AudioStreamCallback {
public:
virtual ~AudioStreamCallbackCapturer() = default;
void OnStateChange(const State state) override;
void SaveCallback(const std::weak_ptr<AudioCapturerCallback> &callback);
private:
std::weak_ptr<AudioCapturerCallback> callback_;
};
} // namespace AudioStandard
} // namespace OHOS

View File

@ -18,6 +18,7 @@
#include "audio_capturer_private.h"
#include "audio_errors.h"
#include "audio_stream.h"
#include "media_log.h"
namespace OHOS {
namespace AudioStandard {
@ -65,12 +66,12 @@ std::unique_ptr<AudioCapturer> AudioCapturer::Create(const AudioCapturerOptions
AudioCapturerPrivate::AudioCapturerPrivate(AudioStreamType audioStreamType)
{
audioCapturer = std::make_unique<AudioStream>(audioStreamType, AUDIO_MODE_RECORD);
audioStream_ = std::make_shared<AudioStream>(audioStreamType, AUDIO_MODE_RECORD);
}
int32_t AudioCapturerPrivate::GetFrameCount(uint32_t &frameCount) const
{
return audioCapturer->GetFrameCount(frameCount);
return audioStream_->GetFrameCount(frameCount);
}
int32_t AudioCapturerPrivate::SetParams(const AudioCapturerParams params) const
@ -81,13 +82,43 @@ int32_t AudioCapturerPrivate::SetParams(const AudioCapturerParams params) const
audioStreamParams.channels = params.audioChannel;
audioStreamParams.encoding = params.audioEncoding;
return audioCapturer->SetAudioStreamInfo(audioStreamParams);
return audioStream_->SetAudioStreamInfo(audioStreamParams);
}
int32_t AudioCapturerPrivate::SetCapturerCallback(const std::shared_ptr<AudioCapturerCallback> &callback)
{
// If the client is using the deprecated SetParams API. SetCapturerCallback must be invoked, after SetParams.
// In general, callbacks can only be set after the capturer state is PREPARED.
CapturerState state = GetStatus();
if (state == CAPTURER_NEW || state == CAPTURER_RELEASED) {
MEDIA_DEBUG_LOG("AudioCapturerPrivate::SetCapturerCallback ncorrect state:%{public}d to register cb", state);
return ERR_ILLEGAL_STATE;
}
if (callback == nullptr) {
MEDIA_ERR_LOG("AudioCapturerPrivate::SetCapturerCallback callback param is null");
return ERR_INVALID_PARAM;
}
// Save and Set reference for stream callback. Order is important here.
if (audioStreamCallback_ == nullptr) {
audioStreamCallback_ = std::make_shared<AudioStreamCallbackCapturer>();
if (audioStreamCallback_ == nullptr) {
MEDIA_ERR_LOG("AudioCapturerPrivate::Failed to allocate memory for audioStreamCallback_");
return ERROR;
}
}
std::shared_ptr<AudioStreamCallbackCapturer> cbStream =
std::static_pointer_cast<AudioStreamCallbackCapturer>(audioStreamCallback_);
cbStream->SaveCallback(callback);
(void)audioStream_->SetStreamCallback(audioStreamCallback_);
return SUCCESS;
}
int32_t AudioCapturerPrivate::GetParams(AudioCapturerParams &params) const
{
AudioStreamParams audioStreamParams;
int32_t result = audioCapturer->GetAudioStreamInfo(audioStreamParams);
int32_t result = audioStream_->GetAudioStreamInfo(audioStreamParams);
if (SUCCESS == result) {
params.audioSampleFormat = static_cast<AudioSampleFormat>(audioStreamParams.format);
params.samplingRate = static_cast<AudioSamplingRate>(audioStreamParams.samplingRate);
@ -108,7 +139,7 @@ int32_t AudioCapturerPrivate::GetCapturerInfo(AudioCapturerInfo &capturerInfo) c
int32_t AudioCapturerPrivate::GetStreamInfo(AudioStreamInfo &streamInfo) const
{
AudioStreamParams audioStreamParams;
int32_t result = audioCapturer->GetAudioStreamInfo(audioStreamParams);
int32_t result = audioStream_->GetAudioStreamInfo(audioStreamParams);
if (SUCCESS == result) {
streamInfo.format = static_cast<AudioSampleFormat>(audioStreamParams.format);
streamInfo.samplingRate = static_cast<AudioSamplingRate>(audioStreamParams.samplingRate);
@ -122,67 +153,83 @@ int32_t AudioCapturerPrivate::GetStreamInfo(AudioStreamInfo &streamInfo) const
int32_t AudioCapturerPrivate::SetCapturerPositionCallback(int64_t markPosition,
const std::shared_ptr<CapturerPositionCallback> &callback)
{
audioCapturer->SetCapturerPositionCallback(markPosition, callback);
audioStream_->SetCapturerPositionCallback(markPosition, callback);
return SUCCESS;
}
void AudioCapturerPrivate::UnsetCapturerPositionCallback()
{
audioCapturer->UnsetCapturerPositionCallback();
audioStream_->UnsetCapturerPositionCallback();
}
int32_t AudioCapturerPrivate::SetCapturerPeriodPositionCallback(int64_t frameNumber,
const std::shared_ptr<CapturerPeriodPositionCallback> &callback)
{
audioCapturer->SetCapturerPeriodPositionCallback(frameNumber, callback);
audioStream_->SetCapturerPeriodPositionCallback(frameNumber, callback);
return SUCCESS;
}
void AudioCapturerPrivate::UnsetCapturerPeriodPositionCallback()
{
audioCapturer->UnsetCapturerPeriodPositionCallback();
audioStream_->UnsetCapturerPeriodPositionCallback();
}
bool AudioCapturerPrivate::Start() const
{
return audioCapturer->StartAudioStream();
return audioStream_->StartAudioStream();
}
int32_t AudioCapturerPrivate::Read(uint8_t &buffer, size_t userSize, bool isBlockingRead) const
{
return audioCapturer->Read(buffer, userSize, isBlockingRead);
return audioStream_->Read(buffer, userSize, isBlockingRead);
}
CapturerState AudioCapturerPrivate::GetStatus() const
{
return (CapturerState)audioCapturer->GetState();
return (CapturerState)audioStream_->GetState();
}
bool AudioCapturerPrivate::GetAudioTime(Timestamp &timestamp, Timestamp::Timestampbase base) const
{
return audioCapturer->GetAudioTime(timestamp, base);
return audioStream_->GetAudioTime(timestamp, base);
}
bool AudioCapturerPrivate::Stop() const
{
return audioCapturer->StopAudioStream();
return audioStream_->StopAudioStream();
}
bool AudioCapturerPrivate::Flush() const
{
return audioCapturer->FlushAudioStream();
return audioStream_->FlushAudioStream();
}
bool AudioCapturerPrivate::Release() const
{
return audioCapturer->ReleaseAudioStream();
return audioStream_->ReleaseAudioStream();
}
int32_t AudioCapturerPrivate::GetBufferSize(size_t &bufferSize) const
{
return audioCapturer->GetBufferSize(bufferSize);
return audioStream_->GetBufferSize(bufferSize);
}
void AudioStreamCallbackCapturer::SaveCallback(const std::weak_ptr<AudioCapturerCallback> &callback)
{
callback_ = callback;
}
void AudioStreamCallbackCapturer::OnStateChange(const State state)
{
std::shared_ptr<AudioCapturerCallback> cb = callback_.lock();
if (cb == nullptr) {
MEDIA_ERR_LOG("AudioStreamCallbackCapturer::OnStateChange cb == nullptr.");
return;
}
cb->OnStateChange(static_cast<CapturerState>(state));
}
std::vector<AudioSampleFormat> AudioCapturer::GetSupportedFormats()

View File

@ -63,8 +63,8 @@ public:
~AudioRendererPrivate();
private:
std::shared_ptr<AudioRendererCallback> callback_ = nullptr;
std::shared_ptr<AudioInterruptCallback> audioInterruptCallback_ = nullptr;
std::shared_ptr<AudioStreamCallback> audioStreamCallback_ = nullptr;
AudioInterrupt audioInterrupt_ =
{STREAM_USAGE_UNKNOWN, CONTENT_TYPE_UNKNOWN, AudioStreamType::STREAM_DEFAULT, 0};
uint32_t sessionID_ = INVALID_SESSION_ID;
@ -91,6 +91,16 @@ private:
bool isForceDucked_ = false;
float instanceVolBeforeDucking_ = 0.2f;
};
class AudioStreamCallbackRenderer : public AudioStreamCallback {
public:
virtual ~AudioStreamCallbackRenderer() = default;
void OnStateChange(const State state) override;
void SaveCallback(const std::weak_ptr<AudioRendererCallback> &callback);
private:
std::weak_ptr<AudioRendererCallback> callback_;
};
} // namespace AudioStandard
} // namespace OHOS
#endif // AUDIO_RENDERER_PRIVATE_H

View File

@ -40,12 +40,12 @@ std::unique_ptr<AudioRenderer> AudioRenderer::Create(AudioStreamType audioStream
std::unique_ptr<AudioRenderer> AudioRenderer::Create(const AudioRendererOptions &rendererOptions)
{
ContentType contentType = rendererOptions.rendererInfo.contentType;
CHECK_AND_RETURN_RET_LOG(contentType >= CONTENT_TYPE_SPEECH && contentType <= CONTENT_TYPE_RINGTONE, nullptr,
CHECK_AND_RETURN_RET_LOG(contentType >= CONTENT_TYPE_UNKNOWN && contentType <= CONTENT_TYPE_RINGTONE, nullptr,
"Invalid content type");
StreamUsage streamUsage = rendererOptions.rendererInfo.streamUsage;
CHECK_AND_RETURN_RET_LOG(streamUsage >= STREAM_USAGE_MEDIA && streamUsage <= STREAM_USAGE_VOICE_ASSISTANT, nullptr,
"Invalid stream usage");
CHECK_AND_RETURN_RET_LOG(streamUsage >= STREAM_USAGE_UNKNOWN && streamUsage <= STREAM_USAGE_VOICE_ASSISTANT,
nullptr, "Invalid stream usage");
AudioStreamType audioStreamType = AudioStream::GetStreamType(contentType, streamUsage);
auto audioRenderer = std::make_unique<AudioRendererPrivate>(audioStreamType);
@ -156,9 +156,11 @@ int32_t AudioRendererPrivate::GetStreamInfo(AudioStreamInfo &streamInfo) const
int32_t AudioRendererPrivate::SetRendererCallback(const std::shared_ptr<AudioRendererCallback> &callback)
{
// If the client is using the deprecated SetParams API. SetRendererCallback must be invoked, after SetParams.
// In general, callbacks can only be set after the renderer state is PREPARED.
RendererState state = GetStatus();
if (state != RENDERER_PREPARED) {
MEDIA_DEBUG_LOG("AudioRendererPrivate::SetRendererCallback State is not PREPARED to register callback");
if (state == RENDERER_NEW || state == RENDERER_RELEASED) {
MEDIA_DEBUG_LOG("AudioRendererPrivate::SetRendererCallback incorrect state:%{public}d to register cb", state);
return ERR_ILLEGAL_STATE;
}
if (callback == nullptr) {
@ -166,12 +168,28 @@ int32_t AudioRendererPrivate::SetRendererCallback(const std::shared_ptr<AudioRen
return ERR_INVALID_PARAM;
}
callback_ = callback;
// Save reference for interrupt callback
if (audioInterruptCallback_ == nullptr) {
MEDIA_ERR_LOG("AudioRendererPrivate::SetRendererCallback audioInterruptCallback_ == nullptr");
return ERROR;
}
std::shared_ptr<AudioInterruptCallbackImpl> cbInterrupt =
std::static_pointer_cast<AudioInterruptCallbackImpl>(audioInterruptCallback_);
cbInterrupt->SaveCallback(callback);
// Save and Set reference for stream callback. Order is important here.
if (audioStreamCallback_ == nullptr) {
audioStreamCallback_ = std::make_shared<AudioStreamCallbackRenderer>();
if (audioStreamCallback_ == nullptr) {
MEDIA_ERR_LOG("AudioRendererPrivate::Failed to allocate memory for audioStreamCallback_");
return ERROR;
}
}
std::shared_ptr<AudioStreamCallbackRenderer> cbStream =
std::static_pointer_cast<AudioStreamCallbackRenderer>(audioStreamCallback_);
cbStream->SaveCallback(callback);
(void)audioStream_->SetStreamCallback(audioStreamCallback_);
return SUCCESS;
}
@ -463,6 +481,21 @@ void AudioInterruptCallbackImpl::OnInterrupt(const InterruptEventInternal &inter
HandleAndNotifyForcedEvent(interruptEvent);
}
void AudioStreamCallbackRenderer::SaveCallback(const std::weak_ptr<AudioRendererCallback> &callback)
{
callback_ = callback;
}
void AudioStreamCallbackRenderer::OnStateChange(const State state)
{
std::shared_ptr<AudioRendererCallback> cb = callback_.lock();
if (cb == nullptr) {
MEDIA_ERR_LOG("AudioStreamCallbackRenderer::OnStateChange cb == nullptr.");
return;
}
cb->OnStateChange(static_cast<RendererState>(state));
}
std::vector<AudioSampleFormat> AudioRenderer::GetSupportedFormats()
{

View File

@ -25,29 +25,6 @@ enum AudioMode {
AUDIO_MODE_RECORD
};
/**
* @brief Enumerates the stream states of the current device.
*
* @since 1.0
* @version 1.0
*/
enum State {
/** INVALID */
INVALID = -1,
/** New */
NEW,
/** Prepared */
PREPARED,
/** Running */
RUNNING,
/** Stopped */
STOPPED,
/** Released */
RELEASED,
/** Paused */
PAUSED
};
class AudioStream : public AudioSession {
public:
AudioStream(AudioStreamType eStreamType, AudioMode eMode);
@ -68,6 +45,7 @@ public:
float GetVolume();
int32_t SetRenderRate(AudioRendererRate renderRate);
AudioRendererRate GetRenderRate();
int32_t SetStreamCallback(const std::shared_ptr<AudioStreamCallback> &callback);
std::vector<AudioSampleFormat> GetSupportedFormats();
std::vector<AudioChannel> GetSupportedChannels();

View File

@ -49,6 +49,8 @@ ohos_shared_library("audio_capturer") {
public_configs = [ ":audio_external_library_config" ]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
part_name = "multimedia_audio_standard"
subsystem_name = "multimedia"
}

View File

@ -59,6 +59,18 @@ enum CapturerState {
CAPTURER_RELEASED
};
class AudioCapturerCallback {
public:
virtual ~AudioCapturerCallback() = default;
/**
* Called when renderer state is updated.
*
* @param state Indicates updated state of the capturer.
* For details, refer enum CapturerState.
*/
virtual void OnStateChange(const CapturerState state) = 0;
};
class CapturerPositionCallback {
public:
virtual ~CapturerPositionCallback() = default;
@ -98,15 +110,6 @@ public:
*/
static std::unique_ptr<AudioCapturer> Create(const AudioCapturerOptions &capturerOptions);
/**
* @brief Obtains the number of frames required in the current condition, in bytes per sample.
*
* @param frameCount Indicates the pointer in which framecount will be written
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
/**
* @brief Sets audio capture parameters.
*
@ -117,6 +120,18 @@ public:
*/
virtual int32_t SetParams(const AudioCapturerParams params) const = 0;
/**
* @brief Registers the capturer callback listener.
* (1)If old SetParams(const AudioCapturerParams params) API,
* this API must be called immediately after SetParams.
* (2) Else if using Create(const AudioCapturerOptions &capturerOptions),
* this API must be called immediately after Create.
*
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t SetCapturerCallback(const std::shared_ptr<AudioCapturerCallback> &callback) = 0;
/**
* @brief Obtains audio capturer parameters.
*
@ -223,12 +238,21 @@ public:
*/
virtual int32_t GetBufferSize(size_t &bufferSize) const = 0;
/* @brief Obtains the number of frames required in the current condition, in bytes per sample.
*
* @param frameCount Indicates the pointer in which framecount will be written
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
/**
* @brief Registers the capturer position callback listener
*
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t SetCapturerPositionCallback(int64_t markPosition,
const std::shared_ptr<CapturerPositionCallback> &callback) = 0;

View File

@ -69,6 +69,14 @@ public:
* For details, refer InterruptEvent struct in audio_info.h
*/
virtual void OnInterrupt(const InterruptEvent &interruptEvent) = 0;
/**
* Called when renderer state is updated.
*
* @param state Indicates updated state of the renderer.
* For details, refer RendererState enum.
*/
virtual void OnStateChange(const RendererState state) = 0;
};
class RendererPositionCallback {
@ -108,6 +116,7 @@ public:
* @return Returns unique pointer to the AudioRenderer object
*/
static std::unique_ptr<AudioRenderer> Create(AudioStreamType audioStreamType);
/**
* @brief creater renderer instance.
*
@ -116,14 +125,6 @@ public:
* @return Returns unique pointer to the AudioRenderer object
*/
static std::unique_ptr<AudioRenderer> Create(const AudioRendererOptions &rendererOptions);
/**
* @brief Obtains the number of frames required in the current condition, in bytes per sample.
*
* @param frameCount Indicates the reference variable in which framecount will be written
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
/**
* @brief Sets audio renderer parameters.
@ -135,6 +136,18 @@ public:
*/
virtual int32_t SetParams(const AudioRendererParams params) = 0;
/**
* @brief Registers the renderer callback listener.
* (1)If using old SetParams(const AudioCapturerParams params) API,
* this API must be called immediatley after SetParams.
* (2) Else if using Create(const AudioRendererOptions &rendererOptions),
* this API must be called immediatley after Create.
*
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t SetRendererCallback(const std::shared_ptr<AudioRendererCallback> &callback) = 0;
/**
* @brief Obtains audio renderer parameters.
*
@ -263,6 +276,15 @@ public:
*/
virtual int32_t GetBufferSize(size_t &bufferSize) const = 0;
/**
* @brief Obtains the number of frames required in the current condition, in bytes per sample.
*
* @param frameCount Indicates the reference variable in which framecount will be written
* @return Returns {@link SUCCESS} if frameCount is successfully obtained; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t GetFrameCount(uint32_t &frameCount) const = 0;
/**
* @brief Set audio renderer descriptors
*
@ -313,15 +335,6 @@ public:
*/
virtual AudioRendererRate GetRenderRate() const = 0;
/**
* @brief Registers the renderer callback listener
*
* @return Returns {@link SUCCESS} if callback registration is successful; returns an error code
* defined in {@link audio_errors.h} otherwise.
*/
virtual int32_t SetRendererCallback(const std::shared_ptr<AudioRendererCallback> &callback) = 0;
/**
* @brief Registers the renderer position callback listener
*

View File

@ -116,9 +116,9 @@ private:
uint32_t capturerFlags_;
napi_env env_;
napi_ref wrapper_;
std::shared_ptr<CapturerPositionCallback> positionCBNapi_ = nullptr;
std::shared_ptr<CapturerPeriodPositionCallback> periodPositionCBNapi_ = nullptr;
std::shared_ptr<AudioCapturerCallback> callbackNapi_ = nullptr;
};
}
}

View File

@ -1141,15 +1141,15 @@ declare namespace audio {
*/
off(type: "periodReach"): void;
/**
* Subscribes period reach event callback.
* Subscribes audio state change event callback.
* @param type Event type.
* @param callback Callback used to listen for the audio state event
* @return Audio state
* @param callback Callback used to listen for the audio state change event.
* @return AudioState
* @since 8
* @syscap SystemCapability.Multimedia.Audio
* @initial
*/
on(type: "stateChanged", callback: Callback<AudioState>): void;
on(type: "stateChange", callback: Callback<AudioState>): void;
}
/**
@ -1355,17 +1355,17 @@ declare namespace audio {
* @initial
*/
off(type: "periodReach"): void;
/**
* Subscribes period reach event callback.
* Subscribes audio state change event callback.
* @param type Event type.
* @param callback Callback used to listen for the audio state event
* @return Audio state
* @param callback Callback used to listen for the audio state change event.
* @return AudioState
* @since 8
* @syscap SystemCapability.Multimedia.Audio
* @initial
*/
on(type: "stateChanged", callback: Callback<AudioState>): void;
on(type: "stateChange", callback: Callback<AudioState>): void;
}
/**
@ -1536,4 +1536,4 @@ declare namespace audio {
}
}
export default audio;
export default audio;

View File

@ -46,10 +46,12 @@ ohos_shared_library("audio") {
]
sources = [
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/audio_capturer_callback_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/audio_capturer_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/audio_parameters_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/capturer_period_position_callback_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_capturer/src/capturer_position_callback_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_common/src/audio_common_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_manager/src/audio_device_descriptor_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_manager/src/audio_manager_callback_napi.cpp",
"//foundation/multimedia/audio_standard/frameworks/js/napi/audio_manager/src/audio_manager_napi.cpp",

View File

@ -62,6 +62,41 @@ struct AudioCache {
bool isFull;
};
/**
* @brief Enumerates the stream states of the current device.
*
* @since 1.0
* @version 1.0
*/
enum State {
/** INVALID */
INVALID = -1,
/** New */
NEW,
/** Prepared */
PREPARED,
/** Running */
RUNNING,
/** Stopped */
STOPPED,
/** Released */
RELEASED,
/** Paused */
PAUSED
};
class AudioStreamCallback {
public:
virtual ~AudioStreamCallback() = default;
/**
* Called when stream state is updated.
*
* @param state Indicates the InterruptEvent information needed by client.
* For details, refer InterruptEvent struct in audio_info.h
*/
virtual void OnStateChange(const State state) = 0;
};
class AudioRendererCallbacks {
public:
virtual ~AudioRendererCallbacks();
@ -388,6 +423,8 @@ public:
*/
AudioRendererRate GetStreamRenderRate();
void SaveStreamCallback(const std::weak_ptr<AudioStreamCallback> &callback);
// Audio timer callback
virtual void OnTimeOut();
@ -441,6 +478,10 @@ private:
std::vector<std::unique_ptr<std::thread>> mPositionCBThreads;
std::vector<std::unique_ptr<std::thread>> mPeriodPositionCBThreads;
std::weak_ptr<AudioStreamCallback> streamCallback_;
State state_;
pa_stream_success_cb_t PAStreamCorkSuccessCb;
// To be set while using audio stream
// functionality for callbacks
AudioRendererCallbacks *mAudioRendererCallbacks;
@ -495,13 +536,16 @@ private:
void ResetPAAudioClient();
// For setting some environment variables required while running from hap
void SetEnv();
int32_t CorkStream();
// Callbacks to be implemented
static void PAStreamStateCb(pa_stream *stream, void *userdata);
static void PAStreamUnderFlowCb(pa_stream *stream, void *userdata);
static void PAContextStateCb(pa_context *context, void *userdata);
static void PAStreamRequestCb(pa_stream *stream, size_t length, void *userdata);
static void PAStreamCmdSuccessCb(pa_stream *stream, int32_t success, void *userdata);
static void PAStreamStartSuccessCb(pa_stream *stream, int32_t success, void *userdata);
static void PAStreamStopSuccessCb(pa_stream *stream, int32_t success, void *userdata);
static void PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata);
static void PAStreamDrainSuccessCb(pa_stream *stream, int32_t success, void *userdata);
static void PAStreamFlushSuccessCb(pa_stream *stream, int32_t success, void *userdata);
static void PAStreamLatencyUpdateCb(pa_stream *stream, void *userdata);

View File

@ -128,11 +128,44 @@ static size_t AlignToAudioFrameSize(size_t l, const pa_sample_spec &ss)
return (l / fs) * fs;
}
void AudioServiceClient::PAStreamCmdSuccessCb(pa_stream *stream, int32_t success, void *userdata)
void AudioServiceClient::PAStreamStartSuccessCb(pa_stream *stream, int32_t success, void *userdata)
{
AudioServiceClient *asClient = (AudioServiceClient *)userdata;
pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asClient->mainLoop;
AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
asClient->state_ = RUNNING;
std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
if (streamCb != nullptr) {
streamCb->OnStateChange(asClient->state_);
}
asClient->streamCmdStatus = success;
pa_threaded_mainloop_signal(mainLoop, 0);
}
void AudioServiceClient::PAStreamStopSuccessCb(pa_stream *stream, int32_t success, void *userdata)
{
AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
asClient->state_ = STOPPED;
std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
if (streamCb != nullptr) {
streamCb->OnStateChange(asClient->state_);
}
asClient->streamCmdStatus = success;
pa_threaded_mainloop_signal(mainLoop, 0);
}
void AudioServiceClient::PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata)
{
AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
asClient->state_ = PAUSED;
std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
if (streamCb != nullptr) {
streamCb->OnStateChange(asClient->state_);
}
asClient->streamCmdStatus = success;
pa_threaded_mainloop_signal(mainLoop, 0);
}
@ -275,6 +308,8 @@ AudioServiceClient::AudioServiceClient()
acache.isFull = false;
acache.totalCacheSize = 0;
acache.buffer = NULL;
PAStreamCorkSuccessCb = PAStreamStopSuccessCb;
}
void AudioServiceClient::ResetPAAudioClient()
@ -345,6 +380,8 @@ void AudioServiceClient::ResetPAAudioClient()
acache.writeIndex = 0;
acache.isFull = false;
acache.totalCacheSize = 0;
PAStreamCorkSuccessCb = NULL;
}
AudioServiceClient::~AudioServiceClient()
@ -638,6 +675,12 @@ int32_t AudioServiceClient::CreateStream(AudioStreamParams audioParams, AudioStr
}
}
state_ = PREPARED;
std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
if (streamCb != nullptr) {
streamCb->OnStateChange(state_);
}
MEDIA_INFO_LOG("Created Stream");
return AUDIO_CLIENT_SUCCESS;
}
@ -674,7 +717,7 @@ int32_t AudioServiceClient::StartStream()
}
streamCmdStatus = 0;
operation = pa_stream_cork(paStream, 0, PAStreamCmdSuccessCb, (void *)this);
operation = pa_stream_cork(paStream, 0, PAStreamStartSuccessCb, (void *)this);
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
pa_threaded_mainloop_wait(mainLoop);
@ -694,12 +737,42 @@ int32_t AudioServiceClient::StartStream()
int32_t AudioServiceClient::PauseStream()
{
return StopStream();
lock_guard<mutex> lock(ctrlMutex);
PAStreamCorkSuccessCb = PAStreamPauseSuccessCb;
int32_t ret = CorkStream();
if (ret) {
return ret;
}
if (!streamCmdStatus) {
MEDIA_ERR_LOG("Stream Pasue Failed");
return AUDIO_CLIENT_ERR;
} else {
MEDIA_INFO_LOG("Stream Pasued Successfully");
return AUDIO_CLIENT_SUCCESS;
}
}
int32_t AudioServiceClient::StopStream()
{
lock_guard<mutex> lock(ctrlMutex);
PAStreamCorkSuccessCb = PAStreamStopSuccessCb;
int32_t ret = CorkStream();
if (ret) {
return ret;
}
if (!streamCmdStatus) {
MEDIA_ERR_LOG("Stream Stop Failed");
return AUDIO_CLIENT_ERR;
} else {
MEDIA_INFO_LOG("Stream Stopped Successfully");
return AUDIO_CLIENT_SUCCESS;
}
}
int32_t AudioServiceClient::CorkStream()
{
CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
pa_operation *operation = NULL;
@ -713,7 +786,7 @@ int32_t AudioServiceClient::StopStream()
}
streamCmdStatus = 0;
operation = pa_stream_cork(paStream, 1, PAStreamCmdSuccessCb, (void *)this);
operation = pa_stream_cork(paStream, 1, PAStreamCorkSuccessCb, (void *)this);
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
pa_threaded_mainloop_wait(mainLoop);
@ -721,13 +794,7 @@ int32_t AudioServiceClient::StopStream()
pa_operation_unref(operation);
pa_threaded_mainloop_unlock(mainLoop);
if (!streamCmdStatus) {
MEDIA_ERR_LOG("Stream Stop Failed");
return AUDIO_CLIENT_ERR;
} else {
MEDIA_INFO_LOG("Stream Stopped Successfully");
return AUDIO_CLIENT_SUCCESS;
}
return AUDIO_CLIENT_SUCCESS;
}
int32_t AudioServiceClient::FlushStream()
@ -1143,6 +1210,13 @@ int32_t AudioServiceClient::ReadStream(StreamBuffer &stream, bool isBlocking)
int32_t AudioServiceClient::ReleaseStream()
{
ResetPAAudioClient();
state_ = RELEASED;
std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
if (streamCb != nullptr) {
streamCb->OnStateChange(state_);
}
return AUDIO_CLIENT_SUCCESS;
}
@ -1165,7 +1239,6 @@ int32_t AudioServiceClient::GetMinimumBufferSize(size_t &minBufferSize)
minBufferSize = (size_t)bufferAttr->fragsize;
}
MEDIA_INFO_LOG("buffer size: %zu", minBufferSize);
return AUDIO_CLIENT_SUCCESS;
}
@ -1558,5 +1631,19 @@ AudioRendererRate AudioServiceClient::GetStreamRenderRate()
{
return renderRate;
}
void AudioServiceClient::SaveStreamCallback(const std::weak_ptr<AudioStreamCallback> &callback)
{
streamCallback_ = callback;
if (state_ != PREPARED) {
return;
}
std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
if (streamCb != nullptr) {
streamCb->OnStateChange(state_);
}
}
} // namespace AudioStandard
} // namespace OHOS

View File

@ -455,5 +455,17 @@ AudioRendererRate AudioStream::GetRenderRate()
{
return GetStreamRenderRate();
}
int32_t AudioStream::SetStreamCallback(const std::shared_ptr<AudioStreamCallback> &callback)
{
if (callback == nullptr) {
MEDIA_ERR_LOG("AudioStream::SetStreamCallback failed. callback == nullptr");
return ERR_INVALID_PARAM;
}
SaveStreamCallback(callback);
return SUCCESS;
}
} // namspace AudioStandard
} // namespace OHOS

View File

@ -33,6 +33,32 @@ namespace AudioTestConstants {
constexpr int32_t SUCCESS = 0;
}
class AudioCapturerCallbackTestImpl : public AudioCapturerCallback {
public:
void OnStateChange(const CapturerState state) override
{
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl:: OnStateChange");
switch (state) {
case CAPTURER_PREPARED:
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_PREPARED");
break;
case CAPTURER_RUNNING:
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_RUNNING");
break;
case CAPTURER_STOPPED:
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_STOPPED");
break;
case CAPTURER_RELEASED:
MEDIA_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_RELEASED");
break;
default:
MEDIA_ERR_LOG("AudioCapturerCallbackTestImpl: OnStateChange NOT A VALID state");
break;
}
}
};
class AudioCapturerTest {
public:
void CheckSupportedParams() const
@ -157,6 +183,14 @@ public:
unique_ptr<AudioCapturer> audioCapturer = AudioCapturer::Create(capturerOptions);
int32_t ret = 0;
shared_ptr<AudioCapturerCallback> cb1 = make_shared<AudioCapturerCallbackTestImpl>();
ret = audioCapturer->SetCapturerCallback(cb1);
if (ret) {
MEDIA_ERR_LOG("AudioCapturerTest: SetCapturerCallback failed %{public}d", ret);
return false;
}
CheckSupportedParams();
if (!InitCapture(audioCapturer)) {

View File

@ -21,8 +21,30 @@ using namespace std;
namespace OHOS {
namespace AudioStandard {
namespace AudioTestConstants {
constexpr int32_t SUCCESS = 0;
void AudioInterruptTest::OnStateChange(const RendererState state)
{
MEDIA_DEBUG_LOG("AudioInterruptTest:: OnStateChange");
switch (state) {
case RENDERER_PREPARED:
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_PREPARED");
break;
case RENDERER_RUNNING:
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_RUNNING");
break;
case RENDERER_STOPPED:
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_STOPPED");
break;
case RENDERER_PAUSED:
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_PAUSED");
break;
case RENDERER_RELEASED:
MEDIA_DEBUG_LOG("AudioInterruptTest: OnStateChange RENDERER_RELEASED");
break;
default:
MEDIA_ERR_LOG("AudioInterruptTest: OnStateChange NOT A VALID state");
break;
}
}
void AudioInterruptTest::OnInterrupt(const InterruptEvent &interruptEvent)
@ -158,7 +180,7 @@ bool AudioInterruptTest::StartRender()
return true;
}
bool AudioInterruptTest::InitRender() const
bool AudioInterruptTest::InitRender()
{
wav_hdr wavHeader;
size_t headerSize = sizeof(wav_hdr);
@ -168,17 +190,18 @@ bool AudioInterruptTest::InitRender() const
return false;
}
AudioRendererParams rendererParams;
rendererParams.sampleFormat = static_cast<AudioSampleFormat>(wavHeader.bitsPerSample);
rendererParams.sampleRate = static_cast<AudioSamplingRate>(wavHeader.SamplesPerSec);
rendererParams.channelCount = static_cast<AudioChannel>(wavHeader.NumOfChan);
rendererParams.encodingType = static_cast<AudioEncodingType>(ENCODING_PCM);
AudioRendererOptions rendererOptions = {};
rendererOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
rendererOptions.streamInfo.samplingRate = static_cast<AudioSamplingRate>(wavHeader.SamplesPerSec);
rendererOptions.streamInfo.format = static_cast<AudioSampleFormat>(wavHeader.bitsPerSample);
rendererOptions.streamInfo.channels = static_cast<AudioChannel>(wavHeader.NumOfChan);
rendererOptions.rendererInfo.contentType = contentType_;
rendererOptions.rendererInfo.streamUsage = streamUsage_;
rendererOptions.rendererInfo.rendererFlags = 0;
if (audioRenderer_->SetParams(rendererParams) != AudioTestConstants::SUCCESS) {
MEDIA_ERR_LOG("AudioInterruptTest: Set audio renderer parameters failed");
if (!audioRenderer_->Release()) {
MEDIA_ERR_LOG("AudioInterruptTest: Release failed");
}
audioRenderer_ = AudioRenderer::Create(rendererOptions);
if (audioRenderer_== nullptr) {
MEDIA_INFO_LOG("AudioInterruptTest: Renderer create failed");
return false;
}
MEDIA_INFO_LOG("AudioInterruptTest: Playback renderer created");
@ -186,10 +209,9 @@ bool AudioInterruptTest::InitRender() const
return true;
}
int32_t AudioInterruptTest::TestPlayback(const AudioStreamType &streamType)
int32_t AudioInterruptTest::TestPlayback()
{
MEDIA_INFO_LOG("AudioInterruptTest: TestPlayback start ");
audioRenderer_ = AudioRenderer::Create(streamType);
if (!InitRender()) {
fclose(wavFile_);
return -1;
@ -232,6 +254,12 @@ int32_t AudioInterruptTest::TestPlayback(const AudioStreamType &streamType)
return 0;
}
void AudioInterruptTest::saveStreamInfo(ContentType contentType, StreamUsage streamUsage)
{
contentType_ = contentType;
streamUsage_ = streamUsage;
}
} // AudioStandard
} // OHOS
@ -243,12 +271,18 @@ int main(int argc, char *argv[])
MEDIA_INFO_LOG("AudioInterruptTest: Render test in");
constexpr int32_t minNumOfArgs = 2;
constexpr int32_t argIndexTwo = 2;
constexpr int32_t argIndexThree = 3;
if ((argv == nullptr) || (argc < minNumOfArgs)) {
if (argv == nullptr) {
MEDIA_ERR_LOG("AudioInterruptTest: argv is null");
return 0;
}
if (argc < minNumOfArgs || argc == minNumOfArgs + 1) {
MEDIA_ERR_LOG("AudioInterruptTest: incorrect argc. Enter either 2 or 4 args");
return 0;
}
MEDIA_INFO_LOG("AudioInterruptTest: argc=%d", argc);
MEDIA_INFO_LOG("AudioInterruptTest: argv[1]=%{public}s", argv[1]);
@ -261,10 +295,6 @@ int main(int argc, char *argv[])
}
MEDIA_INFO_LOG("AudioInterruptTest: path = %{public}s", path);
AudioStreamType streamType = AudioStreamType::STREAM_MUSIC;
if (argc > minNumOfArgs)
streamType = static_cast<AudioStreamType>(strtol(argv[argIndexTwo], NULL, numBase));
auto audioInterruptTest = std::make_shared<AudioInterruptTest>();
audioInterruptTest->wavFile_ = fopen(path, "rb");
@ -273,7 +303,13 @@ int main(int argc, char *argv[])
return -1;
}
int32_t ret = audioInterruptTest->TestPlayback(streamType);
if (argc > minNumOfArgs + 1) { // argc = 4
ContentType contentType = static_cast<ContentType>(strtol(argv[argIndexTwo], NULL, numBase));
StreamUsage streamUsage = static_cast<StreamUsage>(strtol(argv[argIndexThree], NULL, numBase));
audioInterruptTest->saveStreamInfo(contentType, streamUsage);
}
int32_t ret = audioInterruptTest->TestPlayback();
return ret;
}

View File

@ -30,12 +30,13 @@ public:
return shared_from_this();
}
int32_t TestPlayback(const AudioStreamType &streamType);
int32_t TestPlayback();
void OnInterrupt(const InterruptEvent &interruptEvent) override;
void OnStateChange(const RendererState state) override;
void saveStreamInfo(ContentType contentType, StreamUsage streamUsage);
FILE *wavFile_ = nullptr;
private:
bool InitRender() const;
bool InitRender();
bool StartRender();
bool GetBufferLen(size_t &bufferLen) const;
void WriteBuffer();
@ -46,6 +47,8 @@ private:
bool isRenderStopped_ = false;
bool isRenderingCompleted_ = false;
std::unique_ptr<std::thread> writeThread_ = nullptr;
ContentType contentType_ = ContentType::CONTENT_TYPE_MUSIC;
StreamUsage streamUsage_ = StreamUsage::STREAM_USAGE_MEDIA;
};
} // AudioStandard
} // OHOS

View File

@ -22,9 +22,10 @@ using namespace std;
using namespace OHOS;
using namespace OHOS::AudioStandard;
namespace AudioTestConstants {
namespace {
constexpr int32_t ARGS_INDEX_THREE = 3;
constexpr int32_t ARGS_INDEX_TWO = 2;
constexpr int32_t ARGS_COUNT_TWO = 2;
constexpr int32_t ARGS_COUNT_THREE = 3;
constexpr int32_t SUCCESS = 0;
constexpr int32_t STOP_BUFFER_POSITION = 700000;
@ -34,6 +35,36 @@ namespace AudioTestConstants {
constexpr float TRACK_VOLUME = 0.2f;
}
class AudioRendererCallbackTestImpl : public AudioRendererCallback {
public:
void OnInterrupt(const InterruptEvent &interruptEvent) override {}
void OnStateChange(const RendererState state) override
{
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl:: OnStateChange");
switch (state) {
case RENDERER_PREPARED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PREPARED");
break;
case RENDERER_RUNNING:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RUNNING");
break;
case RENDERER_STOPPED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_STOPPED");
break;
case RENDERER_PAUSED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PAUSED");
break;
case RENDERER_RELEASED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RELEASED");
break;
default:
MEDIA_ERR_LOG("AudioRendererCallbackTestImpl: OnStateChange NOT A VALID state");
break;
}
}
};
class AudioRendererTest {
public:
void CheckSupportedParams() const
@ -64,6 +95,29 @@ public:
}
}
void GetRendererStreamInfo(const unique_ptr<AudioRenderer> &audioRenderer) const
{
MEDIA_INFO_LOG("AudioRendererTest: GetRendererInfo:");
AudioRendererInfo rendererInfo;
if (audioRenderer->GetRendererInfo(rendererInfo) == SUCCESS) {
MEDIA_INFO_LOG("AudioRendererTest: Get ContentType: %{public}d", rendererInfo.contentType);
MEDIA_INFO_LOG("AudioRendererTest: Get StreamUsage: %{public}d", rendererInfo.streamUsage);
} else {
MEDIA_ERR_LOG("AudioRendererTest: GetStreamInfo failed");
}
MEDIA_INFO_LOG("AudioRendererTest: GetStreamInfo:");
AudioStreamInfo streamInfo;
if (audioRenderer->GetStreamInfo(streamInfo) == SUCCESS) {
MEDIA_INFO_LOG("AudioRendererTest: Get AudioSamplingRate: %{public}d", streamInfo.samplingRate);
MEDIA_INFO_LOG("AudioRendererTest: Get AudioEncodingType: %{public}d", streamInfo.encoding);
MEDIA_INFO_LOG("AudioRendererTest: Get AudioSampleFormat: %{public}d", streamInfo.format);
MEDIA_INFO_LOG("AudioRendererTest: Get AudioChannel: %{public}d", streamInfo.channels);
} else {
MEDIA_ERR_LOG("AudioRendererTest: GetStreamInfo failed");
}
}
bool InitRender(const unique_ptr<AudioRenderer> &audioRenderer) const
{
MEDIA_INFO_LOG("AudioRendererTest: Starting renderer");
@ -76,20 +130,10 @@ public:
}
MEDIA_INFO_LOG("AudioRendererTest: Playback started");
if (audioRenderer->SetVolume(AudioTestConstants::TRACK_VOLUME) == AudioTestConstants::SUCCESS) {
if (audioRenderer->SetVolume(TRACK_VOLUME) == SUCCESS) {
MEDIA_INFO_LOG("AudioRendererTest: volume set to: %{public}f", audioRenderer->GetVolume());
}
MEDIA_INFO_LOG("AudioRendererTest: Get Audio parameters:");
AudioRendererParams paRendererParams;
if (audioRenderer->GetParams(paRendererParams) == AudioTestConstants::SUCCESS) {
MEDIA_INFO_LOG("AudioRendererTest: Get Audio format: %{public}d", paRendererParams.sampleFormat);
MEDIA_INFO_LOG("AudioRendererTest: Get Audio sampling rate: %{public}d", paRendererParams.sampleRate);
MEDIA_INFO_LOG("AudioRendererTest: Get Audio channels: %{public}d", paRendererParams.channelCount);
} else {
MEDIA_ERR_LOG("AudioRendererTest: Get Audio parameters failed");
}
return true;
}
@ -97,20 +141,20 @@ public:
FILE &wavFile) const
{
uint64_t currFilePos = ftell(&wavFile);
if (!stopTested && (currFilePos > AudioTestConstants::STOP_BUFFER_POSITION) && audioRenderer->Stop()) {
if (!stopTested && (currFilePos > STOP_BUFFER_POSITION) && audioRenderer->Stop()) {
stopTested = true;
sleep(AudioTestConstants::STOP_RENDER_TIME_SECONDS);
sleep(STOP_RENDER_TIME_SECONDS);
MEDIA_INFO_LOG("Audio render resume");
if (!audioRenderer->Start()) {
MEDIA_ERR_LOG("resume stream failed");
return false;
}
} else if (!pauseTested && (currFilePos > AudioTestConstants::PAUSE_BUFFER_POSITION)
} else if (!pauseTested && (currFilePos > PAUSE_BUFFER_POSITION)
&& audioRenderer->Pause()) {
pauseTested = true;
sleep(AudioTestConstants::PAUSE_RENDER_TIME_SECONDS);
sleep(PAUSE_RENDER_TIME_SECONDS);
MEDIA_INFO_LOG("Audio render resume");
if (audioRenderer->SetVolume(1.0) == AudioTestConstants::SUCCESS) {
if (audioRenderer->SetVolume(1.0) == SUCCESS) {
MEDIA_INFO_LOG("AudioRendererTest: after resume volume set to: %{public}f",
audioRenderer->GetVolume());
}
@ -219,9 +263,9 @@ public:
ContentType contentType = ContentType::CONTENT_TYPE_MUSIC;
StreamUsage streamUsage = StreamUsage::STREAM_USAGE_MEDIA;
if (argc > AudioTestConstants::ARGS_COUNT_THREE) {
contentType = static_cast<ContentType>(strtol(argv[AudioTestConstants::ARGS_INDEX_TWO], NULL, numBase));
streamUsage = static_cast<StreamUsage>(strtol(argv[AudioTestConstants::ARGS_INDEX_THREE], NULL, numBase));
if (argc > ARGS_COUNT_THREE) {
contentType = static_cast<ContentType>(strtol(argv[ARGS_INDEX_TWO], NULL, numBase));
streamUsage = static_cast<StreamUsage>(strtol(argv[ARGS_INDEX_THREE], NULL, numBase));
}
AudioRendererOptions rendererOptions = {};
@ -235,6 +279,21 @@ public:
unique_ptr<AudioRenderer> audioRenderer = AudioRenderer::Create(rendererOptions);
if (audioRenderer == nullptr) {
MEDIA_ERR_LOG("AudioRendererTest: Create failed");
return false;
}
int32_t ret = 0;
shared_ptr<AudioRendererCallback> cb1 = make_shared<AudioRendererCallbackTestImpl>();
ret = audioRenderer->SetRendererCallback(cb1);
if (ret) {
MEDIA_ERR_LOG("AudioRendererTest: SetRendererCallback failed %{public}d", ret);
return false;
}
GetRendererStreamInfo(audioRenderer);
CheckSupportedParams();
if (!InitRender(audioRenderer)) {
@ -268,15 +327,18 @@ int main(int argc, char *argv[])
{
MEDIA_INFO_LOG("AudioRendererTest: Render test in");
if ((argv == nullptr) || (argc < AudioTestConstants::ARGS_COUNT_THREE)) {
if (argv == nullptr) {
MEDIA_ERR_LOG("AudioRendererTest: argv is null");
return 0;
}
if (argc < ARGS_COUNT_TWO || argc == ARGS_COUNT_THREE) {
MEDIA_ERR_LOG("AudioRendererTest: incorrect argc. Enter either 2 or 4 args");
return 0;
}
MEDIA_INFO_LOG("AudioRendererTest: argc=%{public}d", argc);
MEDIA_INFO_LOG("file path argv[1]=%{public}s", argv[1]);
MEDIA_INFO_LOG("content type argv[2]=%{public}s", argv[AudioTestConstants::ARGS_INDEX_TWO]);
MEDIA_INFO_LOG("stream usage argv[3]=%{public}s", argv[AudioTestConstants::ARGS_INDEX_THREE]);
AudioRendererTest testObj;
bool ret = testObj.TestPlayback(argc, argv);

View File

@ -34,6 +34,32 @@ namespace {
constexpr int32_t NUM_BASE = 10;
}
void AudioRendererCallbackTestImpl::OnStateChange(const RendererState state)
{
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl:: OnStateChange");
switch (state) {
case RENDERER_PREPARED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PREPARED");
break;
case RENDERER_RUNNING:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RUNNING");
break;
case RENDERER_STOPPED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_STOPPED");
break;
case RENDERER_PAUSED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_PAUSED");
break;
case RENDERER_RELEASED:
MEDIA_DEBUG_LOG("AudioRendererCallbackTestImpl: OnStateChange RENDERER_RELEASED");
break;
default:
MEDIA_ERR_LOG("AudioRendererCallbackTestImpl: OnStateChange NOT A VALID state");
break;
}
}
void AudioRendererCallbackTestImpl::OnInterrupt(const InterruptEvent &interruptEvent)
{
MEDIA_DEBUG_LOG("InterruptMultiRendererTest: OnInterrupt");

View File

@ -23,6 +23,7 @@ namespace AudioStandard {
class AudioRendererCallbackTestImpl : public AudioRendererCallback {
public:
void OnInterrupt(const InterruptEvent &interruptEvent) override;
void OnStateChange(const RendererState state) override;
bool isRendererPaused_ = false;
bool isStopInProgress_ = false;
bool isRendererStopped_ = false;

View File

@ -23,6 +23,7 @@ namespace AudioStandard {
class AudioRendererCallbackTest : public AudioRendererCallback {
public:
void OnInterrupt(const InterruptEvent &interruptEvent) override;
void OnStateChange(const RendererState state) override {}
};
class AudioRendererUnitTest : public testing::Test {