mirror of
https://github.com/openharmony/multimedia_audio_lite.git
synced 2026-07-19 11:42:12 -04:00
add audio capture service
Signed-off-by: starfish002 <shaoyuan.zhang@huawei.com>
This commit is contained in:
+35
-3
@@ -16,6 +16,34 @@ import("//build/lite/ndk/ndk.gni")
|
||||
shared_library("audio_capturer_lite") {
|
||||
sources = [
|
||||
"audio_capturer.cpp",
|
||||
"audio_capturer_client.cpp",
|
||||
]
|
||||
|
||||
cflags = [ "-fPIC" ]
|
||||
cflags += [ "-Wall" ]
|
||||
cflags_cc = cflags
|
||||
include_dirs = [
|
||||
"//foundation/multimedia/audio_lite/interfaces/kits",
|
||||
"//foundation/multimedia/audio_lite/services/include",
|
||||
"//foundation/multimedia/utils/lite/interfaces/kits",
|
||||
"//foundation/multimedia/audio_lite/frameworks",
|
||||
"//foundation/distributedschedule/samgr_lite/interfaces/kits/registry",
|
||||
"//base/security/permission/interfaces/kits/permission_lite",
|
||||
"//foundation/distributedschedule/samgr_lite/interfaces/kits/registry",
|
||||
"//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base/security/permission/services/permission_lite/pms_client:pms_client",
|
||||
"//foundation/communication/ipc_lite:liteipc_adapter",
|
||||
"//foundation/graphic/surface:lite_surface",
|
||||
"//foundation/multimedia/utils/lite:media_common",
|
||||
"//third_party/bounds_checking_function:libsec_shared",
|
||||
]
|
||||
}
|
||||
|
||||
shared_library("audio_capturer_impl") {
|
||||
sources = [
|
||||
"audio_capturer_impl.cpp",
|
||||
"audio_encoder/audio_encoder.cpp",
|
||||
"audio_source/audio_source.cpp",
|
||||
@@ -24,11 +52,14 @@ shared_library("audio_capturer_lite") {
|
||||
cflags += [ "-Wall" ]
|
||||
cflags_cc = cflags
|
||||
include_dirs = [
|
||||
"audio_encoder/include",
|
||||
"audio_source/include",
|
||||
"//foundation/multimedia/utils/lite/hals",
|
||||
"//foundation/multimedia/audio_lite/frameworks/audio_encoder/include",
|
||||
"//foundation/multimedia/audio_lite/frameworks/audio_source/include",
|
||||
"//foundation/multimedia/audio_lite/frameworks",
|
||||
"//foundation/multimedia/audio_lite/interfaces/kits",
|
||||
"//foundation/multimedia/audio_lite/services/include",
|
||||
"//drivers/peripheral/audio/interfaces/include",
|
||||
"//drivers/peripheral/codec/interfaces/include",
|
||||
"//foundation/multimedia/utils/lite/interfaces/kits",
|
||||
"//drivers/peripheral/format/interfaces/include",
|
||||
]
|
||||
|
||||
@@ -38,6 +69,7 @@ shared_library("audio_capturer_lite") {
|
||||
"-L$outdir",
|
||||
"-lcodec",
|
||||
"-laudio_hw",
|
||||
"-lpthread",
|
||||
]
|
||||
deps = [
|
||||
"//foundation/graphic/surface:lite_surface",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "audio_capturer.h"
|
||||
#include "audio_capturer_impl.h"
|
||||
#include "audio_capturer_client.h"
|
||||
#include "media_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
@@ -28,7 +29,7 @@ namespace Audio {
|
||||
} while (0)
|
||||
|
||||
AudioCapturer::AudioCapturer()
|
||||
: impl_(new(std::nothrow) AudioCapturerImpl())
|
||||
: impl_(new(std::nothrow) AudioCapturerClient())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,9 +37,10 @@ AudioCapturer::~AudioCapturer()
|
||||
{
|
||||
}
|
||||
|
||||
bool AudioCapturer::GetMinFrameCount(int32_t sampleRate, int32_t channelCount, AudioCodecFormat audioFormat, size_t &frameCount)
|
||||
bool AudioCapturer::GetMinFrameCount(int32_t sampleRate, int32_t channelCount, AudioCodecFormat audioFormat,
|
||||
size_t &frameCount)
|
||||
{
|
||||
return AudioCapturerImpl::GetMinFrameCount(sampleRate, channelCount, audioFormat, frameCount);
|
||||
return AudioCapturerClient::GetMinFrameCount(sampleRate, channelCount, audioFormat, frameCount);
|
||||
}
|
||||
|
||||
uint64_t AudioCapturer::GetFrameCount()
|
||||
@@ -56,7 +58,7 @@ State AudioCapturer::GetStatus()
|
||||
bool AudioCapturer::GetAudioTime(Timestamp ×tamp, Timestamp::Timebase base)
|
||||
{
|
||||
CHK_NULL_RETURN(impl_, false);
|
||||
return impl_->GetTimestamp(timestamp, base);
|
||||
return impl_->GetAudioTime(timestamp, base);
|
||||
}
|
||||
|
||||
int32_t AudioCapturer::SetCapturerInfo(const AudioCapturerInfo info)
|
||||
@@ -74,7 +76,7 @@ int32_t AudioCapturer::GetCapturerInfo(AudioCapturerInfo &info)
|
||||
bool AudioCapturer::Start()
|
||||
{
|
||||
CHK_NULL_RETURN(impl_, false);
|
||||
return impl_->Record();
|
||||
return impl_->Start();
|
||||
}
|
||||
|
||||
bool AudioCapturer::Stop()
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 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_client.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include "audio_capturer_server.h"
|
||||
#include "liteipc_adapter.h"
|
||||
#include "media_log.h"
|
||||
#include "samgr_lite.h"
|
||||
#include "securec.h"
|
||||
#include "surface_impl.h"
|
||||
|
||||
extern "C" void __attribute__((weak)) OHOS_SystemInit(void)
|
||||
{
|
||||
SAMGR_Bootstrap();
|
||||
}
|
||||
|
||||
using namespace OHOS::Media;
|
||||
using namespace std;
|
||||
namespace OHOS {
|
||||
namespace Audio {
|
||||
constexpr int32_t SURFACE_QUEUE_SIZE = 5;
|
||||
constexpr int32_t SURFACE_SIZE = 8192;
|
||||
constexpr int32_t SURFACE_HEIGHT = 1;
|
||||
constexpr int32_t SURFACE_WIDTH = 8192;
|
||||
|
||||
struct CallBackPara {
|
||||
int funcId;
|
||||
int32_t ret;
|
||||
void* data;
|
||||
};
|
||||
|
||||
|
||||
AudioCapturer::AudioCapturerClient *AudioCapturer::AudioCapturerClient::GetInstance()
|
||||
{
|
||||
static AudioCapturerClient client;
|
||||
return &client;
|
||||
}
|
||||
|
||||
static int32_t ProxyCallbackFunc(void *owner, int code, IpcIo *reply)
|
||||
{
|
||||
if (code != 0) {
|
||||
MEDIA_ERR_LOG("callback error, code = %d", code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (owner == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CallBackPara* para = (CallBackPara*)owner;
|
||||
AudioCapturerFuncId funcId = (AudioCapturerFuncId)para->funcId;
|
||||
para->ret = IpcIoPopInt32(reply);
|
||||
switch (funcId) {
|
||||
case AUD_CAP_FUNC_CONNECT:
|
||||
case AUD_CAP_FUNC_DISCONNECT:
|
||||
case AUD_CAP_FUNC_SET_INFO:
|
||||
case AUD_CAP_FUNC_START:
|
||||
case AUD_CAP_FUNC_STOP:
|
||||
case AUD_CAP_FUNC_RELEASE:
|
||||
case AUD_CAP_FUNC_SET_SURFACE:
|
||||
break;
|
||||
case AUD_CAP_FUNC_GET_FRAME_COUNT:
|
||||
(*(uint64_t *)para->data) = IpcIoPopUint64(reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_GET_STATUS:
|
||||
(*(uint32_t *)para->data) = IpcIoPopUint32(reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_GET_INFO: {
|
||||
uint32_t size = 0;
|
||||
void *bufferAdd = IpcIoPopFlatObj(reply, &size);
|
||||
if (bufferAdd == nullptr || size == 0) {
|
||||
MEDIA_INFO_LOG("IpcIoPopFlatObj info failed");
|
||||
return -1;
|
||||
}
|
||||
memcpy_s(para->data, sizeof(AudioCapturerInfo), bufferAdd, size);
|
||||
break;
|
||||
}
|
||||
case AUD_CAP_FUNC_GET_MIN_FRAME_COUNT:
|
||||
(*(uint32_t *)para->data) = IpcIoPopUint32(reply);
|
||||
break;
|
||||
default :
|
||||
MEDIA_INFO_LOG("Callback, unkown funcId = %d", para->funcId);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t AudioCapturer::AudioCapturerClient::InitSurface(void)
|
||||
{
|
||||
MEDIA_DEBUG_LOG("AudioCapturerClient InitSurface");
|
||||
Surface *surface = Surface::CreateSurface();
|
||||
if (surface == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
surface->RegisterConsumerListener(*this);
|
||||
surface_.reset(surface);
|
||||
|
||||
surface->SetWidthAndHeight(SURFACE_WIDTH, SURFACE_HEIGHT);
|
||||
surface->SetQueueSize(SURFACE_QUEUE_SIZE);
|
||||
surface->SetSize(SURFACE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioCapturer::AudioCapturerClient::AudioCapturerClient()
|
||||
{
|
||||
OHOS_SystemInit();
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IUnknown *iUnknown = SAMGR_GetInstance()->GetDefaultFeatureApi(AUDIO_CAPTURER_SERVICE_NAME);
|
||||
if (iUnknown == nullptr) {
|
||||
MEDIA_ERR_LOG("iUnknown is NULL");
|
||||
throw runtime_error("Ipc proxy GetDefaultFeatureApi failed.");
|
||||
}
|
||||
|
||||
(void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&proxy_);
|
||||
if (proxy_ == nullptr) {
|
||||
MEDIA_ERR_LOG("QueryInterface failed");
|
||||
throw runtime_error("Ipc proxy init failed.");
|
||||
}
|
||||
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_CONNECT, .ret = MEDIA_IPC_FAILED, .data = this};
|
||||
int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_CONNECT, nullptr, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Connect audio capturer server failed, ret=%d", ret);
|
||||
throw runtime_error("Ipc proxy Invoke failed.");
|
||||
}
|
||||
|
||||
/* Creating a Surface and Initializing Settings */
|
||||
MEDIA_DEBUG_LOG("InitSurface audio capturer.");
|
||||
InitSurface();
|
||||
/* The surface is transferred to the server for processing */
|
||||
timeStampValid_ = false;
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 1);
|
||||
dynamic_cast<SurfaceImpl *>(surface_.get())->WriteIoIpcIo(io);
|
||||
para = {.funcId = AUD_CAP_FUNC_SET_SURFACE, .ret = MEDIA_IPC_FAILED, .data = this};
|
||||
ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_SET_SURFACE, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Connect audio capturer set surface failed, ret=%d", ret);
|
||||
throw runtime_error("Ipc proxy Invoke failed.");
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("Create audio capturer client succeed.");
|
||||
}
|
||||
|
||||
void AudioCapturer::AudioCapturerClient::ReleaseAllBuffer()
|
||||
{
|
||||
timeStampValid_ = false;
|
||||
while (true) {
|
||||
SurfaceBuffer *surfaceBuf = surface_->AcquireBuffer();
|
||||
if (surfaceBuf == nullptr) {
|
||||
break;
|
||||
}
|
||||
surface_->ReleaseBuffer(surfaceBuf);
|
||||
}
|
||||
}
|
||||
|
||||
AudioCapturer::AudioCapturerClient::~AudioCapturerClient()
|
||||
{
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_DISCONNECT, .ret = MEDIA_IPC_FAILED};
|
||||
uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_DISCONNECT, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Disconnect audioCapturer server failed, ret=%d", ret);
|
||||
}
|
||||
|
||||
/* release all surface buffer */
|
||||
ReleaseAllBuffer();
|
||||
surface_.reset();
|
||||
surface_ = nullptr;
|
||||
MEDIA_INFO_LOG("dector");
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerClient::GetMinFrameCount(int32_t sampleRate, int32_t channelCount,
|
||||
AudioCodecFormat audioFormat, size_t &frameCount)
|
||||
{
|
||||
AudioCapturerClient *client = AudioCapturer::AudioCapturerClient::GetInstance();
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
IpcIoPushInt32(&io, sampleRate);
|
||||
IpcIoPushInt32(&io, channelCount);
|
||||
IpcIoPushFlatObj(&io, &audioFormat, sizeof(audioFormat));
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_MIN_FRAME_COUNT, .ret = MEDIA_IPC_FAILED, .data = &frameCount};
|
||||
uint32_t ret = client->proxy_->Invoke(client->proxy_, AUD_CAP_FUNC_GET_MIN_FRAME_COUNT, &io, ¶,
|
||||
ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("GetMinFrameCount failed, ret=%d", ret);
|
||||
return false;
|
||||
}
|
||||
return (para.ret == 0) ? true : false;
|
||||
}
|
||||
|
||||
uint64_t AudioCapturer::AudioCapturerClient::GetFrameCount()
|
||||
{
|
||||
IpcIo io;
|
||||
uint64_t frameCount;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_FRAME_COUNT, .ret = MEDIA_IPC_FAILED, .data = &frameCount};
|
||||
uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_FRAME_COUNT, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("GetFrameCount failed, ret=%d", ret);
|
||||
}
|
||||
|
||||
return frameCount;
|
||||
}
|
||||
|
||||
State AudioCapturer::AudioCapturerClient::GetStatus()
|
||||
{
|
||||
IpcIo io;
|
||||
uint32_t state;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_STATUS, .ret = MEDIA_IPC_FAILED, .data = &state};
|
||||
uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_STATUS, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("GetStatus failed, ret=%d", ret);
|
||||
}
|
||||
|
||||
return (State)state;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerClient::GetAudioTime(Timestamp ×tamp, Timestamp::Timebase base)
|
||||
{
|
||||
timestamp = curTimestamp_;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t AudioCapturer::AudioCapturerClient::SetCapturerInfo(const AudioCapturerInfo info)
|
||||
{
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
IpcIoPushFlatObj(&io, &info, sizeof(info));
|
||||
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_SET_INFO, .ret = MEDIA_IPC_FAILED};
|
||||
int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_SET_INFO, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("SetCapturerInfo failed, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
return para.ret;
|
||||
}
|
||||
|
||||
int32_t AudioCapturer::AudioCapturerClient::GetCapturerInfo(AudioCapturerInfo &info)
|
||||
{
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_INFO, .ret = MEDIA_IPC_FAILED};
|
||||
int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_INFO, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("GetCapturerInfo failed, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
return para.ret;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerClient::Start()
|
||||
{
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_START, .ret = MEDIA_IPC_FAILED};
|
||||
int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_START, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Start failed, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return para.ret;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerClient::Stop()
|
||||
{
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_STOP, .ret = MEDIA_IPC_FAILED};
|
||||
int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_STOP, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Stop failed, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return para.ret;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerClient::Release()
|
||||
{
|
||||
IpcIo io;
|
||||
uint8_t tmpData[DEFAULT_IPC_SIZE];
|
||||
IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
|
||||
CallBackPara para = {.funcId = AUD_CAP_FUNC_RELEASE, .ret = MEDIA_IPC_FAILED};
|
||||
int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_RELEASE, &io, ¶, ProxyCallbackFunc);
|
||||
if (ret != 0) {
|
||||
MEDIA_ERR_LOG("Release failed, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
return para.ret;
|
||||
}
|
||||
|
||||
int32_t AudioCapturer::AudioCapturerClient::Read(uint8_t *buffer, size_t userSize, bool isBlockingRead)
|
||||
{
|
||||
if (buffer == NULL || userSize == 0) {
|
||||
return ERR_INVALID_READ;
|
||||
}
|
||||
int32_t readLen = ERR_INVALID_READ;
|
||||
do {
|
||||
SurfaceBuffer *surfaceBuf = surface_->AcquireBuffer();
|
||||
if (surfaceBuf == nullptr) {
|
||||
if (isBlockingRead) {
|
||||
usleep(10000); // indicates 10000 microseconds
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *buf = static_cast<uint8_t *> (surfaceBuf->GetVirAddr());
|
||||
int32_t dataSize = surfaceBuf->GetSize();
|
||||
if (dataSize - sizeof(Timestamp) > userSize) {
|
||||
surface_->ReleaseBuffer(surfaceBuf);
|
||||
MEDIA_ERR_LOG("input buffer size too small.");
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy_s(buffer, userSize, buf + sizeof(Timestamp), dataSize - sizeof(Timestamp));
|
||||
memcpy_s(&curTimestamp_, sizeof(Timestamp), buf, sizeof(Timestamp));
|
||||
timeStampValid_ = true;
|
||||
|
||||
surface_->ReleaseBuffer(surfaceBuf);
|
||||
readLen = dataSize - sizeof(Timestamp);
|
||||
break;
|
||||
} while (isBlockingRead);
|
||||
|
||||
return readLen;
|
||||
}
|
||||
|
||||
void AudioCapturer::AudioCapturerClient::OnBufferAvailable()
|
||||
{
|
||||
if (surface_ == nullptr) {
|
||||
MEDIA_ERR_LOG("surface is NULL");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IClientProxy *AudioCapturer::AudioCapturerClient::GetIClientProxy()
|
||||
{
|
||||
return proxy_;
|
||||
}
|
||||
} // namespace Audio
|
||||
} // namespace OHOS
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 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_CLIENT_H
|
||||
#define AUDIO_CAPTURER_CLIENT_H
|
||||
|
||||
#include <mutex>
|
||||
#include "audio_capturer.h"
|
||||
#include "iproxy_client.h"
|
||||
#include "media_info.h"
|
||||
#include "surface.h"
|
||||
|
||||
using OHOS::Surface;
|
||||
using std::mutex;
|
||||
using OHOS::SurfaceBuffer;
|
||||
using OHOS::IBufferConsumerListener;
|
||||
using OHOS::Audio::Timestamp;
|
||||
using OHOS::Audio::AudioCapturerInfo;
|
||||
|
||||
namespace OHOS {
|
||||
namespace Audio {
|
||||
class AudioCapturer::AudioCapturerClient : public IBufferConsumerListener {
|
||||
public:
|
||||
AudioCapturerClient();
|
||||
~AudioCapturerClient();
|
||||
static bool GetMinFrameCount(int32_t sampleRate, int32_t channelCount, AudioCodecFormat audioFormat,
|
||||
size_t &frameCount);
|
||||
uint64_t GetFrameCount();
|
||||
int32_t SetCapturerInfo(const AudioCapturerInfo info);
|
||||
int32_t GetCapturerInfo(AudioCapturerInfo &info);
|
||||
bool Start();
|
||||
int32_t Read(uint8_t *buffer, size_t userSize, bool isBlockingRead);
|
||||
State GetStatus();
|
||||
bool GetAudioTime(Timestamp ×tamp, Timestamp::Timebase base);
|
||||
bool Stop();
|
||||
bool Release();
|
||||
void OnBufferAvailable() override;
|
||||
static AudioCapturerClient *GetInstance();
|
||||
|
||||
private:
|
||||
bool InitAudioCapturerClient();
|
||||
IClientProxy *GetIClientProxy();
|
||||
int32_t InitSurface(void);
|
||||
void ReleaseAllBuffer();
|
||||
|
||||
SvcIdentity sid_;
|
||||
IClientProxy *proxy_ = nullptr;
|
||||
std::shared_ptr<Surface> surface_;
|
||||
std::mutex lock_;
|
||||
Timestamp curTimestamp_;
|
||||
bool timeStampValid_ = false;
|
||||
};
|
||||
} // namespace Audio
|
||||
} // namespace OHOS
|
||||
#endif // AUDIO_CAPTURER_CLIENT_H
|
||||
@@ -37,14 +37,14 @@ const unsigned long long TIME_CONVERSION_NS_US = 1000ULL; /* ns to us */
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
AudioCapturer::AudioCapturerImpl::AudioCapturerImpl()
|
||||
AudioCapturerImpl::AudioCapturerImpl()
|
||||
:audioSource_(new(std::nothrow) AudioSource()),
|
||||
audioEncoder_(nullptr)
|
||||
{
|
||||
MEDIA_DEBUG_LOG("ctor");
|
||||
}
|
||||
|
||||
AudioCapturer::AudioCapturerImpl::~AudioCapturerImpl()
|
||||
AudioCapturerImpl::~AudioCapturerImpl()
|
||||
{
|
||||
if (status_ != RELEASED) {
|
||||
Release();
|
||||
@@ -52,12 +52,13 @@ AudioCapturer::AudioCapturerImpl::~AudioCapturerImpl()
|
||||
MEDIA_ERR_LOG("dtor");
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerImpl::GetMinFrameCount(int32_t sampleRate, int32_t channelCount, AudioCodecFormat audioFormat, size_t &frameCount)
|
||||
bool AudioCapturerImpl::GetMinFrameCount(int32_t sampleRate, int32_t channelCount, AudioCodecFormat audioFormat,
|
||||
size_t &frameCount)
|
||||
{
|
||||
return AudioSource::GetMinFrameCount(sampleRate, channelCount, audioFormat, frameCount);;
|
||||
return AudioSource::GetMinFrameCount(sampleRate, channelCount, audioFormat, frameCount);
|
||||
}
|
||||
|
||||
uint64_t AudioCapturer::AudioCapturerImpl::GetFrameCount()
|
||||
uint64_t AudioCapturerImpl::GetFrameCount()
|
||||
{
|
||||
CHK_NULL_RETURN(audioSource_, 0);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
@@ -68,13 +69,13 @@ uint64_t AudioCapturer::AudioCapturerImpl::GetFrameCount()
|
||||
return audioSource_->GetFrameCount();
|
||||
}
|
||||
|
||||
State AudioCapturer::AudioCapturerImpl::GetStatus()
|
||||
State AudioCapturerImpl::GetStatus()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return status_;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerImpl::GetTimestamp(Timestamp ×tamp, Timestamp::Timebase base)
|
||||
bool AudioCapturerImpl::GetTimestamp(Timestamp ×tamp, Timestamp::Timebase base)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (status_ == RELEASED) {
|
||||
@@ -85,7 +86,27 @@ bool AudioCapturer::AudioCapturerImpl::GetTimestamp(Timestamp ×tamp, Timest
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t AudioCapturer::AudioCapturerImpl::SetCapturerInfo(const AudioCapturerInfo info)
|
||||
static void FillSourceConfig(AudioSourceConfig &sourceConfig, const AudioCapturerInfo &info, uint32_t deviceId)
|
||||
{
|
||||
sourceConfig.deviceId = deviceId;
|
||||
sourceConfig.audioFormat = info.audioFormat;
|
||||
sourceConfig.sampleRate = info.sampleRate;
|
||||
sourceConfig.channelCount = info.channelCount;
|
||||
sourceConfig.interleaved = false;
|
||||
sourceConfig.bitWidth = info.bitWidth;
|
||||
sourceConfig.streamUsage = info.streamType;
|
||||
}
|
||||
|
||||
static void FillEncConfig(AudioEncodeConfig &encodeConfig, const AudioCapturerInfo &info)
|
||||
{
|
||||
encodeConfig.audioFormat = info.audioFormat;
|
||||
encodeConfig.bitRate = info.bitRate;
|
||||
encodeConfig.sampleRate = info.sampleRate;
|
||||
encodeConfig.channelCount = info.channelCount;
|
||||
encodeConfig.bitWidth = info.bitWidth;
|
||||
}
|
||||
|
||||
int32_t AudioCapturerImpl::SetCapturerInfo(const AudioCapturerInfo info)
|
||||
{
|
||||
CHK_NULL_RETURN(audioSource_, ERROR);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
@@ -101,13 +122,7 @@ int32_t AudioCapturer::AudioCapturerImpl::SetCapturerInfo(const AudioCapturerInf
|
||||
}
|
||||
MEDIA_INFO_LOG("info.sampleRate:%d", info.sampleRate);
|
||||
AudioSourceConfig sourceConfig;
|
||||
sourceConfig.deviceId = devices[0].deviceId;
|
||||
sourceConfig.audioFormat = info.audioFormat;
|
||||
sourceConfig.sampleRate = info.sampleRate;
|
||||
sourceConfig.channelCount = info.channelCount;
|
||||
sourceConfig.interleaved = false;
|
||||
sourceConfig.bitWidth = info.bitWidth;
|
||||
sourceConfig.streamUsage = info.streamType;
|
||||
FillSourceConfig(sourceConfig, info, devices[0].deviceId);
|
||||
ret = audioSource_->Initialize(sourceConfig);
|
||||
if (ret != SUCCESS) {
|
||||
MEDIA_ERR_LOG("Initialize failed inputSource:%d", info.inputSource);
|
||||
@@ -115,11 +130,7 @@ int32_t AudioCapturer::AudioCapturerImpl::SetCapturerInfo(const AudioCapturerInf
|
||||
}
|
||||
if (info.audioFormat != PCM && info.audioFormat != AUDIO_DEFAULT) {
|
||||
AudioEncodeConfig encodeConfig;
|
||||
encodeConfig.audioFormat = info.audioFormat;
|
||||
encodeConfig.bitRate = info.bitRate;
|
||||
encodeConfig.sampleRate = info.sampleRate;
|
||||
encodeConfig.channelCount = info.channelCount;
|
||||
encodeConfig.bitWidth = info.bitWidth;
|
||||
FillEncConfig(encodeConfig, info);
|
||||
MEDIA_INFO_LOG("audioEncoder_ bitRate:%d", info.bitRate);
|
||||
std::unique_ptr<AudioEncoder> audioEncoder(new(std::nothrow) AudioEncoder());
|
||||
audioEncoder_ = std::move(audioEncoder);
|
||||
@@ -140,8 +151,7 @@ int32_t AudioCapturer::AudioCapturerImpl::SetCapturerInfo(const AudioCapturerInf
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int32_t AudioCapturer::AudioCapturerImpl::GetCapturerInfo(AudioCapturerInfo &info)
|
||||
int32_t AudioCapturerImpl::GetCapturerInfo(AudioCapturerInfo &info)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (status_ == RELEASED) {
|
||||
@@ -152,7 +162,7 @@ int32_t AudioCapturer::AudioCapturerImpl::GetCapturerInfo(AudioCapturerInfo &inf
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerImpl::Record()
|
||||
bool AudioCapturerImpl::Record()
|
||||
{
|
||||
CHK_NULL_RETURN(audioSource_, false);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
@@ -189,9 +199,9 @@ bool AudioCapturer::AudioCapturerImpl::Record()
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t AudioCapturer::AudioCapturerImpl::Read(uint8_t *buffer, size_t userSize, bool isBlockingRead)
|
||||
int32_t AudioCapturerImpl::Read(uint8_t *buffer, size_t userSize, bool isBlockingRead)
|
||||
{
|
||||
if (buffer == NULL || userSize == 0) {
|
||||
if (buffer == nullptr || userSize == 0) {
|
||||
MEDIA_ERR_LOG("Invalid buffer:%p userSize:%u", buffer, userSize);
|
||||
return ERR_INVALID_READ;
|
||||
}
|
||||
@@ -229,7 +239,7 @@ int32_t AudioCapturer::AudioCapturerImpl::Read(uint8_t *buffer, size_t userSize,
|
||||
return readLen;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerImpl::StopInternal()
|
||||
bool AudioCapturerImpl::StopInternal()
|
||||
{
|
||||
CHK_NULL_RETURN(audioSource_, false);
|
||||
int32_t ret;
|
||||
@@ -252,7 +262,7 @@ bool AudioCapturer::AudioCapturerImpl::StopInternal()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerImpl::Stop()
|
||||
bool AudioCapturerImpl::Stop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (status_ != RECORDING) {
|
||||
@@ -262,7 +272,7 @@ bool AudioCapturer::AudioCapturerImpl::Stop()
|
||||
return StopInternal();
|
||||
}
|
||||
|
||||
bool AudioCapturer::AudioCapturerImpl::Release()
|
||||
bool AudioCapturerImpl::Release()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (status_ == RELEASED) {
|
||||
|
||||
@@ -31,7 +31,7 @@ enum AudioChannel {
|
||||
|
||||
class AudioSource;
|
||||
class AudioEncoder;
|
||||
class AudioCapturer::AudioCapturerImpl {
|
||||
class AudioCapturerImpl {
|
||||
public:
|
||||
AudioCapturerImpl();
|
||||
virtual ~AudioCapturerImpl();
|
||||
@@ -46,9 +46,10 @@ public:
|
||||
uint64_t GetFrameCount();
|
||||
State GetStatus();
|
||||
bool GetTimestamp(Timestamp ×tamp, Timestamp::Timebase base);
|
||||
|
||||
|
||||
private:
|
||||
bool StopInternal();
|
||||
|
||||
std::unique_ptr<AudioSource> audioSource_;
|
||||
std::unique_ptr<AudioEncoder> audioEncoder_;
|
||||
State status_ = INITIALIZED;
|
||||
|
||||
@@ -247,8 +247,8 @@ public:
|
||||
bool Release();
|
||||
|
||||
private:
|
||||
class AudioCapturerImpl;
|
||||
std::unique_ptr<AudioCapturerImpl> impl_;
|
||||
class AudioCapturerClient;
|
||||
std::unique_ptr<AudioCapturerClient> impl_;
|
||||
};
|
||||
} // namespace Audio
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2021-2022 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.
|
||||
import("//build/lite/config/component/lite_component.gni")
|
||||
import("//build/lite/ndk/ndk.gni")
|
||||
|
||||
static_library("audio_capturer_server") {
|
||||
sources = [
|
||||
"src/audio_capturer_samgr.cpp",
|
||||
"src/audio_capturer_server.cpp",
|
||||
]
|
||||
cflags = [ "-fPIC" ]
|
||||
cflags += [ "-Wall" ]
|
||||
cflags_cc = cflags
|
||||
include_dirs = [
|
||||
"//foundation/multimedia/audio_lite/services/include",
|
||||
"//foundation/multimedia/audio_lite/interfaces/kits",
|
||||
"//foundation/multimedia/audio_lite/frameworks",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//base/security/permission/interfaces/kits/permission_lite",
|
||||
"//foundation/distributedschedule/samgr_lite/interfaces/kits/registry",
|
||||
"//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr",
|
||||
"//foundation/distributedschedule/samgr_lite/interfaces/kits/communication/broadcast",
|
||||
"//foundation/multimedia/utils/lite/interfaces/kits",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base/security/permission/services/permission_lite/pms_client:pms_client",
|
||||
"//foundation/communication/ipc_lite:liteipc_adapter",
|
||||
"//foundation/distributedschedule/samgr_lite/samgr:samgr",
|
||||
"//foundation/graphic/surface:lite_surface",
|
||||
"//foundation/multimedia/audio_lite/frameworks:audio_capturer_impl",
|
||||
"//foundation/multimedia/utils/lite:media_common",
|
||||
"//third_party/bounds_checking_function:libsec_shared",
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 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_SERVER_H
|
||||
#define AUDIO_CAPTURER_SERVER_H
|
||||
|
||||
#include <mutex>
|
||||
#include <pthread.h>
|
||||
#include <thread>
|
||||
#include "audio_capturer_impl.h"
|
||||
#include "liteipc_adapter.h"
|
||||
#include "serializer.h"
|
||||
#include "surface.h"
|
||||
|
||||
using OHOS::Audio::AudioCapturerImpl;
|
||||
using OHOS::Surface;
|
||||
namespace OHOS {
|
||||
namespace Audio {
|
||||
enum AudioCapturerFuncId {
|
||||
AUD_CAP_FUNC_CONNECT,
|
||||
AUD_CAP_FUNC_DISCONNECT,
|
||||
AUD_CAP_FUNC_GET_FRAME_COUNT,
|
||||
AUD_CAP_FUNC_GET_STATUS,
|
||||
AUD_CAP_FUNC_GET_TIME,
|
||||
AUD_CAP_FUNC_SET_INFO,
|
||||
AUD_CAP_FUNC_GET_INFO,
|
||||
AUD_CAP_FUNC_START,
|
||||
AUD_CAP_FUNC_STOP,
|
||||
AUD_CAP_FUNC_RELEASE,
|
||||
AUD_CAP_FUNC_GET_MIN_FRAME_COUNT,
|
||||
AUD_CAP_FUNC_SET_SURFACE,
|
||||
AUD_CAP_FUNC_BUTT,
|
||||
};
|
||||
|
||||
static constexpr int32_t DEFAULT_IPC_SIZE = 100;
|
||||
#define AUDIO_CAPTURER_SERVICE_NAME "AudioCapServer"
|
||||
|
||||
/* Since IPC is serialized, there is no concurrency problem */
|
||||
class AudioCapturerServer {
|
||||
public:
|
||||
AudioCapturerServer() = default;
|
||||
~AudioCapturerServer() = default;
|
||||
|
||||
int32_t AudioCapturerServerInit();
|
||||
static AudioCapturerServer *GetInstance();
|
||||
AudioCapturerImpl *GetAudioCapturer(pid_t pid);
|
||||
void AcceptServer(pid_t pid, IpcIo *reply);
|
||||
void DropServer(pid_t pid, IpcIo *reply);
|
||||
void Dispatch(int32_t funcId, pid_t pid, IpcIo *req, IpcIo *reply);
|
||||
static void *ReadAudioDataProcess(void *serverStr);
|
||||
|
||||
private:
|
||||
void GetMinFrameCount(IpcIo *req, IpcIo *reply);
|
||||
int32_t SetSurfaceProcess(Surface *surface);
|
||||
void SetInfo(AudioCapturerImpl *capturer, IpcIo *req, IpcIo *reply);
|
||||
void GetInfo(AudioCapturerImpl *capturer, IpcIo *reply);
|
||||
void Start(AudioCapturerImpl *capturer, IpcIo *reply);
|
||||
void Stop(AudioCapturerImpl *capturer, IpcIo *reply);
|
||||
void GetMiniFrameCount(IpcIo *req, IpcIo *reply);
|
||||
void GetFrameCount(AudioCapturerImpl *capturer, IpcIo *reply);
|
||||
void GetStatus(AudioCapturerImpl *capturer, IpcIo *reply);
|
||||
void SetSurface(IpcIo *req, IpcIo *reply);
|
||||
|
||||
pid_t clientPid_ = -1;
|
||||
AudioCapturerImpl *capturer_ = nullptr;
|
||||
Surface *surface_ = nullptr;
|
||||
// std::thread dataThreadId_;
|
||||
pthread_t dataThreadId_ = 0;
|
||||
std::mutex lock_;
|
||||
bool threadExit_ = false;
|
||||
};
|
||||
|
||||
void AudioCapturerServiceReg();
|
||||
} // namespace Audio
|
||||
} // namespace OHOS
|
||||
#endif // AUDIO_CAPTURER_SERVER_H
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 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 <ohos_errno.h>
|
||||
#include <ohos_init.h>
|
||||
#include "audio_capturer_server.h"
|
||||
#include "feature.h"
|
||||
#include "iproxy_server.h"
|
||||
#include "media_log.h"
|
||||
#include "samgr_lite.h"
|
||||
#include "service.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Audio {
|
||||
struct DefaultFeatureApi {
|
||||
INHERIT_SERVER_IPROXY;
|
||||
};
|
||||
|
||||
struct AudioCapturerService {
|
||||
INHERIT_SERVICE;
|
||||
INHERIT_IUNKNOWNENTRY(DefaultFeatureApi);
|
||||
Identity identity;
|
||||
};
|
||||
|
||||
static const char *GetName(Service *service)
|
||||
{
|
||||
(void)service;
|
||||
return AUDIO_CAPTURER_SERVICE_NAME;
|
||||
}
|
||||
|
||||
static BOOL Initialize(Service *service, Identity identity)
|
||||
{
|
||||
AudioCapturerService *capturerSvc = (AudioCapturerService *)service;
|
||||
capturerSvc->identity = identity;
|
||||
MEDIA_INFO_LOG("Initialize(%s)! Identity<%d, %d, %p>", AUDIO_CAPTURER_SERVICE_NAME, identity.serviceId,
|
||||
identity.featureId, identity.queueId);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL MessageHandle(Service *service, Request *msg)
|
||||
{
|
||||
MEDIA_DEBUG_LOG("MessageHandle(%s)! Request<%d, %d, %p>", service->GetName(service), msg->msgId, msg->msgValue,
|
||||
msg->data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static TaskConfig GetTaskConfig(Service *service)
|
||||
{
|
||||
(void)service;
|
||||
TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL, 0x800, 20, SHARED_TASK};
|
||||
return config;
|
||||
}
|
||||
|
||||
static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
|
||||
{
|
||||
pid_t pid = GetCallingPid(origin);
|
||||
AudioCapturerServer *mng = AudioCapturerServer::GetInstance();
|
||||
mng->Dispatch(funcId, pid, req, reply);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void AudioCapturerServiceReg()
|
||||
{
|
||||
static AudioCapturerService audioCapturerSvc = {
|
||||
.GetName = GetName,
|
||||
.Initialize = Initialize,
|
||||
.MessageHandle = MessageHandle,
|
||||
.GetTaskConfig = GetTaskConfig,
|
||||
SERVER_IPROXY_IMPL_BEGIN,
|
||||
.Invoke = Invoke,
|
||||
IPROXY_END,
|
||||
};
|
||||
MEDIA_INFO_LOG("Input AudioCapturerServiceReg");
|
||||
bool ret = SAMGR_GetInstance()->RegisterService((Service *)&audioCapturerSvc);
|
||||
if (!ret) {
|
||||
MEDIA_ERR_LOG("AudioCapturer regist service failed.");
|
||||
return;
|
||||
}
|
||||
ret = SAMGR_GetInstance()->RegisterDefaultFeatureApi(AUDIO_CAPTURER_SERVICE_NAME, GET_IUNKNOWN(audioCapturerSvc));
|
||||
if (!ret) {
|
||||
MEDIA_ERR_LOG("AudioCapturer regist feature failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // namespace Audio
|
||||
} // namespace OHOS
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 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_server.h"
|
||||
|
||||
#include "audio_capturer_impl.h"
|
||||
#include "media_errors.h"
|
||||
#include "media_log.h"
|
||||
#include "securec.h"
|
||||
#include "surface.h"
|
||||
#include "surface_impl.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace OHOS::Media;
|
||||
namespace OHOS {
|
||||
namespace Audio {
|
||||
AudioCapturerServer *AudioCapturerServer::GetInstance()
|
||||
{
|
||||
static AudioCapturerServer mng;
|
||||
return &mng;
|
||||
}
|
||||
|
||||
AudioCapturerImpl *AudioCapturerServer::GetAudioCapturer(pid_t pid)
|
||||
{
|
||||
return (pid == clientPid_) ? capturer_ : nullptr;
|
||||
}
|
||||
|
||||
int32_t AudioCapturerServer::AudioCapturerServerInit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioCapturerServer::AcceptServer(pid_t pid, IpcIo *reply)
|
||||
{
|
||||
MEDIA_INFO_LOG("in");
|
||||
if (clientPid_ == -1) {
|
||||
capturer_ = new AudioCapturerImpl;
|
||||
clientPid_ = pid;
|
||||
IpcIoPushInt32(reply, MEDIA_OK);
|
||||
} else {
|
||||
IpcIoPushInt32(reply, MEDIA_IPC_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioCapturerServer::DropServer(pid_t pid, IpcIo *reply)
|
||||
{
|
||||
MEDIA_INFO_LOG("in");
|
||||
if (pid == clientPid_) {
|
||||
if (dataThreadId_ != 0) {
|
||||
threadExit_ = true;
|
||||
pthread_join(dataThreadId_, nullptr);
|
||||
threadExit_ = false;
|
||||
dataThreadId_ = 0;
|
||||
}
|
||||
delete capturer_;
|
||||
capturer_ = nullptr;
|
||||
clientPid_ = -1;
|
||||
}
|
||||
IpcIoPushInt32(reply, MEDIA_OK);
|
||||
}
|
||||
|
||||
void *AudioCapturerServer::ReadAudioDataProcess(void *serverStr)
|
||||
{
|
||||
AudioCapturerServer *serverStore = (AudioCapturerServer *)serverStr;
|
||||
if (serverStore == nullptr || serverStore->surface_ == nullptr) {
|
||||
MEDIA_ERR_LOG("No available serverStore in surface.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MEDIA_INFO_LOG("thread work");
|
||||
while (!serverStore->threadExit_) {
|
||||
/* request surface buffer */
|
||||
SurfaceBuffer *surfaceBuf = serverStore->surface_->RequestBuffer();
|
||||
if (surfaceBuf == nullptr) {
|
||||
usleep(20000); // indicates 20000 microseconds
|
||||
continue;
|
||||
}
|
||||
uint32_t size = serverStore->surface_->GetSize();
|
||||
void *buf = surfaceBuf->GetVirAddr();
|
||||
uint32_t offSet = sizeof(Timestamp);
|
||||
/* Timestamp + audio data */
|
||||
/* read frame data, and reserve timestamp space */
|
||||
int32_t readLen = serverStore->capturer_->Read((uint8_t *)buf + offSet, size - offSet, true);
|
||||
if (readLen == ERR_INVALID_READ) {
|
||||
serverStore->surface_->CancelBuffer(surfaceBuf);
|
||||
usleep(20000); // indicates 20000 microseconds
|
||||
continue;
|
||||
}
|
||||
|
||||
Timestamp timestamp;
|
||||
Timestamp::Timebase base = {};
|
||||
bool ret = serverStore->capturer_->GetTimestamp(timestamp, base);
|
||||
if (!ret) {
|
||||
MEDIA_ERR_LOG("No readtime get.");
|
||||
serverStore->surface_->CancelBuffer(surfaceBuf);
|
||||
continue;
|
||||
}
|
||||
memcpy_s((uint8_t *)buf, sizeof(Timestamp), ×tamp, sizeof(Timestamp));
|
||||
surfaceBuf->SetSize(sizeof(Timestamp) + readLen);
|
||||
|
||||
// flush buffer
|
||||
if (serverStore->surface_->FlushBuffer(surfaceBuf) != 0) {
|
||||
MEDIA_ERR_LOG("Flush surface buffer failed.");
|
||||
serverStore->surface_->CancelBuffer(surfaceBuf);
|
||||
ret = MEDIA_ERR;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
MEDIA_INFO_LOG("thread exit");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int32_t AudioCapturerServer::SetSurfaceProcess(Surface *surface)
|
||||
{
|
||||
if (surface == nullptr) {
|
||||
MEDIA_INFO_LOG("Surface is null");
|
||||
return -1;
|
||||
}
|
||||
surface_ = surface;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioCapturerServer::GetMinFrameCount(IpcIo *req, IpcIo *reply)
|
||||
{
|
||||
int32_t sampleRate = IpcIoPopInt32(req);
|
||||
int32_t channelCount = IpcIoPopInt32(req);
|
||||
AudioCodecFormat audioFormat = (AudioCodecFormat)IpcIoPopInt32(req);
|
||||
size_t frameCount;
|
||||
bool ret = AudioCapturerImpl::GetMinFrameCount(sampleRate, channelCount, audioFormat, frameCount);
|
||||
IpcIoPushInt32(reply, ret);
|
||||
IpcIoPushUint32(reply, frameCount);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::SetInfo(AudioCapturerImpl *capturer, IpcIo *req, IpcIo *reply)
|
||||
{
|
||||
AudioCapturerInfo info;
|
||||
uint32_t size = 0;
|
||||
void *bufferAdd = IpcIoPopFlatObj(req, &size);
|
||||
|
||||
if (bufferAdd == nullptr || size == 0) {
|
||||
MEDIA_INFO_LOG("IpcIoPopFlatObj info failed");
|
||||
IpcIoPushInt32(reply, -1);
|
||||
return;
|
||||
}
|
||||
memcpy_s(&info, sizeof(AudioCapturerInfo), bufferAdd, size);
|
||||
int32_t ret = capturer->SetCapturerInfo(info);
|
||||
IpcIoPushInt32(reply, ret);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::GetInfo(AudioCapturerImpl *capturer, IpcIo *reply)
|
||||
{
|
||||
AudioCapturerInfo info;
|
||||
int32_t ret = capturer->GetCapturerInfo(info);
|
||||
IpcIoPushInt32(reply, ret);
|
||||
IpcIoPushFlatObj(reply, &info, sizeof(AudioCapturerInfo));
|
||||
}
|
||||
|
||||
void AudioCapturerServer::Start(AudioCapturerImpl *capturer, IpcIo *reply)
|
||||
{
|
||||
bool record = capturer->Record();
|
||||
if (record) {
|
||||
threadExit_ = false;
|
||||
pthread_create(&dataThreadId_, nullptr, ReadAudioDataProcess, this);
|
||||
MEDIA_INFO_LOG("create thread ReadAudioDataProcess SUCCESS");
|
||||
}
|
||||
IpcIoPushInt32(reply, record);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::Stop(AudioCapturerImpl *capturer, IpcIo *reply)
|
||||
{
|
||||
int32_t ret = capturer->Stop();
|
||||
if (dataThreadId_ != 0) {
|
||||
threadExit_ = true;
|
||||
pthread_join(dataThreadId_, nullptr);
|
||||
threadExit_ = false;
|
||||
dataThreadId_ = 0;
|
||||
}
|
||||
IpcIoPushInt32(reply, ret);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::GetMiniFrameCount(IpcIo *req, IpcIo *reply)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
int32_t sampleRate = IpcIoPopInt32(req);
|
||||
int32_t channelCount = IpcIoPopInt32(req);
|
||||
AudioCodecFormat *audioFormat = (AudioCodecFormat *)IpcIoPopFlatObj(req, &size);
|
||||
|
||||
size_t frameCount;
|
||||
bool ret = AudioCapturerImpl::GetMinFrameCount(sampleRate, channelCount, *audioFormat, frameCount);
|
||||
IpcIoPushInt32(reply, ret);
|
||||
IpcIoPushUint64(reply, frameCount);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::GetFrameCount(AudioCapturerImpl *capturer, IpcIo *reply)
|
||||
{
|
||||
uint64_t frameCount = capturer->GetFrameCount();
|
||||
IpcIoPushInt32(reply, MEDIA_OK);
|
||||
IpcIoPushUint64(reply, frameCount);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::GetStatus(AudioCapturerImpl *capturer, IpcIo *reply)
|
||||
{
|
||||
State status = capturer->GetStatus();
|
||||
IpcIoPushInt32(reply, MEDIA_OK);
|
||||
IpcIoPushInt32(reply, status);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::SetSurface(IpcIo *req, IpcIo *reply)
|
||||
{
|
||||
Surface *surface = SurfaceImpl::GenericSurfaceByIpcIo(*req);
|
||||
int32_t ret = SetSurfaceProcess(surface);
|
||||
IpcIoPushInt32(reply, ret);
|
||||
}
|
||||
|
||||
void AudioCapturerServer::Dispatch(int32_t funcId, pid_t pid, IpcIo *req, IpcIo *reply)
|
||||
{
|
||||
int32_t ret;
|
||||
if (funcId == AUD_CAP_FUNC_GET_MIN_FRAME_COUNT) {
|
||||
return;
|
||||
}
|
||||
if (funcId == AUD_CAP_FUNC_CONNECT) {
|
||||
AcceptServer(pid, reply);
|
||||
return;
|
||||
}
|
||||
auto capturer = GetAudioCapturer(pid);
|
||||
if (capturer == nullptr) {
|
||||
MEDIA_ERR_LOG("Cannot find client object.(pid=%d)", pid);
|
||||
IpcIoPushInt32(reply, MEDIA_IPC_FAILED);
|
||||
}
|
||||
switch (funcId) {
|
||||
case AUD_CAP_FUNC_DISCONNECT:
|
||||
DropServer(pid, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_GET_FRAME_COUNT:
|
||||
GetFrameCount(capturer, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_GET_STATUS:
|
||||
GetStatus(capturer, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_SET_INFO:
|
||||
SetInfo(capturer, req, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_GET_INFO:
|
||||
GetInfo(capturer, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_START:
|
||||
Start(capturer, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_STOP:
|
||||
Stop(capturer, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_RELEASE:
|
||||
ret = capturer->Release();
|
||||
IpcIoPushInt32(reply, ret);
|
||||
break;
|
||||
case AUD_CAP_FUNC_SET_SURFACE:
|
||||
SetSurface(req, reply);
|
||||
break;
|
||||
case AUD_CAP_FUNC_GET_MIN_FRAME_COUNT:
|
||||
GetMiniFrameCount(req, reply);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace Audio
|
||||
} // namespace OHOS
|
||||
+13
-12
@@ -20,24 +20,25 @@ group("lite_audio_test") {
|
||||
}
|
||||
|
||||
if (ohos_build_type == "debug") {
|
||||
unittest("lite_audio_unittest") {
|
||||
unittest("lite_audio_unittest") {
|
||||
output_dir = "$root_out_dir/test/unittest/audiolite"
|
||||
sources = [ "unittest/audiolite_test.cpp" ]
|
||||
include_dirs = [
|
||||
"//foundation/multimedia/audio_lite/frameworks/audio_encoder/include",
|
||||
"//foundation/multimedia/audio_lite/frameworks/audio_source/include",
|
||||
"//foundation/multimedia/audio_lite/interfaces/kits",
|
||||
"//foundation/multimedia/utils/lite/include",
|
||||
"//drivers/peripheral/audio/interfaces/include",
|
||||
"//drivers/peripheral/codec/interfaces/include",
|
||||
"//drivers/peripheral/format/interfaces/include",
|
||||
"//foundation/multimedia/audio_lite/test/unittest",
|
||||
"//foundation/multimedia/audio_lite/frameworks/audio_encoder/include",
|
||||
"//foundation/multimedia/audio_lite/frameworks/audio_source/include",
|
||||
"//foundation/multimedia/audio_lite/interfaces/kits",
|
||||
"//foundation/multimedia/utils/lite/include",
|
||||
"//drivers/peripheral/audio/interfaces/include",
|
||||
"//drivers/peripheral/codec/interfaces/include",
|
||||
"//drivers/peripheral/format/interfaces/include",
|
||||
"//foundation/multimedia/audio_lite/test/unittest",
|
||||
"//foundation/multimedia/utils/lite/interfaces/kits",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//foundation/multimedia/audio_lite/frameworks:audio_capturer_lite",
|
||||
"//foundation/multimedia/utils/lite:media_common",
|
||||
"//third_party/bounds_checking_function:libsec_shared",
|
||||
"//foundation/multimedia/audio_lite/frameworks:audio_capturer_lite",
|
||||
"//foundation/multimedia/utils/lite:media_common",
|
||||
"//third_party/bounds_checking_function:libsec_shared",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user