From e5498bed7c7f2e5d3aaaee45daaa554c810539b5 Mon Sep 17 00:00:00 2001 From: Andrew Wason Date: Mon, 9 Oct 2023 14:46:14 -0400 Subject: [PATCH] Add quad filter demo. Rework how resizing works. --- demo/examples/filter-banner.qml | 3 -- demo/examples/filter-demo.qml | 2 - demo/examples/filter-quad.qml | 44 ++++++++++++++++++ demo/examples/producer-demo.qml | 2 - demo/examples/transition-demo3d.qml | 2 - demo/examples/transition-shader-crosszoom.qml | 3 -- demo/examples/transition-shader-pagecurl.qml | 9 ++-- demo/examples/transition-simple.qml | 15 ++++-- demo/mlt/mlt_filter_quad | 16 +++++++ demo/mlt/tests/extract_frames | 1 + .../fixtures/linux/frei0r/filter_quad.png | Bin 0 -> 17497 bytes .../tests/fixtures/linux/mlt/filter_quad.png | Bin 0 -> 17497 bytes .../fixtures/macos/frei0r/filter_quad.png | Bin 0 -> 15693 bytes .../tests/fixtures/macos/mlt/filter_quad.png | Bin 0 -> 15693 bytes vfxpipe/vfxpipe.cpp | 23 ++++++--- vfxpipe/vfxpipe.h | 2 +- viewer/viewer.cpp | 2 +- webvfx/content_context.cpp | 8 ---- webvfx/content_context.h | 5 -- webvfx/frameserver.cpp | 8 +++- webvfx/qml_content.cpp | 11 +---- webvfx/qml_content.h | 2 - 22 files changed, 101 insertions(+), 57 deletions(-) create mode 100644 demo/examples/filter-quad.qml create mode 100755 demo/mlt/mlt_filter_quad create mode 100644 demo/mlt/tests/fixtures/linux/frei0r/filter_quad.png create mode 100644 demo/mlt/tests/fixtures/linux/mlt/filter_quad.png create mode 100644 demo/mlt/tests/fixtures/macos/frei0r/filter_quad.png create mode 100644 demo/mlt/tests/fixtures/macos/mlt/filter_quad.png diff --git a/demo/examples/filter-banner.qml b/demo/examples/filter-banner.qml index 6f1995b..9baf635 100644 --- a/demo/examples/filter-banner.qml +++ b/demo/examples/filter-banner.qml @@ -2,9 +2,6 @@ import QtQuick import QtMultimedia Rectangle { - width: webvfx.videoSize.width - height: webvfx.videoSize.height - VideoOutput { id: video anchors.fill: parent diff --git a/demo/examples/filter-demo.qml b/demo/examples/filter-demo.qml index daa3942..d2a97a8 100644 --- a/demo/examples/filter-demo.qml +++ b/demo/examples/filter-demo.qml @@ -2,8 +2,6 @@ import QtQuick import QtMultimedia Rectangle { - width: webvfx.videoSize.width - height: webvfx.videoSize.height color: "lightgray" VideoOutput { diff --git a/demo/examples/filter-quad.qml b/demo/examples/filter-quad.qml new file mode 100644 index 0000000..cded9f1 --- /dev/null +++ b/demo/examples/filter-quad.qml @@ -0,0 +1,44 @@ +import QtQuick +import QtQuick.Layouts +import QtMultimedia + +GridLayout { + id: grid + columns: 2 + + VideoOutput { + id: tlVideo + Layout.column: 0 + Layout.row: 0 + Layout.fillWidth: true + Layout.fillHeight: true + } + VideoOutput { + id: trVideo + Layout.column: 1 + Layout.row: 0 + Layout.fillWidth: true + Layout.fillHeight: true + } + VideoOutput { + id: blVideo + Layout.column: 0 + Layout.row: 1 + Layout.fillWidth: true + Layout.fillHeight: true + } + VideoOutput { + id: brVideo + Layout.column: 1 + Layout.row: 1 + Layout.fillWidth: true + Layout.fillHeight: true + } + Component.onCompleted: { + var videoSource = webvfx.addVideoSource(); + webvfx.appendVideoSink(videoSource, tlVideo.videoSink); + webvfx.appendVideoSink(videoSource, trVideo.videoSink); + webvfx.appendVideoSink(videoSource, blVideo.videoSink); + webvfx.appendVideoSink(videoSource, brVideo.videoSink); + } +} \ No newline at end of file diff --git a/demo/examples/producer-demo.qml b/demo/examples/producer-demo.qml index eaa7896..719ed3f 100644 --- a/demo/examples/producer-demo.qml +++ b/demo/examples/producer-demo.qml @@ -3,8 +3,6 @@ import QtQuick.Shapes 1.0 Shape { id: shape - width: webvfx.videoSize.width - height: webvfx.videoSize.height anchors.centerIn: parent ShapePath { fillGradient: RadialGradient { diff --git a/demo/examples/transition-demo3d.qml b/demo/examples/transition-demo3d.qml index c272418..a048a3c 100644 --- a/demo/examples/transition-demo3d.qml +++ b/demo/examples/transition-demo3d.qml @@ -6,8 +6,6 @@ import stream.webvfx.WebVfx View3D { id: view - width: webvfx.videoSize.width - height: webvfx.videoSize.height environment: SceneEnvironment { clearColor: "skyblue" diff --git a/demo/examples/transition-shader-crosszoom.qml b/demo/examples/transition-shader-crosszoom.qml index fb2fc19..7863c8c 100644 --- a/demo/examples/transition-shader-crosszoom.qml +++ b/demo/examples/transition-shader-crosszoom.qml @@ -2,9 +2,6 @@ import QtQuick 2.0 import QtMultimedia Rectangle { - width: webvfx.videoSize.width - height: webvfx.videoSize.height - VideoOutput { id: sourceVideo anchors.fill: parent diff --git a/demo/examples/transition-shader-pagecurl.qml b/demo/examples/transition-shader-pagecurl.qml index 65c3da1..e133258 100644 --- a/demo/examples/transition-shader-pagecurl.qml +++ b/demo/examples/transition-shader-pagecurl.qml @@ -2,16 +2,13 @@ import QtQuick 2.0 import QtMultimedia Rectangle { - width: webvfx.videoSize.width - height: webvfx.videoSize.height - - VideoOutput { + VideoOutput { id: sourceVideo anchors.fill: parent visible: false layer.enabled: true - } - VideoOutput { + } + VideoOutput { id: targetVideo anchors.fill: parent visible: false diff --git a/demo/examples/transition-simple.qml b/demo/examples/transition-simple.qml index 59b9c60..3239cb5 100644 --- a/demo/examples/transition-simple.qml +++ b/demo/examples/transition-simple.qml @@ -2,8 +2,7 @@ import QtQuick import QtMultimedia Rectangle { - width: webvfx.videoSize.width - height: webvfx.videoSize.height + id: root color: "lightgray" VideoOutput { @@ -37,6 +36,15 @@ Rectangle { id: animationController animation: animation } + Connections { + target: root + function onWidthChanged(w) { + animationController.reload(); + } + function onHeightChanged(h) { + animationController.reload(); + } + } Component.onCompleted: { webvfx.appendVideoSink(webvfx.addVideoSource(), sourceVideo.videoSink); webvfx.appendVideoSink(webvfx.addVideoSource(), targetVideo.videoSink); @@ -46,8 +54,5 @@ Rectangle { function onRenderRequested(time) { animationController.progress = time; } - function onVideoSizeChanged(size) { - animationController.reload(); - } } } diff --git a/demo/mlt/mlt_filter_quad b/demo/mlt/mlt_filter_quad new file mode 100755 index 0000000..c95f1d4 --- /dev/null +++ b/demo/mlt/mlt_filter_quad @@ -0,0 +1,16 @@ +#!/bin/bash + +BASEDIR=$(dirname "${BASH_SOURCE[0]}") +export DISPLAY=${DISPLAY:-:0} +case ${PLUGIN:-frei0r} in +frei0r) + FILTER=("frei0r.webvfx_filter" "0=\"\"${BASEDIR}/../examples/filter-quad.qml?webvfx_duration=300/30\"\"") + ;; +mlt) + FILTER=(mltwebvfx:"${BASEDIR}/../examples/filter-quad.qml") + ;; +esac +REDTESTSRC=lavfi:$(COLOR=red ${BASEDIR}/tests/testsrc) +melt -verbose "${VFX_SOURCE:-${REDTESTSRC}}" out=299 \ + -filter "${FILTER[@]}" out=299 \ + $(eval echo $(< "${VFX_CONSUMER:-${BASEDIR}/consumer_sdl}")) mlt_profile=${BASEDIR}/webvfx_profile diff --git a/demo/mlt/tests/extract_frames b/demo/mlt/tests/extract_frames index 78c9c32..dee2d0f 100755 --- a/demo/mlt/tests/extract_frames +++ b/demo/mlt/tests/extract_frames @@ -7,6 +7,7 @@ OUTPUT_DIR=${1:?Usage: $(basename $0) OUTPUT_DIR} ${BASEDIR}/extract_frame -s 00:00:04 "${BASEDIR}/../mlt_filter_banner" "${OUTPUT_DIR}/filter_banner.png" ${BASEDIR}/extract_frame -s 00:00:04 "${BASEDIR}/../mlt_filter_demo" "${OUTPUT_DIR}/filter_demo.png" +${BASEDIR}/extract_frame -s 00:00:04 "${BASEDIR}/../mlt_filter_quad" "${OUTPUT_DIR}/filter_quad.png" ${BASEDIR}/extract_frame -s 00:00:04 "${BASEDIR}/../mlt_producer_demo" "${OUTPUT_DIR}/producer_demo.png" ${BASEDIR}/extract_frame -s 00:00:09 "${BASEDIR}/../mlt_transition_demo3d" "${OUTPUT_DIR}/transition_demo3d.png" ${BASEDIR}/extract_frame -s 00:00:09 "${BASEDIR}/../mlt_transition_shader_crosszoom_extra" "${OUTPUT_DIR}/transition_shader_crosszoom.png" diff --git a/demo/mlt/tests/fixtures/linux/frei0r/filter_quad.png b/demo/mlt/tests/fixtures/linux/frei0r/filter_quad.png new file mode 100644 index 0000000000000000000000000000000000000000..a43594020a0fcd501c5a1555d7e89289fa6e8809 GIT binary patch literal 17497 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 literal 0 HcmV?d00001 diff --git a/demo/mlt/tests/fixtures/macos/mlt/filter_quad.png b/demo/mlt/tests/fixtures/macos/mlt/filter_quad.png new file mode 100644 index 0000000000000000000000000000000000000000..0d9813f2e35e4d1e02c3bd7a06757304e5ee813d GIT binary patch literal 15693 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 literal 0 HcmV?d00001 diff --git a/vfxpipe/vfxpipe.cpp b/vfxpipe/vfxpipe.cpp index 9d1b635..6e8e6e8 100644 --- a/vfxpipe/vfxpipe.cpp +++ b/vfxpipe/vfxpipe.cpp @@ -16,7 +16,7 @@ namespace VfxPipe { -std::tuple spawnProcess(int* pipeReadStdout, int* pipeWriteStdin, int* pipeReadStderr, const std::string& url, ErrorHandler errorHandler) +std::tuple spawnProcess(int* pipeReadStdout, int* pipeWriteStdin, int* pipeReadStderr, const std::string& url, uint32_t width, uint32_t height, ErrorHandler errorHandler) { int fdsToChildStdin[2]; int fdsFromChildStdout[2]; @@ -70,7 +70,7 @@ std::tuple spawnProcess(int* pipeReadStdout, int* pipeWriteStdin, exit(1); } } else { - errorHandler(std::string("vfxpipe unable to determine library path")); + errorHandler("vfxpipe unable to determine library path"); exit(1); } } @@ -86,8 +86,19 @@ std::tuple spawnProcess(int* pipeReadStdout, int* pipeWriteStdin, close(fdsFromChildStderr[1]); } + VideoFrameFormat format(VideoFrameFormat::RGBA32, width, height); uint32_t sinkCount = 0; - if (!dataIO(*pipeReadStdout, reinterpret_cast(&sinkCount), sizeof(sinkCount), read, errorHandler)) { + if (!(writeVideoFrameFormat(*pipeWriteStdin, format, errorHandler) + && dataIO(*pipeReadStdout, reinterpret_cast(&sinkCount), sizeof(sinkCount), read, errorHandler))) { + errorHandler("vfxpipe failed to read sink count"); + close(*pipeReadStdout); + *pipeReadStdout = -1; + close(*pipeWriteStdin); + *pipeWriteStdin = -1; + if (pipeReadStderr) { + close(*pipeReadStderr); + *pipeReadStderr = -1; + } return { -1, 0 }; } @@ -110,10 +121,10 @@ FrameServer::~FrameServer() close(pipeWriteStdin); } -bool FrameServer::initialize(ErrorHandler errorHandler, int* pipeReadStderr) +bool FrameServer::initialize(ErrorHandler errorHandler, uint32_t width, uint32_t height, int* pipeReadStderr) { if (!pid) { - std::tie(pid, sinkCount) = spawnProcess(&pipeReadStdout, &pipeWriteStdin, pipeReadStderr, url, errorHandler); + std::tie(pid, sinkCount) = spawnProcess(&pipeReadStdout, &pipeWriteStdin, pipeReadStderr, url, width, height, errorHandler); if (pid == -1) { errorHandler("vfxpipe failed to spawn process"); return false; @@ -128,7 +139,7 @@ bool FrameServer::renderFrame(double time, const std::vector& if (pid == -1) return false; if (!pid) { - if (!initialize(errorHandler)) + if (!initialize(errorHandler, outputFrame.format.width, outputFrame.format.height)) return false; } diff --git a/vfxpipe/vfxpipe.h b/vfxpipe/vfxpipe.h index b0f53b8..4fe5428 100644 --- a/vfxpipe/vfxpipe.h +++ b/vfxpipe/vfxpipe.h @@ -98,7 +98,7 @@ class FrameServer { public: FrameServer(const std::string& url); ~FrameServer(); - bool initialize(ErrorHandler errorHandler, int* pipeReadStderr = nullptr); + bool initialize(ErrorHandler errorHandler, uint32_t width, uint32_t height, int* pipeReadStderr = nullptr); bool renderFrame(double time, const std::vector& sourceFrames, RenderedVideoFrame& outputFrame, ErrorHandler errorHandler); std::string& getUrl() { return url; } uint32_t getSinkCount() { return sinkCount; } diff --git a/viewer/viewer.cpp b/viewer/viewer.cpp index 2597940..a6b162e 100644 --- a/viewer/viewer.cpp +++ b/viewer/viewer.cpp @@ -240,7 +240,7 @@ void Viewer::createContent(const QString& fileName) delete errorNotifier; int pipeReadStderr = 0; - if (frameServer->initialize(errorHandler, &pipeReadStderr)) { + if (frameServer->initialize(errorHandler, size.width(), size.height(), &pipeReadStderr)) { errorNotifier = new QSocketNotifier(pipeReadStderr, QSocketNotifier::Read, this); connect(errorNotifier, &QSocketNotifier::activated, this, &Viewer::onErrorReadyRead); setContentUIEnabled(true); diff --git a/webvfx/content_context.cpp b/webvfx/content_context.cpp index e2e8bdb..6469c5b 100644 --- a/webvfx/content_context.cpp +++ b/webvfx/content_context.cpp @@ -39,14 +39,6 @@ QString ContentContext::getStringParameter(const QString& name) return QString(); } -void ContentContext::setVideoSize(QSize size) -{ - if (videoSize == size) - return; - videoSize = size; - emit videoSizeChanged(size); -} - qsizetype ContentContext::addVideoSource() { videoSinks.resize(videoSinks.size() + 1); diff --git a/webvfx/content_context.h b/webvfx/content_context.h index b2c3aa2..35df3ce 100644 --- a/webvfx/content_context.h +++ b/webvfx/content_context.h @@ -24,7 +24,6 @@ namespace WebVfx { class ContentContext : public QObject { Q_OBJECT - Q_PROPERTY(QSize videoSize READ getVideoSize WRITE setVideoSize NOTIFY videoSizeChanged) // QML contents can set this if it requires async rendering. // It should invoke emitAsyncRenderComplete when ready Q_PROPERTY(bool asyncRenderRequired READ isAsyncRenderRequired WRITE setAsyncRenderRequired) @@ -57,8 +56,6 @@ class ContentContext : public QObject { // webvfx.emitAsyncRenderComplete() Q_INVOKABLE void emitAsyncRenderComplete(); - QSize getVideoSize() const { return videoSize; }; - void setVideoSize(QSize size); bool isAsyncRenderRequired() { return asyncRenderRequired; }; void setAsyncRenderRequired(bool asyncRender) { asyncRenderRequired = asyncRender; }; const QList>& getVideoSinks() { return videoSinks; } @@ -68,14 +65,12 @@ class ContentContext : public QObject { // time is normalized 0..1.0 // JS: webvfx.renderRequested.connect(function (time) { doSomething(); }) void renderRequested(double time); - void videoSizeChanged(QSize size); void asyncRenderComplete(); private: Parameters* parameters; QList> videoSinks; - QSize videoSize; bool asyncRenderRequired; }; diff --git a/webvfx/frameserver.cpp b/webvfx/frameserver.cpp index 9daeb6e..1e11214 100644 --- a/webvfx/frameserver.cpp +++ b/webvfx/frameserver.cpp @@ -104,6 +104,11 @@ FrameServer::FrameServer(QUrl& qmlUrl, QObject* parent) urlQuery.removeQueryItem("webvfx_duration"); content = new WebVfx::QmlContent(new FrameServerParameters(urlQuery)); + if (!VfxPipe::readVideoFrameFormat(STDIN_FILENO, outputFrame.format, ioErrorHandler)) { + return; + } + content->resize(outputFrame.format.width, outputFrame.format.height); + qmlUrl.setQuery(QString()); connect(content, &WebVfx::QmlContent::contentLoadFinished, this, &FrameServer::onContentLoadFinished); @@ -119,7 +124,6 @@ FrameServer::~FrameServer() void FrameServer::onContentLoadFinished(bool result) { if (result) { - auto size = content->getContentSize(); auto videoSinks = content->getVideoSinks(); for (const auto videoSink : videoSinks) { frameSinks.append(FrameSink(videoSink)); @@ -161,7 +165,7 @@ void FrameServer::readFrames() if (!VfxPipe::readVideoFrameFormat(STDIN_FILENO, outputFrame.format, ioErrorHandler)) return; - content->setContentSize(QSize(outputFrame.format.width, outputFrame.format.height)); + content->resize(outputFrame.format.width, outputFrame.format.height); uint32_t frameCount; if (!VfxPipe::dataIO(STDIN_FILENO, reinterpret_cast(&frameCount), sizeof(frameCount), read, ioErrorHandler)) diff --git a/webvfx/qml_content.cpp b/webvfx/qml_content.cpp index 256a74d..bbbdf84 100644 --- a/webvfx/qml_content.cpp +++ b/webvfx/qml_content.cpp @@ -20,7 +20,7 @@ QmlContent::QmlContent(RenderControl* renderControl, Parameters* parameters) , renderControl(renderControl) , renderExpected(false) { - setResizeMode(ResizeMode::SizeViewToRootObject); + setResizeMode(ResizeMode::SizeRootObjectToView); // Expose context to the QML rootContext()->setContextProperty("webvfx", contentContext); @@ -60,13 +60,6 @@ void QmlContent::loadContent(const QUrl& url) setSource(url); } -void QmlContent::setContentSize(const QSize& size) -{ - if (contentContext->getVideoSize() != size) { - contentContext->setVideoSize(size); - } -} - void QmlContent::contextAsyncRenderComplete() { if (!renderExpected) { @@ -83,7 +76,7 @@ void QmlContent::contextAsyncRenderComplete() void QmlContent::renderContent(double time) { - if (!renderControl->install(this, contentContext->getVideoSize())) { + if (!renderControl->install(this, size())) { emit renderComplete(QImage()); } diff --git a/webvfx/qml_content.h b/webvfx/qml_content.h index f24875b..2ac8557 100644 --- a/webvfx/qml_content.h +++ b/webvfx/qml_content.h @@ -30,8 +30,6 @@ class QmlContent : public QQuickView { ~QmlContent() override; void loadContent(const QUrl& url); - void setContentSize(const QSize& size); - QSize getContentSize() { return contentContext->getVideoSize(); } const QList>& getVideoSinks() { return contentContext->getVideoSinks(); } void renderContent(double time);