1. IDR 帧与普通 I 帧的区别

所有的 IDR 帧都是 I 帧,但不是所有的 I 帧都是 IDR 帧。

  • 普通 I 帧:是一个全帧压缩图像,不依赖其他帧就能解码。但是,在它之后的 P 帧或 B 帧可以跨过这个 I 帧去参考它之前的帧。

  • IDR 帧:它会“清空”解码器的参考帧队列。这意味着,IDR 帧之后的任何帧都绝对不能参考该 IDR 帧之前的任何帧。


2. IDR 帧的两个核心作用

A. 解码器的“重置键”

当解码器遇到 IDR 帧时,它知道之前所有的参考数据都不再需要了。这防止了错误无限传递。如果视频流因为网络抖动丢包了,画面会花屏,直到下一个 IDR 帧 出现,画面才会恢复正常。

B. 随机访问与切入点

视频流的“快进”或“重新连接”只能从 IDR 帧开始。

  • 为什么你的拉流端有时报 no one is publishingtimeout 如果推流端发送数据的频率太低,或者 IDR 帧间隔(GOP)设置得太大(比如 10 秒才一个),拉流端在接入时可能要等很久才能拿到第一个 IDR 帧和对应的 SPS/PPS,从而导致连接超时断开。



ffmpeg -re -i input.mp4 -c:v libx264 -g 30 -force_key_frames "expr:gte(t,n_forced*1)" -f rtsp rtsp://...
  • -g 30:每 30 帧设一个 GOP。

  • force_key_frames:强制每秒产生一个关键帧(IDR 帧)。

以下是关于视频传输基础知识的详细讲解:

3. 时间戳:PTS 与 DTS

视频帧在传输过程中并不是简单地“发一帧播一帧”,因为为了压缩效率,视频帧的解码顺序显示顺序往往是不一致的。

  • PTS (Presentation Time Stamp, 显示时间戳)

    • 定义:告诉播放器这一帧应该在什么时间点展示给用户看。

    • 作用:确保音视频同步(AV Sync)。播放器会对比音频 PTS 和视频 PTS,决定是否需要跳帧或等待。

  • DTS (Decoding Time Stamp, 解码时间戳)

    • 定义:告诉解码器这一帧应该在什么时间点进行解码。

    • 必要性:在使用 B 帧(双向预测帧)时,解码器必须先解码后面的 P 帧才能解码前面的 B 帧,因此 DTS 会早于 PTS。


4. 时间基 (Time Base)

时间戳(PTS/DTS)本身通常不是以“秒”为单位的整数,而是一个刻度数。要转换成秒,必须配合 Time Base

  • 概念时间(秒) = PTS × Time Base

  • 示例:如果系统的 Time Base1/90000(这是 RTSP/封装格式中常见的频率),而某一帧的 PTS90000,那么它的显示时间就是 90000 * (1/90000) = 1秒

  • 在 RK3588 开发中的意义:如果你在代码中直接把 1, 2, 3 赋值给 PTS 却发现推流失败,通常是因为你的 Time Base 设置得很大(如 90000),导致服务器认为你的帧间隔只有几万分之一秒,从而判定为异常。


5. NALU:视频流的“原子”单位

H.264/H.265 的数据流是由一个个 NALU (Network Abstraction Layer Unit) 组成的。

  • 起始码 (Start Code):在 Annex B 格式中,每个 NALU 以 00 00 00 0100 00 01 开头。

  • NALU 类型

    • SPS (序列参数集):包含分辨率、配置等级等全局信息。

    • PPS (图像参数集):包含具体图像的解码参数。

    • IDR 帧:即即时解码刷新帧,是解码的起点。

    • SEI:补充增强信息,有时用于传输元数据(如摄像头旋转角度)。


6. 视频帧类型:GOP 结构

