Files
drivers_peripheral/audio/test/sample/idl_render.c
T
2022-09-07 12:28:41 +08:00

1376 lines
42 KiB
C

/*
* Copyright (c) 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 <dlfcn.h>
#include <limits.h>
#include <pthread.h>
#include <securec.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include "hdf_base.h"
#include "hdf_remote_adapter_if.h"
#include "inttypes.h"
#include "osal_mem.h"
#include "v1_0/iaudio_manager.h"
#define AUDIO_FUNC_LOGE(fmt, arg...) \
do { \
printf("%s: [%s]: [%d]:[ERROR]:" fmt "\n", __FILE__, __func__, __LINE__, ##arg); \
} while (0)
#define MAX_AUDIO_ADAPTER_DESC 5
#define BUFFER_LEN 256
#define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157
#define ID_FMT 0x20746d66
#define ID_DATA 0x61746164
#define MOVE_LEFT_NUM 8
#define AUDIO_SAMPLE_RATE_8K 8000
#define AUDIO_CHANNELCOUNT 2
#define AUDIO_SAMPLE_RATE_48K 48000
#define PATH_LEN 256
#define DEEP_BUFFER_RENDER_PERIOD_SIZE 4096
#define DEEP_BUFFER_RENDER_PERIOD_COUNT 8
#define INT_32_MAX 0x7fffffff
#define EXT_PARAMS_MAXLEN 107
#define BITS_TO_FROMAT 3
#define SERVICE_NAME "idl_audio_service"
enum AudioPCMBit {
PCM_8_BIT = 8, /* 8-bit PCM */
PCM_16_BIT = 16, /* 16-bit PCM */
PCM_24_BIT = 24, /* 24-bit PCM */
PCM_32_BIT = 32, /* 32-bit PCM */
};
enum RenderSoundCardMode {
PRIMARY = 1,
PRIMARY_EXT = 2,
AUDIO_USB = 3,
AUDIO_A2DP = 4,
};
enum RenderLoadingMode {
DIRECT = 1,
SERVICE = 2,
};
struct AudioHeadInfo {
uint32_t testFileRiffId;
uint32_t testFileRiffSize;
uint32_t testFileFmt;
uint32_t audioFileFmtId;
uint32_t audioFileFmtSize;
uint16_t audioFileFormat;
uint16_t audioChannelNum;
uint32_t audioSampleRate;
uint32_t audioByteRate;
uint16_t audioBlockAlign;
uint16_t audioBitsPerSample;
uint32_t dataId;
uint32_t dataSize;
};
struct StrPara {
struct IAudioRender *render;
FILE *file;
struct AudioSampleAttributes attrs;
uint64_t *replyBytes;
char *frame;
int32_t bufferSize;
};
struct IAudioRender *g_render = NULL;
struct IAudioAdapter *g_adapter = NULL;
static struct IAudioManager *g_audioManager = NULL;
struct AudioDeviceDescriptor g_devDesc;
struct AudioSampleAttributes g_attrs;
struct AudioPort g_audioPort;
struct AudioHeadInfo g_wavHeadInfo;
static struct StrPara g_str;
void (*g_audioManagerRelease)(struct IAudioManager *) = NULL;
void (*g_audioAdapterRelease)(struct IAudioAdapter *) = NULL;
void (*g_audioRenderRelease)(struct IAudioRender *) = NULL;
pthread_t g_tids;
char *g_frame = NULL;
void *g_handle;
FILE *g_file;
char g_path[256];
char g_adapterName[PATH_LEN] = {0};
static int32_t g_closeEnd = 0;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t g_functionCond = PTHREAD_COND_INITIALIZER;
bool g_waitSleep = false;
enum RenderMenuId {
RENDER_START = 1,
RENDER_STOP,
RENDER_RESUME,
RENDER_PAUSE,
SET_RENDER_VOLUME,
SET_RENDER_GAIN,
SET_RENDER_MUTE,
SET_RENDER_ATTRIBUTES,
SET_RENDER_SLECET_SCENE,
GET_RENDER_EXT_PARAMS,
GET_RENDER_POSITION,
};
enum RenderInputType {
INPUT_INT = 0,
INPUT_FLOAT,
INPUT_UINT32,
};
typedef int32_t (*AudioRenderOperation)(struct IAudioRender **);
struct ProcessRenderMenuSwitchList {
enum RenderMenuId cmd;
AudioRenderOperation operation;
};
static void CleanStdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
static int32_t CheckInputName(int type, void *val)
{
int ret;
int inputInt = 0;
float inputFloat = 0.0;
uint32_t inputUint = 0;
if (val == NULL) {
return HDF_FAILURE;
}
printf("\n");
switch (type) {
case INPUT_INT:
ret = scanf_s("%d", &inputInt);
if (inputInt < 0 || inputInt > GET_RENDER_POSITION + 1) {
AUDIO_FUNC_LOGE("Input failure");
return HDF_FAILURE;
}
*(int *)val = inputInt;
break;
case INPUT_FLOAT:
ret = scanf_s("%f", &inputFloat);
*(float *)val = inputFloat;
break;
case INPUT_UINT32:
ret = scanf_s("%u", &inputUint);
if (inputUint > 0xFFFFFFFF || inputUint < 0) {
return HDF_FAILURE;
}
*(uint32_t *)val = inputUint;
break;
default:
ret = EOF;
break;
}
if (ret == 0) {
CleanStdin();
} else if (ret == EOF) {
AUDIO_FUNC_LOGE("Input failure occurs!");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static void SystemInputFail(void)
{
printf("please ENTER to go on...");
while (getchar() != '\n') {
continue;
}
}
static int32_t InitAttrs(struct AudioSampleAttributes *attrs)
{
if (attrs == NULL) {
return HDF_FAILURE;
}
/* Initialization of audio parameters for playback */
attrs->format = AUDIO_FORMAT_PCM_16_BIT;
attrs->channelCount = AUDIO_CHANNELCOUNT;
attrs->sampleRate = AUDIO_SAMPLE_RATE_48K;
attrs->interleaved = 0;
attrs->type = AUDIO_IN_MEDIA;
attrs->period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
attrs->frameSize = PCM_16_BIT * attrs->channelCount / PCM_8_BIT;
attrs->isBigEndian = false;
attrs->isSignedData = true;
attrs->startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs->frameSize);
attrs->stopThreshold = INT_32_MAX;
attrs->silenceThreshold = 0;
return HDF_SUCCESS;
}
static int32_t InitDevDesc(struct AudioDeviceDescriptor *devDesc, uint32_t portId)
{
if (devDesc == NULL) {
return HDF_FAILURE;
}
/* Initialization of audio parameters for playback */
devDesc->portId = portId;
devDesc->pins = PIN_OUT_SPEAKER;
devDesc->desc = strdup("cardname");
return HDF_SUCCESS;
}
static uint32_t StringToInt(const char *flag)
{
if (flag == NULL) {
return 0;
}
uint32_t temp = flag[0];
for (int32_t i = (int32_t)strlen(flag) - 1; i >= 0; i--) {
temp <<= MOVE_LEFT_NUM;
temp += flag[i];
}
return temp;
}
static int32_t WavHeadAnalysis(FILE *file, struct AudioSampleAttributes *attrs)
{
if (file == NULL || attrs == NULL) {
return HDF_FAILURE;
}
size_t ret;
const char *audioRiffIdParam = "RIFF";
const char *audioFileFmtParam = "WAVE";
const char *aduioDataIdParam = "data";
ret = fread(&g_wavHeadInfo, sizeof(g_wavHeadInfo), 1, file);
if (ret != 1) {
return HDF_FAILURE;
}
uint32_t audioRiffId = StringToInt(audioRiffIdParam);
uint32_t audioFileFmt = StringToInt(audioFileFmtParam);
uint32_t aduioDataId = StringToInt(aduioDataIdParam);
if (g_wavHeadInfo.testFileRiffId != audioRiffId || g_wavHeadInfo.testFileFmt != audioFileFmt ||
g_wavHeadInfo.dataId != aduioDataId) {
return HDF_FAILURE;
}
attrs->channelCount = g_wavHeadInfo.audioChannelNum;
attrs->sampleRate = g_wavHeadInfo.audioSampleRate;
switch (g_wavHeadInfo.audioBitsPerSample) {
case PCM_8_BIT: {
attrs->format = AUDIO_FORMAT_PCM_8_BIT;
break;
}
case PCM_16_BIT: {
attrs->format = AUDIO_FORMAT_PCM_16_BIT;
break;
}
case PCM_24_BIT: {
attrs->format = AUDIO_FORMAT_PCM_24_BIT;
break;
}
case PCM_32_BIT: {
attrs->format = AUDIO_FORMAT_PCM_32_BIT;
break;
}
default:
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t SwitchAdapter(struct AudioAdapterDescriptor *descs, const char *adapterNameCase,
enum AudioPortDirection portFlag, struct AudioPort *renderPort, int32_t size)
{
struct AudioAdapterDescriptor *desc = NULL;
if (descs == NULL || adapterNameCase == NULL || renderPort == NULL) {
return HDF_FAILURE;
}
uint32_t port;
for (int32_t index = 0; index < size; index++) {
desc = &descs[index];
if (desc == NULL) {
continue;
}
if (desc->adapterName == NULL) {
return HDF_FAILURE;
}
if (strcmp((const char *)desc->adapterName, adapterNameCase)) {
continue;
}
for (port = 0; port < desc->portsLen; port++) {
// Only find out the port of out in the sound card
if (desc->ports[port].dir == portFlag) {
*renderPort = desc->ports[port];
return index;
}
}
}
return HDF_ERR_NOT_SUPPORT;
}
static void StreamClose(int32_t sig)
{
/* allow the stream to be closed gracefully */
(void)signal(sig, SIG_IGN);
g_closeEnd = 1;
}
static uint32_t PcmFormatToBits(enum AudioFormat formatBit)
{
switch (formatBit) {
case AUDIO_FORMAT_PCM_16_BIT:
return PCM_16_BIT;
case AUDIO_FORMAT_PCM_8_BIT:
return PCM_8_BIT;
default:
return PCM_16_BIT;
}
}
static uint32_t PcmFramesToBytes(const struct AudioSampleAttributes attrs)
{
return DEEP_BUFFER_RENDER_PERIOD_SIZE * attrs.channelCount * (PcmFormatToBits(attrs.format) >> BITS_TO_FROMAT);
}
static int32_t StopAudioFiles(struct IAudioRender **renderS)
{
if (renderS == NULL) {
return HDF_FAILURE;
}
if (g_waitSleep) {
pthread_mutex_lock(&g_mutex);
g_waitSleep = false;
pthread_cond_signal(&g_functionCond);
pthread_mutex_unlock(&g_mutex);
}
if (!g_closeEnd) {
g_closeEnd = true;
usleep(100000); // sleep 100000us
}
struct IAudioRender *render = *renderS;
if (render == NULL) {
AUDIO_FUNC_LOGE("render is null");
return HDF_FAILURE;
}
int32_t ret = render->Stop((void *)render);
if (ret < 0) {
AUDIO_FUNC_LOGE("Stop Render!");
}
if (g_adapter == NULL || g_adapter->DestroyRender == NULL) {
return HDF_FAILURE;
}
ret = g_adapter->DestroyRender(g_adapter);
if (ret < 0) {
AUDIO_FUNC_LOGE("Destroy Render!");
}
g_audioRenderRelease(render);
*renderS = NULL;
g_render = NULL;
if (g_frame != NULL) {
OsalMemFree(g_frame);
g_frame = NULL;
}
if (g_file != NULL) {
fclose(g_file);
g_file = NULL;
}
printf("Stop Successful\n");
return ret;
}
static int32_t FrameStartMmap(const struct StrPara *param)
{
if (param == NULL) {
return HDF_FAILURE;
}
const struct StrPara *strParam = param;
struct IAudioRender *render = strParam->render;
struct AudioMmapBufferDescripter mmapDesc;
(void)signal(SIGINT, StreamClose);
// get file length
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
return HDF_FAILURE;
}
// get fileSize
FILE *fp = fopen(pathBuf, "rb+");
if (fp == NULL) {
printf("Open file failed!\n");
return HDF_FAILURE;
}
int32_t ret = fseek(fp, 0, SEEK_END);
if (ret != 0) {
fclose(fp);
return HDF_FAILURE;
}
int32_t reqSize = (int32_t)ftell(fp);
if (reqSize < 0) {
fclose(fp);
return HDF_FAILURE;
}
(void)fclose(fp);
// Init param
mmapDesc.memoryFd = 0; // default 0
mmapDesc.filePath = strdup(pathBuf);
mmapDesc.isShareable = 1; // 1:Shareable ,0:Don't share
mmapDesc.transferFrameSize = DEEP_BUFFER_RENDER_PERIOD_SIZE / 4; // One frame size 4 bit
mmapDesc.offset = sizeof(g_wavHeadInfo);
// start
if (render == NULL || render->ReqMmapBuffer == NULL) {
return HDF_FAILURE;
}
ret = render->ReqMmapBuffer(render, reqSize, &mmapDesc);
if (ret < 0 || reqSize <= 0) {
printf("Request map fail,please check.\n");
return HDF_FAILURE;
}
if (g_render != NULL) {
ret = StopAudioFiles(&render);
if (ret < 0) {
AUDIO_FUNC_LOGE("StopAudioFiles File!");
}
}
return HDF_SUCCESS;
}
static int32_t FrameStart(const struct StrPara *param)
{
if (param == NULL) {
return HDF_FAILURE;
}
const struct StrPara *strParam = param;
struct IAudioRender *render = strParam->render;
char *frame = strParam->frame;
int32_t bufferSize = strParam->bufferSize;
int32_t ret;
size_t readSize;
size_t remainingDataSize = g_wavHeadInfo.testFileRiffSize;
size_t numRead;
(void)signal(SIGINT, StreamClose);
uint64_t replyBytes;
if (g_file == NULL) {
return HDF_FAILURE;
}
if (render == NULL || render->RenderFrame == NULL || frame == NULL) {
return HDF_FAILURE;
}
do {
readSize = (remainingDataSize > bufferSize) ? (size_t)bufferSize : remainingDataSize;
numRead = fread(frame, 1, readSize, g_file);
if (numRead > 0) {
ret = render->RenderFrame(render, (int8_t *)frame, numRead, &replyBytes);
if (ret == HDF_ERR_INVALID_OBJECT) {
AUDIO_FUNC_LOGE("Render already stop!");
break;
}
remainingDataSize -= numRead;
}
while (g_waitSleep) {
printf("music pause now.\n");
pthread_cond_wait(&g_functionCond, &g_mutex);
printf("music resume now.\n");
}
} while (!g_closeEnd && numRead > 0 && remainingDataSize > 0);
if (!g_closeEnd) {
printf("\nPlay complete, please select input again\n");
(void)StopAudioFiles(&render);
}
return HDF_SUCCESS;
}
static void FileClose(FILE **file)
{
if ((file != NULL) && ((*file) != NULL)) {
fclose(*file);
*file = NULL;
}
return;
}
static int32_t InitPlayingAudioParam(struct IAudioRender *render)
{
if (render == NULL) {
return HDF_FAILURE;
}
uint32_t bufferSize = PcmFramesToBytes(g_attrs);
g_frame = (char *)OsalMemCalloc(bufferSize);
if (g_frame == NULL) {
return HDF_FAILURE;
}
(void)memset_s(&g_str, sizeof(struct StrPara), 0, sizeof(struct StrPara));
g_str.render = render;
g_str.bufferSize = (int32_t)bufferSize;
g_str.frame = g_frame;
return HDF_SUCCESS;
}
static void PrintPlayMode(void)
{
printf(" ============= Play Render Mode ==========\n");
printf("| 1. Render non-mmap |\n");
printf("| 2. Render mmap |\n");
printf(" ======================================== \n");
}
static int32_t SelectPlayMode(int32_t *palyModeFlag)
{
if (palyModeFlag == NULL) {
AUDIO_FUNC_LOGE("palyModeFlag is null");
return HDF_FAILURE;
}
system("clear");
int choice = 0;
PrintPlayMode();
printf("Please enter your choice:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
AUDIO_FUNC_LOGE("CheckInputName Fail");
return HDF_FAILURE;
} else {
*palyModeFlag = choice;
}
return HDF_SUCCESS;
}
static int32_t StartPlayThread(int32_t palyModeFlag)
{
pthread_attr_t tidsAttr;
pthread_attr_init(&tidsAttr);
pthread_attr_setdetachstate(&tidsAttr, PTHREAD_CREATE_DETACHED);
switch (palyModeFlag) {
case 1: // 1. Stander Loading
if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
return HDF_FAILURE;
}
break;
case 2: // 2. Low latency Loading
if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStartMmap), &g_str) != 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
return HDF_FAILURE;
}
break;
default:
printf("Input error,Switched to non-mmap Mode for you,");
SystemInputFail();
if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
return HDF_FAILURE;
}
break;
}
return HDF_SUCCESS;
}
static int32_t PlayingAudioInitFile(void)
{
if (g_file != NULL) {
AUDIO_FUNC_LOGE("the music is playing,please stop first");
return HDF_FAILURE;
}
g_closeEnd = false;
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
return HDF_FAILURE;
}
g_file = fopen(pathBuf, "rb");
if (g_file == NULL) {
printf("failed to open '%s'\n", g_path);
return HDF_FAILURE;
}
if (WavHeadAnalysis(g_file, &g_attrs) < 0) {
AUDIO_FUNC_LOGE("Frame test is Fail");
FileClose(&g_file);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp)
{
if (renderTemp == NULL) {
AUDIO_FUNC_LOGE("render is null");
return HDF_FAILURE;
}
struct IAudioRender *render = NULL;
int32_t ret = g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &render);
if (render == NULL || ret < 0 || render->RenderFrame == NULL) {
AUDIO_FUNC_LOGE("AudioDeviceCreateRender failed or RenderFrame is null");
return HDF_FAILURE;
}
// Playing audio files
if (render->Start((void *)render)) {
AUDIO_FUNC_LOGE("Start Bind Fail!");
g_adapter->DestroyRender(g_adapter);
g_audioRenderRelease(render);
return HDF_FAILURE;
}
if (InitPlayingAudioParam(render) < 0) {
g_adapter->DestroyRender(g_adapter);
g_audioRenderRelease(render);
return HDF_FAILURE;
}
*renderTemp = render;
return HDF_SUCCESS;
}
static int32_t PlayingAudioFiles(struct IAudioRender **renderS)
{
if (renderS == NULL || g_adapter == NULL || g_adapter->CreateRender == NULL) {
return HDF_FAILURE;
}
if (PlayingAudioInitFile() < 0) {
AUDIO_FUNC_LOGE("PlayingAudioInitFile Fail");
return HDF_FAILURE;
}
int32_t palyModeFlag = 0;
if (SelectPlayMode(&palyModeFlag) < 0) {
AUDIO_FUNC_LOGE("SelectPlayMode Fail");
FileClose(&g_file);
return HDF_FAILURE;
}
struct IAudioRender *render = NULL;
if (PlayingAudioInitRender(&render) < 0) {
AUDIO_FUNC_LOGE("PlayingAudioInitRender fail");
FileClose(&g_file);
return HDF_FAILURE;
}
if (StartPlayThread(palyModeFlag) < 0) {
FileClose(&g_file);
if (g_adapter != NULL && g_adapter->DestroyRender != NULL) {
g_adapter->DestroyRender(g_adapter);
}
g_audioRenderRelease(render);
return HDF_FAILURE;
}
*renderS = render;
printf("Start Successful,Music is playing\n");
return HDF_SUCCESS;
}
static void PrintMenu0(void)
{
printf(" ============= Play Render Sound Card Mode ==========\n");
printf("| 1. Render Primary |\n");
printf("| 2. Render Primary_Ext |\n");
printf("| 3. Render Usb |\n");
printf("| 4. Render A2dp |\n");
printf(" =================================================== \n");
}
static void PrintMenu1(void)
{
printf(" ============== Play Render Loading Mode ===========\n");
printf("| 1. Render Direct Loading |\n");
printf("| 2. Render Service Loading |\n");
printf("| Note: switching is not supported in the MPI's |\n");
printf("| version. |\n");
printf(" ================================================== \n");
}
static int32_t SwitchInternalOrExternal(char *adapterNameCase, int32_t nameLen)
{
system("clear");
int choice = 0;
PrintMenu0();
printf("Please enter your choice:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
return HDF_FAILURE;
}
switch (choice) {
case PRIMARY:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "primary");
break;
case PRIMARY_EXT:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "primary_ext");
break;
case AUDIO_USB:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "usb");
break;
case AUDIO_A2DP:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "a2dp");
break;
default:
printf("Input error,Switched to Acodec in for you,");
SystemInputFail();
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "primary");
break;
}
return HDF_SUCCESS;
}
static int32_t SelectLoadingMode(char *resolvedPath, int32_t pathLen)
{
system("clear");
int choice = 0;
char *soPathHdi = NULL;
char *soPathProxy = NULL;
soPathHdi = HDF_LIBRARY_FULL_PATH("libhdi_audio_passthrough");
#ifdef __aarch64__
soPathProxy = "/system/lib64/libaudio_proxy_1.0.z.so";
#else
soPathProxy = "/system/lib/libaudio_proxy_1.0.z.so";
#endif
PrintMenu1();
printf("Please enter your choice:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
return HDF_FAILURE;
}
switch (choice) {
case DIRECT:
if (snprintf_s(resolvedPath, pathLen, pathLen - 1, "%s", soPathHdi) < 0) {
return HDF_FAILURE;
}
break;
case SERVICE:
if (snprintf_s(resolvedPath, pathLen, pathLen - 1, "%s", soPathProxy) < 0) {
return HDF_FAILURE;
}
break;
default:
printf("Input error,Switched to direct loading in for you,");
SystemInputFail();
if (snprintf_s(resolvedPath, pathLen, pathLen - 1, "%s", soPathHdi) < 0) {
return HDF_FAILURE;
}
break;
}
return HDF_SUCCESS;
}
void AudioAdapterDescriptorFree(struct AudioAdapterDescriptor *dataBlock, bool freeSelf)
{
if (dataBlock == NULL) {
return;
}
if (dataBlock->adapterName != NULL) {
OsalMemFree(dataBlock->adapterName);
dataBlock->adapterName = NULL;
}
if (dataBlock->ports != NULL) {
OsalMemFree(dataBlock->ports);
}
if (freeSelf) {
OsalMemFree(dataBlock);
}
}
static void ReleaseAdapterDescs(struct AudioAdapterDescriptor **descs, uint32_t descsLen)
{
if (descsLen > 0 && descs != NULL && (*descs) != NULL) {
for (uint32_t i = 0; i < descsLen; i++) {
AudioAdapterDescriptorFree(&(*descs)[i], false);
}
OsalMemFree(*descs);
*descs = NULL;
}
}
static int32_t GetManagerAndLoadAdapter(const char *adapterNameCase, struct AudioPort *renderPort)
{
if (adapterNameCase == NULL || renderPort == NULL) {
AUDIO_FUNC_LOGE("The Parameter is NULL");
return HDF_FAILURE;
}
struct IAudioManager *(*getAudioManager)(const char *) = NULL;
getAudioManager = (struct IAudioManager *(*)(const char *))(dlsym(g_handle, "AudioManagerGetInstance"));
if (getAudioManager == NULL) {
return HDF_FAILURE;
}
(void)HdfRemoteGetCallingPid();
struct IAudioManager *audioManagerIns = getAudioManager(SERVICE_NAME);
if (audioManagerIns == NULL) {
AUDIO_FUNC_LOGE("Get audio Manager Fail");
return HDF_FAILURE;
}
g_audioManager = audioManagerIns;
struct AudioAdapterDescriptor *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc(
sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC));
if (descs == NULL) {
AUDIO_FUNC_LOGE("OsalMemCalloc for descs failed");
return HDF_FAILURE;
}
uint32_t adapterNum = MAX_AUDIO_ADAPTER_DESC;
int32_t ret = audioManagerIns->GetAllAdapters(audioManagerIns, descs, &adapterNum);
if (ret < 0 || adapterNum == 0) {
AUDIO_FUNC_LOGE("Get All Adapters Fail");
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
// Get qualified sound card and port
enum AudioPortDirection port = PORT_OUT; // Set port information
int32_t index = SwitchAdapter(descs, adapterNameCase, port, renderPort, adapterNum);
if (index < 0) {
AUDIO_FUNC_LOGE("Not Switch Adapter Fail");
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
if (audioManagerIns->LoadAdapter(audioManagerIns, &descs[index], &g_adapter)) {
AUDIO_FUNC_LOGE("Load Adapter Fail");
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
if (g_adapter == NULL) {
AUDIO_FUNC_LOGE("load audio device failed");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t InitRenderParam(const char *adapterNameCase, uint32_t portId)
{
if (adapterNameCase == NULL) {
AUDIO_FUNC_LOGE("The Parameter is NULL");
return HDF_FAILURE;
}
if (g_adapter == NULL) {
AUDIO_FUNC_LOGE("g_adapter is NULL");
return HDF_FAILURE;
}
// Initialization port information, can fill through mode and other parameters
(void)g_adapter->InitAllPorts(g_adapter);
// User needs to set
if (InitAttrs(&g_attrs) < 0) {
AUDIO_FUNC_LOGE("InitAttrs failed");
return HDF_FAILURE;
}
// Specify a hardware device
if (InitDevDesc(&g_devDesc, portId) < 0) {
AUDIO_FUNC_LOGE("InitDevDesc failed");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t RenderGetAdapterAndInitEnvParams(const char *adapterNameCase)
{
struct AudioPort renderPort;
int32_t ret = GetManagerAndLoadAdapter(adapterNameCase, &renderPort);
if (ret < 0) {
return ret;
}
if (InitRenderParam(adapterNameCase, renderPort.portId) < 0) {
g_audioManager->UnloadAdapter(g_audioManager, adapterNameCase);
g_audioAdapterRelease(g_adapter);
g_adapter = NULL;
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t InitReleaseFun(void)
{
g_audioManagerRelease = (void (*)(struct IAudioManager *))(dlsym(g_handle, "AudioManagerRelease"));
if (g_audioManagerRelease == NULL) {
AUDIO_FUNC_LOGE("get AudioManagerRelease fun ptr failed");
return HDF_FAILURE;
}
g_audioAdapterRelease = (void (*)(struct IAudioAdapter *))(dlsym(g_handle, "AudioAdapterRelease"));
if (g_audioAdapterRelease == NULL) {
AUDIO_FUNC_LOGE("get AudioAdapterRelease fun ptr failed");
return HDF_FAILURE;
}
g_audioRenderRelease = (void (*)(struct IAudioRender *))(dlsym(g_handle, "AudioRenderRelease"));
if (g_audioRenderRelease == NULL) {
AUDIO_FUNC_LOGE("get AudioRenderRelease fun ptr failed");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t InitParam(void)
{
/* Internal and external switch,begin */
if (SwitchInternalOrExternal(g_adapterName, PATH_LEN) < 0) {
return HDF_FAILURE;
}
char resolvedPath[PATH_LEN] = {0}; // Select loading mode,begin
if (SelectLoadingMode(resolvedPath, PATH_LEN) < 0) {
return HDF_FAILURE;
}
/* Select loading mode,end */
g_audioPort.dir = PORT_OUT;
g_audioPort.portId = 0;
g_audioPort.portName = "AOP";
g_handle = dlopen(resolvedPath, 1);
if (g_handle == NULL) {
AUDIO_FUNC_LOGE("Open so Fail, reason:%s", dlerror());
return HDF_FAILURE;
}
if (InitReleaseFun() < 0) {
AUDIO_FUNC_LOGE("InitReleaseFun Fail");
dlclose(g_handle);
return HDF_FAILURE;
}
if (RenderGetAdapterAndInitEnvParams(g_adapterName) < 0) {
AUDIO_FUNC_LOGE("GetProxyManagerFunc Fail");
if (g_audioManager != NULL) {
g_audioManagerRelease(g_audioManager);
g_audioManager = NULL;
}
dlclose(g_handle);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t SetRenderMute(struct IAudioRender **render)
{
(void)render;
int32_t val;
bool isMute = false;
int32_t ret;
if (g_render == NULL || g_render->GetMute == NULL) {
return HDF_FAILURE;
}
ret = g_render->GetMute((void *)g_render, &isMute);
if (ret < 0) {
AUDIO_FUNC_LOGE("The current mute state was not obtained!");
}
printf("Now %s ,Do you need to set mute status(1/0):", isMute ? "mute" : "not mute");
ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
return HDF_FAILURE;
}
if (isMute != 0 && isMute != 1) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render == NULL || g_render->SetMute == NULL) {
AUDIO_FUNC_LOGE("Music already stop!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
ret = g_render->SetMute((void *)g_render, !isMute);
}
return ret;
}
static int32_t SetRenderVolume(struct IAudioRender **render)
{
(void)render;
int32_t ret;
float val = 0.0;
if (g_render == NULL || g_render->GetVolume == NULL) {
return HDF_FAILURE;
}
ret = g_render->GetVolume((void *)g_render, &val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get current volume failed!");
SystemInputFail();
return ret;
}
printf("Now the volume is %f ,Please enter the volume value you want to set (0.0-1.0):", val);
ret = CheckInputName(INPUT_FLOAT, (void *)&val);
if (ret < 0) {
return HDF_FAILURE;
}
if (val < 0.0 || val > 1.0) {
AUDIO_FUNC_LOGE("Invalid volume value!");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render == NULL || g_render->SetVolume == NULL) {
AUDIO_FUNC_LOGE("Music already stop!");
SystemInputFail();
return HDF_FAILURE;
}
ret = g_render->SetVolume((void *)g_render, val);
if (ret < 0) {
AUDIO_FUNC_LOGE("set volume fail!");
SystemInputFail();
}
return ret;
}
static int32_t GetRenderGain(struct IAudioRender **render)
{
(void)render;
int32_t ret;
float val = 1.0;
if (g_render == NULL || g_render->GetGain == NULL) {
return HDF_FAILURE;
}
ret = g_render->GetGain((void *)g_render, &val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get current gain failed!");
SystemInputFail();
return HDF_FAILURE;
}
printf("Now the gain is %f,", val);
SystemInputFail();
return HDF_SUCCESS;
}
static int32_t SetRenderPause(struct IAudioRender **render)
{
(void)render;
if (g_waitSleep) {
AUDIO_FUNC_LOGE("Already pause,not need pause again!");
SystemInputFail();
return HDF_FAILURE;
}
int32_t ret;
if (g_render == NULL || g_render->Pause == NULL) {
return HDF_FAILURE;
}
ret = g_render->Pause((void *)g_render);
if (ret != 0) {
return HDF_FAILURE;
}
printf("Pause success!\n");
g_waitSleep = true;
return HDF_SUCCESS;
}
static int32_t SetRenderResume(struct IAudioRender **render)
{
(void)render;
if (!g_waitSleep) {
AUDIO_FUNC_LOGE("Now is Playing,not need resume!");
SystemInputFail();
return HDF_FAILURE;
}
int32_t ret;
if (g_render == NULL || g_render->Resume == NULL) {
return HDF_FAILURE;
}
ret = g_render->Resume((void *)g_render);
if (ret != 0) {
return HDF_FAILURE;
}
printf("resume success!\n");
pthread_mutex_lock(&g_mutex);
g_waitSleep = false;
pthread_cond_signal(&g_functionCond);
pthread_mutex_unlock(&g_mutex);
return HDF_SUCCESS;
}
static void PrintAttributesFromat(void)
{
printf(" ============= Render Sample Attributes Fromat =============== \n");
printf("| 1. Render AUDIO_FORMAT_PCM_8_BIT |\n");
printf("| 2. Render AUDIO_FORMAT_PCM_16_BIT |\n");
printf("| 3. Render AUDIO_FORMAT_PCM_24_BIT |\n");
printf("| 4. Render AUDIO_FORMAT_PCM_32_BIT |\n");
printf(" ============================================================= \n");
}
static int32_t SelectAttributesFomat(uint32_t *pcmFomat)
{
int32_t ret;
int val = 0;
if (pcmFomat == NULL) {
AUDIO_FUNC_LOGE("fomat is null!");
return HDF_FAILURE;
}
PrintAttributesFromat();
printf("Please select audio format,If not selected, the default is 16bit:");
ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
AUDIO_FUNC_LOGE("CheckInputName failed.");
return HDF_FAILURE;
}
switch (val) {
case AUDIO_FORMAT_PCM_8_BIT:
*pcmFomat = AUDIO_FORMAT_PCM_8_BIT;
break;
case AUDIO_FORMAT_PCM_16_BIT:
*pcmFomat = AUDIO_FORMAT_PCM_16_BIT;
break;
case AUDIO_FORMAT_PCM_24_BIT:
*pcmFomat = AUDIO_FORMAT_PCM_24_BIT;
break;
case AUDIO_FORMAT_PCM_32_BIT:
*pcmFomat = AUDIO_FORMAT_PCM_32_BIT;
break;
default:
*pcmFomat = AUDIO_FORMAT_PCM_16_BIT;
break;
}
return HDF_SUCCESS;
}
static int32_t SetRenderAttributes(struct IAudioRender **render)
{
(void)render;
struct AudioSampleAttributes attrs;
if (g_render == NULL || g_render->GetSampleAttributes == NULL) {
AUDIO_FUNC_LOGE("The pointer is null!");
return HDF_FAILURE;
}
int32_t ret = g_render->GetSampleAttributes((void *)g_render, &attrs);
if (ret < 0) {
AUDIO_FUNC_LOGE("GetRenderAttributes failed!");
} else {
printf("Current sample attributes:\n");
printf("audioType is %u\nfomat is %u\nsampleRate is %u\nchannalCount is"
"%u\nperiod is %u\nframesize is %u\nbigEndian is %u\nSignedData is %u\n",
attrs.type, attrs.format, attrs.sampleRate, attrs.channelCount, attrs.period, attrs.frameSize,
attrs.isBigEndian, attrs.isSignedData);
}
printf("Set Sample Attributes,");
SystemInputFail();
system("clear");
printf("The sample attributes you want to set,Step by step, please.\n");
ret = SelectAttributesFomat((uint32_t *)(&attrs.format));
if (ret < 0) {
AUDIO_FUNC_LOGE("SetRenderAttributes format failed!");
return HDF_FAILURE;
}
printf("\nPlease input sample rate(48000,44100,32000...):");
ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.sampleRate));
if (ret < 0) {
return HDF_FAILURE;
}
printf("\nPlease input bigEndian(false=0/true=1):");
ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.isBigEndian));
if (ret < 0) {
return HDF_FAILURE;
}
if (g_render == NULL || g_render->SetSampleAttributes == NULL) {
AUDIO_FUNC_LOGE("Music already complete,Please replay and set the attrbutes!");
SystemInputFail();
return HDF_FAILURE;
}
ret = g_render->SetSampleAttributes((void *)g_render, &attrs);
if (ret < 0) {
AUDIO_FUNC_LOGE("Set render attributes failed!");
SystemInputFail();
}
return ret;
}
static int32_t SelectRenderScene(struct IAudioRender **render)
{
(void)render;
system("clear");
int32_t ret;
int val = 0;
struct AudioSceneDescriptor scene;
printf(" =================== Select Scene ===================== \n");
printf("0 is Speaker. |\n");
printf("1 is HeadPhones. |\n");
printf(" ====================================================== \n");
printf("Please input your choice:\n");
ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0 || (val != 0 && val != 1)) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
scene.scene.id = 0;
scene.desc.pins = PIN_OUT_HEADSET;
} else {
scene.scene.id = 0;
scene.desc.pins = PIN_OUT_SPEAKER;
}
scene.desc.desc = "mic";
if (g_render == NULL) {
AUDIO_FUNC_LOGE("Music already stop,");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render->SelectScene == NULL) {
return HDF_FAILURE;
}
ret = g_render->SelectScene((void *)g_render, &scene);
if (ret < 0) {
AUDIO_FUNC_LOGE("Select scene fail\n");
}
return ret;
}
static int32_t GetExtParams(struct IAudioRender **render)
{
(void)render;
char keyValueList[BUFFER_LEN] = {0};
int32_t ret;
if (g_render == NULL || g_render->GetExtraParams == NULL) {
return HDF_FAILURE;
}
ret = g_render->GetExtraParams((void *)g_render, keyValueList, EXT_PARAMS_MAXLEN);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get EXT params failed!");
SystemInputFail();
return HDF_FAILURE;
}
printf("keyValueList = %s\n", keyValueList);
return HDF_SUCCESS;
}
static int32_t GetRenderMmapPosition(struct IAudioRender **render)
{
(void)render;
int32_t ret;
if (g_render == NULL || g_render->GetMmapPosition == NULL) {
return HDF_FAILURE;
}
uint64_t frames = 0;
struct AudioTimeStamp time;
time.tvNSec = 0;
time.tvSec = 0;
ret = g_render->GetMmapPosition((void *)g_render, &frames, &time);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get current Mmap frames Position failed!");
SystemInputFail();
return HDF_FAILURE;
}
printf("Now the Position is %" PRIu64 "\n", frames);
return HDF_SUCCESS;
}
static void PrintMenu2(void)
{
printf(" ================== Play Render Menu ================== \n");
printf("| 1. Render Start |\n");
printf("| 2. Render Stop |\n");
printf("| 3. Render Resume |\n");
printf("| 4. Render Pause |\n");
printf("| 5. Render SetVolume |\n");
printf("| 6. Render GetGain |\n");
printf("| 7. Render SetMute |\n");
printf("| 8. Render SetAttributes |\n");
printf("| 9. Render SelectScene |\n");
printf("| 10. Render getEXtParams |\n");
printf("| 11. Render getMmapPosition |\n");
printf("| 12.Exit |\n");
printf(" ====================================================== \n");
}
static struct ProcessRenderMenuSwitchList g_processRenderMenuSwitchList[] = {
{RENDER_START, PlayingAudioFiles},
{RENDER_STOP, StopAudioFiles},
{RENDER_RESUME, SetRenderResume},
{RENDER_PAUSE, SetRenderPause},
{SET_RENDER_VOLUME, SetRenderVolume},
{SET_RENDER_GAIN, GetRenderGain},
{SET_RENDER_MUTE, SetRenderMute},
{SET_RENDER_ATTRIBUTES, SetRenderAttributes},
{SET_RENDER_SLECET_SCENE, SelectRenderScene},
{GET_RENDER_EXT_PARAMS, GetExtParams},
{GET_RENDER_POSITION, GetRenderMmapPosition},
};
static void ProcessMenu(int32_t choice)
{
int32_t i;
if (choice == GET_RENDER_POSITION + 1) {
AUDIO_FUNC_LOGE("Exit from application program!");
return;
}
if (g_render == NULL && choice != 1) {
AUDIO_FUNC_LOGE("This render already release!");
SystemInputFail();
return;
}
for (i = RENDER_START; i <= GET_RENDER_POSITION; ++i) {
if ((choice == (int32_t)g_processRenderMenuSwitchList[i - 1].cmd) &&
(g_processRenderMenuSwitchList[i - 1].operation != NULL)) {
g_processRenderMenuSwitchList[i - 1].operation(&g_render);
}
}
}
static void Choice(void)
{
int32_t choice = 0;
int ret;
while (choice < GET_RENDER_POSITION + 1 && choice >= 0) {
system("clear");
PrintMenu2();
printf("your choice is:\n");
ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
continue;
}
if (choice < RENDER_START || choice > GET_RENDER_POSITION + 1) {
AUDIO_FUNC_LOGE("You input is wrong!");
choice = 0;
SystemInputFail();
continue;
}
ProcessMenu(choice);
}
}
int32_t main(int32_t argc, char const *argv[])
{
if (argc < 2 || argv == NULL || argv[0] == NULL) { // The parameter number is not greater than 2
printf("usage:[1]sample [2]/data/test.wav\n");
return 0;
}
if (argv[1] == NULL || strlen(argv[1]) == 0) {
return HDF_FAILURE;
}
int32_t ret = 0;
ret = strncpy_s(g_path, PATH_LEN - 1, argv[1], strlen(argv[1]) + 1);
if (ret != 0) {
return HDF_FAILURE;
}
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
return HDF_FAILURE;
}
FILE *file = fopen(pathBuf, "rb");
if (file == NULL) {
printf("Failed to open '%s',Please enter the correct file name \n", g_path);
return HDF_FAILURE;
}
(void)fclose(file);
if (InitParam() != HDF_SUCCESS) { // init
AUDIO_FUNC_LOGE("InitParam Fail!");
return HDF_FAILURE;
}
Choice();
if (g_render != NULL && g_adapter != NULL) {
StopAudioFiles(&g_render);
}
if (g_audioManager != NULL && g_audioManager->UnloadAdapter != NULL) {
g_audioManager->UnloadAdapter(g_audioManager, g_adapterName);
g_audioAdapterRelease(g_adapter);
g_adapter = NULL;
g_audioManagerRelease(g_audioManager);
g_audioManager = NULL;
}
dlclose(g_handle);
return 0;
}