rkmedia的使用

一、rkmedia_test测试例程

        RKMedia 的核心思想是把各个硬件资源独立成模块,模块开放出输入和输出端通过绑定的方式控制流从某个模块流出并且流入另外一个模块

        目前 rk 平台可以支持的摄像头数据 yuv 和 raw 数据。 Raw 数据是没有经过 isp 信号处理的原始数据,需要 rk 芯片内部 isp 图像处理才能还原真实图像。 Yuv 数据是 camera 端的 isp 经过处理后送出来的数据。  

 rkmedia的使用:

代码目录:external/rkmedia/examples/

本文以rkmedia_vi_vo_test.c为例,还有许多的例程,大家可以自行研究。

#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include "common/sample_common.h"
#include "rkmedia_api.h"

static bool quit = false;
static void sigterm_handler(int sig) {
  fprintf(stderr, "signal %d\n", sig);
  quit = true;
}

static RK_CHAR optstr[] = "?::a::I:M:";
static const struct option long_options[] = {
    {"aiq", optional_argument, NULL, 'a'},
    {"camid", required_argument, NULL, 'I'},
    {"multictx", required_argument, NULL, 'M'},
    {"help", optional_argument, NULL, '?'},
    {NULL, 0, NULL, 0},
};

static void print_usage(const RK_CHAR *name) {
  printf("usage example:\n");
#ifdef RKAIQ
  printf("\t%s [-a [iqfiles_dir]]"
         "[-I 0] "
         "[-M 0] "
         "\n",
         name);
  printf("\t-a | --aiq: enable aiq with dirpath provided, eg:-a "
         "/oem/etc/iqfiles/, "
         "set dirpath empty to using path by default, without this option aiq "
         "should run in other application\n");
  printf("\t-M | --multictx: switch of multictx in isp, set 0 to disable, set "
         "1 to enable. Default: 0\n");
#else
  printf("\t%s [-I 0]\n", name);
#endif
  printf("\t-I | --camid: camera ctx id, Default 0\n");
}

