xref: /OK3568_Linux_fs/external/rockit/mpi/example/mod/test_mpi_vdec.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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