OpenHarmony实战:帆移植案例(中)
OpenHarmony实战:帆移植案例(上)
Audio服务介绍
服务节点
基于ADM框架的audio驱动对HDI层提供三个服务hdf_audio_render、hdf_audio_capture、hdf_audio_control。 开发板audio驱动服务节点如下:
console:/dev # ls -al hdf_audio_*
crw------- 1 system system 249, 5 1970-01-01 00:21 hdf_audio_capture //录音数据流服务。
crw------- 1 system system 249, 3 1970-01-01 00:21 hdf_audio_codec_dev0 //音频设备名称。
crw------- 1 system system 249, 4 1970-01-01 00:21 hdf_audio_control //音频控制流服务。
crw------- 1 system system 249, 6 1970-01-01 00:21 hdf_audio_render //播放数据流务。
-
音频控制流服务
用来接收上层lib层下发的控制指令,包括音量控制、增益控制、通路控制,这些控制指令都是通过控制流服务下发到驱动。
-
音频数据播放流服务
用来接收上层lib层下发的音频数据和播放相关的参数,还有播放的启动、暂停、恢复、停止指令,这些指令都是由播放数据流下发到驱动。
-
音频数据录音流服务
用来向上层lib层传输音频数据和接收上层lib层下发的录音相关的参数,还有录音的启动、暂停、恢复、停止指令,这些指令都是由录音数据流下发到驱动。
驱动服务
每个audio设备包括如下服务:
hdf_audio_codec_dev0 | 音频设备名称 |
---|---|
dma_service_0 | dma 驱动服务 |
dai_service | cpu dai 驱动服务 |
codec_service_0 | codec 驱动服务 |
dsp_service_0 | dsp 驱动服务(可选项) |
hdf_audio_codec_dev1 | 音频设备名称 |
---|---|
dma_service_0 | dma 驱动服务 |
dai_service | cpu dai 驱动服务 |
codec_service_1 | accessory 驱动服务(特指smartPA) |
dsp_service_0 | dsp 驱动服务(可选项) |
代码路径
vendor/rockchip/rk3399/hdf_config/khdf
├── audio #audio私有配置文件
├── device_info
| └── device_info.hcs #设备配置文件
└── hdf.hcs #引用hcs配置文件
配置节点说明
以codec驱动为例,在device_info.hcs文件中的audio host节点下添加codec节点信息。
audio :: host {hostName = "audio_host";priority = 60;
...device_codec :: device {device0 :: deviceNode {policy = 1;priority = 50;preload = 0;permission = 0666;moduleName = "CODEC_ES8316";serviceName = "codec_service_0";deviceMatchAttr = "hdf_codec_driver";}}
...}
实现驱动
在驱动文件中实现与device_info.hcs配置节点moduleName相同的驱动逻辑。
/* HdfDriverEntry implementations */
static int32_t Es8316DriverBind(struct HdfDeviceObject *device)
{
...return HDF_SUCCESS;
}static int32_t Es8316DriverInit(struct HdfDeviceObject *device)
{
...return HDF_SUCCESS;
}/* HdfDriverEntry definitions */
struct HdfDriverEntry g_es8316DriverEntry = {.moduleVersion = 1,.moduleName = "CODEC_ES8316",.Bind = Es8316DriverBind,.Init = Es8316DriverInit,.Release = NULL,
};
HDF_INIT(g_es8316DriverEntry);
总结
基于HDF框架的ADM音频框架,为Open Harmony的音频开发提供了统一的架构基础,为各平台音频驱动适配提供了统一的接口。音频驱动可以一平台开发多平台适用,提高了开发效率。此文档对ADM框架进行了简单的介绍,希望有助于开发者开发和应用。
Camera
简介
本文以OpenHarmony 3.0为基础,讲解基于HDF(Hardware Driver Foundation)驱动框架开发的Camera驱动框架,包括Camera驱动的架构组成、功能部件的实现和服务节点详细介绍。
Camera驱动框架图
OpenHarmony HDF Camera驱动模块架构图
以Camera Host 部分做如下说明:
- HDI实现层(HDI Implementation):对上实现Open Harmony OS相机标准南向接口。
- 框架层(PipelineCore):对接HDI实现层的控制、流的转发,实现数据通路的搭建、管理相机各个硬件设备等功能。
- 适配层(Platform Adaption):屏蔽底层芯片和OS差异,支持多平台适配。
对于rk3399E/T的Usb Camera来分析,内核使用linux-4.19。Usb Camera依赖linux下的V4L2的uvc,从上面的框架图分析HDF Camera已经实现了兼容linux 的 V4L2 uvc,所以调试过程首先要保证uvc所涉及的USB和Camera的驱动正常。
Camera驱动介绍
配置信息
arch/arm64/configs/rockchip_linux_defconfig
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=y
节点信息
插入Usb Camera 前
# ls -l dev/video*
crw-rw---- 1 root root 81, 0 2013-01-18 10:59 dev/video0
crw-rw---- 1 root root 81, 1 2013-01-18 10:59 dev/video1
crw-rw---- 1 root root 81, 2 2013-01-18 10:59 dev/video2
crw-rw---- 1 root root 81, 3 2013-01-18 10:59 dev/video3
crw-rw---- 1 root root 81, 4 2013-01-18 10:59 dev/video4
crw-rw---- 1 root root 81, 5 2013-01-18 10:59 dev/video5
crw-rw---- 1 root root 81, 6 2013-01-18 10:59 dev/video6
crw-rw---- 1 root root 81, 7 2013-01-18 10:59 dev/video7
crw-rw---- 1 root root 81, 8 2013-01-18 10:59 dev/video8
crw-rw---- 1 root root 81, 9 2013-01-18 10:59 dev/video9
#
插入Usb Camera后新增节点dev/video10和dev/video11
# ls -l dev/video*
crw-rw---- 1 root root 81, 0 2013-01-18 10:59 dev/video0
crw-rw---- 1 root root 81, 1 2013-01-18 10:59 dev/video1
crw------- 1 root root 81, 10 2013-01-18 11:01 dev/video10
crw------- 1 root root 81, 11 2013-01-18 11:01 dev/video11
crw-rw---- 1 root root 81, 2 2013-01-18 10:59 dev/video2
crw-rw---- 1 root root 81, 3 2013-01-18 10:59 dev/video3
crw-rw---- 1 root root 81, 4 2013-01-18 10:59 dev/video4
crw-rw---- 1 root root 81, 5 2013-01-18 10:59 dev/video5
crw-rw---- 1 root root 81, 6 2013-01-18 10:59 dev/video6
crw-rw---- 1 root root 81, 7 2013-01-18 10:59 dev/video7
crw-rw---- 1 root root 81, 8 2013-01-18 10:59 dev/video8
crw-rw---- 1 root root 81, 9 2013-01-18 10:59 dev/video9
#
打开设备节点
在Open Harmony OS的代码环境中,编译如下代码为可执行程序,在开发板测执行,无报错说明该节点open success。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>int main(void)
{// 1. 打开设备int fd = open("/dev/video10", O_RDWR);if (fd < 0) {printf("open device fail\n");return -1;}close(fd);return 0;
}
获取参数
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>int main(void)
{// 1. 打开设备int fd = open("/dev/video10", O_RDWR);if (fd < 0) {printf("open device fail\n");return -1;}// 2. 获取摄像头支持的格式 ioctl(文件描述符, 命令, 与命令对应的结构体)struct v4l2_fmtdesc v4fmt;v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int i = 0;while(1) {v4fmt.index = i++;int ret = ioctl(fd, VIDIOC_ENUM_FMT, &v4fmt);if (ret < 0) {printf("get fmt fail\n");}unsigned char *p = (unsigned char*)&v4fmt.pixelformat;printf("index=%d\n", v4fmt.index);printf("flags=%d\n", v4fmt.flags);printf("description=%s\n", v4fmt.description);printf("pixelformat=%c%c%c%c\n", p[0], p[1], p[2], p[3]);printf("reserved=%d\n", v4fmt.reserved[0]);}close(fd);return 0;
}
在Open Harmony OS的代码环境中,编译如上代码为可执行程序,在开发板测执行。结果显示支持YUYV和MJPEG 2种输出格式。
index=0flags=0description=YUYV 4:2:2pixelformat=YUYVreserved=0index=1flags=1description=Motion-JPEGpixelformat=MJPGreserved=0
设置缓冲区队列
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>int main(void)
{// 1. 打开设备int fd = open("/dev/video10", O_RDWR);if (fd < 0) {printf("open device fail\n");return -1;}// 2. 设置采集格式struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;vfmt.fmt.pix.width = 640;vfmt.fmt.pix.height = 480;vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; // 设置的视频采集格式(与上面获取的格式一致)int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt); // 设置格式if (ret < 0) {printf("set fmt fail\n");return -1;}memset(&vfmt, 0, sizeof(vfmt));vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd, VIDIOC_G_FMT, &vfmt); // 获取格式if (ret < 0) {printf("set->get fmt fail\n");return -1;}// 3. 申请内核缓冲区队列struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; // 申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP; // 内存映射方式 MMAP/USERPTRret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer); // 分配内存if (ret < 0) {printf("req buffer fail\n");return -1;}// 4. 关闭设备close(fd);return 0;
}
在Open Harmony OS的代码环境中,编译如上代码为可执行程序,在开发板测执行。
执行结果:req buffer fail
原因分析:ioctl(fd, VIDIOC_REQBUFS, &reqbuffer); 失败
定位方法1:在内核中加LOG定位VIDIOC_REQBUFS失败的地方。发现所有的ioctl命令下发后都会使用drivers/media/v4l2-core/v4l2-ioctl.c中的video_usercopy接口,但还是没有定位到具体的失败原因。
定位方法2:求助视美泰验证linux-4.19内核debian版本的Usb Camera是否OK。结果:debian版本使用gst-launch-1.0 v4l2src device=/dev/video10 ! image/jpeg, width= 1280, height=720, framerate=30/1 ! jpegparse ! mppjpegdec ! kmssink sync=false命令后HDMI屏幕可以出来正常的预览画面。
通过如上的操作后,基本可以确认linux的V4L2 uvc驱动和外设Usb Camera驱动都是正常的。接下来就该调试Open Harmony OS的HDF Camera了。
接口介绍
查看现有Open Harmony OS上的关于camera的可执行程序:ohos_camera_demo、v4l2_main
ohos_camera_demo
执行结果:输入o后无预览画面,也无LOG报错信息。
# ohos_camera_demo
GetUintParameter debug.bytrace.tags.enableflags error.
Options:
-h | --help Print this message
-o | --offline stream offline test
-c | --capture capture one picture
-w | --set WB Set white balance Cloudy
-v | --video capture Viedeo of 10s
-a | --Set AE Set Auto exposure
-f | --Set Flashlight Set flashlight ON 5s OFF
-q | --quit stop preview and quit this app
o
Options:
-h | --help Print this message
-o | --offline stream offline test
-c | --capture capture one picture
-w | --set WB Set white balance Cloudy
-v | --video capture Viedeo of 10s
-a | --Set AE Set Auto exposure
-f | --Set Flashlight Set flashlight ON 5s OFF
-q | --quit stop preview and quit this app
原因分析:ohos_camera_demo目前仅支持MPP,不支持V4L2,故先放弃该demo调试。
v4l2_main
执行结果:输入u 报错:ERROR:main test:cannot open framebuffer /dev/fb0 file node
Options:
-h | --help Print this message
-p | --preview start preview on platform sensor
-c | --capture capture one picture
-w | --set WB Set white balance Cloudy
-e | --Set AE Set exposure time
-v | --video capture Viedeo of 10s
-u | --uvc start preview on uvc preview
-a | --Set ATE Set Auto exposure
-q | --quit stop preview and quit this app
INFO:please input command(input -q exit this app)u
ERROR:main test:cannot open framebuffer /dev/fb0 file nodeINFO:V4L2OpenDevice /dev/video10
原因分析:查看dev/fb0节点是否存在:不存在fb0节点。继续查找根目录下有无其他fb0节点,出现了dev/graphics/fb0节点。
# ls -l dev/fb0
ls: dev/fb0: No such file or directory# find -name fb0
./dev/graphics/fb0
./sys/class/graphics/fb0
./sys/devices/platform/display-subsystem/graphics/fb0
需把v4l2_main可执行程序中的dev/fb0改为dev/graphics/fb0。此处fb0为framebuffer,作用是在屏幕上显示预览画面。
修改点:drivers/peripheral
diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp
index b351f49..d9c4cb3 100755
--- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp
+++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp
@@ -186,9 +186,9 @@ RetCode FBInit()if (g_fbFd)return RC_OK;- g_fbFd = open("/dev/fb0", O_RDWR);
+ g_fbFd = open("/dev/graphics/fb0", O_RDWR);if (g_fbFd < 0) {
- CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/fb0");
+ CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/graphics/fb0");return RC_ERROR;}diff --git a/camera/hal/test/v4l2/src/test_display.cpp b/camera/hal/test/v4l2/src/test_display.cpp
index db908e7..7025deb 100644
--- a/camera/hal/test/v4l2/src/test_display.cpp
+++ b/camera/hal/test/v4l2/src/test_display.cpp
@@ -114,9 +114,9 @@ void TestDisplay::FBLog()RetCode TestDisplay::FBInit(){
- fbFd_ = open("/dev/fb0", O_RDWR);
+ fbFd_ = open("/dev/graphics/fb0", O_RDWR);if (fbFd_ < 0) {
- CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/fb0");
+ CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/graphics/fb0");return RC_ERROR;}@@ -439,4 +439,4 @@ void TestDisplay::StopStream(std::vector<int>& captureIds, std::vector<int>& strstd::cout << "==========[test log]check Capture: ReleaseStreams fail, rc = " << rc << std::endl;}}
-}
\ No newline at end of file
+}
diff --git a/display/hal/default/display_layer.c b/display/hal/default/display_layer.c
index ee7a825..e12a653 100644
--- a/display/hal/default/display_layer.c
+++ b/display/hal/default/display_layer.c
@@ -24,7 +24,7 @@#define DEV_ID 0#define LAYER_ID 0
-#define FB_PATH "/dev/fb0"
+#define FB_PATH "/dev/graphics/fb0"#define DISP_WIDTH 800#define DISP_HEIGHT 480#define BITS_PER_PIXEL 32
修改后重新编译v4l2_main,编译命令:./build.sh --product-name rk3399 --ccache --build-target v4l2_main
编译成功后可执行程序路径:./out/rk3399/hdf/hdf/v4l2_main
将新编译的v4l2_main推送到开发板测的system/bin路径下:
hdc shell "mount -o rw,remount /"
hdc file send D:\cyyanl\work\RockChip\bin\v4l2_main /system/bin
继续执行v4l2_main结果后无framebuffer报错,说明该问题已解决。(另一种思路:分析fb0为何在/dev/graphics/fb0而不是常规的/dev/fb0,然后修改为/dev/fb0。后面有时间再调试该思路)
新报错:ERROR:error: ioctl VIDIOC_QUERYBUF failed.
Options:
-h | --help Print this message
-p | --preview start preview on platform sensor
-c | --capture capture one picture
-w | --set WB Set white balance Cloudy
-e | --Set AE Set exposure time
-v | --video capture Viedeo of 10s
-u | --uvc start preview on uvc preview
-a | --Set ATE Set Auto exposure
-q | --quit stop preview and quit this app
INFO:please input command(input -q exit this app)
u
INFO:the fixed information is as follow:
INFO:id=
INFO:sem_start=0
INFO:smem_len=2457600
...
INFO:V4L2AllocBuffer
INFO:V4L2AllocBuffer:memoryType_ = 2
INFO:V4L2AllocBuffer:V4L2_MEMORY_USERPTR = 2
INFO:V4L2AllocBuffer:VIDIOC_QUERYBUF = 3226490377
ERROR:error: ioctl VIDIOC_QUERYBUF failed.
ERROR:error: Creatbuffer: V4L2AllocBuffer error
ERROR:main test:V4L2PreviewThread CreatBuffer fail i = 0
原因分析:ioctl(fd, VIDIOC_QUERYBUF, &buf)失败。回过头再看"调试linux L4V2 uvc驱动章节->设置格式申请缓冲区队列"中的报错也是
ioctl(fd, VIDIOC_REQBUFS, &reqbuffer)。由此分析出Open Harmony OS上的ioctl VIDIOC_REQBUFS都会报错。再看两次失败的差异点:
内存映射方式不同: V4L2_MEMORY_MMAP和V4L2_MEMORY_USERPTR
从OpenHarmony的issuse得知暂不支持V4L2_MEMORY_MMAP内存映射,映射方式就分析到这里,接下来还是用v4l2_main的V4L2_MEMORY_USERPTR进行调试分析。
参考:V4L2设备增加MMAP申请内存的方式和下图
接着再分析ioctl(fd, VIDIOC_QUERYBUF, &buf)失败,查看VIDIOC_QUERYBUF的定义:videodev2.h
#define VIDIOC_QUERYBUF_IOWR('V', 9, struct v4l2_buffer)
此处插入ioctl的定义:int ioctl(int fd, int cmd, …); VIDIOC_QUERYBUF作为cmd的入参,是int类型。也就是一个数字命令码,该命令码通过ioctl发送给内核后,会有与之对应的函数操作,故用户态下发的命令码应和内核接受的命令码一致。下面验证命令码一致性。
videodev2.h中一共有77个和内核交互的命令码,把内核态和用户态的都打印出来做对比:
用户态加打印:drivers/peripheral
diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp
index d7dd15f..f7254b4 100644
--- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp
+++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp
@@ -162,37 +162,119 @@ RetCode HosV4L2Buffers::V4L2DequeueBuffer(int fd)return RC_OK;}+static void cyyanl_printf_cmd(void)
+{
+#if 1
+ CAMERA_LOGD("*************************************************************************************");
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCAP ) = 0x%x\n", VIDIOC_QUERYCAP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FMT ) = 0x%x\n", VIDIOC_ENUM_FMT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_FMT ) = 0x%x\n", VIDIOC_G_FMT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_FMT ) = 0x%x\n", VIDIOC_S_FMT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_REQBUFS ) = 0x%x\n", VIDIOC_REQBUFS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYBUF ) = 0x%x\n", VIDIOC_QUERYBUF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_FBUF ) = 0x%x\n", VIDIOC_G_FBUF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_FBUF ) = 0x%x\n", VIDIOC_S_FBUF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_OVERLAY ) = 0x%x\n", VIDIOC_OVERLAY );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QBUF ) = 0x%x\n", VIDIOC_QBUF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_EXPBUF ) = 0x%x\n", VIDIOC_EXPBUF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DQBUF ) = 0x%x\n", VIDIOC_DQBUF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMON ) = 0x%x\n", VIDIOC_STREAMON );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMOFF ) = 0x%x\n", VIDIOC_STREAMOFF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_PARM ) = 0x%x\n", VIDIOC_G_PARM );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_PARM ) = 0x%x\n", VIDIOC_S_PARM );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_STD ) = 0x%x\n", VIDIOC_G_STD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_STD ) = 0x%x\n", VIDIOC_S_STD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMSTD ) = 0x%x\n", VIDIOC_ENUMSTD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMINPUT ) = 0x%x\n", VIDIOC_ENUMINPUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_CTRL ) = 0x%x\n", VIDIOC_G_CTRL );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_CTRL ) = 0x%x\n", VIDIOC_S_CTRL );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_TUNER ) = 0x%x\n", VIDIOC_G_TUNER );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_TUNER ) = 0x%x\n", VIDIOC_S_TUNER );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDIO ) = 0x%x\n", VIDIOC_G_AUDIO );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDIO ) = 0x%x\n", VIDIOC_S_AUDIO );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCTRL ) = 0x%x\n", VIDIOC_QUERYCTRL );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYMENU ) = 0x%x\n", VIDIOC_QUERYMENU );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_INPUT ) = 0x%x\n", VIDIOC_G_INPUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_INPUT ) = 0x%x\n", VIDIOC_S_INPUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_EDID ) = 0x%x\n", VIDIOC_G_EDID );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_EDID ) = 0x%x\n", VIDIOC_S_EDID );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_OUTPUT ) = 0x%x\n", VIDIOC_G_OUTPUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_OUTPUT ) = 0x%x\n", VIDIOC_S_OUTPUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMOUTPUT ) = 0x%x\n", VIDIOC_ENUMOUTPUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDOUT ) = 0x%x\n", VIDIOC_G_AUDOUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDOUT ) = 0x%x\n", VIDIOC_S_AUDOUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_MODULATOR ) = 0x%x\n", VIDIOC_G_MODULATOR );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_MODULATOR ) = 0x%x\n", VIDIOC_S_MODULATOR );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_FREQUENCY ) = 0x%x\n", VIDIOC_G_FREQUENCY );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_FREQUENCY ) = 0x%x\n", VIDIOC_S_FREQUENCY );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_CROPCAP ) = 0x%x\n", VIDIOC_CROPCAP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_CROP ) = 0x%x\n", VIDIOC_G_CROP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_CROP ) = 0x%x\n", VIDIOC_S_CROP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_JPEGCOMP ) = 0x%x\n", VIDIOC_G_JPEGCOMP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_JPEGCOMP ) = 0x%x\n", VIDIOC_S_JPEGCOMP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYSTD ) = 0x%x\n", VIDIOC_QUERYSTD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_FMT ) = 0x%x\n", VIDIOC_TRY_FMT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDIO ) = 0x%x\n", VIDIOC_ENUMAUDIO );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDOUT ) = 0x%x\n", VIDIOC_ENUMAUDOUT );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_PRIORITY ) = 0x%x\n", VIDIOC_G_PRIORITY );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_PRIORITY ) = 0x%x\n", VIDIOC_S_PRIORITY );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_SLICED_VBI_CAP ) = 0x%x\n", VIDIOC_G_SLICED_VBI_CAP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_LOG_STATUS ) = 0x%x\n", VIDIOC_LOG_STATUS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_EXT_CTRLS ) = 0x%x\n", VIDIOC_G_EXT_CTRLS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_EXT_CTRLS ) = 0x%x\n", VIDIOC_S_EXT_CTRLS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_EXT_CTRLS ) = 0x%x\n", VIDIOC_TRY_EXT_CTRLS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMESIZES ) = 0x%x\n", VIDIOC_ENUM_FRAMESIZES );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMEINTERVALS) = 0x%x\n", VIDIOC_ENUM_FRAMEINTERVALS);
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_ENC_INDEX ) = 0x%x\n", VIDIOC_G_ENC_INDEX );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENCODER_CMD ) = 0x%x\n", VIDIOC_ENCODER_CMD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_ENCODER_CMD ) = 0x%x\n", VIDIOC_TRY_ENCODER_CMD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_HW_FREQ_SEEK ) = 0x%x\n", VIDIOC_S_HW_FREQ_SEEK );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_CREATE_BUFS ) = 0x%x\n", VIDIOC_CREATE_BUFS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_PREPARE_BUF ) = 0x%x\n", VIDIOC_PREPARE_BUF );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_SELECTION ) = 0x%x\n", VIDIOC_G_SELECTION );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_SELECTION ) = 0x%x\n", VIDIOC_S_SELECTION );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DECODER_CMD ) = 0x%x\n", VIDIOC_DECODER_CMD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_DECODER_CMD ) = 0x%x\n", VIDIOC_TRY_DECODER_CMD );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_DV_TIMINGS ) = 0x%x\n", VIDIOC_ENUM_DV_TIMINGS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_DV_TIMINGS ) = 0x%x\n", VIDIOC_QUERY_DV_TIMINGS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DV_TIMINGS_CAP ) = 0x%x\n", VIDIOC_DV_TIMINGS_CAP );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FREQ_BANDS ) = 0x%x\n", VIDIOC_ENUM_FREQ_BANDS );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DBG_G_CHIP_INFO ) = 0x%x\n", VIDIOC_DBG_G_CHIP_INFO );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_EXT_CTRL ) = 0x%x\n", VIDIOC_QUERY_EXT_CTRL );
+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(BASE_VIDIOC_PRIVATE ) = 0x%x\n", BASE_VIDIOC_PRIVATE );
+ CAMERA_LOGD("*************************************************************************************");
+#endif
+}
+RetCode HosV4L2Buffers::V4L2AllocBuffer(int fd, const std::shared_ptr<FrameSpec>& frameSpec){struct v4l2_buffer buf = {};struct v4l2_plane planes[1] = {};
- CAMERA_LOGD("V4L2AllocBuffer\n");
+ CAMERA_LOGD("V4L2AllocBuffer enter\n");+ cyyanl_printf_cmd();if (frameSpec == nullptr) {CAMERA_LOGE("V4L2AllocBuffer frameSpec is NULL\n");return RC_ERROR;}
-switch (memoryType_) {case V4L2_MEMORY_MMAP:// to do somethingbreak;case V4L2_MEMORY_USERPTR:
+ CAMERA_LOGD("V4L2AllocBuffer:V4L2_MEMORY_USERPTR = %d\n", V4L2_MEMORY_USERPTR);buf.type = bufferType_;buf.memory = memoryType_;buf.index = (uint32_t)frameSpec->buffer_->GetIndex();
-if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ CAMERA_LOGD("V4L2AllocBuffer:V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = %d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);buf.m.planes = planes;buf.length = 1;}
内核态打印:kernel/linux/linux-4.19/
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 0842a47c6..8aa60407f 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2902,10 +2902,93 @@ struct uvc_driver uvc_driver = {},};+static void cyyanl_printk_cmd(void)
+{
+ printk("*************************************************************************************");
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCAP ) = %ld\n", VIDIOC_QUERYCAP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FMT ) = %ld\n", VIDIOC_ENUM_FMT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_FMT ) = %ld\n", VIDIOC_G_FMT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_FMT ) = %ld\n", VIDIOC_S_FMT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_REQBUFS ) = %ld\n", VIDIOC_REQBUFS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYBUF ) = %ld\n", VIDIOC_QUERYBUF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_FBUF ) = %ld\n", VIDIOC_G_FBUF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_FBUF ) = %ld\n", VIDIOC_S_FBUF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_OVERLAY ) = %ld\n", VIDIOC_OVERLAY );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QBUF ) = %ld\n", VIDIOC_QBUF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_EXPBUF ) = %ld\n", VIDIOC_EXPBUF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DQBUF ) = %ld\n", VIDIOC_DQBUF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMON ) = %ld\n", VIDIOC_STREAMON );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMOFF ) = %ld\n", VIDIOC_STREAMOFF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_PARM ) = %ld\n", VIDIOC_G_PARM );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_PARM ) = %ld\n", VIDIOC_S_PARM );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_STD ) = %ld\n", VIDIOC_G_STD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_STD ) = %ld\n", VIDIOC_S_STD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMSTD ) = %ld\n", VIDIOC_ENUMSTD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMINPUT ) = %ld\n", VIDIOC_ENUMINPUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_CTRL ) = %ld\n", VIDIOC_G_CTRL );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_CTRL ) = %ld\n", VIDIOC_S_CTRL );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_TUNER ) = %ld\n", VIDIOC_G_TUNER );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_TUNER ) = %ld\n", VIDIOC_S_TUNER );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDIO ) = %ld\n", VIDIOC_G_AUDIO );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDIO ) = %ld\n", VIDIOC_S_AUDIO );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCTRL ) = %ld\n", VIDIOC_QUERYCTRL );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYMENU ) = %ld\n", VIDIOC_QUERYMENU );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_INPUT ) = %ld\n", VIDIOC_G_INPUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_INPUT ) = %ld\n", VIDIOC_S_INPUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_EDID ) = %ld\n", VIDIOC_G_EDID );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_EDID ) = %ld\n", VIDIOC_S_EDID );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_OUTPUT ) = %ld\n", VIDIOC_G_OUTPUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_OUTPUT ) = %ld\n", VIDIOC_S_OUTPUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMOUTPUT ) = %ld\n", VIDIOC_ENUMOUTPUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDOUT ) = %ld\n", VIDIOC_G_AUDOUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDOUT ) = %ld\n", VIDIOC_S_AUDOUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_MODULATOR ) = %ld\n", VIDIOC_G_MODULATOR );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_MODULATOR ) = %ld\n", VIDIOC_S_MODULATOR );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_FREQUENCY ) = %ld\n", VIDIOC_G_FREQUENCY );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_FREQUENCY ) = %ld\n", VIDIOC_S_FREQUENCY );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_CROPCAP ) = %ld\n", VIDIOC_CROPCAP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_CROP ) = %ld\n", VIDIOC_G_CROP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_CROP ) = %ld\n", VIDIOC_S_CROP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_JPEGCOMP ) = %ld\n", VIDIOC_G_JPEGCOMP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_JPEGCOMP ) = %ld\n", VIDIOC_S_JPEGCOMP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYSTD ) = %ld\n", VIDIOC_QUERYSTD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_FMT ) = %ld\n", VIDIOC_TRY_FMT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDIO ) = %ld\n", VIDIOC_ENUMAUDIO );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDOUT ) = %ld\n", VIDIOC_ENUMAUDOUT );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_PRIORITY ) = %ld\n", VIDIOC_G_PRIORITY );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_PRIORITY ) = %ld\n", VIDIOC_S_PRIORITY );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_SLICED_VBI_CAP ) = %ld\n", VIDIOC_G_SLICED_VBI_CAP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_LOG_STATUS ) = %ld\n", VIDIOC_LOG_STATUS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_EXT_CTRLS ) = %ld\n", VIDIOC_G_EXT_CTRLS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_EXT_CTRLS ) = %ld\n", VIDIOC_S_EXT_CTRLS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_EXT_CTRLS ) = %ld\n", VIDIOC_TRY_EXT_CTRLS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMESIZES ) = %ld\n", VIDIOC_ENUM_FRAMESIZES );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMEINTERVALS) = %ld\n", VIDIOC_ENUM_FRAMEINTERVALS);
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_ENC_INDEX ) = %ld\n", VIDIOC_G_ENC_INDEX );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENCODER_CMD ) = %ld\n", VIDIOC_ENCODER_CMD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_ENCODER_CMD ) = %ld\n", VIDIOC_TRY_ENCODER_CMD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_HW_FREQ_SEEK ) = %ld\n", VIDIOC_S_HW_FREQ_SEEK );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_CREATE_BUFS ) = %ld\n", VIDIOC_CREATE_BUFS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_PREPARE_BUF ) = %ld\n", VIDIOC_PREPARE_BUF );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_SELECTION ) = %ld\n", VIDIOC_G_SELECTION );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_SELECTION ) = %ld\n", VIDIOC_S_SELECTION );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DECODER_CMD ) = %ld\n", VIDIOC_DECODER_CMD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_DECODER_CMD ) = %ld\n", VIDIOC_TRY_DECODER_CMD );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_DV_TIMINGS ) = %ld\n", VIDIOC_ENUM_DV_TIMINGS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_DV_TIMINGS ) = %ld\n", VIDIOC_QUERY_DV_TIMINGS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DV_TIMINGS_CAP ) = %ld\n", VIDIOC_DV_TIMINGS_CAP );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FREQ_BANDS ) = %ld\n", VIDIOC_ENUM_FREQ_BANDS );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DBG_G_CHIP_INFO ) = %ld\n", VIDIOC_DBG_G_CHIP_INFO );
+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_EXT_CTRL ) = %ld\n", VIDIOC_QUERY_EXT_CTRL );
+ printk("cyyanl v4l2 ioctl cmd(BASE_VIDIOC_PRIVATE ) = %ld\n", BASE_VIDIOC_PRIVATE );
+ printk("*************************************************************************************");
+}
+static int __init uvc_init(void){int ret;
-
+ printk("cyyanl enter uvc_init\n");
+ cyyanl_printk_cmd();uvc_debugfs_init();ret = usb_register(&uvc_driver.driver);
打印结果对比:VIDIOC_QUERYBUF用户态为0xc0505609,内核态为0xc0585609 还有其他几处命令码也不同。
分析命令码不一致问题,先找出VIDIOC_QUERYBUF用户态和内核态实际编译时所定义的地方差异:
用户态:kernel/linux/patches/linux-5.10/prebuilts/usr/include/linux/videodev2.h +1358
内核态:kernel/linux/linux-4.19/include/uapi/linux/videodev2.h +2361
此时怀疑VIDIOC_QUERYBUF不一致是头文件不同所导致(目前没做修改验证同改为linux-4.19是否可行)。对现有问题求助客户,并在OpenHarmony上寻找有无相似问题。找到了相似的issuse:
接下来,调试思路分为2路:
-
同意用户态和内核态的VIDIOC_QUERYBUF
方案:把用户态的0xc0505609改为内核态的0xc0585609
修改点:drivers/peripheral
diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp index d7dd15f..f7254b4 100644 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cppbuf.m.planes = planes;buf.length = 1;} - CAMERA_LOGD("V4L2_MEMORY_USERPTR Print the cnt: %{public}d\n", buf.index); - - if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) { - CAMERA_LOGE("error: ioctl VIDIOC_QUERYBUF failed: %{public}s\n", strerror(errno)); + if (ioctl(fd, /*VIDIOC_QUERYBUF*/0xc0585609, &buf) < 0) { + CAMERA_LOGE("error: ioctl VIDIOC_QUERYBUF failed.\n");return RC_ERROR;}
再次运行v4l2_main结果:Signal 4报错
原因分析:此时ioctl(fd, /VIDIOC_QUERYBUF/0xc0585609, &buf) 已经成功了。Signal 4分析可能又是cmd命令码的问题。
此路虽然解决了当前问题,但会有新问题Signal 4,故先暂停。
INFO:main test:allocating display buffer memory INFO:main test:do_mmap: pmem mmap fd 5 ptr 0xf7508000 len 2457600 INFO:V4L2OpenDevice /dev/video10 INFO:V4L2ReqBuffers buffCont 4 INFO:Creatbuffer frameSpec->buffer index == 0 INFO:V4L2AllocBuffer Signal 4
-
分析命令码不一致的根因,并做修改
根因分析:结构体的大小根据32位与64位编译会产生差异,从而影响VIDIOC_QUERYBUF的值。
修改点:修改用户态编译v4l2_buffer结构体的timestamp定义,并将用户态编译的头文件#include <linux/videodev2.h>替换成
修改过的videodev2.h,即#include ”videodev2.h“。(实际操作为把修改后的videodev2.h拷贝到v4l2_main编译目录中)
kernel/linux/linux-4.19/
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index ba548d7f0..b0fb48f65 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -958,13 +958,20 @@ struct v4l2_plane {* Contains data exchanged by application and driver using one of the Streaming* I/O methods.*/ + +struct timeval_user { + long tv_sec; + long tv_usec; +}; +struct v4l2_buffer {__u32 index;__u32 type;__u32 bytesused;__u32 flags;__u32 field; - struct timeval timestamp; + //struct timeval timestamp; + struct timeval_user timestamp;struct v4l2_timecode timecode;__u32 sequence;
drivers/peripheral
diff --git a/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h b/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h index 00ddea7..962ebc3 100755 --- a/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h +++ b/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h @@ -15,7 +15,8 @@#ifndef HOS_CAMERA_PROJET_HARDWARE_H#define HOS_CAMERA_PROJET_HARDWARE_H -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"namespace OHOS::Camera {#define PREVIEW_PIXEL_FORMAT V4L2_PIX_FMT_YUV420 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h index 6f45882..a8d6819 100644 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h @@ -19,7 +19,8 @@#include <mutex>#include <map>#include <cstring> -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include <sys/ioctl.h>#include "v4l2_common.h"#if defined(V4L2_UTEST) || defined (V4L2_MAIN_TEST) diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h index 5b93f36..05191a7 100644 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h @@ -16,7 +16,8 @@#ifndef HOS_CAMERA_V4L2_CONTROL_H#define HOS_CAMERA_V4L2_CONTROL_H-#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include <errno.h>#include <sys/ioctl.h>#include "v4l2_common.h" diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h index 10dc9b4..e3b3056 100644 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h @@ -19,7 +19,8 @@#include <mutex>#include <thread>#include <vector> -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include <sys/epoll.h>#include <sys/ioctl.h>#include <sys/types.h> diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h index de892e9..44bb1b4 100644 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h @@ -19,7 +19,8 @@#include <vector>#include <cstring>#include <fcntl.h> -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include <sys/ioctl.h>#include <sys/stat.h>#include <unistd.h> diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h index 1a62f37..96c70aa 100644 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h @@ -18,7 +18,8 @@#include <thread>#include <fcntl.h>#include <linux/netlink.h> -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include <sys/ioctl.h>#include <sys/select.h>#include <linux/netlink.h>zz diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp index b351f49..5483b85 100755 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp @@ -22,7 +22,8 @@#include <sys/mman.h>#include <sys/time.h>#include <linux/fb.h> -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include "securec.h"#include "v4l2_uvc.h"#include "v4l2_dev.h" diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp index 778cf05..96618be 100644 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp @@ -14,7 +14,8 @@*/#include <cstring> -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include <sys/ioctl.h>#include "v4l2_stream.h" diff --git a/camera/hal/test/v4l2/include/test_display.h b/camera/hal/test/v4l2/include/test_display.h index d437e26..8e5205e 100644 --- a/camera/hal/test/v4l2/include/test_display.h +++ b/camera/hal/test/v4l2/include/test_display.h @@ -44,7 +44,8 @@#include <errno.h>#include <getopt.h>#include <linux/fb.h> -#include <linux/videodev2.h> +//#include <linux/videodev2.h> +#include "videodev2.h"#include <mutex>#include <pthread.h>#include <stdlib.h> @@ -138,4 +139,4 @@ public:void StartCapture(int streamId, int captureId, bool shutterCallback, bool isStreaming);float calTime(struct timeval start, struct timeval end);}; -#endif \ No newline at end of file +#endif
再次编译v4l2_main后执行,log无报错。HDMI屏上就显示预览画面。
回过头来再看整个调试流程,发现该摄像头支持YUYV格式和MJPEG格式,查看v4l2_main中默认预览用的是YUYV,改为MJPEG再次调试。
修改点:
diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp
index b351f49..5483b85 100755
--- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp
+++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp
@@ -394,7 +395,9 @@ void V4L2SetDeviceFormat(DeviceFormat& format, const std::string devname)if (devname == "uvcvideo" || devname == "uvcvideo1") {if (g_isPreviewOnUvc) {
- format.fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
+ CAMERA_LOGD("cyyanl enter V4L2SetDeviceFormat : g_isPreviewOnUvc\n");
+ //format.fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
+ format.fmtdesc.pixelformat = V4L2_PIX_FMT_MJPEG;format.fmtdesc.width = width;format.fmtdesc.height = height;}
v4l2_main执行结果:该显示异常,目前先不分析MJPEG格式。
到此为止,v4l2_main运行正常,可以预览(预览画面色彩异常与屏幕显示格式有关,暂不做修改)。接下来调试拍照和录像。
执行v4l2_main后,先输入u进行uvc预览,再运行c进行拍照,再运行v进行录像,照片和录像文件生成到当前执行的路径下:
# ls -l *.jpeg
-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC0.jpeg
-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC1.jpeg
-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC2.jpeg
-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC3.jpeg
#
# ls -l *.h264
-rwxrw-rw- 1 root 29034400 85401600 2013-01-18 15:20 uvc.h264
将如上文件导出到电脑端查看:
照片uvc0.jpeg
录像uvc.h264在手机端可查看,播放正常。
附录
/*** struct v4l2_buffer - video buffer info* @index: id number of the buffer* @type: enum v4l2_buf_type; buffer type (type == *_MPLANE for* multiplanar buffers);* @bytesused: number of bytes occupied by data in the buffer (payload);* unused (set to 0) for multiplanar buffers* @flags: buffer informational flags* @field: enum v4l2_field; field order of the image in the buffer* @timestamp: frame timestamp* @timecode: frame timecode* @sequence: sequence count of this frame* @memory: enum v4l2_memory; the method, in which the actual video data is* passed* @offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP;* offset from the start of the device memory for this plane,* (or a "cookie" that should be passed to mmap() as offset)* @userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;* a userspace pointer pointing to this buffer* @fd: for non-multiplanar buffers with memory == V4L2_MEMORY_DMABUF;* a userspace file descriptor associated with this buffer* @planes: for multiplanar buffers; userspace pointer to the array of plane* info structs for this buffer* @length: size in bytes of the buffer (NOT its payload) for single-plane* buffers (when type != *_MPLANE); number of elements in the* planes array for multi-plane buffers** Contains data exchanged by application and driver using one of the Streaming* I/O methods.*/struct v4l2_buffer {__u32 index;__u32 type;__u32 bytesused;__u32 flags;__u32 field;struct timeval timestamp;struct v4l2_timecode timecode;__u32 sequence;/* memory location */__u32 memory;union {__u32 offset;unsigned long userptr;struct v4l2_plane *planes;__s32 fd;} m;__u32 length;__u32 reserved2;__u32 reserved;
}
未完待续~~~~
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)最新学习路线
-
HarmonOS基础技能
- HarmonOS就业必备技能
- HarmonOS多媒体技术
- 鸿蒙NaPi组件进阶
- HarmonOS高级技能
- 初识HarmonOS内核
- 实战就业级设备开发
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。
相关文章:

OpenHarmony实战:帆移植案例(中)
OpenHarmony实战:帆移植案例(上) Audio服务介绍 服务节点 基于ADM框架的audio驱动对HDI层提供三个服务hdf_audio_render、hdf_audio_capture、hdf_audio_control。 开发板audio驱动服务节点如下: console:/dev # ls -al hdf_au…...

武汉星起航:创始人张振邦智慧领航,孵化伙伴共绘跨境新蓝图!
在风起云涌的跨境电商行业中,武汉星起航电子商务有限公司如同一颗璀璨的明星,引领着众多创业者迈向成功的彼岸。而这一切的背后,都离不开公司创始人张振邦先生的卓越领导与深厚经验。他凭借着在电子商务行业多年的深耕与积累,为武…...

上下收缩、折叠面板
效果: 上下收缩、折叠面板,类似QQ好友列表那种。原理就是在一个布局中,通过button来实现一个独立widget的visible/disable 实现: 1.分组按钮 #ifndef EXPANDPANEL_H #define EXPANDPANEL_H#include <QWidget>class…...

XC7A35T-2FGG484 嵌入式FPGA现场可编程门阵列 Xilinx
XC7A35T-2FGG484 是一款由Xilinx(赛灵思)制造的FPGA(现场可编程门阵列)芯片 以下是XC7A35T-2FGG484 的主要参数: 1. 系列:Artix-7 2. 逻辑单元数量:33280个 3. 工艺技术:28nm 4. …...

淘宝订单API接口:电商业务自动化的新选择
淘宝订单API接口在电商业务自动化中扮演了至关重要的角色。首先,通过API接口,商家可以自动化地查询、创建、修改和删除订单,极大地提高了订单处理效率,减少了人工操作,降低了错误率。其次,商家可以实时获取…...

识典百科词条创建技巧,教你如何轻松创建热门识典百科词条!
网络已经成为人们获取知识和信息的主要途径。在这样一个背景下,识典百科作为一个综合性的网络百科全书,在为读者们提供各种知识的同时,也给广大用户提供了一个创建、编辑和分享知识的平台。如何在识典百科上创建一个高质量的词条,…...

iOS 开发中上传 IPA 文件的方法(无需 Mac 电脑)
引言 在 iOS 开发中,将 IPA 文件上传到苹果开发者中心是一个重要的步骤。通常情况下,我们需要使用 Mac 电脑上的 Xcode 或 Application Loader 工具来完成这个任务。然而,如果你没有 Mac 电脑,也没有关系,本文将介绍一…...

2024-04-08 问AI: 介绍一下AI 大神 吴恩达
文心一言 吴恩达(Andrew Ng)是AI领域的一位重要人物,他的贡献和影响力在学术界、工业界以及在线教育领域都极为显著。 吴恩达出生于1976年,是一位华裔美国人,他在斯坦福大学担任计算机科学系和电子工程系的副教授&am…...

Leetcode面试经典150_Q12整数转罗马数字
题目: 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M …...

Docker-compose部署Alertmanager+Dingtalk+Prometheus+Grafana实现钉钉报警
部署监控 version: 3.7services: #dingtalkdingtalk:image: timonwong/prometheus-webhook-dingtalk:latestcontainer_name: dingtalkrestart: alwayscommand:- --config.file/etc/prometheus-webhook-dingtalk/config.ymlvolumes:- /data/monitor/dingtalk/config.yml:/etc/p…...

算法刷题记录 Day40
算法刷题记录 Day40 Date: 2024.04.06 kamma 56. 多重背包 #include<bits/stdc.h> using namespace std;int main(){int n, c;while(cin>>c>>n){vector<int> weights(n, 0);vector<int> values(n, 0);vector<int> knums(n, 0);for(int …...

Android JNI基础
目录 一、JNI简介1.1 什么是JNI1.2 用途1.3 优点 二、初探JNI2.1 新建cpp\cmake2.2 build.gradle配置2.3 java层配置2.4 cmake和c 三、API详解3.1 JNI API3.1.1 数据类型3.1.2 方法 3.2 CMake脚本 四、再探JNI 一、JNI简介 1.1 什么是JNI JNI(Java Native Interfa…...

裙边挡边带是什么
裙边挡边带:了解其功能与应用 在日常生活和工业生产中,我们经常会遇到各种形状和功能的带子。其中,裙边挡边带是一种特殊类型的带子,它具有独特的结构和功能,被广泛应用于各种场合。本文将介绍裙边挡边带的基本概念、…...

chabot项目介绍
项目介绍 整体的目录如下所示: 上述的项目结构中出了model是必须的外,其他的都可以根据训练的代码参数传入进行调整,有些不需要一定存在data train.pkl:对原始训练语料进行tokenize之后的文件,存储一个list对象,list的每条数据表…...

ChromeOS 中自启动 Fcitx5 和托盘 stalonetray
ChromeOS 更新的飞快,旧文章的方法也老是不好用,找遍了也没找到很好的可以开机自启动 Linux VM 和输入法、托盘的方法。 研究了一下(不,是很久),终于找到个丑陋的实现。 方法基于 ChromeOS 123.0.6312.94…...

画图理解JVM相关内容
文章目录 1. JVM视角下,内存划分2. 类内存分布硬核详解1. 获取堆内存参数2. 扫描堆内存,定位实例3. 查看实例所在地址的数据4. 找到实例所指向的类信息的地址5. 查看class信息6. 结论 3. Java的对象创建流程4. 垃圾判别算法4.1 引用计数法4.2 可达性分析…...

Scikit-Learn K均值聚类
Scikit-Learn K均值聚类 1、K均值聚类1.1、K均值聚类及原理1.2、K均值聚类的优缺点1.3、聚类与分类的区别2、Scikit-Learn K均值聚类2.1、Scikit-Learn K均值聚类API2.2、K均值聚类初体验(寻找最佳K)2.3、K均值聚类案例1、K均值聚类 K-均值(K-Means)是一种聚类算法,属于无…...

蓝桥杯 - 受伤的皇后
解题思路: 递归 回溯(n皇后问题的变种) 在 N 皇后问题的解决方案中,我们是从棋盘的顶部向底部逐行放置皇后的,这意味着在任何给定时间,所有未来的行(即当前行之下的所有行)都还没…...

AcWing---乌龟棋---线性dp
312. 乌龟棋 - AcWing题库 思路: 原来没有碰到过类似的题: dp数组为思维:dp[i][j][k][r],分别表示用了i个第一类型卡片,j个第二类型卡片...所到的格子数的最大分数,为啥不用记录乌龟到了哪里呢࿱…...

python代码使用过程中使用快捷键注释时报错
1.代码 2.代码报错 3.代码注释后的结果 4. 原因...

go之web框架gin
介绍 Gin 是一个用 Go (Golang) 编写的 Web 框架。 它具有类似 martini 的 API,性能要好得多,多亏了 httprouter,速度提高了 40 倍。 如果您需要性能和良好的生产力,您一定会喜欢 Gin。 安装 go get -u github.com/gin-gonic/g…...

SpringBoot 定时任务实践、定时任务按指定时间执行
Q1. springboot怎样创建定时任务? 很显然,人人都知道,Scheduled(cron ".....") Q2. 如上所示创建了定时任务却未能执行是为什么? 如果你的cron确定没写错的话 cron表达式是否合法,可参考此处,…...

MYSQL数据库故障排除与优化
目录 MySQL 单实例故障排查 MySQL 主从故障排查 MySQL 优化 MySQL 单实例故障排查 故障现象 1 ERROR 2002 (HY000): Cant connect to local MySQL server through socket /data/mysql/mysql.sock (2) 问题分析:以上这种情况一般都…...

算法-数论-蓝桥杯
算法-数论 1、最大公约数 def gcd(a,b):if b 0:return areturn gcd(b, a%b) # a和b的最大公约数等于b与a mod b 的最大公约数def gcd(a,b):while b ! 0:cur aa bb cur%bpassreturn a欧几里得算法 a可以表示成a kb r(a,b,k,…...

222.完全二叉树节点个数
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最…...

C++中的string类操作详解
引言 针对C中的string,本文主要讲解如何对其进行插入、删除、查找、比较、截断、分割以及与数字之间的相互转换等。 字符串插入 1. append方法 std::string str "hello"; str.append(7, w); // 在末尾添加7个字符w str.append("wwwwwww");…...

Java绘图坐标体系
一、介绍 下图说明了Java坐标系。坐标原点位于左上角,以像素为单位。在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐…...
【MATLAB源码-第38期】基于OFDM的块状导频和梳状导频误码率性能对比,以及LS/LMMSE两种信道估计方法以及不同调制方式对比。
操作环境: MATLAB 2022a 1、算法描述 块状导频和梳状导频都是用于无线通信系统中信道估计的方法。 块状导频: 定义: 在频域上,块状导频是连续放置的一组导频符号。这意味着所有的导频符号都集中在一个短的时间段内发送。 优点…...

javaWeb车辆管理系统设计与实现
摘 要 随着经济的日益增长,车辆作为最重要的交通工具,在企事业单位中得以普及,单位的车辆数目已经远远不止简单的几辆,与此同时就产生了车辆资源的合理分配使用问题。 企业车辆管理系统运用现代化的计算机管理手段,不但可以对车辆的使用进行合理的管理,…...

【DM8】间隔分区
是范围分区的一个扩展 如果使用了间隔函数做分区,在数据插入的时候,如果没有合适的分区,数据库会自动创建一个新的分区。 –year往后推两年 SELECT SYSDATE numtoyminterval(2,‘YEAR’); –month往后推两年 SELECT SYSDATE numtoyminterv…...