廊坊做网站公司哪家好,无锡网站建设要多少钱,福州营销型网站建设价格,网站开发与设计课程设计若该文为原创文章#xff0c;转载请注明原文出处。
一、介绍
学习DRM的目的是想做类似NVR显示多路实时流#xff0c;通过勇哥#xff08;Marc)的指导#xff0c;大概流程是通过Zlmedia拉流#xff0c;RK3568的MPP解码,DRM显示#xff0c;可以使用HDMI或DIS屏幕#xf…若该文为原创文章转载请注明原文出处。
一、介绍
学习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.hstatic 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} -stdc11)
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 ./)编译后把可执行文件上传到板子运行后测试正常。 如有侵权或需要完整代码请及时联系博主。