解码带PTS的H264 PES时libav输出视频卡顿问题排查
卡顿问题排查步骤
第一步:确认AVPacket的时间戳字段赋值正确性
- 不要只赋值
AVPacket.pts,H264存在B帧时必须同时正确赋值AVPacket.dts,如果你的源流没有B帧,也要保证dts和pts值一致,避免解码器内部时间戳计算紊乱 - 确认时间戳的时间基是否匹配:你从PES拿到的PTS默认是1/90000的时间基,必须显式将对应
AVStream.time_base设置为(AVRational){1, 90000},或者将PTS/DTS的值转换成解码器对应的时间基后再赋值,不要直接跨时间基赋值 - 逐包打印时间戳:每次给AVPacket赋值后,打印
pkt.pts、pkt.dts、pkt.duration三个字段,确认没有重复、跳变、回退的情况,25fps的流每帧的duration在1/90000时间基下固定为3600,检查是否符合预期
第二步:检查解码器输出帧的时间戳处理逻辑
- 解码得到AVFrame后,不要直接使用原始的
pts值,必须调用av_rescale_q()将帧的时间戳从解码器时间基转换为你最终输出容器/渲染器的时间基,转换时要严格对应两端的time_base参数,避免时间精度丢失 - 如果
best_effort_timestamp出现跳变,说明你输入给解码器的AVPacket的dts序列存在异常,优先回查送包的时间戳逻辑 - 确认你输出/渲染时的帧间隔计算是否正确:不要依赖固定25fps的间隔硬做延时,必须按相邻两帧的pts差值做同步,固定帧率假设在时间戳有微小偏差时就会出现卡顿
- 如果你是输出到文件,检查复用器的
AVCodecContext.time_base是否设置正确,不要和输入流的时间基混淆,建议复用器的视频时间基设置为(AVRational){1, 25}或者和输入流一致
第三步:解码器配置排查
- 确认解码器打开时没有跳过必要参数:必须给
AVCodecContext的width、height、pix_fmt、extradata、extradata_size赋值正确,其中H264的extradata是SPS/PPS数据,缺失的话解码器虽然可能解码成功,但会出现帧缓存逻辑异常 - 检查是否开启了不必要的解码缓存:如果你的流是低延迟实时流,要设置
AVCodecContext.flags |= AV_CODEC_FLAG_LOW_DELAY,关闭解码器的多帧缓存,避免帧累积导致的卡顿 - 确认送包逻辑没有丢包或者乱序:每次送包给
avcodec_send_packet()后要检查返回值,返回AVERROR(EAGAIN)时要先把已解码的帧全部用avcodec_receive_frame()收完再送下一个包,不要直接丢包
第四步:快速验证方法
如果上面的排查都没发现问题,可以做对比测试:
- 将你解复用得到的H264裸流直接写入
.264文件,用ffmpeg命令行转封装成mp4:ffmpeg -r 25 -i test.264 -c copy out.mp4,播放out.mp4看是否卡顿,如果不卡顿说明你的解复用输出的裸流是正常的,问题出在你后续的解码/时间戳处理逻辑 - 直接用ffmpeg的默认解复用器解复用你的源文件,和你自定义解复用器输出的AVPacket的pts、dts、duration字段做逐包对比,就能快速定位时间戳赋值的差异点
内容的提问来源于stack exchange,提问作者refunse
相关产品推荐
相关产品推荐

