可以首先参考前面两篇文章:

Hi3559AV100外接UVC/MJPEG相机实时采图设计(一):Linux USB摄像头驱动分析:

https://www.cnblogs.com/iFrank/p/14399421.html

Hi3559AV100外接UVC/MJPEG相机实时采图设计(二):V4L2接口的实现(以YUV422为例):

https://www.cnblogs.com/iFrank/p/14403397.html

  下面将给出Hi3559AV100外接UVC/MJPEG相机实时采图设计的整体流程,主要实现是通过V4L2接口将UVC/MJPEG相机采集的数据送入至MPP平台,经过VDEC、VPSS、VO最后通过HDMI的输出,最后给出(三)V4L2接口通过MPP平台输出。

板载平台:BOXER-8410AI

芯片型号:Hi3559AV100

相机型号:Logitch c270

开发环境:VM15.5+ubuntu16.04+Hilinux

1、V4L2接口经MPP平台输出通路

  这一篇随笔是给出V4L2接口通过MPP平台下VDEC、VPSS、VO最后通过HDMI视频流输出,实现了如下通路:

  其中的SD Card改为mmap内存映射空间数据,经V4L2接口一帧一帧数据进行传输。其他相关介绍可以参考:

基于Hi3559AV100的视频采集(VDEC-VPSS-VO)整体框图设计

https://www.cnblogs.com/iFrank/p/14370575.html

2、实现方案

  给出具体的实现代码,下面为main函数:

  1 /******************************************************************************
2 * function : main()
3 * Description : video ouput
4 ******************************************************************************/
5 #ifdef __HuaweiLite__
6 int app_main(int argc, char *argv[])
7 #else
8 int main(int argc, char *argv[])
9 #endif
10 {
11 HI_S32 s32Ret = HI_SUCCESS;
12
13 // ******* V4L2 **********
14 ///*
15 if(init_v4l2() == FALSE)
16 {
17 return(FALSE);
18 }
19
20 v4l2_mmap();
21
22
23 if(start_v4l2() == FALSE)
24 {
25 return(FALSE);
26 }
27
28 //*/
29 //*********** **************
30
31
32 if ((argc < 2) || (1 != strlen(argv[1])))
33 {
34 printf("\nInvaild input! For examples:\n");
35 SAMPLE_VDEC_Usage(argv[0]);
36 return HI_FAILURE;
37 }
38
39 if ((argc > 2) && ('1' == *argv[2]))
40 {
41 g_enIntfSync = VO_OUTPUT_1080P60;
42 }
43 else
44 {
45 g_enIntfSync = VO_OUTPUT_3840x2160_30;
46 }
47
48 #ifndef __HuaweiLite__
49 signal(SIGINT, SAMPLE_VDEC_HandleSig);
50 signal(SIGTERM, SAMPLE_VDEC_HandleSig);
51 #endif
52
53 /******************************************
54 choose the case
55 ******************************************/
56 switch (*argv[1])
57 {
58 case '0':
59 {
60 s32Ret = SAMPLE_H265_VDEC_VPSS_VO();
61 break;
62 }
63 case '1':
64 {
65 s32Ret = SAMPLE_H264_VDEC_VPSS_VO();
66 break;
67 }
68 case '2':
69 {
70 s32Ret = SAMPLE_JPEG_VDEC_VPSS_VO();
71 break;
72 }
73 case '3':
74 {
75 s32Ret = SAMPLE_JPEG_VDEC_To_RGB();
76 break;
77 }
78 case '4':
79 {
80 s32Ret = SAMPLE_H264_VDEC_VPSS_VO_MIPI_Tx();
81 break;
82 }
83 default :
84 {
85 SAMPLE_PRT("the index is invaild!\n");
86 SAMPLE_VDEC_Usage(argv[0]);
87 s32Ret = HI_FAILURE;
88 break;
89 }
90 }
91
92 if (HI_SUCCESS == s32Ret)
93 {
94 SAMPLE_PRT("program exit normally!\n");
95 }
96 else
97 {
98 SAMPLE_PRT("program exit abnormally!\n");
99 }
100
101 return s32Ret;
102 }

  给出细节实现函数代码(其中图片像素为640×480,像素格式为PT_MJPEG,HDMI输出设置为1080p60):

  1 HI_S32 SAMPLE_JPEG_VDEC_VPSS_VO(HI_VOID)
