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

【备战秋招】C++音视频开发经典面试题整理

1、简要介绍一下对 H.264 的了解?

1)基础描述

H.264 是由国际标准组织机构(ISO)下属的运动图象专家组(MPEG)和国际电传视讯联盟远程通信标准化组织(ITU-T)开发的系列编码标准之一。

2)码流结构

H.264 原始码流(裸流)是由一个接一个 NALU 组成,它的功能分为两层:VCL(视频编码层)和 NAL(网络抽象层)。

  • 视频编码层 VCL(Video Coding Layer):是对视频编码核心算法过程、子宏块、宏块、片等概念的定义。这层主要是为了尽可能的独立于网络来高效的对视频内容进行编码。

  • 网路抽象层 NAL(Network Abstract Layer):负责将 VCL 产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。

3)两种封装

H.264 的两种封装:AnnexB 模式和 AVCC 模式。

AnnexB 模式:

  • 传统模式

  • 有 startcode,startcode 码是:00 00 01 或 00 00 00 01 (3 字节或 4 字节)

  • SPS 和 PPS 在码流中分别作为一个 NALU

AVCC 模式:

  • 没有 startcode,SPS 和 PPS 以及其它信息被封装在 container 中,每一个 frame 前面 4 个字节是这个 frame 的长度

  • 一般在 mp4、mkv 格式中常用 AVCC 模式

很多解码器只支持 AnnexB 这种模式,因此需要将 AVCC 模式做转换,在 ffmpeg 中⽤ h264_mp4toannexb_filter 可以做转换,实现如下:

const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb"); AVBSFContext *bsf_ctx = NULL; 
// 初始化过滤器上下⽂ 
av_bsf_alloc(bsfilter, &bsf_ctx); 
// 添加解码器属性
avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->cod ecpar);
av_bsf_init(bsf_ctx);

2、H.264 编码框架分层目的是什么?

对 H.264 编码框架进行分层的主要目标是为了有高的视频压缩比和良好的网络亲和性。

VCL 层负责视频的信号处理,包含压缩,量化等处理,NAL 层则负责解决编码后数据的网络传输。

这样可以将 VCL 和 NAL 的处理放到不同平台来处理,可以减少因为网络环境不同对 VCL 的比特流进行重构和重编码。

这样将编码和网络传输进行隔离,使功能单一、便于维护。

3、介绍一下 I、P、B 帧编码、解码、显示顺序?

我们以下图为例来介绍一下 I、P、B 帧的编码过程:

编码器编码一个 I 帧,然后向后跳过几个帧,用这个 I 帧作为基准帧对一个未来 P 帧进行编码,然后跳回到这个 I 帧之后的下一个帧。I 帧和 P 帧之间的帧可以被编码为 B 帧。之后,编码器会再次跳过几个帧,使用第一个 P 帧作为基准帧,编码另外一个 P 帧,然后再次跳回,用 B 帧填充显示序列中的空隙。这个过程不断持续,然后每间隔一定的帧数后插入一个新的 I 帧。

由于帧之间存在依赖关系,所以各帧的解码顺序和编码顺序是一致的,先被编码的帧在解码时就会先被解码。为了实现这一点,编码的时候需要根据每帧的编码顺序会为其记录上一个 DTS(Decoding Time Stamp)用于解码时按此顺序进行解码。

如上面介绍的编码过程,P 帧由前一个 I 帧或 P 帧来预测,而 B 帧由前后的两个 P 帧或一个 I 帧和一个 P 帧来预测,因而当存在 B 帧时,帧的编解码顺序和帧的显示顺序会有所不同,这时候就需要为每帧记录上一个 PTS(Presentation Time Stamp)用于解码后按顺序显示。

4、H.264 与 H.265 有什么区别?

1)主要区别

  • H.265 也称为高效视频编码 (HEVC),是 H.264 的升级和更高级的版本;

  • H.265 的编码架构大致上 和 H.264 的架构相似,主要也包含:帧内预测(intra prediction)、帧间预测(inter prediction)、转换(transform)、量化(quantization)、去区块滤波器(deblocking filter)、熵编码(entropy coding)等模块。但在 H.265 编码架构中,整体被分为了三个基本单位,分别是编码单位(coding unit, CU)、预测单位(predict unit, PU)和转换单位(transform unit, TU);

  • 比起 H.264,H.265 提供了更多不同的工具来降低码率,以编码单位来说,H.264 中每个宏块(macroblock/MB)大小最大为 16x16 像素,而 H.265 的编码单位最大为 64x64;

  • H.265 的帧内预测模式支持 35 种方向(而 H.264 只支持 8 种),并且提供了更好的运动补偿处理和矢量预测方法。

5、RTMP 和 RTSP 有什么区别?使用 RTSP 是基于 UDP 传输的话,我们怎样进行乱序重排?

RTMP 和 RTSP 的区别:

RTMP 使用 TCP 作为传输层协议,能保证不丢包和接收顺序,传输质量高。