视频压缩通过 GOP (Group of Pictures) 来实现,一个 GOP 是指两个 I 帧之间的连续帧序列。

  • I 帧 (Intra-coded):全帧压缩,类似一张 JPEG 图片,解码不依赖其他帧。

  • P 帧 (Predictive-coded):前向预测帧,只记录与前一帧的差异。

  • B 帧 (Bi-predictive):双向预测帧,参考前后两帧。注意:实时通信(如你的拼接项目)通常会禁用 B 帧来降低延迟。



7. 视频传输的“来龙去脉”(封装与协议)

视频压缩好了,但它只是一堆乱糟糟的数学数据。要传输它,需要分层处理:

第一步:NALU (原子层)

将压缩后的数据切成一个个小包。

  • SPS/PPS:说明书,告诉解码器分辨率是多少。

  • IDR 帧:关键点,告诉解码器从这里可以开始工作。

第二步:容器 (Container)

把视频包和音频包像“包饺子”一样裹在一起。

  • 常见格式:MP4, MKV, FLV, TS。

第三步:协议 (Protocol) —— 你的 RTSP 报错就在这

容器是静态的,协议是动态的。

  • RTSP/RTMP:相当于“物流快递”。它负责握手、建立连接、控制播放/暂停。

  • PTS/DTS:相当于包上的“快递单号”。

    • DTS (解码时间戳):告诉解码器什么时候拆包。

    • PTS (显示时间戳):告诉屏幕什么时候把画贴出来。


8 pts dts的时间戳时干嘛的 按时间播放什么意思

在视频传输中,PTSDTS 的存在是因为视频并不是按照“排队领盒饭”的简单顺序处理的。为了让视频体积更小,人们发明了复杂的“跳跃式”参考机制,这导致了解码顺序显示顺序的脱节。


1. 为什么要分 PTS 和 DTS?

视频帧分为 I、P、B 三种类型。问题的核心在于 B 帧(双向参考帧)

  • DTS (Decoding Time Stamp)解码时间戳。告诉解码器什么时候该把这一帧数据“拆包”并还原成图像像素。

  • PTS (Presentation Time Stamp)显示时间戳。告诉播放器什么时候该把这一帧图像“贴到屏幕上”给用户看。

为什么它们不一样? 想象你要组装一个模型,B 零件需要参考 A 零件和 C 零件。那么:

  1. 你必须先拿到 A 和 C(解码顺序/DTS)。

  2. 即使你先拿到了 C,你也得等 B 组装好后,按顺序摆放 A -> B -> C(显示顺序/PTS)。

在没有 B 帧的情况下(比如很多低延迟监控流),DTS 和 PTS 通常是相等的。但只要有 B 帧,DTS 就会比 PTS 提前,因为解码器必须“未雨绸缪”,先解码后面的参考帧。


2. “按时间播放”是什么意思?

“按时间播放”本质上是**将视频帧从“数学刻度”还原为“人类感知时间”**的过程。

视频文件里存储的 PTS 并不是“00:00:01”这样的文字,而是一个计数器数值(类似于时钟的滴答数)。

A. 时间基 (Time Base) 的概念

由于计算机处理速度很快,秒这个单位太大了。视频系统会把 1 秒切成很多份,这就是 Time Base(时间基)

  • 常见的 RTSP 时间基是 1/90000

  • 这意味着 1 秒钟被切成了 90,000 份。

B. 还原公式

播放器看到的逻辑是:

播放时间 (秒)=PTS×Time Base

举个例子: 如果一帧视频的 PTS 是 180000,时间基是 1/90000。 播放器计算:180000×(1/90000)=2.0。 那么播放器就会等系统时钟走到第 2.0 秒的那一刻,把这帧画面刷到屏幕上。

在视频开发的整条流水线中,这些关键的元数据(SPS/PPS, PTS/DTS)是由不同的环节逐层添加上去的。

我们可以把这个过程看作一个“物流工厂”:

1. 谁添加了 SPS 和 PPS?(配置说明书)

