基于 Hisilicon Hi3559v200 实现视频回放功能

一、前言

客户需要 Hisilicon DVR 项目上实现  快进/快退 ,暂停播放 ,感兴趣区域的放大缩小功能 ,并要求对这些功能封装函数 ,用命令行的形式对这些功能继续测试 ,接下来我将与大家分享实现这些功能的过程

二、程序运行环境

使用的硬件平台为 :HI3559V200DMEB VER.A


                       图1 HI3559V200DMEB Board

使用的软件版本为 :Hi3559V200_MobileCam_SDK_V1.0.1.5  , Project Type 为 SampleCam


                                               图2 SampleCam Menuconfig

三、搭建视频回放播放器的环境

3.1  编译 player_sample

Hisilicon 自带视频播放软件 player_sample ,这个软件的路径为 :middleware\sample\liteplayer\player_sample ,

编译结束后会在目录下生成 sample_play 的应用程序

3.2  拷贝库文件

需要将 liteos 测的镜像烧写为 sample/liteos/media_app.bin (对应的压缩镜像为media_app_zip.bin)

把 middleware/sample/liteplayer/player_sample/AAC/libhiaacdec.so拷贝到单板的 /app/sharefs/ 下

将 middleware/component/liteplayer/lib/目录下的 libffmpeg_demuxer.so 拷贝至单板的 /usr/lib/ 下面

3.3  运行 sample_play

把 test.mp4 文件拷贝到 SD 卡

sh /app/komod/mmc_load.sh    //  挂载 SD

mount /dev/mmcblk0p1 /mnt    //  挂载 SD

./app/sharefs/sharefs &

./sample_play test.mp4

通过以上步骤可以看到 视频可以正常播放,快进/快退 ,暂停/播放 功能都是正常的 ,但抓取感兴趣图像功能没有


四、加入缩放功能

4.1 视频回放的数据流程


                                                                            图3 视频回放的处理流程图

从上面的流程图可以了解到视频的处理流程 :

MP4 --> VDEC --> VPSS --> VO  --> Display

视频文件解码后会通过 VPSS 通道把数据送到 VO ,然后进行显示


4.2 缩放的工作原理 

数据在 VPSS 通道经过 CROP  进行扣图 ,通过 VGS 进行缩放 ,然后送到 VO 进行显示

VPSS 的裁剪是通过调用下面的函数完成 :

HI_S32 HI_MPI_VPSS_SetChnCrop(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, const
                                                            VPSS_CROP_INFO_S *pstCropInfo);

参数说明 :

VpssGrp : VPSS GROUP 号 [0, VPSS_MAX_GRP_NUM) 

VpssChn : VPSS 通道号  取值范围:[0, VPSS_MAX_CHN_NUM) 

pstCropInfo : CROP 功能参数

4.3  Linux 和 Liteos 通过 HiSysLink 进行双核间的跨核通信


                                                               图4 HiSysLink 双核通信架构图

我们接下来会在 Middleware 的 Client 端封装一个函数 
HI_S32 HI_MW_VPSS_Crop_Video(HI_HANDLE hVpssGrpHdl, HI_HANDLE hVpssChnHdl,
                                                           HI_HANDLE hDispHdl, HI_HANDLE hWndHdl, HI_U32 u32Width, HI_U32 u32Height,
                                                           HI_U32 u32Startx, HI_U32 u32Starty)

通过 HiSysLink 的方式把数据送到 Middleware 的 Server 端 ,Server  收到数据后调用 HI_MPI_VPSS_SetChnCrop()来抓取图像

--- a/media_adpt/hi3559v200/media_init.c
+++ b/media_adpt/hi3559v200/media_init.c

+HI_S32 HI_MW_VPSS_Crop_Video(HI_HANDLE hVpssGrpHdl, HI_HANDLE hVpssChnHdl,
+                                                  HI_HANDLE hDispHdl, HI_HANDLE hWndHdl, HI_U32 u32Width, HI_U32 u32Height,
+                                                  HI_U32 u32Startx, HI_U32 u32Starty)
+{
+    printf("====== HI_MW_VPSS_Crop_Video ======= \n");
+    return COMMON_Client_VPSS_Crop_Video(hVpssGrpHdl, hVpssChnHdl, hDispHdl, hWndHdl, 
+                                               u32Width, u32Height, u32Startx, u32Starty);
+}

HI_MW_VPSS_Crop_Video()调用函数 COMMON_Client_VPSS_Crop_Video();

