音视频基础知识分享

音视频基础知识分享

RKMedia的各个组件及其交互

首先上图:

在这里插入图片描述

考虑到公司业务主要是相机,所以,主要去关注图像数据流,对于音频数据流直接忽略。

图像数据流向:

  1. Camera Sensor将光信号转换成电信号(Raw数据) ->

  2. ISP( image signal peocess)初步对raw数据进行一些处理,此时数据格式变成了(yuv420的变种)NV12格式 ->

  3. NV12格式数据下面的流向大体有三种:MPP、RGA、DRM。

  4. 首先是MPP,在rkmedia中,该模块主要对传送过来的图像数据做编码操作,比如将数据编码成H264、H265格式。这些格式能极大的压缩图像数据的大小。具体H264里面的结构,文章后面有详细介绍。OSD对于框图中MPP上面的OSD模块,可以为MPP中每一帧图像添加一些额外的标记吧。OSD模块和MPP是 相互绑定 的,至少我目前在代码中看到的是这样。

  5. 其次是RGA,该模块独立存在,并且可以对输入的NV12图像进行裁剪、缩放、旋转,然后将处理都图像数据发送给MPP模块。

  6. 最后是DRM模块,该模块就是一个图像显示框架,可以直接将输入的数据显示到屏幕上。

  7. 在经过MPP模块编码后的图像,最后还会一个叫Muxer的模块,该模块会将编码后的图像数据和音频数据进行打包,打包成MP4或者flx等格式,最后推流给服务器。

raw原始图像格式有四种包括:BGGR、RGGB、GBRG、GRBG。也称Bayer raw。

VI是基于v4l2接口实现

RKMedia接收者和发送者绑定限制:

在这里插入图片描述

摄像头的工作方式

摄像头有三种工作方式:

typedef enum {RK_AIQ_WORKING_MODE_NORMAL,                 // 又称单帧模式RK_AIQ_WORKING_MODE_ISP_HDR2    = 0x10,     // 两帧和成一帧RK_AIQ_WORKING_MODE_ISP_HDR3    = 0x20,     // 三帧合成一帧
//    RK_AIQ_WORKING_MODE_SENSOR_HDR = 10, // sensor built-in hdr mode
} rk_aiq_working_mode_t;

hdr解释为高动态范围,能显示的亮度范围更大,三帧合一中的三帧对应:欠曝光帧,正常曝光帧,过度曝光帧。

一般使用常规单帧

关于MIPI接口标准也是很复杂,本文先在应用层简单了解一下它的使用,具体细节,后面需要再去深究。这里还是贴一张它的框图:

在这里插入图片描述

上面的CCI就是相机控制接口,使用I2C进行通信。下面CSI就是相机串行接口,主要是传输数据用的。

接下来根据ISP的初始化代码来进一步了解ISP:

代码如下:

// RK_S32 SAMPLE_COMM_ISP_Init(RK_S32 CamId, rk_aiq_working_mode_t WDRMode,
//                             RK_BOOL MultiCam, const char *iq_file_dir) rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL;
int fps = 30;
SAMPLE_COMM_ISP_Init(s32CamId, hdr_mode, bMultictx, pIqfilesPath);
SAMPLE_COMM_ISP_Run(s32CamId);// 设置isp处理帧率非视频显示帧率
SAMPLE_COMM_ISP_SetFrameRate(s32CamId, fps);

CamId:代表使用哪个mipi csi,0代表mipi csi0,1代表mipi csi1,如果只有一个摄像头就可以为0,不管摄像头插在哪个接口(默认id就是0),如果有两个摄像头,就必须有camid的区分。

WDRMode:就是上面提到的三种工作模式。

MultiCam:false代表开启一个摄像头的isp,true代表开启多个摄像头的isp,一个摄像头设置为false即可。

iq_file_dir:并且ISP的工作会依赖iq配置文件,所以函数SAMPLE_COMM_ISP_Init中iq_file_dir就是iq文件所在目录。

此外,多个摄像头使用一个isp会分时复用,

注意这里提一下ISPP输出码流格式限制:

在这里插入图片描述