int main(int argc, char *argv[]) {
  int ret = 0;
  int video_width = 400;
  int video_height = 400;
  int disp_width = 720;
  int disp_height = 1280;
  RK_S32 s32CamId = 0;
#ifdef RKAIQ
  RK_BOOL bMultictx = RK_FALSE;
#endif
  int c;
  char *iq_file_dir = NULL;
  while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) {
    const char *tmp_optarg = optarg;
    switch (c) {
    case 'a':
      if (!optarg && NULL != argv[optind] && '-' != argv[optind][0]) {
        tmp_optarg = argv[optind++];
      }
      if (tmp_optarg) {
        iq_file_dir = (char *)tmp_optarg;
      } else {
        iq_file_dir = "/oem/etc/iqfiles";
      }
      break;
    case 'I':
      s32CamId = atoi(optarg);
      break;
#ifdef RKAIQ
    case 'M':
      if (atoi(optarg)) {
        bMultictx = RK_TRUE;
      }
      break;
#endif
    case '?':
    default:
      print_usage(argv[0]);
      return 0;
    }
  }

  printf("#zcy CameraIdx: %d\n\n", s32CamId);
  if (iq_file_dir) {
#ifdef RKAIQ
    printf("#Rkaiq XML DirPath: %s\n", iq_file_dir);
    printf("#bMultictx: %d\n\n", bMultictx);
    rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL;
    int fps = 30;
    SAMPLE_COMM_ISP_Init(s32CamId, hdr_mode, bMultictx, iq_file_dir);
    SAMPLE_COMM_ISP_Run(s32CamId);
    SAMPLE_COMM_ISP_SetFrameRate(s32CamId, fps);
#endif
  }

  RK_MPI_SYS_Init();
  VI_CHN_ATTR_S vi_chn_attr;
  vi_chn_attr.pcVideoNode = "rkispp_scale0";
  vi_chn_attr.u32BufCnt = 3;
  vi_chn_attr.u32Width = video_width;
  vi_chn_attr.u32Height = video_height;
  vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
  vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
  ret = RK_MPI_VI_SetChnAttr(s32CamId, 0, &vi_chn_attr);
  ret |= RK_MPI_VI_EnableChn(s32CamId, 0);
  if (ret) {
    printf("Create vi[0] failed! ret=%d\n", ret);
    return -1;
  }

  /* test rgn cover */
  COVER_INFO_S CoverInfo;
  OSD_REGION_INFO_S RngInfo;
  memset(&CoverInfo, 0, sizeof(CoverInfo));
  memset(&RngInfo, 0, sizeof(RngInfo));
  CoverInfo.enPixelFormat = PIXEL_FORMAT_ARGB_8888;
  CoverInfo.u32Color = 0xFFFF0000; // blue
  RngInfo.enRegionId = REGION_ID_0;
  RngInfo.u32PosX = 0;
  RngInfo.u32PosY = 0;
  RngInfo.u32Width = 100;
  RngInfo.u32Height = 100;
  RngInfo.u8Enable = 1;
  RK_MPI_VI_RGN_SetCover(s32CamId, 1, &RngInfo, &CoverInfo);

  // rga0 for primary plane
  RGA_ATTR_S stRgaAttr;
  memset(&stRgaAttr, 0, sizeof(stRgaAttr));
  stRgaAttr.bEnBufPool = RK_TRUE;
  stRgaAttr.u16BufPoolCnt = 3;
  stRgaAttr.u16Rotaion = 90;
  stRgaAttr.stImgIn.u32X = 0;
  stRgaAttr.stImgIn.u32Y = 0;
  stRgaAttr.stImgIn.imgType = IMAGE_TYPE_NV12;
  stRgaAttr.stImgIn.u32Width = video_width;
  stRgaAttr.stImgIn.u32Height = video_height;
  stRgaAttr.stImgIn.u32HorStride = video_width;
  stRgaAttr.stImgIn.u32VirStride = video_height;
  stRgaAttr.stImgOut.u32X = 0;
  stRgaAttr.stImgOut.u32Y = 0;
  stRgaAttr.stImgOut.imgType = IMAGE_TYPE_RGB888;
  stRgaAttr.stImgOut.u32Width = disp_width;
  stRgaAttr.stImgOut.u32Height = disp_height;
  stRgaAttr.stImgOut.u32HorStride = disp_width;
  stRgaAttr.stImgOut.u32VirStride = disp_height;
  ret = RK_MPI_RGA_CreateChn(0, &stRgaAttr);
  if (ret) {
    printf("Create rga[0] falied! ret=%d\n", ret);
    return -1;
  }

  VO_CHN_ATTR_S stVoAttr = {0};
  // VO[0] for primary plane
  stVoAttr.pcDevNode = "/dev/dri/card0";
  stVoAttr.emPlaneType = VO_PLANE_PRIMARY;
  stVoAttr.enImgType = IMAGE_TYPE_RGB888;
  stVoAttr.u16Zpos = 0;
  stVoAttr.stDispRect.s32X = 0;
  stVoAttr.stDispRect.s32Y = 0;
  stVoAttr.stDispRect.u32Width = disp_width;
  stVoAttr.stDispRect.u32Height = disp_height;
  ret = RK_MPI_VO_CreateChn(0, &stVoAttr);
  if (ret) {
    printf("Create vo[0] failed! ret=%d\n", ret);
    return -1;
  }

  MPP_CHN_S stSrcChn = {0};
  MPP_CHN_S stDestChn = {0};

  printf("#Bind VI[0] to RGA[0]....\n");
  stSrcChn.enModId = RK_ID_VI;
  stSrcChn.s32ChnId = 0;
  stDestChn.enModId = RK_ID_RGA;
  stDestChn.s32ChnId = 0;
  ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
  if (ret) {
    printf("Bind vi[0] to rga[0] failed! ret=%d\n", ret);
    return -1;
  }

  printf("# Bind RGA[0] to VO[0]....\n");
  stSrcChn.enModId = RK_ID_RGA;
  stSrcChn.s32ChnId = 0;
  stDestChn.enModId = RK_ID_VO;
  stDestChn.s32ChnId = 0;
  ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
  if (ret) {
    printf("Bind rga[0] to vo[0] failed! ret=%d\n", ret);
    return -1;
  }

  printf("%s initial finish\n", __func__);
  signal(SIGINT, sigterm_handler);
  while (!quit) {
    usleep(500000);
  }

  printf("%s exit!\n", __func__);
  stSrcChn.enModId = RK_ID_VI;
  stSrcChn.s32ChnId = 0;
  stDestChn.enModId = RK_ID_RGA;
  stDestChn.s32ChnId = 0;
  ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
  if (ret) {
    printf("UnBind vi[0] to rga[0] failed! ret=%d\n", ret);
    return -1;
  }

  stSrcChn.enModId = RK_ID_RGA;
  stSrcChn.s32ChnId = 0;
  stDestChn.enModId = RK_ID_VO;
  stDestChn.s32ChnId = 0;
  ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
  if (ret) {
    printf("UnBind rga[0] to vo[0] failed! ret=%d\n", ret);
    return -1;
  }

  RK_MPI_VO_DestroyChn(0);
  RK_MPI_RGA_DestroyChn(0);
  RK_MPI_VI_DisableChn(s32CamId, 0);

  if (iq_file_dir) {
#ifdef RKAIQ
    SAMPLE_COMM_ISP_Stop(s32CamId);
#endif
  }
  return 0;
}

