diff --git a/audio/test/sample/idl_render.c b/audio/test/sample/idl_render.c index 167fd3474209bb9dfa35360adf79ee44b30b2ada..734b44cbaafd82b4754ead65657f5f58ba674867 100644 --- a/audio/test/sample/idl_render.c +++ b/audio/test/sample/idl_render.c @@ -40,6 +40,8 @@ #define INT_32_MAX 0x7fffffff #define EXT_PARAMS_MAXLEN 107 #define BITS_TO_FROMAT 3 +#define AUDIO_NORMOL_PALY 1 +#define AUDIO_MMAP_PLAY 2 struct StrPara { struct IAudioRender *render; @@ -50,6 +52,9 @@ struct StrPara { int32_t bufferSize; }; +/** + * @brief Globle param area. + */ struct IAudioRender *g_render = NULL; struct IAudioAdapter *g_adapter = NULL; static struct IAudioManager *g_audioManager = NULL; @@ -71,6 +76,16 @@ pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t g_functionCond = PTHREAD_COND_INITIALIZER; bool g_waitSleep = false; bool g_isDirect = true; +int32_t g_palyModeFlag; +uint32_t g_mmapFrameSizeInByte; +int32_t g_dupedMmapFd; +int32_t g_totalFrameSize; +int32_t g_totalBufferSize; +int32_t g_burstFrameSize; +char *g_dupedMmapAddress = NULL; +uint32_t g_currWritePos = 0; +int32_t g_mmapReadPos = 0; +int32_t g_alreadyReadFrame = 0; enum RenderMenuId { RENDER_START = 1, @@ -250,70 +265,197 @@ static int32_t StopAudioFiles(struct IAudioRender **renderS) return ret; } -static int32_t FrameStartMmap(const struct StrPara *param) +static int32_t ReqMmapDupAddress(const struct StrPara *param) { if (param == NULL) { return HDF_FAILURE; } + const struct StrPara *strParam = param; struct IAudioRender *render = strParam->render; - struct AudioMmapBufferDescriptor mmapDesc; + if (render == NULL || render->ReqMmapBuffer == NULL) { + return HDF_FAILURE; + } + int32_t ret = HDF_SUCCESS; + int32_t totalBufferInMs = 50; // 5 * (6 + 2 * (2)) = 50ms, the buffer size, not latency. + g_mmapFrameSizeInByte = (g_attrs.channelCount) * (PcmFormatToBits(g_attrs.format) >> BITS_TO_FROMAT); + int32_t reqSize = totalBufferInMs * (g_attrs.sampleRate / 1000); + struct AudioMmapBufferDescriptor mmapDesc = {0}; - (void)signal(SIGINT, StreamClose); + ret = render->ReqMmapBuffer(render, reqSize, &mmapDesc); + if (ret < 0 || reqSize <= 0) { + printf("Request map fail,please check.\n"); + return HDF_FAILURE; + } - // get file length - char pathBuf[PATH_MAX] = {'\0'}; - if (realpath(g_path, pathBuf) == NULL) { + int32_t periodFrameMaxSize = 1920000; // 192khz * 10s + if (mmapDesc.totalBufferFrames < 0 || mmapDesc.transferFrameSize < 0 || mmapDesc.transferFrameSize > periodFrameMaxSize) { return HDF_FAILURE; } - // get fileSize - FILE *fp = fopen(pathBuf, "rb+"); - if (fp == NULL) { - printf("Open file failed!\n"); + g_dupedMmapFd = dup(mmapDesc.memoryFd); // fcntl(fd, 1030,3) after dup? + g_totalFrameSize = mmapDesc.totalBufferFrames; // 1440 ~ 3840 + g_burstFrameSize = mmapDesc.transferFrameSize; // 240 + + if (g_mmapFrameSizeInByte > ULLONG_MAX / g_totalFrameSize) { + return HDF_FAILURE; + } + + g_totalBufferSize = g_totalFrameSize * g_mmapFrameSizeInByte; + g_dupedMmapAddress = (char *)mmap(NULL, g_totalBufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_dupedMmapFd, 0); + if (g_dupedMmapAddress == NULL) { + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t GetMmapPositionByFrame(uint64_t frames, const struct StrPara *param) +{ + if (param == NULL) { + return HDF_FAILURE; + } + const struct StrPara *strParam = param; + struct IAudioRender *render = strParam->render; + if (render == NULL || render->GetMmapPosition == NULL) { return HDF_FAILURE; } - int32_t ret = fseek(fp, 0, SEEK_END); + struct AudioTimeStamp timestamp = {}; + int32_t ret = render->GetMmapPosition(render, &frames, ×tamp); if (ret != 0) { - fclose(fp); return HDF_FAILURE; } - int32_t reqSize = (int32_t)ftell(fp); - if (reqSize < 0) { - fclose(fp); + g_alreadyReadFrame = frames; // frames already read. + g_mmapReadPos = g_mmapFrameSizeInByte * (frames - g_totalFrameSize * (frames / g_totalFrameSize)); + if (g_mmapReadPos >= 0 && g_mmapReadPos < g_totalBufferSize) { 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) { - free(mmapDesc.filePath); + return HDF_SUCCESS; +} + +static void ReleaseMmapBuffer() +{ + if (g_dupedMmapAddress != NULL) { + munmap(g_dupedMmapAddress, g_totalBufferSize); + g_dupedMmapAddress = NULL; + g_totalBufferSize = 0; + } +} + +static void PreparePositionOffset() +{ + int32_t periodByteSize = g_burstFrameSize * g_mmapFrameSizeInByte; + if ((uint64_t)(periodByteSize * 1) > ULLONG_MAX - g_mmapReadPos) { + return; + } + int32_t tempPos = g_mmapReadPos + periodByteSize * 1; // 1 period ahead + g_currWritePos = (tempPos < g_totalBufferSize ? tempPos : tempPos - g_totalBufferSize); +} + +static int32_t RenderMmapFrame(int8_t *frame, uint32_t frameLen, uint32_t* replyLen) +{ + if (frame == NULL || replyLen == NULL) { + *replyLen = 0; + return HDF_FAILURE; + } + if (frameLen > (g_totalBufferSize - g_burstFrameSize * g_mmapFrameSizeInByte)) { + printf("large then the remained buffer size"); + *replyLen = 0; return HDF_FAILURE; } - ret = render->ReqMmapBuffer(render, reqSize, &mmapDesc); - if (ret < 0 || reqSize <= 0) { - free(mmapDesc.filePath); - printf("Request map fail,please check.\n"); + char *writePtr = g_dupedMmapAddress + g_currWritePos; + uint32_t tempPos = g_currWritePos + frameLen; + if (tempPos <= g_totalBufferSize) { + if (memcpy_s(writePtr, (g_totalBufferSize - g_currWritePos), frame, frameLen)) { + printf("copy failed"); + return HDF_FAILURE; + } + g_currWritePos = (tempPos == g_totalBufferSize ? 0 : tempPos); + *replyLen = frameLen; + } else { + size_t writeableSize = g_totalBufferSize - g_currWritePos; + if (memcpy_s(writePtr, writeableSize, frame, writeableSize) || + memcpy_s(g_dupedMmapAddress, g_totalBufferSize, (void *)(frame + writeableSize), + (frameLen - writeableSize))) { + printf("copy failed"); + return HDF_FAILURE; + } + g_currWritePos = frameLen - writeableSize; + *replyLen = g_currWritePos; + } + + return HDF_SUCCESS; +} + +static int32_t DoMmapPlay() +{ + if (g_file == NULL) { return HDF_FAILURE; } + size_t perReadSize; + size_t mmapFrameSize = 0; + size_t remainingDataSize = g_wavHeadInfo.riffSize; - if (g_render != NULL) { - ret = StopAudioFiles(&render); - if (ret < 0) { - free(mmapDesc.filePath); - AUDIO_FUNC_LOGE("StopAudioFiles File!"); + if ((uint64_t)(g_burstFrameSize) > ULLONG_MAX / g_mmapFrameSizeInByte) { + return HDF_FAILURE; + } + mmapFrameSize = g_burstFrameSize*g_mmapFrameSizeInByte; + char *frame = (char *)OsalMemCalloc(mmapFrameSize); + + do { + uint32_t replyBytes = 0; + size_t readSize = (remainingDataSize > mmapFrameSize) ? (size_t)mmapFrameSize : remainingDataSize; + perReadSize = fread(frame, 1, readSize, g_file); + if (perReadSize > 0) { + int32_t ret = RenderMmapFrame((int8_t *)frame, perReadSize, &replyBytes); + if (ret == HDF_ERR_INVALID_OBJECT) { + AUDIO_FUNC_LOGE("Render already stop!"); + break; + } + remainingDataSize -= perReadSize; + } + + while (g_waitSleep) { + printf("music pause now.\n"); + pthread_cond_wait(&g_functionCond, &g_mutex); + printf("music resume now.\n"); } + } while (!g_closeEnd && perReadSize > 0 && remainingDataSize > 0); + + if (!g_closeEnd) { + printf("\nPlay complete, please select input again\n"); + (void)StopAudioFiles(&g_render); + } + return HDF_SUCCESS; +} + + +static int32_t FrameStartMmap(const struct StrPara *param) +{ + if (param == NULL) { + return HDF_FAILURE; + } + uint64_t firstFrames = 0; + (void)signal(SIGINT, StreamClose); + + if (ReqMmapDupAddress(param) != HDF_SUCCESS) { + printf("requst mmap buffer failed"); + return HDF_FAILURE; + } + + if (GetMmapPositionByFrame(firstFrames, param) != HDF_SUCCESS) { + printf("requst mmap buffer failed"); + return HDF_FAILURE; } - free(mmapDesc.filePath); + + PreparePositionOffset(); + printf("burstSize=%d\t, totolFrame=%d, sizeInbyte=%d", g_burstFrameSize, g_totalBufferSize, g_mmapFrameSizeInByte); + DoMmapPlay(); + + ReleaseMmapBuffer(); return HDF_SUCCESS; } @@ -416,8 +558,6 @@ static int32_t SelectPlayMode(int32_t *palyModeFlag) int choice = 0; - system("clear"); - PrintPlayMode(); printf("Please enter your choice:"); @@ -438,13 +578,13 @@ static int32_t StartPlayThread(int32_t palyModeFlag) pthread_attr_init(&tidsAttr); pthread_attr_setdetachstate(&tidsAttr, PTHREAD_CREATE_DETACHED); switch (palyModeFlag) { - case 1: // 1. Stander Loading + case AUDIO_NORMOL_PALY: // 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 + case AUDIO_MMAP_PLAY: // 2. Low latency Loading if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStartMmap), &g_str) != 0) { AUDIO_FUNC_LOGE("Create Thread Fail"); return HDF_FAILURE; @@ -492,7 +632,7 @@ static int32_t PlayingAudioInitFile(void) return HDF_SUCCESS; } -static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp) +static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp, int32_t palyModeFlag) { if (renderTemp == NULL) { AUDIO_FUNC_LOGE("render is null"); @@ -502,6 +642,12 @@ static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp) if (g_adapter == NULL || g_adapter->CreateRender == NULL) { return HDF_FAILURE; } + + if (palyModeFlag == AUDIO_MMAP_PLAY) { + // set mmap type + g_attrs.type = AUDIO_MMAP_NOIRQ; + } + int32_t ret = g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &render, &g_renderId); if (render == NULL || ret < 0 || render->RenderFrame == NULL) { AUDIO_FUNC_LOGE("AudioDeviceCreateRender failed or RenderFrame is null"); @@ -516,6 +662,10 @@ static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp) return HDF_FAILURE; } + if (palyModeFlag == AUDIO_MMAP_PLAY) { + render->SetVolume(render, 0.8); + } + if (InitPlayingAudioParam(render) < 0) { g_adapter->DestroyRender(g_adapter, g_renderId); IAudioRenderRelease(render, g_isDirect); @@ -536,21 +686,14 @@ static int32_t PlayingAudioFiles(struct IAudioRender **renderS) 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) { + if (PlayingAudioInitRender(&render, g_palyModeFlag) < 0) { AUDIO_FUNC_LOGE("PlayingAudioInitRender fail"); FileClose(&g_file); return HDF_FAILURE; } - if (StartPlayThread(palyModeFlag) < 0) { + if (StartPlayThread(g_palyModeFlag) < 0) { FileClose(&g_file); if (g_adapter != NULL && g_adapter->DestroyRender != NULL) { g_adapter->DestroyRender(g_adapter, g_renderId); @@ -741,6 +884,12 @@ static int32_t InitParam(void) } return HDF_FAILURE; } + + if (SelectPlayMode(&g_palyModeFlag) != HDF_SUCCESS) { + AUDIO_FUNC_LOGE("SelectPlayMode Fail"); + return HDF_FAILURE; + } + return HDF_SUCCESS; }