GStreamer AppSrc管道关闭时丢帧问题:推送N个缓冲仅生成N-1帧
解决GStreamer 1.14.5 appsrc推送帧后文件丢失最后一帧的问题
核心原因
这种偶发丢帧,大概率是EOS事件发送过早——最后一帧缓冲还没被编码器/复用器处理完成,管道就被EOS强制终止了。两种发送EOS的方式没解决问题,本质是没确保所有缓冲都被完全处理。
具体解决步骤
逐帧确认推送成功后再继续
每次调用appsrc.push_buffer()后,必须检查返回值是否为Gst.FlowReturn.OK,确认当前缓冲被成功接收后,再推送下一个。不能批量推完所有缓冲立刻发EOS,必须等最后一帧的推送确认返回后再触发EOS。示例代码:
for buffer in frame_buffers: ret = self._appsrc.push_buffer(buffer) if ret != Gst.FlowReturn.OK: # 按需处理推送失败场景 break # 所有缓冲推送完成后,再发送EOS self._appsrc.send_event(Gst.Event.new_eos())用appsrc专属方法触发结束流程
GStreamer的appsrc自带end_of_stream()方法,比手动发送EOS事件更规范,在1.14.5版本中兼容性更好:# 所有缓冲推送完成后调用 self._appsrc.end_of_stream()等待管道完成EOS处理再停止
发送EOS后不能立刻停管道,要等总线的EOS信号确认,确保编码器和复用器完全处理完所有帧并写入文件:bus = self._pipeline.get_bus() # 阻塞等待EOS信号 msg = bus.timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS) # 收到EOS后再重置管道状态 self._pipeline.set_state(Gst.State.NULL)检查复用器配置
如果用mp4mux这类容器复用器,需设置streamable=True适配流式写入场景,避免因容器索引未完成导致最后一帧丢失:muxer = Gst.ElementFactory.make("mp4mux", "muxer") muxer.set_property("streamable", True)
内容的提问来源于stack exchange,提问作者mallwright
相关产品推荐
相关产品推荐