这是由 编码器 (Encoder) 产生的。

  • 在你之前的命令中:当你调用 -c:v h264_rkmpp 时,瑞芯微的硬件编码器芯片在初始化时,会根据你设置的分辨率(1920x1080)和码率(4M)计算出这套“说明书”。

  • 传输过程:编码器通常只在最开始生成一次。由于你后来添加了 -bsf:v dump_extra,FFmpeg 的比特流过滤器会在每一个 IDR 帧前强行把这些数据“复印”一份插进去。


2. 谁添加了 PTS 和 DTS?(物流单号)

这个数据的来源分为两个阶段:

阶段 A:采集端(初稿)
  • 来源:由 采集设备(摄像头/V4L2)封装库 添加。

  • 逻辑:当你从 /dev/video75 读取数据时,内核驱动会给每一帧打上一个“系统时间戳”,告诉 FFmpeg 这一帧是什么时候拍下来的。

阶段 B:推流端(校订)
  • 来源:由 你的代码逻辑FFmpeg 容器层 (Muxer) 重新计算。

  • 逻辑

    • 解码后:原始像素(YUV)本身是不带 PTS 的,PTS 存在于 AVPacket(压缩包)里。当你解码成 AVFrame 后,FFmpeg 会把 PTS 传递给这个图像。

    • 编码后:当你把拼接后的图像送入编码器,你需要给编码器输出的新包重新分配 PTS。

    • 封装时:当你调用 av_interleaved_write_frame 时,FFmpeg 会根据输出流的 时间基 (Time Base)(比如 90kHz)将你的秒数转换成最终的数值。


3. 为什么你的程序会报错 encode_write_fail

这通常是因为在 阶段 B 出了问题:

  • 你是“搬运工”还是“发货员”?

    • 如果你的代码只是简单地把从摄像头读到的 PTS 丢给推流端,而没有考虑多个摄像头之间的同步或者拼接处理造成的延迟,PTS 就会出现重叠或倒流。

    • 关键: 推流服务器(如 MediaMTX)要求收到的 PTS 必须是严格递增的。如果你给出的单号(PTS)是乱的,发货程序就会报错 fail


4. 总结:数据流转表

数据类型 谁负责生成 存储位置 作用
SPS/PPS 编码器芯片 (RKMPP) 码流头部 / Extradata 告诉解码器如何初始化硬件
IDR 帧 编码器芯片 (RKMPP) 关键帧 NALU 视频流的即时刷新点
DTS FFmpeg 封装层 AVPacket 确定解码器什么时候“拆包”
PTS 你的代码逻辑 AVPacket / AVFrame 确定画面什么时候“上屏”

你的下一步工作: 在代码中打印 pkt->pts。如果发现 pts 的值没有按照固定间隔(例如 30fps 应该是每帧增加 3000 左右,视 Time Base 而定)稳定增长,或者出现了变小的情况,你就找到了 encode_write_fail 的真凶。

idr是指 i帧 p b帧吗

简单来说:IDR 帧属于 I 帧的一种,但它比普通的 I 帧更“绝”。

为了理解它们的关系,我们可以把视频流看作一列火车,每一节车厢就是一帧:

1. I、P、B 帧:视频压缩的三剑客

这是按压缩方式分类的三种基本帧类型:

  • I 帧 (Intra-coded picture,帧内编码帧)

    • 特点:完整的图像。它不参考任何其他帧,自己就能解压出一张图片。

    • 形象理解:像一张独立的 JPEG 照片。

  • P 帧 (Predictive-coded picture,前向预测编码帧)

    • 特点:不完整。它只记录与前一帧相比发生的变化。

    • 形象理解:只记录“动了的地方”,背景没动就不记。

  • B 帧 (Bi-directionally predicted picture,双向预测编码帧)

    • 特点:最省空间。它参考前面后面的帧来推算自己。

    • 形象理解:根据过去和未来来猜现在的样子

Logo

一站式 AI 云服务平台

更多推荐