视频和视频帧:视频和帧基础知识整理-程序员宅基地

技术标签: 音视频应用  知识普及  前端普及  

写在前面

本文将介绍的是:

  1. 视频的基础知识。包括:视频协议和格式视频流
  2. 视频帧的基础知识。包括:YUV帧格式常见的帧名词(帧率fps、分辨率、码率)“奇怪”的帧名词(1080p和1080i)视频编解码而衍生的帧名词(GOP、I\B\P帧)

修改记录

2019年4月8日首次完成该文章,内容包括:

  1. 视频协议、格式、播放原理等基础内容;
  2. YUV格式、fps、分辨率、GOP和I/B/P帧等视频帧相关的基础知识;
  3. 提到了H264等视频压缩技术。

2019年9月7日进行二次修改,修改内容如下:

  1. 第一章节增加视频流介绍,删除了播放原理介绍;
  2. 第二章增加了YUV采样和存储格式的示意图,场、1080p和1080i的介绍;删除了YUV的颜色值域(Color Range)介绍;
  3. 删除了原第三章的内容,这块会在后续中出专文介绍。

I. 视频的基础知识

相信所有人对视频一定不陌生,平时也一定经常在各大视频网站(如腾讯视频、哔哩哔哩)浏览,甚至偶尔也会把视频缓存到本地,保存成.mkv,.avi文件之类啦。前者是我们常说的『网络流媒体』,后者是『本地视频文件』。提到这里,两个问题来了:

  1. 本地视频文件常见有MP4、MKV、AVI等,这些都是什么?有什么区别?
  2. 在腾讯视频、哔哩哔哩网上看的视频,与本地播放的MP4、MKV、AVI文件,有什么区别?

 

介绍第一个问题之前,必须引入一个名词『视频封装格式』,简称『视频格式』,也称为『容器』。有的说法还要区分是视频文件格式和视频封装格式,本文统一称『视频封装格式』。

视频格式

问题1:本地视频文件常见有MP4、MKV、AVI等,这些都是什么?有什么区别?

首先,MP4、AVI、MKV都是本地视频文件的后缀,在windows系统下,用于提示操作系统应该采用哪个应用程序打开。而在流媒体领域,这些都被称为『视频封装格式』,因为除了音视频流之外,它们还包含了一些辅助信息以及组织视音频的方式。不同格式的视频在不同平台上用户体验不同,很大原因在于对视音频的组织方式带来的差异。笔者以为百度百科上的解释蛮通俗易懂的(维基百科的说法不够直白):

视频格式是视频播放软件为了能够播放视频文件而赋予视频文件的一种识别符号。

简言之,视频格式规定了和播放器的通信协议。

其次,笔者最近准备开始深入研究MP4、AVI、MKV等内部原理,主要是对视音频的组织方式,比如在播放视频的时候,我们可以选择国语、粤语、英语等各种语言,这就意味着这段视音频中包括了多个音频流。【给自己留个坑吧。】

最后,笔者推荐一篇非常棒的博客:视频文件格式知多少,汇总的非常全。

问题1引申:对要做视音频处理的开发们来说,接触MP4、MKV、AVI等各种格式视音频文件时,有什么需要注意的吗?

视音频处理可以延展出很多领域,包括解码、编码、过滤、增强处理等等。笔者目前只在解码领域探索,答案是:对于解码而言,没有区别。其他领域暂不清楚。

『视频封装格式』,是在编码的视音频基础上进行一次“包装”,添加与播放相关的协议数据(这个是笔者的认知,如有表述不准确,欢迎批评指正)。目前主流开源的框架,在“解包装”工作上做的已经非常成熟了,如FFMpeg,提供了用于打开视音频的API,开发人员无需关注具体视频格式,直接可以取出视音频流做处理。

 

接下来,介绍第二个问题,笔者再引入名词『视频协议』,也有说法认为『视频协议』也属于『视频封装格式』。

视频协议

问题2:在腾讯视频、哔哩哔哩网上看的视频,与本地播放的MP4、MKV、AVI文件,有什么区别?

