Skip to content

Commit

Permalink
move stuff around
Browse files Browse the repository at this point in the history
  • Loading branch information
rectalogic committed Jan 5, 2024
1 parent 0100f0b commit 93a43d0
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 103 deletions.
10 changes: 10 additions & 0 deletions src/MediaFX/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,17 @@ set_property(TARGET mediafxtool PROPERTY OUTPUT_NAME mediafx)
qt_add_qml_module(mediafx
URI MediaFX
QML_FILES
qml/sequence.js
qml/MediaSequence.qml
qml/MultiEffectState.qml
qml/effects/MediaMixer.qml
qml/effects/CrossFadeMixer.qml
)
qt_add_shaders(mediafx "shaders"
PREFIX
"/shaders"
FILES
qml/effects/crossfade.frag
)

target_link_libraries(mediafx PUBLIC PkgConfig::ffms2 Qt6::Core Qt6::Gui Qt6::GuiPrivate Qt6::Multimedia Qt6::Qml Qt6::Quick)
Expand Down
3 changes: 2 additions & 1 deletion src/MediaFX/interval.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ using namespace std::chrono;
class Interval {
Q_GADGET
QML_VALUE_TYPE(interval)
QML_STRUCTURED_VALUE
Q_PROPERTY(int start READ start FINAL)
Q_PROPERTY(int end READ end FINAL)
Q_PROPERTY(int duration READ duration FINAL)

public:
constexpr Interval() noexcept = default;
Expand All @@ -51,6 +51,7 @@ class Interval {

constexpr qint64 start() const noexcept { return duration_cast<milliseconds>(s).count(); }
constexpr qint64 end() const noexcept { return duration_cast<milliseconds>(e).count(); }
constexpr qint64 duration() const noexcept { return duration_cast<milliseconds>(e - s).count(); }

Q_INVOKABLE constexpr bool contains(qint64 time) const noexcept
{
Expand Down
2 changes: 2 additions & 0 deletions src/MediaFX/media_clip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ void MediaClip::setClipStart(qint64 ms)
}
m_clipStart = ms;
emit clipStartChanged();
emit clipDurationChanged();
}

void MediaClip::setClipEnd(qint64 ms)
Expand All @@ -75,6 +76,7 @@ void MediaClip::setClipEnd(qint64 ms)
}
m_clipEnd = ms;
emit clipEndChanged();
emit clipDurationChanged();
}

void MediaClip::render()
Expand Down
4 changes: 4 additions & 0 deletions src/MediaFX/media_clip.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ class MediaClip : public QObject, public QQmlParserStatus {
Q_PROPERTY(QUrl source READ source WRITE setSource REQUIRED FINAL)
Q_PROPERTY(int clipStart READ clipStart WRITE setClipStart NOTIFY clipStartChanged FINAL)
Q_PROPERTY(int clipEnd READ clipEnd WRITE setClipEnd NOTIFY clipEndChanged FINAL)
Q_PROPERTY(int clipDuration READ clipDuration NOTIFY clipDurationChanged FINAL)
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged FINAL)
Q_PROPERTY(Interval clipCurrentTime READ clipCurrentTime NOTIFY clipCurrentTimeChanged FINAL)
QML_ELEMENT

