PlayerWin::PlayerWin(QWidget *parent) : QWidget(parent) { setMinimumWidth(200); //setCursor(QCursor(Qt::UpArrowCursor)); isFullScreen = false; state = 0; isWideModel = false; mainGLayout = new QGridLayout(this); mainGLayout->setMargin(0); mainGLayout->setSpacing(0); player= new AVPlayer(this); renderer = new GLWidgetRenderer(this); player->setRenderer(renderer); player->setAudioOutput(QtAV::AudioOutputFactory::create(QtAV::AudioOutputId_OpenAL)); QVariantHash opt; opt["probesize"] = 14096; player->setOptionsForFormat(opt); mainGLayout->addWidget(renderer,0,0,1,1); //QImage img("://images/icon.png"); //renderer->setOutAspectRatioMode(VideoRenderer::RendererAspectRatio); // QImage img(5,5,QImage::Format_ARGB32); // img.fill(Qt::black); // renderer->receive(VideoFrame(img)); renderer->setVisible(false); playerMaskLbl = new QLabel; playerMaskLbl->setAlignment(Qt::AlignCenter); playerMaskLbl->setStyleSheet("background-color:rgba(0,0,0,255)"); playerMaskLbl->setPixmap(QPixmap("://images/icon.png")); mainGLayout->addWidget(playerMaskLbl,1,0,1,1); connect(player, SIGNAL(mediaStatusChanged(QtAV::MediaStatus)), this, SLOT(handleMediaStatusChanged(QtAV::MediaStatus))); connect(player, SIGNAL(error(QtAV::AVError)), this, SLOT(handleError(QtAV::AVError))); updateProgressBarT = new QTimer; connect(updateProgressBarT, SIGNAL(timeout()), this, SLOT(setProgressbarPosition())); updateProgressBarT->start(500); subtitleWidget = new SubtitleWidget(this); EndOfMediaMark=0; }
void StelVideoMgr::loadVideo(const QString& filename, const QString& id, const float x, const float y, const bool show, const float alpha) { if (videoObjects.contains(id)) { qWarning() << "[StelVideoMgr] Video object with ID" << id << "already exists, dropping it"; dropVideo(id); } videoObjects[id] = new VideoPlayer; videoObjects[id]->videoItem= new QGraphicsVideoItem(); // This sets a tiny size so that if window should appear before proper resize, it should not disturb. videoObjects[id]->videoItem->setSize(QSizeF(1,1)); videoObjects[id]->player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); videoObjects[id]->duration=-1; // -1 to signal "unknown". videoObjects[id]->resolution=QSize(); // initialize with "invalid" empty resolution, we must detect this when player is starting! videoObjects[id]->keepVisible=false; videoObjects[id]->needResize=true; // resolution and target frame not yet known. videoObjects[id]->simplePlay=true; videoObjects[id]->targetFrameSize=QSizeF(); // start with invalid, depends on parameters given in playVideo(), playPopoutVideo() and resolution detected only after playing started. videoObjects[id]->popupOrigin=QPointF(); videoObjects[id]->popupTargetCenter=QPointF(); videoObjects[id]->player->setProperty("Stel_id", id); // allow tracking of log messages and access of members. videoObjects[id]->player->setVideoOutput(videoObjects[id]->videoItem); videoObjects[id]->videoItem->setOpacity(alpha); #ifndef Q_OS_WIN // There is a notable difference: on Windows this causes a crash. On Linux, it is required, else the movie frame is visible before proper resize. videoObjects[id]->videoItem->setVisible(show); #endif videoObjects[id]->lastPos=-1; // A few connections are not really needed, they are signals we don't use. TBD: Remove or keep commented out? connect(videoObjects[id]->player, SIGNAL(bufferStatusChanged(int)), this, SLOT(handleBufferStatusChanged(int))); connect(videoObjects[id]->player, SIGNAL(durationChanged(qint64)), this, SLOT(handleDurationChanged(qint64))); // (CRITICALLY IMPORTANT!) connect(videoObjects[id]->player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(handleError(QMediaPlayer::Error))); connect(videoObjects[id]->player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(handleMediaStatusChanged(QMediaPlayer::MediaStatus))); //connect(videoObjects[id]->player, SIGNAL(positionChanged(qint64)), this, SLOT(handlePositionChanged(qint64))); // we test isSeekable() where needed, so only debug log entry. --> And we may use the signal however now during blocking load below! connect(videoObjects[id]->player, SIGNAL(seekableChanged(bool)), this, SLOT(handleSeekableChanged(bool))); connect(videoObjects[id]->player, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(handleStateChanged(QMediaPlayer::State))); connect(videoObjects[id]->player, SIGNAL(videoAvailableChanged(bool)), this, SLOT(handleVideoAvailableChanged(bool))); connect(videoObjects[id]->player, SIGNAL(audioAvailableChanged(bool)), this, SLOT(handleAudioAvailableChanged(bool))); connect(videoObjects[id]->player, SIGNAL(mutedChanged(bool)), this, SLOT(handleMutedChanged(bool))); connect(videoObjects[id]->player, SIGNAL(volumeChanged(int)), this, SLOT(handleVolumeChanged(int))); connect(videoObjects[id]->player, SIGNAL(availabilityChanged(bool)), this, SLOT(handleAvailabilityChanged(bool))); connect(videoObjects[id]->player, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus)), this, SLOT(handleAvailabilityChanged(QMultimedia::AvailabilityStatus))); // Only this is triggered also on Windows. Lets us read resolution etc. (CRITICALLY IMPORTANT!) connect(videoObjects[id]->player, SIGNAL(metaDataChanged()), this, SLOT(handleMetaDataChanged())); // That signal would require less overhead, but is not triggered under Windows and apparently also not on MacOS X. (QTBUG-42034.) // If this becomes available/bugfixed, it should be preferred as being more elegant. // connect(videoObjects[id]->player, SIGNAL(metaDataChanged(QString,QVariant)), this, SLOT(handleMetaDataChanged(QString,QVariant))); // We need an absolute pathname here. QMediaContent content(QUrl::fromLocalFile(QFileInfo(filename).absoluteFilePath())); videoObjects[id]->player->setMedia(content); if (verbose) { qDebug() << "Loading " << content.canonicalUrl(); qDebug() << "Media Resources queried from player:"; qDebug() << "\tSTATUS: " << videoObjects[id]->player->mediaStatus(); qDebug() << "\tFile: " << videoObjects[id]->player->currentMedia().canonicalUrl(); } // qDebug() << "scene->addItem..."; StelMainView::getInstance().scene()->addItem(videoObjects[id]->videoItem); // qDebug() << "scene->addItem OK"; videoObjects[id]->videoItem->setPos(x, y); // DEFAULT SIZE: show a tiny frame. This gets updated to native resolution as soon as resolution becomes known. Needed? //videoObjects[id]->videoItem->setSize(QSizeF(1, 1)); // after many troubles with incompletely loaded files we attempt a blocking load from https://wiki.qt.io/Seek_in_Sound_File // This may be no longer required. But please keep the block here for testing/reactivation if necessary. // if (! videoObjects[id]->player->isSeekable()) // { // qDebug() << "Not Seekable!"; // if (verbose) // qDebug() << "Blocking load ..."; // QEventLoop loop; // QTimer timer; // qDebug() << "Not Seekable: setSingleShot"; // timer.setSingleShot(true); // timer.setInterval(5000); // 5 seconds, may be too long? // qDebug() << "Not Seekable: connect..."; // loop.connect(&timer, SIGNAL (timeout()), &loop, SLOT (quit()) ); // loop.connect(videoObjects[id]->player, SIGNAL (seekableChanged(bool)), &loop, SLOT (quit())); // qDebug() << "Not Seekable: loop..."; // loop.exec(); // if (verbose) // qDebug() << "Blocking load finished, should be seekable now or 5s are over."; // } if (verbose) qDebug() << "Loaded video" << id << "for pos " << x << "/" << y << "Size" << videoObjects[id]->videoItem->size(); videoObjects[id]->player->setPosition(0); // This should force triggering a metadataAvailable() with resolution update. if (show) videoObjects[id]->player->play(); else videoObjects[id]->player->pause(); }