RTSP 使用 RTP 格式协议和 RTCP 控制协议,命令与数据分离。传输层协议一般会选择 UDP,延迟比较低,传输效率高。

RTSP 中的 RTP 格式头中有 SequenceNumber 字段,可以通过这个序号实现排序。

6、假如给你一堆乱序的 RTP 包,应该怎样实现乱序重排?

可以利用接收 RTP 包缓冲队列使用包的序号进行排序。

在丢包情况下为保证传输质量会引入 NACK 和 FEC 机制。

NACK 表示接收端通知发送端一些包丢失,发送 NACK 包请求重传;FEC 前向纠错值的是每个包携带一些冗余信息可以在部分包丢失的时候利用其他包进行重建。

如果重传次数过多,包无法重建,或者丢的包过多,此时可以丢帧直接跳过丢失的部分。

7、对 YUV 格式有了解吗?YUV 数据做转换是怎样实现的,比如说 YUV422 转为 YUV420?

YUV 格式是传输视频常用的格式,因为相对于 RGB 格式它可以节省更多空间。

YUV 的格式有很多,例如:YUV444、YUV422、YUV420,常用的 YUV 格式是 YUV420 格式。Y 表示亮度信息,是人眼最敏感的分量,UV 则表示色度信息。

YUV420 表示采样方式:UV 分量具有 2:1 的水平采样,2:1 的垂直采样,这里并不是指只有 U,没有 V,而是对于每一行,只有一个 U 或者 V 分量,如果第一行是 4:2:0,那么下一行就是 4:0:2。

可以用工具 YUVView 直接打开 YUV 格式的数据。

YUV 数据因为计算量大和数据量大可以都放到 GPU 存储和计算,YUV422 转 YUV420 可以利用 OpenGL 将 YUV422 的 UV 数据转换成 texture 纹理,编写 shader 做格式转换逻辑继而生成 YUV420 的 UV texture,再通过 readPixel 将显存的 UV 数据读取出来。转换逻辑即将纹理 UV 分量隔行采样。

8、你在项目中是怎么降低端到端的延时的?

面是直播走 RTMP 推流、HTTP-FLV 播放方案降低端到端延迟的思路:

  • 推流端的延迟包含编码延迟和发送缓存队列引入的延迟。可以通过调节编码参数(B 帧、码率、帧率)减小编码延迟但会影响画质。另外可以提高上传的传输性能来减小传输时长。

  • CDN 链路上的传输延迟。包括推流的链路和播放回源的链路,这部分延迟不是太大,但依旧会引入几百 ms 的延迟。

  • CDN 拉流边缘节点的吐流策略会直接影响延迟的大小。直播流编码的 GOP 的长度,CDN 在客户端拉流时吐几秒的数据、按照 GOP 分隔如何丢数据,这些策略都会影响延时。

  • 播放端可以通过对当前已下载的 buffer 进行倍速播放和跳帧来降低缓存从而达到降低延迟。注意如果倍速过大,声音是会明显变调的,需要通过算法来调整。跳帧一定要注意视频跳到 I 帧,音频对齐视频进行丢弃。

9、如何监控视频播放黑屏、花屏、绿屏等异常?

视频播放时如果遇到黑屏、花屏、绿屏通常会伴有解码器的报错或异常信息,我们可以上报这些异常信息来实现对这些情况的监控。

但是也有一些情况,即使出现黑屏、花屏、绿屏的情况了,解码器也没有报错或异常,这时候就需要我们对解码后的画面进行检测来识别这些问题。一般可以这样:

  • 用传统的图像处理算法来识别。对于黑屏、绿屏可以用传统图像处理算法来进行识别,但这里也会有一些误识别的问题,比如视频本身就有些亮度较低、正常全黑帧、正常全绿帧的情况,可能也会被识别为异常。

  • 训练 AI 模型类识别。对于花屏,可以训练 AI 模型来进行识别。训练过程可以通过人工构造丢帧视频的方法来生成花屏样本,同时筛选出无花屏问题的正常样本,基于这两类样本来做二分类模型的训练。

10、介绍一下 FFmpeg 中关于 timebase 的基础知识与应用?

1)timebase 定义

在 FFmpeg 中,time_base 是一个关键概念,它用于表示时间单位。在处理音频或视频流时,time_base 可以根据不同的采样频率或帧率来定义。timebase 在 FFmpeg 的定义是一个 AVRational 结构体:

typedef struct AVRational{int num; ///< numerator  int den; ///< denominator  
} AVRational;

2)timebase 的使用

在某些情况下,time_base 是根据采样频率来定义的。例如:对于视频采样频率为 90KHz(90000Hz)的情况,time_base 就相当于 1/90000 秒。另一种定义 time_base 的方式是根据帧率。例如:对于视频帧率为 24fps 的情况,time_base 就相当于 1/24 秒。在 FFmpeg 的分层结构中,原始数据层、编解码层和封装层都有对应的 time_base。原始数据层和封装层都通过 AVStream 进行处理,而编解码层则对应 AVCodec。

