如何等待 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 在流尾编码缓冲帧的主要内容,如果未能解决你的问题,请参考以下文章

H264和X264究竟有什么区别?

H264编码系列之ffmpeg和x264码率控制分析

x264

H264软编码导致画面切换时不流畅

H264软编码导致画面切换时不流畅

Python-Opencv 在内存缓冲区上写入 x264 视频