导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    OK536N-C+UVC摄像头+10寸LVDS屏幕实现实时采集绘制(纯软方案)

    飞凌嵌入式专区
    1
    1
    50
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • TrueDei
      TrueDei LV 3 最后由 编辑

      突如其来想法

      恰好看到OK536N-C的手册支持UVC,手里恰好有一个UVC摄像头,也恰好有一个LVDS的屏幕,也恰好产生了一个好奇的想法:

      是否可以实时采集UVC摄像头的数据然后通过LVDS屏幕绘制出来?

      如果可以实现的话,还可以继续延伸,例如:增加AI的一些应用,通过LVDS实时显示出来。

      先来看下效果

      a66ff11b-6349-4d97-a98e-e249435ca9f9-image.png

      为好奇买单

      为了能快速为我的好奇买单,按照初步调试一个板子的经验,肯定先翻看官方的doc手册,是否支持UVC(USB Video Class).

      第一步:确定是否支持:

      在Tina_Linux_USB_开发指南.pdf中有说明,是支持UVC的:

      Device Drivers ‑‑‑>
      <*> Multimedia support ‑‑‑>
      [*] Media USB Adapters ‑‑‑>
      <*> USB Video Class (UVC)
      [*] UVC input events device support
      

      第二步:查找是否有案例

      因为OK536N-C是基于全志T536的,所以飞凌+强强联手,案例也会弥补一些全志官方空缺的demo.

      现在看下飞凌的demo:在forlinx目录下

      飞凌的团队确实缺少了这个我这个好奇想法的功能demo的支持。

      017ba906-d68d-4855-b652-10fbd77d6a81-image.png

      再来看下全志官方的demo:

      有2个demo比较好奇,一个是fbinit_test和usbcam_test

      97e8e9b7-98c0-4eae-a25b-f1d3a78f2f34-image.png

      fbinit_test的功能描述:

      此demo用于清除当前显示的fb的数据,让显示屏上处于干净的状态,方便测试应用送显。

      usbcam_test的功能描述:

      此demo用于验证usb camera功能是否正常。

      没错,这两个就是我们实现的基石,就是快速开发的地基。

      现在目标找到了!!!

      开始买单

      了解清楚你UVC摄像头和LVDS屏幕的参数。

      例如我的UVC摄像头支持YUYV(YUYV 4:2:2)/H264/H265/MJPG(Motion-JPEG):

      而且每个格式下还支持不同的分辨率和帧率。

      camName=HD Camera,devName=Input 1,camPath=/dev/video1
      fmt index=0,description=YUYV 4:2:2,pixelformat=YUYV,v_fmt_type=0
      framsize.discrete.height=720,framsize.discrete.width=1280,framsize.frameRates.size()=2,frameRates=,10,5
      framsize.discrete.height=576,framsize.discrete.width=1024,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=600,framsize.discrete.width=800,framsize.frameRates.size()=2,frameRates=,10,5
      framsize.discrete.height=448,framsize.discrete.width=800,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=480,framsize.discrete.width=640,framsize.frameRates.size()=5,frameRates=,25,20,15,10,5
      framsize.discrete.height=360,framsize.discrete.width=640,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=270,framsize.discrete.width=480,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=180,framsize.discrete.width=320,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      fmt index=1,description=Motion-JPEG,pixelformat=MJPG,v_fmt_type=1
      framsize.discrete.height=1080,framsize.discrete.width=1920,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=896,framsize.discrete.width=1600,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=720,framsize.discrete.width=1280,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=576,framsize.discrete.width=1024,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=540,framsize.discrete.width=960,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=600,framsize.discrete.width=800,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=448,framsize.discrete.width=800,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=576,framsize.discrete.width=720,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=480,framsize.discrete.width=720,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=480,framsize.discrete.width=640,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=360,framsize.discrete.width=640,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=270,framsize.discrete.width=480,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=288,framsize.discrete.width=352,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=240,framsize.discrete.width=320,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      fmt index=2,description=H.264,pixelformat=H264,v_fmt_type=2
      framsize.discrete.height=1080,framsize.discrete.width=1920,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=896,framsize.discrete.width=1600,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=720,framsize.discrete.width=1280,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=576,framsize.discrete.width=1024,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=540,framsize.discrete.width=960,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=600,framsize.discrete.width=800,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=448,framsize.discrete.width=800,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=576,framsize.discrete.width=720,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=480,framsize.discrete.width=720,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=480,framsize.discrete.width=640,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=360,framsize.discrete.width=640,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=270,framsize.discrete.width=480,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=288,framsize.discrete.width=352,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=240,framsize.discrete.width=320,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      fmt index=3,description=35363248-0000-0010-8000-00aa003,pixelformat=,v_fmt_type=2
      framsize.discrete.height=1080,framsize.discrete.width=1920,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=896,framsize.discrete.width=1600,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=720,framsize.discrete.width=1280,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=576,framsize.discrete.width=1024,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=540,framsize.discrete.width=960,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=600,framsize.discrete.width=800,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=448,framsize.discrete.width=800,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=576,framsize.discrete.width=720,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=480,framsize.discrete.width=720,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=480,framsize.discrete.width=640,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=360,framsize.discrete.width=640,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=270,framsize.discrete.width=480,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=288,framsize.discrete.width=352,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      framsize.discrete.height=240,framsize.discrete.width=320,framsize.frameRates.size()=6,frameRates=,30,25,20,15,10,5
      ============================================================
      
      

      LVDS屏幕:

      1、支持RGB888的1280*800的分辨率;

      有了这些参数,就可以很清楚的知道下一步要干什么。

      1、选择采集的格式,因为转RGB,使用YUV是比较合适的,纯软件也简单一些。

      所以我们选择采集YUV,才从YUV中选择一个何时的分辨率,我们选择1280*720的,因为这个最接近LVDS屏幕的最大分辨率:

      fmt index=0,description=YUYV 4:2:2,pixelformat=YUYV,v_fmt_type=0
      framsize.discrete.height=720,framsize.discrete.width=1280,framsize.frameRates.size()=2,frameRates=,10,5
      

      实现功能

      1、获取UVC相机的各种参数

      这里用到了我的一个开源项目中的一个代码。

      https://github.com/truedei/UPlayer

      https://github.com/truedei/UPlayer/blob/main/src/core/utils/v4l2utils.h

      https://github.com/truedei/UPlayer/blob/main/src/core/utils/v4l2utils.cpp

      直接复制出来小改后使用即可.

      e3e18578-15b7-4357-bf26-1eb74fc79954-image.png

      然后就可以得到UVC的各种参数:

      #include "v4l2utils.h"
      
      int main(int argc, char *argv[]) {
      
        // 查询所有拥有video能力的USB设备
        {
          vector<Camera> cms = GetAllVideoDevices();
          for(auto c: cms)
          {
              cout << "camName=" << c.camName.c_str()
              << ",devName=" << c.devName.c_str()
              << ",camPath=" << c.camPath.c_str() << endl;
      
              auto vfmts = c.vfmts;
              for(auto fmt: vfmts)
              {
                  cout << "fmt index=" << fmt.index
                      << ",description=" << fmt.description.c_str()
                      << ",pixelformat=" << fmt.pixelformat
                      << ",v_fmt_type=" << fmt.v_fmt_type
                      << endl;
                  auto frmsizes = fmt.frmsizes;
                  for(auto fs: frmsizes)
                  {
                      cout << "framsize.discrete.height="  << fs.height
                          << ",framsize.discrete.width="  << fs.width ;
      
                      auto frmsizes = fs.frameRates;
                      cout << ",framsize.frameRates.size()="  << frmsizes.size()
                      <<",frameRates=";
                      for(auto fr: frmsizes)
                      {
                          cout << ","  << fr;
                      }
                      cout << endl;
                  }
              }
              cout << "============================================================" << endl;
          }
        }
      
          ....
          ....
          ....
      }
      

      main函数分为4大部分:

      1、查询UVC的参数,选择合适的参数进行初始化;

      2、初始化LVDS屏幕fd描述符,以及获取参数;

      3、获取数据&数据转换&渲染数据;

      4、释放数据;

      68a93175-d31c-43ea-a393-60cf4e7ed886-image.png

      比较核心的是转换&绘制图像数据:

      这里我还做了特殊处理,上下对齐黑边,因为分辨率不一致,不好看

      179ae148-d4ea-48f2-9756-29ac7a46305c-image.png

      未使用硬件加速处理的时间:

      read_frame time cost 0.145181(s)
      read_frame time cost 0.111765(s)
      read_frame time cost 0.111757(s)
      

      效果还是可以的,后期再用硬件加速看看效果。

      代码已放在github:

      https://github.com/truedei/OK536N-C-LVDS-UVC

      1 条回复 最后回复 回复 引用 分享 2
      • 1 / 1
      • First post
        Last post

      Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

      行为准则 | 用户协议 | 隐私权政策