OpenHarmony(鸿蒙南向)——平台驱动指南【HDMI】

news2024/9/27 8:34:42

往期知识点记录:

  • 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
  • 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
  • 持续更新中……

概述

功能简介

HDMI(High Definition Multimedia Interface),即高清多媒体接口,主要用于DVD、机顶盒等音视频Source到TV、显示器等Sink设备的传输。

HDMI以主从方式工作,通常有一个Source端和一个Sink端。

HDMI接口定义了完成HDMI传输的通用方法集合,包括:

  • HDMI控制器管理:打开或关闭HDMI控制器

  • HDMI启动/停止传输:启动或停止HDMI传输

  • HDMI控制器设置:设置音频、视频及HDR属性,设置色彩深度、声音图像消隐等

  • HDMI读取EDID:读取Sink端原始的EDID数据

  • HDMI热插拔:注册/注销热插拔回调函数

基本概念

HDMI是Hitachi、Panasonic、Philips、Silicon Image、Sony、Thomson、Toshiba共同发布的一款音视频传输协议。传输过程遵循TMDS(Transition Minimized Differential Signaling)协议。

  • TMDS(Transition Minimized Differential signal):过渡调制差分信号,也被称为最小化传输差分信号,用于发送音频、视频及各种辅助数据。

  • DDC(Display Data Channel):显示数据通道,发送端与接收端可利用DDC通道得知彼此的发送与接收能力,但HDMI仅需单向获知接收端(显示器)的能力。

  • CEC(Consumer Electronics Control):消费电子控制,该功能应该能够在连接HDMI的发送设备与接收设备之间实现交互操作。

  • FRL(Fixed Rate Link):TMDS 的架构进行讯号传输时,最高带宽可达 18Gbps,而FRL模式的带宽则提升到48 Gbps。

  • HDCP(High-bandwidth Digital Content Protection):即高带宽数字内容保护技术,当用户对高清晰信号进行非法复制时,该技术会进行干扰,降低复制出来的影像的质量,从而对内容进行保护。

  • EDID(Extended Display Identification Data):扩展显示标识数据,通常存储在显示器的固件中,标识供应商信息、EDID版本信息、最大图像大小、颜色设置、厂商预设置、频率范围的限制以及显示器名和序列号的字符串。

运作机制

在HDF框架中,HDMI模块接口适配模式拟采用独立服务模式,如图1所示。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDF设备管理器的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。

独立服务模式下,核心层不会统一发布一个服务供上层使用,因此这种模式下驱动要为每个控制器发布一个服务,具体表现为:

  • 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。

  • device_info.hcs文件中deviceNode的policy字段为1或2,不能为0。

图 1 HDMI独立服务模式结构图

HDMI模块各分层作用:

  • 接口层提供打开HDMI设备、启动HDMI传输、停止HDMI传输、声音图像消隐设置、设置色彩深度、获取色彩深度、设置视频属性、获取视频属性、设置HDR属性、读取Sink端原始EDID数据、注册HDMI热插拔检测回调函数、注销HDMI热插拔检测回调函数、关闭HDMI设备的接口。

  • 核心层主要提供HDMI控制器的打开、关闭及管理的能力,通过钩子函数与适配层交互。

  • 适配层主要是将钩子函数的功能实例化,实现具体的功能。

HDMI的Source端提供+5V和GND,用于DDC和CEC通信。通过DDC通道,Source端可以读取Sink端的各项参数,如接受能力等;CEC为可选通道,用于同步Source端与Sink端的控制信号,改善用户体验。TMDS通道有四组差分信号,TMDS Clock Channel为TMDS提供时钟信号,其余三组传输音视频数据及各种辅助数据;HDP为热插拔检测端口,当有Sink端接入时,Source端会通过中断服务程序进行响应。

HDMI物理连接如图2所示:

图 2 HDMI物理连线示意图

约束与限制

HDMI模块当前仅支持轻量和小型系统内核(LiteOS),暂无实际适配驱动 。

使用指导

场景介绍