3)封装层 timebase,视频流/音频流 timebase 和现实时间戳的的关系和转换

封装层 tbn、视频 tbc 和音频 tbc 可以各不相同,相互不影响。现实时间基我们一般选用 1us 即 (1/1000000)s。因为每一层用的时间基不同,在函数参数传递上只会使用时间基前面的倍数值,timebase 是统一的,因此时间在不同的时间基上面需要做一层转换。 例如:现实时间 1s 转换到音频流时间实现为 1000000 * (1/1000000) = 44100 * (1/44100),那么现实时间 1000000 在音频流时间值则为 44100。举一个开发中的实例:如果想 seek 视频到现实时间的 X ms。

int64_t seekTime = (int64_t)(( X / 1000 )  / av_q2d(videoStream->time_base)); 
av_seek_frame(videoFormatCtx_, video_index_, seekTime, AVSEEK_FLAG_BACKWARD);

因为 av_seek_frame 是在视频流层面,时间基与现实时间不同,需要转换并将转换后的值作为参数才能得到正确的结果。

4)转换函数解析

double av_q2d(AVRational a) //将AVRational 对象转换为小数,便于转换
// 将一个时间戳a从时基bq转换到时基cq下
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)

例如,将视频流的一帧 pts(a * atbr) 转换到封装层打包成 AVPacket,封装层 timebase 为 tbn,此时需要转换 int64 t = av_rescale_q_rnd(a, atbr, tbn);。

如果还不知道音视频开发需要学习哪些内容的同学,可以参考程序员老廖的学习路线,主页也分享了很多音视频的面试题和项目供大家学习参考

最全音视频学习路线-互联网音视频-嵌入式音视频https://www.bilibili.com/video/BV138DoY7E74/

11、I 帧和 IDR 帧有什么区别?在什么情况下 I 帧不是 IDR 帧?

I 帧:I 帧是视频序列中的关键帧,它是一个完整的图像帧,类似于 JPEG 或 BMP 图像文件。I 帧不依赖于其他帧,因此可以独立解码和显示。在视频序列中,I 帧通常用于随机访问点,也作为其他帧解码的参考。

IDR 帧:IDR 帧是一种特殊的 I 帧,它具有刷新解码器缓冲区的功能。当解码器接收到 IDR 帧时,它会清除之前的解码状态,确保从该帧开始解码,从而避免错误传播。IDR 帧通常用于视频序列的随机访问点,以及在视频传输或存储中用于错误恢复。

因此 IDR 帧一定是 I 帧,但是 I 帧则不一定是 IDR 帧。在遇到 OpenGOP 的情况下,就会出现 I 帧为非 IDR 帧的情况。

OpenGOP

如上图所示右数第一个 I 帧就是一个非 IDR 的 I 帧,前一个 GOP 中的 B 帧依赖了当前 GOP 的 I 帧。所以右数第一个 I 帧接受时,不能刷新解码器,否则上一个 GOP 中的 B 帧无法被成功解码,可能会出现花屏或者报错。

12、如果让你设计一个播放器的架构,你会分哪几层?

我们可以分下面几层来设计播放器的架构:

  • 音视频核心层:职责在于处理网络协议、音视频解封装(Demuxer)、音视频解码(Decoder)、音视频数据结构封装等等,通常基于 FFmpeg 来实现。

  • 播放器内核层:基于音视频核心层的能力来封装播放器内核能力,包括使用多线程、多缓冲区串联网络、解封装、解码、渲染等节点;支持播放、暂停、seek、刷新数据源等控制能力;提供播放状态获取、播放事件回调、播放器错误上报等接口。

  • 播放器封装层:基于平台开发语言对播放器内核进行封装,提供高内聚低耦合的播放器接口。

  • 播放器工具层:在播放器核心能力的基础上组装和扩展其他播放相关的其他能力,比如:边下边播视频缓存能力、播放远程配置能力、播放数据埋点上报能力等等。

  • 播放业务控制层:基于业务属性进行播放策略控制,比如:码率选档、解码方式选择、网络链路优选等策略。

13、如何降低处理音视频链路中的内存峰值?

音视频处理链路中的内存峰值一般是视频数据导致的,要降低内存峰值一般可以从两个方面入手:

降低采集参数:

  • 降低采集视频分辨率

  • 降低采集视频帧率

降低并发任务数量:

  • 将任务分优先级,按照优先级串行执行,这样既能降低内存峰值,也会降低 CPU 峰值

14、聊聊对音视频同步的理解?

音视频对齐方式有三种:

  • 以音频时钟为基准

  • 以视频时钟为基准

  • 以第三方时钟为基准

由于音频播放都是硬件来驱动的,相对比较稳定,另外音频 pts 通常是单调递增的,所以一般是按照音视时钟为准。

以一个 44.1KHz 的 AAC 音频流和 24 FPS 的视频流为例,理想情况下,音视频完全同步,音视频播放过程如下图所示:

音视频同步

但实际情况下,如果用上面那种简单的方式,慢慢的就会出现音视频不同步的情况,主要原因是同步时,时间粒度太大了,难以精准控制。所以需要引入一个参考时钟(要求参考时钟上的时间是恒定线性递增的)来提高音频时钟的时间粒度,比如:系统时间,进而进行精准时钟对齐。最后以音频时钟为准,视频放快了就减慢播放速度,播放快了就丢帧或加快播放的速度。

15、为什么在 YUV 转 RGB 转换中 UV 分量要减去 0.5?

在 YUV 到 RGB 的转换公式中,U 和 V 分量减去 0.5 的原因与 YUV 颜色空间的编码方式有关。YUV 格式通常用于视频压缩,其中 Y 代表亮度(luminance),而 U 和 V 代表色度(chrominance),也就是颜色信息。在某些 YUV 格式中,U 和 V 的取值范围是标准化的,例如在 8 位颜色深度中,U 和 V 的取值范围是从 -128 到 127。这种表示方法将色度的中心点设在了 0,使得色度信号可以表示正负偏差。

在进行 YUV 到 RGB 的转换时,为了将 U 和 V 的取值范围从对称的 -128 到 127 归一化为非对称的 0 到 255,并且将中心点从 128 移动到 0,需要对 U 和 V 进行偏移量的减法操作。具体来说,通过减去 0.5(或 128 对应的小数形式),可以将 U 和 V 的取值范围转换为 0 到 255,从而与 RGB 的取值范围相匹配。

例如,如果使用如下的转换公式:

[ R = Y + 1.4075 * (V - 128) ]
[ G = Y - 0.34414 * (U - 128) - 0.71414 * (V - 128) ]
[ B = Y + 1.772 * (U - 128) ]

在这个公式中,U 和 V 减去 128 实际上就是将色度信号的中心从 128 移动到 0,然后再进行缩放操作以匹配 RGB 的取值范围。如果不进行这个减法操作,色度信号将不会正确地转换为 RGB 颜色空间,导致颜色失真。

总结来说,U 和 V 分量后面减去 0.5 是为了将色度信号的表示方式从 YUV 颜色空间转换为 RGB 颜色空间,确保颜色信息的准确传递。

16、如何获取视频流中的 QP 值?

在 H.264 中,量化参数(QP)的获取涉及到几个层级:

  • 图像参数集(PPS):包含初始量化参数 pic_init_qp_minus26,其取值范围是 -26 到 +25。

  • 片头(Slice Header):每个片(Slice)都有自己的片头,其中包含 slice_qp_delta,表示当前片所有宏块的量化参数初始值 QPy Slice,计算公式为:QPy Slice = 26 + pic_init_qp_minus26 + slice_qp_delta,其取值范围是 0 到 51。

  • 宏块(Macroblock, MB):宏块是编码的基本单元,宏块量化参数偏移值 mb_qp_delta 表示前后两个宏块之间的偏移,取值范围是 -26 到 +25。第一个宏块的 QP 值等于片头的 QP 值,后续宏块的 QP 值计算方式为 QP = (QPprev + mb_qp_delta + 52) % 52。

要从 H.264 码流中提取 QP 值,需要执行以下步骤:

  • 1、解析 NALU:首先需要定位并提取 NALU,因为 QP 值信息分布在 PPS 和 Slice Header 中。

  • 2、解析 PPS:找到 PPS NALU 并解析出 pic_init_qp_minus26。

  • 3、解析 Slice Header:对于每个 Slice,解析 Slice Header 以获取 slice_qp_delta。

  • 4、计算 QP 值:根据上述解析出的参数和宏块信息,计算每个宏块的 QP 值。

使用工具:可以使用如 ffmpeg 等工具来辅助解析码流和提取 QP 值。例如,ffmpeg 提供了 -showqp 选项来显示量化参数。

编程实现:也可以通过编程方式,如使用 Python 结合相关库来解析 H.264 码流并提取 QP 值。

在实际应用中,可能需要结合具体的编码场景和需求来选择合适的工具和方法,以实现对 H.264 码流中 QP 值的提取。

17、视频编码对 QP 值的控制有哪些?

在视频编码中,QP(Quantization Parameter)值是一个重要的概念,它对编码后视频的质量和码率有着直接的影响。视频编码中的量化步骤是将像素值映射到一个较小的数值范围内,这一步骤会损失一些图像细节,但可以显著减少编码后视频的数据量。

QP 值决定了量化过程中的量化步长,从而影响量化的精度。较小的 QP 值意味着量化步长较小,量化过程更精细,编码后的视频质量更高,但同时也会导致码率增加; 较大的 QP 值意味着量化步长较大,量化过程更粗糙,编码后的视频质量较低,但码率会减少。