2 {
3 VB_CONFIG_S stVbConfig;
4 HI_S32 i, s32Ret = HI_SUCCESS;
5 VDEC_THREAD_PARAM_S stVdecSend[VDEC_MAX_CHN_NUM];
6 SIZE_S stDispSize;
7 VO_LAYER VoLayer;
8 HI_U32 u32VdecChnNum, VpssGrpNum;
9 VPSS_GRP VpssGrp;
10 pthread_t VdecThread[2*VDEC_MAX_CHN_NUM];
11 PIC_SIZE_E enDispPicSize;
12 SAMPLE_VDEC_ATTR astSampleVdec[VDEC_MAX_CHN_NUM];
13 VPSS_CHN_ATTR_S astVpssChnAttr[VPSS_MAX_CHN_NUM];
14 SAMPLE_VO_CONFIG_S stVoConfig;
15 VPSS_GRP_ATTR_S stVpssGrpAttr;
16 HI_BOOL abChnEnable[VPSS_MAX_CHN_NUM];
17 VO_INTF_SYNC_E enIntfSync;
18
19 u32VdecChnNum = 1;
20 VpssGrpNum = u32VdecChnNum;
21
22
23 /************************************************
24 step1: init SYS, init common VB(for VPSS and VO)
25 *************************************************/
26 if(VO_OUTPUT_3840x2160_30 == g_enIntfSync)
27 {
28 enDispPicSize = PIC_3840x2160;
29 enIntfSync = VO_OUTPUT_3840x2160_30;
30 }
31 else
32 {
33 enDispPicSize = PIC_1080P;
34 enIntfSync = VO_OUTPUT_1080P60;
35 }
36
37 s32Ret = SAMPLE_COMM_SYS_GetPicSize(enDispPicSize, &stDispSize);
38 if(s32Ret != HI_SUCCESS)
39 {
40 SAMPLE_PRT("sys get pic size fail for %#x!\n", s32Ret);
41 goto END1;
42 }
43
44 memset(&stVbConfig, 0, sizeof(VB_CONFIG_S));
45 stVbConfig.u32MaxPoolCnt = 1;
46 stVbConfig.astCommPool[0].u32BlkCnt = 10*u32VdecChnNum;
47 stVbConfig.astCommPool[0].u64BlkSize = COMMON_GetPicBufferSize(stDispSize.u32Width, stDispSize.u32Height,
48 PIXEL_FORMAT_YVU_SEMIPLANAR_420, DATA_BITWIDTH_8, COMPRESS_MODE_SEG, 0);
49 s32Ret = SAMPLE_COMM_SYS_Init(&stVbConfig);
50 if(s32Ret != HI_SUCCESS)
51 {
52 SAMPLE_PRT("init sys fail for %#x!\n", s32Ret);
53 goto END1;
54 }
55
56 /************************************************
57 step2: init module VB or user VB(for VDEC)
58 *************************************************/
59 for(i=0; i<u32VdecChnNum; i++)
60 {
61 astSampleVdec[i].enType = PT_MJPEG;
62 astSampleVdec[i].u32Width = 640;
63 astSampleVdec[i].u32Height = 480;
64 astSampleVdec[i].enMode = VIDEO_MODE_FRAME;
65 astSampleVdec[i].stSapmleVdecPicture.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
66 astSampleVdec[i].stSapmleVdecPicture.u32Alpha = 255;
67 astSampleVdec[i].u32DisplayFrameNum = 2;
68 astSampleVdec[i].u32FrameBufCnt = astSampleVdec[i].u32DisplayFrameNum + 1;
69 }
70 s32Ret = SAMPLE_COMM_VDEC_InitVBPool(u32VdecChnNum, &astSampleVdec[0]);
71 if(s32Ret != HI_SUCCESS)
72 {
73 SAMPLE_PRT("init mod common vb fail for %#x!\n", s32Ret);
74 goto END2;
75 }
76
77 /************************************************
78 step3: start VDEC
79 *************************************************/
80 s32Ret = SAMPLE_COMM_VDEC_Start(u32VdecChnNum, &astSampleVdec[0]);
81 if(s32Ret != HI_SUCCESS)
82 {
83 SAMPLE_PRT("start VDEC fail for %#x!\n", s32Ret);
84 goto END3;
85 }
86
87 /************************************************
88 step4: start VPSS
89 *************************************************/
90 stVpssGrpAttr.u32MaxW = 640;
91 stVpssGrpAttr.u32MaxH = 480;
92 stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
93 stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;
94 stVpssGrpAttr.enDynamicRange = DYNAMIC_RANGE_SDR8;
95 stVpssGrpAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
96 stVpssGrpAttr.bNrEn = HI_FALSE;
97
98 memset(abChnEnable, 0, sizeof(abChnEnable));
99 abChnEnable[0] = HI_TRUE;
100 astVpssChnAttr[0].u32Width = stDispSize.u32Width;
101 astVpssChnAttr[0].u32Height = stDispSize.u32Height;
102 astVpssChnAttr[0].enChnMode = VPSS_CHN_MODE_AUTO;
103 astVpssChnAttr[0].enCompressMode = COMPRESS_MODE_SEG;
104 astVpssChnAttr[0].enDynamicRange = DYNAMIC_RANGE_SDR8;
105 astVpssChnAttr[0].enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
106 astVpssChnAttr[0].stFrameRate.s32SrcFrameRate = -1;
107 astVpssChnAttr[0].stFrameRate.s32DstFrameRate = -1;
108 astVpssChnAttr[0].u32Depth = 0;
109 astVpssChnAttr[0].bMirror = HI_FALSE;
110 astVpssChnAttr[0].bFlip = HI_FALSE;
111 astVpssChnAttr[0].stAspectRatio.enMode = ASPECT_RATIO_NONE;
112 astVpssChnAttr[0].enVideoFormat = VIDEO_FORMAT_LINEAR;
113
114 for(i=0; i<u32VdecChnNum; i++)
115 {
116 VpssGrp = i;
117 s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, &abChnEnable[0], &stVpssGrpAttr, &astVpssChnAttr[0]);
118 if(s32Ret != HI_SUCCESS)
119 {
120 SAMPLE_PRT("start VPSS fail for %#x!\n", s32Ret);
121 goto END4;
122 }
123 }
124
125
126
127 /************************************************
128 step5: start VO
129 *************************************************/
130 stVoConfig.VoDev = SAMPLE_VO_DEV_UHD;
131 stVoConfig.enVoIntfType = VO_INTF_HDMI;
132 stVoConfig.enIntfSync = enIntfSync;
133 stVoConfig.enPicSize = enDispPicSize;
134 stVoConfig.u32BgColor = COLOR_RGB_BLUE;
135 stVoConfig.u32DisBufLen = 3;
136 stVoConfig.enDstDynamicRange = DYNAMIC_RANGE_SDR8;
137 stVoConfig.enVoMode = VO_MODE_1MUX;
138 stVoConfig.enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
139 stVoConfig.stDispRect.s32X = 0;
140 stVoConfig.stDispRect.s32Y = 0;
141 stVoConfig.stDispRect.u32Width = stDispSize.u32Width;
142 stVoConfig.stDispRect.u32Height = stDispSize.u32Height;
143 stVoConfig.stImageSize.u32Width = stDispSize.u32Width;
144 stVoConfig.stImageSize.u32Height = stDispSize.u32Height;
145 stVoConfig.enVoPartMode = VO_PART_MODE_SINGLE;
146 s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
147 if(s32Ret != HI_SUCCESS)
148 {
149 SAMPLE_PRT("start VO fail for %#x!\n", s32Ret);
150 goto END5;
151 }
152
153 /************************************************
154 step6: VDEC bind VPSS
155 *************************************************/
156 for(i=0; i<u32VdecChnNum; i++)
157 {
158 s32Ret = SAMPLE_COMM_VDEC_Bind_VPSS(i, i);
159 if(s32Ret != HI_SUCCESS)
160 {
161 SAMPLE_PRT("vdec bind vpss fail for %#x!\n", s32Ret);
162 goto END6;
163 }
164 }
165
166 /************************************************
167 step7: VPSS bind VO
168 *************************************************/
169 VoLayer = stVoConfig.VoDev;
170 for(i=0; i<VpssGrpNum; i++)
171 {
172 s32Ret = SAMPLE_COMM_VPSS_Bind_VO(i, 0, VoLayer, i);
173 if(s32Ret != HI_SUCCESS)
174 {
175 SAMPLE_PRT("vpss bind vo fail for %#x!\n", s32Ret);
176 goto END7;
177 }
178 }
179
180
181
182 /************************************************
183 step8: send stream to VDEC
184 *************************************************/
185 for(i=0; i<u32VdecChnNum; i++)
186 {
187 ////snprintf(stVdecSend[i].cFileName, sizeof(stVdecSend[i].cFileName), "3840x2160.jpg");
188 snprintf(stVdecSend[i].cFileName, sizeof(stVdecSend[i].cFileName), "txtjpeg.txt");
189
190 //#define SAMPLE_STREAM_PATH "./source_file"
191 snprintf(stVdecSend[i].cFilePath, sizeof(stVdecSend[i].cFilePath), "%s", "/nfsroot");
192 stVdecSend[i].enType = astSampleVdec[i].enType;
193 stVdecSend[i].s32StreamMode = astSampleVdec[i].enMode;
194 stVdecSend[i].s32ChnId = i;
195 stVdecSend[i].s32IntervalTime = 1000;
196 stVdecSend[i].u64PtsInit = 0;
197 stVdecSend[i].u64PtsIncrease = 0;
198 stVdecSend[i].eThreadCtrl = THREAD_CTRL_START;
199 stVdecSend[i].bCircleSend = HI_TRUE;
200 stVdecSend[i].s32MilliSec = 0;
201 stVdecSend[i].s32MinBufSize = (astSampleVdec[i].u32Width * astSampleVdec[i].u32Height * 3)>>1;
202 }
203
204
205
206 SAMPLE_COMM_VDEC_StartSendStream(u32VdecChnNum, &stVdecSend[0], &VdecThread[0]);
207
208 SAMPLE_COMM_VDEC_CmdCtrl(u32VdecChnNum, &stVdecSend[0], &VdecThread[0]);
209
210 SAMPLE_COMM_VDEC_StopSendStream(u32VdecChnNum, &stVdecSend[0], &VdecThread[0]);
211
212 END7:
213 for(i=0; i<VpssGrpNum; i++)
214 {
215 s32Ret = SAMPLE_COMM_VPSS_UnBind_VO(i, 0, VoLayer, i);
216 if(s32Ret != HI_SUCCESS)
217 {
218 SAMPLE_PRT("vpss unbind vo fail for %#x!\n", s32Ret);
219 }
220 }
221
222 END6:
223 for(i=0; i<u32VdecChnNum; i++)
224 {
225 s32Ret = SAMPLE_COMM_VDEC_UnBind_VPSS(i, i);
226 if(s32Ret != HI_SUCCESS)
227 {
228 SAMPLE_PRT("vdec unbind vpss fail for %#x!\n", s32Ret);
229 }
230 }
231
232 END5:
233 SAMPLE_COMM_VO_StopVO(&stVoConfig);
234
235 END4:
236 for(i = VpssGrp; i >= 0; i--)
237 {
238 VpssGrp = i;
239 SAMPLE_COMM_VPSS_Stop(VpssGrp, &abChnEnable[0]);
240 }
241
242 END3:
243 SAMPLE_COMM_VDEC_Stop(u32VdecChnNum);
244
245 END2:
246 SAMPLE_COMM_VDEC_ExitVBPool();
247
248 END1:
249 SAMPLE_COMM_SYS_Exit();
250
251 return s32Ret;
252 }

  参考了sample_vdec.c、sample_common_vdec.c、sample_common_vpss.csample_common_vo.c等,定义了V4L2如下参数:

 1 /*******************************************************
2 function announce
3 *******************************************************/
4
5 //@@@@@@@@@@@@@ V4L2 @@@@@@@@@@@
6 #define TRUE 1
7 #define FALSE 0
8
9
10 #define FILE_VIDEO "/dev/video0"
11
12
13 #define IMAGEWIDTH 640
14 #define IMAGEHEIGHT 480
15
16 int video_fd;
17 struct v4l2_capability cap;
18
19 struct v4l2_fmtdesc fmtdesc;
20 struct v4l2_format fmt;
21 struct v4l2_streamparm setfps;
22 struct v4l2_requestbuffers req;
23 struct v4l2_buffer buf,readbuffer;
24 struct v4l2_buffer queuebuffer;
25
26 int my_type;
27
28
29 //for v4l2_mmap function,to cache data
30 struct buffer
31 {
32 void * start;
33 unsigned int length;
34 }*buffers;
35
36
37
38 int init_v4l2(void);
39 int start_v4l2(void);
40 int v4l2_mmap(void);
41 int stop_v4l2(void);
42 int close_v4l2(void);
43 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