具体地解释一下代码的功能。

  1. 首先,代码通过getopt_long函数解析命令行参数。其中,-a或--aiq参数可选择是否启用AIQ(图像质量增强),可以提供IQ文件的目录作为参数;-I或--camid参数用于指定摄像头的编号;-M或--multictx参数用于选择是否启用多通道配置。
  2. 如果启用了AIQ(定义了RKAIQ宏),则会调用SAMPLE_COMM_ISP_Init函数进行AIQ模块的初始化配置,并根据参数设置HDR模式和是否启用多通道配置。然后调用SAMPLE_COMM_ISP_Run函数开始运行ISP(图像信号处理)模块,并设置帧率。
  3. 调用RK_MPI_SYS_Init函数进行系统初始化。
  4. 设置视频输入通道属性,包括视频宽高、像素格式、工作模式等,并通过RK_MPI_VI_SetChnAttr和RK_MPI_VI_EnableChn函数使能视频输入通道。
  5. 测试遮挡区域(cover)。创建COVER_INFO_S和OSD_REGION_INFO_S结构体来设置遮挡区域的颜色、位置和大小等信息,然后调用RK_MPI_VI_RGN_SetCover函数将遮挡区域应用到视频输入通道上。
  6. 使用RGA(Rockchip Graphics Accelerator)模块进行图像转换。首先创建RGA_ATTR_S结构体,设置输入图像和输出图像的参数,包括图像类型、宽高、步长等。然后调用RK_MPI_RGA_CreateChn函数创建RGA通道。
  7. 创建VO(Video Output)通道用于显示视频到屏幕上。设置VO的设备节点、平面类型、图像类型、显示位置和大小等参数,并调用RK_MPI_VO_CreateChn函数创建VO通道。
  8. 通过RK_MPI_SYS_Bind函数将VI(Video Input)通道和RGA通道、RGA通道和VO通道进行绑定,从而实现视频输入、处理和输出的流程。
  9. 进入主循环,等待SIGINT信号(通过signal函数注册了SIGINT的处理函数)。主循环中使用usleep函数暂停程序500毫秒,直到接收到SIGINT信号时退出循环。
  10. 在退出之前,调用RK_MPI_SYS_UnBind函数解绑VI和RGA通道、RGA和VO通道。然后销毁RGA通道和VO通道,最后禁用视频输入通道。
  11. 如果启用了AIQ(定义了RKAIQ宏),则调用SAMPLE_COMM_ISP_Stop函数停止ISP模块的运行。

 二、RKMedia例程测试注意事项

查看图像的stride,图像的stride(跨度、跨距、步长、步幅),表示在内存中每行像素所占的字节数。

在RKMedia下,设置采集的图像的宽度能被16整除,且stride=图像的宽度即可!

即:400x400

图像buffer宽度 = stride宽度

stride宽度 / 16 = 整数n

1.不能在开启ispserver服务的时候又指定 iqfiles,会报错,两者存在冲突,二者选其一。