HDMI具有体积小,传输速率高,传输带宽宽,兼容性好,能同时传输无压缩音视频信号等优点。与传统的全模拟接口相比,HDMI不但增加了设备间接线的便捷性,还提供了一些HDMI特有的智能化功能,可用于小体积设备进行高质量音视频传输的场景。

接口说明

HDMI模块提供的主要接口如下所示,具体API详见//drivers/hdf_core/framework/include/platform/hdmi_if.h。

表 1 HDMI驱动API接口功能介绍

接口名描述
HdmiOpen打开HDMI控制器
HdmiClose关闭HDMI控制器
HdmiStart启动HDMI传输
HdmiStop停止HDMI传输
HdmiAvmuteSet声音图像消隐设置
HdmiDeepColorSet设置色彩深度
HdmiDeepColorGet获取色彩深度
HdmiSetVideoAttribute设置视频属性
HdmiSetAudioAttribute设置音频属性
HdmiSetHdrAttribute设置HDR属性
HdmiReadSinkEdid读取Sink端原始EDID数据
HdmiRegisterHpdCallbackFunc注册HDMI热插拔检测回调函数
HdmiUnregisterHpdCallbackFunc注销HDMI热插拔检测回调函数

开发步骤

使用HDMI设备的一般流程如图3所示。

图 3 HDMI设备使用流程图

打开HDMI控制器

在进行HDMI通信前,首先要调用HdmiOpen打开HDMI控制器。

DevHandle HdmiOpen(int16_t number);

表 2 HdmiOpen参数和返回值描述

参数参数描述
numberint16_t类型,HDMI控制器号
返回值返回值描述
NULL打开HDMI控制器失败
控制器句柄打开的HDMI控制器句柄

假设系统中存在2个HDMI控制器,编号从0到1,以下代码示例为获取0号控制器:

DevHandle hdmiHandle = NULL;  // HDMI控制器句柄

// 打开HDMI控制器
hdmiHandle = HdmiOpen(0);
if (hdmiHandle == NULL) {
    HDF_LOGE("HdmiOpen: hdmi open fail!\n");
    return NULL;
}
注册热插拔检测回调函数
int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback);

表 3 HdmiRegisterHpdCallbackFunc参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
callback结构体指针,热插拔回调函数信息
返回值返回值描述
HDF_SUCCESS注册成功
负数注册失败

注册热插拔检测回调函数示例:

// 热插拔检测回调函数定义
static void HdmiHpdHandle(void *data, bool hpd)
{
    if (data == NULL) {
        HDF_LOGE("priv data is NULL");
        return;
    }
    if (hpd == true) {
        HDF_LOGD("HdmiHpdHandle: hot plug");
        // 调用者添加相关处理
    } else {
        HDF_LOGD("HdmiHpdHandle: hot unplug");
        // 调用者添加相关处理
    }
}

// 热插拔检测回调函数注册示例
struct HdmiHpdCallbackInfo info = {0};
info.data = handle;
info.callbackFunc = HdmiHpdHandle;
ret = HdmiRegisterHpdCallbackFunc(hdmiHandle, info);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiRegisterHpdCallbackFunc: Register hpd callback func fail, ret:%d", ret);
    return ret;
}
读取EDID
int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);

表 4 HdmiReadSinkEdid参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
bufferuint8_t类型指针,数据缓冲区
lenuint32_t类型,数据长度
返回值返回值描述
正整数成功读取的原始EDID数据
负数或0读取失败

读取Sink端的原始EDID数据示例:

int32_t len;
uint8_t edid[HDMI_EDID_MAX_LEN] = {0};

len = HdmiReadSinkEdid(hdmiHandle, edid, HDMI_EDID_MAX_LEN);
if (len <= 0) {
    HDF_LOGE("HdmiReadSinkEdid: hdmi read sink edid fail, len = %d.", len);
	return HDF_FAILURE;
}
设置音频属性
int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr);

表 5 HdmiSetAudioAttribute参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
attr结构体指针,音频属性
返回值返回值描述
HDF_SUCCESS设置成功
负数设置失败