视频协议』是针对网络流媒体而言的,也就是只有在有网络时通过浏览器或者移动端APP才能看到的视频,目前常见的协议有RTSP、RTMP、HLS、HTTP等。笔者短暂地接触过GStreamer开发,在连接到RSTP视频时,发现除了视音频流和metadata之外,还携带了播放的信令。

也有文章会把『视频协议』归入『视频封装格式』。笔者看来,这么分类也有其道理:『视频协议』和『视频封装格式』都同时携带了视音频和metadata,以及协议/格式需要的其他信息。以FFMpeg为例,并不区分视频格式和视频协议;但是GStreamer的话,还时需要指定『视频协议』,但是不区分『视频封装格式』。

 

剥开『视频封装格式』和『视频协议』的外壳,接下来了解视音频流本身,这才是流媒体领域中真正的主角。本文仅介绍视频流。

视频流

就视频流而言,相信大家平时一定经常听到类似“h264码流”、“yuv流”、“编码流”、“解码流”,“原始流”、“裸流”,“压缩后的流”或者“未压缩的流”等等。归纳而言,提到『视频流』的时候,一定只有两种形式:

  • 经过压缩算法压缩的流数据,称为『编码流』,又因为目前压缩/编码算法以H264为主,因此也常常称为『H264码流』。
  • 未经压缩的流数据,是解码后的流数据,称为『原始流』,可以想象视频是由一幅一幅在时间上连续的“图像”组成的,而因为视频内部的“图像”是『YUV』(后文将介绍),因此也常常称为『YUV流』。

总结出现的名称,“h264码流”、“编码流”、“压缩后的流”是压缩/编码后的视频流;而“yuv流”、“解码流”、“未压缩的流”则是未经压缩/编码的视频流。“裸流”是一个具有歧义的词,是上下文内容,既可以是前者,也可以是后者。

因此,如果以后阅读任何流媒体相关的文章时,看到『视频流』都应该搞清楚,这究竟是编码/压缩的,还是没有。在生活中,接触到的视频文件绝大部分都是编码/压缩后的;在网络传输场景中,绝大部分也是编码/压缩后的。只有在视频播放时,观众观赏到的时一帧帧被『转码』为『RGB』的解码后视频流。

编码/压缩在流媒体领域是一项非常重要的技术:从『H264码流』到『YUV流』的过程称为解码,反之称为编码


II. 帧

流媒体领域,『』很重要,『』的基本元素『』同样重要。原因在于:对于视频编码/压缩而言,它的核心是采用尽量小的空间存储一组时间上连续的帧数据;而对于视频解码而言,就是把被编码/压缩后的一组帧数据尽量恢复成原来的样子。能够被100%恢复的编码/压缩算法称为无损压缩,反之称为有损压缩(虽然无损压缩是最理想的,但是在很多实际场景中为了追求高压缩率,比如为了减小网络带宽压力,常常不得不选择有损压缩)。由此可见,『』是视频流媒体领域的核心。接下来,一起来认识什么是『』。

『帧』,可以联想成我们平时看到的一幅幅“图像”,只不过我们平时接触的图片是『RGB』格式的,而视频帧通常是『YUV』格式的。既然提到了『RGB』和『YUV』,那么就来了解下帧的格式『YUV』,引出第一个问题:

问题3:帧为什么采用『YUV』格式?『YUV』是什么?