RGA模块的使用

接下来深入认识一下RGA模块的使用:

RGA_ATTR_S stRgaAttr;
memset(&stRgaAttr, 0, sizeof(stRgaAttr));
stRgaAttr.bEnBufPool = RK_TRUE;             // 使用缓冲池
stRgaAttr.u16BufPoolCnt = 3;                // 缓冲池的数量
stRgaAttr.u16Rotaion = 90;                  // 旋转90度
stRgaAttr.stImgIn.u32X = 0;                 // 在输入图像的横坐标为x处取样
stRgaAttr.stImgIn.u32Y = 0;                 // 在输入图像的纵坐标为y处取样
stRgaAttr.stImgIn.imgType = IMAGE_TYPE_NV12;// 输入图像格式
stRgaAttr.stImgIn.u32Width = video_width;   // 输入图像宽
stRgaAttr.stImgIn.u32Height = video_height; // 输入图像高
stRgaAttr.stImgIn.u32HorStride = video_width; // 水平跨距
stRgaAttr.stImgIn.u32VirStride = video_height;  // 垂直跨距
stRgaAttr.stImgOut.u32X = 0;                    // 相对stImgIn.u32X
stRgaAttr.stImgOut.u32Y = 0;                    // 相对stImgIn.u32Y
stRgaAttr.stImgOut.imgType = IMAGE_TYPE_RGB888; // 输出图像格式
stRgaAttr.stImgOut.u32Width = disp_width;       // 输出宽
stRgaAttr.stImgOut.u32Height = disp_height;     // 输出高
stRgaAttr.stImgOut.u32HorStride = disp_width;   // 含义同输入
stRgaAttr.stImgOut.u32VirStride = disp_height;  // 含义同输入
ret = RK_MPI_RGA_CreateChn(0, &stRgaAttr);

前后还其实涉及VI模块、以及VI和RGA模块的绑定,考虑到篇幅太大,这里就掠过了,主要看RGA模块的配置。

总结一下:stImgIn可以利用stImgIn.u32X、stImgIn.u32Y进行裁剪,stImgOut可以利用stImgOut.u32Width、stImgOut.u32Height进行缩放。

RGA模块对图像格式的支持也是有限的,参考如下:

在这里插入图片描述

modetest命令可查看各个图层支持的格式

VOP对 VO_PLANE_PRIMARY = 0,
VO_PLANE_OVERLAY,两层有裁剪功能。并且VO_PLANE_OVERLAY还支持缩放

VO_PLANE_OVERLAY -> win0
VO_PLANE_PRIMARY -> win2
VO_PLANE_CURSOR -> 背景层(rv1126不支持)

杂项

I帧(IDR帧,Instantaneous Decoding Refresh) :帧内编码帧是一种自带全部信息的独立帧,无需参考其它图像便可独立进行解码,视频序列中的第一个帧始终都是I帧。 属于帧内压缩,压缩质量好,压缩比例小。IDR帧一定是I帧,I帧不一定是IDR帧。

P帧 :前向参考,采用帧内、帧间压缩。

B帧 :前后参考,采用帧内、帧间压缩,实时视频传输会关闭B帧。未来无法预测,需要先将B帧缓冲,等待后面的帧解码后,再从B帧往后开始播放。

压缩比:B>P>I

GOP :H264中GOP就是一个图像序列,即从I帧开始到最后一个连续的非I帧为止的一组帧,一般而言同一组GOP的帧之间相似度很高。

GOP又分两种:

  • open GOP:不同GOP之间的P、B帧可以跨GOP进行参考

  • close GOP:不同GOP之间的P、B帧不能跨GOP参考,也即不能参考IDR帧之前的帧。

RKKmedia的GOP有三种模式:如下:

在这里插入图片描述

再细分

一帧图像可以划分成一个或者多个slice,slice称为片或者条带。

slice:I条带、P条带、B条带。为支持不同编码流之间的切换,还定义了SI条带、SP条带。

设置条带的目的就是为了并行编码,使编码片之间相互独立进行编码,能够限制误码的扩散和传播。

在这里插入图片描述