设置音频属性示例:

struct HdmiAudioAttr audioAttr = {0};
int32_t ret;

audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3;
audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S;
audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16;
audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K;
audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3;
ret = HdmiSetAudioAttribute(handle, &audioAttr);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiSetAudioAttribute: hdmi set audio attribute fail!, ret:%d", ret);
    return ret;
}
设置视频属性
int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr);

表 6 HdmiSetVideoAttribute参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
attr结构体指针,视频属性
返回值返回值描述
HDF_SUCCESS设置成功
负数设置失败

设置视频属性示例:

struct HdmiVideoAttr videoAttr = {0};
int32_t ret;

videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444;
videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED;
videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL;
ret = HdmiSetVideoAttribute(handle, &videoAttr);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiSetVideoAttribute: hdmi set video attribute fail, ret:%d.", ret);
    return ret;
}
设置HDR属性
int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr);

表 7 HdmiSetHdrAttribute参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
attr结构体指针,HDR属性
返回值返回值描述
HDF_SUCCESS设置成功
负数设置失败

设置HDR属性示例:

struct HdmiHdrAttr hdrAttr = {0};
int32_t ret;

hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3;
hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY;
hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048;
hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1;
hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709;
ret = HdmiSetHdrAttribute(handle, &hdrAttr);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiSetHdrAttribute: hdmi set hdr attribute fail, ret:%d", ret);
    return ret;
}
设置HDMI声音图像消隐
int32_t HdmiAvmuteSet(DevHandle handle, bool enable);

表 8 HdmiAvmuteSet参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
enable布尔值,使能/去使能avmute
返回值返回值描述
HDF_SUCCESS设置成功
负数设置失败

设置声音图像消隐示例:

int32_t ret;

ret = HdmiAvmuteSet(hdmiHandle, true);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiAvmuteSet: hdmi avmute set fail, ret:%d", ret);
    return ret;
}
设置色彩深度
int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color);

表 9 HdmiDeepColorSet参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
color枚举类型,色彩深度
返回值返回值描述
HDF_SUCCESS设置成功
负数设置失败

设置色彩深度示例:

int32_t ret;

ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiDeepColorSet: hdmi deep color set fail, ret:%d.", ret);
    return ret;
}
获取色彩深度
int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color);

表 10 HdmiDeepColorGet参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
color枚举类型指针,色彩深度
返回值返回值描述
HDF_SUCCESS获取成功
负数获取失败

获取色彩深度示例:

enum HdmiDeepColor color;
int32_t ret;

ret = HdmiDeepColorGet(handle, &color);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiDeepColorGet: hdmi deep color get fail, ret:%d", ret);
    return ret;
}
启动HDMI传输
int32_t HdmiStart(DevHandle handle);

表 11 HdmiStart参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
返回值返回值描述
HDF_SUCCESS启动成功
负数启动失败

启动HDMI传输示例:

int32_t ret;

ret = HdmiStart(hdmiHandle);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiStart: start transmission fail, ret:%d", ret);
    return ret;
}
停止HDMI传输
int32_t HdmiStop(DevHandle handle);

表 12 HdmiStop参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
返回值返回值描述
HDF_SUCCESS停止成功
负数停止失败

停止HDMI传输示例:

int32_t ret;

ret = HdmiStop(hdmiHandle);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiStop: stop transmission fail, ret:%d.", ret);
    return ret;
}
注销热插拔检测回调函数
int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle);

表 13 HdmiUnregisterHpdCallbackFunc参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄
返回值返回值描述
HDF_SUCCESS注销成功
负数注销失败

注销热插拔检测回调函数示例:

int32_t ret;

ret = HdmiUnregisterHpdCallbackFunc(hdmiHandle);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("HdmiUnregisterHpdCallbackFunc:unregister fail, ret:%d.", ret);
    return ret;
}
关闭HDMI控制器
void HdmiClose(DevHandle handle);

表 14 HdmiClose参数和返回值描述

参数参数描述
handleDevHandle类型,HDMI控制器句柄

