xref: /OK3568_Linux_fs/external/rockit/mpi/example/mod/test_mpi_vo.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 
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <sys/prctl.h>
23 #include <pthread.h>
24 
25 #include "rk_debug.h"
26 #include "rk_mpi_sys.h"
27 #include "rk_mpi_vo.h"
28 #include "rk_mpi_vdec.h"
29 #include "rk_mpi_mb.h"
30 #include "rk_common.h"
31 
32 #include "test_comm_argparse.h"
33 #include "test_comm_utils.h"
34 
35 #define MAX_FRAME_QUEUE              8
36 #define MAX_TIME_OUT_MS              20
37 
38 #ifndef VDEC_INT64_MIN
39 #define VDEC_INT64_MIN               (-0x7fffffffffffffffLL-1)
40 #endif
41 
42 #ifndef VDEC_INT64_MAX
43 #define VDEC_INT64_MAX               INT64_C(9223372036854775807)
44 #endif
45 
46 #ifndef rk_safe_free
47 #define rk_safe_free(p)              { if (p) {free(p); (p)=RK_NULL;} }
48 #endif
49 
50 #ifndef rk_safe_delete
51 #define rk_safe_delete(p)            { if (p) {delete(p); (p)=RK_NULL;} }
52 #endif
53 
54 #define VDEC_ARRAY_ELEMS(a)          (sizeof(a) / sizeof((a)[0]))
55 
56 typedef struct rkVO_Timing_S {
57     RK_S32  enIntfSync;
58     RK_U32  u32Width;
59     RK_U32  u32Height;
60 } VO_Timing_S;
61 
62 typedef struct _rkWbcCfg {
63     VO_WBC_SOURCE_S stWbcSource;
64     VO_WBC_ATTR_S stWbcAttr;
65     RK_S32 s32ChnId;
66     RK_S32 s32VdecChnId;
67 } WBC_CFG;
68 
69 typedef struct _rkVdecCfg {
70     RK_U32 u32FrameBufferCnt;
71     COMPRESS_MODE_E enCompressMode;
72 } VDEC_CFG;
73 
74 typedef struct _rkVOCfg {
75     RK_U32 u32Screen0VoLayer;
76     RK_U32 u32Screen1VoLayer;
77 
78     RK_U32 u32Screen0Rows;
79     RK_U32 u32Screen1Rows;
80     RK_BOOL bDoubleScreen;
81 } VO_CFG;
82 
83 typedef struct _rkParserCfg {
84     char *srcFileUri[VDEC_MAX_CHN_NUM];
85     RK_CODEC_ID_E enCodecId;
86     RK_U32 u32SrcWidth;
87     RK_U32 u32SrcHeight;
88     RK_U32 u32StreamIndex;
89     void  *pExtraData;
90     RK_U32 u32ExtraDataSize;
91 } PARSER_CFG;
92 
93 typedef struct _rkBorderCfg {
94     RK_U32 u32LeftWidth;
95     RK_U32 u32RightWidth;
96     RK_U32 u32TopWidth;
97     RK_U32 u32BottomWidth;
98 } Border_CFG;
99 
100 #define RK356X_VOP_LAYER_CLUSTER_0      0
101 #define RK356X_VOP_LAYER_CLUSTER_1      2
102 #define RK356X_VOP_LAYER_ESMART_0       4
103 #define RK356X_VOP_LAYER_ESMART_1       5
104 #define RK356X_VOP_LAYER_SMART_0        6
105 #define RK356X_VOP_LAYER_SMART_1        7
106 
107 #define RK356X_VO_DEV_HD0               0
108 #define RK356X_VO_DEV_HD1               1
109 
110 #define DISPLAY_TYPE_HDMI               0
111 #define DISPLAY_TYPE_EDP                1
112 #define DISPLAY_TYPE_VGA                2
113 #define DISPLAY_TYPE_DP                 3
114 #define DISPLAY_TYPE_HDMI_EDP           4
115 
116 typedef struct _PixelFormatMap {
117     RK_U32 index;
118     PIXEL_FORMAT_E format;
119 } PixelFormatMap;
120 
121 const static PixelFormatMap testPixelFormat[] = {
122     // usual yuv/rga formats
123     {1,              RK_FMT_YUV420SP},
124     {2,              RK_FMT_YUV420SP_VU},
125     {3,              RK_FMT_RGB565},
126     {4,              RK_FMT_BGR565},
127     {5,              RK_FMT_RGB888},
128     {6,              RK_FMT_BGR888},
129     {7,              RK_FMT_BGRA8888},
130     {8,              RK_FMT_RGBA8888},
131     {9,              RK_FMT_RGBA5551},
132     {10,             RK_FMT_BGRA5551}
133 };
134 
135 #define MAX_VO_FORMAT_RGB_NUM        17
136 #define WBC_FORMAT_BGRA8888          0
137 #define WBC_FORMAT_RGBA8888          1
138 #define WBC_FORMAT_RGB888            2
139 #define WBC_FORMAT_BGR888            3
140 #define WBC_FORMAT_YUV420SP          4
141 #define WBC_FORMAT_YUV420SP_VU       5
142 
143 #define VO_CHANNEL_PLAY_NORMAL           0
144 #define VO_CHANNEL_PLAY_PAUSE            1
145 #define VO_CHANNEL_PLAY_STEP             2
146 #define VO_CHANNEL_PLAY_SPEED            3
147 
148 #define WBC_SOURCE_DEV                0
149 #define WBC_SOURCE_VIDEO              1
150 #define WBC_SOURCE_GRAPHIC            2
151 
152 #define MAX_WINDOWS_NUM               64
153 #define MAX_STEP_FRAME_NUM            50
154 
155 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
156 
157 typedef struct _TEST_MODE {
158     RK_U32 mode;
159     VO_INTF_SYNC_E enIntfSync;
160 } TEST_MODE_S;
161 
162 static VO_DEV VoLayer = RK356X_VOP_LAYER_CLUSTER_0;
163 static VO_DEV VoLayer_second = RK356X_VOP_LAYER_CLUSTER_1;
164 
165 TEST_MODE_S test_mode_table[] = {
166     {0,     VO_OUTPUT_640x480_60},
167     {1,     VO_OUTPUT_PAL},
168     {2,     VO_OUTPUT_576P50},
169     {3,     VO_OUTPUT_NTSC},
170     {4,     VO_OUTPUT_480P60},
171     {5,     VO_OUTPUT_800x600_60},
172     {6,     VO_OUTPUT_1024x768_60},
173     {7,     VO_OUTPUT_720P50},
174     {8,     VO_OUTPUT_720P60},
175     {9,     VO_OUTPUT_1280x1024_60},
176     {10,    VO_OUTPUT_1080P24},
177     {11,    VO_OUTPUT_1080P25},
178     {12,    VO_OUTPUT_1080P30},
179     {13,    VO_OUTPUT_1080I50},
180     {14,    VO_OUTPUT_1080I60},
181     {15,    VO_OUTPUT_1080P50},
182     {16,    VO_OUTPUT_1080P60},
183     {17,    VO_OUTPUT_3840x2160_24},
184     {18,    VO_OUTPUT_3840x2160_25},
185     {19,    VO_OUTPUT_3840x2160_30},
186     {20,    VO_OUTPUT_3840x2160_50},
187     {21,    VO_OUTPUT_3840x2160_60},
188     {22,    VO_OUTPUT_4096x2160_24},
189     {23,    VO_OUTPUT_4096x2160_25},
190     {24,    VO_OUTPUT_4096x2160_30},
191     {25,    VO_OUTPUT_4096x2160_50},
192     {26,    VO_OUTPUT_4096x2160_60},
193 };
194 
195 static VO_Timing_S stVoTimings[] = {
196     {VO_OUTPUT_640x480_60, 640, 480},
197     {VO_OUTPUT_800x600_60, 800, 600},
198     {VO_OUTPUT_1024x768_60, 1024, 768},
199     {VO_OUTPUT_1280x1024_60, 1280, 1024},
200     {VO_OUTPUT_1366x768_60, 1366, 768},
201     {VO_OUTPUT_1440x900_60, 1440, 900},
202     {VO_OUTPUT_1280x800_60, 1280, 800},
203     {VO_OUTPUT_1600x1200_60, 1600, 1200},
204     {VO_OUTPUT_1680x1050_60, 1680, 1050},
205     {VO_OUTPUT_1920x1200_60, 1920, 1200},
206 };
207 static void Sample_VO_GetDisplaySize(RK_S32 enIntfSync, RK_U32 *s32W, RK_U32 *s32H) {
208     switch (enIntfSync) {
209         case VO_OUTPUT_640x480_60:
210             *s32W = 640;
211             *s32H = 480;
212             break;
213         case VO_OUTPUT_PAL:
214         case VO_OUTPUT_576P50:
215             *s32W = 720;
216             *s32H = 576;
217             break;
218         case VO_OUTPUT_NTSC:
219         case VO_OUTPUT_480P60:
220             *s32W = 720;
221             *s32H = 480;
222             break;
223         case VO_OUTPUT_800x600_60:
224             *s32W = 800;
225             *s32H = 600;
226             break;
227         case VO_OUTPUT_1024x768_60:
228             *s32W = 1024;
229             *s32H = 768;
230             break;
231         case VO_OUTPUT_720P50:
232         case VO_OUTPUT_720P60:
233             *s32W = 1280;
234             *s32H = 720;
235             break;
236         case VO_OUTPUT_1280x1024_60:
237             *s32W = 1280;
238             *s32H = 1024;
239             break;
240         case VO_OUTPUT_1080P24:
241         case VO_OUTPUT_1080P25:
242         case VO_OUTPUT_1080P30:
243         case VO_OUTPUT_1080I50:
244         case VO_OUTPUT_1080I60:
245         case VO_OUTPUT_1080P50:
246         case VO_OUTPUT_1080P60:
247             *s32W = 1920;
248             *s32H = 1080;
249             break;
250         case VO_OUTPUT_3840x2160_24:
251         case VO_OUTPUT_3840x2160_25:
252         case VO_OUTPUT_3840x2160_30:
253         case VO_OUTPUT_3840x2160_50:
254         case VO_OUTPUT_3840x2160_60:
255             *s32W = 3840;
256             *s32H = 2160;
257             break;
258         case VO_OUTPUT_4096x2160_24:
259         case VO_OUTPUT_4096x2160_25:
260         case VO_OUTPUT_4096x2160_30:
261         case VO_OUTPUT_4096x2160_50:
262         case VO_OUTPUT_4096x2160_60:
263             *s32W = 4096;
264             *s32H = 2160;
265             break;
266         default:
267             for (RK_S32 i = 0; i < ARRAY_LENGTH(stVoTimings); i++) {
268                 if (stVoTimings[i].enIntfSync == enIntfSync) {
269                     *s32W = stVoTimings[i].u32Width;
270                     *s32H = stVoTimings[i].u32Height;
271                     break;
272                 }
273             }
274             break;
275     }
276 }
277 
278 #define Sample_Print(format, ...)       RK_LOGI(format, ##__VA_ARGS__)
279 
280 typedef struct _rkMpiVOCtx {
281     RK_S32  VoDev;
282     RK_S32  VoLayer;
283     RK_S32  VoLayerMode;
284 
285     RK_S32  u32Windows;
286     RK_U32  enIntfType; /* 0 HDMI 1 edp */
287     RK_U32  enIntfSync; /* VO_OUTPUT_1080P50 */
288     RK_U32  enIntfSync_second;
289     RK_U32  s32X;
290     RK_U32  s32Y;
291 
292     RK_U32  u32Screen0DisplayWidth;
293     RK_U32  u32Screen0DisplayHeight;
294     RK_U32  u32Screen1DisplayWidth;
295     RK_U32  u32Screen1DisplayHeight;
296 
297     RK_U32  u32Screen0ImageWidth;
298     RK_U32  u32Screen0ImageHeight;
299     RK_U32  u32Screen1ImageWidth;
300     RK_U32  u32Screen1ImageHeight;
301 
302     RK_U32  bDoubleScreen;
303     RK_U32  u32DispWidth;
304     RK_U32  u32DispHeight;
305     RK_U32  u32ImgeWidth;
306     RK_U32  u32ImageHeight;
307     RK_U32  s32PixFormat;
308     RK_U32  u32DispFrmRt;
309     RK_U32  u32DispFrmRtRatio;
310     RK_U32  uEnMode;
311     RK_BOOL bBorder;
312     RK_S32  loopCount;
313 
314     RK_U32  wbc_enable;
315     RK_BOOL wbc_auto;
316     RK_U32  ui;
317     RK_U32  ui_alpha;
318     RK_U32  u32WbcWidth;
319     RK_S32  u32WbcHeight;
320     COMPRESS_MODE_E  u32WbcCompressMode;
321     RK_S32  u32WbcPixFormat;
322     RK_U32  u32WbcSourceType;
323     RK_U32  u32WbcSourceId;
324 
325     VO_LAYER   VoVideoLayer;
326     RK_U32     u32VideoWindows;
327     RK_U32     u32GFXLayers;
328     VO_LAYER   VOGfxLayer;
329     RK_BOOL    threadExit;
330 
331     RK_BOOL     bVoPlay;
332     const char *cfgFileUri;
333     RK_S32      s32LoopCount;
334     RK_U32      u32ChnIndex;
335     RK_U32      u32Screen0Chn;
336     RK_U32      u32ChnDismode;
337     RK_U32      u32Screen1Chn;
338     RK_BOOL     bThreadExit;
339 
340     RK_BOOL     bEnWbc;
341     RK_BOOL     bEnWbcToVO;
342     RK_BOOL     bChnPriority;
343 
344     PARSER_CFG  stParserCfg;
345     VDEC_CFG    stVdecCfg;
346     VO_CFG      stVoCfg;
347     WBC_CFG     stWbcCfg;
348     RK_BOOL     wbc_bind;
349     RK_U32      bHomologous;
350     Border_CFG  stBorderCfg;
351 } TEST_VO_CTX_S;
352 
353 typedef struct _VO_Send_Thread_Param {
354     RK_U32 u32VideoWindows;
355     VO_LAYER VoVideoLayer;
356     RK_U32 u32GFXLayers;
357     VO_LAYER VOGfxLayer;
358     RK_U32 u32Exit;
359 } VoThreadParam;
360 
361 static RK_S32 SampleSetVoInterfacetiming(VO_PUB_ATTR_S *stVoPubAttr, RK_U32 enIntfSync) {
362     RK_U32 i;
363     RK_S32 s32Ret = RK_SUCCESS;
364 
365     for (i = 0; i < ARRAY_LENGTH(test_mode_table); i++) {
366         if (enIntfSync == test_mode_table[i].mode)
367             break;
368     }
369 
370     if (i == ARRAY_LENGTH(test_mode_table)) {
371         Sample_Print("%s not found supported mode in test mode_table\n", __func__);
372         return RK_FAILURE;
373      }
374 
375     stVoPubAttr->enIntfSync = test_mode_table[i].enIntfSync;
376 
377     return s32Ret;
378 }
379 static PIXEL_FORMAT_E Sample_wbc_formt(RK_S32 format) {
380     switch (format) {
381         case WBC_FORMAT_BGRA8888:
382             return RK_FMT_BGRA8888;
383         case WBC_FORMAT_RGBA8888:
384             return RK_FMT_RGBA8888;
385         case WBC_FORMAT_RGB888:
386             return RK_FMT_RGB888;
387         case WBC_FORMAT_BGR888:
388             return RK_FMT_BGR888;
389         case WBC_FORMAT_YUV420SP:
390             return RK_FMT_YUV420SP;
391         case WBC_FORMAT_YUV420SP_VU:
392             return RK_FMT_YUV420SP_VU;
393         default:
394             return RK_FMT_BUTT;
395     }
396 }
397 
398 static void* vochn_test_thread_func(void *pArgs) {
399     TEST_VO_CTX_S *ctx = reinterpret_cast<TEST_VO_CTX_S *>(pArgs);
400     RK_S32 i, j;
401 
402     while (1) {
403         if (ctx->u32ChnDismode == VO_CHANNEL_PLAY_PAUSE) {
404             for (i = 0; i < ctx->u32Screen0Chn; i++) {
405                 RK_MPI_VO_PauseChn(VoLayer, i);
406             }
407 
408             usleep(1000llu * 2000);
409 
410             for (i = 0; i < ctx->u32Screen0Chn; i++) {
411                 RK_MPI_VO_ResumeChn(VoLayer, i);
412             }
413         } else if (ctx->u32ChnDismode == VO_CHANNEL_PLAY_STEP) {
414             for (i = 0; i < ctx->u32Screen0Chn; i++) {
415                 for (RK_S32 j = 0; j < MAX_STEP_FRAME_NUM; j++) {
416                     RK_MPI_VO_StepChn(VoLayer, i);
417                 }
418             }
419 
420             usleep(1000llu * 2000);
421 
422             for (i = 0; i < ctx->u32Screen0Chn; i++) {
423                 RK_MPI_VO_ResumeChn(VoLayer, i);
424             }
425         } else if (ctx->u32ChnDismode == VO_CHANNEL_PLAY_SPEED) {
426             for (i = 0; i < ctx->u32Screen0Chn; i++) {
427                 RK_MPI_VO_SetChnFrameRate(VoLayer, i, ctx->u32DispFrmRt * ctx->u32DispFrmRtRatio);
428             }
429 
430             usleep(1000llu * 2000);
431 
432             for (i = 0; i < ctx->u32Screen0Chn; i++) {
433                 RK_MPI_VO_ResumeChn(VoLayer, i);
434             }
435         }
436 
437         if (ctx->stVoCfg.bDoubleScreen) {
438             if (ctx->u32ChnDismode == VO_CHANNEL_PLAY_PAUSE) {
439                 for (i = 0; i < ctx->u32Screen1Chn; i++) {
440                     RK_MPI_VO_PauseChn(VoLayer_second, i);
441                 }
442                 usleep(1000llu * 2000);
443                 for (i = 0; i < ctx->u32Screen1Chn; i++) {
444                     RK_MPI_VO_ResumeChn(VoLayer_second, i);
445                 }
446             } else if (ctx->u32ChnDismode == VO_CHANNEL_PLAY_STEP) {
447                 for (i = 0; i < ctx->u32Screen1Chn; i++) {
448                     for (RK_S32 j = 0; j < MAX_STEP_FRAME_NUM; j++) {
449                         RK_MPI_VO_StepChn(VoLayer_second, i);
450                     }
451                 }
452 
453                 usleep(1000llu * 2000);
454 
455                 for (i = 0; i < ctx->u32Screen1Chn; i++) {
456                     RK_MPI_VO_ResumeChn(VoLayer_second, i);
457                 }
458            } else if (ctx->u32ChnDismode == VO_CHANNEL_PLAY_SPEED) {
459                 for (i = 0; i < ctx->u32Screen1Chn; i++) {
460                     RK_MPI_VO_SetChnFrameRate(VoLayer_second, i, ctx->u32DispFrmRt * ctx->u32DispFrmRtRatio);
461                 }
462 
463                 usleep(1000llu * 2000);
464 
465                 for (i = 0; i < ctx->u32Screen1Chn; i++) {
466                     RK_MPI_VO_ResumeChn(VoLayer_second, i);
467                 }
468             }
469         }
470     }
471 
472     return RK_NULL;
473 }
474 
475 static RK_S32 mpi_vo_init_sample(const TEST_VO_CTX_S *ctx, RK_S32 primRows , RK_S32 secondRows) {
476     VO_PUB_ATTR_S VoPubAttr;
477     VO_VIDEO_LAYER_ATTR_S stLayerAttr;
478     VO_CSC_S  VideoCSC;
479     VO_CHN_ATTR_S VoChnAttr[64];
480     VO_BORDER_S border;
481     RK_S32  i;
482     RK_U32 count = 0;
483     RK_U32 u32DispBufLen;
484     RK_U32 s32Ret;
485     RK_U32 u32DispWidth = ctx->u32DispWidth;
486     RK_U32 u32DispHeight = ctx->u32DispHeight;
487     RK_U32 u32ImageWidth = u32DispWidth;
488     RK_U32 u32ImageHeight = u32DispHeight;
489 
490     memset(&VoPubAttr, 0, sizeof(VO_PUB_ATTR_S));
491     memset(&stLayerAttr, 0, sizeof(VO_VIDEO_LAYER_ATTR_S));
492     memset(&VideoCSC, 0, sizeof(VO_CSC_S));
493     memset(&VoChnAttr, 0, sizeof(VoChnAttr));
494     memset(&border, 0, sizeof(VO_BORDER_S));
495 
496     VoPubAttr.enIntfType = VO_INTF_HDMI;
497     VoPubAttr.enIntfSync = VO_OUTPUT_1080P60;
498 
499     s32Ret = RK_MPI_VO_SetPubAttr(RK356X_VO_DEV_HD0, &VoPubAttr);
500     if (s32Ret != RK_SUCCESS) {
501         return s32Ret;
502     }
503     s32Ret = RK_MPI_VO_Enable(RK356X_VO_DEV_HD0);
504     if (s32Ret != RK_SUCCESS) {
505         return s32Ret;
506     }
507     if (ctx->stVoCfg.bDoubleScreen) {
508         VO_PUB_ATTR_S VoPubAttr1;
509         VoPubAttr1.enIntfType = VO_INTF_EDP;
510         VoPubAttr1.enIntfSync = VO_OUTPUT_1024x768_60;
511         VoPubAttr1.u32BgColor = 0x000000;
512         s32Ret = RK_MPI_VO_SetPubAttr(RK356X_VO_DEV_HD1, &VoPubAttr1);
513         if (s32Ret != RK_SUCCESS) {
514             return s32Ret;
515         }
516         s32Ret = RK_MPI_VO_Enable(RK356X_VO_DEV_HD1);
517         if (s32Ret != RK_SUCCESS) {
518             return s32Ret;
519         }
520 
521         s32Ret = RK_MPI_VO_GetLayerDispBufLen(VoLayer_second, &u32DispBufLen);
522         if (s32Ret != RK_SUCCESS) {
523             RK_LOGE("Get display buf len failed with error code %d!\n", s32Ret);
524             return s32Ret;
525         }
526         u32DispBufLen = 4;
527         s32Ret = RK_MPI_VO_SetLayerDispBufLen(VoLayer_second, u32DispBufLen);
528         if (s32Ret != RK_SUCCESS) {
529             return s32Ret;
530         }
531     }
532 
533     s32Ret = RK_MPI_VO_GetLayerDispBufLen(VoLayer, &u32DispBufLen);
534     if (s32Ret != RK_SUCCESS) {
535         RK_LOGE("Get display buf len failed with error code %d!\n", s32Ret);
536         return s32Ret;
537     }
538     u32DispBufLen = 4;
539     s32Ret = RK_MPI_VO_SetLayerDispBufLen(VoLayer, u32DispBufLen);
540     if (s32Ret != RK_SUCCESS) {
541         return s32Ret;
542     }
543     Sample_VO_GetDisplaySize(VoPubAttr.enIntfSync, &u32DispWidth, &u32DispHeight);
544     stLayerAttr.stDispRect.s32X = 0;
545     stLayerAttr.stDispRect.s32Y = 0;
546     stLayerAttr.stDispRect.u32Width = u32DispWidth;
547     stLayerAttr.stDispRect.u32Height = u32DispHeight;
548     stLayerAttr.stImageSize.u32Width = u32ImageWidth;
549     stLayerAttr.stImageSize.u32Height = u32ImageHeight;
550 
551     stLayerAttr.u32DispFrmRt = 30;
552     if (VoLayer == RK356X_VOP_LAYER_ESMART_0) {
553         stLayerAttr.enPixFormat = RK_FMT_YUV420SP;
554     } else {
555        stLayerAttr.enPixFormat = RK_FMT_RGBA8888;
556     }
557     VideoCSC.enCscMatrix = VO_CSC_MATRIX_IDENTITY;
558     VideoCSC.u32Contrast =  50;
559     VideoCSC.u32Hue = 50;
560     VideoCSC.u32Luma = 50;
561     VideoCSC.u32Satuature = 50;
562 
563     s32Ret = RK_MPI_VO_SetLayerAttr(VoLayer, &stLayerAttr);
564     if (s32Ret != RK_SUCCESS) {
565         return s32Ret;
566     }
567     s32Ret = RK_MPI_VO_EnableLayer(VoLayer);
568     if (s32Ret != RK_SUCCESS) {
569         return s32Ret;
570     }
571     s32Ret = RK_MPI_VO_SetLayerCSC(VoLayer, &VideoCSC);
572     if (s32Ret != RK_SUCCESS) {
573         return s32Ret;
574     }
575 
576     RK_S32 totalCH = primRows * primRows;
577     for (i = 0; i < totalCH; i++) {
578         VoChnAttr[i].bDeflicker = RK_FALSE;
579         VoChnAttr[i].u32Priority = 1;
580         VoChnAttr[i].stRect.s32X = (u32ImageWidth/primRows)*(i%primRows);
581         VoChnAttr[i].stRect.s32Y = (u32ImageHeight/primRows)*(i/primRows);
582         VoChnAttr[i].stRect.u32Width = u32ImageWidth/primRows;
583         VoChnAttr[i].stRect.u32Width = VoChnAttr[i].stRect.u32Width;
584         VoChnAttr[i].stRect.u32Height = u32ImageHeight/primRows;
585         VoChnAttr[i].stRect.u32Height = VoChnAttr[i].stRect.u32Height;
586     }
587 
588     for (i = 0; i < totalCH; i++) {
589         RK_S32 s32ret = RK_MPI_VO_SetChnAttr(VoLayer, i, &VoChnAttr[i]);
590         if (RK_SUCCESS != s32ret) {
591             RK_LOGE("vo set dev %d chn %d attr failed! \n", VoLayer, i);
592         }
593         border.bBorderEn = RK_TRUE;
594         border.stBorder.u32Color = 0x191970;
595         border.stBorder.u32LeftWidth = 2;
596         border.stBorder.u32RightWidth = 2;
597         border.stBorder.u32TopWidth = 2;
598         border.stBorder.u32BottomWidth = 2;
599         s32Ret = RK_MPI_VO_SetChnBorder(VoLayer, i, &border);
600         if (s32Ret != RK_SUCCESS) {
601             return s32Ret;
602         }
603     }
604 
605     if (ctx->stVoCfg.bDoubleScreen) {
606         u32DispWidth = ctx->u32Screen1DisplayWidth;
607         u32DispHeight = ctx->u32Screen1DisplayHeight;
608         u32ImageWidth = u32DispWidth;
609         u32ImageHeight = u32DispHeight;
610         Sample_VO_GetDisplaySize(VO_OUTPUT_1024x768_60, &u32DispWidth, &u32DispHeight);
611         stLayerAttr.stDispRect.s32X = 0;
612         stLayerAttr.stDispRect.s32Y = 0;
613         stLayerAttr.stDispRect.u32Width = u32DispWidth;
614         stLayerAttr.stDispRect.u32Height = u32DispHeight;
615         stLayerAttr.stImageSize.u32Width = u32ImageWidth;
616         stLayerAttr.stImageSize.u32Height = u32ImageHeight;
617 
618         stLayerAttr.u32DispFrmRt = 30;
619         if (VoLayer_second == RK356X_VOP_LAYER_ESMART_1) {
620             stLayerAttr.enPixFormat = RK_FMT_YUV420SP;
621         } else {
622            stLayerAttr.enPixFormat = RK_FMT_BGR888;
623         }
624 
625         s32Ret = RK_MPI_VO_SetLayerAttr(VoLayer_second, &stLayerAttr);
626         if (s32Ret != RK_SUCCESS) {
627             return s32Ret;
628         }
629         s32Ret = RK_MPI_VO_EnableLayer(VoLayer_second);
630         if (s32Ret != RK_SUCCESS) {
631             return s32Ret;
632         }
633         s32Ret = RK_MPI_VO_SetLayerCSC(VoLayer_second, &VideoCSC);
634         if (s32Ret != RK_SUCCESS) {
635             return s32Ret;
636         }
637 
638         totalCH = secondRows * secondRows;
639         for (i = 0; i < totalCH; i++) {
640             VoChnAttr[i].bDeflicker = RK_FALSE;
641             VoChnAttr[i].u32Priority = 1;
642             VoChnAttr[i].stRect.s32X = (u32ImageWidth/secondRows)*(i%secondRows);
643             VoChnAttr[i].stRect.s32Y = (u32ImageHeight/secondRows)*(i/secondRows);
644             VoChnAttr[i].stRect.u32Width = u32ImageWidth/secondRows;
645             VoChnAttr[i].stRect.u32Width = VoChnAttr[i].stRect.u32Width;
646             VoChnAttr[i].stRect.u32Height = u32ImageHeight/secondRows;
647             VoChnAttr[i].stRect.u32Height = VoChnAttr[i].stRect.u32Height;
648         }
649         /* demo Chn Priority test */
650         if (ctx->bChnPriority) {
651             VoChnAttr[0].u32Priority = 15;
652 
653             VoChnAttr[1].u32Priority = 10;
654             VoChnAttr[1].stRect.s32X = (u32ImageWidth/secondRows)*(1%secondRows) -  100;
655             VoChnAttr[1].stRect.s32Y = (u32ImageHeight/secondRows)*(1/secondRows) + 100;
656             VoChnAttr[1].stRect.u32Width = u32ImageWidth/secondRows + 200;
657             VoChnAttr[1].stRect.u32Width = VoChnAttr[1].stRect.u32Width;
658             VoChnAttr[1].stRect.u32Height = u32ImageWidth/secondRows + 200;
659             VoChnAttr[1].stRect.u32Height = VoChnAttr[1].stRect.u32Height;
660 
661             VoChnAttr[2].u32Priority = 5;
662         }
663 
664         for (i = 0; i < totalCH; i++) {
665             RK_S32 s32ret = RK_MPI_VO_SetChnAttr(VoLayer_second, i, &VoChnAttr[i]);
666             if (RK_SUCCESS != s32ret) {
667                 RK_LOGE("vo set dev %d chn %d attr failed! \n", VoLayer_second, i);
668             }
669             border.bBorderEn = RK_TRUE;
670             border.stBorder.u32Color = 0x191970;
671             border.stBorder.u32LeftWidth = 2;
672             border.stBorder.u32RightWidth = 2;
673             border.stBorder.u32TopWidth = 2;
674             border.stBorder.u32BottomWidth = 2;
675             s32Ret = RK_MPI_VO_SetChnBorder(VoLayer_second, i, &border);
676             if (s32Ret != RK_SUCCESS) {
677                 return s32Ret;
678             }
679         }
680     }
681 
682     return RK_SUCCESS;
683 }
684 
685 
686 static RK_S32 mpi_vo_deinit_sample(const TEST_VO_CTX_S *ctx) {
687     RK_S32 s32Ret = RK_SUCCESS;
688 
689     s32Ret = RK_MPI_VO_DisableLayer(VoLayer);
690     if (s32Ret != RK_SUCCESS) {
691         return s32Ret;
692     }
693     if (ctx->stVoCfg.bDoubleScreen) {
694         s32Ret = RK_MPI_VO_DisableLayer(VoLayer_second);
695         if (s32Ret != RK_SUCCESS) {
696             return s32Ret;
697         }
698     }
699 
700     s32Ret = RK_MPI_VO_Disable(RK356X_VO_DEV_HD0);
701     if (s32Ret != RK_SUCCESS) {
702         return s32Ret;
703     }
704     if (ctx->stVoCfg.bDoubleScreen) {
705         s32Ret = RK_MPI_VO_Disable(RK356X_VO_DEV_HD1);
706         if (s32Ret != RK_SUCCESS) {
707             return s32Ret;
708         }
709     }
710 
711     return s32Ret;
712 }
713 
714 
715 static RK_S32 open_config(TEST_VO_CTX_S *ctx) {
716     FILE *fp = RK_NULL;
717     RK_U32 u32Count = 0;
718     RK_U32 u32FileLen = 0;
719     RK_U32 u32Len = 0;
720     RK_S32 s32Ret = 0;
721     char *line = RK_NULL;
722     char *pBuffer = RK_NULL;
723 
724     if ((fp = fopen(ctx->cfgFileUri, "r")) == RK_NULL) {
725         RK_LOGE("Error! opening file");
726         return RK_FAILURE;
727     }
728     fseek(fp, 0L, SEEK_END);
729     u32FileLen = ftell(fp);
730     fseek(fp, 0, SEEK_SET);
731 
732     size_t sLen = 0;
733     size_t read = 0;
734     while (read = getline(&line, &sLen, fp) != -1) {
735         pBuffer = reinterpret_cast<char *>(malloc(strlen(line)));
736         RK_S32 len = strlen(line);
737         snprintf(pBuffer, strlen(line), "%s", line);
738         while (len) {
739             if (pBuffer[len] == '\r') {
740                 memcpy(&(pBuffer[len]), &(pBuffer[len + 1]), strlen(line) - len);
741             }
742             len--;
743         }
744         ctx->stParserCfg.srcFileUri[u32Count] = pBuffer;
745 
746         RK_LOGI("url %s", ctx->stParserCfg.srcFileUri[u32Count]);
747         u32Count++;
748 
749         if (u32Count >= VDEC_MAX_CHN_NUM)
750             break;
751     }
752 
753     fclose(fp);
754     return RK_SUCCESS;
755 }
756 
757 static RK_S32 close_config(TEST_VO_CTX_S *ctx) {
758     RK_S32 i;
759 
760     for (i = 0; i < VDEC_MAX_CHN_NUM; i++) {
761         if (ctx->stParserCfg.srcFileUri[i] != RK_NULL) {
762             rk_safe_free(ctx->stParserCfg.srcFileUri[i]);
763         }
764     }
765     return RK_SUCCESS;
766 }
767 
768 static RK_S32 creat_wbc(TEST_VO_CTX_S *ctx, RK_U32 u32Ch) {
769     RK_S32 s32Ret = RK_SUCCESS;
770     VO_WBC VoWbc = u32Ch;
771 
772     switch (ctx->u32WbcSourceType) {
773         case WBC_SOURCE_DEV:
774             ctx->stWbcCfg.stWbcSource.enSourceType = VO_WBC_SOURCE_DEV;
775             break;
776         default:
777             ctx->stWbcCfg.stWbcSource.enSourceType = VO_WBC_SOURCE_VIDEO;
778     }
779     s32Ret = RK_MPI_VO_SetWbcSource(VoWbc, &ctx->stWbcCfg.stWbcSource);
780     if (s32Ret != RK_SUCCESS) {
781         return s32Ret;
782     }
783     s32Ret = RK_MPI_VO_SetWbcAttr(VoWbc, &ctx->stWbcCfg.stWbcAttr);
784     if (s32Ret != RK_SUCCESS) {
785         return s32Ret;
786     }
787     s32Ret = RK_MPI_VO_EnableWbc(VoWbc);
788     if (s32Ret != RK_SUCCESS) {
789         return s32Ret;
790     }
791 
792     return RK_SUCCESS;
793 }
794 
795 static RK_S32 destory_wbc(RK_U32 u32Ch) {
796     VO_WBC VoWbc = u32Ch;
797     RK_MPI_VO_DisableWbc(VoWbc);
798 
799     return RK_SUCCESS;
800 }
801 
802 static RK_S32 creat_vdec(TEST_VO_CTX_S *ctx, RK_U32 u32Ch) {
803     RK_S32 s32Ret = RK_SUCCESS;
804     VDEC_CHN_ATTR_S pstAttr;
805     VDEC_CHN_PARAM_S stVdecParam;
806 
807     pstAttr.enMode = VIDEO_MODE_FRAME;
808     pstAttr.enType = ctx->stParserCfg.enCodecId;
809     pstAttr.u32PicWidth = ctx->stParserCfg.u32SrcWidth;
810     pstAttr.u32PicHeight = ctx->stParserCfg.u32SrcHeight;
811     pstAttr.u32FrameBufCnt = ctx->stVdecCfg.u32FrameBufferCnt;
812 
813     s32Ret = RK_MPI_VDEC_CreateChn(u32Ch, &pstAttr);
814     if (s32Ret != RK_SUCCESS) {
815         RK_LOGE("create %d vdec failed! ", u32Ch);
816         RK_LOGE(R"(enMode %d enType %d u32PicWidth %d u32PicHeight %d \
817             u32PicVirWidth %d u32PicVirHeight %d u32FrameBufCnt %d)", \
818             pstAttr.enMode, pstAttr.enType, pstAttr.u32PicWidth, pstAttr.u32PicHeight, \
819             pstAttr.u32PicVirWidth, pstAttr.u32PicVirHeight, pstAttr.u32FrameBufCnt);
820         return s32Ret;
821     }
822 
823     stVdecParam.stVdecVideoParam.enCompressMode = ctx->stVdecCfg.enCompressMode;
824     s32Ret = RK_MPI_VDEC_SetChnParam(u32Ch, &stVdecParam);
825     if (s32Ret != RK_SUCCESS) {
826         return s32Ret;
827     }
828     s32Ret = RK_MPI_VDEC_StartRecvStream(u32Ch);
829     if (s32Ret != RK_SUCCESS) {
830         return s32Ret;
831     }
832 
833     if (TEST_COMM_GetUriSchemeType(ctx->stParserCfg.srcFileUri[u32Ch]) != RK_URI_SCHEME_LOCAL) {
834         s32Ret = RK_MPI_VDEC_SetDisplayMode(u32Ch, VIDEO_DISPLAY_MODE_PREVIEW);
835     } else {
836         s32Ret = RK_MPI_VDEC_SetDisplayMode(u32Ch, VIDEO_DISPLAY_MODE_PLAYBACK);
837     }
838     if (s32Ret != RK_SUCCESS) {
839         return s32Ret;
840     }
841 
842     RK_LOGI("create %d vdec success", u32Ch);
843     return RK_SUCCESS;
844 }
845 
846 static RK_S32 screen1_process(TEST_VO_CTX_S *ctx, RK_U32 u32Index) {
847     RK_S32 s32Ret = RK_SUCCESS;
848     MPP_CHN_S stSrcChn, stDstChn;
849 
850     s32Ret = creat_vdec(ctx, u32Index);
851     if (s32Ret != RK_SUCCESS) {
852         RK_LOGE("creat %d ch vdec failed!", u32Index);
853         return s32Ret;
854     }
855 
856     s32Ret = RK_MPI_VO_EnableChn(ctx->stVoCfg.u32Screen1VoLayer, u32Index - ctx->u32Screen0Chn);
857     if (s32Ret != RK_SUCCESS) {
858         RK_LOGE("creat %d layer %d ch vo failed!",
859             ctx->stVoCfg.u32Screen1VoLayer, u32Index - ctx->u32Screen0Chn);
860         return s32Ret;
861     }
862     RK_LOGD("create vo layer %d ch %d", ctx->stVoCfg.u32Screen1VoLayer,  u32Index - ctx->u32Screen0Chn);
863 
864     stSrcChn.enModId = RK_ID_VDEC;
865     stSrcChn.s32DevId = 0;
866     stSrcChn.s32ChnId = u32Index;
867 
868     RK_LOGD("vdec  Ch %d", stSrcChn.s32ChnId);
869     stDstChn.enModId = RK_ID_VO;
870     stDstChn.s32DevId = ctx->stVoCfg.u32Screen1VoLayer;
871     stDstChn.s32ChnId = u32Index - ctx->u32Screen0Chn;
872 
873     RK_LOGD("VoLayer %d, voCh %d", ctx->stVoCfg.u32Screen1VoLayer,  u32Index - ctx->u32Screen0Chn);
874 
875     s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDstChn);
876     if (s32Ret != RK_SUCCESS) {
877         RK_LOGE("vdec and vo bind error");
878         return s32Ret;
879     }
880 
881     return RK_SUCCESS;
882 }
883 
884 static RK_S32 screen0_process(TEST_VO_CTX_S *ctx, RK_U32 u32Index) {
885     RK_S32 s32Ret = RK_SUCCESS;
886     MPP_CHN_S stSrcChn, stDstChn;
887 
888     s32Ret = creat_vdec(ctx, u32Index);
889     if (s32Ret != RK_SUCCESS) {
890         RK_LOGE("creat %d ch vdec failed!", u32Index);
891         return s32Ret;
892     }
893 
894     s32Ret = RK_MPI_VO_EnableChn(ctx->stVoCfg.u32Screen0VoLayer, u32Index);
895     if (s32Ret != RK_SUCCESS) {
896          RK_LOGE("creat %d layer %d ch vo failed!", ctx->stVoCfg.u32Screen0VoLayer, u32Index);
897          return s32Ret;
898     }
899 
900     RK_LOGD("create vo layer %d ch %d", ctx->stVoCfg.u32Screen0VoLayer, u32Index);
901 
902     stSrcChn.enModId = RK_ID_VDEC;
903     stSrcChn.s32DevId = 0;
904     stSrcChn.s32ChnId = u32Index;
905     RK_LOGD("vdec  Ch %d", stSrcChn.s32ChnId);
906 
907     stDstChn.enModId = RK_ID_VO;
908     stDstChn.s32DevId = ctx->stVoCfg.u32Screen0VoLayer;
909     stDstChn.s32ChnId = u32Index;
910     RK_LOGD("voLayer %d, voCh %d", stDstChn.s32DevId,  stDstChn.s32ChnId);
911 
912     s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDstChn);
913     if (s32Ret != RK_SUCCESS) {
914         RK_LOGE("vdec and vo bind error ");
915         return s32Ret;
916     }
917 
918     return RK_SUCCESS;
919 }
920 
921 static RK_S32 wbc_process(TEST_VO_CTX_S *ctx) {
922     RK_S32 s32Ret = RK_SUCCESS;
923     MPP_CHN_S stSrcChn, stDstChn;
924 
925     s32Ret = creat_wbc(ctx, 0);
926     if (s32Ret != RK_SUCCESS) {
927         RK_LOGE("create wbc failed");
928         return s32Ret;
929     }
930 
931     stSrcChn.enModId = RK_ID_WBC;
932     stSrcChn.s32DevId = 0;
933     stSrcChn.s32ChnId = 0;
934 
935     if (ctx->bEnWbcToVO) {
936         stDstChn.enModId   = RK_ID_VO;
937 
938         if (ctx->stWbcCfg.stWbcSource.u32SourceId == RK356X_VO_DEV_HD1) {
939             s32Ret = RK_MPI_VO_EnableChn(ctx->stVoCfg.u32Screen0VoLayer, ctx->u32Screen0Chn);
940             if (s32Ret != RK_SUCCESS) {
941                 RK_LOGE("creat %d layer %d ch vo failed!",
942                     ctx->stVoCfg.u32Screen0VoLayer, ctx->u32Screen0Chn);
943                 return s32Ret;
944             }
945             stDstChn.s32DevId  = ctx->stVoCfg.u32Screen0VoLayer;
946         } else {
947             s32Ret = RK_MPI_VO_EnableChn(ctx->stVoCfg.u32Screen1VoLayer, ctx->u32Screen1Chn);
948             if (s32Ret != RK_SUCCESS) {
949                 RK_LOGE("creat %d layer %d ch vo failed!",
950                     ctx->stVoCfg.u32Screen1VoLayer, ctx->u32Screen1Chn);
951                 return s32Ret;
952             }
953             stDstChn.s32DevId  = ctx->stVoCfg.u32Screen1VoLayer;
954         }
955         stDstChn.s32ChnId  = ctx->u32Screen1Chn;
956 
957         if (ctx->wbc_bind == RK_TRUE) {
958             s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDstChn);
959             if (s32Ret != RK_SUCCESS) {
960                 RK_LOGE("creat wbc bind vo failed!");
961                 return RK_FAILURE;
962             }
963         } else {
964             RK_LOGD("WBC enabled,but not bind");
965         }
966     }
967 
968     return RK_SUCCESS;
969 }
970 
971 
972 RK_S32 unit_mpi_voplay_test(TEST_VO_CTX_S *ctx) {
973     RK_U32  i, k;
974 
975     RK_S32 s32Ret = RK_SUCCESS;
976     RK_U32 u32MaxCh = 0;
977     RK_U32 u32step = 0;
978     RK_S32 u32VpssGrap = 0;
979 
980     MPP_CHN_S stSrcChn, stDstChn;
981 
982     TEST_VO_CTX_S mpiVdecCtx[VDEC_MAX_CHN_NUM];
983     TEST_VO_CTX_S mpiVencCtx[VENC_MAX_CHN_NUM];
984 
985     pthread_t vdecSendThread[VDEC_MAX_CHN_NUM];
986     pthread_t vdecGetThread[VDEC_MAX_CHN_NUM];
987 
988     pthread_t voThread;
989     RK_U32 u32VdecSendThreadNum = 0;
990     RK_U32 u32VdecGetThreadNum = 0;
991     RK_U32 u32Ch = 0;
992 
993     if (open_config(ctx) < 0) {
994         RK_LOGE("parser cfg failed!");
995         return RK_FAILURE;
996     }
997 
998     mpi_vo_init_sample(ctx, ctx->stVoCfg.u32Screen0Rows, ctx->stVoCfg.u32Screen1Rows);
999 
1000     u32MaxCh =  ctx->u32Screen1Chn + ctx->u32Screen0Chn;
1001 
1002     RK_LOGD("screen0Ch %d screen1Ch %d maxCh %d", ctx->u32Screen0Chn, ctx->u32Screen1Chn, u32MaxCh);
1003 
1004     for (i = 0; i < ctx->u32Screen0Chn; i++) {
1005         s32Ret = screen0_process(ctx, i);
1006         if (s32Ret != RK_SUCCESS) {
1007             RK_LOGE("screen0_process failed!", i);
1008             continue;
1009         }
1010         ctx->u32ChnIndex = i;
1011         memcpy(&(mpiVdecCtx[i]), ctx, sizeof(TEST_VO_CTX_S));
1012         u32VdecSendThreadNum++;
1013     }
1014 
1015 
1016     for (i = ctx->u32Screen0Chn; i < u32MaxCh; i++) {
1017             s32Ret = screen1_process(ctx, i);
1018             if (s32Ret != RK_SUCCESS) {
1019                 RK_LOGE("screen1_process failed!", i);
1020                 continue;
1021             }
1022             ctx->u32ChnIndex = i;
1023             memcpy(&(mpiVdecCtx[i]), ctx, sizeof(TEST_VO_CTX_S));
1024             u32VdecSendThreadNum++;
1025         }
1026 
1027     pthread_create(&voThread, 0, vochn_test_thread_func, reinterpret_cast<void *>(ctx));
1028 
1029     if (ctx->bEnWbc) {
1030         s32Ret = wbc_process(ctx);
1031         if (s32Ret == RK_SUCCESS) {
1032             RK_LOGE("wb process ok");
1033         } else {
1034             RK_LOGE("wb process failed");
1035         }
1036     }
1037 
1038     u32VdecSendThreadNum = 0;
1039     for (i = 0; i< ctx->u32Screen0Chn; i++) {
1040         pthread_join(vdecSendThread[u32VdecSendThreadNum], RK_NULL);
1041         u32VdecSendThreadNum++;
1042 
1043         stSrcChn.enModId = RK_ID_VDEC;
1044         stSrcChn.s32DevId = 0;
1045         stSrcChn.s32ChnId = i;
1046 
1047         stDstChn.enModId = RK_ID_VO;
1048         stDstChn.s32DevId = ctx->stVoCfg.u32Screen0VoLayer;
1049         stDstChn.s32ChnId = i;
1050 
1051         s32Ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDstChn);
1052         if (s32Ret != RK_SUCCESS) {
1053             return s32Ret;
1054         }
1055 
1056         s32Ret = RK_MPI_VDEC_StopRecvStream(i);
1057         if (s32Ret != RK_SUCCESS) {
1058             return s32Ret;
1059         }
1060         s32Ret = RK_MPI_VDEC_DestroyChn(i);
1061         if (s32Ret != RK_SUCCESS) {
1062             return s32Ret;
1063         }
1064         s32Ret = RK_MPI_VO_DisableChn(ctx->stVoCfg.u32Screen0VoLayer, i);
1065         if (s32Ret != RK_SUCCESS) {
1066             return s32Ret;
1067         }
1068     }
1069 
1070     for (i = ctx->u32Screen0Chn; i < u32MaxCh; i++) {
1071             pthread_join(vdecSendThread[u32VdecSendThreadNum], RK_NULL);
1072             u32VdecSendThreadNum++;
1073 
1074             stSrcChn.enModId = RK_ID_VDEC;
1075             stSrcChn.s32DevId = 0;
1076             stSrcChn.s32ChnId = i;
1077 
1078             stDstChn.enModId = RK_ID_VO;
1079             stDstChn.s32DevId = ctx->stVoCfg.u32Screen1VoLayer;
1080             stDstChn.s32ChnId = i;
1081 
1082             s32Ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDstChn);
1083             if (s32Ret != RK_SUCCESS) {
1084                 return s32Ret;
1085             }
1086             s32Ret = RK_MPI_VDEC_StopRecvStream(i);
1087             if (s32Ret != RK_SUCCESS) {
1088                 return s32Ret;
1089             }
1090             s32Ret = RK_MPI_VDEC_DestroyChn(i);
1091             if (s32Ret != RK_SUCCESS) {
1092                 return s32Ret;
1093             }
1094             s32Ret = RK_MPI_VO_DisableChn(ctx->stVoCfg.u32Screen1VoLayer, i);
1095             if (s32Ret != RK_SUCCESS) {
1096                 return s32Ret;
1097             }
1098         }
1099 
1100     if (ctx->bEnWbc) {
1101         if (ctx->bEnWbcToVO) {
1102             stSrcChn.enModId    = RK_ID_WBC;
1103             stSrcChn.s32DevId   = 0;
1104             stSrcChn.s32ChnId   = 0;
1105 
1106             stDstChn.enModId   = RK_ID_VO;
1107             stDstChn.s32DevId  = ctx->stVoCfg.u32Screen0VoLayer;
1108             stDstChn.s32ChnId  = 0;
1109 
1110             s32Ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDstChn);
1111             if (s32Ret != RK_SUCCESS) {
1112                 return s32Ret;
1113             }
1114             s32Ret = destory_wbc(0);
1115             if (s32Ret != RK_SUCCESS) {
1116                 return s32Ret;
1117             }
1118             s32Ret = RK_MPI_VO_DisableChn(ctx->stVoCfg.u32Screen0VoLayer, 0);
1119             if (s32Ret != RK_SUCCESS) {
1120                 return s32Ret;
1121             }
1122         }
1123     }
1124 
1125     mpi_vo_deinit_sample(ctx);
1126     close_config(ctx);
1127     return RK_SUCCESS;
1128 }
1129 
1130 static void Sample_VO_GetPictureData(VO_FRAME_INFO_S *pstFrameInfo, const char *pFileName) {
1131     RK_S32 u32Fd;
1132     RK_U32 u32Size, u32Bpp, u32Stride;
1133 
1134     switch (pstFrameInfo->enPixelFormat) {
1135     case RK_FMT_RGBA8888:
1136         u32Bpp = 4;
1137         break;
1138     case RK_FMT_RGB888:
1139     case RK_FMT_BGR888:
1140         u32Bpp = 3;
1141         break;
1142     case RK_FMT_YUV420SP:
1143     case RK_FMT_YUV420SP_VU:
1144         u32Bpp = 1;
1145         break;
1146     default:
1147         Sample_Print("%s Unsupported Format %d\n", __func__, pstFrameInfo->enPixelFormat);
1148     return;
1149     }
1150 
1151     u32Fd = open(pFileName, O_RDONLY);
1152     if (u32Fd < 0) {
1153         Sample_Print("cat not find file\n");
1154         return;
1155     }
1156     u32Size = lseek(u32Fd, 0, SEEK_END);
1157     lseek(u32Fd, 0, SEEK_SET);
1158 
1159     Sample_Print("%dx%d %dx%d\n",
1160                   pstFrameInfo->u32Width, pstFrameInfo->u32Height,
1161                   pstFrameInfo->u32VirWidth, pstFrameInfo->u32VirHeight);
1162 
1163     if (pstFrameInfo->u32Width != pstFrameInfo->u32VirWidth) {
1164         u32Stride = pstFrameInfo->u32VirWidth * u32Bpp;
1165 
1166         for (RK_S32 i = 0; i < pstFrameInfo->u32Height; i++)
1167             read(u32Fd, reinterpret_cast<RK_S8 *>(pstFrameInfo->pData) + u32Stride * i,
1168                         pstFrameInfo->u32Width * u32Bpp);
1169 
1170             if (pstFrameInfo->enPixelFormat == RK_FMT_YUV420SP ||
1171                 pstFrameInfo->enPixelFormat == RK_FMT_YUV420SP_VU) {
1172                 for (RK_S32 i = 0; i < pstFrameInfo->u32Height / 2; i++)
1173                     read(u32Fd, reinterpret_cast<RK_S8 *>(pstFrameInfo->pData)
1174                                 + u32Stride * pstFrameInfo->u32VirHeight + i * u32Stride,
1175                                 pstFrameInfo->u32Width);
1176                 }
1177             } else {
1178                 read(u32Fd, pstFrameInfo->pData, u32Size);
1179             }
1180             close(u32Fd);
1181 }
1182 
1183 static void filewrite(void *buf, uint32_t size, char *file) {
1184     int fd = open(file, O_WRONLY | O_CREAT);
1185 
1186     if (fd < 0) {
1187         printf("cat not open file\n");
1188         return;
1189     }
1190 
1191     write(fd, buf, size);
1192     close(fd);
1193 }
1194 
1195 static void Sample_VO_DrawUI(VO_FRAME_INFO_S *pstFrameInfo, RK_S32 format, RK_S32 value) {
1196     RK_S32 PixelVal0, PixelVal1;
1197     RK_S8 *pData = reinterpret_cast<RK_S8 *>(pstFrameInfo->pData);
1198     RK_U32 u32Offset;
1199 
1200     for (RK_S32 i = 0; i < pstFrameInfo->u32Height; i++) {
1201         for (RK_S32 j = 0; j < pstFrameInfo->u32Width; j++) {
1202             u32Offset = i * pstFrameInfo->u32VirWidth + j;
1203             if (format == RK_FMT_BGRA5551) {
1204                 u32Offset = u32Offset * 2;
1205                 PixelVal0 = value | 0x8000;
1206                 PixelVal1 = value & 0x7FFF;
1207             } else if (format == RK_FMT_BGRA8888) {
1208                 u32Offset = u32Offset * 4;
1209                 PixelVal0 = 0x000000FF;
1210             } else {
1211                 continue;
1212             }
1213 
1214             if (j < pstFrameInfo->u32Width / 2) {
1215                 if (format == RK_FMT_BGRA5551) {
1216                     pData[u32Offset] = PixelVal0 & 0xff;
1217                     pData[u32Offset + 1] = (PixelVal0 >> 8) & 0xff;
1218                 } else if (format == RK_FMT_BGRA8888) {
1219                     pData[u32Offset] = PixelVal0 & 0xff;
1220                     pData[u32Offset + 1] = (PixelVal0 >> 8) & 0xff;
1221                     pData[u32Offset + 1] = (PixelVal0 >> 16) & 0xff;
1222                     pData[u32Offset + 1] = (PixelVal0 >> 24) & 0xff;
1223                 }
1224             } else {
1225                 if (format == RK_FMT_BGRA5551) {
1226                     pData[u32Offset] = PixelVal1 & 0xff;
1227                     pData[u32Offset + 1] = (PixelVal1 >> 8) & 0xff;
1228                 } else if (format == RK_FMT_BGRA8888) {
1229                     pData[u32Offset] = PixelVal0 & 0xff;
1230                     pData[u32Offset + 1] = (PixelVal0 >> 8) & 0xff;
1231                     pData[u32Offset + 1] = (PixelVal0 >> 16) & 0xff;
1232                     pData[u32Offset + 1] = (PixelVal0 >> 24) & 0xff;
1233                }
1234             }
1235         }
1236     }
1237 }
1238 
1239 static RK_S32 Sample_VO_MultiGFXLayer_Start(VO_LAYER VoLayer, RK_U32 u32Layers) {
1240     VO_VIDEO_LAYER_ATTR_S    stLayerAttr;
1241     VO_CHN_ATTR_S            stChnAttr;
1242     VO_CHN_PARAM_S           stParam;
1243     VO_BORDER_S              stBorder;
1244     RK_U32                   u32Row, u32Column, i;
1245     RK_U32                   u32WinWidth, u32WinHeight;
1246     RK_S32                   s32Ret = RK_SUCCESS;
1247 
1248     s32Ret = RK_MPI_VO_GetLayerAttr(VoLayer, &stLayerAttr);
1249     if (s32Ret != RK_SUCCESS) {
1250         Sample_Print("[%s] Get Layer Attr failed\n", __func__);
1251         return RK_FAILURE;
1252     }
1253 
1254     for (i = 0; i < u32Layers; i++) {
1255         stChnAttr.stRect.s32X = 0;
1256         stChnAttr.stRect.s32Y = 0;
1257         stChnAttr.stRect.u32Width = stLayerAttr.stDispRect.u32Width;
1258         stChnAttr.stRect.u32Height = stLayerAttr.stDispRect.u32Height;
1259         stChnAttr.u32Priority = i;
1260         if (i == 0) {
1261             stChnAttr.u32FgAlpha = 128;
1262             stChnAttr.u32BgAlpha = 0;
1263         } else {
1264             stChnAttr.u32FgAlpha = 0;
1265             stChnAttr.u32BgAlpha = 128;
1266         }
1267 
1268         s32Ret = RK_MPI_VO_SetChnAttr(VoLayer, i, &stChnAttr);
1269         if (s32Ret != RK_SUCCESS) {
1270             Sample_Print("[%s] set chn Attr failed\n", __func__);
1271             return RK_FAILURE;
1272         }
1273 
1274         s32Ret = RK_MPI_VO_EnableChn(VoLayer, i);
1275         if (s32Ret != RK_SUCCESS) {
1276             Sample_Print("[%s] Enalbe chn failed\n", __func__);
1277             return RK_FAILURE;
1278         }
1279     }
1280 
1281     Sample_Print("[%s] success\n", __func__);
1282     return s32Ret;
1283 }
1284 
1285 static RK_S32 Sample_VO_MultiWindowns_Start(TEST_VO_CTX_S *ctx) {
1286     VO_VIDEO_LAYER_ATTR_S    stLayerAttr;
1287     VO_CHN_ATTR_S            stChnAttr;
1288     VO_CHN_PARAM_S           stChnParam;
1289     VO_BORDER_S              stBorder;
1290     RK_U32                   u32Row, u32Column, i;
1291     RK_U32                   u32WinWidth, u32WinHeight;
1292     RK_U32                   u32X, u32Y;
1293     RK_S32                   s32Ret = RK_SUCCESS;
1294     RK_U32 disp_width = 1920;
1295     RK_U32 disp_height = 1080;
1296 
1297     if (ctx->u32Windows <= 2)
1298         u32Row = 1;
1299     else if (ctx->u32Windows <= 4)
1300         u32Row = 2;
1301     else if (ctx->u32Windows <= 9)
1302         u32Row = 3;
1303     else if (ctx->u32Windows <= 16)
1304         u32Row = 4;
1305     else if (ctx->u32Windows <= 36)
1306         u32Row = 6;
1307     else if (ctx->u32Windows <= 64)
1308         u32Row = 8;
1309     else
1310         return RK_FAILURE;
1311 
1312     u32Column = ctx->u32Windows / u32Row + ((ctx->u32Windows % u32Row)? 1: 0);
1313 
1314     s32Ret = RK_MPI_VO_GetLayerAttr(ctx->VoLayer, &stLayerAttr);
1315 
1316     if (s32Ret != RK_SUCCESS)
1317         return RK_FAILURE;
1318 
1319     u32WinWidth = stLayerAttr.stDispRect.u32Width / u32Column;
1320     u32WinHeight = stLayerAttr.stDispRect.u32Height / u32Row;
1321 
1322     for (i = 0; i <ctx->u32Windows; i++) {
1323         u32X = i % u32Column;
1324         u32Y = i / u32Column;
1325         stChnAttr.stRect.s32X = stLayerAttr.stDispRect.s32X + u32X * u32WinWidth;
1326         stChnAttr.stRect.s32Y = stLayerAttr.stDispRect.s32Y + u32Y * u32WinHeight;
1327         stChnAttr.stRect.u32Width = u32WinWidth;
1328         stChnAttr.stRect.u32Height = u32WinHeight;
1329         stChnAttr.u32FgAlpha = 255;
1330         stChnAttr.u32BgAlpha = 0;
1331         // set priority
1332         stChnAttr.u32Priority = 1;
1333 
1334         s32Ret = RK_MPI_VO_SetChnAttr(ctx->VoLayer, i, &stChnAttr);
1335         if (s32Ret != RK_SUCCESS)
1336             return RK_FAILURE;
1337 
1338         // set video aspect ratio
1339         if (ctx->uEnMode == 2) {
1340             stChnParam.stAspectRatio.enMode = ASPECT_RATIO_MANUAL;
1341             stChnParam.stAspectRatio.stVideoRect.s32X = stLayerAttr.stDispRect.s32X + u32X * u32WinWidth;
1342             stChnParam.stAspectRatio.stVideoRect.s32Y = stLayerAttr.stDispRect.s32Y + u32Y * u32WinHeight;
1343             stChnParam.stAspectRatio.stVideoRect.u32Width = u32WinWidth/2;
1344             stChnParam.stAspectRatio.stVideoRect.u32Height = u32WinHeight/2;
1345             RK_MPI_VO_SetChnParam(ctx->VoLayer, i, &stChnParam);
1346         } else if (ctx->uEnMode == 1) {
1347             stChnParam.stAspectRatio.enMode = ASPECT_RATIO_AUTO;
1348             stChnParam.stAspectRatio.stVideoRect.s32X = stLayerAttr.stDispRect.s32X + u32X * u32WinWidth;
1349             stChnParam.stAspectRatio.stVideoRect.s32Y = stLayerAttr.stDispRect.s32Y + u32Y * u32WinHeight;
1350             stChnParam.stAspectRatio.stVideoRect.u32Width = u32WinWidth;
1351             stChnParam.stAspectRatio.stVideoRect.u32Height = u32WinHeight;
1352             RK_MPI_VO_SetChnParam(ctx->VoLayer, i, &stChnParam);
1353         }
1354 
1355         stBorder.stBorder.u32Color = 0xFFFAFA;
1356         stBorder.stBorder.u32TopWidth = ctx->stBorderCfg.u32TopWidth;
1357         stBorder.stBorder.u32BottomWidth = ctx->stBorderCfg.u32BottomWidth;
1358         stBorder.stBorder.u32LeftWidth = ctx->stBorderCfg.u32LeftWidth;
1359         stBorder.stBorder.u32RightWidth = ctx->stBorderCfg.u32RightWidth;
1360         stBorder.bBorderEn = ctx->bBorder;
1361         s32Ret = RK_MPI_VO_SetChnBorder(ctx->VoLayer, i, &stBorder);
1362         if (s32Ret != RK_SUCCESS)
1363             return RK_FAILURE;
1364 
1365         s32Ret = RK_MPI_VO_EnableChn(ctx->VoLayer, i);
1366         if (s32Ret != RK_SUCCESS)
1367             return RK_FAILURE;
1368     }
1369 
1370     return s32Ret;
1371 }
1372 
1373 static RK_S32 Sample_VO_MultiWindowns_Stop(VO_LAYER VoLayer, RK_U32 u32Windows) {
1374     RK_U32 i;
1375     RK_S32 s32Ret = RK_SUCCESS;
1376 
1377     for (i = 0; i < u32Windows; i++) {
1378         s32Ret = RK_MPI_VO_DisableChn(VoLayer, i);
1379         if (s32Ret != RK_SUCCESS)
1380             return RK_FAILURE;
1381     }
1382 
1383     return s32Ret;
1384 }
1385 
1386 static RK_S32 Sample_VO_StartDev(VO_DEV VoDev, VO_PUB_ATTR_S *pstPubAttr) {
1387     RK_S32 s32Ret = RK_SUCCESS;
1388 
1389     s32Ret = RK_MPI_VO_SetPubAttr(VoDev, pstPubAttr);
1390     if (s32Ret != RK_SUCCESS)
1391         return RK_FAILURE;
1392 
1393     s32Ret = RK_MPI_VO_Enable(VoDev);
1394     if (s32Ret != RK_SUCCESS)
1395         return RK_FAILURE;
1396 
1397      return s32Ret;
1398 }
1399 
1400 static RK_S32 Sample_VO_StopDev(VO_DEV VoDev) {
1401     RK_S32 s32Ret = RK_SUCCESS;
1402 
1403     s32Ret = RK_MPI_VO_Disable(VoDev);
1404     if (s32Ret != RK_SUCCESS)
1405         return RK_FAILURE;
1406 
1407     return s32Ret;
1408 }
1409 
1410 static RK_S32 Sample_VO_StartLayer(VO_LAYER VoLayer, const VO_VIDEO_LAYER_ATTR_S *pstLayerAttr) {
1411     RK_S32 s32Ret = RK_SUCCESS;
1412 
1413     s32Ret = RK_MPI_VO_SetLayerAttr(VoLayer, pstLayerAttr);
1414     if (s32Ret != RK_SUCCESS)
1415         return RK_FAILURE;
1416 
1417     s32Ret = RK_MPI_VO_EnableLayer(VoLayer);
1418     if (s32Ret != RK_SUCCESS)
1419         return RK_FAILURE;
1420 
1421     return s32Ret;
1422 }
1423 
1424 static RK_S32 Sample_VO_StopLayer(VO_LAYER VoLayer) {
1425     RK_S32 s32Ret = RK_SUCCESS;
1426 
1427     s32Ret = RK_MPI_VO_DisableLayer(VoLayer);
1428     if (s32Ret != RK_SUCCESS)
1429         return RK_FAILURE;
1430 
1431     return s32Ret;
1432 }
1433 
1434 static RK_S32 Sample_VO_SetVFrame(VIDEO_FRAME_INFO_S *pVFrame,
1435                                    RK_U32              u32Width,
1436                                    RK_U32              u32Height,
1437                                    RK_U32              u32VirWidth,
1438                                    RK_U32              u32VirHeight,
1439                                    PIXEL_FORMAT_E      enPixelFormat,
1440                                    RK_VOID             *pMblk) {
1441     RK_S32 s32Ret = RK_SUCCESS;
1442 
1443     if (pVFrame == NULL && pMblk == NULL)
1444         return RK_FAILURE;
1445 
1446     if (!u32Width || !u32Height ||
1447         !u32VirWidth || !u32VirHeight ||
1448         enPixelFormat >= RK_FMT_BUTT)
1449         s32Ret = RK_FAILURE;
1450 
1451     pVFrame->stVFrame.pMbBlk = pMblk;
1452     pVFrame->stVFrame.u32Width = u32Width;
1453     pVFrame->stVFrame.u32Height = u32Height;
1454     pVFrame->stVFrame.u32VirWidth = u32VirWidth;
1455     pVFrame->stVFrame.u32VirHeight = u32VirHeight;
1456     pVFrame->stVFrame.enPixelFormat = enPixelFormat;
1457 
1458     return s32Ret;
1459 }
1460 static RK_S32 Sample_VO_BindVoWbc(VO_DEV VoWbcDev, VO_LAYER VoLayer, VO_CHN VoChn) {
1461     MPP_CHN_S stSrcChn, stDestChn;
1462 
1463     stSrcChn.enModId    = RK_ID_WBC;
1464     stSrcChn.s32DevId   = VoWbcDev;
1465     stSrcChn.s32ChnId   = 0;
1466 
1467     stDestChn.enModId   = RK_ID_VO;
1468     stDestChn.s32ChnId  = VoChn;
1469     stDestChn.s32DevId  = VoLayer;
1470 
1471     return RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
1472 }
1473 
1474 static RK_S32 Sample_VO_UnBindVoWbc(VO_DEV VoWbcDev, VO_LAYER VoLayer, VO_CHN VoChn) {
1475     MPP_CHN_S stSrcChn, stDestChn;
1476 
1477     stSrcChn.enModId    = RK_ID_WBC;
1478     stSrcChn.s32DevId   = VoWbcDev;
1479     stSrcChn.s32ChnId   = 0;
1480 
1481     stDestChn.enModId   = RK_ID_VO;
1482     stDestChn.s32ChnId  = VoChn;
1483     stDestChn.s32DevId  = VoLayer;
1484 
1485     return RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
1486 }
1487 
1488 static RK_S32 Sample_VO_CreateGFXData(RK_U32 u32Width, RK_U32 u32Height, RK_U32 foramt, RK_U32 value, RK_VOID **pMblk) {
1489     VO_FRAME_INFO_S stFrameInfo;
1490     RK_U32 u32BuffSize;
1491 
1492     u32BuffSize = RK_MPI_VO_CreateGraphicsFrameBuffer(u32Width, u32Height, foramt, pMblk);
1493     if (u32BuffSize == 0) {
1494         Sample_Print("can not create gfx buffer\n");
1495         return RK_FAILURE;
1496     }
1497 
1498     RK_MPI_VO_GetFrameInfo(*pMblk, &stFrameInfo);
1499     if (foramt == RK_FMT_RGB888) {
1500         if (u32Width == 1920 && u32Height == 1080 && value == 0)
1501             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_1080P_RGB_0.yuv");
1502         else if (u32Width == 1920 && u32Height == 1080 && value == 1 )
1503             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_1080P_RGB_1.yuv");
1504         else if (u32Width == 1024 && u32Height == 768 && value == 0 )
1505             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_768P_RGB_0.yuv");
1506         else if (u32Width == 1024 && u32Height == 768 && value == 1)
1507             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_768P_RGB_1.yuv");
1508         else
1509             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_480P_RGB.yuv");
1510     } else if (foramt == RK_FMT_RGBA8888) {
1511         if (u32Width == 1920 && u32Height == 1080 && value == 0 )
1512             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_1080P_RGBA.yuv");
1513         else if (u32Width == 1920 && u32Height == 1080 && value == 1 )
1514             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_1080P2_RGBA.yuv");
1515         else if (u32Width == 1024 && u32Height == 768)
1516             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_768P_RGBA.yuv");
1517         else
1518             Sample_VO_GetPictureData(&stFrameInfo, "/userdata/test/vo/res_480P_RGBA.yuv");
1519     } else {
1520         Sample_VO_DrawUI(&stFrameInfo, foramt, value);
1521     }
1522 
1523     return RK_SUCCESS;
1524 }
1525 
1526 static RK_VOID * Sample_VO_SendPicture_Mosaic(RK_VOID *pArg) {
1527     VoThreadParam *pParam = reinterpret_cast<VoThreadParam *>(pArg);
1528     VIDEO_FRAME_INFO_S *pstVFrame;
1529     RK_VOID *pMblk, *pMblk_1080P, *pMblk_1080P2, *pMblk_768P, *pMblk_480P, *pMblk_G0, *pMblk_G1;
1530     RK_U32 count;
1531 
1532     Sample_VO_CreateGFXData(1920, 1080, RK_FMT_RGBA8888, 0, &pMblk_1080P);
1533     Sample_VO_CreateGFXData(1920, 1080, RK_FMT_RGBA8888, 1, &pMblk_1080P2);
1534     Sample_VO_CreateGFXData(720,  480,  RK_FMT_RGBA8888, 0, &pMblk_480P);
1535     Sample_VO_CreateGFXData(1024, 768,  RK_FMT_RGBA8888, 0, &pMblk_768P);
1536     Sample_VO_CreateGFXData(1920, 1080, RK_FMT_BGRA5551, 0x1F, &pMblk_G0);
1537     Sample_VO_CreateGFXData(1920, 1080, RK_FMT_BGRA5551, 0x1F << 10, &pMblk_G1);
1538 
1539     pstVFrame = reinterpret_cast<VIDEO_FRAME_INFO_S *>(malloc(sizeof(VIDEO_FRAME_INFO_S)));
1540 
1541     while (!pParam->u32Exit) {
1542         if (pParam->VoVideoLayer >= 0) {
1543             for (RK_U32 i = 0; i < pParam->u32VideoWindows; i++) {
1544                 if (pParam->u32VideoWindows > 10) {
1545                     pstVFrame->stVFrame.u32Width = 720;
1546                     pstVFrame->stVFrame.u32Height = 480;
1547                     pstVFrame->stVFrame.u32VirWidth = 720;
1548                     pstVFrame->stVFrame.u32VirHeight = 480;
1549                     pstVFrame->stVFrame.enPixelFormat = RK_FMT_RGBA8888;
1550                     pMblk = pMblk_480P;
1551                 } else if (count % 2) {
1552                     pMblk = pMblk_1080P;
1553                     pstVFrame->stVFrame.u32Width = 1920;
1554                     pstVFrame->stVFrame.u32Height = 1080;
1555                     pstVFrame->stVFrame.u32VirWidth = 1920;
1556                     pstVFrame->stVFrame.u32VirHeight = 1080;
1557                     pstVFrame->stVFrame.enPixelFormat = RK_FMT_RGBA8888;
1558                     pstVFrame->stVFrame.pMbBlk = pMblk;
1559                 } else {
1560                     pMblk = pMblk_1080P2;
1561                     pstVFrame->stVFrame.u32Width = 1920;
1562                     pstVFrame->stVFrame.u32Height = 1080;
1563                     pstVFrame->stVFrame.u32VirWidth = 1920;
1564                     pstVFrame->stVFrame.u32VirHeight = 1080;
1565                     pstVFrame->stVFrame.enPixelFormat = RK_FMT_RGBA8888;
1566                     pstVFrame->stVFrame.pMbBlk = pMblk;
1567                 }
1568 
1569                 pstVFrame->stVFrame.pMbBlk = pMblk;
1570                 RK_MPI_VO_SendFrame(pParam->VoVideoLayer, i, pstVFrame, 0);
1571             }
1572         }
1573         if (pParam->VOGfxLayer >= 0) {
1574             for (RK_U32 i = 0; i < pParam->u32GFXLayers; i++) {
1575                 if (i == 0)
1576                     pMblk = pMblk_G0;
1577                 else if (i == 1)
1578                     pMblk = pMblk_G1;
1579                 else
1580                    continue;
1581 
1582                 pstVFrame->stVFrame.u32Width = 1920;
1583                 pstVFrame->stVFrame.u32Height = 1080;
1584                 pstVFrame->stVFrame.u32VirWidth = 1920;
1585                 pstVFrame->stVFrame.u32VirHeight = 1080;
1586                 pstVFrame->stVFrame.enPixelFormat = RK_FMT_BGRA5551;
1587                 pstVFrame->stVFrame.pMbBlk = pMblk;
1588                 RK_MPI_VO_SendFrame(pParam->VOGfxLayer, i, pstVFrame, 0);
1589             }
1590         }
1591         usleep(1000000);
1592         count++;
1593     }
1594     free(pstVFrame);
1595     RK_MPI_VO_DestroyGraphicsFrameBuffer(pMblk);
1596     Sample_Print("%s exit\n", __func__);
1597 
1598     return NULL;
1599 }
1600 
1601 static RK_VOID Sample_VO_StartSendPicture_Mosaic(pthread_t *pThreadID, VoThreadParam *pstParam) {
1602     pthread_create(pThreadID, NULL, Sample_VO_SendPicture_Mosaic, reinterpret_cast<RK_VOID *>(pstParam));
1603 }
1604 
1605 static RK_VOID Sample_VO_StopSendPicture_Mosaic(pthread_t tThreadID, VoThreadParam *pstParam) {
1606     pstParam->u32Exit = 1;
1607     pthread_join(tThreadID, RK_NULL);
1608 }
1609 
1610 static RK_S32 Sample_VO_Demo_Video_Mosaic(TEST_VO_CTX_S *ctx) {
1611     VO_PUB_ATTR_S            stVoPubAttr;
1612     VO_VIDEO_LAYER_ATTR_S    stLayerAttr;
1613     RK_U32                   u32DispWidth, u32DispHeight;
1614     RK_U32                   u32ImageWidth, u32ImageHeight;
1615     VO_LAYER                 VoLayer;
1616     VO_DEV                   VoDev;
1617     RK_S32                   u32Windows;
1618     RK_U32                   u32Fps, i;
1619     pthread_t                tThreadID;
1620     RK_S32                   s32Ret = RK_SUCCESS;
1621     VO_LAYER_MODE_E          Vo_layer_mode;
1622     VoThreadParam            stThreadParam;
1623     PIXEL_FORMAT_E           video_format;
1624 
1625     VoDev = ctx->VoDev;
1626     u32Windows = ctx->u32Windows;
1627     u32Fps =  ctx->u32DispFrmRt;
1628     VoLayer = ctx->VoLayer;
1629     for (RK_U32 j = 0; j < VDEC_ARRAY_ELEMS(testPixelFormat); j++) {
1630         if (ctx->s32PixFormat == testPixelFormat[j].index) {
1631             video_format =  testPixelFormat[j].format;
1632             break;
1633         }
1634     }
1635 
1636     Sample_Print("%s VoDev %u Windows %u video_format %x\n", __func__, VoDev, u32Windows, video_format);
1637 
1638     /* Bind Layer */
1639     switch (ctx->VoLayerMode) {
1640         case 0:
1641             Vo_layer_mode = VO_LAYER_MODE_CURSOR;
1642             break;
1643         case 1:
1644             Vo_layer_mode = VO_LAYER_MODE_GRAPHIC;
1645             break;
1646         case 2:
1647             Vo_layer_mode = VO_LAYER_MODE_VIDEO;
1648             break;
1649         default:
1650             Vo_layer_mode = VO_LAYER_MODE_VIDEO;
1651     }
1652 
1653     RK_MPI_VO_BindLayer(VoLayer, VoDev, Vo_layer_mode);
1654 
1655     switch (ctx->enIntfType) {
1656         case DISPLAY_TYPE_VGA:
1657             stVoPubAttr.enIntfType = VO_INTF_VGA;
1658             break;
1659         case DISPLAY_TYPE_HDMI:
1660             stVoPubAttr.enIntfType = VO_INTF_HDMI;
1661             break;
1662         case DISPLAY_TYPE_EDP:
1663             stVoPubAttr.enIntfType = VO_INTF_EDP;
1664             break;
1665         case DISPLAY_TYPE_DP:
1666             stVoPubAttr.enIntfType = VO_INTF_DP;
1667             break;
1668         case DISPLAY_TYPE_HDMI_EDP :
1669             stVoPubAttr.enIntfType = VO_INTF_HDMI | VO_INTF_EDP;
1670             break;
1671         default:
1672             stVoPubAttr.enIntfType = VO_INTF_HDMI;
1673             Sample_Print("IntfType not set,use INTF_HDMI default\n");
1674     }
1675 
1676     for (i = 0; i < ARRAY_LENGTH(test_mode_table); i++) {
1677         if (ctx->enIntfSync == test_mode_table[i].mode)
1678             break;
1679     }
1680 
1681     if (i == ARRAY_LENGTH(test_mode_table)) {
1682         Sample_Print("%s not found supported mode in test mode_table\n", __func__);
1683         return RK_FAILURE;
1684     }
1685 
1686     stVoPubAttr.enIntfSync = test_mode_table[i].enIntfSync;
1687     stVoPubAttr.u32BgColor = 0x000000;
1688     Sample_VO_StartDev(VoDev, &stVoPubAttr);
1689 
1690      /* Enable Layer */
1691     stLayerAttr.enPixFormat           = video_format;
1692     stLayerAttr.stDispRect.s32X       = 0;
1693     stLayerAttr.stDispRect.s32Y       = 0;
1694     Sample_VO_GetDisplaySize(stVoPubAttr.enIntfSync, &u32DispWidth, &u32DispHeight);
1695 
1696     u32ImageWidth  = u32DispWidth;
1697     u32ImageHeight = u32DispHeight;
1698     stLayerAttr.stDispRect.u32Width   = u32DispWidth;
1699     stLayerAttr.stDispRect.u32Height  = u32DispHeight;
1700     stLayerAttr.stImageSize.u32Width  = u32ImageWidth;
1701     stLayerAttr.stImageSize.u32Height = u32ImageHeight;
1702     stLayerAttr.u32DispFrmRt          = ctx->u32DispFrmRt;
1703 
1704     Sample_VO_StartLayer(VoLayer, &stLayerAttr);
1705     Sample_VO_MultiWindowns_Start(ctx);
1706     stThreadParam.u32Exit = 0;
1707     stThreadParam.u32VideoWindows = u32Windows;
1708     stThreadParam.VoVideoLayer = VoLayer;
1709     stThreadParam.VOGfxLayer = -1;
1710     stThreadParam.u32GFXLayers = -1;
1711 
1712     Sample_Print("Start Send Picture\n");
1713     Sample_VO_StartSendPicture_Mosaic(&tThreadID, &stThreadParam);
1714 
1715     while (1) {
1716         Sample_Print("Press 'q' to quit\n");
1717         if (getchar() == 'q')
1718             break;
1719     }
1720 
1721     Sample_VO_StopSendPicture_Mosaic(tThreadID, &stThreadParam);
1722     Sample_VO_MultiWindowns_Stop(VoLayer, u32Windows);
1723     Sample_VO_StopLayer(VoLayer);
1724     Sample_VO_StopDev(VoDev);
1725  end:
1726     RK_MPI_VO_UnBindLayer(VoLayer, VoDev);
1727     RK_MPI_VO_CloseFd();
1728 
1729     return s32Ret;
1730 }
1731 
1732 static RK_S32 Sample_VO_Demo_UI(TEST_VO_CTX_S *ctx) {
1733     VO_PUB_ATTR_S            stVoPubAttr;
1734     VO_VIDEO_LAYER_ATTR_S    stLayerAttr;
1735     VIDEO_FRAME_INFO_S       *pstVFrame;
1736     RK_U32                   u32DispWidth, u32DispHeight;
1737     RK_U32                   u32ImgWidth, u32ImgHeight;
1738     VO_LAYER                 VoLayer;
1739     RK_S32                   VoDev;
1740     RK_S32                   VoDev_second;
1741     VO_LAYER                 VoLayer_second;
1742     RK_VOID *pMblk_1080P_1   = RK_NULL;
1743     RK_VOID *pMblk_1080P_2   = RK_NULL;
1744     RK_VOID *pMblk_768P_1    = RK_NULL;
1745     RK_VOID *pMblk_768P_2    = RK_NULL;
1746     RK_U32   s32Ret          = RK_SUCCESS;
1747     RK_S32   count           = 0;
1748     PIXEL_FORMAT_E           plane_format;
1749 
1750     for (RK_U32 j = 0; j < VDEC_ARRAY_ELEMS(testPixelFormat); j++) {
1751         if (ctx->s32PixFormat == testPixelFormat[j].index) {
1752             plane_format =  testPixelFormat[j].format;
1753             break;
1754         }
1755     }
1756 
1757     pstVFrame = reinterpret_cast<VIDEO_FRAME_INFO_S *>(malloc(sizeof(VIDEO_FRAME_INFO_S)));
1758     /* GFX buffer dispaly on VoDev 0 */
1759     Sample_VO_CreateGFXData(1920, 1080,
1760                             RK_FMT_RGB888, 0, &pMblk_1080P_1);
1761     Sample_VO_CreateGFXData(1920, 1080,
1762                             RK_FMT_RGB888, 1, &pMblk_1080P_2);
1763 
1764     /* GFX buffer dispaly on VoDev 1 */
1765     if (ctx->bDoubleScreen) {
1766         Sample_Print("DoubleScreen UI Demo test");
1767         Sample_VO_CreateGFXData(1024, 768,
1768                                 RK_FMT_RGB888, 0, &pMblk_768P_1);
1769         Sample_VO_CreateGFXData(1024, 768,
1770                                 RK_FMT_RGB888, 1, &pMblk_768P_2);
1771     } else if (ctx->bHomologous) {
1772          Sample_Print("Homologous UI Demo test");
1773     } else {
1774         Sample_Print("Single HDMI Screen UI Demo test");
1775     }
1776     /* Bind Layer */
1777     VoLayer = RK356X_VOP_LAYER_ESMART_0;
1778     VoDev   = RK356X_VO_DEV_HD0;
1779     if (ctx->bDoubleScreen) {
1780         VoLayer_second = RK356X_VOP_LAYER_ESMART_1;
1781         VoDev_second   = RK356X_VO_DEV_HD1;
1782         RK_MPI_VO_BindLayer(VoLayer_second, VoDev_second, VO_LAYER_MODE_GRAPHIC);
1783     }
1784     RK_MPI_VO_BindLayer(VoLayer, VoDev, VO_LAYER_MODE_GRAPHIC);
1785 
1786     if (ctx->bHomologous) {
1787         stVoPubAttr.enIntfType = VO_INTF_HDMI | VO_INTF_EDP;
1788         stVoPubAttr.u32BgColor = 0x000000;
1789     } else {
1790         stVoPubAttr.enIntfType = VO_INTF_HDMI;
1791     }
1792     SampleSetVoInterfacetiming(&stVoPubAttr, ctx->enIntfSync);
1793     Sample_VO_StartDev(VoDev, &stVoPubAttr);
1794 
1795     stLayerAttr.enPixFormat                  = plane_format;
1796     stLayerAttr.stDispRect.s32X              = 0;
1797     stLayerAttr.stDispRect.s32Y              = 0;
1798     stLayerAttr.stDispRect.u32Width          = ctx->u32Screen0DisplayWidth;
1799     stLayerAttr.stDispRect.u32Height         = ctx->u32Screen0DisplayHeight;
1800     stLayerAttr.stImageSize.u32Width         = ctx->u32Screen0ImageWidth;
1801     stLayerAttr.stImageSize.u32Height        = ctx->u32Screen0ImageHeight;
1802     Sample_VO_StartLayer(VoLayer, &stLayerAttr);
1803 
1804     if (ctx->bDoubleScreen) {
1805         stVoPubAttr.enIntfType = VO_INTF_EDP;
1806         stVoPubAttr.u32BgColor = 0x000000;
1807         SampleSetVoInterfacetiming(&stVoPubAttr, ctx->enIntfSync_second);
1808         Sample_VO_StartDev(VoDev_second, &stVoPubAttr);
1809         stLayerAttr.enPixFormat                  = plane_format;
1810         stLayerAttr.stDispRect.s32X              = 0;
1811         stLayerAttr.stDispRect.s32Y              = 0;
1812         stLayerAttr.stDispRect.u32Width          = ctx->u32Screen1DisplayWidth;
1813         stLayerAttr.stDispRect.u32Height         = ctx->u32Screen1DisplayHeight;
1814         stLayerAttr.stImageSize.u32Width         = ctx->u32Screen1ImageWidth;
1815         stLayerAttr.stImageSize.u32Height        = ctx->u32Screen1ImageHeight;
1816         Sample_VO_StartLayer(VoLayer_second, &stLayerAttr);
1817     }
1818 
1819     while (1) {
1820         sleep(1);
1821         count++;
1822         if (count % 2) {
1823             Sample_VO_SetVFrame(pstVFrame,
1824                                 1920,
1825                                 1080,
1826                                 1920,
1827                                 1080,
1828                                 RK_FMT_RGB888,
1829                                 pMblk_1080P_1);
1830             RK_MPI_VO_SendLayerFrame(VoLayer, pstVFrame);
1831             if (ctx->bDoubleScreen) {
1832                 Sample_VO_SetVFrame(pstVFrame,
1833                                     ctx->u32Screen1DisplayWidth,
1834                                     ctx->u32Screen1DisplayHeight,
1835                                     ctx->u32Screen1DisplayWidth,
1836                                     ctx->u32Screen1DisplayHeight,
1837                                     RK_FMT_RGB888,
1838                                     pMblk_768P_1);
1839                 RK_MPI_VO_SendLayerFrame(VoLayer_second, pstVFrame);
1840             }
1841         } else {
1842             Sample_VO_SetVFrame(pstVFrame,
1843                                 1920,
1844                                 1080,
1845                                 1920,
1846                                 1080,
1847                                 RK_FMT_RGB888,
1848                                 pMblk_1080P_2);
1849             RK_MPI_VO_SendLayerFrame(VoLayer, pstVFrame);
1850             if (ctx->bDoubleScreen) {
1851                 Sample_VO_SetVFrame(pstVFrame,
1852                                     ctx->u32Screen1DisplayWidth,
1853                                     ctx->u32Screen1DisplayHeight,
1854                                     ctx->u32Screen1DisplayWidth,
1855                                     ctx->u32Screen1DisplayHeight,
1856                                     RK_FMT_RGB888,
1857                                     pMblk_768P_2);
1858                 RK_MPI_VO_SendLayerFrame(VoLayer_second, pstVFrame);
1859             }
1860         }
1861 
1862         if (count == ctx->loopCount )
1863             break;
1864     }
1865 
1866     Sample_VO_StopLayer(VoLayer);
1867     Sample_VO_StopDev(VoDev);
1868     RK_MPI_VO_UnBindLayer(VoLayer, VoDev);
1869     RK_MPI_VO_DestroyGraphicsFrameBuffer(pMblk_1080P_1);
1870     RK_MPI_VO_DestroyGraphicsFrameBuffer(pMblk_1080P_2);
1871 
1872     if (ctx->bDoubleScreen) {
1873         Sample_VO_StopLayer(VoLayer_second);
1874         Sample_VO_StopDev(VoDev_second);
1875         RK_MPI_VO_UnBindLayer(VoLayer_second, VoDev_second);
1876         RK_MPI_VO_DestroyGraphicsFrameBuffer(pMblk_768P_1);
1877         RK_MPI_VO_DestroyGraphicsFrameBuffer(pMblk_768P_2);
1878     }
1879 end:
1880     RK_MPI_VO_CloseFd();
1881 
1882     return s32Ret;
1883 }
1884 
1885 static RK_S32 Sample_VO_Demo_Alpha(TEST_VO_CTX_S *ctx) {
1886     VO_PUB_ATTR_S           stVoPubAttr;
1887     VO_VIDEO_LAYER_ATTR_S   stLayerAttr;
1888     VoThreadParam           stThreadParam;
1889     RK_U32                  u32DispWidth, u32DispHeight, u32GfxLayers;
1890     VO_LAYER                VoGfxLayer, VoVideoLayer;
1891     RK_S32                  s32Ret = RK_SUCCESS;
1892     RK_U32                  u32VideoWindows;
1893     pthread_t               tThreadDev0;
1894     PIXEL_FORMAT_E          video_format;
1895     RK_U32                  VoWbc;
1896     PIXEL_FORMAT_E          wbc_format;
1897     VO_LAYER                VoLayer;
1898     VO_DEV                  VoDev;
1899 
1900     u32VideoWindows =  ctx->u32Windows;
1901     for (RK_U32 j = 0; j < VDEC_ARRAY_ELEMS(testPixelFormat); j++) {
1902         if (ctx->s32PixFormat == testPixelFormat[j].index) {
1903             video_format =  testPixelFormat[j].format;
1904             break;
1905         }
1906     }
1907     /* Bind Layer */
1908     VoDev == RK356X_VO_DEV_HD0;
1909     VoGfxLayer = RK356X_VOP_LAYER_ESMART_0;
1910     VoVideoLayer = RK356X_VOP_LAYER_CLUSTER_0;
1911     RK_MPI_VO_BindLayer(VoGfxLayer, VoDev, VO_LAYER_MODE_GRAPHIC);
1912     RK_MPI_VO_BindLayer(VoVideoLayer, VoDev, VO_LAYER_MODE_VIDEO);
1913     /* Enable VO Dev0 Device */
1914     u32DispWidth = 1920;
1915     u32DispHeight = 1080;
1916     stVoPubAttr.enIntfType = VO_INTF_HDMI;
1917     stVoPubAttr.enIntfSync = VO_OUTPUT_1080P60;
1918     Sample_VO_StartDev(VoDev, &stVoPubAttr);
1919     /* Enable Vodev 0  Video Layer */
1920     if (VoVideoLayer != -1) {
1921         stLayerAttr.enPixFormat              = video_format;
1922         stLayerAttr.stDispRect.s32X          = 0;
1923         stLayerAttr.stDispRect.s32Y          = 0;
1924         stLayerAttr.stDispRect.u32Width      = u32DispWidth;
1925         stLayerAttr.stDispRect.u32Height     = u32DispHeight;
1926         stLayerAttr.stImageSize.u32Width     = u32DispWidth;
1927         stLayerAttr.stImageSize.u32Height    = u32DispHeight;
1928         stLayerAttr.u32DispFrmRt             = 25;
1929         Sample_VO_StartLayer(VoVideoLayer, &stLayerAttr);
1930         ctx->VoLayer = VoVideoLayer;
1931         Sample_VO_MultiWindowns_Start(ctx);
1932     }
1933     /* Enable Vodev 0  GFX Layer */
1934     u32GfxLayers = 2;
1935     if (VoGfxLayer != -1) {
1936         stLayerAttr.enPixFormat                  = video_format;
1937         stLayerAttr.stDispRect.s32X              = 0;
1938         stLayerAttr.stDispRect.s32Y              = 0;
1939         stLayerAttr.stDispRect.u32Width          = u32DispWidth;
1940         stLayerAttr.stDispRect.u32Height         = u32DispHeight;
1941         stLayerAttr.stImageSize.u32Width         = u32DispWidth;
1942         stLayerAttr.stImageSize.u32Height        = u32DispHeight;
1943         stLayerAttr.u32DispFrmRt                 = 25;
1944         Sample_VO_StartLayer(VoGfxLayer, &stLayerAttr);
1945         Sample_VO_MultiGFXLayer_Start(VoGfxLayer, u32GfxLayers);
1946     }
1947 
1948     Sample_Print("HD0: Start Send Picture\n");
1949 
1950     stThreadParam.u32Exit         = 0;
1951     stThreadParam.u32VideoWindows = u32VideoWindows;
1952     stThreadParam.VoVideoLayer    = VoVideoLayer;
1953     stThreadParam.u32GFXLayers    = u32GfxLayers;
1954     stThreadParam.VOGfxLayer      = VoGfxLayer;
1955     Sample_VO_StartSendPicture_Mosaic(&tThreadDev0, &stThreadParam);
1956 
1957     Sample_Print("Start HD1\n");
1958     VoDev = RK356X_VO_DEV_HD1;
1959     /* Bind Vodev1 Layer */
1960     VoLayer = RK356X_VOP_LAYER_CLUSTER_1;
1961     RK_MPI_VO_BindLayer(VoLayer, VoDev, VO_LAYER_MODE_VIDEO);
1962     /* Enable VO Dev1 Device */
1963     u32DispWidth = 1024;
1964     u32DispHeight = 768;
1965     stVoPubAttr.enIntfType = VO_INTF_EDP;
1966     stVoPubAttr.enIntfSync = VO_OUTPUT_1024x768_60;
1967     stVoPubAttr.u32BgColor = 0x000000;
1968     Sample_VO_StartDev(VoDev, &stVoPubAttr);
1969     /* Enable Layer */
1970     stLayerAttr.enPixFormat              = RK_FMT_BGR888;
1971     stLayerAttr.stDispRect.s32X          = 0;
1972     stLayerAttr.stDispRect.s32Y          = 0;
1973     stLayerAttr.stDispRect.u32Width      = u32DispWidth;
1974     stLayerAttr.stDispRect.u32Height     = u32DispHeight;
1975     stLayerAttr.stImageSize.u32Width     = u32DispWidth;
1976     stLayerAttr.stImageSize.u32Height    = u32DispHeight;
1977     stLayerAttr.u32DispFrmRt             = 25;
1978     Sample_VO_StartLayer(VoLayer, &stLayerAttr);
1979 
1980     ctx->VoLayer = VoLayer;
1981     ctx->u32Windows = 1;
1982     Sample_VO_MultiWindowns_Start(ctx);
1983 
1984     Sample_Print("Start DEV0 WBC\n");
1985     /* Start WBC and bind to HD0 */
1986     VoWbc = 0;
1987     /* WBC bind source */
1988     ctx->stWbcCfg.stWbcSource.enSourceType = VO_WBC_SOURCE_DEV;
1989     ctx->stWbcCfg.stWbcSource.u32SourceId = RK356X_VO_DEV_HD0;
1990 
1991     RK_MPI_VO_SetWbcSource(VoWbc, &ctx->stWbcCfg.stWbcSource);
1992     /* Start WBC */
1993     wbc_format = Sample_wbc_formt(ctx->u32WbcPixFormat);
1994 
1995     ctx->stWbcCfg.stWbcAttr.enPixelFormat = wbc_format;
1996     Sample_Print("wbc format is %x\n", ctx->stWbcCfg.stWbcAttr.enPixelFormat);
1997 
1998     RK_MPI_VO_SetWbcAttr(VoWbc, &ctx->stWbcCfg.stWbcAttr);
1999     RK_MPI_VO_EnableWbc(VoWbc);
2000 
2001     if (ctx->wbc_bind == RK_TRUE)
2002         Sample_VO_BindVoWbc(VoWbc, VoLayer, 0);
2003     sleep(2);
2004     while (1) {
2005         Sample_Print("Press 'q' to quit\n");
2006         if (getchar() == 'q')
2007             break;
2008     }
2009     Sample_VO_StopSendPicture_Mosaic(tThreadDev0, &stThreadParam);
2010     Sample_VO_UnBindVoWbc(VoWbc, VoLayer, 0);
2011     Sample_Print("Stop dev0 WBC\n");
2012     RK_MPI_VO_DisableWbc(VoWbc);
2013 
2014     Sample_Print("Stop HD1\n");
2015     Sample_VO_MultiWindowns_Stop(VoLayer, 1);
2016     Sample_VO_StopLayer(VoLayer);
2017     Sample_VO_StopDev(VoDev);
2018     RK_MPI_VO_UnBindLayer(VoLayer, VoDev);
2019 
2020     Sample_Print("Stop HD0");
2021     VoGfxLayer   = RK356X_VOP_LAYER_ESMART_0;
2022     VoVideoLayer = RK356X_VOP_LAYER_CLUSTER_0;
2023     VoDev        = RK356X_VO_DEV_HD0;
2024     Sample_VO_MultiWindowns_Stop(VoGfxLayer, u32GfxLayers);
2025     Sample_VO_StopLayer(VoGfxLayer);
2026     Sample_VO_MultiWindowns_Stop(VoVideoLayer, u32VideoWindows);
2027     Sample_VO_StopLayer(VoVideoLayer);
2028     RK_MPI_VO_UnBindLayer(VoGfxLayer, VoDev);
2029     RK_MPI_VO_UnBindLayer(VoVideoLayer, VoDev);
2030     Sample_VO_StopDev(VoDev);
2031 
2032     RK_MPI_VO_CloseFd();
2033 
2034     return s32Ret;
2035 }
2036 
2037 static RK_S32 Sample_VO_Video_Homologous(TEST_VO_CTX_S *ctx) {
2038     VO_WBC_SOURCE_S          stWbcSource;
2039     VO_WBC_ATTR_S            stWbcAttr;
2040     RK_U32 VoWbc;
2041     VIDEO_FRAME_INFO_S       *pFrame;
2042     VO_PUB_ATTR_S            stVoPubAttr;
2043     VO_VIDEO_LAYER_ATTR_S    stLayerAttr;
2044     RK_U32                   u32DispWidth, u32DispHeight;
2045     VO_LAYER                 VoLayer;
2046     VO_DEV                   VoDev;
2047     RK_S32                   u32Windows;
2048     RK_U32                   u32Fps, i;
2049     pthread_t                tThreadID;
2050     RK_S32                   s32Ret = RK_SUCCESS;
2051     VO_LAYER_MODE_E          Vo_layer_mode;
2052     VoThreadParam            stThreadParam;
2053     PIXEL_FORMAT_E           video_format;
2054     TEST_VO_CTX_S   stVoCtx;
2055     PIXEL_FORMAT_E  wbc_format;
2056     VoDev = ctx->VoDev;
2057     u32Windows = ctx->u32Windows;
2058     u32Fps =  ctx->u32DispFrmRt;
2059     VoLayer = ctx->VoLayer;
2060     for (RK_U32 j = 0; j < VDEC_ARRAY_ELEMS(testPixelFormat); j++) {
2061         if (ctx->s32PixFormat == testPixelFormat[j].index) {
2062             video_format =  testPixelFormat[j].format;
2063             break;
2064         }
2065     }
2066 
2067     Sample_Print("%s VoDev %u Windows %u video_format %x\n", __func__, VoDev, u32Windows, video_format);
2068 
2069     /* Bind Layer */
2070     switch (ctx->VoLayerMode) {
2071         case 0:
2072             Vo_layer_mode = VO_LAYER_MODE_CURSOR;
2073             break;
2074         case 1:
2075             Vo_layer_mode = VO_LAYER_MODE_GRAPHIC;
2076             break;
2077         case 2:
2078             Vo_layer_mode = VO_LAYER_MODE_VIDEO;
2079             break;
2080         default:
2081             Vo_layer_mode = VO_LAYER_MODE_VIDEO;
2082     }
2083 
2084     RK_MPI_VO_BindLayer(VoLayer, VoDev, VO_LAYER_MODE_VIDEO);
2085 
2086     switch (ctx->enIntfType) {
2087         case DISPLAY_TYPE_VGA:
2088             stVoPubAttr.enIntfType = VO_INTF_VGA;
2089             break;
2090         case DISPLAY_TYPE_HDMI:
2091             stVoPubAttr.enIntfType = VO_INTF_HDMI;
2092             break;
2093         case DISPLAY_TYPE_EDP:
2094             stVoPubAttr.enIntfType = VO_INTF_EDP;
2095             break;
2096         case DISPLAY_TYPE_DP:
2097             stVoPubAttr.enIntfType = VO_INTF_DP;
2098             break;
2099         default:
2100             stVoPubAttr.enIntfType = VO_INTF_HDMI;
2101             Sample_Print("IntfType not set,use INTF_HDMI default\n");
2102     }
2103 
2104     for (i = 0; i < ARRAY_LENGTH(test_mode_table); i++) {
2105         if (ctx->enIntfSync == test_mode_table[i].mode)
2106             break;
2107     }
2108 
2109     if (i == ARRAY_LENGTH(test_mode_table)) {
2110         Sample_Print("%s not found supported mode in test mode_table\n", __func__);
2111         return RK_FAILURE;
2112     }
2113 
2114     stVoPubAttr.enIntfSync = test_mode_table[i].enIntfSync;
2115     Sample_VO_StartDev(VoDev, &stVoPubAttr);
2116 
2117      /* Enable Layer */
2118     stLayerAttr.enPixFormat                  = video_format;
2119     stLayerAttr.stDispRect.s32X              = ctx->s32Y;
2120     stLayerAttr.stDispRect.s32Y              = ctx->s32Y;
2121     if (ctx->VoDev== RK356X_VO_DEV_HD0) {
2122     stLayerAttr.stDispRect.u32Width          = ctx->u32DispWidth;
2123     stLayerAttr.stDispRect.u32Height         = ctx->u32DispHeight;
2124     stLayerAttr.stImageSize.u32Width         = ctx->u32ImgeWidth;
2125     stLayerAttr.stImageSize.u32Height        = ctx->u32ImageHeight;
2126     } else if (ctx->VoDev== RK356X_VO_DEV_HD1) {
2127     stLayerAttr.stDispRect.u32Width          = 1024;
2128     stLayerAttr.stDispRect.u32Height         = 768;
2129     stLayerAttr.stImageSize.u32Width         = 1024;
2130     stLayerAttr.stImageSize.u32Height        = 768;
2131     }
2132     stLayerAttr.u32DispFrmRt                 = ctx->u32DispFrmRt;
2133     Sample_VO_StartLayer(VoLayer, &stLayerAttr);
2134     Sample_VO_MultiWindowns_Start(ctx);
2135     stThreadParam.u32Exit = 0;
2136     stThreadParam.u32VideoWindows = u32Windows;
2137     stThreadParam.VoVideoLayer = VoLayer;
2138     stThreadParam.VOGfxLayer = -1;
2139     stThreadParam.u32GFXLayers = -1;
2140 
2141     Sample_Print("Start Send Picture\n");
2142     Sample_VO_StartSendPicture_Mosaic(&tThreadID, &stThreadParam);
2143 
2144     Sample_Print("Start HD1\n");
2145     /* Start HD1 Device */
2146     VoDev = RK356X_VO_DEV_HD1;
2147     /* Bind Layer */
2148     VoLayer = RK356X_VOP_LAYER_CLUSTER_1;
2149     RK_MPI_VO_BindLayer(VoLayer, VoDev, VO_LAYER_MODE_VIDEO);
2150 
2151     /* Enable VO Device */
2152     if (VoDev == RK356X_VO_DEV_HD0) {
2153         u32DispWidth = 1920;
2154         u32DispHeight = 1080;
2155         stVoPubAttr.enIntfType = VO_INTF_HDMI;
2156         stVoPubAttr.enIntfSync = VO_OUTPUT_1080P50;
2157     } else if (VoDev == RK356X_VO_DEV_HD1) {
2158         u32DispWidth = 1024;
2159         u32DispHeight = 768;
2160         stVoPubAttr.u32BgColor = 0x000000;
2161         stVoPubAttr.enIntfType = VO_INTF_EDP;
2162         stVoPubAttr.enIntfSync = VO_OUTPUT_1024x768_60;
2163     } else {
2164         s32Ret = RK_FAILURE;
2165        // goto end;
2166     }
2167     Sample_VO_StartDev(VoDev, &stVoPubAttr);
2168 
2169     /* Enable Layer */
2170     stLayerAttr.enPixFormat              = RK_FMT_BGR888;
2171     stLayerAttr.stDispRect.s32X          = 0;
2172     stLayerAttr.stDispRect.s32Y          = 0;
2173     stLayerAttr.stDispRect.u32Width      = u32DispWidth;
2174     stLayerAttr.stDispRect.u32Height     = u32DispHeight;
2175     stLayerAttr.stImageSize.u32Width     = u32DispWidth;
2176     stLayerAttr.stImageSize.u32Height    = u32DispHeight;
2177     stLayerAttr.u32DispFrmRt             = 25;
2178     Sample_VO_StartLayer(VoLayer, &stLayerAttr);
2179 
2180     ctx->VoLayer = RK356X_VOP_LAYER_CLUSTER_1;
2181     ctx->u32Windows = 1;
2182     Sample_VO_MultiWindowns_Start(ctx);
2183 
2184     Sample_Print("Start Cluster0 WBC\n");
2185 
2186     /* Start WBC and bind to HD0 */
2187     VoWbc = 0;
2188     /* WBC bind source */
2189     ctx->stWbcCfg.stWbcSource.enSourceType = VO_WBC_SOURCE_VIDEO;
2190     ctx->stWbcCfg.stWbcSource.u32SourceId = RK356X_VO_DEV_HD0;
2191 
2192     RK_MPI_VO_SetWbcSource(VoWbc, &ctx->stWbcCfg.stWbcSource);
2193 
2194     /* Start WBC */
2195     wbc_format = Sample_wbc_formt(ctx->u32WbcPixFormat);
2196 
2197     ctx->stWbcCfg.stWbcAttr.enPixelFormat = wbc_format;
2198     if (ctx->u32WbcWidth > 1920 && ctx->u32WbcHeight > 1080) {
2199         Sample_Print("WBC resolution exceeding 1080P\n");
2200         ctx->u32WbcWidth = 1920;
2201         ctx->u32WbcHeight = 1080;
2202     }
2203 
2204     ctx->stWbcCfg.stWbcAttr.stTargetSize.u32Width =  ctx->u32WbcWidth;
2205     ctx->stWbcCfg.stWbcAttr.stTargetSize.u32Height =  ctx->u32WbcHeight;
2206 
2207     Sample_Print("wbc format is %x\n", ctx->stWbcCfg.stWbcAttr.enPixelFormat);
2208 
2209     RK_MPI_VO_SetWbcAttr(VoWbc, &ctx->stWbcCfg.stWbcAttr);
2210     RK_MPI_VO_EnableWbc(VoWbc);
2211 
2212     Sample_Print("--------------\nWBC Enabled\n---------------\n");
2213 
2214     if (ctx->wbc_auto == RK_TRUE) {
2215         /* Bind WBC to HD1 */
2216         if (ctx->wbc_bind == RK_TRUE)
2217             Sample_VO_BindVoWbc(VoWbc, VoLayer, 0);
2218 
2219         while (1) {
2220             Sample_Print("Press 'q' to quit\n");
2221             if (getchar() == 'q')
2222                 break;
2223         }
2224         Sample_VO_StopSendPicture_Mosaic(tThreadID, &stThreadParam);
2225         Sample_Print("Stop WBC\n");
2226         Sample_VO_UnBindVoWbc(VoWbc, VoLayer, 0);
2227         RK_MPI_VO_DisableWbc(VoWbc);
2228         Sample_Print("Stop HD1\n");
2229         Sample_VO_MultiWindowns_Stop(VoLayer, 1);
2230         Sample_VO_StopLayer(VoLayer);
2231         Sample_VO_StopDev(VoDev);
2232         RK_MPI_VO_UnBindLayer(VoLayer, VoDev);
2233         Sample_Print("Stop HD0\n");
2234         VoDev = RK356X_VO_DEV_HD0;
2235         VoLayer = RK356X_VOP_LAYER_CLUSTER_0;
2236 
2237         Sample_VO_MultiWindowns_Stop(VoLayer, u32Windows);
2238         Sample_VO_StopLayer(VoLayer);
2239         Sample_VO_StopDev(VoDev);
2240         RK_MPI_VO_CloseFd();
2241     }
2242 
2243     return s32Ret;
2244 }
2245 
2246 static RK_S32 check_options(const TEST_VO_CTX_S *ctx) {
2247     if (ctx->VoDev > VO_MAX_DEV_NUM) {
2248         RK_LOGE("illegal param, pls enter 0 or 1 max Vodev is %d!", VO_MAX_DEV_NUM);
2249         goto __FAILED;
2250     }
2251     if ((ctx->VoLayerMode == 2) && (ctx->VoLayer > VO_MAX_LAYER_NUM)) {
2252         RK_LOGE("illegal param, pls enter 0 or 2 max VoLyer is %d!", VO_MAX_LAYER_NUM);
2253         goto __FAILED;
2254     }
2255     if ((ctx->VoLayerMode == 1) && (ctx->VoLayer > VO_MAX_LAYER_NUM)) {
2256         RK_LOGE("illegal param, pls enter 4 or 5 max VoLyer is %d!", VO_MAX_LAYER_NUM);
2257         goto __FAILED;
2258     }
2259     if (ctx->u32Windows <= 0 || ctx->u32Windows >= MAX_WINDOWS_NUM) {
2260         RK_LOGE("illegal param, windos rang [1,63] max u32Windows is %d!", MAX_WINDOWS_NUM);
2261         goto __FAILED;
2262     }
2263     if (ctx->u32WbcPixFormat >= MAX_VO_FORMAT_RGB_NUM) {
2264         RK_LOGE("illegal param, WBC PixFormat rang [0,3]");
2265         goto __FAILED;
2266     }
2267     if (ctx->s32PixFormat > MAX_VO_FORMAT_RGB_NUM) {
2268         RK_LOGE("illegal param, Vidoe PixFormat rang [0,17]");
2269         goto __FAILED;
2270     }
2271 
2272     return RK_SUCCESS;
2273 
2274 __FAILED:
2275     return RK_FAILURE;
2276 }
2277 
2278 static const char *const usages[] = {
2279     "./rk_mpi_vo_test [-i SRC_PATH] [--imag_width IMG_WIDTH]"
2280     "[--imag_height IMG_HEIGHT] [--dis_width DIS_WIDTH] [--dis_height DIS_HEIGHT]...",
2281     NULL,
2282 };
2283 
2284 static void  mpi_vo_test_show_options(const TEST_VO_CTX_S *ctx) {
2285     RK_PRINT("cmd parse result:\n");
2286     RK_PRINT("vop device id                   : %d\n", ctx->VoDev);
2287     RK_PRINT("vop layer id                    : %d\n", ctx->VoLayer);
2288     RK_PRINT("window size                     : %d\n", ctx->u32Windows);
2289     RK_PRINT("connector type                  : %d\n", ctx->enIntfType);
2290     RK_PRINT("display mode                    : %d\n", ctx->enIntfSync);
2291     RK_PRINT("layer mode                      : %d\n", ctx->VoLayerMode);
2292     RK_PRINT("display resolution rect X       : %d\n", ctx->s32X);
2293     RK_PRINT("display resolution rect Y       : %d\n", ctx->s32Y);
2294     RK_PRINT("display pixel format            : %d\n", ctx->s32PixFormat);
2295     RK_PRINT("display resolution width        : %d\n", ctx->u32DispWidth);
2296     RK_PRINT("display resolution height       : %d\n", ctx->u32DispHeight);
2297     RK_PRINT("display resolution0 width       : %d\n", ctx->u32Screen0DisplayWidth);
2298     RK_PRINT("display resolution0 height      : %d\n", ctx->u32Screen0DisplayHeight);
2299     RK_PRINT("display resolution1 width       : %d\n", ctx->u32Screen1DisplayWidth);
2300     RK_PRINT("display resolution1 height      : %d\n", ctx->u32Screen1DisplayHeight);
2301     RK_PRINT("double screen                   : %d\n", ctx->bDoubleScreen);
2302     RK_PRINT("display rate                    : %d\n", ctx->u32DispFrmRt);
2303     RK_PRINT("display rate ratio              : %d\n", ctx->u32DispFrmRtRatio);
2304     RK_PRINT("chn display mode                : %d\n", ctx->u32ChnDismode);
2305     RK_PRINT("chn Border lpx                  : %d\n", ctx->stBorderCfg.u32LeftWidth);
2306     RK_PRINT("chn Border rpx                  : %d\n", ctx->stBorderCfg.u32RightWidth);
2307     RK_PRINT("chn Border tpx                  : %d\n", ctx->stBorderCfg.u32TopWidth);
2308     RK_PRINT("chn Border bpx                  : %d\n", ctx->stBorderCfg.u32BottomWidth);
2309     RK_PRINT("video aspect ratio mode         : %d\n", ctx->uEnMode);
2310     RK_PRINT("input ImgWidth                  : %d\n", ctx->u32ImgeWidth);
2311     RK_PRINT("input ImgHeight                 : %d\n", ctx->u32ImageHeight);
2312     RK_PRINT("ui                              : %d\n", ctx->ui);
2313     RK_PRINT("loopcount                       : %d\n", ctx->loopCount);
2314     RK_PRINT("ui alpha                        : %d\n", ctx->ui_alpha);
2315     RK_PRINT("wbc enable                      : %d\n", ctx->wbc_enable);
2316     RK_PRINT("wbc bind enable                 : %d\n", ctx->wbc_bind);
2317     RK_PRINT("wbc width                       : %d\n", ctx->u32WbcWidth);
2318     RK_PRINT("wbc height                      : %d\n", ctx->u32WbcHeight);
2319     RK_PRINT("wbc compress mode               : %d\n", ctx->u32WbcCompressMode);
2320     RK_PRINT("wbc pixel format                : %d\n", ctx->u32WbcPixFormat);
2321     RK_PRINT("wbc source type                 : %d\n", ctx->u32WbcSourceType);
2322     RK_PRINT("wbc souce id                    : %d\n", ctx->u32WbcSourceId);
2323 }
2324 
2325 void init_cfg(TEST_VO_CTX_S *ctx) {
2326     RK_S32 i = 0;
2327 
2328     ctx->loopCount = 10;
2329     ctx->u32Windows = 4;
2330     ctx->enIntfType = 0;  /* 0: HDMI 1: EDP 2: VGA 3: DP */
2331     ctx->enIntfSync = 16; /* 1080P60 */
2332     ctx->enIntfSync_second = 6; /* 768P */
2333 
2334     ctx->VoDev = RK356X_VO_DEV_HD0;
2335     ctx->VoLayer = RK356X_VOP_LAYER_CLUSTER_0;
2336     ctx->VoLayerMode = 1; /* CURSOR = 0,GRAPHIC = 1,VIDEO = 2,*/
2337 
2338     ctx->u32ImgeWidth = 1920;
2339     ctx->u32ImageHeight = 1080;
2340 
2341     ctx->bDoubleScreen = RK_TRUE;
2342     ctx->stVoCfg.bDoubleScreen = RK_TRUE;
2343     ctx->s32X = 0;
2344     ctx->s32Y = 0;
2345     ctx->u32Screen0DisplayWidth  = 1920;
2346     ctx->u32Screen0DisplayHeight = 1080;
2347     ctx->u32Screen1DisplayWidth  = 1024;
2348     ctx->u32Screen1DisplayHeight = 768;
2349 
2350     ctx->u32Screen0ImageWidth  = 1920;
2351     ctx->u32Screen0ImageHeight = 1080;
2352     ctx->u32Screen1ImageWidth  = 1024;
2353     ctx->u32Screen1ImageHeight = 768;
2354 
2355     ctx->u32DispWidth  = 1920;
2356     ctx->u32DispHeight = 1080;
2357     ctx->s32PixFormat = 5;
2358     ctx->u32DispFrmRt = 30;
2359     ctx->u32DispFrmRtRatio = 1;
2360     ctx->uEnMode = 1;
2361 
2362     ctx->wbc_auto = RK_TRUE;
2363     ctx->u32WbcWidth = 1024;
2364     ctx->u32WbcHeight = 768;
2365     ctx->u32WbcPixFormat = WBC_FORMAT_BGR888;
2366     ctx->u32WbcCompressMode = COMPRESS_MODE_NONE;
2367     ctx->u32WbcSourceType = WBC_SOURCE_VIDEO;
2368     ctx->u32WbcSourceId = RK356X_VO_DEV_HD0;
2369 
2370     ctx->bVoPlay = RK_FALSE;
2371     ctx->bBorder = RK_FALSE;
2372     ctx->bHomologous = RK_FALSE;
2373     ctx->u32Screen0Chn = 16;
2374     ctx->u32Screen1Chn = 4;
2375     ctx->bEnWbc = RK_FALSE;
2376     ctx->wbc_bind = RK_FALSE;
2377     ctx->bChnPriority = RK_FALSE;
2378     ctx->bEnWbcToVO = RK_TRUE;
2379     ctx->s32LoopCount = -1;
2380     ctx->u32ChnDismode = VO_CHANNEL_PLAY_NORMAL;
2381 
2382     ctx->stVoCfg.u32Screen0VoLayer = RK356X_VOP_LAYER_CLUSTER_0;
2383     ctx->stVoCfg.u32Screen1VoLayer = RK356X_VOP_LAYER_CLUSTER_1;
2384     ctx->stVoCfg.u32Screen0Rows = 4;
2385     ctx->stVoCfg.u32Screen1Rows = 3;
2386 
2387     ctx->stVdecCfg.u32FrameBufferCnt = MAX_FRAME_QUEUE;
2388     ctx->stVdecCfg.enCompressMode = COMPRESS_AFBC_16x16;
2389     ctx->stWbcCfg.stWbcSource.enSourceType = VO_WBC_SOURCE_VIDEO;
2390     ctx->stWbcCfg.stWbcSource.u32SourceId = RK356X_VO_DEV_HD0;
2391     ctx->stWbcCfg.stWbcAttr.enPixelFormat = RK_FMT_YUV420SP;
2392     ctx->stWbcCfg.stWbcAttr.stTargetSize.u32Width = 1024;
2393     ctx->stWbcCfg.stWbcAttr.stTargetSize.u32Height = 768;
2394     ctx->stWbcCfg.stWbcAttr.u32FrameRate = 25;
2395     ctx->stWbcCfg.stWbcAttr.enCompressMode = COMPRESS_MODE_NONE;
2396     ctx->stWbcCfg.s32ChnId = 0;
2397     ctx->stWbcCfg.s32VdecChnId = -1;
2398 
2399     ctx->stBorderCfg.u32BottomWidth = 2;
2400     ctx->stBorderCfg.u32TopWidth = 2;
2401     ctx->stBorderCfg.u32LeftWidth = 2;
2402     ctx->stBorderCfg.u32RightWidth = 2;
2403 }
2404 
2405 int main(int argc, const char **argv) {
2406     RK_S32  s32Ret;
2407     TEST_VO_CTX_S ctx;
2408 
2409     memset(&ctx, 0, sizeof(TEST_VO_CTX_S));
2410 
2411     init_cfg(&ctx);
2412 
2413     struct argparse_option options[] = {
2414         OPT_HELP(),
2415         OPT_GROUP("basic options:"),
2416         OPT_STRING('i', "input",  &(ctx.cfgFileUri),
2417                    "input config file. <required>", NULL, 0, 0),
2418         OPT_INTEGER('d', "device_id", &(ctx.VoDev),
2419                      "Vop id. e.g.(0/1). default(0).", NULL, 0, 0),
2420         OPT_INTEGER('l', "layer_id", &(ctx.VoLayer),
2421                      "Layer id. e.g.(0/2/4/6) default(0).", NULL, 0, 0),
2422         OPT_INTEGER('\0', "wbc_enable", &(ctx.wbc_enable),
2423                      "wbc_enalbe. e.g.(0) default(0).", NULL, 0, 0),
2424         OPT_INTEGER('\0', "wbc_bind",  &(ctx.wbc_bind),
2425                    "enable wbc bind, default(1): 0: disable, 1: enable", NULL, 0, 0),
2426         OPT_INTEGER('\0', "ui", &(ctx.ui),
2427                      "ui. e.g.(0) default(0).", NULL, 0, 0),
2428         OPT_INTEGER('\0', "loopCount", &(ctx.loopCount),
2429                      "loopCount. e.g.(0) default(10).", NULL, 0, 0),
2430         OPT_INTEGER('\0', "ui_alpha", &(ctx.ui_alpha),
2431                      "ui_alpha. e.g.(0) default(0).", NULL, 0, 0),
2432         OPT_INTEGER('w', "Windows", &(ctx.u32Windows),
2433                      "windows num. e.g [1-64] default(4),max is 63.", NULL, 0, 0),
2434         OPT_INTEGER('\0', "ConnectorType", &(ctx.enIntfType),
2435                      "Connctor Type. e.g.(0: HDMI 1: EDP 2: VGA). <required>", NULL, 0, 0),
2436         OPT_INTEGER('\0', "layer_mode", &(ctx.VoLayerMode),
2437                      "Layer type. e.g.(0: CURSOR 1: UI 2: Video). <required>", NULL, 0, 0),
2438         OPT_INTEGER('\0', "display_mode", &(ctx.enIntfSync),
2439                      "dispaly. e.g.(12/14) default (12. 12 is 1080P60). <required>", NULL, 0, 0),
2440         OPT_INTEGER('\0', "display0_mode", &(ctx.enIntfSync_second),
2441                      "dispaly. e.g.(12/14) default (12. 12 is 1080P60). <required>", NULL, 0, 0),
2442         OPT_INTEGER('\0', "disp_frmrt", &(ctx.u32DispFrmRt),
2443                      "disp_frmrt. default(25).", NULL, 0, 0),
2444         OPT_INTEGER('\0', "disp_frmrt_ratio", &(ctx.u32DispFrmRtRatio),
2445                      "disp_frmrt_ratio. e.g.(32, 16, 8, 4, 2 ,1). default(1).", NULL, 0, 0),
2446         OPT_INTEGER('\0', "aspect_mode", &(ctx.uEnMode),
2447                      "video aspect ratio."
2448                      "e.g.(1: ratio no change 2: ratio manual set). default(1).", NULL, 0, 0),
2449         OPT_INTEGER('\0', "border_lpx", &(ctx.stBorderCfg.u32LeftWidth),
2450                      "chn Border lpx. default(2).", NULL, 0, 0),
2451         OPT_INTEGER('\0', "border_rpx", &(ctx.stBorderCfg.u32RightWidth),
2452                       "chn Border rpx. default(2).", NULL, 0, 0),
2453         OPT_INTEGER('\0', "border_tpx", &(ctx.stBorderCfg.u32TopWidth),
2454                      "chn Border tpx. default(2).", NULL, 0, 0),
2455         OPT_INTEGER('\0', "border_bpx", &(ctx.stBorderCfg.u32BottomWidth),
2456                      "chn Border bpx. default(2).", NULL, 0, 0),
2457         OPT_INTEGER('\0', "disp_x", &(ctx.s32X),
2458                      "disp_x. default(0).", NULL, 0, 0),
2459         OPT_INTEGER('\0', "disp_y", &(ctx.s32Y),
2460                     "disp_y. default(0).", NULL, 0, 0),
2461         OPT_INTEGER('\0', "video_format", &(ctx.s32PixFormat),
2462                      "video pixel format."
2463                      "e.g.(0: ARGB8888 1: ABGR888 2: RGB888 3: BGR888 4: RK_FMT_YUV420SP)."
2464                      "default(4. 4 is RGB888).", NULL, 0, 0),
2465         OPT_INTEGER('\0', "disp_width", &(ctx.u32DispWidth),
2466                      "dst width. e.g.(1920). <required>", NULL, 0, 0),
2467         OPT_INTEGER('\0', "disp_height", &(ctx.u32DispHeight),
2468                      "dst height. e.g.(1080). <required>", NULL, 0, 0),
2469         OPT_INTEGER('\0', "image0_width", &(ctx.u32Screen0ImageWidth),
2470                      "image0 width. e.g.(1920). <required>", NULL, 0, 0),
2471         OPT_INTEGER('\0', "image0_height", &(ctx.u32Screen0ImageHeight),
2472                      "image0 height. e.g.(1080). <required>", NULL, 0, 0),
2473         OPT_INTEGER('\0', "image1_width", &(ctx.u32Screen1ImageWidth),
2474                      "image1 width. e.g.(1024). <required>", NULL, 0, 0),
2475         OPT_INTEGER('\0', "image1_height", &(ctx.u32Screen1ImageHeight),
2476                      "image1 height. e.g.(768). <required>", NULL, 0, 0),
2477         OPT_INTEGER('\0', "disp0_width", &(ctx.u32Screen0DisplayWidth),
2478                      "dst width. e.g.(1920). <required>", NULL, 0, 0),
2479         OPT_INTEGER('\0', "disp0_height", &(ctx.u32Screen0DisplayHeight),
2480                      "dst height. e.g.(1080). <required>", NULL, 0, 0),
2481         OPT_INTEGER('\0', "disp1_width", &(ctx.u32Screen1DisplayWidth),
2482                      "dst width. e.g.(1024). <required>", NULL, 0, 0),
2483         OPT_INTEGER('\0', "disp1_height", &(ctx.u32Screen1DisplayHeight),
2484                      "dst height. e.g.(768). <required>", NULL, 0, 0),
2485         OPT_INTEGER('\0', "image_width", &(ctx.u32ImgeWidth),
2486                      "dst width. e.g.(1920). <required>", NULL, 0, 0),
2487         OPT_INTEGER('\0', "image_height", &(ctx.u32ImageHeight),
2488                      "dst height. e.g.(1080). <required>", NULL, 0, 0),
2489         OPT_INTEGER('\0', "wbc_width", &(ctx.u32WbcWidth),
2490                      "dst width. e.g.(1920). <required>", NULL, 0, 0),
2491         OPT_INTEGER('\0', "wbc_height", &(ctx.u32WbcHeight),
2492                      "dst height. e.g.(1080). <required>", NULL, 0, 0),
2493         OPT_INTEGER('\0', "wbc_compress", &(ctx.u32WbcCompressMode),
2494                      "wbc compress mode. default(0).", NULL, 0, 0),
2495         OPT_INTEGER('\0', "wbc_format", &(ctx.u32WbcPixFormat),
2496                      "wbc pixel format."
2497                      "e.g.(0: ARGB8888 1: ABGR888 2: RGB888 3: BGR888)."
2498                      "default(0).", NULL, 0, 0),
2499         OPT_INTEGER('\0', "wbc_type", &(ctx.u32WbcSourceType),
2500                      "wbc souce type. e.g.(0: dev 1: video default(1).", NULL, 0, 0),
2501         OPT_INTEGER('\0', "wbc_id", &(ctx.u32WbcSourceId),
2502                      "wbc souce id. default(0).", NULL, 0, 0),
2503         OPT_STRING('\0', "voplay",  &(ctx.bVoPlay),
2504                    "play video test, default(0): 0: RK_FALSE, 1: RK_TRUE", NULL, 0, 0),
2505         OPT_STRING('\0', "bBorder",  &(ctx.bBorder),
2506                    "Border enable, default(0): 0: RK_FALSE, 1: RK_TRUE", NULL, 0, 0),
2507         OPT_STRING('\0', "wbc_auto",  &(ctx.wbc_auto),
2508                    "wbc auto bind, default(1): 0: RK_FALSE, 1: RK_TRUE", NULL, 0, 0),
2509         OPT_INTEGER('\0', "screen0_chn", &(ctx.u32Screen0Chn),
2510                     "the channel num of screen0. default(16)", NULL, 0, 0),
2511         OPT_INTEGER('\0', "chn_display", &(ctx.u32ChnDismode),
2512                      "the chn dispaly mode."
2513                      "e.g.(0: normol 1: pause 2: step 3: speed).default(0).", NULL, 0, 0),
2514         OPT_INTEGER('\0', "screen1_chn", &(ctx.u32Screen1Chn),
2515                     "the channel num of screen1 default(4)", NULL, 0, 0),
2516         OPT_INTEGER('\0', "screen0_rows", &(ctx.stVoCfg.u32Screen0Rows),
2517                     "the rows/cols of screen0 display. default(4: 4x4)", NULL, 0, 0),
2518         OPT_INTEGER('\0', "screen1_rows", &(ctx.stVoCfg.u32Screen1Rows),
2519                     "the rows/cols of screen1 display.default(3 : 3x3)", NULL, 0, 0),
2520         OPT_INTEGER('\0', "en_wbc", &(ctx.bEnWbc),
2521                     "enable wbc. default(0)", NULL, 0, 0),
2522         OPT_INTEGER('\0', "en_chnPriority", &(ctx.bChnPriority),
2523                     "enable Chn Priority. default(0)", NULL, 0, 0),
2524         OPT_INTEGER('\0', "wbc_src",  &(ctx.stWbcCfg.stWbcSource.u32SourceId),
2525                    "the source of wbc, default(1)", NULL, 0, 0),
2526         OPT_INTEGER('\0', "double_screen",  &(ctx.bDoubleScreen),
2527                    "double screen or not, default(1): 0: FALSE, 1: TRUE", NULL, 0, 0),
2528         OPT_INTEGER('\0', "Homologous",  &(ctx.bHomologous),
2529                    "Homologous Display, default(0)", NULL, 0, 0),
2530         OPT_END(),
2531     };
2532 
2533     struct argparse argparse;
2534     argparse_init(&argparse, options, usages, 0);
2535     argparse_describe(&argparse, "\nselect a test case to run.",
2536                                  "\nuse --help for details.");
2537 
2538     argc = argparse_parse(&argparse, argc, argv);
2539 
2540     mpi_vo_test_show_options(&ctx);
2541 
2542     if (check_options(&ctx)) {
2543         RK_LOGE("illegal input parameters");
2544         argparse_usage(&argparse);
2545         goto __FAILED;
2546     }
2547 
2548     if (RK_MPI_SYS_Init() != RK_SUCCESS) {
2549         goto __FAILED;
2550     }
2551 
2552     if (ctx.wbc_enable) {
2553         Sample_VO_Video_Homologous(&ctx);
2554     } else if (ctx.ui_alpha) {
2555         Sample_VO_Demo_Alpha(&ctx);
2556     } else if (ctx.ui) {
2557         Sample_VO_Demo_UI(&ctx);
2558     } else if (ctx.bVoPlay) {
2559          unit_mpi_voplay_test(&ctx);
2560     } else {
2561         Sample_VO_Demo_Video_Mosaic(&ctx);
2562     }
2563 
2564     Sample_Print("test running ok.");
2565 
2566     return RK_SUCCESS;
2567 __FAILED:
2568     RK_LOGE("test running failed!");
2569     return RK_FAILURE;
2570 }
2571