对于部分软编库来说是可以设置平均/最大/最小 QP 值的。下面我们重点说下客户端如何设置 QP。

  • 在 iOS 中使用 VideoToolbox 编码视频时通过属性值设置最大 QP 和最小 QP 值。属性 key 为 kVTCompressionPropertyKey_MinAllowedFrameQP、kVTCompressionPropertyKey_MaxAllowedFrameQP。 这样编码器就会保证是编码出来的文件 QP 值在这个范围。其次如果你设置了码率,他也会在这个范围内尽量使用你设置的码率。但是如果你设置的码率过高或者过低,QP 值无法满足时,编码器则根据优先以 QP 值自动调整码率。

  • Android 部分机型的编码器可以开启质量编码模式,即 KEY_BITRATE_MODE 为 BITRATE_MODE_CQ。质量可以通过设置参数 KEY_VIDEO_QP_MAX、KEY_VIDEO_QP_MIN、KEY_VIDEO_QP_P_MAX、KEY_VIDEO_QP_P_MIN、KEY_VIDEO_QP_B_MAX、KEY_VIDEO_QP_B_MIN 等一系列参数来控制帧的 QP 值。

18、纹理有哪些环绕方式(wrapping)?

  • 重复(GL_Repeat):纹理在每个纹理坐标轴上重复出现,当纹理坐标超出 [0,1] 范围时,纹理会在该轴上重复出现。这种方式适用于创建无缝平铺效果。这是对纹理的默认行为。

  • 镜像重复(GL_MIRRORED_REPEAT):与重复(GL_Repeat)方式相似,但当纹理坐标超出 [0,1] 范围时,会将其镜像翻转后再重复出现。这可以有效减少纹理重复造成的视觉疲劳。

  • 夹取到边缘(GL_CLAMP_TO_EDGE):与夹取方式类似,但在超出范围时,会使用边缘纹素的颜色,产生一种边缘被拉伸的效果。

  • 夹取到边框(GL_CLAMP_TO_BORDER):超出范围时,使用指定的边框颜色。这种方式通常用于在超出纹理范围时填充边框颜色,避免黑边。

19、为什么视频会议用 UDP?如果用 TCP 实现音视频,需要建立几次连接?用 UDP 实现音视频,有什么方法可以保证通话质量?

1)为什么视频会议用 UDP?

视频会议场景最重要的体验指标一般是『通话延时』和『语音音质』两方面。

在传输层使用 UDP 的主要考虑是为了降低通话延时。因为 UDP 的不需要 TCP 那样的面向连接、可靠传输、拥塞控制等机制,这些机制(比如三次握手建连、丢包重传等)通常都会带来相对 UDP 更高的延时。

当然,另外一方面原因是人们对视频会议中图像信息的损失容忍度是比较高的,这样即使 UDP 无法保证可靠性,有时候还是可以接受的。

2)如果用 TCP 实现音视频,需要建立几次连接?

可以做到只建连一次,多路复用。 也可以音频和视频各使用一路连接。

3)用 UDP 实现音视频,有什么方法可以保证通话质量?

使用 UDP 享受了低延时,牺牲了可靠性。但可靠性牺牲太多导致不可用也是不可接受的,所以还需要做一些机制来保证一定的可靠性,比如我们可以参考 WebRTC 的机制:

  • NACK:通过丢包重传解决丢包问题,会增加延时。

  • FEC:通过冗余数据解决丢包问题,会增加带宽占用。

  • JitterBuffer:通过队列对接收到的数据进行缓冲,出队时将数据包均匀平滑的取出,解决视频的乱序与抖动。

  • NetEQ:类似 JitterBuffer,解决音频的乱序与抖动。

20、为什么会有 YUV 这种数据?它相比 RGB 数据有什么优点?

RGB 工业显示器要求一幅彩色图像由分开的 R、G、B 信号组成,而电视显示器则需要混合信号输入,为了实现对这两种标准的兼容,NTSC(美国国家电视系统委员会)制定了 YIQ 颜色模型,它的主要优点是可以实现对彩色电视和黑白电视的兼容,即可以用黑白电视收看彩色电视信号。YUV 颜色模型则是在 YIQ 的基础上发展而来。

YUV 颜色模型中用亮度、色度来表示颜色。它的亮度信息和色度信息是分离的,其中 Y 表示亮度通道,U 和 V 则表示色度通道。如果只有 Y 信息,没有 U、V 信息,那么表示的图像就是灰度图像。YUV 常用在各种影像处理场景中。YUV 在对照片或视频编码时,考虑到人眼对亮度信息的敏感度高于色度信息,允许降低色度的带宽。这样一来就可以对色度信息进行压缩,所以 YUV 可以相对 RGB 使用更少的数据带宽。比如常见的采样格式有:4:2:1、4:1:1、4:2:0 等,它们分别相对 RGB 压缩了 33.3%、50%、50% 的数据量。

21、RTMP 消息分优先级的设计有什么好处?

RTMP 的消息优先级是:控制消息 > 音频消息 > 视频消息。当网络传输能力受限时,优先传输高优先级消息的数据。

