QGst::BinPtr GstExporter::createDecoder(const int i) { qDebug() << "createDecoder start, i: " << i; char* decArray = nameWithIndex("decoder", i); QGst::BinPtr decoderBin; try { decoderBin = QGst::Bin::create(decArray); QGst::ElementPtr parser = QGst::ElementFactory::make("h264parse"); QGst::ElementPtr decoder; if (usesOmx) { decoder = QGst::ElementFactory::make("omxh264dec"); } else { decoder = QGst::ElementFactory::make("avdec_h264"); } decoderBin->add(parser, decoder); parser->link(decoder); QGst::PadPtr parserSinkPad = parser->getStaticPad("sink"); QGst::PadPtr decoderSrcPad = decoder->getStaticPad("src"); // Add Ghostpads for abstraction decoderBin->addPad(QGst::GhostPad::create(parserSinkPad, "sink")); decoderBin->addPad(QGst::GhostPad::create(decoderSrcPad, "src")); } catch (const QGlib::Error& error) { qCritical() << "Failed to create a decoder:" << error; return QGst::BinPtr(); } return decoderBin; }
void UriHandlerTest::makeTest() { QVERIFY(QGst::UriHandler::protocolIsSupported(QGst::UriSrc, "file")); QGst::ElementPtr e = QGst::UriHandler::makeFromUri(QGst::UriSrc, QUrl::fromLocalFile("/bin/sh")); QVERIFY(!e.isNull()); QGst::UriHandlerPtr u = e.dynamicCast<QGst::UriHandler>(); QVERIFY(!u.isNull()); QCOMPARE(u->uri(), QUrl::fromLocalFile("/bin/sh")); }
void RefPointerTest::cppWrappersTest() { QGst::ElementPtr e = QGst::ElementFactory::make("playbin"); QVERIFY(!e.isNull()); { QGst::PipelinePtr pipeline = e.dynamicCast<QGst::Pipeline>(); QVERIFY(!pipeline.isNull()); //the C++ wrappers must be the same QCOMPARE(static_cast<QGlib::RefCountedObject*>(pipeline.operator->()), static_cast<QGlib::RefCountedObject*>(e.operator->())); } { QGst::ChildProxyPtr proxy = e.dynamicCast<QGst::ChildProxy>(); QVERIFY(!proxy.isNull()); //the C++ wrappers must be the same QCOMPARE(static_cast<QGlib::RefCountedObject*>(proxy.operator->()), static_cast<QGlib::RefCountedObject*>(e.operator->())); } { //new wrap() should give the same C++ instance GstElement *gobj = e; QGst::ElementPtr e2 = QGst::ElementPtr::wrap(gobj); QCOMPARE(static_cast<QGlib::RefCountedObject*>(e2.operator->()), static_cast<QGlib::RefCountedObject*>(e.operator->())); } { QGst::StreamVolumePtr sv = e.dynamicCast<QGst::StreamVolume>(); QVERIFY(!sv.isNull()); //now the C++ wrapper must not be the same, since Pipeline does not inherit StreamVolume QVERIFY(static_cast<QGlib::RefCountedObject*>(sv.operator->()) != static_cast<QGlib::RefCountedObject*>(e.operator->())); } { QGst::MessagePtr msg = QGst::ApplicationMessage::create(e); QGst::MessagePtr msg2 = msg; QCOMPARE(static_cast<QGlib::RefCountedObject*>(msg.operator->()), static_cast<QGlib::RefCountedObject*>(msg2.operator->())); QVERIFY(msg2 == msg); QGst::MessagePtr msg3 = QGst::MessagePtr::wrap(msg2); QVERIFY(static_cast<QGlib::RefCountedObject*>(msg3.operator->()) != static_cast<QGlib::RefCountedObject*>(msg2.operator->())); QVERIFY(msg3 == msg2); } }
const QString GstRecorder::recordLocally() { QGst::BinPtr videoSrcBin = createVideoSrcBin(); //QGst::BinPtr audioSrcBin = createAudioSrcBin(); //QGst::ElementPtr mux = QGst::ElementFactory::make("mp4mux"); QGst::BinPtr mux = createVideoMuxBin(); QGst::ElementPtr sink = QGst::ElementFactory::make("filesink"); QString currentTime = QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss"); const QString filename = QDir::current().absoluteFilePath( currentTime + "-device-" + QString::number(deviceNumber) + ".mp4"); qDebug() << "GstRecorder: writing to:" << filename; sink->setProperty("location", filename); if (!videoSrcBin || !sink) { qDebug() << "Error. One or more elements could not be created."; return ""; } if (m_pipeline) { qDebug() << "Another Recording was not started. Already one in progress"; return ""; } m_pipeline = QGst::Pipeline::create(); //m_pipeline->add(videoSrcBin, audioSrcBin, mux, sink); m_pipeline->add(videoSrcBin, mux, sink); //QGst::PadPtr videoPad = mux->getRequestPad("video_%u"); //QGst::PadPtr audioPad = mux->getRequestPad("audio_%u"); //videoSrcBin->getStaticPad("src")->link(videoPad); //audioSrcBin->getStaticPad("src")->link(audioPad); videoSrcBin->link(mux); mux->link(sink); m_pipeline->bus()->addSignalWatch(); QGlib::connect(m_pipeline->bus(), "message", this, &GstRecorder::onBusMessage); m_pipeline->setState(QGst::StatePlaying); return filename; }
QGst::BinPtr QtGStreamerCaptureBackend::createAudioSrcBin() { QGst::BinPtr audioBin; try { audioBin = QGst::Bin::fromDescription("autoaudiosrc name=\"audiosrc\" ! audioconvert ! " "audioresample ! audiorate ! vorbisenc name=enc quality=0.6 ! queue"); } catch (const QGlib::Error &error) { qCritical() << "Failed to create audio source bin:" << error; return QGst::BinPtr(); } QGst::ElementPtr src = audioBin->getElementByName("audiosrc"); //autoaudiosrc creates the actual source in the READY state src->setState(QGst::StateReady); return audioBin; }
void App::startListen(QGst::PipelinePtr pipe, int port) { QGst::ElementPtr rtcpudpsink = QGst::ElementFactory::make("udpsrc"); rtcpudpsink->setProperty("host", "127.0.0.1"); // TODO settings rtcpudpsink->setProperty("port", port); // source // rtcpudpsink->setProperty("sync", false); // rtcpudpsink->setProperty("async", false); rtcpudpsink->setProperty("caps", QGst::Caps::fromString("application/x-rtp,media=(string)audio, clock-rate=(int)8000, encoding-name=(string)SPEEX,payload=(int)110")); pipe->add(rtcpudpsink); QGst::ElementPtr bin; try { bin = QGst::Bin::fromDescription( "rtpspeexdepay ! speexdec ! audioconvert" ); } catch (const QGlib::Error & error) { qCritical() << error; qFatal("One ore more required elements are missing. Aborting..."); } pipe->add(bin); rtcpudpsink->link(bin); volumeIn = QGst::ElementFactory::make("volume"); // TODO settings pipe->add(volumeIn); bin->link(volumeIn); QGst::ElementPtr audioSynk = QGst::ElementFactory::make("autoaudiosink"); pipe->add(audioSynk); volumeIn->link(audioSynk); }
void GstExporter::callbackNewPad(const QGst::ElementPtr& sender, const QGst::PadPtr& pad) { QString padName = pad->name(); qDebug() << "new pad created: " << padName; QString demuxerName = sender->name(); QRegExp rx("(\\d+)"); rx.indexIn(demuxerName); quint16 i = rx.cap(1).toInt(); QString decoderQString = "decoder" + QString::number(i); QByteArray decoderBa = decoderQString.toLocal8Bit(); char* decoderName = decoderBa.data(); QGst::ElementPtr decoder = m_pipeline->getElementByName(decoderName); pad->link(decoder->getStaticPad("sink")); }
QGst::BinPtr GstExporter::createFileSrcBin(const QString path, const int i) { qDebug() << "creating filesrc bin, path: " << path << " i: " << i; QGst::BinPtr videoBin; QDir current = QDir::current(); current.cd("recordings"); const QString fullPath = current.absoluteFilePath(path); try { char* srcname = nameWithIndex("file", i); QGst::ElementPtr src = QGst::ElementFactory::make("filesrc", srcname); src->setProperty("location", fullPath); char* demuxName = nameWithIndex("demux", i); QGst::ElementPtr demuxer = QGst::ElementFactory::make("qtdemux", demuxName); QGst::BinPtr decoder = createDecoder(i); QGst::ElementPtr scale = QGst::ElementFactory::make("videoscale"); QGst::ElementPtr capsfilter = createCapsFilter(elementWidthPx, elementHeightPx); char* binname = nameWithIndex("filebin", i); videoBin = QGst::Bin::create(binname); videoBin->add(src, demuxer, decoder, capsfilter, scale); src->link(demuxer); videoBin->linkMany(decoder, scale, capsfilter); qDebug() << "filesrc bin: Added and linked all elements"; QGst::PadPtr filterPadSrc = capsfilter->getStaticPad("src"); videoBin->addPad(QGst::GhostPad::create(filterPadSrc, "src")); qDebug() << "filesrc bin: Added Ghostpad to the bin"; QGlib::connect(demuxer, "pad-added", this, &GstExporter::callbackNewPad, QGlib::PassSender); } catch (const QGlib::Error& error) { qCritical() << "Failed to create a filesource:" << error; return QGst::BinPtr(); } return videoBin; }
QGst::BinPtr GstRecorder::createAudioSrcBin() { QGst::BinPtr audioBin; qDebug() << "creating Audio Source bin."; try { audioBin = QGst::Bin::fromDescription( "autoaudiosrc name=\"audiosrc\" ! audioconvert ! " "audioresample ! audiorate ! speexenc ! queue"); } catch (const QGlib::Error &error) { qCritical() << "Failed to create audioSrcBin: " << error; return QGst::BinPtr(); } QGst::ElementPtr src = audioBin->getElementByName("audiosrc"); //autoaudiosrc creates the actual source in the READY state src->setState(QGst::StateReady); return audioBin; }
QGst::BinPtr GstExporter::createVideoMixer() { qDebug() << "createVideoMixer start"; QGst::BinPtr videoMixerBin = QGst::Bin::create(); try { QGst::ElementPtr videoMixer = QGst::ElementFactory::make("videomixer", "mix"); videoMixer->setProperty("background", (int) 1); //black background videoMixerBin->add(videoMixer); int count = 0; // go through every element in the grid for (int i = 0; i < rec_->grid.height; ++i) { for (int j = 0; j < rec_->grid.width; ++j) { VideoFile* current = &rec_->grid.grid[i][j]; if (current->id != 0) { qDebug() << "Working on video[" << i << "][" << j << "] with id: " << current->id; QGst::PadPtr pad = videoMixer->getRequestPad("sink_%u"); pad->setProperty("ypos", i * elementHeightPx); pad->setProperty("xpos", j * elementWidthPx); qDebug() << "Pad created with xpos: " << pad->property("xpos") << ", ypos: " << pad->property("ypos"); QGst::BinPtr filesrc = createFileSrcBin(current->filepath, count); videoMixerBin->add(filesrc); QGst::PadPtr sourcepad = filesrc->getStaticPad("src"); sourcepad->link(pad); ++count; } } } QGst::PadPtr mixSrcPad = videoMixer->getStaticPad("src"); videoMixerBin->addPad(QGst::GhostPad::create(mixSrcPad, "src")); } catch (const QGlib::Error& error) { qDebug() << "Failed to create a videomixer:" << error; return QGst::BinPtr(); } return videoMixerBin; }
QGst::ElementPtr GstExporter::createCapsFilter(const quint16 width, const quint16 height) { qDebug() << "creating capsfilter with width: " << width << ", height: " << height; QGst::ElementPtr capsfilter; try { capsfilter = QGst::ElementFactory::make("capsfilter"); const QGst::CapsPtr caps = QGst::Caps::createSimple("video/x-raw"); caps->setValue("width", (int)width); caps->setValue("height", (int)height); capsfilter->setProperty("caps", caps); } catch (const QGlib::Error& error) { qCritical() << "Failed to create capsfilter: " << error; return QGst::ElementPtr(); } return capsfilter; }
void RefPointerTest::equalityTest() { QGst::BinPtr bin = QGst::Bin::create(); QGst::ElementPtr element = bin; QVERIFY(element == bin); QVERIFY(bin == element); QVERIFY(bin == bin); GstElement *e = element; QVERIFY(e == element); QVERIFY(element == e); QVERIFY(bin == e); QVERIFY(e == bin); e++; QVERIFY(e != element); QVERIFY(element != e); QVERIFY(bin != e); QVERIFY(e != bin); e = NULL; QVERIFY(e != element); QVERIFY(element != e); QVERIFY(bin != e); QVERIFY(e != bin); element.clear(); QVERIFY(element != bin); QVERIFY(bin != element); QVERIFY(e == element); QVERIFY(element == e); bin.clear(); QVERIFY(element == bin); QVERIFY(bin == element); QVERIFY(bin == bin); QVERIFY(bin == e); QVERIFY(e == bin); }
QGst::BinPtr GstRecorder::createVideoSrcBin() { QGst::BinPtr videoBin; try { videoBin = QGst::Bin::create(); QGst::ElementPtr src = QGst::ElementFactory::make("v4l2src"); src->setProperty("device", devicepath); qDebug() << "GstRecorder: v4l2src with device: " << devicepath; QGst::ElementPtr encoder; QGst::ElementPtr capsfilter = createCapsFilter(videoWitdhPx, videoHeightPx, framerate); //QGst::ElementPtr parse = QGst::ElementFactory::make("h264parse"); //QGst::ElementPtr queue = QGst::ElementFactory::make("queue"); if (usesOmx) { encoder = QGst::ElementFactory::make("omxh264enc"); } else { encoder = QGst::ElementFactory::make("x264enc"); qDebug() << "GstRecoder: created x264enc"; } videoBin->add(src, capsfilter, encoder); videoBin->linkMany(src, capsfilter, encoder); qDebug() << "GstRecorder: createVideoSrcBin: added and linked the elements"; QGst::PadPtr encoderSrcPad = encoder->getStaticPad("src"); videoBin->addPad(QGst::GhostPad::create(encoderSrcPad, "src")); } catch (const QGlib::Error &error) { qDebug() << "Failed to create video source bin:" << error; return QGst::BinPtr(); } return videoBin; }
void VideoSinkController::initFromStreamingThread(const QGst::PadPtr & srcPad, const QGst::PipelinePtr & pipeline) { m_bin = QGst::Bin::create(); m_tee = QGst::ElementFactory::make("tee"); QGst::ElementPtr fakesink = QGst::ElementFactory::make("fakesink"); fakesink->setProperty("sync", false); fakesink->setProperty("async", false); fakesink->setProperty("silent", true); fakesink->setProperty("enable-last-sample", false); m_bin->add(m_tee, fakesink); m_tee->getRequestPad("src_%u")->link(fakesink->getStaticPad("sink")); QGst::PadPtr binSinkPad = QGst::GhostPad::create(m_tee->getStaticPad("sink"), "sink"); m_bin->addPad(binSinkPad); pipeline->add(m_bin); m_bin->syncStateWithParent(); srcPad->link(binSinkPad); }
QString GstExporter::exportVideo() { qDebug() << "Starting Videoexport..."; QGst::BinPtr mixer = createVideoMixer(); QGst::BinPtr encoder = createEncoder(); QGst::ElementPtr scale = QGst::ElementFactory::make("videoscale"); QGst::ElementPtr sink = QGst::ElementFactory::make("filesink"); QGst::ElementPtr capsfilter = createCapsFilter(exportWidthPx, exportHeightPx); QString recordingTime = rec_->datetime.toString("yyyy_MM_dd_hh_mm_ss"); qDebug() << "Loaded recodring, recording time: " << rec_->datetime; QDir current = QDir::current(); current.mkdir("exports"); current.cd("exports"); QString filename = current.absoluteFilePath("export-" + recordingTime + ".mp4"); sink->setProperty("location", filename); m_pipeline = QGst::Pipeline::create(); m_pipeline->add(mixer, capsfilter, encoder, scale, sink); m_pipeline->linkMany(mixer, capsfilter, scale, encoder, sink); qDebug() << "GstExporter: pipeline: Added and linked all elements"; m_pipeline->bus()->addSignalWatch(); QGlib::connect(m_pipeline->bus(), "message", this, &GstExporter::onBusMessage); qDebug() << "exportVideo(): Starting pipeline"; m_pipeline->setState(QGst::StatePlaying); timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &GstExporter::progressPercent); timer->start(1000); return current.relativeFilePath(filename); }
void QtGStreamerCaptureBackend::startCapture(const QString &filePath) { // clear pipeline if still existing if (m_pipeline) { qCWarning(LIBSOUND_LOG) << "removing forgotten pipeline"; //send an end-of-stream event to flush metadata and cause an EosMessage to be delivered m_pipeline->sendEvent(QGst::EosEvent::create()); } QGst::BinPtr audioSrcBin = createAudioSrcBin(); QGst::ElementPtr mux = QGst::ElementFactory::make("oggmux"); QGst::ElementPtr sink = QGst::ElementFactory::make("filesink"); if (!audioSrcBin || !mux || !sink) { qCritical() << "One or more elements could not be created. " << "Verify that you have all the necessary element plugins installed."; return; } // set output path sink->setProperty("location", filePath); m_pipeline = QGst::Pipeline::create(); m_pipeline->add(audioSrcBin, mux, sink); //link elements QGst::PadPtr audioPad = mux->getRequestPad("audio_%u"); audioSrcBin->getStaticPad("src")->link(audioPad); mux->link(sink); //connect the bus m_pipeline->bus()->addSignalWatch(); QGlib::connect(m_pipeline->bus(), "message", this, &QtGStreamerCaptureBackend::onBusMessage); m_pipeline->setState(QGst::StatePlaying); }
void GstRecorder::createRtpSink(quint16 port, QString address) { QGst::BinPtr videoSrcBin = createVideoSrcBin(); QGst::ElementPtr rtpbin = QGst::ElementFactory::make("rtpbin"); QGst::ElementPtr h264pay = QGst::ElementFactory::make("rtph264pay"); if (!videoSrcBin || !rtpbin) { qDebug() << "Error. One or more elements could not be created."; return; } m_pipeline = QGst::Pipeline::create(); m_pipeline->add(videoSrcBin, h264pay); videoSrcBin->link(h264pay); m_pipeline->add(rtpbin); // send_rtp_sink_0 is needed as a parameter for rtpbin for the configuration h264pay->link(rtpbin, "send_rtp_sink_0"); QGst::ElementPtr RtpUdpSink = QGst::ElementFactory::make("udpsink"); RtpUdpSink->setProperty("port", (int)port); RtpUdpSink->setProperty("host", address); if (!RtpUdpSink) { qFatal("Failed to create udpsink. Aborting..."); } m_pipeline->add(RtpUdpSink); rtpbin->link("send_rtp_src_0", RtpUdpSink); QGst::ElementPtr RtcpUdpSink = QGst::ElementFactory::make("udpsink"); RtcpUdpSink->setProperty("port", port + 1); RtcpUdpSink->setProperty("host", address); RtcpUdpSink->setProperty("sync", false); // needed for real-time RtcpUdpSink->setProperty("async", false); m_pipeline->add(RtcpUdpSink); rtpbin->link("send_rtcp_src_0", RtcpUdpSink); QGst::ElementPtr RtcpUdpSrc = QGst::ElementFactory::make("udpsrc"); RtcpUdpSrc->setProperty("port", port + 2); m_pipeline->add(RtcpUdpSrc); RtcpUdpSrc->link(rtpbin, "recv_rtcp_sink_0"); // watch the bus m_pipeline->bus()->addSignalWatch(); QGlib::connect(m_pipeline->bus(), "message", this, &GstRecorder::onBusMessage); qDebug() << "Streaming to RTP"; m_pipeline->setState(QGst::StatePlaying); }
void App::startVoice() { rtpbin = QGst::ElementFactory::make("gstrtpbin"); if (!rtpbin) { qFatal("Failed to create gstrtpbin"); } qDebug() << "initn create"; m_pipelineOut->add(rtpbin); //audio content //sending side QGst::ElementPtr audiosrc; try { audiosrc = QGst::Bin::fromDescription( // "alsasrc device=plughw:0 ! queue ! audioconvert ! audiorate ! audio/x-raw-int,rate=8000 " // "! speexenc ! rtpspeexpay" // ); "audiotestsrc ! queue ! audioconvert ! audiorate ! audio/x-raw-int,rate=8000 ! audioconvert" ); // audiosrc = QGst::Bin::fromDescription( // "audiotestsrc ! audioconvert ! level ! audioconvert ! twolame ! rtpmpapay" // ); } catch (const QGlib::Error & error) { qCritical() << error; qFatal("One ore more required elements are missing. Aborting..."); } m_pipelineOut->add(audiosrc); volumeOut = QGst::ElementFactory::make("volume"); m_pipelineOut->add(volumeOut); // TODO settings audiosrc->link(volumeOut); QGst::ElementPtr decoder; try { decoder = QGst::Bin::fromDescription( "speexenc vad=false ! rtpspeexpay" ); } catch (const QGlib::Error & error) { qCritical() << error; qFatal("One ore more required elements are missing. Aborting..."); } m_pipelineOut->add(decoder); volumeOut->link(decoder); decoder->link(rtpbin, "send_rtp_sink_1"); rtpudpsink = QGst::ElementFactory::make("udpsink"); if (!rtpudpsink) { qFatal("Failed to create udpsink. Aborting..."); } rtpudpsink->setProperty("host", "127.0.0.1"); // desttination 192.168.0.102 rtpudpsink->setProperty("port", 5000); // port m_pipelineOut->add(rtpudpsink); rtpbin->link("send_rtp_src_1", rtpudpsink); }