In this example, we have two pipelines, one pipeline that gets data from a file, decodes the audio stream and sends the audio buffers to appsink, and a second pipeline that gets data from appsrc and pushes them to an audio sink. Appsink from the first pipeline is linked with appsrc from the second pipeline in our code, by listening to appsink's newBuffer() signal, getting the buffer and pushing it to appsrc with the pushBuffer() method. The result is a choppy audio player.
#include <iostream>
#include <QCoreApplication>
#include <QGlib/Error>
#include <QGlib/Connect>
#include <QGst/Init>
#include <QGst/Bus>
#include <QGst/Pipeline>
#include <QGst/Parse>
#include <QGst/Message>
#include <QGst/Utils/ApplicationSink>
#include <QGst/Utils/ApplicationSource>
{
public:
protected:
{
m_src->endOfStream();
}
{
m_src->pushBuffer(sample->buffer());
return QGst::FlowOk;
}
private:
};
class Player : public QCoreApplication
{
public:
Player(int argc, char **argv);
~Player();
private:
private:
MySink m_sink;
};
Player::Player(int argc, char **argv)
: QCoreApplication(argc, argv), m_sink(&m_src)
{
if (argc <= 1) {
std::cerr << "Usage: " << argv[0] << " <audio_file>" << std::endl;
std::exit(1);
}
const char *caps = "audio/x-raw, format=(string)S16LE, channels=(int)1,"
" rate=(int)44100, layout=(string)interleaved";
QString pipe1Descr = QString("filesrc location=\"%1\" ! "
"decodebin ! "
"audioconvert ! "
"audioresample ! "
"appsink name=\"mysink\" caps=\"%2\"").arg(argv[1], caps);
m_sink.setElement(pipeline1->getElementByName("mysink"));
QGlib::connect(pipeline1->bus(),
"message::error",
this, &Player::onBusMessage);
pipeline1->bus()->addSignalWatch();
QString pipe2Descr = QString("appsrc name=\"mysrc\" caps=\"%1\" is-live=true format=3 ! "
"autoaudiosink").arg(caps);
m_src.setElement(pipeline2->getElementByName("mysrc"));
QGlib::connect(pipeline2->bus(),
"message",
this, &Player::onBusMessage);
pipeline2->bus()->addSignalWatch();
pipeline1->setState(QGst::StatePlaying);
pipeline2->setState(QGst::StatePlaying);
}
Player::~Player()
{
pipeline1->setState(QGst::StateNull);
pipeline2->setState(QGst::StateNull);
}
{
switch (message->type()) {
case QGst::MessageEos:
quit();
break;
case QGst::MessageError:
break;
default:
break;
}
}
int main(int argc, char **argv)
{
Player p(argc, argv);
return p.exec();
}
Smart pointer class for working with wrapper classes that support reference counting.
RefPointer< X > staticCast() const
RefPointer< X > dynamicCast() const
Wrapper class for messages of type QGst::MessageError.
Wrapper class for GstPipeline.
Helper class for using a GstAppSink.
virtual FlowReturn newSample()
Helper class for using a GstAppSrc.
bool connect(void *instance, const char *detailedSignal, T *receiver, R(T::*slot)(Args...), ConnectFlags flags=0)
ElementPtr launch(const char *description)