要使优先级能够有效执行,分块也很关键:将大消息切割成小块,可以避免大的低优先级的消息(如视频消息)堵塞了发送缓冲从而阻塞了小的高优先级的消息(如音频消息或控制消息)。

22、iOS 中如何判断一个视频帧是不是关键帧?

在 VideoToolbox 中,可以通过检查给定的 CMSampleBuffer 是否是视频帧,并且是否是关键帧。通过检查 kCMSampleAttachmentKey_NotSync 键的值,如果它为 false ,则说明这是一个关键帧。以下是示例代码

#import <VideoToolbox/VideoToolbox.h>BOOL isKeyFrame(CMSampleBufferRef sampleBuffer) {CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);if (!formatDescription) {return NO;}CMMediaType mediaType = CMFormatDescriptionGetMediaType(formatDescription);if (mediaType != kCMMediaType_Video) {return NO;}CFArrayRef sampleAttachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true);CFDictionaryRef sampleAttachments = (CFDictionaryRef)CFArrayGetValueAtIndex(sampleAttachmentsArray, 0);BOOL isKeyFrame = !CFDictionaryContainsKey(sampleAttachments, kCMSampleAttachmentKey_NotSync);return isKeyFrame;
}

23、iOS 中系统 API 提供了哪些视频编码的方式?

在 iOS 中,实现视频编码的方式主要包括以下两种:

  • AVFoundation 框架:AVFoundation 是苹果提供的一个用于处理音视频数据的框架,它提供了一系列用于捕获、处理和输出音视频数据的类和方法。通过 AVFoundation 框架,可以使用 AVAssetWriter 和 AVAssetWriterInput 类来实现编码视频。

  • VideoToolbox 框架:VideoToolbox 是苹果提供的一个专门用于处理视频数据的框架,它提供了硬件加速的视频编码和解码功能。使用 VideoToolbox,可以利用 iOS 设备上的硬件编码器来实现高效的视频编码。

相比而言,AVFoundation 框架则提供了更加上层的接口,更简单易用,但因此对于一些特殊需求和高级功能,可能无法满足。VideoToolbox 则提供了更直接的对硬件编码器的访问,允许开发者能更细致的控制编码器的配置和参数,并且可以直接操作编码器的输入和输出数据,灵活性更好。

24、VideoToolbox 视频帧解码失败以后应该如何重试?

  • 1、重新初始化解码器:尝试重新初始化 Videotoolbox 解码器,有时候重新初始化可以解决解码过程中的一些临时问题。

  • 2、检查视频文件:确保视频文件没有损坏或者格式不正确。有时候解码失败是因为视频文件本身的问题,可以尝试使用其他工具或者重新获取视频文件。

  • 3、检查当前内存:在解码过程中如果 CMSampleBuffer 不及时释放,可能会导致内存过高导致解码器报 -11800 通用错误。

  • 4、尝试重新解码当前帧:将当前帧以及当前 gop 内前序帧都重新输入给解码器。

来源:关键帧 - 个人中心

相关文章:

【备战秋招】C++音视频开发经典面试题整理

1、简要介绍一下对 H.264 的了解&#xff1f; 1&#xff09;基础描述 H.264 是由国际标准组织机构&#xff08;ISO&#xff09;下属的运动图象专家组&#xff08;MPEG&#xff09;和国际电传视讯联盟远程通信标准化组织&#xff08;ITU-T&#xff09;开发的系列编码标准之一。…...

【音频处理】java流式调用ffmpeg命令

今天发现一个ffmpeg的用法&#xff0c;用子进程直接从标准输入写入输入&#xff0c;就可以从标准流式输出获取转码结果。 这样的好处是不用去写ffmpeg的代码&#xff0c;只需要写对ffmpeg的命令、在输入输出的地方加缓存就能进行流式转码了&#xff0c;方便快捷。 但是也有坏处…...

《java创世手记》---java基础篇(下)

《Java 创世手记 - 基础篇&#xff08;下&#xff09;》 第五章&#xff1a;契约与规范 —— 接口 (Interfaces) 与抽象类 (Abstract Classes) 造物主&#xff0c;在你日益繁荣的世界里&#xff0c;你发现仅仅依靠“继承”来构建“物种体系”有时会遇到一些限制。比如&#x…...

【MySQL】C语言连接

要使用C语言连接mysql&#xff0c;需要使用mysql官网提供的库&#xff0c;大家可以去官网下载 我们使用C接口库来进行连接 要正确使用&#xff0c;我们需要做一些准备工作: 保证mysql服务有效在官网上下载合适自己平台的mysql connect库&#xff0c;以备后用 下载开发库 s…...

How API Gateways handle raw TCP packets

How these gateways actually perform their roles at the HTTP packet level? Let’s break it down into something more concrete with examples of how these gateways perform their “unique entrance” function by requiring clients to follow specific protocols, …...

芯片配置文件自动化生成

