当前位置: 首页 > news >正文

MM-Camera架构-ProcessCaptureRequest 流程分析

image

文章目录

  • processCaptureRequest\_3\_4
    • 1.1 mDevice
    • 1.2 mDevice->ops->process\_capture\_request
    • 1.3 hardware to vendor
  • mct\_shimlayer\_process\_event
    • 2.1 mct\_shimlayer\_handle\_parm
    • 2.2 mct\_shimlayer\_reg\_buffer

processCaptureRequest_3_4

sdm660的摄像头走camera hal 3.4接口,每个预览帧,都是由camera service发起,通过camera HAL的CameraDeviceSession::processCaptureRequest_3_4接口,通知hal,请求一个预览帧。

hardware/interfaces/camera/device/3.4/default/CameraDeviceSession.cpp

Return<void> CameraDeviceSession::processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest>& requests,const hidl_vec<V3_2::BufferCache>& cachesToRemove,ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb)  {for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {s = processOneCaptureRequest_3_4(requests[i]);}...
}Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request)  {...//@ 1.1 - 1.2status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);...
}

1.1 mDevice

mDevicecamera_device_t或者camera3_device_t定义。camera1camera3代表的是CAMERA DEVICE API VERSION,camera3canera1完全不一样。这里mDevicecamera3_device_t定义。

camera3_device_t:是 camera HAL 核心结构体之一,是对 venor camera HAL 实现的抽象,APP 通过 Framework对底层Camera设备(物理设备和逻辑虚拟设备)的操作都是通过对 camera3_device_t 实例对象来进行的。
camera3_device_t:主要用来表示Camera设备,其中定义了Camera3_device_ops操作集合,用来实现正常获取图像数据以及控制Camera的功能。

typedef struct camera3_device {hw_device_t common;camera3_device_ops_t *ops;void *priv;
} camera3_device_t;

HAL3的核心接口都是在camera3_device_ops中被定义。
camera3_device_ops结构体定义了一系列的函数指针,用来指向平台厂商实际的实现方法。

typedef struct camera3_device_ops {/*initialize何时被调用:在camera_modul_t中的open方法之后,其他camera3_device_ops方法之前被调用。主要作用:将上层实现的回调方法注册到HAL中,并根据需要在该方法中加入自定义的一些初始化操作。返回时间:在5ms内返回,最长不能超过10ms。*/int (*initialize)(const struct camera3_device *,const camera3_callback_ops_t *callback_ops);/*configure_streams何时被调用:在Initialize方法完成之后,在调用process_capture_request方法之前被调用主要作用:重设当前正在运行的Pipeline以及设执行的输入输出流,其中它回见stream_list中的新的数据流替换之前配置的数据流。返回时间:500ms内返回,最长不能超过1000ms*/int (*configure_streams)(const struct camera3_device *,camera3_stream_configuration_t *stream_list);int (*register_stream_buffers)(const struct camera3_device *,const camera3_stream_buffer_set_t *buffer_set);const camera_metadata_t* (*construct_default_request_settings)(const struct camera3_device *,int type);/*process_capture_request主要作用:下发单次新的capture request到HAL中,上层必须保证该方法的调用都是在一个线程中完成,而且该方法是异步的,其结果是通过HAL调用另一个接口process_capture_result()来返回结果给上层,在使用过程中,通过in-flight机制,保证短时间内下发足够多的requst,从而满足帧率要求。*/int (*process_capture_request)(const struct camera3_device *,camera3_capture_request_t *request);void (*get_metadata_vendor_tag_ops)(const struct camera3_device*,vendor_tag_query_ops_t* ops);void (*dump)(const struct camera3_device *, int fd);int (*flush)(const struct camera3_device *);void (*signal_stream_flush)(const struct camera3_device*,uint32_t num_streams,const camera3_stream_t* const* streams);int (*is_reconfiguration_required)(const struct camera3_device*,const camera_metadata_t* old_session_params,const camera_metadata_t* new_session_params);/* reserved for future use */void *reserved[6];
} camera3_device_ops_t;

1.2 mDevice->ops->process_capture_request

