diff options
Diffstat (limited to 'src')
4 files changed, 51 insertions, 150 deletions
diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp index 36f8c049b..f3e2d884c 100644 --- a/src/gsttools/qvideosurfacegstsink.cpp +++ b/src/gsttools/qvideosurfacegstsink.cpp @@ -56,7 +56,6 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate( : m_surface(surface) , m_pool(0) , m_renderReturn(GST_FLOW_ERROR) - , m_lastPrerolledBuffer(0) , m_bytesPerLine(0) , m_startCanceled(false) { @@ -74,7 +73,6 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate( QVideoSurfaceGstDelegate::~QVideoSurfaceGstDelegate() { - setLastPrerolledBuffer(0); } QList<QVideoFrame::PixelFormat> QVideoSurfaceGstDelegate::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const @@ -209,23 +207,6 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) return m_renderReturn; } -void QVideoSurfaceGstDelegate::setLastPrerolledBuffer(GstBuffer *prerolledBuffer) -{ - // discard previously stored buffer - if (m_lastPrerolledBuffer) { - gst_buffer_unref(m_lastPrerolledBuffer); - m_lastPrerolledBuffer = 0; - } - - if (!prerolledBuffer) - return; - - // store a reference to the buffer - Q_ASSERT(!m_lastPrerolledBuffer); - m_lastPrerolledBuffer = prerolledBuffer; - gst_buffer_ref(m_lastPrerolledBuffer); -} - void QVideoSurfaceGstDelegate::queuedStart() { if (!m_startCanceled) { @@ -397,8 +378,6 @@ QVideoSurfaceGstSink *QVideoSurfaceGstSink::createSink(QAbstractVideoSurface *su sink->delegate = new QVideoSurfaceGstDelegate(surface); - g_signal_connect(G_OBJECT(sink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), sink); - return sink; } @@ -434,16 +413,15 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) sink_parent_class = reinterpret_cast<GstVideoSinkClass *>(g_type_class_peek_parent(g_class)); + GstVideoSinkClass *video_sink_class = reinterpret_cast<GstVideoSinkClass *>(g_class); + video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame; + GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class); base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps; base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps; base_sink_class->buffer_alloc = QVideoSurfaceGstSink::buffer_alloc; base_sink_class->start = QVideoSurfaceGstSink::start; base_sink_class->stop = QVideoSurfaceGstSink::stop; - // base_sink_class->unlock = QVideoSurfaceGstSink::unlock; // Not implemented. - base_sink_class->event = QVideoSurfaceGstSink::event; - base_sink_class->preroll = QVideoSurfaceGstSink::preroll; - base_sink_class->render = QVideoSurfaceGstSink::render; GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class); element_class->change_state = QVideoSurfaceGstSink::change_state; @@ -709,27 +687,6 @@ void QVideoSurfaceGstSink::setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buf } } -void QVideoSurfaceGstSink::handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d) -{ - Q_UNUSED(o); - Q_UNUSED(p); - QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(d); - - gboolean value = true; // "show-preroll-frame" property is true by default - g_object_get(G_OBJECT(sink), "show-preroll-frame", &value, NULL); - - GstBuffer *buffer = sink->delegate->lastPrerolledBuffer(); - // Render the stored prerolled buffer if requested. - // e.g. player is in stopped mode, then seek operation is requested, - // surface now stores a prerolled frame, but doesn't display it until - // "show-preroll-frame" property is set to "true" - // when switching to pause or playing state. - if (value && buffer) { - sink->delegate->render(buffer); - sink->delegate->setLastPrerolledBuffer(0); - } -} - GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( GstBaseSink *base, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer) { @@ -842,44 +799,9 @@ gboolean QVideoSurfaceGstSink::stop(GstBaseSink *base) return TRUE; } -gboolean QVideoSurfaceGstSink::unlock(GstBaseSink *base) -{ - Q_UNUSED(base); - - return TRUE; -} - -gboolean QVideoSurfaceGstSink::event(GstBaseSink *base, GstEvent *event) -{ - // discard prerolled frame - if (event->type == GST_EVENT_FLUSH_START) { - VO_SINK(base); - sink->delegate->setLastPrerolledBuffer(0); - } - - return TRUE; -} - -GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer) -{ - VO_SINK(base); - - gboolean value = true; // "show-preroll-frame" property is true by default - g_object_get(G_OBJECT(base), "show-preroll-frame", &value, NULL); - if (value) { - sink->delegate->setLastPrerolledBuffer(0); // discard prerolled buffer - return sink->delegate->render(buffer); // display frame - } - - // otherwise keep a reference to the buffer to display it later - sink->delegate->setLastPrerolledBuffer(buffer); - return GST_FLOW_OK; -} - -GstFlowReturn QVideoSurfaceGstSink::render(GstBaseSink *base, GstBuffer *buffer) +GstFlowReturn QVideoSurfaceGstSink::show_frame(GstVideoSink *base, GstBuffer *buffer) { VO_SINK(base); - sink->delegate->setLastPrerolledBuffer(0); // discard prerolled buffer return sink->delegate->render(buffer); } diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h index d152e2a44..11b305d27 100644 --- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h +++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h @@ -84,9 +84,6 @@ public: GstFlowReturn render(GstBuffer *buffer); - GstBuffer *lastPrerolledBuffer() const { return m_lastPrerolledBuffer; } - void setLastPrerolledBuffer(GstBuffer *lastPrerolledBuffer); // set prerolledBuffer to 0 to discard prerolled buffer - private slots: void queuedStart(); void queuedStop(); @@ -108,8 +105,6 @@ private: QVideoSurfaceFormat m_format; QVideoFrame m_frame; GstFlowReturn m_renderReturn; - // this pointer is not 0 when there is a prerolled buffer waiting to be displayed - GstBuffer *m_lastPrerolledBuffer; int m_bytesPerLine; bool m_started; bool m_startCanceled; @@ -126,8 +121,6 @@ public: QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle); static void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer); - static void handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d); - private: static GType get_type(); static void class_init(gpointer g_class, gpointer class_data); @@ -147,11 +140,7 @@ private: static gboolean start(GstBaseSink *sink); static gboolean stop(GstBaseSink *sink); - static gboolean unlock(GstBaseSink *sink); - - static gboolean event(GstBaseSink *sink, GstEvent *event); - static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer); - static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer); + static GstFlowReturn show_frame(GstVideoSink *sink, GstBuffer *buffer); private: QVideoSurfaceGstDelegate *delegate; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index 2f7047f97..fed756ac9 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -60,7 +60,6 @@ QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *sessio , m_currentState(QMediaPlayer::StoppedState) , m_mediaStatus(QMediaPlayer::NoMedia) , m_bufferProgress(-1) - , m_seekToStartPending(false) , m_pendingSeekPosition(-1) , m_setMediaPending(false) , m_stream(0) @@ -69,7 +68,7 @@ QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *sessio Q_ASSERT(m_resources); connect(m_session, SIGNAL(positionChanged(qint64)), - this, SLOT(updatePosition(qint64))); + this, SIGNAL(positionChanged(qint64))); connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64))); connect(m_session, SIGNAL(mutedStateChanged(bool)), @@ -94,8 +93,6 @@ QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *sessio this, SLOT(handleInvalidMedia())); connect(m_session, SIGNAL(playbackRateChanged(qreal)), this, SIGNAL(playbackRateChanged(qreal))); - connect(m_session, SIGNAL(seekableChanged(bool)), - this, SLOT(applyPendingSeek(bool))); connect(m_resources, SIGNAL(resourcesGranted()), SLOT(handleResourcesGranted())); //denied signal should be queued to have correct state update process, @@ -117,7 +114,7 @@ QMediaPlayerResourceSetInterface* QGstreamerPlayerControl::resources() const qint64 QGstreamerPlayerControl::position() const { - return m_seekToStartPending ? 0 : m_session->position(); + return m_pendingSeekPosition != -1 ? m_pendingSeekPosition : m_session->position(); } qint64 QGstreamerPlayerControl::duration() const @@ -183,15 +180,21 @@ void QGstreamerPlayerControl::setPosition(qint64 pos) if (m_mediaStatus == QMediaPlayer::EndOfMedia) { m_mediaStatus = QMediaPlayer::LoadedMedia; - m_seekToStartPending = true; } - if (m_session->isSeekable() && m_session->seek(pos)) { - m_seekToStartPending = false; - } else { + if (m_currentState == QMediaPlayer::StoppedState) { m_pendingSeekPosition = pos; - //don't display the first video frame since it's not what user requested. - m_session->showPrerollFrames(false); + emit positionChanged(m_pendingSeekPosition); + } else if (m_session->isSeekable()) { + m_session->showPrerollFrames(true); + m_session->seek(pos); + m_pendingSeekPosition = -1; + } else if (m_session->state() == QMediaPlayer::StoppedState) { + m_pendingSeekPosition = pos; + emit positionChanged(m_pendingSeekPosition); + } else if (m_pendingSeekPosition != -1) { + m_pendingSeekPosition = -1; + emit positionChanged(m_pendingSeekPosition); } popAndNotifyState(); @@ -239,26 +242,30 @@ void QGstreamerPlayerControl::playOrPause(QMediaPlayer::State newState) } #endif + if (m_mediaStatus == QMediaPlayer::EndOfMedia && m_pendingSeekPosition == -1) { + m_pendingSeekPosition = 0; + } + if (!m_resources->isGranted()) m_resources->acquire(); if (m_resources->isGranted()) { - if (m_seekToStartPending) { + // show prerolled frame if switching from stopped state + if (m_pendingSeekPosition == -1) { + m_session->showPrerollFrames(true); + } else if (m_session->state() == QMediaPlayer::StoppedState) { + // Don't evaluate the next two conditions. + } else if (m_session->isSeekable()) { m_session->pause(); - if (!m_session->seek(0)) { - m_bufferProgress = -1; - m_session->stop(); - m_mediaStatus = QMediaPlayer::LoadingMedia; - } - m_seekToStartPending = false; + m_session->showPrerollFrames(true); + m_session->seek(m_pendingSeekPosition); + m_pendingSeekPosition = -1; + } else { + m_pendingSeekPosition = -1; } bool ok = false; - // show prerolled frame if switching from stopped state - if (newState != QMediaPlayer::StoppedState && m_currentState == QMediaPlayer::StoppedState && m_pendingSeekPosition == -1) - m_session->showPrerollFrames(true); - //To prevent displaying the first video frame when playback is resumed //the pipeline is paused instead of playing, seeked to requested position, //and after seeking is finished (position updated) playback is restarted @@ -305,7 +312,7 @@ void QGstreamerPlayerControl::stop() m_session->pause(); if (m_mediaStatus != QMediaPlayer::EndOfMedia) { - m_seekToStartPending = true; + m_pendingSeekPosition = 0; emit positionChanged(position()); } } @@ -343,7 +350,7 @@ void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice * m_currentState = QMediaPlayer::StoppedState; QMediaContent oldMedia = m_currentResource; - m_pendingSeekPosition = -1; + m_pendingSeekPosition = 0; m_session->showPrerollFrames(false); // do not show prerolled frames until pause() or play() explicitly called m_setMediaPending = false; @@ -390,7 +397,6 @@ void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice * m_currentResource = content; m_stream = stream; - m_seekToStartPending = false; QNetworkRequest request; @@ -462,8 +468,21 @@ void QGstreamerPlayerControl::updateSessionState(QMediaPlayer::State state) { pushState(); - if (state == QMediaPlayer::StoppedState) + if (state == QMediaPlayer::StoppedState) { + m_session->showPrerollFrames(false); m_currentState = QMediaPlayer::StoppedState; + } + + if (state == QMediaPlayer::PausedState && m_currentState != QMediaPlayer::StoppedState) { + if (m_pendingSeekPosition != -1 && m_session->isSeekable()) { + m_session->showPrerollFrames(true); + m_session->seek(m_pendingSeekPosition); + } + m_pendingSeekPosition = -1; + + if (m_currentState == QMediaPlayer::PlayingState) + m_session->play(); + } updateMediaStatus(); @@ -512,7 +531,6 @@ void QGstreamerPlayerControl::processEOS() m_mediaStatus = QMediaPlayer::EndOfMedia; emit positionChanged(position()); m_session->endOfMediaReset(); - m_setMediaPending = true; if (m_currentState != QMediaPlayer::StoppedState) { m_currentState = QMediaPlayer::StoppedState; @@ -549,17 +567,12 @@ void QGstreamerPlayerControl::setBufferProgress(int progress) emit bufferStatusChanged(m_bufferProgress); } -void QGstreamerPlayerControl::applyPendingSeek(bool isSeekable) -{ - if (isSeekable && m_pendingSeekPosition != -1) - setPosition(m_pendingSeekPosition); -} - void QGstreamerPlayerControl::handleInvalidMedia() { pushState(); m_mediaStatus = QMediaPlayer::InvalidMedia; m_currentState = QMediaPlayer::StoppedState; + m_setMediaPending = true; popAndNotifyState(); } @@ -636,24 +649,4 @@ void QGstreamerPlayerControl::popAndNotifyState() } } -void QGstreamerPlayerControl::updatePosition(qint64 pos) -{ -#ifdef DEBUG_PLAYBIN - qDebug() << Q_FUNC_INFO << pos/1000.0 << "pending:" << m_pendingSeekPosition/1000.0; -#endif - - if (m_pendingSeekPosition != -1) { - //seek request is complete, it's safe to resume playback - //with prerolled frame displayed - m_pendingSeekPosition = -1; - if (m_currentState != QMediaPlayer::StoppedState) - m_session->showPrerollFrames(true); - if (m_currentState == QMediaPlayer::PlayingState) { - m_session->play(); - } - } - - emit positionChanged(pos); -} - QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h index 94f7b7019..0a5f8af83 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h @@ -103,8 +103,6 @@ private Q_SLOTS: void updateMediaStatus(); void processEOS(); void setBufferProgress(int progress); - void applyPendingSeek(bool isSeekable); - void updatePosition(qint64 pos); void handleInvalidMedia(); @@ -127,7 +125,6 @@ private: QStack<QMediaPlayer::MediaStatus> m_mediaStatusStack; int m_bufferProgress; - bool m_seekToStartPending; qint64 m_pendingSeekPosition; bool m_setMediaPending; QMediaContent m_currentResource; |