关闭HDMI控制器示例:

HdmiClose(hdmiHandle);

使用实例

本例程以操作开发板上的HDMI设备为例,详细展示HDMI接口的完整使用流程。

本例拟在Hi3516DV300开发板上对虚拟驱动进行简单的传输操作:

  • SOC:hi3516dv300。

  • HDMI控制器:使用0号HDMI控制器。

示例如下:

#include "hdmi_if.h"          /* HDMI标准接口头文件 */
#include "hdf_log.h"         /* 标准日志打印头文件 */
#include "osal_time.h"       /* 标准延迟&睡眠接口头文件 */

/* 热插拔回调函数 */
static void HdmiHpdHandle(void *data, bool hpd)
{
    if (data == NULL) {
    HDF_LOGE("priv data is NULL");
    return;
    }

    if (hpd == true) {
        HDF_LOGD("HdmiHpdHandle: hot plug");
        /* 调用者添加相关处理 */
    } else {
        HDF_LOGD("HdmiHpdHandle: hot unplug");
        /* 调用者添加相关处理 */
    }
}

/* 设置HDMI相关属性 */
static int32_t TestHdmiSetAttr(DevHandle handle)
{
    enum HdmiDeepColor color;
    struct HdmiVideoAttr videoAttr = {0};
    struct HdmiAudioAttr audioAttr = {0};
    struct HdmiHdrAttr hdrAttr = {0};
    int32_t ret;

    ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS);

    if (ret != 0) {
        HDF_LOGE("HdmiDeepColorSet failed.");
        return ret;
    }
    ret = HdmiDeepColorGet(handle, &color);
    if (ret != 0) {
        HDF_LOGE("HdmiDeepColorGet failed.");
        return ret;
    }
    HDF_LOGE("HdmiDeepColorGet successful, color = %d.", color);
    videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444;
    videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED;
    videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
    videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL;
    ret = HdmiSetVideoAttribute(handle, &videoAttr);
    if (ret != 0) {
        HDF_LOGE("HdmiSetVideoAttribute failed.");
        return ret;
    }
    audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3;
    audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S;
    audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16;
    audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K;
    audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3;
    ret = HdmiSetAudioAttribute(handle, &audioAttr);
    if (ret != 0) {
        HDF_LOGE("HdmiSetAudioAttribute failed.");
        return ret;
    }
    hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3;
    hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY;
    hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048;
    hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1;
    hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709;
    ret = HdmiSetHdrAttribute(handle, &hdrAttr);
    if (ret != 0) {
        HDF_LOGE("HdmiSetHdrAttribute failed.");
        return ret;
    }

    return 0;
}

/* HDMI例程总入口 */
static int32_t TestCaseHdmi(void)
{
    DevHandle handle = NULL;
    int32_t ret;

    struct HdmiHpdCallbackInfo info = {0};
    uint8_t data[128] = {0};

    HDF_LOGD("HdmiAdapterInit: successful.");
    handle = HdmiOpen(0);
    if (handle == NULL) {
        HDF_LOGE("HdmiOpen failed.");
        return ret;
    }
    info.data = handle;
    info.callbackFunc = HdmiHpdHandle;
    ret = HdmiRegisterHpdCallbackFunc(handle, &info);
    if (ret != 0) {
        HDF_LOGE("HdmiRegisterHpdCallbackFunc failed.");
        return ret;
    }

    ret = HdmiReadSinkEdid(handle, data, 128);
    if (ret <= 0) {
        HDF_LOGE("HdmiReadSinkEdid failed.");
        return ret;
    }
    HDF_LOGE("HdmiReadSinkEdid successful, data[6] = %d, data[8] = %d.", data[6], data[8]);

    ret = TestHdmiSetAttr(handle);
    if (ret != 0) {
        HDF_LOGE("TestHdmiSetAttr failed.");
        return ret;
    }

    ret = HdmiStart(handle);
    if (ret != 0) {
        HDF_LOGE("HdmiStart failed.");
        return ret;
    }

    OsalMSleep(1000);

    ret = HdmiStop(handle);
    if (ret != 0) {
        HDF_LOGE("HdmiStop failed.");
        return ret;
    }

    ret = HdmiUnregisterHpdCallbackFunc(handle);
    if (ret != 0) {
        HDF_LOGE("HdmiUnregisterHpdCallbackFunc failed.");
        return ret;
    }
    HdmiClose(handle);
    return 0;
}

