1 /*
2 * Copyright 2018 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 <cstdio>
19 #include <cerrno>
20 #include <cstring>
21 #include <cstdlib>
22 #include <unistd.h>
23 #include <pthread.h>
24 #include <sys/stat.h>
25 #include <sys/poll.h>
26 #include <sys/types.h>
27 #include "rk_debug.h"
28 #include "rk_mpi_vdec.h"
29 #include "rk_mpi_sys.h"
30 #include "rk_mpi_mb.h"
31 #include "rk_mpi_cal.h"
32 #include "rk_mpi_vo.h"
33 #include "test_comm_argparse.h"
34 #include "test_comm_utils.h"
35
36 #define MAX_STREAM_CNT 8
37 #define MAX_TIME_OUT_MS 20
38
39 #ifndef VDEC_INT64_MIN
40 #define VDEC_INT64_MIN (-0x7fffffffffffffffLL-1)
41 #endif
42
43 #ifndef VDEC_INT64_MAX
44 #define VDEC_INT64_MAX INT64_C(9223372036854775807)
45 #endif
46
47 typedef struct _rkMpiVDECCtx {
48 const char *srcFileUri;
49 const char *dstFilePath;
50 RK_U32 u32SrcWidth;
51 RK_U32 u32SrcHeight;
52 RK_S32 s32LoopCount;
53 RK_U32 u32ChnIndex;
54 RK_U32 u32ChNum;
55 RK_U32 u32InputMode;
56 RK_CODEC_ID_E enCodecId;
57 RK_U32 u32CompressMode;
58 RK_U32 u32FrameBufferCnt;
59 pthread_t pVdecThread;
60 pthread_t pGetPicThread;
61 RK_U32 u32StreamIndex;
62 void *pExtraData;
63 RK_U32 u32ExtraDataSize;
64 RK_U32 u32ReadSize;
65 RK_BOOL threadExit;
66 RK_S32 s32ChnFd;
67 RK_BOOL bEnableMbPool;
68 MB_POOL s32Pool;
69 RK_S32 s32OutputPixFmt;
70 RK_BOOL bEnableDei;
71 RK_BOOL bEnableColmv;
72 } TEST_VDEC_CTX_S;
73
dump_frame_to_file(VIDEO_FRAME_INFO_S * pstFrame,FILE * fp)74 static void dump_frame_to_file(VIDEO_FRAME_INFO_S *pstFrame, FILE *fp) {
75 RK_U32 i;
76 RK_U32 width = 0;
77 RK_U32 height = 0;
78 RK_U32 h_stride = 0;
79 RK_U32 v_stride = 0;
80 RK_U8 *base_y = RK_NULL;
81 RK_U8 *base_c = RK_NULL;
82 RK_U8 *base = RK_NULL;
83
84 if (NULL == fp)
85 return;
86
87 base = (RK_U8 *)RK_MPI_MB_Handle2VirAddr(pstFrame->stVFrame.pMbBlk);
88 RK_MPI_SYS_MmzFlushCache(pstFrame->stVFrame.pMbBlk, RK_TRUE);
89 width = pstFrame->stVFrame.u32Width;
90 height = pstFrame->stVFrame.u32Height;
91
92 switch (pstFrame->stVFrame.enPixelFormat) {
93 case RK_FMT_YUV420SP_VU :
94 case RK_FMT_YUV420SP : {
95 h_stride = pstFrame->stVFrame.u32VirWidth;
96 v_stride = pstFrame->stVFrame.u32VirHeight;
97
98 base_y = base;
99 base_c = base + h_stride * v_stride;
100
101 for (i = 0; i < height; i++, base_y += h_stride) {
102 fwrite(base_y, 1, width, fp);
103 }
104 for (i = 0; i < height / 2; i++, base_c += h_stride) {
105 fwrite(base_c, 1, width, fp);
106 }
107 } break;
108
109 case RK_FMT_YUV420SP_10BIT : {
110 h_stride = pstFrame->stVFrame.u32VirWidth * 10 / 8;
111 v_stride = pstFrame->stVFrame.u32VirHeight;
112
113 base_y = base;
114 base_c = base + h_stride * v_stride;
115
116 for (i = 0; i < height; i++, base_y += h_stride) {
117 fwrite(base_y, 1, width, fp);
118 }
119 for (i = 0; i < height / 2; i++, base_c += h_stride) {
120 fwrite(base_c, 1, width, fp);
121 }
122 } break;
123
124 case RK_FMT_RGB565:
125 case RK_FMT_BGR565: {
126 h_stride = pstFrame->stVFrame.u32VirWidth * 2;
127 v_stride = pstFrame->stVFrame.u32VirHeight;
128 base_y = base;
129
130 for (i = 0; i < height; i++, base_y += h_stride)
131 fwrite(base_y, 1, width * 2, fp);
132 } break;
133 case RK_FMT_RGB888:
134 case RK_FMT_BGR888: {
135 h_stride = pstFrame->stVFrame.u32VirWidth * 3;
136 v_stride = pstFrame->stVFrame.u32VirHeight;
137 base_y = base;
138
139 for (i = 0; i < height; i++, base_y += h_stride)
140 fwrite(base_y, 1, width * 3, fp);
141 } break;
142 default : {
143 RK_LOGE("not supported format %d\n", pstFrame->stVFrame.enPixelFormat);
144 } break;
145 }
146 }
147
check_options(const TEST_VDEC_CTX_S * ctx)148 static RK_S32 check_options(const TEST_VDEC_CTX_S *ctx) {
149 if (ctx->srcFileUri == RK_NULL) {
150 goto __FAILED;
151 }
152
153 if (ctx->u32InputMode == VIDEO_MODE_STREAM) {
154 if (ctx->enCodecId <= RK_VIDEO_ID_Unused ||
155 ctx->u32SrcWidth <= 0 ||
156 ctx->u32SrcHeight <= 0) {
157 goto __FAILED;
158 }
159 }
160 return RK_SUCCESS;
161
162 __FAILED:
163 return RK_FAILURE;
164 }
165
166
mpi_vdec_poll_event(RK_S32 timeoutMsec,RK_S32 fd)167 RK_S32 mpi_vdec_poll_event(RK_S32 timeoutMsec, RK_S32 fd) {
168 RK_S32 num_fds = 1;
169 struct pollfd pollFds[num_fds];
170 RK_S32 ret = 0;
171
172 RK_ASSERT(fd > 0);
173 memset(pollFds, 0, sizeof(pollFds));
174 pollFds[0].fd = fd;
175 pollFds[0].events = (POLLPRI | POLLIN | POLLERR | POLLNVAL | POLLHUP);
176
177 ret = poll(pollFds, num_fds, timeoutMsec);
178 if (ret > 0 && (pollFds[0].revents & (POLLERR | POLLNVAL | POLLHUP))) {
179 RK_LOGE("fd:%d polled error", fd);
180 return -1;
181 }
182
183 return ret;
184 }
185
mpi_create_vdec(TEST_VDEC_CTX_S * ctx,RK_S32 s32Ch,VIDEO_MODE_E enMode)186 RK_S32 mpi_create_vdec(TEST_VDEC_CTX_S *ctx, RK_S32 s32Ch, VIDEO_MODE_E enMode) {
187 RK_S32 s32Ret = RK_SUCCESS;
188 VDEC_CHN_ATTR_S stAttr;
189 VDEC_CHN_PARAM_S stVdecParam;
190 MB_POOL_CONFIG_S stMbPoolCfg;
191 VDEC_PIC_BUF_ATTR_S stVdecPicBufAttr;
192 MB_PIC_CAL_S stMbPicCalResult;
193 VDEC_MOD_PARAM_S stModParam;
194
195 memset(&stAttr, 0, sizeof(VDEC_CHN_ATTR_S));
196 memset(&stVdecParam, 0, sizeof(VDEC_CHN_PARAM_S));
197 memset(&stModParam, 0, sizeof(VDEC_MOD_PARAM_S));
198
199 if (ctx->bEnableMbPool) {
200 stModParam.enVdecMBSource = MB_SOURCE_USER;
201 s32Ret = RK_MPI_VDEC_SetModParam(&stModParam);
202 if (s32Ret != RK_SUCCESS) {
203 RK_LOGE("vdec %d SetModParam failed! errcode %x", ctx->u32ChnIndex, s32Ret);
204 return s32Ret;
205 }
206 }
207
208 stAttr.enMode = enMode;
209 stAttr.enType = ctx->enCodecId;
210 stAttr.u32PicWidth = ctx->u32SrcWidth;
211 stAttr.u32PicHeight = ctx->u32SrcHeight;
212 stAttr.u32FrameBufCnt = ctx->u32FrameBufferCnt;
213 stAttr.u32StreamBufCnt = MAX_STREAM_CNT;
214
215 if (!ctx->bEnableColmv) {
216 stAttr.stVdecVideoAttr.bTemporalMvpEnable = RK_FALSE;
217 }
218
219 s32Ret = RK_MPI_VDEC_CreateChn(ctx->u32ChnIndex, &stAttr);
220 if (s32Ret != RK_SUCCESS) {
221 RK_LOGE("create %d vdec failed! ", ctx->u32ChnIndex);
222 return s32Ret;
223 }
224
225 if (ctx->enCodecId == RK_VIDEO_ID_MJPEG) {
226 stVdecParam.stVdecPictureParam.enPixelFormat = (PIXEL_FORMAT_E)ctx->s32OutputPixFmt;
227 } else {
228 stVdecParam.stVdecVideoParam.enCompressMode = (COMPRESS_MODE_E)ctx->u32CompressMode;
229 }
230 if (ctx->bEnableDei) {
231 stVdecParam.stVdecVideoParam.bDeiEn = ctx->bEnableDei;
232 }
233 // it is only effective to disable MV when decoding sequence output
234 if (!ctx->bEnableColmv) {
235 stVdecParam.stVdecVideoParam.enOutputOrder = VIDEO_OUTPUT_ORDER_DEC;
236 }
237
238 s32Ret = RK_MPI_VDEC_SetChnParam(ctx->u32ChnIndex, &stVdecParam);
239 if (s32Ret != RK_SUCCESS) {
240 RK_LOGE("set chn %d param failed %x! ", ctx->u32ChnIndex, s32Ret);
241 return s32Ret;
242 }
243
244 ctx->s32ChnFd = RK_MPI_VDEC_GetFd(ctx->u32ChnIndex);
245 if (ctx->s32ChnFd <= 0) {
246 RK_LOGE("get fd chn %d failed %d", ctx->u32ChnIndex, ctx->s32ChnFd);
247 return s32Ret;
248 }
249
250 if (ctx->bEnableMbPool) {
251 memset(&stMbPoolCfg, 0, sizeof(MB_POOL_CONFIG_S));
252
253 stVdecPicBufAttr.enCodecType = ctx->enCodecId;
254 stVdecPicBufAttr.stPicBufAttr.u32Width = ctx->u32SrcWidth;
255 stVdecPicBufAttr.stPicBufAttr.u32Height = ctx->u32SrcHeight;
256 stVdecPicBufAttr.stPicBufAttr.enPixelFormat = (PIXEL_FORMAT_E)ctx->s32OutputPixFmt;
257 stVdecPicBufAttr.stPicBufAttr.enCompMode = (COMPRESS_MODE_E)ctx->u32CompressMode;
258 s32Ret = RK_MPI_CAL_VDEC_GetPicBufferSize(&stVdecPicBufAttr, &stMbPicCalResult);
259 if (s32Ret != RK_SUCCESS) {
260 RK_LOGE("get picture buffer size failed. err 0x%x", s32Ret);
261 return s32Ret;
262 }
263
264 stMbPoolCfg.u64MBSize = stMbPicCalResult.u32MBSize;;
265 stMbPoolCfg.u32MBCnt = 10;
266 stMbPoolCfg.enRemapMode = MB_REMAP_MODE_CACHED;
267 stMbPoolCfg.bPreAlloc = RK_TRUE;
268 ctx->s32Pool = RK_MPI_MB_CreatePool(&stMbPoolCfg);
269 if (ctx->s32Pool == MB_INVALID_POOLID) {
270 RK_LOGE("create pool failed!");
271 return s32Ret;
272 }
273 s32Ret = RK_MPI_VDEC_AttachMbPool(ctx->u32ChnIndex, ctx->s32Pool);
274 if (s32Ret != RK_SUCCESS) {
275 RK_LOGE("attatc vdec mb pool %d failed! ", ctx->u32ChnIndex);
276 return s32Ret;
277 }
278 }
279
280 s32Ret = RK_MPI_VDEC_StartRecvStream(ctx->u32ChnIndex);
281 if (s32Ret != RK_SUCCESS) {
282 RK_LOGE("start recv chn %d failed %x! ", ctx->u32ChnIndex, s32Ret);
283 return s32Ret;
284 }
285
286 return RK_SUCCESS;
287 }
288
mpi_destory_vdec(TEST_VDEC_CTX_S * ctx,RK_S32 s32Ch)289 RK_S32 mpi_destory_vdec(TEST_VDEC_CTX_S *ctx, RK_S32 s32Ch) {
290 RK_MPI_VDEC_StopRecvStream(s32Ch);
291
292 if (ctx->s32ChnFd > 0) {
293 RK_MPI_VDEC_CloseFd(s32Ch);
294 }
295
296 if (ctx->bEnableMbPool) {
297 RK_MPI_VDEC_DetachMbPool(s32Ch);
298 RK_MPI_VDEC_DestroyChn(s32Ch);
299 RK_MPI_MB_DestroyPool(ctx->s32Pool);
300 } else {
301 RK_MPI_VDEC_DestroyChn(s32Ch);
302 }
303
304 return RK_SUCCESS;
305 }
306
mpi_create_stream_mode(TEST_VDEC_CTX_S * ctx,RK_S32 s32Ch)307 RK_S32 mpi_create_stream_mode(TEST_VDEC_CTX_S *ctx, RK_S32 s32Ch) {
308 VIDEO_MODE_E enMode;
309
310 if (ctx->enCodecId == RK_VIDEO_ID_MJPEG || ctx->enCodecId == RK_VIDEO_ID_JPEG) {
311 ctx->u32ReadSize = ctx->u32SrcWidth * ctx->u32SrcHeight;
312 enMode = VIDEO_MODE_FRAME;
313 } else {
314 enMode = VIDEO_MODE_STREAM;
315 }
316
317 return mpi_create_vdec(ctx, s32Ch, enMode);
318 }
319
mpi_create_frame_mode(TEST_VDEC_CTX_S * ctx,RK_S32 s32Ch)320 RK_S32 mpi_create_frame_mode(TEST_VDEC_CTX_S *ctx, RK_S32 s32Ch) {
321 RK_S32 s32Ret = RK_SUCCESS;
322
323 s32Ret = mpi_create_vdec(ctx, s32Ch, VIDEO_MODE_FRAME);
324 if (s32Ret != RK_SUCCESS) {
325 goto __FAILED;
326 }
327
328 return s32Ret;
329 __FAILED:
330
331 return RK_FAILURE;
332 }
333
mpi_get_pic(void * pArgs)334 void* mpi_get_pic(void *pArgs) {
335 TEST_VDEC_CTX_S *ctx = reinterpret_cast<TEST_VDEC_CTX_S *>(pArgs);
336 FILE *fp = RK_NULL;
337 VIDEO_FRAME_INFO_S sFrame;
338 RK_S32 s32Ret;
339 char name[256] = {0};
340 RK_S32 s32FrameCount = 0;
341
342 memset(&sFrame, 0, sizeof(VIDEO_FRAME_INFO_S));
343
344 if (ctx->dstFilePath != RK_NULL) {
345 mkdir(ctx->dstFilePath, 0777);
346 snprintf(name, sizeof(name), "%stest_%d.bin", ctx->dstFilePath, ctx->u32ChnIndex);
347
348 fp = fopen(name, "wb");
349 if (fp == RK_NULL) {
350 RK_LOGE("can't open output file %s\n", name);
351 return NULL;
352 }
353 }
354
355 while (!ctx->threadExit) {
356 if (ctx->s32ChnFd > 0) {
357 s32Ret = mpi_vdec_poll_event(-1, ctx->s32ChnFd);
358 if (s32Ret < 0) {
359 if (ctx->threadExit)
360 break;
361
362 usleep(1000llu);
363 continue;
364 }
365 }
366
367 s32Ret = RK_MPI_VDEC_GetFrame(ctx->u32ChnIndex, &sFrame, MAX_TIME_OUT_MS);
368 if (s32Ret >= 0) {
369 s32FrameCount++;
370 RK_LOGI("get chn %d frame %d", ctx->u32ChnIndex, s32FrameCount);
371 if ((sFrame.stVFrame.u32FrameFlag & FRAME_FLAG_SNAP_END) == FRAME_FLAG_SNAP_END) {
372 RK_MPI_VDEC_ReleaseFrame(ctx->u32ChnIndex, &sFrame);
373 RK_LOGI("chn %d reach eos frame.", ctx->u32ChnIndex);
374 break;
375 }
376
377 dump_frame_to_file(&sFrame, fp);
378 RK_MPI_VDEC_ReleaseFrame(ctx->u32ChnIndex, &sFrame);
379 } else {
380 if (ctx->threadExit)
381 break;
382
383 usleep(1000llu);
384 }
385 }
386
387 if (fp)
388 fclose(fp);
389 RK_LOGI("%s out", __FUNCTION__);
390 return RK_NULL;
391 }
392
393
mpi_vdec_free(void * opaque)394 static RK_S32 mpi_vdec_free(void *opaque) {
395 if (opaque)
396 free(opaque);
397 return 0;
398 }
399
mpi_send_stream(void * pArgs)400 static void* mpi_send_stream(void *pArgs) {
401 TEST_VDEC_CTX_S *ctx = reinterpret_cast<TEST_VDEC_CTX_S *>(pArgs);
402 RK_S32 s32Size = 0;
403 RK_S32 s32Ret = 0;
404 RK_U8 *data = RK_NULL;
405 FILE *fp = RK_NULL;
406 MB_BLK buffer = RK_NULL;
407 MB_EXT_CONFIG_S pstMbExtConfig;
408 VDEC_CHN_STATUS_S staus;
409 VDEC_CHN_ATTR_S stAttr;
410 VDEC_CHN_PARAM_S stVdecParam;
411 VDEC_STREAM_S stStream;
412 RK_S32 s32PacketCount = 0;
413 RK_S32 s32ReachEOS = 0;
414
415 memset(&stStream, 0, sizeof(VDEC_STREAM_S));
416
417 fp = fopen(ctx->srcFileUri, "r");
418 if (fp == RK_NULL) {
419 RK_LOGE("open file %s failed", ctx->srcFileUri);
420 return RK_NULL;
421 }
422
423 while (!ctx->threadExit) {
424 data = reinterpret_cast<RK_U8 *>(calloc(ctx->u32ReadSize, sizeof(RK_U8)));
425 memset(data, 0, ctx->u32ReadSize);
426 s32Size = fread(data, 1, ctx->u32ReadSize, fp);
427 if (s32Size <= 0) {
428 if (ctx->s32LoopCount--) {
429 mpi_vdec_free(data);
430 s32ReachEOS = 0;
431 fseek(fp, 0, SEEK_SET);
432 RK_LOGI("ctx->s32LoopCount = %d",ctx->s32LoopCount);
433 if (ctx->u32ChnIndex) {
434 for (int i = 0; i < ctx->u32ChNum; i++) {
435 VO_CHN_ATTR_S stChnAttr;
436 RK_MPI_VO_GetChnAttr(0, i, &stChnAttr);
437 if (ctx->s32LoopCount % 2)
438 stChnAttr.u32Priority = ctx->u32ChNum - i;
439 else
440 stChnAttr.u32Priority = i;
441 RK_MPI_VO_SetChnAttr(0, i, &stChnAttr);
442 }
443 }
444 continue;
445 } else
446 s32ReachEOS = 1;
447 }
448
449 memset(&pstMbExtConfig, 0, sizeof(MB_EXT_CONFIG_S));
450 pstMbExtConfig.pFreeCB = mpi_vdec_free;
451 pstMbExtConfig.pOpaque = data;
452 pstMbExtConfig.pu8VirAddr = data;
453 pstMbExtConfig.u64Size = s32Size;
454
455 RK_MPI_SYS_CreateMB(&buffer, &pstMbExtConfig);
456
457 stStream.u64PTS = 0;
458 stStream.pMbBlk = buffer;
459 stStream.u32Len = s32Size;
460 stStream.bEndOfStream = s32ReachEOS ? RK_TRUE : RK_FALSE;
461 stStream.bEndOfFrame = s32ReachEOS ? RK_TRUE : RK_FALSE;
462 stStream.bBypassMbBlk = RK_TRUE;
463 __RETRY:
464 s32Ret = RK_MPI_VDEC_SendStream(ctx->u32ChnIndex, &stStream, MAX_TIME_OUT_MS);
465 if (s32Ret < 0) {
466 if (ctx->threadExit) {
467 mpi_vdec_free(data);
468 RK_MPI_MB_ReleaseMB(stStream.pMbBlk);
469 break;
470 }
471 usleep(1000llu);
472 goto __RETRY;
473 } else {
474 s32PacketCount++;
475 RK_MPI_MB_ReleaseMB(stStream.pMbBlk);
476 //RK_LOGI("send chn %d packet %d", ctx->u32ChnIndex, s32PacketCount);
477 }
478 if (s32ReachEOS) {
479 RK_LOGI("chn %d input reach EOS", ctx->u32ChnIndex);
480 break;
481 }
482 }
483
484 if (fp)
485 fclose(fp);
486
487 RK_LOGI("%s out\n", __FUNCTION__);
488 return RK_NULL;
489 }
490
create_vo(RK_U32 ChCnt)491 static RK_S32 create_vo(RK_U32 ChCnt) {
492 /* Enable VO */
493 VO_PUB_ATTR_S VoPubAttr;
494 VO_VIDEO_LAYER_ATTR_S stLayerAttr;
495 RK_S32 s32Ret = RK_SUCCESS;
496 VO_CHN_ATTR_S stChnAttr;
497 VO_LAYER VoLayer = 0;
498 VO_DEV VoDev = 0;
499
500 RK_MPI_VO_DisableLayer(VoLayer);
501 RK_MPI_VO_DisableLayer(4);
502 RK_MPI_VO_DisableLayer(5);
503 RK_MPI_VO_DisableLayer(6);
504 RK_MPI_VO_DisableLayer(7);
505 RK_MPI_VO_Disable(VoDev);
506
507 memset(&VoPubAttr, 0, sizeof(VO_PUB_ATTR_S));
508 memset(&stLayerAttr, 0, sizeof(VO_VIDEO_LAYER_ATTR_S));
509
510 stLayerAttr.enPixFormat = RK_FMT_RGB888;
511 stLayerAttr.stDispRect.s32X = 0;
512 stLayerAttr.stDispRect.s32Y = 0;
513 stLayerAttr.u32DispFrmRt = 30;
514 stLayerAttr.stDispRect.u32Width = 1920;
515 stLayerAttr.stDispRect.u32Height = 1080;
516 stLayerAttr.stImageSize.u32Width = 1920;
517 stLayerAttr.stImageSize.u32Height = 1080;
518
519 s32Ret = RK_MPI_VO_GetPubAttr(VoDev, &VoPubAttr);
520 if (s32Ret != RK_SUCCESS) {
521 return s32Ret;
522 }
523
524 VoPubAttr.enIntfType = VO_INTF_HDMI;
525 VoPubAttr.enIntfSync = VO_OUTPUT_DEFAULT;
526
527 s32Ret = RK_MPI_VO_SetPubAttr(VoDev, &VoPubAttr);
528 if (s32Ret != RK_SUCCESS) {
529 return s32Ret;
530 }
531 s32Ret = RK_MPI_VO_Enable(VoDev);
532 if (s32Ret != RK_SUCCESS) {
533 return s32Ret;
534 }
535
536 s32Ret = RK_MPI_VO_BindLayer(VoLayer, VoDev, VO_LAYER_MODE_VIDEO);
537 if (s32Ret != RK_SUCCESS) {
538 RK_LOGE("RK_MPI_VO_BindLayer failed,s32Ret:%d\n", s32Ret);
539 return RK_FAILURE;
540 }
541
542 s32Ret = RK_MPI_VO_SetLayerAttr(VoLayer, &stLayerAttr);
543 if (s32Ret != RK_SUCCESS) {
544 RK_LOGE("RK_MPI_VO_SetLayerAttr failed,s32Ret:%d\n", s32Ret);
545 return RK_FAILURE;
546 }
547
548 s32Ret = RK_MPI_VO_EnableLayer(VoLayer);
549 if (s32Ret != RK_SUCCESS) {
550 RK_LOGE("RK_MPI_VO_EnableLayer failed,s32Ret:%d\n", s32Ret);
551 return RK_FAILURE;
552 }
553
554 for (int i = 0; i < ChCnt; i++) {
555 stChnAttr.stRect.u32Width = stLayerAttr.stImageSize.u32Width / ChCnt;
556 stChnAttr.stRect.u32Height = stLayerAttr.stImageSize.u32Height / ChCnt;
557 stChnAttr.stRect.s32X = i * stChnAttr.stRect.u32Width / 2;
558 stChnAttr.stRect.s32Y = i * stChnAttr.stRect.u32Height / 2;
559 stChnAttr.u32Priority = i;
560 stChnAttr.u32FgAlpha = 128;
561 stChnAttr.u32BgAlpha = 0;
562
563 s32Ret = RK_MPI_VO_SetChnAttr(VoLayer, i, &stChnAttr);
564 if (s32Ret != RK_SUCCESS) {
565 RK_LOGE("set chn Attr failed,s32Ret:%d\n", s32Ret);
566 return RK_FAILURE;
567 }
568 }
569
570 return s32Ret;
571 }
572
573
unit_test_mpi_vdec(TEST_VDEC_CTX_S * ctx)574 RK_S32 unit_test_mpi_vdec(TEST_VDEC_CTX_S *ctx) {
575 MPP_CHN_S stSrcChn, stDestChn;
576 RK_S32 s32Ret = RK_FAILURE;
577 RK_U32 u32Ch = 0;
578 TEST_VDEC_CTX_S vdecCtx[VDEC_MAX_CHN_NUM];
579 pthread_t vdecThread[VDEC_MAX_CHN_NUM];
580 pthread_t getPicThread[VDEC_MAX_CHN_NUM];
581
582 for (u32Ch = 0; u32Ch < ctx->u32ChNum; u32Ch++) {
583 if (ctx->u32ChNum > 1) {
584 ctx->u32ChnIndex = u32Ch;
585 }
586 memcpy(&(vdecCtx[u32Ch]), ctx, sizeof(TEST_VDEC_CTX_S));
587
588 // Does not support JPEG stream framing, read the size of one picture at a time
589 // and send it to the decoder.
590 if (ctx->u32InputMode == VIDEO_MODE_STREAM || ctx->enCodecId == RK_VIDEO_ID_MJPEG ||
591 ctx->enCodecId == RK_VIDEO_ID_JPEG) {
592 mpi_create_stream_mode(&vdecCtx[u32Ch], u32Ch);
593 pthread_create(&vdecThread[u32Ch], 0, mpi_send_stream, reinterpret_cast<void *>(&vdecCtx[u32Ch]));
594 } else {
595 return -1;
596 }
597
598 //pthread_create(&getPicThread[u32Ch], 0, mpi_get_pic, reinterpret_cast<void *>(&vdecCtx[u32Ch]));
599 }
600
601 s32Ret = create_vo(ctx->u32ChNum);
602 if (s32Ret != RK_SUCCESS) {
603 RK_LOGE("create vo ch failed");
604 return -1;
605 }
606 // bind vi to vo
607 for (int i = 0; i < ctx->u32ChNum; i++) {
608 stSrcChn.enModId = RK_ID_VDEC;
609 stSrcChn.s32DevId = 0;
610 stSrcChn.s32ChnId = i;
611
612 stDestChn.enModId = RK_ID_VO;
613 stDestChn.s32DevId = 0;
614 stDestChn.s32ChnId = i;
615
616 s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
617 if (s32Ret != RK_SUCCESS) {
618 RK_LOGE("vi band vo fail:%x", s32Ret);
619 return -1;
620 }
621
622 // enable vo
623 s32Ret = RK_MPI_VO_EnableChn(0, i);
624 if (s32Ret != RK_SUCCESS) {
625 RK_LOGE("Enalbe vo chn failed, s32Ret = %d\n", s32Ret);
626 return -1;
627 }
628 }
629
630 for (u32Ch = 0; u32Ch < ctx->u32ChNum; u32Ch++) {
631 pthread_join(vdecThread[u32Ch], RK_NULL);
632 pthread_join(getPicThread[u32Ch], RK_NULL);
633
634 vdecCtx[u32Ch].threadExit = RK_TRUE;
635 if (ctx->u32ChNum > 1) {
636 mpi_destory_vdec(&vdecCtx[u32Ch], u32Ch);
637 } else {
638 mpi_destory_vdec(&vdecCtx[u32Ch], ctx->u32ChnIndex);
639 }
640 }
641
642 return RK_SUCCESS;
643 }
644
mpi_vdec_test_show_options(const TEST_VDEC_CTX_S * ctx)645 static void mpi_vdec_test_show_options(const TEST_VDEC_CTX_S *ctx) {
646 RK_PRINT("cmd parse result:\n");
647 RK_PRINT("input file name : %s\n", ctx->srcFileUri);
648 RK_PRINT("output path : %s\n", ctx->dstFilePath);
649 RK_PRINT("input width : %d\n", ctx->u32SrcWidth);
650 RK_PRINT("input height : %d\n", ctx->u32SrcHeight);
651 RK_PRINT("input codecId : %d\n", ctx->enCodecId);
652 RK_PRINT("loop count : %d\n", ctx->s32LoopCount);
653 RK_PRINT("channel index : %d\n", ctx->u32ChnIndex);
654 RK_PRINT("channel number : %d\n", ctx->u32ChNum);
655 RK_PRINT("output compress mode : %d\n", ctx->u32CompressMode);
656 RK_PRINT("input mode : %d\n", ctx->u32InputMode);
657 RK_PRINT("enable mb pool : %d\n", ctx->bEnableMbPool);
658 RK_PRINT("output pix format : %d\n", ctx->s32OutputPixFmt);
659 RK_PRINT("enable deinterlace : %d\n", ctx->bEnableDei);
660 RK_PRINT("enable colmv : %d\n", ctx->bEnableColmv);
661 return;
662 }
663
664 static const char *const usages[] = {
665 "./rk_mpi_vdec_test [-i SRC_PATH] [-o OUTPUT_PATH]...",
666 NULL,
667 };
668
main(int argc,const char ** argv)669 int main(int argc, const char **argv) {
670 TEST_VDEC_CTX_S ctx;
671 memset(&ctx, 0, sizeof(TEST_VDEC_CTX_S));
672
673 ctx.u32InputMode = VIDEO_MODE_STREAM;
674 ctx.s32LoopCount = 1;
675 ctx.u32CompressMode = COMPRESS_MODE_NONE; // Suggest::COMPRESS_AFBC_16x16;
676 ctx.u32FrameBufferCnt = 8;
677 ctx.u32ReadSize = 1024;
678 ctx.u32ChNum = 1;
679 ctx.bEnableColmv = RK_TRUE;
680 ctx.s32OutputPixFmt = (RK_S32)RK_FMT_YUV420SP;
681 ctx.u32SrcWidth = 1920;
682 ctx.u32SrcHeight = 1080;
683 ctx.enCodecId = RK_VIDEO_ID_AVC;
684
685 struct argparse_option options[] = {
686 OPT_HELP(),
687 OPT_GROUP("basic options:"),
688 OPT_STRING('i', "input", &(ctx.srcFileUri),
689 "input file name. <required>", NULL, 0, 0),
690 OPT_STRING('o', "output", &(ctx.dstFilePath),
691 "the directory of decoder output", NULL, 0, 0),
692 OPT_INTEGER('C', "codec", &(ctx.enCodecId),
693 "input stream codec(8:h264, 9:mjpeg, 12:h265,...) <required on StreamMode>", NULL, 0, 0),
694 OPT_INTEGER('n', "loop_count", &(ctx.s32LoopCount),
695 "loop running count. default(1)", NULL, 0, 0),
696 OPT_INTEGER('w', "width", &(ctx.u32SrcWidth),
697 "input source width <required on StreamMode>", NULL, 0, 0),
698 OPT_INTEGER('h', "height", &(ctx.u32SrcHeight),
699 "input source height <required on StreamMode>", NULL, 0, 0),
700 OPT_INTEGER('\0', "channel_index", &(ctx.u32ChnIndex),
701 "vdec channel index. default(0).", NULL, 0, 0),
702 OPT_INTEGER('c', "channel_count", &(ctx.u32ChNum),
703 "vdec channel count. default(1).", NULL, 0, 0),
704 OPT_INTEGER('\0', "dec_mode", &(ctx.u32InputMode),
705 "vdec decode mode. range(0:StreamMode, 1:FrameMode). default(0)", NULL, 0, 0),
706 OPT_INTEGER('\0', "dec_buf_cnt", &(ctx.u32FrameBufferCnt),
707 "vdec decode output buffer count, default(8)", NULL, 0, 0),
708 OPT_INTEGER('\0', "compress_mode", &(ctx.u32CompressMode),
709 "vdec compress mode, default(0); 0: NONE, 1: AFBC_16X16", NULL, 0, 0),
710 OPT_INTEGER('\0', "en_mbpool", &(ctx.bEnableMbPool),
711 "enable mb pool, default(0).", NULL, 0, 0),
712 OPT_INTEGER('\0', "pixfmt", &(ctx.s32OutputPixFmt),
713 "jpeg output pixel format, default(0); 0: YUV420SP", NULL, 0, 0),
714 OPT_INTEGER('\0', "en_dei", &(ctx.bEnableDei),
715 "enable deinterlace, default(0);", NULL, 0, 0),
716 OPT_INTEGER('\0', "en_colmv", &(ctx.bEnableColmv),
717 "enable colmv, default(1);", NULL, 0, 0),
718 OPT_END(),
719 };
720
721 struct argparse argparse;
722 argparse_init(&argparse, options, usages, 0);
723 argparse_describe(&argparse, "\nselect a test case to run.",
724 "\nuse --help for details.");
725
726 argc = argparse_parse(&argparse, argc, argv);
727 mpi_vdec_test_show_options(&ctx);
728
729 if (check_options(&ctx)) {
730 RK_LOGE("illegal input parameters");
731 argparse_usage(&argparse);
732 goto __FAILED;
733 }
734
735 if (RK_MPI_SYS_Init() != RK_SUCCESS) {
736 goto __FAILED;
737 }
738
739 while (ctx.s32LoopCount > 0) {
740 if (unit_test_mpi_vdec(&ctx) < 0) {
741 goto __FAILED;
742 }
743 ctx.s32LoopCount--;
744 }
745
746 if (RK_MPI_SYS_Exit() != RK_SUCCESS) {
747 goto __FAILED;
748 }
749
750 RK_LOGE("test running success!");
751 return RK_SUCCESS;
752 __FAILED:
753 RK_LOGE("test running failed! %d count running done not yet.", ctx.s32LoopCount);
754 return RK_FAILURE;
755 }
756
757