代码的主要功能是将设置了芯片寄存器的Excel表格&#xff08;.xls或.xlsx&#xff09;中的特定工作表的数据转换成SVD格式。 步骤 Excel文件读取 使用xlrd库打开Excel文件处理.xls格式的特殊情况&#xff08;formatting_infoTrue&#xff09;获取"global"工作表数…...

新能源汽车与油车销量

中国油车与新能源车销量对比&#xff08;2022-2025年&#xff09; ‌1. 市场份额演化&#xff08;2022-2025年&#xff09;‌ ‌年份‌ ‌新能源车销量 &#xff08;渗透率&#xff09;‌ ‌燃油车销量 &#xff08;渗透率&#xff09;‌ ‌关键事件‌ ‌2022‌ 688.7万辆…...

LVS-DR 负载均衡集群

目录 一、简介 1.1 LVS-DR工作原理核心特性 1.2 数据包流向深度解析 二、实验环境准备与规划 三、LVS调度器配置实战 3.1 绑定虚拟IP地址&#xff08;VIP&#xff09; 3.2 调整内核参数禁用重定向 3.3 配置负载均衡策略 四、真实服务器节点配置 4.1 绑定VIP到lo接口 …...

基于Java,SpringBoot,Vue,UniAPP宠物洗护医疗喂养预约服务商城小程序管理系统设计

摘要 随着宠物经济的快速发展&#xff0c;宠物主对宠物服务的便捷性、专业性需求日益增长。本研究设计并实现了一套宠物洗护医疗喂养预约服务小程序系统&#xff0c;采用 Java 与 SpringBoot 构建后端服务&#xff0c;结合 Vue 开发管理后台&#xff0c;通过 UniAPP 实现多端适…...

中车靶场,网络安全暑期实训营

不善攻防&#xff0c;何谈就业&#xff1f; 实训目的&#xff1a;提升实战能力&#xff0c;直通就业快道。 实训对象&#xff1a;面向计算机相关专业、有兴趣接触网络攻防、大专及以上学历的学员。 知识准备 为确保高效实训&#xff0c;学员需具备一定的实战基础。报名后&am…...

2.2.2 06年T1

成功的同化机器——美国&#xff1a;2006年考研英语&#xff08;一&#xff09;Text 1精析 本文解析2006年考研英语&#xff08;一&#xff09;第一篇文章&#xff0c;揭示美国社会强大的文化同化力及其表现。 一、原文与翻译 Paragraph 1&#xff1a;美国社会的同化本质 L1: …...

split_conversion将json转成yolo训练用的txt,在直接按照8:1:1的比例分成训练集,测试集,验证集

第一章 使用说明 类别自己在代码中改&#xff0c;其他四个参数 --json-folder:json文件夹路径 --txt-folder&#xff1a;转换成功后txt的存放路径 --images-dir&#xff1a;图片文件夹路径 --save-dir&#xff1a;转换完成分割后所有文件的路径 终端命令行&#xff1a;p…...

响应式系统与Spring Boot响应式应用开发

响应式系统概述 过去十年间,为应对移动和云计算的需求,软件行业通过改进开发流程来构建更稳定、健壮且灵活的软件系统。这种演进不仅服务于传统用户端(桌面/Web),还需支持多样化设备(手机、传感器等)。为应对这些挑战,多个组织共同制定了《响应式宣言》(2014年发布)…...

【第1章 基础知识】1.8 在 Canvas 中使用 HTML 元素

文章目录 前言示例-橡皮筋式选取框示例代码 前言 尽管我们可以说 Canvas 是 HTML5 之中最棒的功能&#xff0c;不过在实现网络应用程序时&#xff0c;很少会单独使用它。在绝大多数情况下&#xff0c;你都会将一个或更多的 canvas 元素与其他 HTML 控件结合起来使用&#xff0…...

c++流之sstream/堆or优先队列的应用[1]

目录 c流之sstream 解释 注意事项 215.数据流的第k大 问题分析 修正代码 主要修改点 优先队列的比较规则 代码中的比较逻辑 为什么这样能维护第 k 大元素&#xff1f; 举个例子 总结 Python 实现&#xff08;使用heapq库&#xff09; Java 实现&#xff08;使用P…...

SAR ADC 比较器噪声分析(二)

SAR ADC的比较器是非常重要的模块&#xff0c;需要仔细设计。主要考虑比较器的以下指标&#xff1a; 1)失调电压 2)输入共模范围 3)比较器精度 4)传输延时 5)噪声 6)功耗 这里主要讲一下动态比较器的noise。 动态比较器一般用于高速SAR ADC中&#xff0c;且精度不会超过12bit…...

c#与java的相同点和不同点

C# 和 Java 是两大主流的、面向对象的、托管型编程语言&#xff0c;它们共享许多相似的设计理念和语法&#xff0c;但也在细节、生态系统和运行平台上存在显著差异。以下是它们的相同点和不同点的详细对比&#xff1a; 一、相同点 (核心相似之处) 语法高度相似&#xff1a; 都源…...

phpmyadmin

