diff --git a/AVQt/src/common/PixelFormat.cpp b/AVQt/src/common/PixelFormat.cpp index 95a712fcb35037d0152f631cf1682adfd62f620c..d4972f392808ca19301e618eac938c31f9569811 100644 --- a/AVQt/src/common/PixelFormat.cpp +++ b/AVQt/src/common/PixelFormat.cpp @@ -80,7 +80,7 @@ namespace AVQt::common { AVQt::common::PixelFormat::registerGPUFormat({.format = AV_PIX_FMT_MMAL, .nativeFormat = nullptr}); AVQt::common::PixelFormat::registerGPUFormat({.format = AV_PIX_FMT_MEDIACODEC, .nativeFormat = nullptr}); - AVQt::common::PixelFormat::registerGPUFormat({.format = AV_PIX_FMT_QSV, .nativeFormat = &FullFormatPixelFormatOf}); + AVQt::common::PixelFormat::registerGPUFormat({.format = AV_PIX_FMT_QSV, .nativeFormat = &OneInterleavedPlanePixelFormatOf}); AVQt::common::PixelFormat::registerGPUFormat({.format = AV_PIX_FMT_VDPAU, .nativeFormat = nullptr}); AVQt::common::PixelFormat::registerGPUFormat({.format = AV_PIX_FMT_VIDEOTOOLBOX, .nativeFormat = nullptr}); diff --git a/AVQt/src/decoder/QSVDecoderImpl.cpp b/AVQt/src/decoder/QSVDecoderImpl.cpp index 1df16402d67e3047d035e82caad64a5b10ba21bd..14a71c9143ed67dd51455d6d045ac7bde2026edc 100644 --- a/AVQt/src/decoder/QSVDecoderImpl.cpp +++ b/AVQt/src/decoder/QSVDecoderImpl.cpp @@ -6,13 +6,14 @@ #include "private/QSVDecoderImpl_p.hpp" #include "common/PixelFormat.hpp" +#include "decoder/VideoDecoderFactory.hpp" namespace AVQt { const api::VideoDecoderInfo &QSVDecoderImpl::info() { static const api::VideoDecoderInfo info = { .metaObject = QSVDecoderImpl::staticMetaObject, - .name = "VAAPI", - .platforms = {common::Platform::Linux_X11, common::Platform::Linux_Wayland}, + .name = "QSV", + .platforms = {common::Platform::Linux_X11, common::Platform::Linux_Wayland, common::Platform::Windows}, .supportedInputPixelFormats = { {AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, {AV_PIX_FMT_YUV420P10, AV_PIX_FMT_NONE}, @@ -102,7 +103,7 @@ namespace AVQt { auto *framesContext = reinterpret_cast<AVHWFramesContext *>(framesCtxRef->data); framesContext->format = AV_PIX_FMT_QSV; - framesContext->sw_format = static_cast<AVPixelFormat>(d->codecParams->format); + framesContext->sw_format = common::PixelFormat{static_cast<AVPixelFormat>(d->codecParams->format), AV_PIX_FMT_QSV}.toNativeFormat().getCPUFormat(); framesContext->width = d->codecParams->width; framesContext->height = d->codecParams->height; framesContext->initial_pool_size = 32; @@ -128,6 +129,13 @@ namespace AVQt { goto fail; } + d->frameFetcher = std::make_unique<QSVDecoderImplPrivate::FrameFetcher>(d); + d->frameFetcher->start(); + if (!d->frameFetcher->isRunning()) { + qWarning() << "[AVQt::QSVDecoderImpl] Failed to start frame fetcher"; + goto fail; + } + return true; } else { qWarning("[AVQt::QSVDecoderImpl] Already opened"); @@ -135,6 +143,7 @@ namespace AVQt { } fail: d->open = false; + d->frameFetcher.reset(); d->codecContext.reset(); d->hwDeviceContext.reset(); d->hwFramesContext.reset(); @@ -146,6 +155,7 @@ namespace AVQt { bool shouldBe = false; if (d->open.compare_exchange_strong(shouldBe, false)) { + d->frameFetcher.reset(); d->codecContext.reset(); d->hwDeviceContext.reset(); d->hwFramesContext.reset(); @@ -308,3 +318,7 @@ namespace AVQt { qDebug() << "FrameFetcher stopped"; } }// namespace AVQt + +static_block { + AVQt::VideoDecoderFactory::getInstance().registerDecoder(AVQt::QSVDecoderImpl::info()); +} diff --git a/AVQt/src/decoder/QSVDecoderImpl.hpp b/AVQt/src/decoder/QSVDecoderImpl.hpp index e26fff260c904a30912bb462f077a955c2a741ac..3915d738093fba372436afe745ba9e0375e9e890 100644 --- a/AVQt/src/decoder/QSVDecoderImpl.hpp +++ b/AVQt/src/decoder/QSVDecoderImpl.hpp @@ -14,10 +14,11 @@ namespace AVQt { class QSVDecoderImpl : public QObject, public api::IVideoDecoderImpl { Q_OBJECT Q_DECLARE_PRIVATE(QSVDecoderImpl) + Q_INTERFACES(AVQt::api::IVideoDecoderImpl) public: static const api::VideoDecoderInfo &info(); - explicit QSVDecoderImpl(AVCodecID codecId, QObject *parent = nullptr); + Q_INVOKABLE explicit QSVDecoderImpl(AVCodecID codecId, QObject *parent = nullptr); ~QSVDecoderImpl() override; bool open(std::shared_ptr<AVCodecParameters> codecParams) override; void close() override; diff --git a/AVQt/src/decoder/private/QSVDecoderImpl_p.hpp b/AVQt/src/decoder/private/QSVDecoderImpl_p.hpp index b047224130f07c87f5f36da1333454c67964a5f1..f159008ffbabdb9037b2daffdd0f67117fe25c0f 100644 --- a/AVQt/src/decoder/private/QSVDecoderImpl_p.hpp +++ b/AVQt/src/decoder/private/QSVDecoderImpl_p.hpp @@ -50,6 +50,8 @@ namespace AVQt { std::shared_ptr<AVBufferRef> hwFramesContext{nullptr, &destroyAVBufferRef}; std::atomic_bool open{false}, firstFrame{true}; + + std::unique_ptr<FrameFetcher> frameFetcher{}; }; }// namespace AVQt diff --git a/AVQt/src/renderers/FallbackFrameMapper.cpp b/AVQt/src/renderers/FallbackFrameMapper.cpp index ed4157b44d96aa6e6318b235f1ef823f826508cc..860b4f95362fa79dc90d6ba65fd0e61e77b98a7d 100644 --- a/AVQt/src/renderers/FallbackFrameMapper.cpp +++ b/AVQt/src/renderers/FallbackFrameMapper.cpp @@ -209,6 +209,7 @@ namespace AVQt { QMutexLocker lock(&d->renderMutex); bool shouldBe = true; if (d->running.compare_exchange_strong(shouldBe, false)) { + d->afterStopThread = QThread::currentThread(); lock.unlock(); QThread::quit(); QThread::wait(); @@ -382,6 +383,9 @@ namespace AVQt { emit frameReady(frame->pts, fbo); qDebug("Frame ready"); } + if (d->afterStopThread) { + d->context->moveToThread(d->afterStopThread); + } } void FallbackFrameMapperPrivate::bindResources() { diff --git a/AVQt/src/renderers/private/FallbackFrameMapper_p.hpp b/AVQt/src/renderers/private/FallbackFrameMapper_p.hpp index 97f1f75ecf2daa647b95053020928c347aa8e768..d86791b38e5958269812642e671fcbf4c1696fc8 100644 --- a/AVQt/src/renderers/private/FallbackFrameMapper_p.hpp +++ b/AVQt/src/renderers/private/FallbackFrameMapper_p.hpp @@ -73,6 +73,8 @@ namespace AVQt { QOpenGLBuffer vbo{}; QOpenGLBuffer ibo{}; + QThread *afterStopThread{nullptr}; + std::unique_ptr<SwsContext, decltype(&destroySwsContext)> pSwsContext{nullptr, &destroySwsContext}; std::atomic_bool paused{false}, firstFrame{true}, running{false}; diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b6fb8c837f51ab82344dd39a58d2b017e7faef2..5296a9e2db8e6e6e3ad89a25fe70774cdbc2919d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ if (NOT QT_VERSION) endif () set(PGRAPH_QT_VERSION "${QT_VERSION}" CACHE INTERNAL "PGRAPH_QT_VERSION") set(SC_QT_VERSION "${QT_VERSION}" CACHE INTERNAL "SC_QT_VERSION") -#set(CMAKE_PREFIX_PATH "/home/silas/ffmpeg_build/" CACHE INTERNAL "CMAKE_PREFIX_PATH") +set(CMAKE_PREFIX_PATH "/home/silas/ffmpeg_build/" CACHE INTERNAL "CMAKE_PREFIX_PATH") add_subdirectory(libpgraph_network) diff --git a/Player/OpenGlWidgetRenderer.cpp b/Player/OpenGlWidgetRenderer.cpp index 9fe931511c8cc80c2982b8d87b7ac47efe78b331..7e637cd79f33426a77c63e9d8c95adb41a1de773 100644 --- a/Player/OpenGlWidgetRenderer.cpp +++ b/Player/OpenGlWidgetRenderer.cpp @@ -246,8 +246,8 @@ bool OpenGLWidgetRenderer::isPaused() const { bool OpenGLWidgetRenderer::open() { Q_D(OpenGLWidgetRenderer); - d->mapper = AVQt::OpenGLFrameMapperFactory::getInstance().create({d->params.isHWAccel ? d->params.swPixelFormat : d->params.pixelFormat, d->params.isHWAccel ? d->params.pixelFormat : AV_PIX_FMT_NONE}, - QStringList() << "VAAPI"); + d->mapper = AVQt::OpenGLFrameMapperFactory::getInstance() + .create({d->params.isHWAccel ? d->params.swPixelFormat : d->params.pixelFormat, d->params.isHWAccel ? d->params.pixelFormat : AV_PIX_FMT_NONE}); // clang-format off // Preserve normalized form of Qt SIGNAL/SLOT macro connect(std::dynamic_pointer_cast<QObject>(d->mapper).get(), SIGNAL(frameReady(qint64,std::shared_ptr<QOpenGLFramebufferObject>)), diff --git a/Player/main.cpp b/Player/main.cpp index ae94d15d7ba39a6a2efe16cab1f0529d0a62aa27..4046b4df1593eadf90bf349d7f3f2d3efdb7660c 100644 --- a/Player/main.cpp +++ b/Player/main.cpp @@ -53,9 +53,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt logFile.open(QIODevice::WriteOnly); } - //#ifndef QT_DEBUG +#ifndef QT_DEBUG if (type > QtMsgType::QtDebugMsg) - //#endif +#endif { QString output; QTextStream os(&output); @@ -144,7 +144,7 @@ int main(int argc, char *argv[]) { auto muxer = std::make_shared<AVQt::Muxer>(std::move(muxerConfig), registry); AVQt::VideoDecoder::Config videoDecoderConfig{}; - videoDecoderConfig.decoderPriority << "VAAPI"; + videoDecoderConfig.decoderPriority << "QSV"; auto decoder1 = std::make_shared<AVQt::VideoDecoder>(videoDecoderConfig, registry); auto decoder2 = std::make_shared<AVQt::VideoDecoder>(videoDecoderConfig, registry); // auto decoder3 = std::make_shared<AVQt::VideoDecoder>("VAAPI", registry); @@ -220,9 +220,9 @@ int main(int argc, char *argv[]) { // encoderInPad->link(decoder1OutPad); // decoder2InPad->link(encoderOutPad); decoder1InPad->link(demuxerOutPad); - // ccInPad->link(decoder1OutPad); - encoder1InPad->link(decoder1OutPad); - encoder2InPad->link(decoder1OutPad); + ccInPad->link(decoder1OutPad); + // encoder1InPad->link(decoder1OutPad); + // encoder2InPad->link(decoder1OutPad); // yuvrgbconverterInPad->link(decoder1OutPad); // renderer2InPad->link(decoder1OutPad); renderer1InPad->link(decoder1OutPad); @@ -231,8 +231,8 @@ int main(int argc, char *argv[]) { // renderer2InPad->link(decoder2OutPad); // yuvrgbconverterOutPad->link(frameSaverInPad); - muxerInPad1->link(encoder1OutPad); - muxerInPad2->link(encoder2OutPad); + // muxerInPad1->link(encoder1OutPad); + // muxerInPad2->link(encoder2OutPad); demuxer->open(); @@ -241,9 +241,9 @@ int main(int argc, char *argv[]) { demuxer->start(); - QTimer::singleShot(5000, [demuxer]() { - QApplication::quit(); - }); + // QTimer::singleShot(5000, [demuxer]() { + // QApplication::quit(); + // }); // QTimer::singleShot(4000, [demuxer]{ // demuxer->pause(true);