使用GstApp.AppSrc循环播放Gst.Sample列表 [英] Looping playback of a list of Gst.Sample with GstApp.AppSrc

查看:334
本文介绍了使用GstApp.AppSrc循环播放Gst.Sample列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to write a simple music player using GStreamer. I want to play any arbitrary music file ABS_FILE_PATH, store the samples for other purposes and later loop over these indefinitely, once the original end of stream is reached.

现在播放音乐的效果很好,直到播放完曲目的最后一个样本后不久.在大多数情况下,只有寂静,但有时会有一两个可听见的样本表明轨道刚刚开始播放.终端输出也是如此.它表明,在循环开始后的几个样本中,need-data信号的发送频率比以前更高.

Now playing the music works fine until short after the last sample of the track was played. Most of the time there's just silence, but sometimes there are one or two audible samples indicating, that the track just started playing again. The same holds for the terminal output. It shows, that a few samples after looping was started, the need-data signal is sent more frequently than before.

我已经使用fakesink来转储数据,这似乎工作得很好.数据像预期的那样被循环.

I've used fakesink for dumping the data, which seemed to work perfectly fine. The data was just looped, like it was intended.

那么这里会发生什么呢?为什么样本不播放第二(第三,第四,...)时间?我的想法用光了.

So what happens here? Why don't the samples play a second (third, fourth, ...) time? I've run out of ideas.

下面,我添加了一个最小的示例,说明我在没有任何UI的情况下所做的事情,但存在相同的问题:

Following I added a minimal example of what I'm doing without any UI, but with the same problem:

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

推荐答案

的评论蒂亚戈斯(Thiagoss).

I've found a working solution with help of the comment of thiagoss.

GstBuffer结构文档列出与时间戳相关的所有字段

The GstBuffer struct documentation lists all the fields relevant for the timestamp

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

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

where the presentation timestamp pts is the relevant value. Setting it to Gst.CLOCK_TIME_NONE before using the sample for a second time will solve the issue:

# 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

这篇关于使用GstApp.AppSrc循环播放Gst.Sample列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