安装PHPMyAdmin PHPMyAdmin通常可通过包管理器安装或手动部署。对于Linux系统&#xff08;如Ubuntu&#xff09;&#xff0c;使用以下命令安装&#xff1a; sudo apt update sudo apt install phpmyadmin安装过程中会提示选择Web服务器&#xff08;如Apache或Nginx&#xff0…...

机器学习Day5-模型诊断

实现机器学习算法的技巧。当我们训练模型或使用模型时&#xff0c;发现预测误差很 大&#xff0c;可以考虑进行以下优化&#xff1a; &#xff08;1&#xff09;获取更多的训练样本 &#xff08;2&#xff09;使用更少的特征 &#xff08;3&#xff09;获取其他特征 &#xff…...

如何将 WSL 的 Ubuntu-24.04 迁移到其他电脑

在使用 Windows Subsystem for Linux (WSL) 时&#xff0c;我们可能会遇到需要将现有的 WSL 环境迁移到其他电脑的情况。无论是为了备份、更换设备&#xff0c;还是在不同电脑之间共享开发环境&#xff0c;掌握迁移 WSL 子系统的方法都是非常有用的。本文将以 Ubuntu-24.04 为例…...

金融欺诈有哪些检测手段

金融欺诈检测是一个多层次的动态防御过程&#xff0c;需要结合技术手段、数据分析、人工智能和人工审核。以下是当前主流的检测手段和技术分类。 ### **一、核心技术手段** 1. **规则引擎&#xff08;Rule-Based Systems&#xff09;** - **原理**&#xff1a;预设基于历史…...

HTML5 全面知识点总结

一、HTML 基础概念 HTML&#xff1a;超文本标记语言&#xff0c;用于创建网页和 Web 应用的结构。 超文本&#xff1a;可以包含文字、图片、音频、视频、链接等多种媒体。 标记语言&#xff1a;通过标签标记网页的各个部分。 二、HTML5 的新特性&#xff08;区别于 HTML4&am…...

vscode一直连接不上虚拟机或者虚拟机容器怎么办?

1. 检查并修复文件权限 右键点击 C:\Users\20325\.ssh\config 文件&#xff0c;选择 属性 → 安全 选项卡。 确保只有你的用户账户有完全控制权限&#xff0c;移除其他用户&#xff08;如 Hena\Administrator&#xff09;的权限。 如果 .ssh 文件夹权限也有问题&#xff0c;同…...

初学c语言21(文件操作)

一.为什么使用文件 之前我们写的程序的数据都是存储到内存里面的&#xff0c;当程序结束时&#xff0c;内存回收&#xff0c;数据丢失&#xff0c; 再次运行程序时&#xff0c;就看不到上次程序的数据&#xff0c;如果要程序的数据一直保存得使用文件 二.文件 文件一般可以…...

数学复习笔记 21

4.15 稍微有点难啊。克拉默法则忘掉了&#xff0c;然后第二类数学归纳法是第一次见。行列式和矩阵&#xff0c;向量和方程组。这是前面四章。现在考研只剩下一个大题。所以就是考最后两章&#xff0c;特征值和二次型。感觉看网课的作用就是辅助理解&#xff0c;自己看书的话&am…...

华为OD机试真题——数据分类(2025B卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 B卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》 华为OD机试真题《数据…...

JavaWeb开发基础Servlet生命周期与工作原理

Servlet生命周期 Servlet的生命周期由Servlet容器(如Tomcat、Jetty等)管理&#xff0c;主要包括以下5个阶段&#xff1a; 加载Servlet类 创建Servlet实例 调用init方法 调用service方法 调用destroy方法 加载(Loading)&#xff1a; 当Servlet容器启动或第一次接收到对某个…...

三防平板科普:有什么特殊功能?应用在什么场景?

在数字化浪潮席卷全球的今天&#xff0c;智能设备已成为现代工业、应急救援、户外作业等领域的核心工具。然而&#xff0c;常规平板电脑在极端环境下的脆弱性&#xff0c;如高温、粉尘、水浸或撞击&#xff0c;往往成为制约效率与安全的短板。三防平板&#xff08;防水、防尘、…...

百度外链生态的优劣解构与优化策略深度研究

本文基于搜索引擎算法演进与外链建设实践&#xff0c;系统剖析百度外链的作用机制与价值模型。通过数据统计、案例分析及算法逆向工程&#xff0c;揭示不同类型外链在权重传递、流量获取、信任背书等维度的差异化表现&#xff0c;提出符合搜索引擎规则的外链建设技术方案&#…...

笔记: 在WPF中ContentElement 和 UIElement 的主要区别

一、目的&#xff1a;简要姐扫在WPF中ContentElement 和 UIElement 的主要区别 ContentElement 和 UIElement 是 WPF 中的两个基类&#xff0c;它们在功能和用途上有显著的区别。 二、主要区别 ContentElement 主要特点: • 没有视觉表示: ContentElement 本身不直接渲染任…...