xref: /OK3568_Linux_fs/external/rockit/mpi/example/mod/test_mpi_adec.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 #include <cstdio>
18 #include <cerrno>
19 #include <cstring>
20 #include <cstdlib>
21 #include <unistd.h>
22 #include <pthread.h>
23 #include "rk_debug.h"
24 #include "rk_mpi_adec.h"
25 #include "rk_mpi_mb.h"
26 #include "rk_mpi_sys.h"
27 #include "test_comm_argparse.h"
28 
29 typedef struct _rkMpiADECCtx {
30     const char *srcFilePath;
31     const char *dstFilePath;
32     RK_S32      s32LoopCount;
33     RK_S32      s32ChnNum;
34     RK_S32      s32SampleRate;
35     RK_S32      s32Channel;
36     char       *chCodecId;
37     RK_S32      s32DecMode;
38     RK_BOOL     bBlock;
39     RK_S32      s32ChnIndex;
40     RK_S32      s32QueryStat;
41     RK_S32      s32ClrChnBuf;
42 } TEST_ADEC_CTX_S;
43 
query_adec_flow_graph_stat(ADEC_CHN AdChn)44 void query_adec_flow_graph_stat(ADEC_CHN AdChn) {
45     RK_S32 ret = 0;
46     ADEC_CHN_STATE_S pstStat;
47     memset(&pstStat, 0, sizeof(ADEC_CHN_STATE_S));
48     ret = RK_MPI_ADEC_QueryChnStat(AdChn, &pstStat);
49     if (ret == RK_SUCCESS) {
50         RK_LOGI("query adec flow status:");
51         RK_LOGI("EOS flag : %d", pstStat.bEndOfStream);
52         RK_LOGI("total number of channel buffer : %d", pstStat.u32BufferFrmNum);
53         RK_LOGI("free number of channel buffer : %d", pstStat.u32BufferFreeNum);
54         RK_LOGI("busy number of channel buffer : %d", pstStat.u32BufferBusyNum);
55     }
56 }
57 
adec_data_free(void * opaque)58 static RK_S32 adec_data_free(void *opaque) {
59     if (opaque) {
60         free(opaque);
61         opaque = RK_NULL;
62     }
63 
64     return 0;
65 }
66 
test_find_audio_codec_id(TEST_ADEC_CTX_S * params)67 static RK_U32 test_find_audio_codec_id(TEST_ADEC_CTX_S *params) {
68     if (params == RK_NULL)
69         return -1;
70 
71     char *format = params->chCodecId;
72     if (strstr(format, "mp2")) {
73         return RK_AUDIO_ID_MP2;
74     } else if (strstr(format, "g726")) {
75         return RK_AUDIO_ID_ADPCM_G726;
76     } else if (strstr(format, "g711a")) {
77         return RK_AUDIO_ID_PCM_ALAW;
78     } else if (strstr(format, "g711u")) {
79         return RK_AUDIO_ID_PCM_MULAW;
80     }
81 
82     if (params->s32DecMode == ADEC_MODE_STREAM) {
83         RK_LOGE("test not find codec id : %s", params->chCodecId);
84         return RK_AUDIO_ID_Unused;
85     } else {
86         // if set packet mode, try to get codecId, channels, samplerate
87         return RK_AUDIO_ID_AutoDetect;
88     }
89 }
90 
test_init_mpi_adec(TEST_ADEC_CTX_S * params)91 RK_S32 test_init_mpi_adec(TEST_ADEC_CTX_S *params) {
92     RK_S32 i = 0;
93     RK_S32 s32ret = 0;
94     ADEC_CHN_ATTR_S stAdecAttr;
95     ADEC_CHN AdChn = (ADEC_CHN)(params->s32ChnIndex);
96     memset(&stAdecAttr, 0, sizeof(ADEC_CHN_ATTR_S));
97 
98     if (stAdecAttr.stCodecAttr.u32Channels == 0) {
99         stAdecAttr.stCodecAttr.u32Channels = params->s32Channel;
100         stAdecAttr.stCodecAttr.u32SampleRate = params->s32SampleRate;
101     }
102 
103     RK_U32 codecId = test_find_audio_codec_id(params);
104     if (codecId == RK_AUDIO_ID_Unused) {
105         return RK_FAILURE;
106     }
107 
108     stAdecAttr.enType = (RK_CODEC_ID_E)codecId;
109     stAdecAttr.enMode = (ADEC_MODE_E)params->s32DecMode;
110     stAdecAttr.u32BufCount = 4;
111 
112     s32ret = RK_MPI_ADEC_CreateChn(AdChn, &stAdecAttr);
113     if (s32ret) {
114         RK_LOGE("create adec chn %d err:0x%x\n", AdChn, s32ret);
115         return RK_FAILURE;
116     }
117 
118     return RK_SUCCESS;
119 }
120 
test_deinit_mpi_adec(TEST_ADEC_CTX_S * ctx)121 RK_S32 test_deinit_mpi_adec(TEST_ADEC_CTX_S *ctx) {
122     RK_MPI_ADEC_DestroyChn(ctx->s32ChnIndex);
123     return RK_SUCCESS;
124 }
125 
send_stream_thread(void * arg)126 static void *send_stream_thread(void *arg) {
127     RK_S32 s32ret = 0;
128     TEST_ADEC_CTX_S *params = reinterpret_cast<TEST_ADEC_CTX_S *>(arg);
129     RK_U8 *srcData = RK_NULL;
130     RK_S32 srcSize = 0;
131     FILE  *file = RK_NULL;
132     RK_S32 err = 0;
133     RK_S32 pktEos = 0;
134     AUDIO_STREAM_S stAudioStream;
135     RK_BOOL bBlock = params->bBlock;
136     ADEC_CHN AdChn = (ADEC_CHN)(params->s32ChnIndex);
137     RK_U64 timeStamp = 0;
138     RK_S32 count = 0;
139     RK_S64 dataOffset = 0;
140 
141     file = fopen(params->srcFilePath, "rb");
142     if (file == RK_NULL) {
143         RK_LOGE("failed to open input file(%s), error: %s", params->srcFilePath, strerror(errno));
144         goto __FAILED;
145     }
146 
147     while (1) {
148         srcData = reinterpret_cast<RK_U8 *>(calloc(1024, sizeof(RK_U8)));
149         memset(srcData, 0, 1024);
150 
151         srcSize = fread(srcData, 1, 1024, file);
152 
153         if (srcSize == 0 || srcData == RK_NULL) {
154             RK_LOGI("read eos packet, now send eos packet!");
155             pktEos = 1;
156         }
157 
158         if (pktEos) {
159             RK_MPI_ADEC_SendEndOfStream(AdChn, RK_FALSE);
160             break;
161         } else {
162             stAudioStream.u32Len = srcSize;
163             stAudioStream.u64TimeStamp = timeStamp;
164             stAudioStream.u32Seq = ++count;
165             stAudioStream.bBypassMbBlk = RK_TRUE;
166             MB_EXT_CONFIG_S extConfig = {0};
167             extConfig.pFreeCB = adec_data_free;
168             extConfig.pOpaque = srcData;
169             extConfig.pu8VirAddr = srcData;
170             extConfig.u64Size    = srcSize;
171             RK_MPI_SYS_CreateMB(&(stAudioStream.pMbBlk), &extConfig);
172 __RETRY:
173             s32ret = RK_MPI_ADEC_SendStream(AdChn, &stAudioStream, bBlock);
174             if (s32ret != RK_SUCCESS) {
175                 RK_LOGE("fail to send adec stream.");
176                 goto __RETRY;
177             }
178             RK_MPI_MB_ReleaseMB(stAudioStream.pMbBlk);
179         }
180         timeStamp++;
181     }
182 
183 __FAILED:
184     if (file) {
185         fclose(file);
186         file = RK_NULL;
187     }
188 
189     return RK_NULL;
190 }
191 
receive_data_thread(void * arg)192 static void *receive_data_thread(void *arg) {
193     RK_S32 s32ret = 0;
194     FILE  *file = RK_NULL;
195     TEST_ADEC_CTX_S *params = reinterpret_cast<TEST_ADEC_CTX_S *>(arg);
196     AUDIO_FRAME_INFO_S  *pstFrmInfo = RK_NULL;
197 
198     pstFrmInfo = reinterpret_cast<AUDIO_FRAME_INFO_S *>(malloc(sizeof(AUDIO_FRAME_INFO_S)));
199     memset(pstFrmInfo, 0, sizeof(AUDIO_FRAME_INFO_S));
200 
201     RK_BOOL bBlock = params->bBlock;
202     ADEC_CHN AdChn = (ADEC_CHN)(params->s32ChnIndex);
203     RK_S32 eos = 0;
204     RK_S32 count = 0;
205 
206     if (params->dstFilePath) {
207         file = fopen(params->dstFilePath, "wb+");
208         if (file == RK_NULL) {
209             RK_LOGE("failed to open output file %s, error: %s.", params->dstFilePath, strerror(errno));
210             goto __FAILED;
211         }
212     }
213 
214     while (1) {
215         s32ret = RK_MPI_ADEC_GetFrame(AdChn, pstFrmInfo, bBlock);
216         if (s32ret == RK_SUCCESS) {
217             MB_BLK bBlk = pstFrmInfo->pstFrame->pMbBlk;
218             RK_VOID *pstFrame = RK_MPI_MB_Handle2VirAddr(bBlk);
219             RK_S32 frameSize = pstFrmInfo->pstFrame->u32Len;
220             eos = (frameSize <= 0) ? 1 : 0;
221             if (pstFrame) {
222                 RK_LOGV("get frame data = %p, size = %d", pstFrame, frameSize);
223                 if (file) {
224                     fwrite(pstFrame, frameSize, 1, file);
225                     fflush(file);
226                 }
227                 //  release frame
228                 RK_MPI_ADEC_ReleaseFrame(AdChn, pstFrmInfo);
229                 count++;
230             }
231         } else {
232             RK_LOGE("fail to get adec frame.");
233         }
234 
235         if (params->s32QueryStat) {
236             query_adec_flow_graph_stat(AdChn);
237             params->s32QueryStat = 0;
238         }
239 
240         if (params->s32ClrChnBuf) {
241             RK_LOGI("test clear chn(%d) buf", AdChn);
242             RK_MPI_ADEC_ClearChnBuf(AdChn);
243             params->s32ClrChnBuf = 0;
244         }
245 
246         if (eos) {
247             RK_LOGI("get eos packet.");
248             break;
249         }
250     }
251 
252 __FAILED:
253     if (pstFrmInfo) {
254         free(pstFrmInfo);
255         pstFrmInfo = RK_NULL;
256     }
257 
258     if (file) {
259         fclose(file);
260         file = RK_NULL;
261     }
262     return RK_NULL;
263 }
264 
unit_test_mpi_adec(TEST_ADEC_CTX_S * params)265 RK_S32 unit_test_mpi_adec(TEST_ADEC_CTX_S *params) {
266     RK_S32 i = 0;
267     TEST_ADEC_CTX_S adecCtx[ADEC_MAX_CHN_NUM];
268     pthread_t tidSend[ADEC_MAX_CHN_NUM];
269     pthread_t tidReceive[ADEC_MAX_CHN_NUM];
270 
271     if (params->s32ChnNum > ADEC_MAX_CHN_NUM) {
272         RK_LOGE("adec chn(%d) > max_chn(%d)", params->s32ChnNum, ADEC_MAX_CHN_NUM);
273         goto __FAILED;
274     }
275 
276     params->bBlock = RK_TRUE;
277 
278     for (i = 0; i < params->s32ChnNum; i++) {
279         memcpy(&(adecCtx[i]), params, sizeof(TEST_ADEC_CTX_S));
280         adecCtx[i].s32ChnIndex = i;
281 
282         if (test_init_mpi_adec(&adecCtx[i]) == RK_FAILURE) {
283             goto __FAILED;
284         }
285 
286         if (params->s32DecMode == ADEC_MODE_STREAM) {
287             pthread_create(&tidSend[i], RK_NULL, send_stream_thread, reinterpret_cast<void *>(&adecCtx[i]));
288         } else {
289 
290         }
291         pthread_create(&tidReceive[i], RK_NULL, receive_data_thread, reinterpret_cast<void *>(&adecCtx[i]));
292     }
293 
294     for (i = 0; i < params->s32ChnNum; i++) {
295         pthread_join(tidSend[i], RK_NULL);
296         pthread_join(tidReceive[i], RK_NULL);
297         test_deinit_mpi_adec(&adecCtx[i]);
298     }
299 
300     return RK_SUCCESS;
301 __FAILED:
302 
303     return RK_FAILURE;
304 }
305 
306 static const char *const usages[] = {
307     "./rk_mpi_adec_test [-i src_path] [-C name] [--input_rate rate] [--input_ch ch]...",
308     NULL,
309 };
310 
mpi_adec_test_show_options(const TEST_ADEC_CTX_S * ctx)311 static void mpi_adec_test_show_options(const TEST_ADEC_CTX_S *ctx) {
312     RK_PRINT("cmd parse result:\n");
313     RK_PRINT("input  file name       : %s\n", ctx->srcFilePath);
314     RK_PRINT("output file name       : %s\n", ctx->dstFilePath);
315     RK_PRINT("loop count             : %d\n", ctx->s32LoopCount);
316     RK_PRINT("channel number         : %d\n", ctx->s32ChnNum);
317     RK_PRINT("input sample rate      : %d\n", ctx->s32SampleRate);
318     RK_PRINT("input channel          : %d\n", ctx->s32Channel);
319     RK_PRINT("input codec name       : %s\n", ctx->chCodecId);
320     RK_PRINT("input decode mode      : %d\n", ctx->s32DecMode);
321     RK_PRINT("query stat             : %d\n", ctx->s32QueryStat);
322     RK_PRINT("clear buf              : %d\n", ctx->s32ClrChnBuf);
323 }
324 
main(int argc,const char ** argv)325 int main(int argc, const char **argv) {
326     RK_S32           i;
327     RK_S32           s32Ret;
328     TEST_ADEC_CTX_S *ctx;
329 
330     ctx = reinterpret_cast<TEST_ADEC_CTX_S *>(malloc(sizeof(TEST_ADEC_CTX_S)));
331     memset(ctx, 0, sizeof(TEST_ADEC_CTX_S));
332 
333     ctx->srcFilePath     = RK_NULL;
334     ctx->dstFilePath     = RK_NULL;
335     ctx->s32LoopCount    = 1;
336     ctx->s32ChnNum       = 1;
337     ctx->s32DecMode      = 0;
338     ctx->chCodecId       = RK_NULL;
339     ctx->s32DecMode      = ADEC_MODE_STREAM;
340 
341     struct argparse_option options[] = {
342         OPT_HELP(),
343         OPT_GROUP("basic options:"),
344         OPT_STRING('i', "input",  &(ctx->srcFilePath),
345                    "input file name , e.g.(./*.mp3). <required>", NULL, 0, 0),
346         OPT_STRING('C', "codec", &(ctx->chCodecId),
347                     "codec, e.g.(mp2/g711a/g711u/g726). <required>", NULL, 0, 0),
348         OPT_INTEGER('\0', "input_ch", &(ctx->s32Channel),
349                     "the number of input stream channels. <required>", NULL, 0, 0),
350         OPT_INTEGER('\0', "input_rate", &(ctx->s32SampleRate),
351                     "the sample rate of input stream. <required>", NULL, 0, 0),
352         OPT_STRING('o', "output", &(ctx->dstFilePath),
353                     "output file name, e.g.(./*.pcm). default(NULL).", NULL, 0, 0),
354         OPT_INTEGER('n', "loop_count", &(ctx->s32LoopCount),
355                     "loop running count. default(1)", NULL, 0, 0),
356         OPT_INTEGER('c', "channel_count", &(ctx->s32ChnNum),
357                     "the count of adec channel. default(1).", NULL, 0, 0),
358         OPT_INTEGER('\0', "dec_mode", &(ctx->s32DecMode),
359                     "the audio stream decode mode, range(0: pack mode, 1: stream mode), default(0)", NULL, 0, 0),
360         OPT_INTEGER('\0', "query_stat", &(ctx->s32QueryStat),
361                     "query adec statistics info, range(0: query, 1: not query), default(0)", NULL, 0, 0),
362         OPT_INTEGER('\0', "clr_buf", &(ctx->s32ClrChnBuf),
363                     "clear buffer of channel, range(0, 1), default(0)", NULL, 0, 0),
364         OPT_END(),
365     };
366 
367     struct argparse argparse;
368     argparse_init(&argparse, options, usages, 0);
369     argparse_describe(&argparse, "\nselect a test case to run.",
370                                  "\nuse --help for details.");
371 
372     argc = argparse_parse(&argparse, argc, argv);
373     mpi_adec_test_show_options(ctx);
374 
375     // must set params
376     if (ctx->srcFilePath == RK_NULL
377         || ctx->s32Channel <= 0
378         || ctx->s32SampleRate <= 0
379         || ctx->chCodecId == RK_NULL) {
380         argparse_usage(&argparse);
381         goto __FAILED;
382     }
383 
384     RK_MPI_SYS_Init();
385 
386     for (i = 0; i < ctx->s32LoopCount; i++) {
387         RK_LOGI("start running loop count  = %d", i);
388         s32Ret = unit_test_mpi_adec(ctx);
389         if (s32Ret != RK_SUCCESS) {
390             goto __FAILED;
391         }
392         RK_LOGI("end running loop count  = %d", i);
393     }
394 
395 __FAILED:
396     if (ctx) {
397         free(ctx);
398         ctx = RK_NULL;
399     }
400 
401     RK_MPI_SYS_Exit();
402     return 0;
403 }
404