3、视频流输出结果

  通过上述步骤最终实现了视频流通路,摄像头采集的图形能够实时的显示在显示屏上,具有良好的效果,现象如下(用手机进行了6s视频的录制,因为博客上不能上传视频,所以以截图进行表示,从结果可以看出,很好实现了视频流的输出且不卡帧):

Hi3559AV100外接UVC/MJPEG相机实时采图设计(三):V4L2接口通过MPP平台输出的更多相关文章

  1. Hi3559AV100外接UVC/MJPEG相机实时采图设计(二):V4L2接口的实现(以YUV422为例)

    下面将给出Hi3559AV100外接UVC/MJPEG相机实时采图设计的整体流程,主要实现是通过V4L2接口将UVC/MJPEG相机采集的数据送入至MPP平台,经过VDEC.VPSS.VO最后通过HD ...

  2. Hi3559AV100外接UVC/MJPEG相机实时采图设计(一):Linux USB摄像头驱动分析

    下面将给出Hi3559AV100外接UVC/MJPEG相机实时采图设计的整体流程,主要实现是通过V4L2接口将UVC/MJPEG相机采集的数据送入至MPP平台,经过VDEC.VPSS.VO最后通过HD ...

  3. Hi3559AV100外接UVC/MJPEG相机实时采图设计(四):VDEC_Send_Stream线程分析

    下面随笔将对Hi3559AV100外接UVC/MJPEG相机实现实时采图设计的关键点-VDEC_Send_Stream线程进行分析,一两个星期前我写了有三篇系列随笔,已经实现了项目功能,大家可以参考下 ...

  4. Hi3559AV100 NNIE开发(5)mobilefacenet.wk仿真成功量化及与CNN_convert_bin_and_print_featuremap.py输出中间层数据对比过程

    前面随笔给出了NNIE开发的基本知识,下面几篇随笔将着重于Mobilefacenet NNIE开发,实现mobilefacenet.wk的chip版本,并在Hi3559AV100上实现mobilefa ...

  5. Dalsa 8K彩色相机Camera link C#采图

    一个采图工具,所以界面做的很简单. private SapAcquisition m_Acquisition; private SapBuffer m_Buffers; private SapAcqT ...

  6. 相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了!

    相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了! 先说图片X×dpi=点数dotX是图片实际尺寸,简单点,我们只算图片的高吧,比如说拍了张图片14 ...

  7. FusionCharts制作实时刷新图

    转自:http://yklovejava-163-com.iteye.com/blog/1889949 下面介绍的是用FusionCharts制作实时刷新图的过程(FusionCharts确实太好用了 ...

  8. Android相机实时自动对焦的完美实现

    https://zhidao.baidu.com/question/873328177698804372.html Android相机实时自动对焦的完美实现 http://blog.csdn.net/ ...

  9. 关于nagios系统下使用shell脚本自定义监控插件的编写以及没有实时监控图的问题

    关于nagios系统下shell自定义监控插件的编写.脚本规范以及没有实时监控图的问题的解决办法 在自已编写监控插件之前我们首先需要对nagios监控原理有一定的了解 Nagios的功能是监控服务和主 ...

