解决方案:视频的基本参数及H264编解码相关概念

优采云 发布时间: 2022-11-12 13:49

  解决方案:视频的基本参数及H264编解码相关概念

  DTS时间戳决定SCR时间等于DTS时间时*敏*感*词*何时解码,与PTS时间戳类似。通常,DTS/PTS 时间戳表示比音频-视频数据包中的 SCR 晚的时间。例如,如果一个视频包的SCR为100ms(意味着播放100ms后从磁盘读取包),那么DTS/PTS值很少是200/280ms,也就是说当SCR达到200ms时,视频is 数据应该在 80ms 后解码并显示(视频数据保存在缓冲区中,直到解码开始)。当与视频流相关的复用率设置得太高时,通常会发生下溢。如果mux rate是1000000bits/sec(意味着*敏*感*词*必须以1000000bits/sec读取文件),但视频速率是2000000bits/sec(意味着视频数据需要以2000000bits/sec显示),从磁盘读取 获取视频数据的速度不够快,无法在 1 秒内读取足够的视频数据。在这种情况下,DTS/PTS 时间戳表示视频在从硬盘读取之前已被解码或显示(DTS/PTS 时间戳将早于收录它们的数据包中的 SCR 时间)。

  现在依靠*敏*感*词*,这基本上不是问题(尽管 MPEG 文件不完全符合 MPEG 标准,因为它们不应该有下溢)。一些编*敏*感*词*(许多著名的基于 PC 的播放器)尽可能快地读取文件以显示视频,如果可能的话忽略 SCR。

  请注意,在您提供的列表中,平均视频流传输速率约为 3Mbps(3000000 位/秒),但峰值为 14Mbps(非常大,DVD 限制为 9.8Mbps)。这意味着需要将复用速率调整得足够大以处理 14Mbps 部分,而 bbMPEG 计算的复用速率有时太低而不会导致下溢。您是否打算使视频流率如此之高?这超出了 DVD 的规格,并且很可能不会在大多数独立设备中播放。如果您不这样计划,我会将 mquant 值从 1 增加,并在视频设置中将最大比特率设置为 9Mbps,以保持比特率更小。

  如果你真的想要视频比特率那么高,你需要增加复用率。从提供的列表中可以得出结论,bbMPEG 使用 06800bits/sec 或 1838350bytes/sec 的复用速率(总数据速率:1838350bytes/sec (06800bits/sec) 行)。您在 force mux rate 字段中设置的值应该以字节/秒为单位,并且可以被 50 整除。所以我将从 36767 (1838350/50) 开始并继续增长,直到不再有下溢错误;

  比特率(比特率) 关于比特率

  由于保存完整逐帧图片的原创视频文件太大,需要通过视频压缩算法对视频中的图片进行压缩,以减小视频文件的大小。视频的失真会越严重,因为视频中原创图像的数据信息在压缩过程中不可避免地会丢失。在了解这一点的前提下,我举个例子,将一个分辨率为1080P的原创视频(未压缩)压缩成两个分别为4GB和1GB的视频文件。因为1GB的视频压缩比更高,很明显看1GB的视频不如4GB的视频清晰(虽然它们的分辨率都是1080P)。

  比特率,也称为比特率,是指在压缩视频时为视频指定一个参数,以告诉压缩软件预期压缩视频的大小。比特率的英文名称是bps(bit per second),它是衡量一个视频大小的平均每秒比特数。

  计算视频的比特率

  我们可以根据视频的长度和大小来推断视频的比特率。下面是一个具体的例子。

  一个 1080P 的视频长 100 分钟,大小为 1GB,视频的比特率是多少?

  100min = 100*60s = 6000s;

1G = 1024M = 1024*1024KB = 1024*1024*1024Bit = 1024*1024*1024*8bit = 8589934592bit;

比特率 = 8589934592/6000s = 1431655b/s = 1.4Mbit/s;