1)查看ispserver服务是否已经开启了:

ps -aux | grep ispserver

2)开启ispserver服务:

ispserver --no-sync-db & // 表示不开启数据库服务dbserver

// 或者

ispserver &

3)关闭ispserver服务:

kill -9 3050

2.如果开启了摄像头应用(mediaserver),请先将其关闭后才可以使用RKMedia抓取图片。

开启和关闭mediaserver的脚本在开发板的/oem目录下:

// 开启摄像头应用(mediaserver

/oem/RkLunch.sh &

// 关闭摄像头应用(mediaserver

/oem/RkLunch-stop.sh

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/202406.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【排序】希尔排序(C语言实现)

文章目录 前言1. 希尔排序的思想2. 希尔排序的一些小优化 前言 本章将详细介绍希尔排序的思想及实现&#xff0c;由于希尔排序是在插入排序的思想上进行升华&#xff0c;所以如果不知道插入排序或者不熟悉的可以先看看这篇文章&#xff1a;《简单排序》中的直接插入排序。 1. 希…

【数据结构】——堆排序

前言&#xff1a;我们已经学习了堆以及实现了堆&#xff0c;那么我们就来给堆进行排序。我们怎么来进行排序呢&#xff1f;这一次我们就来解决这个问题。 如果我们堆排序要求排序&#xff0c;我们是建立大堆还是小堆呢&#xff0c;如果我们建的小堆的话&#xff0c;那我们在排序…

上海亚商投顾:沪指震荡下跌 成交量继续下破8000亿

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日震荡调整&#xff0c;深成指、创业板指午后跌超1%&#xff0c;北证50指数跌超7%&#xff0c;超百只北…

LoadRunner自动化测试工具的应用

目录 第一部分:Loadrunner的简介 1.1 安装注意事项 1.2 协议的选择或者 VUSER 类型的选取 1.3 LR 的基本原理 1.4 测试脚本录制/分配所遵循的几个原则 第二部分:录制脚本 2.1 录制脚本前需要理解的几个基本概念 2.1.1 事务(Transaction) 2.1.2 集合点(Rendezvous) 2.1…

EG系列网关+CLC控制器串口远程下载程序操作说明

EG系列网关CLC控制器串口远程下载程序操作说明 前言&#xff1a;本文档主要说明了使用蓝蜂虚拟网络工具远程给PLC下载程序的步骤及其注意事项。使用蓝蜂虚拟网络工具&#xff0c;不仅支持程序的远程下载&#xff0c;同样支持程序的远程上传与在线监控。 注意&#xff1a;蓝蜂…

vivado综合分析与收敛技巧3

1、最优化 RAMB 输入逻辑以允许输出寄存器推断 以下 RTL 代码片段可从块 RAM &#xff08; 实际上为 ROM &#xff09; 生成关键路径 &#xff0c; 其中包含多个止于触发器 (FF) 的逻辑层次。 RAMB单元已在无可选输出寄存器 (DOA-0) 的情况下完成推断 &#xff0c; 这给 R…

漏洞复现--安恒明御安全网关 aaa_local_web_preview 任意文件上传

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

selenium使用记录

本文记录python环境下使用selenium的一些步骤 Step1&#xff1a;安装并配置驱动 pip install selenium # 使用pip在对应python中安装selenium包为了让selenium能调用指定的浏览器&#xff0c;需要下载对应浏览器的驱动程序&#xff08;这里以edge为例子&#xff09; #Firefo…

高效管理文件方法:根据文件大小智能移动至目标文件夹

在日常的工作中&#xff0c;会遇到大量的文件&#xff0c;从几个KB的小文档到几个GB的大数据文件。如何有效地管理这些文件&#xff0c;以便能够快速找到所需的资料&#xff0c;是一项重要的任务。传统的文件管理方式往往会在大量的文件和文件夹中迷失&#xff0c;而无法快速找…

【教程】 一文部署配置并入门 Redis

综述 什么是Redis Redis官网——Redis.io Redis, 作为一个高性能的键值对数据库&#xff0c;主要应用于以下场景&#xff1a; 缓存系统&#xff1a;由于其高速读写能力&#xff0c;Redis 非常适合用作缓存系统&#xff0c;减少数据库负载。 会话存储&#xff08;Session St…

