使用GstApp.AppSrc循环播放Gst.Sample列表

时间:2015-06-10 18:54:18

标签: python audio-player gstreamer

我正在尝试使用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

1 个答案:

答案 0 :(得分:0)

我在[{3}}的comment的帮助下找到了一个可行的解决方案。

thiagoss列出与时间戳相关的所有字段

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