复制代码

  那么这个视频的码率大约是1.4Mbit/s。这个比特率在在线视频中已经很高了。通常主流视频平台的最高码率在1Mbit左右,比如直播网站斗鱼。高清选项播放的实际视频码率为 900Kbit/s (0.9Mbit)。

  我们可以得出结论,对于相同时长的视频,码率越大,视频尺寸越大,视频质量越清晰(不管各种压缩算法的优劣),这是最直观的感受. 比特率对于视频来说非常重要。

  音视频同步

  上面提到的概念与视频帧、DTS 和 PTS 有关。我们都知道,在一个媒体流中,除了视频之外,一般还包括音频。音频播放也有DTS和PTS的概念,但是音频没有类似视频的B帧,不需要双向预测,所以音频帧的DTS和PTS顺序是一致的。

  将音视频混合在一起播放,呈现出我们经常看到的广义视频。当音视频一起播放时,我们一般需要面对一个问题:如何同步,避免出现画面不声音的情况。

  要实现音视频同步,一般需要选择一个参考时钟。参考时钟上的时间线性增加。在对音频和视频流进行编码时,每帧数据都会根据参考时钟上的时间打上时间戳。播放时,读取数据帧上的时间戳,参考当前参考时钟上的时间安排播放。这里提到的时间戳就是我们前面提到的PTS。在实践中,我们可以选择:同步视频到音频,同步音频到视频,同步音频和视频到外部时钟。

  视频编*敏*感*词*概述软编码和硬编码的概念

  软编码:使用 CPU 进行编码。

  硬编码:不使用CPU进行编码,使用显卡GPU、专用DSP、FPGA、ASIC芯片等硬件进行编码。

  软编码和硬编码的比较

  软编码:实现直接简单,参数调整方便,升级容易,但CPU负载较重,性能比硬编码低,一般在低码率下质量比硬编码好。

  硬编码:性能高,一般在低码率下质量低于硬编码,但部分产品在GPU硬件平台上移植了优秀的软编码算法(如X264),质量与软编码基本相同。

  ios系统中的硬编码

  在 iOS 8.0 系统之前,苹果没有开放系统的硬件编解码功能,但 Mac OS 系统一直都有一个叫做 Video ToolBox 的框架来处理硬件编解码。最后,在 iOS 8.0 之后,Apple 将该框架引入了 iOS。系统。

  H264编码原理与I帧B帧P帧H264编码原理

  H264是新一代的编码标准。它以高压缩和高质量着称,支持各种网络的流媒体传输。在编码方面,我理解他的理论依据是:参考图像在一段时间内的统计结果,在相邻的几张图像中,通常不同的像素点只有10%以内,亮度差异确实变化不超过2%,色度差变化仅在1%以内。因此,对于变化不大的图像,我们可以先编码一个完整的图像帧A,后面的B帧不编码所有图像,而只写与A帧的差值,这样B帧的大小就只有整个框架的大小。1/10 或更少!如果B帧之后的C帧变化不大,我们可以通过参考B继续对C帧进行编码,依此类推。这个图像称为序列(序列是具有相同特征的一段数据)。当一个图像与前一个图像相比变化很大并且不能参考前一帧生成时,那么我们结束前一个序列并开始下一个序列。为这幅图像生成一个序列,即完整的帧A1,后面的图像参照A1生成,只写与A1的差异内容。

  H264 协议中定义了三种类型的帧。完整编码的帧称为I帧,参照前一帧产生的仅收录差异部分编码的帧称为P帧,还有参照前一帧编码的另一帧。调用 B 帧。

  H264使用的核心算法是帧内压缩和帧间压缩。帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。

  序列说明

  在 H264 中,图像以序列为单位进行组织。序列是由图像编码的数据流,从一个 I 帧开始,到下一个 I 帧结束。

  序列的第一个图像称为 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。H.264 引入了用于解码重新同步的 IDR 图像。当*敏*感*词*对IDR图像进行解码时,当参考帧队列即将被清空时,将所有解码数据输出或丢弃,重新搜索参数集开始新的序列。这样,如果前面的序列出现重大错误,这里就有机会重新同步。IDR图片之后的图片永远不会使用IDR之前图片的数据进行解码。

  

  序列是通过对内容差别不大的图像进行编码而生成的数据流。当运动变化相对较小时,序列可能会很长。由于运动变化很小,说明图像的内容变化很小,所以可以编译一个I帧,然后制作P帧和B帧。当运动变化较多时,一个序列可能比较短,例如收录一个I帧和三个或四个P帧。

  三种框架I框架介绍

  为了更好地理解I帧的概念,我列出两个解释:

  工字架特点:

  P 帧

  为了更好地理解P-frames的概念,我还列出了两个解释:

  **P-frame预测与重构:**P-frame以I-frame为参考帧,在I-frame中求P-frame“某一点”的预测值和运动向量,取预测差和运动矢量一起发送。在接收端,根据运动向量,从I帧中找到P帧的“某点”的预测值并加差,得到P帧的“某点”样本值,这样就可以得到完整的P帧。

  P帧特点:

  B 帧

  为了更好的理解P-frames的概念,我还是列出两个解释:

  **B帧的预测与重构:**B帧之前的I或P帧和B帧之后的P帧为参考帧,“找出”B帧“一个点”的预测值和两个运动向量,取预测差异和运动矢量传输。接收端根据运动矢量“找到(计算)”两个参考帧中的预测值,并与差值相加得到B帧的“点”样本值,从而得到完整的B帧。

  B帧的特点:

  I、B、P的每一帧都是根据压缩算法的需要人为定义的,都是真实的物理帧。一般来说,I帧的压缩比是7(和JPG差别很大),P帧是20,B帧可以达到50。可见使用B帧可以节省很多空间,节省的空间可以用于节省更多的I帧,在相同码率下可以提供更好的画质。

  压缩算法说明

  h264的压缩方式:

  分组:将几帧图像分成一个组(GOP,即一个序列)。为了防止运动变化,帧数不宜过多。定义帧:将每组中的每一帧图像定义为三种类型,即I帧、B帧和P帧;预测帧:以I帧为基帧,用I帧预测P帧,再用I帧和P帧预测B帧;数据传输:最后存储和传输I帧数据和预测的差异信息。

  帧内压缩也称为空间压缩。压缩一帧图像时,只考虑这一帧的数据,不考虑相邻帧之间的冗余信息,实际上类似于静态图像压缩。帧内通常使用有损压缩算法,因为帧内压缩是对完整的图像进行编码,因此可以独立解码和显示。帧内压缩通常不能达到很高的压缩率,并且非常接近于编码 jpeg。

  帧间压缩的原理是:相邻几帧的数据有很大的相关性,或者说是连续两帧的信息变化不大的特点。也就是说,连续视频在相邻帧之间具有冗余信息。根据该特征,压缩相邻帧之间的冗余可以进一步增加压缩量并降低压缩率。帧间压缩也称为时间压缩,通过在时间轴上比较不同帧之间的数据来压缩数据。帧间压缩通常是无损的。帧差分算法是一种典型的时间压缩方法。它比较本帧与相邻帧的差异,只记录本帧与其相邻帧的差异,可以大大减少数据量。.

  顺便说一下,有损(Lossy)压缩和无损(Lossy less)压缩。无损压缩是指压缩前和解压后的数据完全相同。大多数无损压缩使用 RLE 游程编码算法。有损压缩是指解压后的数据与压缩前的数据不一样。在压缩过程中,会丢失一些对人眼和耳朵不敏感的图像或音频信息,丢失的信息无法恢复。几乎所有的高压缩算法都使用有损压缩来达到低数据速率的目标。丢失的数据率与压缩率有关。压缩比越小,丢失的数据越多,解压效果通常越差。此外,

  三帧不一样,DTS和PTS不一样

  DTS主要用于视频解码,用于解码阶段。PTS主要用于视频同步和输出。它用于显示。在没有B帧的情况下,DTS和PTS的输出顺序是一样的。

  例子:

  下面是一个 GOP 为 15 的示例,解码后的参考帧及其解码顺序在其中:

  如上图: I帧的解码不依赖于任何其他帧。p帧的解码依赖于之前的I帧或P帧。B 帧的解码取决于最近的前一个 I 帧或 P 帧。帧和下一个最近的 P 帧。

  IOS系统H264视频硬件编解码说明

  我们知道,在IOS8系统之后,苹果将Mac OS中硬件编解码的VideoToolbox框架引入了IOS系统。

  根据苹果WWDC2014 513“直接访问媒体编解码”的描述,苹果之前提供的AVFoundation框架也是使用硬件对视频进行硬编码解码,但是编码后直接写入文件,之后直接显示解码。Video Toolbox框架可以获得编码后的帧结构和解码后的原创图像,因此在做一些视频图像处理方*敏*感*词*有更大的灵活性。

  视频工具箱简介

  在iOS中,有5个视频相关的接口,从顶层开始:AVKit - AVFoundation - VideoToolbox - Core Media - Core Video

  其中VideoToolbox可以将视频解压到CVPixelBuffer,也可以压缩到cmsampleBuffer。

  如果需要使用硬编码,在这5个接口中,需要用到AVKit、AVFoundation和VideoToolbox。这里我只介绍VideoToolbox。

  VideoToolbox 中的对象硬解码

  经过如图所示的典型应用,来说明如何使用硬件解码接口。应用场景是从网络传输H264编码的视频流,最后显示在手机屏幕上。

  要完成以上功能,需要经过以下步骤:

  

  将 H.264 流转换为 cmsampleBuffer 显示 cmsampleBuffer 将 H.264 流转换为 cmsampleBuffer

  我们知道 cmsampleBuffer = CMTime + FormatDesc + CMBlockBuffer 。需要从H264码流中提取以上三个信息。最后组合成cmsampleBuffer,提供给硬解码接口进行解码。

  在H.264的语法中,有一个最基本的层叫做网络抽象层,简称NAL。H.264流数据由一系列NAL单元(NAL Unit,简称NAUL)组成。

  H264的码流由NALU单元组成,一个NALU可能收录:

  NALU 标头

  对于流数据,NAUL header 通常以 0x00 00 01 或 0x00 00 00 01 开头(两者都有可能,下面以 0x00 00 01 为例)。0x00 00 01 称为起始码。

  总结以上知识,我们知道H264码流是由NALU单元组成的,其中收录视频图像数据和H264参数信息。视频图像数据为CMBlockBuffer,可以将H264的参数信息组合成FormatDesc。具体的,参数信息包括SPS(Sequence Parameter Set)和PPS(Picture Parameter Set)。下图是一个H.264码流的结构:

  1)提取sps和pps生成FormatDesc

  2)提取视频图像数据生成CMBlockBuffer

  3)根据需要生成CMTime信息。(实际测试中,添加时间信息后,出现了不稳定的图像,但不添加时间信息就没有了,需要进一步研究,这里建议不要添加时间信息)

  根据上述获取CMVideoFormatDescriptionRef、CMBlockBufferRef和可选的时间信息,使用cmsampleBufferCreate接口获取要解码的原创数据为cmsampleBuffer数据。下图为H264数据转换*敏*感*词*。

  显示 cmsampleBuffer

  有两种显示方式:

  1)通过系统提供的AVSampleBufferDisplayLayer解码显示

  用法与其他CALayer类似。该层内置硬件解码功能,直接将原创cmsampleBuffer的解码图像显示在屏幕上,非常简单方便。

  2) 用 OPenGL 本身渲染

  通过VTDecompression接口,将cmsampleBuffer解码成图像,并在UIImageView或OpenGL上显示图像。

  硬编码

  硬编码的使用也通过一个典型的应用场景来描述。首先通过*敏*感*词*获取采集图像,然后对采集接收到的图像进行硬编码,最后将编码后的数据组合成H264码流通过网络传播.

  以下是具体步骤的说明:

  相机采集数据

  Camera采集,iOS系统为采集相机图像数据提供AVCaptureSession。设置会话的 采集 分辨率。然后设置输入和输出。设置输出时,需要设置委托和输出队列。在委托方法中,处理 采集 好的图像。

  图像输出的格式是未编码的 cmsampleBuffer 形式。

  使用 VTCompressionSession 硬编码

  1)初始化VTCompressionSession

  VTCompressionSession初始化时,通常需要给出width宽度、高度长度、编码器类型kCMVideoCodecType_H264等。然后通过调用VTSessionSetProperty接口设置帧率等属性,demo中提供了一些设置参考。测试时发现几乎没有效果,可能需要进一步调试。最后,需要设置一个回调函数。视频图像编码成功后调用该回调。一切准备就绪后,使用 VTCompressionSessionCreate 创建会话

  2)提取相机采集的原创图像数据到VTCompressionSession进行硬编码

  相机 采集 之后的图像是未编码的 cmsampleBuffer 形式。给定的接口函数 cmsampleBufferGetImageBuffer 用于从中提取 CVPixelBufferRef,硬编码接口 VTCompressionSessionEncodeFrame 用于对帧进行硬编码。,编码成功后,会自动调用会话初始化时设置的回调函数。

  3)使用回调函数将编码成功的cmsampleBuffer转化为H264流,并通过网络传播

  基本上是硬解码的逆过程。解析出参数集SPS和PPS,加上起始代码,组装成NALU。提取视频数据,将长度码转换为起始码,组长为NALU。将 NALU 发送出去。

  下一篇文章我们将介绍H264硬编码和软编码的实现。

  参考

  教程:帝国cms在首页调用指定几个栏目的所有文章和用js实现分页的方法

  先说明一下我的问题:我的博客有两个主题,技术和生活,四栏是技术,四栏是生活。我想在首页调用所有文章的技术类,实现分页。

  首先,让我们调用指定列的所有文章。我不需要 php。我在群友的提示下重新阅读了智能标签。我可以使用智能标签。我只需要在''中写上指定列的ids即可,可以一起使用,也可以分开使用,例如:

  

