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  //播放数据流务。
  1. 音频控制流服务

    用来接收上层lib层下发的控制指令,包括音量控制、增益控制、通路控制,这些控制指令都是通过控制流服务下发到驱动。

  2. 音频数据播放流服务

    用来接收上层lib层下发的音频数据和播放相关的参数,还有播放的启动、暂停、恢复、停止指令,这些指令都是由播放数据流下发到驱动。

  3. 音频数据录音流服务

    用来向上层lib层传输音频数据和接收上层lib层下发的录音相关的参数,还有录音的启动、暂停、恢复、停止指令,这些指令都是由录音数据流下发到驱动。

驱动服务

每个audio设备包括如下服务:

hdf_audio_codec_dev0音频设备名称
dma_service_0dma 驱动服务
dai_servicecpu dai 驱动服务
codec_service_0codec 驱动服务
dsp_service_0dsp 驱动服务(可选项)
hdf_audio_codec_dev1音频设备名称
dma_service_0dma 驱动服务
dai_servicecpu dai 驱动服务
codec_service_1accessory 驱动服务(特指smartPA)
dsp_service_0dsp 驱动服务(可选项)
代码路径
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驱动模块架构图

img

以Camera Host 部分做如下说明:

  1. HDI实现层(HDI Implementation):对上实现Open Harmony OS相机标准南向接口。
  2. 框架层(PipelineCore):对接HDI实现层的控制、流的转发,实现数据通路的搭建、管理相机各个硬件设备等功能。
  3. 适配层(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路:

  1. 同意用户态和内核态的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
  2. 分析命令码不一致的根因,并做修改

    根因分析:结构体的大小根据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学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【24年软考】信息系统项目管理师论文写作技巧(附范文10篇)

24年软考信息系统项目管理师论文写作准备&#xff1a; 论文准备时一定要紧扣考纲来进行&#xff0c;这样才能紧靠考试内容&#xff0c;不至于跑偏得不到高分。 1、多看论文范文&#xff0c;能够从别人的论文中快速熟悉写作的框架和思路。&#xff08;结尾有论文范文分享&…

数据库之DQL操作(数据查询语言)

DQL英文全称是Data Query Language(数据查询语言)&#xff0c;数据查询语言&#xff0c;用来查询数据库中表的记录。查询关键字: SELECT。 本节介绍以下表为例&#xff1a; create table emp(id int comment 编号&#xff0c;workno varchar(10) comment 工号&#xff0c;nam…

mybatis-plus与mybatis同时使用别名问题

在整合mybatis和mybatis-plus的时候发现一个小坑&#xff0c;单独使用mybatis&#xff0c;配置别名如下&#xff1a; #配置映射文件中指定的实体类的别名 mybatis.type-aliases-packagecom.jk.entity XML映射文件如下&#xff1a; <update id"update" paramete…

rabbitmq安装延时插件

rabbitmq安装延时插件 1、下载延迟插件 在 RabbitMQ 的 3.5.7 版本之后&#xff0c;提供了一个插件&#xff08;rabbitmq-delayed-message-exchange&#xff09;来实现延迟队列 &#xff0c;同时需保证 Erlang/OPT 版本为 18.0 之后。 我这里 MQ 的版本是 3.10.0 现在去 GitH…

深入浅出 -- 系统架构之微服务标准组件及职责

我们来认识一下微服务架构在Java体系中依托哪些组件实现的。 相对于单体架构的简单粗暴&#xff0c;微服务的核心是将应用打散&#xff0c;形成多个独立提供的微服务&#xff0c;虽然从管理与逻辑上更符合业务需要。但微服务架构也带来了很多急需解决的核心问题&#xff1a; 1…

Java项目中使用事务

事务的四大特性 事务特性ACID&#xff1a;原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;、持久性&#xff08;Durability&#xff09;。 原子性是指事务包含的所有操作要么全部成功&#x…

HarmonyOS 开发-实现Swiper高度可变化效果

介绍 在很多应用中&#xff0c;swiper组件每一个page的高度是不一致的&#xff0c;所以需要swiper组件下方页面的高度跟着一起变化。 效果图预览 使用说明 向左滑动swiper组件&#xff0c;上方swiper组件高度变高&#xff0c;下方页面随着swiper的变化而平滑的变化。 实现思…

第十三届蓝桥杯C/C++大学B组真题题解(一)

1、扫雷 #include <bits/stdc.h> using namespace std; int n,m; const int N110; int g[N][N]; int dx[8]{-1,-1,-1,0,1,1,1,0}; int dy[8]{-1,0,1,1,1,0,-1,-1}; int dfs(int x,int y){int ans0;for(int i0;i<8;i){int axdx[i],bydy[i];if(a<0||a>n-1||b<0…

【RHEL】redhat yum 报错: not registered to Red Hat Subscription Management.

【RHEL】redhat yum 报错: not registered to Red Hat Subscription Management. 问题描述解决方法参考博客&#xff1a; 问题描述 使用redhat7用yum install -y dos2unix命令时出现这个错误 This system is not registered to Red Hat Subscription Management. You can use …

乳腺癌诊断的集成自注意力Transformer编码器

ETECADx: Ensemble Self-Attention Transformer Encoder for Breast Cancer Diagnosis Using Full-Field Digital X-ray Breast Images 内科医生和放射科医生建议使用多种方法来发现乳腺癌&#xff0c;包括数字乳房x线摄影(DM)、超声(US)和磁共振成像(MRI)。 CAD系统与乳腺x线…

深度学习【向量化(array)】

为什么要向量化 在深度学习安全领域、深度学习练习中&#xff0c;你经常发现在训练大量数据时&#xff0c;深度学习算法表现才更加优越&#xff0c;所以你的代码运行的非常快至关重要&#xff0c;否则&#xff0c;你将要等待非常长的时间去得到结果。所以在深度学习领域向量化…

java中使用雪花算法(Snowflake)为分布式系统生成全局唯一ID

&#xff08;全局唯一ID的解决方案有很多种&#xff0c;这里主要是介绍和学习Snowflake算法&#xff09; 什么是雪花算法&#xff08;Snowflake&#xff09; 雪花算法&#xff08;Snowflake Algorithm&#xff09;是由Twitter公司在2010年左右提出的一种分布式ID生成算法&…

有没有寄快递省钱的方法啊,尤其是搬家寄大件?

从大学开始离家&#xff0c;到读研&#xff0c;工作&#xff0c;辗转换了四五个城市了&#xff0c;大大小小搬家十几次&#xff0c;最近才发现有一个宝藏寄快递方法。 个人寄件贵是为什么呢&#xff1f;据我做物流的朋友说一般我们寄快递因为单量少&#xff0c;所以单件价格都…

Windows下Docker安装Kafka3+集群

编写 docker-compose.yaml 主要参照&#xff1a;https://www.cnblogs.com/wangguishe/p/17563274.html version: "3"services:kafka1:image: bitnami/kafka:3.4.1container_name: kafka1environment:- KAFKA_HEAP_OPTS-Xmx1024m -Xms1024m- KAFKA_ENABLE_KRAFTyes- K…

【一】学习TDengine-总结新技术学习的思考

学习TDengine-总结新技术学习的思考 概要 因业务场景需要我们开始接触时序数据库&#xff0c;于是开始根据以往的学习经验着手熟悉这一项新技术&#xff0c;学习也是一种技能&#xff0c;成功的人越容易成功&#xff0c;因为他们掌握了一套成功的方法&#xff0c;这里提到学习经…

windows 线程同步的四种方式总结

一&#xff1a;内核态下的三种同步方式&#xff1a; 一、互斥变量&#xff08;Mutex&#xff09; 互斥对象包含一个使用数量&#xff0c;一个线程ID和一个计数器。其中线程ID用于标识系统中的哪个线程当前拥有互斥对象&#xff0c;计数器用于指明该线程拥有互斥对象的次数。 创…

Vue的学习之旅-part5

Vue的学习之旅-part5 虚拟DOM的原理用JS模拟DOM结构 vue的方法、计算属性、过滤器computed:{} 计算属性computed计算属性的完全体computed计算属性和methods方法的区别&#xff1a;过滤器&#xff1a;filters:{ 多个方法 } Vuex 状态管理模式 前几篇博客: Vue的学习之旅-part1 …

【算法】第二篇 大衍数列

导航 1. 简介2. 数列特征3. 代码演示 1. 简介 大衍数列&#xff0c;来源于《乾坤谱》中对易传“大衍之数五十”的推论。主要用于解释中国传统文化中的太极衍生原理。数列中的每一项&#xff0c;都代表太极衍生过程中&#xff0c;曾经经历过的两仪数量总和。是中华传统文化中隐…

A Study of Network Forensic Investgation in Docker Environments文章翻译

A Study of Network Forensic Investgation in Docker Environments Docker环境下的网络取证研究 摘要 网络罪犯利用越来越多的技术(如虚拟机或基于容器的基础设施)进行恶意活动。 这些虚拟环境的固有动态简化了恶意服务的快速创建,并隐藏了所涉及的系统,这是以前没有的技…

用AI作图,使用这个免费网站,快看我画的大鹏鸟和美女

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…