宏块就是视频压缩的基本单位、H264固定16*16。

H265:编码单元的名称叫:CTU(树形编码单元),大小是64*64像素,每个CTU包含3个CTB(树形编码快),每个CTU包含若干CU(编码单元),CU还能进行更灵活的细分。

8*8小宏块压缩比小,但图像质量好

16*16大宏块压缩比大,但图像质量查,一些些细节存在失真




YUV

参考:https://zhuanlan.zhihu.com/p/113122344

首先了解一下RGB,RGB以三原色(红绿蓝)来表示一张图片,以一张1280 * 720 大小的图片为例,因为每个像素都有三个字节来控制颜色,所以占用 1280 * 720 * 3 / 1024 / 1024 = 2.63 MB 存储空间

而YUV 颜色编码采用的是 明亮度色度 来指定像素的颜色。

色度 又定义了颜色的两个方面:色调和饱和度

也即yuv中每个像素也可以使用三个字节来控制其颜色。

但是: 对于 YUV 图像来说,**并不是每个像素点都需要包含了 Y、U、V 三个分量,根据不同的采样格式,可以每个 Y 分量都对应自己的 UV 分量,也可以几个 Y 分量共用 UV 分量。**Y 和 UV 分量是可以分离的,如果没有 UV 分量一样可以显示完整的图像,只不过是 黑白的。

yuv和rgb可以相互转化,一般来说,传输会使用yuv(节省带宽),显示的时候会使用rgb。公式如下:

在这里插入图片描述

在这里插入图片描述

接下来就是yuv图像的采样,yuv图像的采样就是基于上面rgb转换成yuv后的数据进行采样,YUV 图像的主流采样方式有如下三种:

  • YUV 4:4:4 采样

  • YUV 4:2:2 采样

  • YUV 4:2:0 采样

YUV 4:4:4 采样

YUV 4:4:4 采样是完整的将rgb->yuv,不存在分量的丢失

形如:

rgb->yuv:假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]对yuv进行采样:采样后的yuv码流:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3对采样后的yuv码流进行网络传输:...将采样后的yuv码流->“完整”的yuv:最后映射出的像素点依旧为 [Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3] 

可以看出来,其图像大小和rgb一样,没有达到节省带宽的目的。

YUV 4:4:4 也是采样进行的第一步,先将rgb码流转换成完整的yuv码流,再根据需求,对vu分量按比例进行采样。(注意:y分量不可漏采!

YUV 4:2:2 采样

表示uv分量占y分量的一半,形如:

rgb->yuv:假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]对yuv进行采样:采样后的yuv码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3 对采样后的yuv码流进行网络传输:...将采样后的yuv码流->“完整”的yuv:最后映射出的像素点为 [Y0 U0 V1]、[Y1 U0 V1]、[Y2 U2 V3]、[Y3 U2 V3]

采样规则: 每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会 间隔一列 采样。也即uv分量是YUV 4:4:4的1/2

可以看到再最后将采样后的yuv”还原“成”完整“的yuv后,第一个像素和第二个像素共用一个uv分量。第三像素和第四像素也一样。并且采样后的yuv码流大小为:(1280 * 720 * 1 + (1280 * 720) / 2 + (1280 * 720) / 2)/ 1024 / 1024 = 1.7578125 MB 可以看到压缩了近三分之一的带宽。

YUV 4:2:0 采样

YUV 4:2:0采样会比较难理解,举个例子,如下:

rgb->yuv:假设图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、 [Y2 U2 V2]、 [Y3 U3 V3]
[Y5 U5 V5]、[Y6 U6 V6]、 [Y7 U7 V7] 、[Y8 U8 V8]对yuv进行采样:采样后的yuv码流为:Y0 U0 Y1 Y2 U2 Y3 Y5 V5 Y6 Y7 V7 Y8对采样后的yuv码流进行网络传输:...将采样后的yuv码流->“完整”的yuv:最后映射出的像素点为:[Y0 U0 V5]、[Y1 U0 V5]、[Y2 U2 V7]、[Y3 U2 V7]
[Y5 U0 V5]、[Y6 U0 V5]、[Y7 U2 V7]、[Y8 U2 V7]