[e:loop={'1,12,13,16',10000,0,0}]

[/e:loop]

  让我们谈谈分页。一开始,我给青姐看我以前调用技术类所有文章的代码,问她如何实现分页。她告诉我这个调用无法实现分页,所以我只好使用自定义列表。她的文章:,但是我在操作过程中提交自定义列表后是空白的,无法查看原因,而且我的主页是动态主页,我还加了反采集和放入index.php 原来是phpcms站的动态链接改成了404的代码,那么我的网站使用中青姐的方法有缺陷。

  先说一下如何使用js实现分页,js在墨鱼博客中找到,原地址: ,但是用了我的网站后出现乱码,解决方法很简单,新建一个文本文档并把代码复制过来,然后另存为,选择UTF-8进行编码,然后新建一个js把代码复制回乱码问题就解决了。

  具体使用方法是在你原来的ul中加上id="list",并写样式display:none,然后在原来的ul下再加一个ul,类名id="list2",这个ul是用来移植的上面隐藏ul,在新添加的ul下调用js,这里我改成index-page.js,我把原文前面调用的js改成page-function.js,整体代码如下:

  这个时候前台打电话是没有问题的,但是你发现风格乱了。据说id="list2"的ul是用来移植id="list"的ul的内容,id="list"的ul也是隐藏的。然后将原创 ul 的类名添加到 id="list2" 的 ul 中。

  然后说样式,样式都在class="ctrlPages"的span里面,分页按钮在a标签里面,大家f12慢慢写样式,我提供我写的:

  

  

/*分页*/

span.ctrlPages {

display: block;

width: 90%;

text-align: center;

line-height: 2.0;

margin: auto;

margin-bottom: 15px;

}

span.ctrlPages a {

border: solid 1px #C6*敏*感*词**敏*感*词*;

padding: 2px 5px 2px 5px;

color: #333;

}

<p>

span.ctrlPages a.curPage {

background-color: #FD9D01;

padding: 3px 5px 3px 5px;

color: #fff;

border: none;

}</p>

  效果如下:

  我觉得当前页和页码提示没什么用,所以我把page-function.js中的相关代码删掉了,这个js中也修改了小样式。以下是修改后的效果

  我的js下载

  dgcms-index-page.rar

  02385c9a4d92a50047ade72*敏*感*词*ff49889.rar(1.44 KB)

  2019年9月29日补充:js实现分页存在缺陷,即一次加载所有列表信息。您可以通过查看源代码来了解这一点。如果您的主页没有使用缓存技术,建议加载或使用自定义您的列表。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线