最后

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

鸿蒙开发面试真题(含参考答案):

在这里插入图片描述

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片
在这里插入图片描述

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

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

相关文章

VS Code设置合集

目录 VS Code设置合集1、汉化2、VS Code自动报错3、VS Code右键没有Open In Default Browser4、VS Code设置颜色主题5、修改默认缩进字符 VS Code设置合集 1、汉化 点击插件 → 搜索chinese → 点击install&#xff0c; 同时按住ctrl shift P → 搜索>configure displ…

架构师:消息队列的技术指南

1、简述 消息队列(Message Queue, MQ)是一种异步通信机制,允许系统的各个组件通过消息在彼此之间进行通信。消息队列通过解耦系统组件、缓冲高峰期请求和提高系统的可扩展性,成为分布式系统中不可或缺的一部分。 2、工作原理 消息队列的基本工作原理是生产者将消息发布到…

Lesson08---string(4)类

Lesson08—string类&#xff08;4&#xff09; c第八章string类的实现 文章目录 Lesson08---string类&#xff08;4&#xff09;前言一、计算机是怎么储存文字的1. 在此之前先思考一个问题2.编码表2.1 ascll码2.2unicode码2.3UTF码2.4gbk码 二、实现一个简单的string1.构造函数…

【LeetCode】每日一题 2024_9_21 边积分最高的节点(哈希)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;边积分最高的节点 代码与解题思路 func edgeScore(edges []int) (ans int) {// 直接维护哈希最大值即可mp : map[int]int{}for i, v : range edges {mp[v] i// 如果多个节点的 边积分 相…

Flutter中使用FFI的方式链接C/C++的so库(harmonyos)

Flutter中使用FFI的方式链接C/C库&#xff08;harmonyos&#xff09; FFI plugin创建和so的配置FFI插件对so库的使用 FFI plugin创建和so的配置 首先我们可以根据下面的链接生成FFI plugin插件&#xff1a;开发FFI plugin插件 然后在主项目中pubspec.yaml 添加插件的依赖路径&…

PDF 秒变 JPG,2024 这些工具来助力

有些扫描仪默认将扫描文档保存为PDF格式&#xff0c;若事先未加留意&#xff0c;便可能累积大量PDF文件。然而&#xff0c;在需要将这些文件插入到其他文档或进行图形设计时&#xff0c;PDF格式可能会显得不够灵活或便捷。这时&#xff0c;将PDF转换为JPG图片格式就成为了一个实…

9.C++程序中的选择语句

选择语句一共分为两种&#xff1a;条件语句和开关语句 其中条件语句叫if语句&#xff0c;常见的形式为&#xff1a;if ... else ... ; 再复杂一些为if... else if ... else ... ; 开关语句又叫switch语句&#xff0c;类型于开关的使用形式常见的有 switch (var) case : ... b…

ai写论文哪个软件好?分享4款ai论文写作工具软件

在当前的学术研究和论文写作领域&#xff0c;AI技术的应用已经成为一种趋势。AI论文写作工具不仅能够提高写作效率&#xff0c;还能帮助研究者生成高质量的论文。以下是四款值得推荐的AI论文写作工具软件&#xff0c;其中特别推荐千笔-AIPassPaper。 1. 千笔-AIPassPaper 传送…

Cluade 3.5 Sonnet 提示词泄露

prompt 翻译&#xff1a; The notebook currently demonstrates support for a two agent setup. Support for GroupChat is currently in development.

EF Core优化技巧之预热处理

1. 前言 今天和听到同事们在讨论一个关于使用EFCore时&#xff0c;为什么第一次查询数据库总是很慢的原因。我们在工作中经常使用EFCore进行数据访问&#xff0c;但发现每次第一次查询都需要较长的时间&#xff0c;这给我们带来了困扰。因此&#xff0c;我们聚在一起&#xff…

Redis实战--Redis应用过程中出现的热门问题及其解决方案

Redis作为一种高性能的key-value数据库&#xff0c;广泛应用于缓存、消息队列、排行榜等场景。然而&#xff0c;在实际应用中&#xff0c;随着业务规模的不断扩大和访问量的持续增长&#xff0c;缓存系统也面临着诸多挑战&#xff0c;其中最为典型的便是缓存穿透、缓存击穿和缓…

Ansible集群服务部署案例

案例描述 本案例共讲述了多个节点部署Elk集群日志分析系统&#xff0c;分别在三个节点使用ansible部署Kibana、Logstash以及Elasticsearch服务。 案例准备 1. 规划节点 IP 主机名 节点 192.168.100.25 ansible Ansible节点 192.168.100.35 node1 Elasticsearch/Kiba…

shell用文件管理备份文件路径

从文件中读取文件路径 while IFS read -r s; do&#xff1a;这行代码启动一个 while 循环&#xff0c;逐行读取 001.sh 文件的内容。 IFS&#xff1a;将内部字段分隔符&#xff08;IFS&#xff09;设置为空&#xff0c;确保读取整行而不被默认的空格和换行符分隔。这样可以保…

知识管理数据库

知识管理数据库&#xff0c;可以分为几类&#xff1a; 灵感库、卡片库、作品库。 灵感库&#xff0c;通常是素材&#xff0c;想法。 片库&#xff0c;是完整的&#xff0c;成段落的文字。 作品库&#xff0c;是文章、专栏&#xff0c;或者书籍。 这三者的关系&#xff0c;好比…

java通过webhook给飞书发送群消息

现在使用飞书的人越来越多了&#xff0c;飞书有一个最大的好处&#xff0c;可以使用webhook简便的发送群消息。而在工作中&#xff0c;也经常会因为一些运维方面的工作&#xff0c;需要给飞书发送群消息&#xff0c;来实时提醒相关负责人,及时处理工作。 一、先看一下效果吧&a…

【计算机网络】网络层详解

文章目录 一、引言二、IP 基础知识1、IP 地址2、路由3、IP报文4、IP报文的分片与重组 三、IP 属于面向无连接型四、IP协议相关技术1、DNS2、ICMP3、NAT技术4、DHCP 一、引言 TCP/IP的心脏是网络层。这一层主要由 IP 和 ICMP 两个协议组成。网络层的主要作用是“实现终端节点之…

Visual Studio Code下载安装及汉化

官网&#xff1a;https://code.visualstudio.com/ 按照指示一步步操作即可&#xff1a; 汉化&#xff1a;

Stable Diffusion零基础学习

Stable Diffusion学习笔记TOP12 _插件篇之ControlNet功能篇 ControlNet目前支持的10多种预处理器&#xff0c;根据数据检测种类可分为两种类型&#xff1a; 1、功能型&#xff1a;拥有着不同的能力 2、构图型&#xff1a;控制着SD扩散图形的构图规则 Seg语义分割&#xff1a…

2025年第十届智能信息技术国际会议 (ICIIT 2025)即将召开!

第10届智能信息技术国际会议&#xff08;ICIIT 2025&#xff09;将于2025年2月20日至23日在越南河内举行。ICIIT系列会议将每年举行&#xff0c;为智能信息技术及相关领域提供互动论坛&#xff0c;除了越南的研究人员外&#xff0c;会议小组还欢迎来自世界各地的有兴趣与该地区…

SpringBoot框架快速入门

1、起步依赖 1.概述 在入门案例中&#xff0c;我们引入了web依赖和test依赖&#xff0c;这两个依赖是SpringBoot中的starter依赖&#xff0c;starter依赖也被称为起步依赖 SpringBoot 在配置上相比Spring要简单许多&#xff0c;其核心在于spring-boot-starter&#xff0c;在使…