Hi all, <br><br>I'm using QtGStreamer-0.10 to play a mp3 file and I'm having difficulties finding out why the resulting sound is so horrible. I wrote the smallest application possible to reproduce the problem I'm facing.<br>
<br>I'm working on a "audio mixer" component that allows you to have multiple audio players instantiated and running. It's job is to mix all audio received by the players and chose to do this task myself because the soundcard I have is terrible and can't deal with 8, 9 audio players simultaneously. So I'm hoping to make it's job easier by sending it only one audio stream.<br>
<br>Let's jump into the code! The application below sets up 2 pipelines: the first named "_ms_pipeline" (as in master pipeline), and its responsible for mixing the audio using only 2 elements: an ADDER linked to AUTOAUDIOSINK. <br>
<br>The second pipeline, named only "pipeline", loads the file from the disk through FILESRC, decodes it, does some stuff using the following elements: APPSRC > VOLUME > AUDIOCONVERT > AUDIORESAMPLE > CAPSFILTER.<br>
<br>At the end I connect the src pad of CAPSFILTER to a sink pad of the ADDER, then set the state of the pipelines to QGst::StatePlaying to start playing the audio.<br><br>The result is awful.<br><br>#include <QtGui/QApplication><br>
<br>#include <QList><br>#include <QPointer><br>#include <QObject><br><br>#include <QGlib/Error><br>#include <QGlib/Connect><br>#include <QGst/Init><br>#include <QGst/Bus><br>#include <QGst/Pipeline><br>
#include <QGst/Parse><br>#include <QGst/Message><br>#include <QGst/Utils/ApplicationSink><br>#include <QGst/Utils/ApplicationSource><br>#include <QGst/ElementFactory><br>#include <QGst/Element><br>
#include <QGst/Pad><br>#include <QGst/Bin><br><br>#include <iostream><br><br>QGst::PipelinePtr _ms_pipeline;<br>QGst::ElementPtr _ms_adder;<br>QGst::ElementPtr _ms_output;<br><br>QGst::ElementPtr appsink;<br>
<br>class MySink : public QGst::Utils::ApplicationSink<br>{<br>public:<br> MySink(QGst::Utils::ApplicationSource *src)<br> : QGst::Utils::ApplicationSink(), m_src(src) {}<br><br>protected:<br> virtual void eos()<br>
{<br> m_src->endOfStream();<br> }<br><br> virtual QGst::FlowReturn newBuffer()<br> {<br> m_src->pushBuffer(pullBuffer());<br> return QGst::FlowOk;<br> }<br><br>private:<br> QGst::Utils::ApplicationSource *m_src;<br>
};<br><br><br>class Player : QObject<br>{<br>public:<br> Player(const char* filename);<br> ~Player() {};<br><br> MySink m_sink; <br> QGst::Utils::ApplicationSource m_src;<br><br> void onNewDecodedPad(QGst::PadPtr pad) <br>
{<br> std::cout << "Player::onNewDecodePad\n";<br> QGst::CapsPtr caps = pad->caps();<br> QGst::StructurePtr structure = caps->internalStructure(0);<br> if (structure->name().contains("audio/x-raw")) <br>
std::cout << "Player::onNewDecodePad audio/x-raw\n";<br><br> QGst::PadPtr saidaDecoder = appsink->getStaticPad("sink");<br> if (pad->link(saidaDecoder) != QGst::PadLinkOk)<br>
std::cout << "Player::onNewDecodePad: Failed link !!!\n";<br><br> }<br>};<br><br><br>int main(int argc, char *argv[])<br>{<br> if (argc < 2) <br> {<br> std::cout << "Usage: qtplayer <file.mp3>\n";<br>
return -1;<br> }<br><br> QApplication app(argc, argv);<br><br> Player player(argv[1]);<br><br> return app.exec();<br>}<br><br><br>Player::Player(const char* filename)<br>: m_sink(&m_src)<br>{<br> QGst::init(0, NULL);<br>
<br> // Master pipeline setup<br><br> _ms_pipeline = QGst::Pipeline::create("mypipe");<br> if (!_ms_pipeline)<br> {<br> qDebug() << "MasterSink: Failed creating pipeline !!!";<br>
return;<br> }<br> _ms_pipeline->setState(QGst::StateNull);<br><br> _ms_adder = QGst::ElementFactory::make("adder","audiomixer");<br> _ms_pipeline->add(_ms_adder);<br><br> _ms_output = QGst::ElementFactory::make("autoaudiosink","audio_out");<br>
_ms_pipeline->add(_ms_output);<br><br> if (!_ms_adder->link(_ms_output))<br> {<br> qDebug() << "MasterSink: Failed linking to _output !!!";<br> return;<br> }<br><br> _ms_pipeline->setState(QGst::StateReady);<br>
std::cout << "_ms_pipeline: StateReady\n";<br><br><br> // This 2nd pipeline loads the file, decodes it and sends the audio stream to the master pipeline <br><br> QGst::PipelinePtr pipeline = QGst::Pipeline::create();<br>
<br> QGst::ElementPtr filesrc = QGst::ElementFactory::make("filesrc");<br> filesrc->setProperty("location", filename);<br> pipeline->add(filesrc); <br><br> QGst::BinPtr decodebin = QGst::ElementFactory::make("decodebin2").dynamicCast<QGst::Bin>();<br>
pipeline->add(decodebin);<br> if (!filesrc->link(decodebin))<br> {<br> qDebug() << "Failed: filesrc > decodebin !!!";<br> return;<br> }<br><br> appsink = QGst::ElementFactory::make("appsink");<br>
pipeline->add(appsink);<br><br> m_sink.setElement(appsink);<br><br> QGst::ElementPtr appsrc = QGst::ElementFactory::make("appsrc");<br> m_src.setElement(appsrc);<br> m_src.setFormat(QGst::FormatDefault);<br>
<br> _ms_pipeline->add(appsrc);<br><br> QGst::ElementPtr vol = QGst::ElementFactory::make("volume");<br> vol->setProperty("volume", 0.7);<br> QGst::ElementPtr convert = QGst::ElementFactory::make("audioconvert");<br>
QGst::ElementPtr resample = QGst::ElementFactory::make("audioresample");<br><br> QGst::ElementPtr filtercaps = QGst::ElementFactory::make("capsfilter");<br> filtercaps->setProperty("caps", QGst::Caps::fromString("audio/x-raw-int, endianness=(int)1234, channels=(int)1, width=(int)16, depth=(int)16, signed=(boolean)true, rate=(int)11025"));<br>
<br> _ms_pipeline->add(vol);<br> _ms_pipeline->add(convert);<br> _ms_pipeline->add(resample);<br> _ms_pipeline->add(filtercaps);<br><br> if (!appsrc->link(vol))<br> {<br> qDebug() << "Failed: appsrc > vol !!!";<br>
return;<br> }<br><br> if (!vol->link(convert))<br> {<br> qDebug() << "Failed: filesrc > decodebin !!!";<br> return;<br> }<br><br> if (!convert->link(resample))<br>
{<br> qDebug() << "Failed: filesrc > decodebin !!!";<br> return;<br> }<br><br> if (!resample->link(filtercaps))<br> {<br> qDebug() << "Failed: filesrc > decodebin !!!";<br>
return;<br> }<br><br> QGst::PadPtr sinkpad = _ms_adder->getRequestPad("sink%d");<br> if (!sinkpad)<br> {<br> qDebug() << "Failed: sinkpad !!!";<br> return;<br>
}<br><br> QGst::PadPtr saidaConverters = filtercaps->getStaticPad("src");<br> if (saidaConverters->link(sinkpad) != QGst::PadLinkOk)<br> {<br> qDebug() << "Failed: saida > sinkpad !!!";<br>
return;<br> }<br><br> QGlib::connect(decodebin, "pad-added", this, &Player::onNewDecodedPad);<br><br> pipeline->setState(QGst::StatePlaying);<br> std::cout << "pipeline: StatePlaying\n";<br>
<br> QGst::State state;<br> pipeline->getState(&state, NULL, 0);<br> std::cout << "pipeline: state is " << state << " while playing would be: " << QGst::StatePlaying << "\n";<br>
<br><br> QGst::State ms_state;<br> _ms_pipeline->getState(&ms_state, NULL, 0);<br> if (ms_state != QGst::StatePlaying)<br> {<br> std::cout << "_ms_pipeline: StatePlaying *AGAIN* was: " << ms_state << "\n";<br>
_ms_pipeline->setState(QGst::StateNull);<br> _ms_pipeline->setState(QGst::StatePlaying);<br> }<br><br> _ms_pipeline->getState(&ms_state, NULL, 0);<br> std::cout << "_ms_pipeline: state is " << ms_state << "\n";<br>
}<br>