--- a/media_adpt/hi3559v200/common_ipcmsg_client.c
+++ b/media_adpt/hi3559v200/common_ipcmsg_client.c

+HI_S32 COMMON_Client_VPSS_Crop_Video(HI_HANDLE hVpssGrpHdl, HI_HANDLE hVpssChnHdl,
+                                                                HI_HANDLE hDispHdl, HI_HANDLE hWndHdl, HI_U32 u32Width, HI_U32 u32Height, HI_U32 u32Startx, HI_U32 u32Starty)
+{
+ HI_S32 s32Ret = HI_SUCCESS;
+ COMMON_VO_OPEN_REQ_MSG_S stOpenReq;
+ stOpenReq.hDispHdl = hDispHdl;
+ stOpenReq.hWndHdl = hWndHdl;
+ stOpenReq.hVpssGrpHdl = hVpssGrpHdl;
+ stOpenReq.hVpssChnHdl = hVpssChnHdl;
+ stOpenReq.u32Width = u32Width;
+ stOpenReq.u32Height = u32Height;
+ stOpenReq.u32Startx = u32Startx;
+ stOpenReq.u32Starty = u32Starty;
+
+ s32Ret = COMMON_IPCMSG_CLIENT_SendSync(COMMON_MSG_CLIENT_VPSS_CROP,
+                                                                       &stOpenReq, sizeof(COMMON_VO_OPEN_REQ_MSG_S), NULL, 0, AVPLAY_MSG_LONG_TIMEOUT);

+
+ printf("====== COMMON_MSG_CLIENT_VPSS_CROP ======= \n");
+
+ if (s32Ret != HI_SUCCESS)
+ {
+ printf("common vo open send ipcmsg exec error ret:%d \n", s32Ret);
+ return HI_FAILURE;
+ }
+ return HI_SUCCESS;
COMMON_Client_VPSS_Crop_Video()函数通过命令 COMMON_IPCMSG_CLIENT_SendSync(COMMON_MSG_CLIENT_VPSS_CROP 与 Server 端通信

--- a/media_adpt/hi3559v200/liteos/common_ipcmsg_server.c
+++ b/media_adpt/hi3559v200/liteos/common_ipcmsg_server.c
@@ -68,6 +68,51 @@ static HI_VOID COMMON_IPCMSG_SVR_HandleVoOpen(HI_IPCMSG_MESSAGE_S* pReq)
}
}

+static HI_VOID COMMON_IPCMSG_SVR_HandleVPSSCropVideo(HI_IPCMSG_MESSAGE_S* pReq)
+{
+    HI_S32 s32Ret = HI_SUCCESS;
+
+    if(pReq->u32BodyLen != sizeof(COMMON_VO_OPEN_REQ_MSG_S))
+    {
+        COMMON_IPCMSG_SendResp(pReq, HI_FAILURE, NULL, 0);
+    }
+    else
+    {
+        COMMON_VO_OPEN_REQ_MSG_S* pstOpen = (COMMON_VO_OPEN_REQ_MSG_S*)pReq->pBody;
+
+        printf("====== COMMON_IPCMSG_SVR_HandleVPSSCropVideo ======= \n");
+
+        s32Ret = PLAYER_VPSS_Crop_Video(pstOpen->hVpssGrpHdl, pstOpen->hVpssChnHdl,
+               pstOpen->hDispHdl, pstOpen->hWndHdl,pstOpen->u32Width,
+               pstOpen->u32Height,pstOpen->u32Startx,pstOpen->u32Starty);
+
+        COMMON_IPCMSG_SendResp(pReq, s32Ret, NULL, 0);
+    }
+}
+

COMMON_IPCMSG_SVR_HandleVPSSCropVideo()函数调用 PLAYER_VPSS_Crop_Video()来抓取感兴趣局域

--- a/media_adpt/hi3559v200/liteos/media_init_liteos.c
+++ b/media_adpt/hi3559v200/liteos/media_init_liteos.c