为此,笔者曾经花了很久去了解颜色空间、电视成像的发展史等,整理结论如下:

  1. 在达到最大压缩率的情况下,能够保证对人眼感知的失真度最小。『YUV』的三通道中,其中"Y"表示明亮度(Lumina nce或Luma),也就是灰阶值;而"U"和"V"表示的则是色度(Chrominance或Chroma)。有一堆科学家研究发现,人眼对UV的敏感度最低,因此可以极大比例地压缩UV两个通道的数值。见视频编解码学习一 yuv格式
  2. 为了向前兼容黑白电视。这个就涉及历史原因了,笔者非常推荐零基础入门音视频开发。历史上在制定视频帧格式时,是有人提出过用RGB的,最终决定用YUV的真正原因其实是这个(见影像使用YUV格式,為什麼不用RGB呢?

接下来解释『YUV』是什么,笔者以为,『YUV』是一种广义的概念,在视频领域,当提到『YUV』的时候,往往是以下几个意思:

  1. 颜色空间

“Y”表示明亮度(Luminance、Luma),“U”和“V”则是色度(Chrominance)、浓度(Chroma)。这里表示的是色彩空间的基,即类似XYZ坐标系的一种色标表示基准,也就是说每一种颜色可以通过三维向量<y^i^,u^i^,v^i^>来表示。与其类似的还有RGB颜色空间、HSV颜色空间等。下图来自How does the YUV color coding work?

​图1. YUV坐标轴示意图

随着通信行业的发展,实际应用之多之复杂,导致『YUV』衍生出了一个大家族。接触视频领域的一定听说过YCbCr,甚至还有YPbPrYIQ等。它们有的已经被时代淘汰,有的现在还在使用。之所以出现『YUV』大家族,完全是因为实际电路系统之间的差异,导致要从『YUV』转到『RGB』空间,实际对应的转化系数是有些许差异的,于是各个部门开始制定各种规范,才有了我们现在看到的『YUV』大家族。

YCbCr是专门针对数字电路而诞生的;YPbPr则是模拟电路。但是,现在是数字时代,所以为了模拟电路而生的YPbPr已经逐渐被淘汰了,而YCbCr还一直发挥着作用。因此现在,YCbCr有时也会被简单地称为/认为『YUV』。

2. 采样率

读者可能听说过“YUV444”,“YUV422”,“YUV420”,到这里可能会纳闷:“YUV不是颜色空间吗?为什么后面还会跟着一串数字?” 因为当你看到YUV后面跟着一串数字的时候,『YUV』已经不再是颜色空间的基的含义了,而是意味着在原始『YUV流』上的采样。
在以前流媒体刚刚兴起时,还没有什么4G/5G,当时为了减小网络传输的带宽的压力,可谓做了种种努力。除了编码/压缩之外,YUV采样率也是一种。
444422420是三种『YUV』(在数字电路中指代YCbCr)的采样,三位数分别代表Y\U\V(数字电路中为Y\Cb\Cr,本段后同)通道的抽样比。所以可以理解,444是全采样;而422是对Y进行全采样,对U\V分别进行1/2均匀采样。有趣的问题来了,420难道是完全丢弃了V通道/分量数据嘛?答案是否定的。
首先,必须要搞明白一个问题,一帧图像是由一个个像素组成的矩形,譬如4x4的尺寸的图像,就是由16个像素点组成的。在平时接触的『RGB』图像中,每个像素必然至少由R\G\B这三个通道组成的(有的图像还有\alpha分量),每个分量的取值一般都是[0,255],也就是[2^0,2^8],因此经常说一个像素占用3字节(如果还有其他分量,比如RGBA,就另当别论)。『YUV』图像同理,它的每个像素是由Y\U\V组成的。
接下来,从整张图像宏观考虑采样问题。还是以4X4的图像为例,444的如下图2-1,这个是形象化成图像的样子,实际在机器内存储并不是这样,具体可以参见博客《图像原始格式一探究竟》422420分别如下图2-2和2-3。

​图2-1. YUV444采样示意图

​图2-1对应YUV444采样,即全采样,图示中可以看出每个像素中的Y\U\V通道都保留下来了,一般来说YUV444太大了,因此很少使用。

​图2-2. YUV422采样示意图

图2-2对应YUV422采样,这种采样方式是:每个扫描线或者说每行相邻2个像素,只取1个像素的U\V分量。此外,可以计算出来,每个像素占用的大小为原来的2/3,因此说YUV422YUV444的2/3大小。

这个时候就有一个问题,在『YUV』转『RGB』时,被抽走了U\V分量的像素要怎么办呢?做法很简单,就是相邻2个像素的Y分量公用保留着的U\V分量。

​图2-2. YUV420采样示意图

图2-3对应YUV420采样,这种采样方式是:隔行进行YUV422每行采样的办法,即相邻2个像素只取1个像素的U\V分量;下一行丢弃所有的U\V分量。此外,可以计算出来,每个像素占用的大小为原来的1/2,因此说YUV420YUV444的1/2大小。恢复U\V分量的办法同YUV422,只不过这里是2X2的矩阵共享保留着的U\V分量。

这种设计办法真的很巧妙!前文提到的"人眼对UV的敏感度最低,因此可以极大比例地压缩UV两个通道的数值",且对于图像而言,相邻的区域像素的色彩、饱和度一般非常接近,因此这种以2X2矩阵为基本单位,只保留1组U\V分量合情合理。

3. 编码/存储格式

大家肯定还听说过YV12YU12NV12NV21吧,看到这里是不是又纳闷:“后面的数字怎么变成2个了?而且前面的英文字母还变了?”
以上统称为『视频的存储格式』,也就是说,计算机是如何存储一帧视频的。
首先,『视频的存储格式』总分为两大类:『打包格式(packed)』和『平面格式(planar)』。前者又被称作『紧凑格式(packed)』。其实除此之外还有『半平面模式(Semi-Planar)』,估计是使用的比较少,因此在很多文章中常被忽略。
笔者很感兴趣,为什么会出现『打包格式』和『平面格式』两大派系,网上搜了很多资料也没找到原因,博客【音视频基础】:I420、YV12、NV12、NV21等常见的YUV420存储格式提到了需要约定存储格式,但也没提到为什么会分成这两种。要么就是派系之争,类似贝叶斯学派和频率学派;要么就是实际应用中逐渐衍生出这两大格式。时至今日,这两个格式还在被使用,因此对于多媒体开发者们都有必要了解。
打包格式』是把Y\U\V分量交叉存储,『平面格式』则是把Y\U\V严格分开存储,『半平面模式』介于两者之间,Y分量分开存储,U\V交叉存储。
以下图为例说明『打包格式』、『平面格式』和『半平面模式』应该是非常清楚的,图摘自博客YUV格式初探

​图3-1. YUV420P存储示意图

​图3-2. YUV420SP存储示意图

​图3-3. YUV420Packet存储示意图

但是关于上图的『打包格式』,笔者是是有一点疑惑的,大多数的说法是”Y\U\V通道交叉存储,相邻的像素尽量打包在一起“,图3-3中U1后面跟着的是U2而不是V1,而且Y\U\V的排列方式似乎也不完全是交叉?笔者尝试在网上搜索『打包格式』更多的例子,没有找到特别好的资料,【这里给自己挖一个坑吧】。

 

接下来,我们继续了解一些帧相关的概念。

常见的帧名词

  1. 帧率(FPS)
    『帧率』,FPS,全称Frames Per Second。指每秒传输的帧数,或者每秒显示的帧数,一般来说,『帧率』影响画面流畅度,且成正比:帧率越大,画面越流畅;帧率越小,画面越有跳动感。一个较权威的说法:
    当视频帧率不低于24fps时,人眼才会觉得视频时连贯的,称为“视觉暂留”现象。
    因此,才有说法:尽管『帧率』越高越流畅,但在很多实际应用场景中24fps就可以了。
  2. 分辨率(Resolution)
    『分辨率』,也常被俗称为『图像的尺寸』或者『图像的大小』。指一帧图像包含的像素的多少,常见有1280x720(720P),1920X1080(1080P)等规格。『分辨率』影响图像大小,且与之成正比:『分辨率』越高,图像越大;反之,图像越小。
  3. 码率(BPS)
    『码率』,BPS,全称Bits Per Second。指每秒传送的数据位数,常见单位KBPS(千位每秒)和MBPS(兆位每秒)。笔者认为这个概念真正要理解起来还是需要好好说明的,网上一说:“『码率』与体积成正比:码率越大,体积越大;码率越小,体积越小”;另一说:“『码率』越大,说明单位时间内取样率越大,数据流精度就越高,这样表现出来的的效果就是:视频画面更清晰画质更高”;还有说法是:”『码率』就是『失真度』“。但是笔者有一段时间就是不理解,每秒传输的数据越大,为什么必然就对应画面更清晰?还有体积怎么理解呢?且看下文”三者之间的关系“。

『帧率』『分辨率』和『码率』三者之间的关系
最理想的情况是画面越清晰、越流畅是最好的。但在实际应用中,还需要结合硬件的处理能力、实际带宽条件选择。高『帧率』高『分辨率』,也就意味着高『码率』,也意味着需要高带宽和强大的硬件能力进行编解码和图像处理。所以『帧率』和『分辨率』应该视情况而定。
要说三者之间的关系,其实就是对于『码率』的理解。在码率(BPS)概念中提到了几段摘自网上的说法,说的都太模糊了,笔者直到阅读了文章Video Bitrate Vs. Frame Rate,才真的理解了『码率』。
首先,这些说法都没有交代一个前提:『帧率』、『分辨率』和『压缩率』都会影响『码率』。Video Bitrate Vs. Frame Rate](https://www.techwalla.com/articles/video-bitrate-vs-frame-rate)文章在一开始就明确指出:

Bitrate serves as a more general indicator of quality, with higher resolutions, higher frame rates and lower compression all leading to an increased bitrate.
『码率』是更广泛的(视频)质量指标:更高的『分辨率』,更高的『帧率』和更低的『压缩率』,都会导致『码率』增加。

文章后面又特别强调『分辨率』和『压缩率』对『码率』的影响:高分辨率意味着图片可以包括更多的细节,低压缩率意味着图片压缩损失越少,即失真越少,越清晰。那为什么不特地讨论『帧率』呢?笔者认为原因有二:一个是『帧率』的影响非常直观,每秒帧数增加必然导致数据量增加;另一个是实际应用场景中『帧率』是相对固定的,我们观看的一般视频都在25-30fps之间,现在一些高帧视频是60fps,可见视频『帧率』在实际场景中被讨论的很少。

 

奇怪的帧名词:1080p和1080i、场

笔者仅仅出于觉得有趣才放上来的,1080p和1080i、场都是相对比较“老”的概念了,在还是CRT电视的时代,显示器显示画面都是靠电子枪一行一行扫描画面才能产生一副完整的图像,这就被称作『』,后来这个名词也不常使用了,被取代它的是『』。【科技在进步,过时的概念、应用都会被新兴的替换,所以真的要不断学习紧跟时代啊!】

1080p1080i也是『』同一时期的概念:

  • ${数字}i的字母”i“表示Interlace,代表隔行扫描,比如奇数『』只扫描奇数行,后一『』即偶数『』只扫描偶数行。这在过去是非常有用的,当时网络条件差,带宽受限,隔行扫描可以很大程度上减少传输的数据,又不至于影响观众观看体验。
  • ${数字}p的字母”p“表示Progressive,即逐行扫描,也就是一『』把全部画面扫描完整。这是后来才提出的概念,这也代表时代进步,带宽条件上来了。

既然都是老概念了,那为什么还要再提呢?借用文章1080P和1080i是什么意思?的一段来说:

进入液晶时代的如今,隔行和逐行其实已经没有太大的意义了,现在的电视或者是显示器都属于固定像素设备,像素点同时发光,并不需要扫描,但是硬要说的话可以认为现在的显示设备都是逐行扫描的,但也并不是说1080P和1080i等就可以淘汰了,毕竟还涉及到摄像机的格式,不过普通观众也不会关心是用什么摄像机拍的,只关心呈现出来的样貌就好了。

 

视频『帧』和编解码密切相关,因此还有不少『帧』的概念是和视频编解码相关的。

视频编解码而衍生的帧名词

  1. I帧、P帧、B帧和IDR帧
    但凡接触过一点视频编解码的读者,一定见过I\P\B帧,至于IDR可能见的少一些。下面,简单解释每种类型:
  • I帧,英文全写Intra Picture,又称帧内编码帧,俗称关键帧。一般来说I帧不需要依赖前后帧信息,可独立进行解码。有数据表明,仅I帧的压缩率,可以达到7,这里其实可以把I帧的压缩等同于单独压缩一幅图片。至于说I帧的压缩只压缩了空间上的冗余信息,放在后续编码相关的系列文章中会详述。【这里再挖一个坑,免得自己忘记了】
  • P帧,英文全写predictive-frame,又称前向预测编码帧,也有帧间预测编码帧。顾名思义,P帧需要依赖前面的I帧或者P帧才能进行编解码,因为一般来说,P帧存储的是当前帧画面与前一帧(前一帧可能是I帧也可能是P帧)的差别,较专业的说法是压缩了时间冗余信息,或者说提取了运动特性P帧的压缩率约在20左右,几乎所有的H264编码流都带有大量的P帧
  • B帧,英文全写bi-directional interpolatedprediction frame,又称 双向预测内插编码帧,简称双向预测编码帧B帧非常特殊,它存储的是本帧与前后帧的差别,因此带有B帧的视频在解码时的逻辑会更复杂些,CPU开销会更大。因此,不是所有的视频都带有B帧,笔者目前还没有接触过带B帧的视频。【找到带B帧视频一定要珍藏起来好好研究!】不过,B帧的压缩率能够达到50甚至更高,在压缩率指标上还是很客观的。
  • IDR帧,英文全写Instantaneous Decoding Refresh,翻译过来是即时解码刷新。听上去,这类帧并不是名词概念,倒像是个动词?IDR帧是一种特殊的I帧,它是为了服务于编解码而提出的概念,IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始,重新算一个新的序列开始编码(摘自博客H264中I帧和IDR帧的区别)。

I/P/B帧,并不是依据视频帧数据内部的元素的不同来区分的,从解码后的帧本身而言,它们没有任何区别。仅仅是在编码时,对帧处理的方式不同而已。

  1. GOP
    英文全称Group Of Pictures,一般来说,指的就是两个I帧之间的间隔,严格来说,是两个IDR帧之间的间隔。笔者对GOP研究的不多,对于网上的说法:“GOP在一定程度上会影响视频画面质量 - 在码率相同的情况下,GOP越大,意味着P\B帧越多,也就更容易获取较好的图像质量”这个说法存疑。【这里留个坑待填】
  2. PTS、DTS
    笔者是在对视频文件硬做解码的时候,发现实际解码输出的fps是硬解的能力上限,比如一个24fps的视频文件,在用硬件解码时,能够达到100+,当时接到一个需求是:“需要控制视频文件的解码率,让它和文件的fps保持一致”。后来查阅了大量的资料,进而了解了DTSPTS的概念:
  • DTS,英文全称Decoding Time Stamp,即解码时间戳,这个时间戳的意义在于告诉解码器该在什么时候解码这一帧的数据。
  • PTS,英文全称Presentation Time Stamp,即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。

这个概念在做视音频同步的时候特别重要,尤其是PTS,目前常见的视音频同步的三种策略“同步到音频的PTS”、“同步到视频的PTS”和“同步到系统/外部时钟”,都是基于PTS完成的。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Qianliwind/article/details/116492700

智能推荐

已知num为无符号十进制整数,请写一非递归算法,该算法输出num对应的r进制的各位数字。要求算法中用到的栈采用线性链表存储结构(1<r<10)。-程序员宅基地

文章浏览阅读74次。思路:num%r得到末位r进制数,num/r得到num去掉末位r进制数后的数字。得到的末位r进制数采用头插法插入链表中,更新num的值,循环计算,直到num为0,最后输出链表。//重置,s指针与头指针指向同一处。//更新num的值,至num为0退出循环。//末位r进制数存入s数据域中。//头插法插入链表中(无头结点)//定义头指针为空,s指针。= NULL) //s不为空,输出链表,栈先入后出。

开始报名!CW32开发者扶持计划正式进行,将助力中国的大学教育及人才培养_cw32开发者扶持计划申请-程序员宅基地

文章浏览阅读176次。武汉芯源半导体积极参与推动中国的大学教育改革以及注重电子行业的人才培养,建立以企业为主体、市场为导向、产学研深度融合的技术创新体系。2023年3月,武汉芯源半导体开发者扶持计划正式开始进行,以打造更为丰富的CW32生态社区。_cw32开发者扶持计划申请

希捷硬盘开机不识别,进入系统后自动扫描硬件以识别显示_st2000dm001不认盘-程序员宅基地

文章浏览阅读5.7k次。2014年底买的一块2TB希捷机械硬盘ST2000DM001-1ER164,用了两年更换了主板、CPU等,后来出现开机不识别的情况,具体表现为:关机后开机,找不到硬盘,就进入BIOS了,只要在BIOS状态下待机半分钟左右再重启,硬盘就会出现。进入系统后,重启(这个过程中主板对硬盘始终处于供电状态),也不会出现不识别硬盘的现象。就好像是硬盘或主板上某个电容坏了一样,刚开始给硬盘通电的N秒钟内电容未能..._st2000dm001不认盘

ADO.NET包含主要对象以及其作用-程序员宅基地

文章浏览阅读1.5k次。ADO.NET的数据源不单单是DB,也可以是XML、ExcelADO.NET连接数据源有两种交互模式:连接模式和断开模式两个对应的组件:数据提供程序(数据提供者)&DataSetSqlConnectionStringBuilder——连接字符串Connection对象用于开启程序和数据库之间的连接public SqlConnection c..._列举ado.net在操作数据库时,常用的对象及作用

Android 自定义对话框不能铺满全屏_android dialog宽度不铺满-程序员宅基地

文章浏览阅读113次。【代码】Android 自定义对话框不能铺满全屏。_android dialog宽度不铺满

Redis的主从集群与哨兵模式_redis的主从和哨兵集群-程序员宅基地

文章浏览阅读331次。Redis的主从集群与哨兵模式Redis的主从模式全量同步增量同步Redis主从同步策略流程redis主从部署环境哨兵模式原理哨兵模式概述哨兵模式的作用哨兵模式项目部署Redis的主从模式1、Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。2、为了分担读压力,Redis支持主从复制,保证主数据库的数据内容和从数据库的内容完全一致。3、Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。全量同步Redis全量复制一般发_redis的主从和哨兵集群

随便推点

mysql utf-8的作用_为什么不建议在MySQL中使用UTF-8-程序员宅基地

文章浏览阅读116次。作者:brightwang原文:https://www.jianshu.com/p/ab9aa8d4df7d最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误:Incorrect string value: ‘😃 我用的是UTF-8编码的客户端,服务器也是UTF-8编码的,数据库也是,就连要保存的这个字符串“????..._mysql utf8的作用

MATLAB中对多张图片进行对比画图操作(包括RGB直方图、高斯+USM锐化后的图、HSV空间分量图及均衡化后的图)_matlab图像比较-程序员宅基地

文章浏览阅读278次。毕业这么久了,最近闲来准备把毕设过程中的代码整理公开一下,所有代码其实都是网上找的,但都是经过调试能跑通的,希望对需要的人有用。PS:里边很多注释不讲什么意思了,能看懂的自然能看懂。_matlab图像比较

16.libgdx根据配置文件生成布局(未完)-程序员宅基地

文章浏览阅读73次。思路:  screen分为普通和复杂两种,普通的功能大部分是页面跳转以及简单的crud数据,复杂的单独弄出来  跳转普通的screen,直接根据配置文件调整设置<layouts> <loyout screenId="0" bg="bg_start" name="start" defaultWinId="" bgm="" remark=""> ..._libgdx ui 布局

playwright-python 处理Text input、Checkboxs 和 radio buttons(三)_playwright checkbox-程序员宅基地

文章浏览阅读3k次,点赞2次,收藏13次。playwright-python 处理Text input和Checkboxs 和 radio buttonsText input输入框输入元素,直接用fill方法即可,支持 ,,[contenteditable] 和<label>这些标签,如下代码:page.fill('#name', 'Peter');# 日期输入page.fill('#date', '2020-02-02')# 时间输入page.fill('#time', '13-15')# 本地日期时间输入p_playwright checkbox

windows10使用Cygwin64安装PHP Swoole扩展_win10 php 安装swoole-程序员宅基地

文章浏览阅读596次,点赞5次,收藏6次。这是我看到最最详细的安装说明文章了,必须要给赞!学习了,也配置了,成功的一批!真不知道还有什么可补充的了,在此做个推广,喜欢的小伙伴,走起!_win10 php 安装swoole

angular2里引入flexible.js(rem的布局)_angular 使用rem-程序员宅基地

文章浏览阅读1k次。今天想实现页面的自适应,本来用的是栅格,但效果不理想,就想起了rem布局。以前使用rem布局,都是在原生html里,还没在框架里使用过,百度没百度出来,就自己琢磨,不知道方法规范不规范,反正成功了,操作如下:1、下载flexible.js2、引入到angular项目里3、根据自己的需要修改细节3.1、在flexible.js里修改每份的像素,3.2、引入cssrem插件,在设置里设..._angular 使用rem

推荐文章

热门文章

相关标签