随机推荐

  1. 【uva 1312】Cricket Field(算法效率--技巧枚举)

    题意:一个 L*R 的网格里有 N 棵树,要求找一个最大空正方形并输出其左下角坐标和长.(1≤L,R≤10000, 0≤N≤100) 解法:枚举空正方形也就是枚举空矩阵,先要固定一个边,才好继续操作. ...

  2. Codeforces Round #668 (Div. 2) B. Array Cancellation (思维,贪心)

    题意:有一个长度为\(n\)并且所有元素和为\(0\)的序列,你可以使\(a_{i}-1\)并且\(a_{j}+1\),如果\(i<j\),那么这步操作就是免费的,否则需要花费一次操作,问最少操 ...

  3. 如何用 4 个小时搭建一个新 “Clubhouse” ,引爆声音社交新风口

    Clubhouse,基于实时音频技术的声音社交现象级火爆 最近,让硅谷两位顶级 VC 大打出手争相投资的 Clubhouse 火到了国内,甚至在社交圈里 "一码难求",此种火爆程度 ...

  4. 51nod1459 带权最短路

    1459 迷宫游戏 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分 ...

  5. CSS3 动态生成内容(在Web中插入内容)====CSS的伪类或者伪元素

    # css3 .类:伪类::伪元素 /* CSS3伪元素/伪类 :https://www.w3.org/TR/css3-selectors/#selectors ::selection 伪元素(F12 ...

  6. MDN All In One

    MDN All In One https://github.com/mdn/ https://wiki.mozilla.org/MDN MDN 要凉了 https://developer.mozill ...

  7. GitHub new features 2020 All In One

    GitHub new features 2020 All In One Discussions Discussions is the space for your community to have ...

  8. zhihu level

    zhihu level https://www.zhihu.com/creator/account/growth-level refs xgqfrms 2012-2020 www.cnblogs.co ...

  9. LeetCode Binary Search All In One

    LeetCode Binary Search All In One Binary Search 二分查找算法 https://leetcode-cn.com/problems/binary-searc ...

  10. 微信小程序-云开发-实战项目

    微信小程序-云开发-实战项目 微信小程序 微信小程序平台服务条款 https://developers.weixin.qq.com/miniprogram/product/service.html h ...