mabatis基于xml方式和注解方式实现多表查询

前面步骤 http://t.csdnimg.cn/IPXMY 1、解释 在数据库中&#xff0c;单表的操作是最简单的&#xff0c;但是在实际业务中最少也有十几张表&#xff0c;并且表与表之间常常相互间联系&#xff1b; 一对一、一对多、多对多是表与表之间的常见的关系。 一对一&#xff1a;一张…

武汉凯迪正大KDZD5289硫化曲线测试仪(电脑无转子硫化仪)

电脑无转子硫化仪 硫化时间测试仪 硫化曲线仪 硫化曲线测试仪 武汉凯迪正大KDZD5289产品概述 KDZD5289硫化曲线测试仪&#xff08;电脑无转子硫化仪&#xff09;采用电脑控制进口温控仪进行准确控温&#xff0c;计算机适时进行数据处理并可进行统计、分析、存储对比等&#xff…

【开源视频联动物联网平台】开箱即用的物联网项目介绍

写一个开箱即用的物联网项目捐献给Dromara组织 一、平台简介 MzMedia开源视频联动物联网平台&#xff0c;简单易用&#xff0c;更适合中小企业和个人学习使用。适用于智能家居、农业监测、水利监测、工业控制&#xff0c;车联网&#xff0c;监控直播&#xff0c;慢直播等场景。…

卷积神经网络(CNN)注意力检测

文章目录 一、前言二、前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据3. 查看数据 二、数据预处理1.加载数据2. 可视化数据4. 配置数据集 三、调用官方网络模型四、设置动态学习率五、编译六、训练模型七、模型评估1. Accuracy与Loss图2. …

docker-compose部署zabbix+grafana

1.引言 1.1目的 zabbixgrafana实现图形化监控 2.部署环境 服务器ip服务版本192.168.5.137zabbix-server6.0.21192.168.5.137grafana10.2.2192.168.5.152zabbix-client6.0.21 3.部署zabbix-server 3.1 创建zabbix目录 mkdir zabbix3.2 编写docker-compose文件 cd zabbix…

从0开始学习JavaScript--JavaScript 工厂模式

JavaScript 工厂模式是一种强大的设计模式&#xff0c;它提供了一种灵活的方式来创建对象。本文将深入讨论工厂模式的基本概念、多种实现方式以及在实际应用中的各种场景。 工厂模式的基本概念 工厂模式旨在通过一个函数或方法来创建对象&#xff0c;而不是通过类直接实例化。…

00Hadoop数据仓库平台

在这里是学习大数据的第一站 什么是数据仓库常见大数据平台组件及介绍 什么是数据仓库 在计算领域&#xff0c;数据仓库&#xff08;DW 或 DWH&#xff09;也称为企业数据仓库&#xff08;EDW&#xff09;&#xff0c;是一种用于报告和数据分析的系统&#xff0c;被认为是商业智…

比特币上的有状态多重签名

无需链下通信 介绍 随着区块链和加密货币空间的发展&#xff0c;越来越需要增强安全措施来保护数字资产。 应对这一挑战的突出解决方案之一是多重签名&#xff08;多重签名&#xff09;钱包。 这些钱包在执行交易之前需要多方签名&#xff0c;从而提供额外的安全层来防止未经授…

vue+el-tooltip 封装提示框组件,只有溢出才提示

效果 封装思路 通过控制el-tooltip的disabled属性控制是否提示通过在内容上绑定mouseenter事件监听内容宽度和可视宽度&#xff0c;判断内容是否溢出 封装代码 <template><div style"display: flex" class"column-overflow"><el-tooltip…

linux 讨论题合集(个人复习)

常规文件的权限是什么&#xff1f;如何分配或修改这些权限&#xff1f;文件夹&#xff08;目录&#xff09;的权限是什么&#xff1f;显示常规文件和文件夹的区别 讨论&#xff1a;①常规的文件权限有四种&#xff0c;r可读、w可写、x可执行、-没有权限&#xff1b;②可以使用c…