采样规则: 每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会交替 间隔一行 采样,并且一行采样中,隔一列 采样。也即uv分量是YUV 4:2:2 采样的1/2

最后在将采样的yuv”还原“成”完整“的yuv后,每四方格像素会共用一个uv分量。并且采样后的yuv码流大小为: (1280 * 720 * 1 + ((1280 / 2) * (720 / 2)) + ((1280 / 2) * (720 / 2)))/ 1024 / 1024 = 1.318359375 MB 将原来的rgb码流大小压缩了1/2倍!

YUV 4:2:2 变种

YUV 4:2:2 采样又有很多变种,比如:YUYV 格式、UYVY 格式、YUV 422P 格式。

YUYV(打包格式)形如:

rgb->yuv:假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]对yuv进行采样:采样后的yuv码流为:Y0 U0 Y1 V0 Y2 U1 Y3 V1 对采样后的yuv码流进行网络传输:...将采样后的yuv码流->“完整”的yuv:最后映射出的像素点为 [Y0 U0 V0]、[Y1 U0 V0]、[Y2 U1 V1]、[Y3 U1 V1]

采样规则: 每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量逐帧依次采样。

UYVY(打包格式) 和YUYV同理,仅仅存储的顺序不同。

YUV 422P(平面格式) :先存储所有Y分量,再存储U,最后V。

YUV 4:2:0 变种

主要包括两大类:YUV 420P 和 YUV 420SP,YUV 420P对应YU12、YV12,YUV 420SP对应NV12、NV21。YUV 420P 和 YUV 420SP都是基于平面模式存储。这里就不展开讨论。




H264

可以参考网站: https://www.zzsin.com/article/avc_0_start.html

H264没有音频、没有时间戳,处理图像本身,啥都没有。

H264又称avc,由一个个nalu组成。

有两种标准:AnnexB、avcC

AnnexB,nalu之间使用起始码分隔(一般是001或者0001(每位代表一字节)),并且类型为sps、pps的nalu当作普通nalu处理。当然,如果原数据中本身存在001字节序列,为使其正常传输,在发送数据前,会将原数据中的所有的”已定义字符“(001/0001)转义一下,这也是防竞争字节的概念。规则如下:

0 0 0 => 0 0 3 0
0 0 1 => 0 0 3 1
0 0 2 => 0 0 3 2
0 0 3 => 0 0 3 3

avcC,在每个nalu前面有一个固定长度的字节,这些字节会描述紧跟着的nalu有效载荷数据的长度。并且在一路采用 avcC 打包的 H.264 流之中,我们首先看到的将是一段被称之为 extradata 的数据,这段数据定义了这个 H.264 流的基本属性数据,当然,也包含了 SPS 和 PPS 数据。和AnnexB不同,avcC会将SPS和PPS放到extradata中(也可以把extradata看作协议头)。extradata还会定义,固定长度的字节的固定长度。extradata格式如下:

长度(bits)名称备注
8version总是等于 0x01
8avc profile所存放第一个 SPS 的第一个字节
8avc compatibility所存放第一个 SPS 的第二个字节
8avc level所存放第一个 SPS 的第三个字节
6reserved保留字段
2NALULengthSizeMinusOneNALU Body Length 数据的长度减去 1
3reserved保留字段
5number of SPS NALUs有几个 SPS,一般情况下这里是 1
for(int i=0; i<number of SPS NALUs; i++){~
16SPS sizeSPS 的长度
变长SPS NALU dataSPS NALU 的数据
}~
8number of PPS NALUs有几个 PPS,一般情况下这里是 1
for(int i=0; i<number of PPS NALUs; i++){~
16PPS sizePPS 的长度
变长PPS NALU dataPPS NALU 的数据
}~

nalu的第一个字节依次存放:禁止位、该nalu的重要性、nalu的类型。格式如下:

nal_unit( NumBytesInNALunit )CDescriptor
forbidden_zero_bitAllf(1)
nal_ref_idcAllu(2)
nal_unit_typeAllu(5)

典型的nalu类型有:

nalu的类型为sps(Sequence Paramater Set)的level表示视频质量(5.1)

nalu的类型为sps(Sequence Paramater Set)的profile表示码流压缩档次(100)

nalu的类型为sei:补充增强信息单元。存放用户自定义的信息(可有可无

其余的参考下图:

在这里插入图片描述

sps的profile值可以参考如下:

在这里插入图片描述

nalu后续字节就是图像的有效载荷。




其他

H264中,码率控制模式(RCMode)包括:CBR、VBR、AVBR

  1. CBR:恒定码率,码率变化平稳,但是当有运动画面时,图像质量会变差只考虑带宽、不考虑图像质量,可以使用这种模式

  2. VBR:可变码率,码率会依据图像质量的变化而变化,在意图像质量可以使用该模式。

  3. AVBR:自适应可变码率,会自动检测当前编码的图像画面是运动的还是静止的,如果是运动的,会提高码率,否则会降低码率,同时考虑带宽和图像质量就使用该模式。结合了CBR和VBR的优点。

RKMedia中有专门的成员来配置选择哪种模式。

英文缩写注释:

ROI:region of interest:感兴趣的区域。

SVC和AVC都属于H264但是属于不同标准


本章完结

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

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

相关文章

指针——函数指针数组

&#xff08;一&#xff09;前文回顾 1、前篇代码分析 void(*signal(int , void(*)(int)))(int) ; 那么这串代码究竟是什么呢&#xff1f; 别慌&#xff0c;让我们来一步一步拆解&#xff0c;首先我们通过之前的学习&#xff0c;已经明白了什么是函数指针&#xff08;如果有…

基于Python实现“气象家园”自动签到

一、安装库 pip install OAFuncs 二、导入库 from OAFuncs.oa_sign.meteorological import sign_in_meteorological_home as sign三、签到 email your_email # 16031215qq.com password your_pwd sign(email, password…

VS Code开发qt项目

没整明白&#xff0c;尴尬 安装扩展 设置cmake路径 前提是已经安装了QT 报错 用msvc选windows启动&#xff0c;用mingw则选gdb启动

基于语音识别的停车共享小程序(lw+演示+源码+运行)

目 录 1 绪论1 1.1 课题研究背景1 1.2 研究现状1 1.3 论文结构安排1 2 系统关键技术2 2.1 微信小程序2 2.2 微信Web开发者工具2 2.3 JavaScript简介2 2.4 微信小程序API接口2 2.5 MYSQL数据库2 3 系统分析1 3.1 可行性分析1 3.1.1 技术可行性1 3.1.2 经济可行性1…

飞腾X100适配Ubuntu说明

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…

[Linux#67][IP] 报头详解 | 网络划分 | CIDR无类别 | DHCP动态分配 | NAT转发 | 路由器

目录 一. IP协议头格式 学习任何协议前的两个关键问题 IP 报头与有效载荷分离 分离方法 为什么需要16位总长度 如何交付 二. 网络通信 1.IP地址的划分理念 2. 子网管理 3.网络划分 CIDR&#xff08;无类别域间路由&#xff09; 目的IP & 当前路由器的子网掩码 …

不做邮箱投稿的奴隶,要做单位信息宣传考核计分投稿的主人

在我刚开始承担单位的信息宣传考核任务时,心中充满了激情与期待。作为一名普通员工,我深知信息宣传的重要性,它不仅关乎单位的形象,更是我们对外沟通的桥梁。然而,现实的残酷让我逐渐体会到了压力的沉重。 最初,我选择了通过邮箱进行投稿。这种方式听起来似乎是最优雅的选择,毕…

页面请求快速迁移至接口工具(apifox、postman) 进行针对性调试

文章目录 需求背景实操 需求背景 自动携带参数&#xff0c;仅进行少量更改 在功能模块开发前期&#xff0c;难免会有让后端协助造数据&#xff0c;对通业务流程的场景 不确定造的数据或者后端的改动是否满足自己的需求&#xff0c;改一次有问题又等着改了再看很浪费时间 调用接…

Redis可视化软件安装

Anther Redis Desktop Manager 软件链接&#xff1a; https://pan.baidu.com/s/1YxCxwoy12G_p8IR5KcPgmQ?pwd1111

CSS 设置网页的背景图片

背景 最近正好在写一个个人博客网站“小石潭记”&#xff0c;需要一张有水&#xff0c;有鱼的图片。正好玩原神遇到了类似场景&#xff0c;于是截图保存&#xff0c;添加到网站里面。以下是效果图&#xff1a; css 写个class&#xff0c;加到整个网页的body上 .bodyBg {ba…

C++ 中的友元(Friend)用法详解

什么是友元&#xff08;Friend&#xff09;&#xff1f;&#x1f46d; 友元 (C) | Microsoft Learn 在C中&#xff0c;友元&#xff08;Friend&#xff09;是一种机制&#xff0c;允许外部函数或类访问某个类的私有&#xff08;private&#xff09;或保护&#xff08;protecte…

IDEA使用Alibaba Cloud Toolkit插件自动化部署jar包

一、下载插件 二、添加服务器主机 三、填写自己服务器配置 四、添加配置 五、配置说明 六、选择maven打包模块 七、maven打包后的jar包位置配一下 八、点击运行发现成功

重学SpringBoot3-Spring WebFlux简介

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-Spring WebFlux简介 1. 什么是 WebFlux&#xff1f;2. WebFlux 与 Spring MVC 的区别3. WebFlux 的用处3.1 非阻塞 I/O 操作3.2 响应式编程模型3.3 更高…

Thread类的介绍

线程是操作系统中的概念&#xff0c;操作系统中的内核实现了线程这种机制&#xff0c;同时&#xff0c;操作系统也提供了一些关于线程的API让程序员来创建和使用线程。 在JAVA中&#xff0c;Thread类就可以被视为是对操作系统中提供一些关于线程的API的的进一步的封装。 多线…

PHP(一)从入门到放弃

参考文献&#xff1a;https://www.php.net/manual/zh/introduction.php PHP 是什么&#xff1f; PHP&#xff08;“PHP: Hypertext Preprocessor”&#xff0c;超文本预处理器的字母缩写&#xff09;是一种被广泛应用的开放源代码的多用途脚本语言&#xff0c;它可嵌入到 HTML…

从新手到高手:Spring AOP的进阶指南

目录 一、AOP简介 1.1 AOP入门案例 1.2 AOP 优点 二、核心概念 2.1 切面(Aspect) 2.2 切点(PointCut) 2.3 通知(Advice) 2.4 织入(Weaving) 三、AOP 原理 3.1 CGLIB 与 JDK动态代理对比 3.2 切面优先级 四、总结 一、AOP简介 AOP(Aspect-Oriented Programming) 面向切面编…

在各大媒体报纸上刊登自己的文章用什么投稿方法发表快?

在职场中,信息宣传是每个单位的重要工作,而每个月的考核投稿任务更是让我深感压力。作为一名普通员工,我常常面临着如何在各大媒体上顺利发表文章的问题。起初,我选择了传统的邮箱投稿方式,然而这条路却让我陷入了无尽的焦虑和挫败之中。 刚开始投稿时,我满怀激情,认真撰写每一…

[论文笔记]HERMES 3 TECHNICAL REPORT

引言 今天带来论文HERMES 3 TECHNICAL REPORT&#xff0c;这篇论文提出了一个强大的工具调用模型&#xff0c;包含了训练方案介绍。同时提出了一个函数调用标准。 为了简单&#xff0c;下文中以翻译的口吻记录&#xff0c;比如替换"作者"为"我们"。 聊天模…

数据库事务

为了保证一致性 1.ACID 事务具有四个基本特性&#xff0c;也就是通常所说的 ACID 特性&#xff0c;即原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#x…

算法: 模拟题目练习

文章目录 模拟替换所有的问号提莫攻击Z 字形变换外观数列数青蛙 总结 模拟 替换所有的问号 按照题目的要求写代码即可~ public String modifyString(String ss) {int n ss.length();if (n 1) {return "a";}char[] s ss.toCharArray();for (int i 0; i < n; i…