RK3568笔记九: DRM显示摄像头
若该文为原创文章,转载请注明原文出处。
一、介绍
学习DRM的目的是想做类似NVR显示多路实时流,通过勇哥(Marc)的指导,大概流程是通过Zlmedia拉流,RK3568的MPP解码,DRM显示,可以使用HDMI或DIS屏幕,所以为了后面的实现,先测试摄像头采集DRM显示。
二、移植过程
测试过程在笔记八里,如有不懂的,请看笔迹八。
移植过程参考GitHub - MontaukLaw/cvv_test
里面有DRM显示两个屏的例子。
程序是以正点原子里的rknn_yolov5_demo例程修改。主要修改几个地方。
大概流程:
1、初始化屏幕 drm_dis_init();
2、opencv打开摄像头cv::VideoCapture cap(0);
3、循环读数据并显示
cap.read(orig_img);
draw_lcd_screen_rgb_960((uint8_t *)img.data, 720 * 1280 * 3);
代码:
main.cc
// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License./*-------------------------------------------Includes
-------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <vector>
#include <string>#include "drm_func.h"
#include "rga_func.h"
#include "rknn_api.h"
#include "yolo.h"#include "RgaUtils.h"
#include "im2d.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include "rga.h"
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "dev.h"
#include "bo.h"static sp_dev *mDev;
#define OUTPUT_DEVICE_LCD 1static drmModeConnectorPtr lcdConnectorPtr = nullptr;
static struct sp_crtc *lcdCRPtr;
static drmModeEncoderPtr lcdEncoderPtr = nullptr;
static uint32_t lcdCrtcId = 0;
static drmModeModeInfoPtr lcdModInfoPtr;static void get_connector(uint8_t outpuDevice)
{int i, j = 0;int ret = 0;printf("mDev->num_connectors = %d\n", mDev->num_connectors);for (j = 0; j < mDev->num_connectors; j++){// name 是分辨率信息printf("connector name:%d\n", j);printf("connector_type:%d\n", j);printf("connector_type_id:%d\n", j);printf("connector status:%d\n", j);// 对应不同的输出设备, 指定不同的connector跟encoderif (outpuDevice == OUTPUT_DEVICE_LCD){if (mDev->connectors[j]->connector_type == DRM_MODE_CONNECTOR_DSI &&mDev->connectors[j]->connection == DRM_MODE_CONNECTED){lcdConnectorPtr = mDev->connectors[j];}}}
}static void get_encoder(uint8_t outpuDevice)
{int i;for (i = 0; i < mDev->num_encoders; i++){if (outpuDevice == OUTPUT_DEVICE_LCD){if (mDev->encoders[i]->encoder_type == DRM_MODE_ENCODER_DSI){lcdEncoderPtr = mDev->encoders[i];lcdCrtcId = lcdEncoderPtr->crtc_id;}}}
}static void get_crtc()
{int j;printf("lcd crtc id:%d\n", lcdCrtcId);for (j = 0; j < mDev->num_crtcs; j++){printf("encoderPtr->crtc_id:%d\n", mDev->crtcs[j].crtc->crtc_id);printf("mode_valid:%d\n", mDev->crtcs[j].crtc->mode_valid);printf("mode_name:%s\n", mDev->crtcs[j].crtc->mode.name);if (mDev->crtcs[j].crtc->crtc_id == lcdCrtcId && mDev->crtcs[j].crtc->mode_valid){lcdCRPtr = &mDev->crtcs[j];}}
}static int init_screens()
{int ret = 0;// 获取lcd connectorget_connector(OUTPUT_DEVICE_LCD);if (!lcdConnectorPtr){printf("failed to get hdmi connector or encoder.\n");return -1;}printf("lcd connector id:%d\n", lcdConnectorPtr->connector_id);// 获取lcd encoderget_encoder(OUTPUT_DEVICE_LCD);if (!lcdEncoderPtr){printf("failed to get encoder.\n");return -2;}printf("lcd encoder id:%d\n", lcdEncoderPtr->encoder_id);// 获取一下显示分辨率之类lcdModInfoPtr = &lcdConnectorPtr->modes[0];// 把connector的encoder id赋值为encoder的idlcdConnectorPtr->encoder_id = lcdEncoderPtr->encoder_id;// 获取lcd crtcget_crtc();if (!lcdCRPtr){printf("failed to get crtc.\n");return -3;}if (lcdCRPtr->scanout){printf("crtc already in use\n");return -4;}printf("lcd crtc id:%d\n", lcdCRPtr->crtc->crtc_id);// allset// 获取bo, 只需要输入分辨率即可.lcdCRPtr->scanout = create_sp_bo(mDev, lcdModInfoPtr->hdisplay, lcdModInfoPtr->vdisplay, 24, 32, DRM_FORMAT_XRGB8888, 0);if (!lcdCRPtr->scanout){printf("failed to create new scanout bo\n");return -5;}printf("fill test color\n");fill_bo(lcdCRPtr->scanout, 0xff, 0xff, 0x0, 0x0);ret = drmModeSetCrtc(mDev->fd, lcdEncoderPtr->crtc_id, lcdCRPtr->scanout->fb_id, 0, 0, &lcdConnectorPtr->connector_id, 1, lcdModInfoPtr);if (ret){printf("failed to set crtc mode ret=%d\n", ret);return -6;}lcdCRPtr->crtc = drmModeGetCrtc(mDev->fd, lcdCRPtr->crtc->crtc_id);memcpy(&lcdCRPtr->crtc->mode, lcdModInfoPtr, sizeof(*lcdModInfoPtr));return 0;
}int drm_dis_init(void)
{int ret = 0;int i = 0;printf("create sp dev\n");// 创建显示设备mDev = create_sp_dev();if (!mDev){printf("failed to exec create_sp_dev.\n");return -10;}printf("init_screen\n");// 初始化屏幕ret = init_screens();if (ret != 0){printf("failed to exec initialize_screens.\n");return -11;}return 0;
}void draw_lcd_screen_rgb_960(uint8_t *data, uint32_t dataSize)
{uint32_t colIdx = 0;uint32_t rowIdx = 0;uint8_t *dataPtr = data;for (rowIdx = 0; rowIdx < 1280; rowIdx++){uint8_t *rowPtr = (uint8_t *)lcdCRPtr->scanout->map_addr + rowIdx * lcdCRPtr->scanout->pitch;for (colIdx = 0; colIdx < 720; colIdx++){uint8_t *pixel = rowPtr + colIdx * 4;pixel[0] = *dataPtr;dataPtr++;pixel[1] = *dataPtr;dataPtr++;pixel[2] = *dataPtr;dataPtr++;pixel[3] = 0xff;}}
}int main(int argc, char **argv)
{int i,j;drm_dis_init();cv::VideoCapture cap(0);if (!cap.isOpened()){std::cout << "无法打开摄像头" << std::endl;return -1;}cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);// using opencvusing namespace cv;using namespace std;cv::Mat orig_img;cv::Mat img;char data_u8[4];while(1){cap.read(orig_img);cv::rotate(orig_img, orig_img, ROTATE_90_COUNTERCLOCKWISE);cv::cvtColor(orig_img, img, cv::COLOR_BGR2RGB);draw_lcd_screen_rgb_960((uint8_t *)img.data, 720 * 1280 * 3);}exit(0);
}
这里需要注意的是显示部分
显示是32位的RGBA,所以需要封装一下,初始化得到了map_addr映射地址,直接填充数据,就会显示。
使用正点原子需要先关闭QT应用程序,不然运行一会就会退出。
CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)project(rknn_yolov5v7x_demo)set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_SKIP_INSTALL_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")# rknn api
set(PLATFORM RK3566_3568)
set(LIB_ARCH aarch64)
set(RKNN_API_PATH ${CMAKE_CURRENT_SOURCE_DIR}/libs/rknpu2/runtime/RK356X/Linux/librknn_api)
set(RKNN_RT_LIB ${RKNN_API_PATH}/aarch64/librknnrt.so)
include_directories(${RKNN_API_PATH}/include)# drm
set(DRM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/common/drm)
set(DRM_RT_LIB ${CMAKE_CURRENT_SOURCE_DIR}/libs/libdrm/lib/libdrm.so)
include_directories(${DRM_DIR}/include)
include_directories(${DRM_DIR}/include/libdrm)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libs/rkdrm/)#rga
set(RGA_PATH ${CMAKE_CURRENT_SOURCE_DIR}/libs/librga)
set(RGA_LIB ${RGA_PATH}/libs/Linux/gcc-aarch64/librga.so)
include_directories(${RGA_PATH}/include)set(OPENCV_LIBS opencv_core opencv_flann opencv_videoio opencv_video opencv_highgui opencv_imgcodecs opencv_imgproc)
set(TOOLCHAIN_DIR /opt/atk-dlrk356x-toolchain)
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/usr/bin/aarch64-buildroot-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/usr/bin/aarch64-buildroot-linux-gnu-c++)
set(SYSROOT ${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu//sysroot/usr/include)
set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu/sysroot)
include_directories(${SYSROOT})
include_directories(${SYSROOT}/opencv4)set(CMAKE_INSTALL_RPATH "lib")# rknn_yolo_demo
include_directories( ${CMAKE_SOURCE_DIR}/include)
add_executable(rknn_yolo_demosrc/drm_func.csrc/rga_func.csrc/yolo.ccsrc/main.ccsrc/bo.ccsrc/dev.ccsrc/modeset.cc
)target_link_libraries(rknn_yolo_demo${RKNN_RT_LIB}${RGA_LIB}${OPENCV_LIBS}${DRM_RT_LIB}dl
)# install target and libraries
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/atk_rknn_yolo_v5_demo)
install(TARGETS rknn_yolo_demo DESTINATION ./)install(PROGRAMS ${RKNN_RT_LIB} DESTINATION lib)
install(PROGRAMS ${RGA_LIB} DESTINATION lib)
install(DIRECTORY model DESTINATION ./)
编译后,把可执行文件上传到板子运行后,测试正常。
如有侵权,或需要完整代码,请及时联系博主。
相关文章:
RK3568笔记九: DRM显示摄像头
若该文为原创文章,转载请注明原文出处。 一、介绍 学习DRM的目的是想做类似NVR显示多路实时流,通过勇哥(Marc)的指导,大概流程是通过Zlmedia拉流,RK3568的MPP解码,DRM显示,可以使用HDMI或DIS屏幕…...
简单明了,汽车级LM317系列LM317D2TR4G线性电压稳压器电源设计-参数应用方案分享
低压差线性稳压器(LDO),是指一种具有恒定电流输出电压的装置,主要由输入变压器、整流器、输出变压器三部分构成,工业原理为将输入的交流电压经过整流、滤波后得到直流输出电压,再经过控制元件和开关器件将稳…...
Flink会话集群docker-compose一键安装
1、安装docker 参考,本人这篇博客:https://blog.csdn.net/taotao_guiwang/article/details/135508643?spm1001.2014.3001.5501 2、flink-conf.yaml flink-conf.yaml放在/home/flink/conf/job、/home/flink/conf/task下面,flink-conf.yaml…...
qt.qpa.plugin: Could not find the Qt platform plugin “windows“ in ““
系统环境:Win10家庭中文版 Qt : 5.12.9 链接了一些64位的第三方库,程序编译完运行后出现 qt.qpa.plugin: Could not find the Qt platform plugin "windows" in "" 弹窗如下: 网上搜了一些都是关于pyQt的,…...
vue面试题集锦
1. 谈一谈对 MVVM 的理解? MVVM 是 Model-View-ViewModel 的缩写。MVVM 是一种设计思想。 Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑; View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,View 是…...
2024年学鸿蒙开发就业前景怎么样?
随着科技的不断进步,鸿蒙系统作为华为自主研发的操作系统,逐渐引起了人们的关注。 2024年,鸿蒙开发就业前景如何? 对于那些对鸿蒙开发感兴趣并希望在这一领域寻找职业发展的人来说,这是一个非常重要的问题。 首先&a…...
Unity网络通讯学习
---部分截图来自 siki学院Unity网络通讯课程 Socket 网络上的两个程序通过一个双向的通信连接实现数据交换,这个连接的一端称为一个 Socket ,Socket 包含了网络通信必须的五种信息 Socket 例子{ 协议: TCP 本地: IP ÿ…...
js入口函数和jQuery入口函数的区别
JS入口函数指的是JavaScript中的主入口函数,用来初始化页面加载完成后的操作。通常情况下,JS入口函数是在HTML页面中的<script>标签中定义的,通过onload事件等方式触发调用。 jQuery入口函数则是指使用jQuery库时的主入口函数…...
Docker-Compose编排Nginx1.25.1+PHP7.4.33+Redis7.0.11环境
实践说明:基于RHEL7(CentOS7.9)部署docker环境(23.0.1、24.0.2),编排也可应用于RHEL7-9(如AlmaLinux9.1),但因为docker的特性,适用场景是不限于此的。 文档形成时期:2017-2023年 因系统或软件版本不同,构建…...
《新课程教学》(电子版)是正规期刊吗?能评职称吗?
《新课程教学》(电子版)主要出版内容为学科教学理论、学科教学实践经验和成果,主要读者对象为中小学教师,期刊设卷首语、名家讲堂、课程与教学、教学实践、考试评价、教育信息化、教学琐谈、教育管理、教师心语、一线课堂、重温经…...
Posgresql macOS安装和基础操作
摘要 本文介绍macOS版本Postgresql的安装,pg常用命令。作为笔记记录,后续方便查看。 Postgresql安装 官网下载postgresql安装包https://www.postgresql.org/download/。官网下载慢时,可以从这里下载我上传的mac版本的pg安装包资源。下载后&am…...
ArkUI-X跨平台已至,何需其它!
运行环境 DevEco Studio:4.0Release OpenHarmony SDK API10 开发板:润和DAYU200 自从写了一篇ArkUI-X跨平台的文章之后,好多人都说对这个项目十分关注。 那么今天我们就来完整的梳理一下这个项目。 1、ArkUI-X 我们之前可能更多接触的…...
(2024,分数蒸馏抽样,Delta 降噪分数,LoRA)PALP:文本到图像模型的提示对齐个性化
PALP: Prompt Aligned Personalization of Text-to-Image Models 公和众和号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0. 摘要 4. 提示对齐方法 4.1 概述 4.2 个性化 4.3 提示对齐分数抽…...
近日遇到数据库及其他问题
一、查找备份表和原表不一样数据 select * from A where (select count(1) from A_BAK where A.IDA_BAK.ID) 0 二、在数据量比较大的表中新增有默认值的列速度较慢问题 使用 以下语句,在上亿数据的表中执行速度较慢 alter table TEST add col_a integer DEFA…...
【conda】conda 版本控制和环境迁移/安装conda加速工具mamba /conda常用指令/Anaconda配置
【conda】安装conda加速工具mamba /conda常用指令/Anaconda配置 0. conda 版本控制和环境迁移1. 安装conda加速工具mamba2. conda install version3. [Anaconda 镜像](https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/)使用帮助4. error deal 0. conda 版本控制和环境迁移…...
“/bin/bash“: stat /bin/bash: no such file or directory: unknown
简介:常规情况下,在进入容器时习惯使用 /bin/bash为结尾,如:docker exec -it test-sanic /bin/bash, 但是如果容器本身使用了精简版,只装了sh命令,未安装bash。这时就会抛出"/bin/bash&quo…...
基于Spring Boot+vue的云上新鲜水果超市商城系统
本云上水果超市是为了提高用户查阅信息的效率和管理人员管理信息的工作效率,可以快速存储大量数据,还有信息检索功能,这大大的满足了用户、员工信息和管理员这三者的需求。操作简单易懂,合理分析各个模块的功能,尽可能…...
vue-ESlint代码规范及修复
1. 介绍 ESLint:是一个代码检查工具,用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)。 在创建项目时,我们使用的是 JavaScript Standard Style 代码风格的规则。 规范网址:https://standardjs.com/rules-zhcn.htm…...
Oracle数据库断电后不能打开的解决
数据库突然断电后,不能打开。或者偶尔能打开,但是很快就关闭。 原因可能很多。但是解决问题只有一种办法:看trace日志,alert错误日志 简单写下我的解决过程: 1,在alert日志中: 错误如下两种:…...
论文复现: In-Loop Filter with Customized Weights For VVC Intra Coding
论文复现: In-Loop Filter with Customized Weights For VVC Intra Coding 这个好难好难。啊啊啊啊。核心:权重预测模块功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的…...
配置华为设备NQA UDP Jitter检测VoIP业务抖动
组网需求 如图1所示,总部和子公司之间需要跨越外部网络进行通信,DeviceA和DeviceD为总部和子公司的网络出口设备,DeviceB和DeviceC为外部网络提供商的边缘设备。 总部和子公司之间经常要通过VoIP进行电话会议,要求双向时延小于2…...
GitHub要求所有贡献代码的用户在2023年底前启用双因素认证
到2023年底,所有向github托管的存储库贡献代码的用户都必须启用一种或多种形式的2FA。 双重身份认证 所谓双重身份认证(Two-Factor Authentication),就是在账号密码以外还额外需要一种方式来确认用户身份。 GitHub正在大力推动双…...
Nginx——强化基础配置
1、牢记Context Context是Nginx中每条指令都会附带的信息,用来说明指令在哪个指令块中使用,可以将Context 理解为配置环境。 每个指令都拥有自己的配置环境,如果把配置环境记错了,或者在设计时未考虑配置环境的作用,…...
黑马苍穹外卖学习Day6
HttpClient 介绍 HttpClient 是 Apache 提供的一个开源的 Java HTTP 客户端库,用于发送 HTTP 请求和处理 HTTP 响应。它提供了一种更简便的方式来执行 HTTP 请求,并支持多种协议,如 HTTP、HTTPS、FTP 等。 使用 HttpClient 可以方便地与远程…...
【Java 设计模式】设计原则之里氏替换原则
文章目录 1. 定义2. 好处3. 应用4. 示例结语 在软件开发中,设计原则是创建灵活、可维护和可扩展软件的基础。 这些原则为我们提供了指导方针,帮助我们构建高质量、易理解的代码。 ✨单一职责原则(SRP) ✨开放/封闭原则(…...
一步步指南:从指定时长中提取需求的帧图片,高效剪辑视频
在现代多媒体时代,视频已经成生活中不可或缺的一部分。从视频中提取某一帧图片,或者对视频进行剪辑,都是常见的需求。下面一起来看云炫AI智剪如何从指定时长中提取需求的帧图片,如何高效地剪辑视频。 按指定时长提取视频某帧图片的…...
【打卡】牛客网:BM93 盛水最多的容器
题目: 考虑到盛水容器的特殊性。双指针从最两边开始遍历,遍历过程中舍弃最小的。 不知道原理。 模板的: class Solution { public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*…...
Golang 文件操作
读取 一次性读取 data, err : os.ReadFile("filename.txt") if err ! nil {log.Fatal(err) } fmt.Println(string(data))按行读取 方式1:bufio.NewScanner file, err : os.Open("filename.txt") if err ! nil {panic(err) } defer file.Clo…...
C++I/O流——(3)文件输入/输出(第二节)
归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言📝 含泪播种的人一定能含笑收获ÿ…...
内网穿透[让你在家里也能榨干学校的服务器]Yep!
内网穿透 问题:什么是内网穿透,内网穿透的作用是什么? 前提!!!!你得拥有超级管理员的权限,比如root,不然后面的一切免提! 应用场景如下:比如你…...
企业门户网站费用/武汉seo公司排名
Mojo C 绑定 API 官方文档:https://chromium.googlesource.com/chromium/src.git//refs/heads/main/mojo/README.md 本文档是Mojo 文档的子集。 概述 Mojo C 绑定 API 利用C 系统 API提供一组更自然的原语,用于通过 Mojo 消息管道进行通信。结合从Mojom IDL 和绑…...
网站的开发环境设计/seo数据是什么意思
我愿称之为丑陋数组好吧 时隔数日,重做了一遍,在一开始想思路的时候,想得有点久,其实两句话概括。 // 1 // 1 2 // 1 3 2 // 1 3 2 4 要求两个数的漂亮数组,要从一个数的出发,将一个数乘2-1变为奇数放在左…...
怎样看一个网站是哪个公司做的/四川网站制作
http://acm.hdu.edu.cn/showproblem.php?pid5253 Prim算法是 1.每次选出 (已经选出的)点集 能够连接 边权值最小的点 2.使用新找出的点能带来的新的更小的边权,来更新旧的较大的边权 3.重复,直到连接所有点 的贪心算法 使用优先…...
behance设计网站图片/十大新媒体平台有哪些
SeismicPro是一个地震剖面显示软件,可从标准SEGY地震数据体中抽取纵测线和横测线的二维剖面,并以波形、变面积和变密度等多种方式进行专业化显示,可进行一键式显示方式切换,并可进行定制开发叠加井轨迹与测井曲线等。 我感觉最人性…...
泰州市网站建设/seo薪资
flex里的[Inspectable]标签用于为as类的属性定义一些可供flex代码提示等使用的信息,比如属性的类型啦合法值啦默认值啦之类的,[Inspectable]标签可以用在属性上,也可以用在getter/setter方法上,写法如下: [Inspectable…...
注册网站怎么注销/营销方法有哪些方式
本人已经疯了...快写完了而关掉浏览器丢失数据之事在此文章上发生了两次,所以本人倍加珍惜这节讲 一下Asp.netMVC中的Helper何谓Helper,其实就是在View中为了实现一些灵活功能而写的方法组其实Asp.net MVC的View是Aspx的页面,本身可以声明定义方法,那为什么要有Helper呢其实无非…...