+HI_S32 PLAYER_VPSS_Crop_Video(HI_HANDLE hVpssGrpHdl, HI_HANDLE hVpssChnHdl, HI_HANDLE hDispHdl, HI_HANDLE hWndHdl,
+                                                    HI_U32 u32Width, HI_U32 u32Height, HI_U32 u32Startx, HI_U32 u32Starty)
+{
+
+ HI_S32 s32Ret = HI_SUCCESS;
+
+ VPSS_CROP_INFO_S stCropInfo;
+
+ printf("==== PLAYER_VPSS_Crop_Video u32Startx = %d , u32Starty = %d====== \n" ,u32Startx ,u32Starty);
+
+ stCropInfo.bEnable = HI_TRUE;
+ stCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;
+ stCropInfo.stCropRect.s32X = u32Startx;
+ stCropInfo.stCropRect.s32Y = u32Starty;
+ stCropInfo.stCropRect.u32Width = u32Width;//640;
+ stCropInfo.stCropRect.u32Height = u32Height;//360;
+ s32Ret = HI_MPI_VPSS_SetGrpCrop(hVpssGrpHdl, &stCropInfo);
+
+ if (s32Ret != HI_SUCCESS)
+ {
+   return s32Ret;
+ }
+
+ s32Ret = HI_MPI_VPSS_GetGrpCrop(hVpssGrpHdl, &stCropInfo);
+ if(s32Ret != HI_SUCCESS)
+ {
+   return s32Ret;
+ }
+
+   return HI_SUCCESS;
+ }
+



五、通过命令行进行测试

添加命令行输入函数 :

--- a/sample/liteplayer/player_sample/player_sample.c
+++ b/sample/liteplayer/player_sample/player_sample.c

printf("Input CMD: quit, pause(pu), replay(re), play(pl), seek(sk), ff [speed] , bw [speed]\n");

- while (fgets(cmd, 10, stdin))
+ while (fgets(cmd, 63, stdin))
{
- cmd[10] = '\0';
+ cmd[63] = '\0';


if (strncmp(cmd, "quit", 4) == 0 )
{
@@ -562,10 +565,52 @@ int main(int argc , char** argv)
s32Ret = HI_LITEPLAYER_TPlay(g_pPlayer, &stTPlayAttr);
printf("HI_LITEPLAYER_TPlay() ret=0x%x\n", s32Ret);
}
- else
- {
- printf("Input CMD: quit, pause(pu), replay(re), play(pl), seek(sk), ff [speed] , bw [speed]\n");
- }

+   else
+   {
+ int startx = 0, starty = 0, width =0, hight = 0;
+
+ printf("cmd strings len : %d \n",strlen(cmd));
+
+ if (strncmp(cmd, "display540", 10) == 0)
+ {
+             if (2 != sscanf(cmd, "display540 startx: %d starty: %d", &startx,&starty))
+             {
+                 printf("display540 startx input err \n" );
+             }
+
+ printf("display540 startx = %d starty = %d \n" ,startx,starty);
+
+ HI_MW_VO_Res_Chg(g_hVpssGrpHandle, g_hVpssGrpChnHandle, g_hDispHandle,+ HI_MW_VO_Res_Chg(g_hVpssGrpHandle, g_hVpssGrpChnHandle, g_hDispHandle,
+                                 g_hDispWndHandle, 960, 540,startx ,starty);
+ }
+
+ if (strncmp(cmd, "display720", 10) == 0)
+ {
+   HI_MW_VO_Res_Chg(g_hVpssGrpHandle, g_hVpssGrpChnHandle, g_hDispHandle,+ g_hDispWndHandle, 1280, 720,0 ,0);
+ }
+
+ if (strncmp(cmd, "cropvideo", 9) == 0)
+ {
+             if (4 != sscanf(cmd, "cropvideo width: %d hight: %d startx: %d starty: %d",&width, &hight,&startx,&starty))
+             {
+                 printf("cropvideo data input err \n" );
+             }
+
+ printf("cropvideo width: %d hight %d startx = %d starty = %d \n" ,width,hight,startx,starty);
+
+ HI_MW_VPSS_Crop_Video(g_hVpssGrpHandle, g_hVpssGrpChnHandle, g_hDispHandle,+ g_hDispWndHandle, width, hight,startx ,starty);
+
+ }
+ if (strncmp(cmd, "cropnormal", 10) == 0)
+ {
+   HI_MW_VPSS_Crop_Video(g_hVpssGrpHandle, g_hVpssGrpChnHandle, g_hDispHandle,+ g_hDispWndHandle, 1920, 1080,0 ,0);
+ }
+
+   }


输入命令后查看效果 

# cropvideo width: 896 hight: 504 startx: 76 starty: 88


左边为放大后的照片 ,右边为放大前的照片


                                                                                  图5 测试结果

六、参考文档

HiMPP媒体处理软件 V4.0 开发参考.pdf , 文档版本 16 ,发布时间 :2020-01-20

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论