/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include "QtFrameGrabber.hxx" #include using namespace ::com::sun::star; namespace { inline OUString toOUString(const QString& s) { return OUString(reinterpret_cast(s.data()), s.length()); } uno::Reference toXGraphic(const QImage& rImage) { QByteArray aData; QBuffer aBuffer(&aData); rImage.save(&aBuffer, "PNG"); SvMemoryStream aStream(aData.data(), aData.size(), StreamMode::READ); vcl::PngImageReader aReader(aStream); Graphic aGraphic; aReader.read(aGraphic); return aGraphic.GetXGraphic(); } } namespace avmedia::qt { QtFrameGrabber::QtFrameGrabber(const QUrl& rSourceUrl) : m_bWaitingForFrame(false) { m_xMediaPlayer = std::make_unique(); m_xMediaPlayer->setSource(rSourceUrl); m_xVideoSink = std::make_unique(); m_xMediaPlayer->setVideoSink(m_xVideoSink.get()); connect(m_xMediaPlayer.get(), &QMediaPlayer::errorOccurred, this, &QtFrameGrabber::onErrorOccured, Qt::SingleShotConnection); } void QtFrameGrabber::onErrorOccured(QMediaPlayer::Error eError, const QString& rErrorString) { std::lock_guard aLock(m_aMutex); SAL_WARN("avmedia", "Media playback error occurred when trying to grab frame: " << toOUString(rErrorString) << ", code: " << eError); m_bWaitingForFrame = false; } void QtFrameGrabber::onVideoFrameChanged(const QVideoFrame& rFrame) { std::lock_guard aLock(m_aMutex); const QImage aImage = rFrame.toImage(); m_xGraphic = toXGraphic(aImage); m_bWaitingForFrame = false; } css::uno::Reference SAL_CALL QtFrameGrabber::grabFrame(double fMediaTime) { std::lock_guard aLock(m_aMutex); m_xMediaPlayer->setPosition(fMediaTime * 1000); // in order to get a video frame, connect to videoFrameChanged signal and start playing // until the first frame has been received m_bWaitingForFrame = true; connect(m_xVideoSink.get(), &QVideoSink::videoFrameChanged, this, &QtFrameGrabber::onVideoFrameChanged, Qt::SingleShotConnection); m_xMediaPlayer->play(); while (m_bWaitingForFrame) { // QMediaPlayer::hasVideo() result isn't valid while media is loading if (m_xMediaPlayer->mediaStatus() != QMediaPlayer::LoadingMedia && !m_xMediaPlayer->hasVideo()) { // There's no video, don't wait for frame m_bWaitingForFrame = false; } else { Scheduler::ProcessEventsToIdle(); } } m_xMediaPlayer->stop(); uno::Reference xGraphic = m_xGraphic; m_xGraphic.clear(); return xGraphic; } }; // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */