【问题标题】:Looping playback of a list of Gst.Sample with GstApp.AppSrc使用 GstApp.AppSrc 循环播放 Gst.Sample 列表
【发布时间】:2015-06-30 21:04:16
【问题描述】:

我正在尝试使用 GStreamer 编写一个简单的音乐播放器。我想播放任意音乐文件ABS_FILE_PATH,将样本存储用于其他目的,然后在到达流的原始结尾后无限期循环。

现在播放音乐可以正常播放,直到播放完曲目的最后一个样本后不久。大多数时候只有沉默,但有时会有一两个声音样本表明曲目刚刚开始播放。这同样适用于终端输出。它表明,在循环开始后的几个样本中,need-data 信号的发送比以前更频繁。

我使用fakesink 转储数据,这似乎工作得很好。数据只是按预期循环。

那么这里会发生什么?为什么样本不播放第二次(第三次,第四次,...)?我的想法已经用完了。

下面我添加了一个没有任何 UI 的最小示例,但存在同样的问题:

import itertools, signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
from gi.repository import Gst, GstApp, Gtk
Gst.init(None)

# read samples with Gst.AppSink from a playbin
playbin = Gst.ElementFactory.make("playbin")
playbin.props.uri = "file://" + ABS_FILE_PATH # only works with absolute paths
playbin.props.audio_sink = GstApp.AppSink(sync=False, emit_signals=True)
playbin.set_state(Gst.State.PLAYING)

# loop over all samples
def samples(app_sink):
    samples = []
    sample = app_sink.pull_sample()
    while sample:
        yield sample
        samples.append(sample)
        sample = app_sink.pull_sample()
    print('looping')
    for sample in itertools.cycle(samples):
        yield sample

# write samples with Gst.AppSrc
def need_data(appsrc, length, samples):
    print('sample')
    sample = next(samples)
    appsrc.set_caps(sample.get_caps())
    appsrc.push_buffer(sample.get_buffer())
src = GstApp.AppSrc(format=Gst.Format.TIME, emit_signals=True)
src.connect('need-data', need_data, samples(playbin.props.audio_sink))

# to the autoaudiosink or just a fakesink
sink = Gst.ElementFactory.make("autoaudiosink")
#sink = Gst.ElementFactory.make("fakesink")
#sink.props.dump = True # dump contents of fakesink

# playback
play = Gst.Pipeline()
play.add(src)
play.add(sink)
src.link(sink)
play.set_state(Gst.State.PLAYING)

Gtk.main()

gst-plugins-base: 1.4.4

【问题讨论】:

  • 您的样本可能会循环时间戳,并且在第二次运行时,当它们返回 0 时,它们会因为迟到而被丢弃。也许您想在 appsrc 中设置 do-timestamp 让它为您添加时间戳,或者您可以累积时间戳/持续时间并在推送之前将它们设置为样本。
  • 演示时间戳是问题所在。谢谢。

标签: python audio-player gstreamer


【解决方案1】:

thiagosscomment 的帮助下,我找到了一个可行的解决方案。

The GstBuffer struct documentation 列出与时间戳相关的所有字段

struct GstBuffer {
  [...]
  /* timestamp */
  GstClockTime           pts;
  GstClockTime           dts;
  GstClockTime           duration;
  [...]
};

其中演示时间戳pts 是相关值。在第二次使用示例之前将其设置为Gst.CLOCK_TIME_NONE 将解决问题:

# loop over all samples
def samples(app_sink):
    samples = []
    sample = app_sink.pull_sample()
    while sample:
        yield sample
        sample.get_buffer().pts = Gst.CLOCK_TIME_NONE #unset the pts
        samples.append(sample)
        sample = app_sink.pull_sample()
    print('looping')
    for sample in itertools.cycle(samples):
        yield sample

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2017-10-17
    • 2016-05-01
    • 2020-03-09
    相关资源
    最近更新 更多