如何等待 x264enc 在流尾编码缓冲帧
Posted
技术标签:
【中文标题】如何等待 x264enc 在流尾编码缓冲帧【英文标题】:How to wait for x264enc to encode buffered frames on end-of-stream 【发布时间】:2019-08-20 14:31:26 【问题描述】:我有一个 Python GStreamer 应用程序,它使用 appsrc 来记录 mp4 文件。
问题在于,尽管为 x264enc 指定了 tune=zerolatency
,但存在延迟,并且在将 eos 发送到管道时会截断输出视频。根据机器的不同,延迟很长,导致输出文件比预期的短得多。
如果我更改管道以将视频保存为 AVI 文件,它不会被截断。不幸的是,生成的文件大约为每分钟 2 GB,而 H.264 为每分钟 12 MB。
这里是 x264enc 管道:
appsrc name=appsrc format=time is-live=true caps=video/x-raw,format=(string)BGR appsrc. ! videoconvert ! x264enc tune=zerolatency ! qtmux ! filesink location=out.mp4
当应用程序完成后,它会向appsrc和管道发送结束消息:
if self._appsrc.emit("end-of-stream") == Gst.FlowReturn.OK:
self._sink_pipeline.send_event(Gst.Event.new_eos())
在 x264enc 处理其缓冲区时,我的应用程序是否可以等待?也许是一条消息?我不在乎需要多长时间才能完成。重要的是推送到appsrc
的所有帧都会写入输出视频文件。
【问题讨论】:
【参考方案1】:实际上,您必须等待该 End-Of-Stream 事件通过管道,然后才能停止它。当所有接收器都收到 End-Of-Stream 时,将向管道的总线发送 End-Of-Stream 消息。
类似这样的:
# <send EOS event>
self._sink_pipeline.get_bus().timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS)
# <stop pipeline>
【讨论】:
【参考方案2】:按照 Florian Zwoch 的回答,下面是一个完整的示例,该示例创建一个视频文件并使用 EOS 信号优雅地终止管道。
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject
from time import sleep
Gst.init(None)
pipe_str = ' videotestsrc name=src do-timestamp=true is-live=true !' \
' x264enc !' \
' h264parse !' \
' matroskamux !' \
' filesink name=f location=test.mp4 '
pipeline = Gst.parse_launch(pipe_str)
bus = pipeline.get_bus()
print("Entering Playing state...")
pipeline.set_state(Gst.State.PLAYING)
sleep(5)
print("Sending an EOS event to the pipeline")
pipeline.send_event(Gst.Event.new_eos())
print("Waiting for the EOS message on the bus")
bus.timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS)
print("Stopping pipeline")
pipeline.set_state(Gst.State.NULL)
注意: 在 Ubuntu 16.04、GStreamer 1.8.3 上测试
【讨论】:
以上是关于如何等待 x264enc 在流尾编码缓冲帧的主要内容,如果未能解决你的问题,请参考以下文章