void GStreamerPipeline::decodedPadAdded( QGst::ElementPtr decoder, QGst::PadPtr pad ) { QString caps = pad->currentCaps()->toString(); qDebug() << "Decoded pad found, caps: " << caps; QGst::PadPtr target; if( caps.startsWith("audio/x-raw") ) { target = mPlaySink->getRequestPad( "audio_raw_sink" ); } else if( caps.startsWith("video/x-raw") ) { target = mPlaySink->getRequestPad( "video_raw_sink" ); } else if( caps.startsWith("text/x-raw") ) { target = mPlaySink->getRequestPad( "text_sink" ); } if( target ) { mPadsFound++; QGst::PadPtr multi_sink, multi_src; multi_sink = mQueue->getRequestPad( QString("sink_%1").arg(mPadsFound).toStdString().c_str() ); multi_src = mQueue->getStaticPad( QString("src_%1").arg(mPadsFound).toStdString().c_str() ); pad->link( multi_sink ); multi_src->link( target ); } }
void VideoSinkController::releaseSrcPad(const QGst::PadPtr & pad) { QGst::PadPtr teeSrcPad = m_pads.take(pad); Q_ASSERT(!teeSrcPad.isNull()); m_bin->removePad(pad); m_tee->releaseRequestPad(teeSrcPad); }
QGst::PadPtr VideoSinkController::requestSrcPad() { QString newPadName = QStringLiteral("src%1").arg(m_padNameCounter); m_padNameCounter++; QGst::PadPtr teeSrcPad = m_tee->getRequestPad("src_%u"); QGst::PadPtr ghostSrcPad = QGst::GhostPad::create(teeSrcPad, newPadName.toLatin1()); ghostSrcPad->setActive(true); m_bin->addPad(ghostSrcPad); m_pads.insert(ghostSrcPad, teeSrcPad); return ghostSrcPad; }
void VideoSinkController::linkVideoSink(const QGst::ElementPtr & sink) { //initFromStreamingThread() is always called before the user knows //anything about this content's src pad, so nobody can possibly link //a video sink before the bin is created. Q_ASSERT(m_bin); qCDebug(LIBKTPCALL); QGst::PadPtr srcPad = m_tee->getRequestPad("src_%u"); m_videoSinkBin = new VideoSinkBin(sink); m_bin->add(m_videoSinkBin->bin()); m_videoSinkBin->bin()->syncStateWithParent(); srcPad->link(m_videoSinkBin->bin()->getStaticPad("sink")); }
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")); }
void VideoSinkController::unlinkVideoSink() { //lock because releaseFromStreamingThread() is always called before the user //knows about the removal of the content's src pad and may try to unlink //externally while releaseFromStreamingThread() is running. QMutexLocker l(&m_videoSinkMutex); if (m_videoSinkBin) { qCDebug(LIBKTPCALL); QGst::PadPtr sinkPad = m_videoSinkBin->bin()->getStaticPad("sink"); QGst::PadPtr srcPad = sinkPad->peer(); srcPad->unlink(sinkPad); m_videoSinkBin->bin()->setState(QGst::StateNull); m_bin->remove(m_videoSinkBin->bin()); delete m_videoSinkBin; m_videoSinkBin = NULL; m_tee->releaseRequestPad(srcPad); } }
void AudioSinkController::initFromStreamingThread(const QGst::PadPtr & srcPad, const QGst::PipelinePtr & pipeline) { m_bin = QGst::Bin::fromDescription( "volume ! " "audioconvert ! " "audioresample ! " "level" ); pipeline->add(m_bin); m_bin->syncStateWithParent(); m_bin->getStaticPad("src")->link(m_adderRequestPad); srcPad->link(m_bin->getStaticPad("sink")); }
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; }
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); }