继续mDevice->ops->process_capture_request
hardware/qcom/camera/QCamera2/HAL3/QCamera3HWI.h中camera3_device_ops_t定义了mCameraOps:

static camera3_device_ops_t mCameraOps;

camera3_device_ops_t QCamera3HardwareInterface::mCameraOps = {.initialize                         = QCamera3HardwareInterface::initialize,.configure_streams                  = QCamera3HardwareInterface::configure_streams,.register_stream_buffers            = NULL,.construct_default_request_settings = QCamera3HardwareInterface::construct_default_request_settings,.process_capture_request            = QCamera3HardwareInterface::process_capture_request,.get_metadata_vendor_tag_ops        = NULL,.dump                               = QCamera3HardwareInterface::dump,.flush                              = QCamera3HardwareInterface::flush,.reserved                           = {0},
};

hardware/qcom/camera/QCamera2/HAL3/QCamera3HWI.cpp

int QCamera3HardwareInterface::process_capture_request(const struct camera3_device *device,camera3_capture_request_t *request)
{LOGE("sundpmy_ process_capture_request E");...QCamera3HardwareInterface *hw =reinterpret_cast<QCamera3HardwareInterface *>(device->priv);int rc = hw->orchestrateRequest(request);LOGE("sundpmy_ process_capture_request X");return rc;
}int32_t QCamera3HardwareInterface::orchestrateRequest(camera3_capture_request_t *request)
{int32_t ret = NO_ERROR;...ret = processCaptureRequest(request, internallyRequestedStreams);...
}

1.3 hardware to vendor

QCamera2Factory构造的时候调用get_num_of_cameras_to_expose,一直到用到mm_camera_load_shim_lib。

 QCamera2Factory::QCamera2Factory(){mHalDescriptors = NULL;mCallbacks = NULL;mNumOfCameras = get_num_of_cameras();mNumOfCameras_expose = get_num_of_cameras_to_expose();get_num_of_cameras_to_expose()---> get_num_of_cameras()--->mm_camera_load_shim_lib() 
}

mm_camera_load_shim_lib里面dlopen:libmmcamera2_mct_shimlayer.so。dlsym获取入口函数:mct_shimlayer_process_module_init

#define SHIMLAYER_LIB "/system/vendor/lib/libmmcamera2_mct_shimlayer.so"int32_t mm_camera_load_shim_lib()
{const char* error = NULL;void *qdaemon_lib = NULL;LOGD("E");qdaemon_lib = dlopen(SHIMLAYER_LIB, RTLD_NOW);if (!qdaemon_lib) {error = dlerror();LOGE("dlopen failed with error %s", error ? error : "");return -1;}*(void **)&mm_camera_shim_module_init =dlsym(qdaemon_lib, "mct_shimlayer_process_module_init");if (!mm_camera_shim_module_init) {error = dlerror();LOGE("dlsym failed with error code %s", error ? error: "");dlclose(qdaemon_lib);return -1;}return mm_camera_shim_module_init(&g_cam_ctrl.cam_shim_ops);
}

mct_shimlayer_process_module_init给shim_ops_tbl赋值: @vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct_shim_layer/mct_shim_layer.c

int mct_shimlayer_process_module_init(mm_camera_shim_ops_t*shim_ops_tbl)
{...shim_ops_tbl->mm_camera_shim_open_session = mct_shimlayer_start_session;shim_ops_tbl->mm_camera_shim_close_session = mct_shimlayer_stop_session;shim_ops_tbl->mm_camera_shim_send_cmd = mct_shimlayer_process_event;...
}

mm_camera_shim_send_cmd的调用:

int32_t mm_camera_module_send_cmd(cam_shim_packet_t *event)
{int32_t rc = -1;if(g_cam_ctrl.cam_shim_ops.mm_camera_shim_send_cmd) {rc = g_cam_ctrl.cam_shim_ops.mm_camera_shim_send_cmd(event);}return rc;
}

mm_camera_module_send_cmd是个包装函数:
mm_camera_module_send_cmd被调用的地方比较多,打印log看一下:

