1 /*
2 * Copyright 2020 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <stdio.h>
19 #include <errno.h>
20 #include <cstring>
21 #include <cstdlib>
22 #include <unistd.h>
23 #include <pthread.h>
24 #include "rk_defines.h"
25 #include "rk_debug.h"
26 #include "rk_mpi_adec.h"
27 #include "rk_mpi_ao.h"
28 #include "rk_mpi_mb.h"
29 #include "rk_mpi_sys.h"
30
31 #include "test_comm_argparse.h"
32
33 #define USE_AO_MIXER 0
34
35 typedef struct _rkMpiAOCtx {
36 const char *srcFilePath;
37 const char *dstFilePath;
38 RK_S32 s32LoopCount;
39 RK_S32 s32ChnNum;
40 RK_S32 s32SampleRate;
41 RK_S32 s32ReSmpSampleRate;
42 RK_S32 s32Channel;
43 RK_S32 s32DeviceChannel;
44 RK_S32 s32BitWidth;
45 RK_S32 s32DevId;
46 RK_S32 s32PeriodCount;
47 RK_S32 s32PeriodSize;
48 char *chCardName;
49 RK_S32 s32ChnIndex;
50 RK_S32 s32SetVolume;
51 RK_S32 s32SetMute;
52 RK_S32 s32SetFadeRate;
53 RK_S32 s32SetTrackMode;
54 RK_S32 s32GetVolume;
55 RK_S32 s32GetMute;
56 RK_S32 s32GetTrackMode;
57 RK_S32 s32QueryChnStat;
58 RK_S32 s32PauseResumeChn;
59 RK_S32 s32SaveFile;
60 RK_S32 s32QueryFileStat;
61 RK_S32 s32ClrChnBuf;
62 RK_S32 s32ClrPubAttr;
63 RK_S32 s32GetPubAttr;
64 } TEST_AO_CTX_S;
65
query_ao_flow_graph_stat(AUDIO_DEV aoDevId,AO_CHN aoChn)66 void query_ao_flow_graph_stat(AUDIO_DEV aoDevId, AO_CHN aoChn) {
67 RK_S32 ret = 0;
68 AO_CHN_STATE_S pstStat;
69 memset(&pstStat, 0, sizeof(AO_CHN_STATE_S));
70 ret = RK_MPI_AO_QueryChnStat(aoDevId, aoChn, &pstStat);
71 if (ret == RK_SUCCESS) {
72 RK_LOGI("query ao flow status:");
73 RK_LOGI("total number of channel buffer : %d", pstStat.u32ChnTotalNum);
74 RK_LOGI("free number of channel buffer : %d", pstStat.u32ChnFreeNum);
75 RK_LOGI("busy number of channel buffer : %d", pstStat.u32ChnBusyNum);
76 }
77 }
78
find_sound_mode(RK_S32 ch)79 static AUDIO_SOUND_MODE_E find_sound_mode(RK_S32 ch) {
80 AUDIO_SOUND_MODE_E channel = AUDIO_SOUND_MODE_BUTT;
81 switch (ch) {
82 case 1:
83 channel = AUDIO_SOUND_MODE_MONO;
84 break;
85 case 2:
86 channel = AUDIO_SOUND_MODE_STEREO;
87 break;
88 default:
89 RK_LOGE("channel = %d not support", ch);
90 return AUDIO_SOUND_MODE_BUTT;
91 }
92
93 return channel;
94 }
95
find_bit_width(RK_S32 bit)96 static AUDIO_BIT_WIDTH_E find_bit_width(RK_S32 bit) {
97 AUDIO_BIT_WIDTH_E bitWidth = AUDIO_BIT_WIDTH_BUTT;
98 switch (bit) {
99 case 8:
100 bitWidth = AUDIO_BIT_WIDTH_8;
101 break;
102 case 16:
103 bitWidth = AUDIO_BIT_WIDTH_16;
104 break;
105 case 24:
106 bitWidth = AUDIO_BIT_WIDTH_24;
107 break;
108 default:
109 RK_LOGE("bitwidth(%d) not support", bit);
110 return AUDIO_BIT_WIDTH_BUTT;
111 }
112
113 return bitWidth;
114 }
115
test_open_device_ao(TEST_AO_CTX_S * ctx)116 RK_S32 test_open_device_ao(TEST_AO_CTX_S *ctx) {
117 AUDIO_DEV aoDevId = ctx->s32DevId;
118 AUDIO_SOUND_MODE_E soundMode;
119
120 AIO_ATTR_S aoAttr;
121 memset(&aoAttr, 0, sizeof(AIO_ATTR_S));
122
123 if (ctx->chCardName) {
124 snprintf(reinterpret_cast<char *>(aoAttr.u8CardName),
125 sizeof(aoAttr.u8CardName), "%s", ctx->chCardName);
126 }
127
128 aoAttr.soundCard.channels = ctx->s32DeviceChannel;
129 aoAttr.soundCard.sampleRate = ctx->s32SampleRate;
130 aoAttr.soundCard.bitWidth = AUDIO_BIT_WIDTH_16;
131
132 AUDIO_BIT_WIDTH_E bitWidth = find_bit_width(ctx->s32BitWidth);
133 if (bitWidth == AUDIO_BIT_WIDTH_BUTT) {
134 goto __FAILED;
135 }
136 aoAttr.enBitwidth = bitWidth;
137 aoAttr.enSamplerate = (AUDIO_SAMPLE_RATE_E)ctx->s32ReSmpSampleRate;
138 soundMode = find_sound_mode(ctx->s32Channel);
139 if (soundMode == AUDIO_SOUND_MODE_BUTT) {
140 goto __FAILED;
141 }
142 aoAttr.enSoundmode = soundMode;
143 aoAttr.u32FrmNum = ctx->s32PeriodCount;
144 aoAttr.u32PtNumPerFrm = ctx->s32PeriodSize;
145
146 aoAttr.u32EXFlag = 0;
147 aoAttr.u32ChnCnt = 2;
148
149 RK_MPI_AO_SetPubAttr(aoDevId, &aoAttr);
150
151 RK_MPI_AO_Enable(aoDevId);
152
153 return RK_SUCCESS;
154 __FAILED:
155 return RK_FAILURE;
156 }
157
test_init_mpi_ao(TEST_AO_CTX_S * params)158 RK_S32 test_init_mpi_ao(TEST_AO_CTX_S *params) {
159 RK_S32 result;
160
161 result = RK_MPI_AO_EnableChn(params->s32DevId, params->s32ChnIndex);
162 if (result != 0) {
163 RK_LOGE("ao enable channel fail, aoChn = %d, reason = %x", params->s32ChnIndex, result);
164 return RK_FAILURE;
165 }
166
167 // set sample rate of input data
168 result = RK_MPI_AO_EnableReSmp(params->s32DevId, params->s32ChnIndex,
169 (AUDIO_SAMPLE_RATE_E)params->s32ReSmpSampleRate);
170 if (result != 0) {
171 RK_LOGE("ao enable channel fail, reason = %x, aoChn = %d", result, params->s32ChnIndex);
172 return RK_FAILURE;
173 }
174
175 return RK_SUCCESS;
176 }
177
deinit_mpi_ao(AUDIO_DEV aoDevId,AO_CHN aoChn)178 RK_S32 deinit_mpi_ao(AUDIO_DEV aoDevId, AO_CHN aoChn) {
179 RK_S32 result = RK_MPI_AO_DisableReSmp(aoDevId, aoChn);
180 if (result != 0) {
181 RK_LOGE("ao disable resample fail, reason = %d", result);
182 return RK_FAILURE;
183 }
184
185 result = RK_MPI_AO_DisableChn(aoDevId, aoChn);
186 if (result != 0) {
187 RK_LOGE("ao disable channel fail, reason = %d", result);
188 return RK_FAILURE;
189 }
190
191 return RK_SUCCESS;
192 }
193
test_close_device_ao(TEST_AO_CTX_S * ctx)194 RK_S32 test_close_device_ao(TEST_AO_CTX_S *ctx) {
195 AUDIO_DEV aoDevId = ctx->s32DevId;
196 RK_S32 result = RK_MPI_AO_Disable(aoDevId);
197 if (result != 0) {
198 RK_LOGE("ao disable fail, reason = %d", result);
199 return RK_FAILURE;
200 }
201 return RK_SUCCESS;
202 }
203
test_set_ao_channel_mode(AUDIO_DEV aoDevId,AO_CHN aoChn)204 RK_S32 test_set_ao_channel_mode(AUDIO_DEV aoDevId, AO_CHN aoChn) {
205 RK_S32 result = 0;
206 AO_CHN_PARAM_S pstParams;
207 memset(&pstParams, 0, sizeof(AO_CHN_PARAM_S));
208 // for test : aoChn0 output left channel, aoChn1 output right channel,
209 if (aoChn == 0) {
210 pstParams.enMode = AUDIO_CHN_MODE_LEFT;
211 } else if (aoChn == 1) {
212 pstParams.enMode = AUDIO_CHN_MODE_RIGHT;
213 }
214
215 result = RK_MPI_AO_SetChnParams(aoDevId, aoChn, &pstParams);
216 if (result != RK_SUCCESS) {
217 RK_LOGE("ao set channel params, aoChn = %d", aoChn);
218 return RK_FAILURE;
219 }
220
221 return RK_SUCCESS;
222 }
223
sendDataThread(void * ptr)224 void* sendDataThread(void * ptr) {
225 TEST_AO_CTX_S *params = reinterpret_cast<TEST_AO_CTX_S *>(ptr);
226 MB_POOL_CONFIG_S pool_config;
227 // set default value for struct
228 RK_U8 *srcData = RK_NULL;
229 AUDIO_FRAME_S frame;
230 RK_U64 timeStamp = 0;
231 RK_S32 s32MilliSec = -1;
232 RK_S32 size = 0;
233 RK_S32 result = 0;
234 FILE *file = RK_NULL;
235 RK_LOGI("params->s32ChnIndex : %d", params->s32ChnIndex);
236 if (USE_AO_MIXER) {
237 if (params->s32ChnIndex == 0) {
238 file = fopen("8000_1_ao0.pcm", "rb");
239 } else if (params->s32ChnIndex == 1) {
240 file = fopen("8000_1_ao1.pcm", "rb");
241 }
242 } else {
243 file = fopen(params->srcFilePath, "rb");
244 }
245
246 if (file == RK_NULL) {
247 RK_LOGE("open save file %s failed because %s.", params->srcFilePath, strerror(errno));
248 goto __EXIT;
249 }
250
251 srcData = reinterpret_cast<RK_U8 *>(calloc(1024, sizeof(RK_U8)));
252 memset(srcData, 0, 1024);
253 while (1) {
254 size = fread(srcData, 1, 1024, file);
255
256 frame.u32Len = size;
257 frame.u64TimeStamp = timeStamp++;
258 frame.enBitWidth = find_bit_width(params->s32BitWidth);
259 frame.enSoundMode = find_sound_mode(params->s32Channel);
260 frame.bBypassMbBlk = RK_FALSE;
261
262 MB_EXT_CONFIG_S extConfig;
263 memset(&extConfig, 0, sizeof(extConfig));
264 extConfig.pOpaque = srcData;
265 extConfig.pu8VirAddr = srcData;
266 extConfig.u64Size = size;
267 RK_MPI_SYS_CreateMB(&(frame.pMbBlk), &extConfig);
268 __RETRY:
269 result = RK_MPI_AO_SendFrame(params->s32DevId, params->s32ChnIndex, &frame, s32MilliSec);
270 if (result < 0) {
271 RK_LOGE("send frame fail, result = %d, TimeStamp = %lld, s32MilliSec = %d",
272 result, frame.u64TimeStamp, s32MilliSec);
273 goto __RETRY;
274 }
275 RK_MPI_MB_ReleaseMB(frame.pMbBlk);
276
277 if (size <= 0) {
278 RK_LOGI("eof");
279 break;
280 }
281 }
282
283 __EXIT:
284 RK_MPI_AO_WaitEos(params->s32DevId, params->s32ChnIndex, s32MilliSec);
285 if (file) {
286 fclose(file);
287 file = RK_NULL;
288 }
289 free(srcData);
290 return RK_NULL;
291 }
292
commandThread(void * ptr)293 void* commandThread(void * ptr) {
294 TEST_AO_CTX_S *params = reinterpret_cast<TEST_AO_CTX_S *>(ptr);
295
296 {
297 AUDIO_FADE_S aFade;
298 aFade.bFade = RK_FALSE;
299 aFade.enFadeOutRate = (AUDIO_FADE_RATE_E)params->s32SetFadeRate;
300 aFade.enFadeInRate = (AUDIO_FADE_RATE_E)params->s32SetFadeRate;
301 RK_BOOL mute = (params->s32SetMute == 0) ? RK_FALSE : RK_TRUE;
302 RK_LOGI("test info : mute = %d, volume = %d", mute, params->s32SetVolume);
303 RK_MPI_AO_SetMute(params->s32DevId, mute, &aFade);
304 RK_MPI_AO_SetVolume(params->s32DevId, params->s32SetVolume);
305 }
306
307 if (params->s32SetTrackMode) {
308 RK_LOGI("test info : set track mode = %d", params->s32SetTrackMode);
309 RK_MPI_AO_SetTrackMode(params->s32DevId, (AUDIO_TRACK_MODE_E)params->s32SetTrackMode);
310 params->s32SetTrackMode = 0;
311 }
312
313 if (params->s32GetVolume) {
314 RK_S32 volume = 0;
315 RK_MPI_AO_GetVolume(params->s32DevId, &volume);
316 RK_LOGI("test info : get volume = %d", volume);
317 params->s32GetVolume = 0;
318 }
319
320 if (params->s32GetMute) {
321 RK_BOOL mute = RK_FALSE;
322 AUDIO_FADE_S fade;
323 RK_MPI_AO_GetMute(params->s32DevId, &mute, &fade);
324 RK_LOGI("test info : is mute = %d", mute);
325 params->s32GetMute = 0;
326 }
327
328 if (params->s32GetTrackMode) {
329 AUDIO_TRACK_MODE_E trackMode;
330 RK_MPI_AO_GetTrackMode(params->s32DevId, &trackMode);
331 RK_LOGI("test info : get track mode = %d", trackMode);
332 params->s32GetTrackMode = 0;
333 }
334
335 if (params->s32QueryChnStat) {
336 query_ao_flow_graph_stat(params->s32DevId, params->s32ChnIndex);
337 params->s32QueryChnStat = 0;
338 }
339
340 if (params->s32SaveFile) {
341 AUDIO_SAVE_FILE_INFO_S saveFile;
342 memset(&saveFile, 0, sizeof(AUDIO_SAVE_FILE_INFO_S));
343 if (params->dstFilePath) {
344 saveFile.bCfg = RK_TRUE;
345 saveFile.u32FileSize = 1024 * 1024;
346 snprintf(saveFile.aFileName, sizeof(saveFile.aFileName), "%s", "ao_save_file.bin");
347 snprintf(saveFile.aFilePath, sizeof(saveFile.aFilePath), "%s", params->dstFilePath);
348 }
349 RK_MPI_AO_SaveFile(params->s32DevId, params->s32ChnIndex, &saveFile);
350 params->s32SaveFile = 0;
351 }
352
353 if (params->s32QueryFileStat) {
354 AUDIO_FILE_STATUS_S fileStat;
355 RK_MPI_AO_QueryFileStatus(params->s32DevId, params->s32ChnIndex, &fileStat);
356 RK_LOGI("test info : query save file status = %d", fileStat.bSaving);
357 params->s32QueryFileStat = 0;
358 }
359
360 if (params->s32PauseResumeChn) {
361 usleep(500 * 1000);
362 RK_MPI_AO_PauseChn(params->s32DevId, params->s32ChnIndex);
363 RK_LOGI("pause test");
364 usleep(1000 * 1000);
365 RK_MPI_AO_ResumeChn(params->s32DevId, params->s32ChnIndex);
366 RK_LOGI("resume test");
367 params->s32PauseResumeChn = 0;
368 }
369
370 if (params->s32ClrChnBuf) {
371 RK_MPI_AO_ClearChnBuf(params->s32DevId, params->s32ChnIndex);
372 params->s32ClrChnBuf = 0;
373 }
374
375 if (params->s32ClrPubAttr) {
376 RK_MPI_AO_ClrPubAttr(params->s32DevId);
377 params->s32ClrPubAttr = 0;
378 }
379
380 if (params->s32GetPubAttr) {
381 AIO_ATTR_S pstAttr;
382 RK_MPI_AO_GetPubAttr(params->s32DevId, &pstAttr);
383 RK_LOGI("input stream rate = %d", pstAttr.enSamplerate);
384 RK_LOGI("input stream sound mode = %d", pstAttr.enSoundmode);
385 RK_LOGI("open sound card rate = %d", pstAttr.soundCard.sampleRate);
386 RK_LOGI("open sound card channel = %d", pstAttr.soundCard.channels);
387 params->s32GetPubAttr = 0;
388 }
389
390 return RK_NULL;
391 }
392
unit_test_mpi_ao(TEST_AO_CTX_S * ctx)393 RK_S32 unit_test_mpi_ao(TEST_AO_CTX_S *ctx) {
394 RK_S32 i = 0;
395 TEST_AO_CTX_S params[AO_MAX_CHN_NUM];
396 pthread_t tidSend[AO_MAX_CHN_NUM];
397 pthread_t tidReceive[AO_MAX_CHN_NUM];
398
399 if (ctx->s32ChnNum > AO_MAX_CHN_NUM) {
400 RK_LOGE("ao chn(%d) > max_chn(%d)", ctx->s32ChnNum, AO_MAX_CHN_NUM);
401 goto __FAILED;
402 }
403
404 if (test_open_device_ao(ctx) != RK_SUCCESS) {
405 goto __FAILED;
406 }
407
408 for (i = 0; i < ctx->s32ChnNum; i++) {
409 memcpy(&(params[i]), ctx, sizeof(TEST_AO_CTX_S));
410 params[i].s32ChnIndex = i;
411
412 if (USE_AO_MIXER) {
413 test_set_ao_channel_mode(params[i].s32DevId, params[i].s32ChnIndex);
414 }
415
416 test_init_mpi_ao(¶ms[i]);
417 pthread_create(&tidSend[i], RK_NULL, sendDataThread, reinterpret_cast<void *>(¶ms[i]));
418 pthread_create(&tidReceive[i], RK_NULL, commandThread, reinterpret_cast<void *>(¶ms[i]));
419 }
420
421 for (i = 0; i < ctx->s32ChnNum; i++) {
422 pthread_join(tidSend[i], RK_NULL);
423 pthread_join(tidReceive[i], RK_NULL);
424 deinit_mpi_ao(params[i].s32DevId, params[i].s32ChnIndex);
425 }
426
427 test_close_device_ao(ctx);
428
429 return RK_SUCCESS;
430 __FAILED:
431
432 return RK_FAILURE;
433 }
434
435 static const char *const usages[] = {
436 "./rk_mpi_ao_test [-i src_path] [--device_rate rate] [--device_ch ch] [--input_rate rate] [--input_ch ch]...",
437 NULL,
438 };
439
mpi_ao_test_show_options(const TEST_AO_CTX_S * ctx)440 static void mpi_ao_test_show_options(const TEST_AO_CTX_S *ctx) {
441 RK_PRINT("cmd parse result:\n");
442 RK_PRINT("input file name : %s\n", ctx->srcFilePath);
443 RK_PRINT("output file name : %s\n", ctx->dstFilePath);
444 RK_PRINT("loop count : %d\n", ctx->s32LoopCount);
445 RK_PRINT("channel number : %d\n", ctx->s32ChnNum);
446 RK_PRINT("open sound rate : %d\n", ctx->s32SampleRate);
447 RK_PRINT("open sound channel : %d\n", ctx->s32DeviceChannel);
448 RK_PRINT("input stream rate : %d\n", ctx->s32ReSmpSampleRate);
449 RK_PRINT("input channel : %d\n", ctx->s32Channel);
450 RK_PRINT("bit_width : %d\n", ctx->s32BitWidth);
451 RK_PRINT("period_count : %d\n", ctx->s32PeriodCount);
452 RK_PRINT("period_size : %d\n", ctx->s32PeriodSize);
453 RK_PRINT("sound card name : %s\n", ctx->chCardName);
454 RK_PRINT("device id : %d\n", ctx->s32DevId);
455 RK_PRINT("set volume : %d\n", ctx->s32SetVolume);
456 RK_PRINT("set mute : %d\n", ctx->s32SetMute);
457 RK_PRINT("set track_mode : %d\n", ctx->s32SetTrackMode);
458 RK_PRINT("get volume : %d\n", ctx->s32GetVolume);
459 RK_PRINT("get mute : %d\n", ctx->s32GetMute);
460 RK_PRINT("get track_mode : %d\n", ctx->s32GetTrackMode);
461 RK_PRINT("query stat : %d\n", ctx->s32QueryChnStat);
462 RK_PRINT("pause and resume chn : %d\n", ctx->s32PauseResumeChn);
463 RK_PRINT("save file : %d\n", ctx->s32SaveFile);
464 RK_PRINT("query save file stat : %d\n", ctx->s32QueryFileStat);
465 RK_PRINT("clear buf : %d\n", ctx->s32ClrChnBuf);
466 RK_PRINT("get attribute : %d\n", ctx->s32GetPubAttr);
467 RK_PRINT("clear attribute : %d\n", ctx->s32ClrPubAttr);
468 }
469
main(int argc,const char ** argv)470 int main(int argc, const char **argv) {
471 RK_S32 i;
472 RK_S32 s32Ret;
473 TEST_AO_CTX_S *ctx;
474
475 ctx = reinterpret_cast<TEST_AO_CTX_S *>(malloc(sizeof(TEST_AO_CTX_S)));
476 memset(ctx, 0, sizeof(TEST_AO_CTX_S));
477
478 ctx->srcFilePath = RK_NULL;
479 ctx->dstFilePath = RK_NULL;
480 ctx->s32LoopCount = 1;
481 ctx->s32ChnNum = 1;
482 ctx->s32SampleRate = 48000;
483 ctx->s32ReSmpSampleRate = 0;
484 ctx->s32DeviceChannel = 2;
485 ctx->s32Channel = 0;
486 ctx->s32BitWidth = 16;
487 ctx->s32PeriodCount = 4;
488 ctx->s32PeriodSize = 1024;
489 ctx->chCardName = RK_NULL;
490 ctx->s32DevId = 0;
491 ctx->s32SetVolume = 100;
492 ctx->s32SetMute = 0;
493 ctx->s32SetTrackMode = 0;
494 ctx->s32SetFadeRate = 0;
495 ctx->s32GetVolume = 0;
496 ctx->s32GetMute = 0;
497 ctx->s32GetTrackMode = 0;
498 ctx->s32QueryChnStat = 0;
499 ctx->s32PauseResumeChn = 0;
500 ctx->s32SaveFile = 0;
501 ctx->s32QueryFileStat = 0;
502 ctx->s32ClrChnBuf = 0;
503 ctx->s32ClrPubAttr = 0;
504 ctx->s32GetPubAttr = 0;
505
506 struct argparse_option options[] = {
507 OPT_HELP(),
508 OPT_GROUP("basic options:"),
509 OPT_STRING('i', "input", &(ctx->srcFilePath),
510 "input file name , e.g.(./*.pcm). <required>", NULL, 0, 0),
511 OPT_INTEGER('\0', "input_ch", &(ctx->s32Channel),
512 "the sample rate of input data. <required>", NULL, 0, 0),
513 OPT_INTEGER('\0', "input_rate", &(ctx->s32ReSmpSampleRate),
514 "the sample rate of input data. <required>", NULL, 0, 0),
515 OPT_INTEGER('\0', "device_ch", &(ctx->s32DeviceChannel),
516 "the number of sound card channels. default(2).", NULL, 0, 0),
517 OPT_INTEGER('\0', "device_rate", &(ctx->s32SampleRate),
518 "the sample rate of open sound card. default(48000).", NULL, 0, 0),
519 OPT_STRING('o', "output", &(ctx->dstFilePath),
520 "output file name, e.g.(./ao). default(NULL).", NULL, 0, 0),
521 OPT_INTEGER('n', "loop_count", &(ctx->s32LoopCount),
522 "loop running count. can be any count. default(1)", NULL, 0, 0),
523 OPT_INTEGER('c', "channel_count", &(ctx->s32ChnNum),
524 "the count of ao channel. default(1).", NULL, 0, 0),
525 OPT_INTEGER('\0', "bit", &(ctx->s32BitWidth),
526 "the bit width of open sound card, range(8, 16, 24), default(16)", NULL, 0, 0),
527 OPT_INTEGER('\0', "period_size", &(ctx->s32PeriodSize),
528 "the period size for open sound card, default(1024)", NULL, 0, 0),
529 OPT_INTEGER('\0', "period_count", &(ctx->s32PeriodCount),
530 "the period count for open sound card, default(4)", NULL, 0, 0),
531 OPT_STRING('\0', "sound_card_name", &(ctx->chCardName),
532 "the sound name for open sound card, default(NULL)", NULL, 0, 0),
533 OPT_INTEGER('\0', "set_volume", &(ctx->s32SetVolume),
534 "set volume test, range(0, 100), default(100)", NULL, 0, 0),
535 OPT_INTEGER('\0', "set_mute", &(ctx->s32SetMute),
536 "set mute test, range(0, 1), default(0)", NULL, 0, 0),
537 OPT_INTEGER('\0', "set_fade", &(ctx->s32SetFadeRate),
538 "set fade rate, range(0, 7), default(0)", NULL, 0, 0),
539 OPT_INTEGER('\0', "set_track_mode", &(ctx->s32SetTrackMode),
540 "set track mode test, range(0:normal, 1:both_left, 2:both_right, 3:exchange, 4:mix,"
541 "5:left_mute, 6:right_mute, 7:both_mute), default(0)", NULL, 0, 0),
542 OPT_INTEGER('\0', "get_volume", &(ctx->s32GetVolume),
543 "get volume test, range(0, 1), default(0)", NULL, 0, 0),
544 OPT_INTEGER('\0', "get_mute", &(ctx->s32GetMute),
545 "get mute test, range(0, 1), default(0)", NULL, 0, 0),
546 OPT_INTEGER('\0', "get_track_mode", &(ctx->s32GetTrackMode),
547 "get track mode test, range(0, 1), default(0)", NULL, 0, 0),
548 OPT_INTEGER('\0', "query_stat", &(ctx->s32QueryChnStat),
549 "query ao statistics info, range(0, 1), default(0)", NULL, 0, 0),
550 OPT_INTEGER('\0', "pause_resume", &(ctx->s32PauseResumeChn),
551 "test ao chn pause and resume function, range(0, 1), default(0)", NULL, 0, 0),
552 OPT_INTEGER('\0', "save_file", &(ctx->s32SaveFile),
553 "test ao save file, if enabled, must set output file, range(0, 1), default(0)", NULL, 0, 0),
554 OPT_INTEGER('\0', "query_file_stat", &(ctx->s32QueryFileStat),
555 "query file status, range(0, 1), default(0)", NULL, 0, 0),
556 OPT_INTEGER('\0', "clr_buf", &(ctx->s32ClrChnBuf),
557 "clear buffer of channel, range(0, 1), default(0)", NULL, 0, 0),
558 OPT_INTEGER('\0', "clr_attr", &(ctx->s32ClrPubAttr),
559 "clear attribute of channel, range(0, 1), default(0)", NULL, 0, 0),
560 OPT_INTEGER('\0', "get_attr", &(ctx->s32GetPubAttr),
561 "get attribute of device, range(0, 1), default(0)", NULL, 0, 0),
562 OPT_END(),
563 };
564
565 struct argparse argparse;
566 argparse_init(&argparse, options, usages, 0);
567 argparse_describe(&argparse, "\nselect a test case to run.",
568 "\nuse --help for details.");
569
570 argc = argparse_parse(&argparse, argc, argv);
571 mpi_ao_test_show_options(ctx);
572
573 if (ctx->srcFilePath == RK_NULL
574 || ctx->s32Channel <= 0
575 || ctx->s32ReSmpSampleRate <= 0) {
576 argparse_usage(&argparse);
577 goto __FAILED;
578 }
579
580 RK_MPI_SYS_Init();
581
582 for (i = 0; i < ctx->s32LoopCount; i++) {
583 RK_LOGI("start running loop count = %d", i);
584 s32Ret = unit_test_mpi_ao(ctx);
585 if (s32Ret != RK_SUCCESS) {
586 goto __FAILED;
587 }
588 RK_LOGI("end running loop count = %d", i);
589 }
590
591 __FAILED:
592 if (ctx) {
593 free(ctx);
594 ctx = RK_NULL;
595 }
596
597 RK_MPI_SYS_Exit();
598 return 0;
599 }
600