signals:
void clipStartChanged();
void clipEndChanged();
void clipDurationChanged();
void activeChanged(bool);
void clipCurrentTimeChanged();
void clipEnded();
Expand All @@ -59,6 +61,8 @@ class MediaClip : public QObject, public QQmlParserStatus {
qint64 clipEnd() const { return m_clipEnd; };
void setClipEnd(qint64 ms);

qint64 clipDuration() const { return m_clipEnd - m_clipStart; };

const Interval& clipCurrentTime() const { return m_currentFrameTime; };

void setActive(bool active);
Expand Down
6 changes: 6 additions & 0 deletions src/MediaFX/media_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#pragma once

#include "interval.h"
#include <QJSEngine>
#include <QList>
#include <QObject>
Expand All @@ -35,6 +36,11 @@ class MediaManager : public QObject {

static MediaManager* singletonInstance();

Q_INVOKABLE Interval createInterval(qint64 start, qint64 end)
{
return Interval(start, end);
};

Session* session() { return m_session; };

void registerClip(MediaClip* clip);
Expand Down
81 changes: 81 additions & 0 deletions src/MediaFX/qml/MediaSequence.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (C) 2024 Andrew Wason
//
// This file is part of mediaFX.
//
// mediaFX is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// mediaFX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with mediaFX.
// If not, see <https://www.gnu.org/licenses/>.

import QtQuick
import QtMultimedia
import MediaFX
import "sequence.js" as Sequence

Item {
id: root

required default property VideoOutput videoOutput
required property list<MediaClip> mediaClips
required property list<MediaMixer> mediaMixers
property int mixDuration: 2500 //XXX ms duration of each mixer

signal mediaSequenceEnded()

Item {
id: internal

property int currentClipIndex: 0
property int currentMixerIndex: 0
property interval mixInterval: MediaManager.createInterval(-1, -1)

anchors.fill: parent

VideoOutput {
id: auxVideo
parent: root.videoOutput.parent
x: root.videoOutput.x
y: root.videoOutput.y
width: root.videoOutput.width
height: root.videoOutput.height
fillMode: root.videoOutput.fillMode
visible: false
}
states: [
State {
name: "video"
PropertyChanges {
Media.clip: root.mediaClips[currentClipIndex]
target: root.videoOutput
}
},
State {
name: "mixer"
PropertyChanges {
Media.clip: root.mediaClips[currentClipIndex]
layer.enabled: true
visible: false
target: root.videoOutput
}
PropertyChanges {
Media.clip: (currentClipIndex + 1 >= root.mediaClips.length) ? null : root.mediaClips[currentClipIndex + 1]
layer.enabled: true
target: auxVideo
}
PropertyChanges {
source: root.videoOutput
dest: auxVideo
target: root.mediaMixers[currentMixerIndex]
}
}
]

Component.onCompleted: Sequence.initializeClip()
}
}
21 changes: 21 additions & 0 deletions src/MediaFX/qml/effects/CrossFadeMixer.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (C) 2024 Andrew Wason
//
// This file is part of mediaFX.
//
// mediaFX is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// mediaFX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with mediaFX.
// If not, see <https://www.gnu.org/licenses/>.

import QtQuick
import MediaFX

MediaMixer {
fragmentShader: "shaders/crossfade.frag.qsb"
}
File renamed without changes.
File renamed without changes.
46 changes: 46 additions & 0 deletions src/MediaFX/qml/sequence.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (C) 2024 Andrew Wason
//
// This file is part of mediaFX.
//
// mediaFX is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// mediaFX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with mediaFX.
// If not, see <https://www.gnu.org/licenses/>.

function onClipEnded() {
if (internal.currentClipIndex + 1 < root.mediaClips.length) {
internal.currentClipIndex += 1;
initializeClip();
}
internal.currentMixerIndex = (internal.currentMixerIndex + 1) % root.mediaMixers.length;
root.mediaMixers[internal.currentMixerIndex].time = 0;
};

function onClipCurrentTimeChanged() {
var clip = root.mediaClips[internal.currentClipIndex];
if (internal.mixInterval.contains(clip.clipCurrentTime)) {
internal.state = "mixer";
root.mediaMixers[internal.currentMixerIndex].time = internal.mixInterval.duration / (clip.clipCurrentTime.start - internal.mixInterval.start);
}
};

function initializeClip() {
var clip = root.mediaClips[internal.currentClipIndex];
// Last clip
if (internal.currentClipIndex >= root.mediaClips.length - 1) {
clip.onClipEnded.connect(root.mediaSequenceEnded)
}
else {
var clampedMixDuration = Math.min(Math.min(root.mixDuration, clip.duration), root.mediaClips[internal.currentClipIndex + 1].duration);
internal.mixInterval = MediaManager.createInterval(clip.clipEnd - clampedMixDuration, clip.clipEnd);
clip.onClipCurrentTimeChanged = onClipCurrentTimeChanged;
clip.onClipEnded = onClipEnded;
}
internal.state = "video";
};
102 changes: 0 additions & 102 deletions tests/qml/MediaSequence.qml

This file was deleted.

0 comments on commit 93a43d0

Please sign in to comment.