D mm-camera: <CPP   >< HIGH> 1485: cpp_hardware_process_frame: [CPP_BUF:] stream_status:0xe7f1608c, iden:0x40002, cur_frame_id:17
E QCamera : <MCI><ERROR> mm_stream_unmap_buf: 2327: sundp_mc func:mm_stream_unmap_buf line:2327 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_stream_map_buf: 2168: sundp_mc func:mm_stream_map_buf line:2168 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_camera_util_s_ctrl: 2111: sundp_mc func:mm_camera_util_s_ctrl line:2111 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =0
D mm-camera: <CPP   >< HIGH> 1485: cpp_hardware_process_frame: [CPP_BUF:] stream_status:0xe7f1608c, iden:0x40002, cur_frame_id:18
E QCamera : <MCI><ERROR> mm_stream_unmap_buf: 2327: sundp_mc func:mm_stream_unmap_buf line:2327 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_stream_map_buf: 2168: sundp_mc func:mm_stream_map_buf line:2168 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_camera_util_s_ctrl: 2111: sundp_mc func:mm_camera_util_s_ctrl line:2111 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =0
D mm-camera: <CPP   >< HIGH> 1485: cpp_hardware_process_frame: [CPP_BUF:] stream_status:0xe7f1608c, iden:0x40002, cur_frame_id:19
E QCamera : <MCI><ERROR> mm_stream_unmap_buf: 2327: sundp_mc func:mm_stream_unmap_buf line:2327 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_stream_map_buf: 2168: sundp_mc func:mm_stream_map_buf line:2168 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_camera_util_s_ctrl: 2111: sundp_mc func:mm_camera_util_s_ctrl line:2111 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =0
D mm-camera: <CPP   >< HIGH> 1485: cpp_hardware_process_frame: [CPP_BUF:] stream_status:0xe7f1608c, iden:0x40002, cur_frame_id:20
E QCamera : <MCI><ERROR> mm_stream_unmap_buf: 2327: sundp_mc func:mm_stream_unmap_buf line:2327 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_stream_map_buf: 2168: sundp_mc func:mm_stream_map_buf line:2168 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =2
E QCamera : <MCI><ERROR> mm_camera_util_s_ctrl: 2111: sundp_mc func:mm_camera_util_s_ctrl line:2111 here
E mm-camera: <SHIM  ><ERROR> 481: mct_shimlayer_process_event: sundp_mct Received event from HAL type =0
D mm-camera: <CPP   >< HIGH> 1485: cpp_hardware_process_frame: [CPP_BUF:] stream_status:0xe7f1608c, iden:0x40002, cur_frame_id:21

以上log,可以看出每一帧,每次captureRequest,mm_camera_module_send_cmd会被调用三次。func:mm_stream_map_buf,func:mm_camera_util_s_ctrl,以及每一帧结束后的func:mm_stream_unmap_buf。


mct_shimlayer_process_event

从cameraservice层到qcom的hal层,到了shimlayer。 vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct_shim_layer/mct_shim_layer.c
从日志看,每次captureRequest,mct_shimlayer_process_event会被调用两次,cmd_type分别是CAM_SHIM_REG_BUF和CAM_SHIM_SET_PARM。

packet->cmd_type----->
typedef enum {CAM_SHIM_SET_PARM,   /*v4l2 set parameter*/CAM_SHIM_GET_PARM,   /*v4l2 get parameter*/CAM_SHIM_REG_BUF,    /*Reg/unreg buffers with back-end*/CAM_SHIM_BUNDLE_CMD, /*Bundled command for streams*/
} cam_shim_cmd_type;int mct_shimlayer_process_event(cam_shim_packet_t *packet)
{switch (packet->cmd_type) {case CAM_SHIM_SET_PARM:case CAM_SHIM_GET_PARM: {session_id = packet->session_id;parm_event = &packet->cmd_data;@2.1rc = mct_shimlayer_handle_parm(packet->cmd_type, session_id, parm_event);  }break;case CAM_SHIM_REG_BUF: {session_id = packet->session_id;reg_buf = &packet->reg_buf;@2.2rc = mct_shimlayer_reg_buffer(session_id, reg_buf);  }break;......
}

接下来看mct_shimlayer_process_event中的2.1 和 2.2。

2.1 mct_shimlayer_handle_parm

2.2 mct_shimlayer_reg_buffer

相关文章:

MM-Camera架构-ProcessCaptureRequest 流程分析

文章目录 processCaptureRequest\_3\_41.1 mDevice1.2 mDevice->ops->process\_capture\_request1.3 hardware to vendor mct\_shimlayer\_process\_event2.1 mct\_shimlayer\_handle\_parm2.2 mct\_shimlayer\_reg\_buffer processCaptureRequest_3_4 sdm660的摄像头走…...

196、管理 RabbitMQ 的用户

开启Rabbitmq的一些命令&#xff1a; 小黑窗输入&#xff1a; rabbitmq-plugins enable rabbitmq_management 启动控制台插件&#xff0c; 就是启动登录rabbitmq控制台的页面&#xff0c;rabbitmq_management 代表了RabbitMQ的管理界面。 rabbitmq-server 启动rabbitMQ服务器…...

【已解决】Python读取sql数据,报错:Not an executable object,解决方案

【已解决】Python读取sql数据&#xff0c;报错&#xff1a;Not an executable object&#xff0c;解决方案 1.报错内容&#xff1a; 通过Python连接sql&#xff0c;读取sql中数据&#xff0c;报错&#xff1a;Not an executable object。具体代码及报错内容见下&#xff1a; …...

STM32 CubeMX ADC采集(HAL库)

STM32 CubeMX ADC采集&#xff08;HAL库&#xff09; STM32 CubeMX STM32 CubeMX ADC采集&#xff08;HAL库&#xff09;ADC介绍ADC主要特征最小识别电压值&#xff1a;2.4/4096≈0.6mv&#xff08;不考虑误差&#xff09;一、STM32 CubeMX设置二、代码部分三&#xff0c;单通道…...

[UUCTF 2022 新生赛]ezpop - 反序列化+字符串逃逸【***】

[UUCTF 2022 新生赛]ezpop 一、解题过程二、其他WP三、总结反思 一、解题过程 题目代码&#xff1a; <?php //flag in flag.php error_reporting(0); class UUCTF{public $name,$key,$basedata,$ob;function __construct($str){$this->name$str;}function __wakeup(){i…...

Selenium进行无界面爬虫开发

在网络爬虫开发中&#xff0c;利用Selenium进行无界面浏览器自动化是一种常见且强大的技术。无界面浏览器可以模拟真实用户的行为&#xff0c;解决动态加载页面和JavaScript渲染的问题&#xff0c;给爬虫带来了更大的便利。本文将为您介绍如何利用Selenium进行无界面浏览器自动…...

万宾荣获深圳应博会“全球应急产业先锋奖”创始人发表峰会演讲

今年5月&#xff0c;住房和城乡建设部表示将全面启动的城市基础设施生命线安全工程工作&#xff0c;通过各类智能感知设备等数字化手段&#xff0c;及早发现和管控城市燃气、桥梁、供水、排水防涝等领域的风险隐患&#xff0c;切实提高城市安全保障能力、维护人民生命财产安全&…...

某果的一个小参数分析

分析链接:aHR0cHM6Ly9hcHBsZWlkLmFwcGxlLmNvbS9hY2NvdW50 分析目标&#xff1a;X-Apple-I-Fd-Client-Info 1.在浏览器搜索关键词&#xff0c;打下断点 我们再里面进行搜索&#xff0c;定位到这个位置&#xff0c;可以看到X-Apple-I-FD-Client-Info这个参数等于e&#xff0c;…...

java学习--day22(进程线程)

文章目录 1.什么是进程2.什么是线程3.线程和进程的区别【面试题】4.并发和并行5.创建线程的两种方式【重点】1.继承Thread2.实现Runnable接口 6.线程下面的几个方法7.线程的同步和锁【重要】 1.什么是进程 是独立的运行程序 ​ 比如咱们电脑软件&#xff0c;你启动起来以后&…...

对音频切分成小音频(机器学习用)

我是把so-vits中小工具&#xff0c;分析源码然后提取出来了。以后可以写在自己的程序里。 -------流程&#xff08;这是我做的流程&#xff0c;你可以不用看&#xff09; 从开源代码中快速获取自己需要的东西 如果有界面f12看他里面的接口&#xff0c;然后在源码中全局搜索&…...

TensorFlow案例学习:对服装图像进行分类

前言 官方为我们提供了一个 对服装图像进行分类 的案例&#xff0c;方便我们快速学习 学习 预处理数据 案例中有下面这段代码 # 预处理数据&#xff0c;检查训练集中的第一个图像可以看到像素值处于0~255之间 plt.figure() # 创建图像窗口 plt.imshow(train_images[0]) # …...

单目3D目标检测——SMOKE 模型推理 | 可视化结果

本文分享SMOKE的模型推理&#xff0c;和可视化结果。以kitti数据集为例子&#xff0c;对训练完的模型进行推理&#xff0c;并可视化3D框的结果&#xff0c;画到图像中。 关于模型原理、搭建开发环境、模型训练&#xff0c;可以参考之前的博客&#xff1a; 【论文解读】SMOKE …...

C++智能指针shared_ptr使用详解

shared_ptr 是一个共享所有权的智能指针,允许多个指针指向同一个对象。 ​ shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用它一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,释放所指向的堆内存。shared_ptr内部的引用计数是…...

基于Java的个性化旅游攻略系统设计与实现(源码+lw+ppt+部署文档+视频讲解等)

文章目录 前言具体实现截图论文参考详细视频演示代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技…...

中国替代方案探索:替代谷歌企业邮箱的选择

“谷歌企业邮箱在中国有哪些替代方案&#xff1f;在中国市场上表现出色的企业邮箱有腾讯企业邮箱、网易企业邮箱、阿里企业邮箱以及适合外贸的Zoho Mail企业邮箱。” 在中国由于各种原因&#xff0c;包括网络安全、数据隐私保护以及与GFW(防火长城)等&#xff0c;谷歌企业邮箱并…...

Holographic MIMO Surfaces (HMIMOS)以及Reconfigurable Holographic Surface(RHS)仿真

这里写目录标题 Simulation setupchatgpt帮我总结代码总结&#xff1a;chatgpt生成的代码还是不靠谱&#xff1a;考虑把之前看的RHS中对于多用户的改成单用户全系MIMO与普通MIMO或者说RIS的区别到底是啥&#xff1f; Holographic MIMO Surfaces &#xff08;HMIMOS&#xff09;…...

RK3568笔记一:RKNN开发环境搭建

若该文为原创文章&#xff0c;转载请注明原文出处。 由于对AI的好奇&#xff0c;想要学习如何部署AI&#xff0c;所以从RV1126到RK3568中过渡。 一、介绍 RK3568开发板使用的是正点原子新出的ATK-DLRK3568 开发板&#xff0c;主要是学习从训练到部署的全过程&#xff0c;并记…...

设计模式 - 行为型模式:策略模式(概述 | 案例实现 | 优缺点 | 使用场景)

目录 一、行为型模式 1.1、策略模式 1.1.1、概论 1.1.2、案例实现 1.1.3、优缺点 1.1.4、使用场景 一、行为型模式 1.1、策略模式 1.1.1、概论 策略模式设计的每一个算法都封装了起来&#xff0c;使他们可以相互替换&#xff0c;通过一个对象委派不同的算法给相应的客户…...

rancher部署pv、pvc、离线部署nfs

&#xff08;1&#xff09;NFS离线安装 使用nfs配置两台机器共享目录 假设两台机器188.188.30.32&#xff08;服务端&#xff09;、188.188.30.31&#xff08;客户端&#xff09;配置nfs 1.在可以联网的机器上下载rpm安装包 yum -y install nfs-utils --downloadonly --dow…...

视频拍摄教程分享

&#xff08;1&#xff09;新片场&#xff1a;静物美食视频拍摄(22.76GB) 链接:https://pan.baidu.com/s/1uj6wcPXGw-ztLQ1cdyogTA 提取码:929z&#xff08;永久有效&#xff09; &#xff08;2&#xff09;新片场&#xff1a;《孙晓迪分镜头脚本》掌握10种类型商业广告创作思…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...