... | ... |
@@ -6,6 +6,38 @@ Rotate [`mpv`][] videos by [arbitrary angles on the GPU][]. |
6 | 6 |
[`mpv`]: https://mpv.io |
7 | 7 |
[arbitrary angles on the GPU]: https://github.com/mpv-player/mpv/issues/3434#issuecomment-275195855 |
8 | 8 |
|
9 |
+## Installation |
|
10 |
+ |
|
11 |
+Copy or [symlink][] the following file into the [`mpv` configuration |
|
12 |
+directory][], preserving subdirectories: |
|
13 |
+ |
|
14 |
+- [`scripts/gpu_rotate.lua`][] |
|
15 |
+ |
|
16 |
+Example usage configuration can be found in: |
|
17 |
+ |
|
18 |
+- [`mpv.conf.example`][] |
|
19 |
+- [`input.conf.example`][] |
|
20 |
+ |
|
21 |
+On Unix-likes, creating symlinks can be done automatically by [`stow`][] by |
|
22 |
+running the following from the repository root: |
|
23 |
+ |
|
24 |
+```sh |
|
25 |
+stow --no-folding --ignore='\.example$' --target="$HOME/.config/mpv" . |
|
26 |
+``` |
|
27 |
+ |
|
28 |
+[symlink]: https://en.wikipedia.org/wiki/Symbolic_link |
|
29 |
+[`mpv` configuration directory]: https://mpv.io/manual/master/#files |
|
30 |
+[`scripts/gpu_rotate.lua`]: scripts/gpu_rotate.lua |
|
31 |
+[`mpv.conf.example`]: mpv.conf.example |
|
32 |
+[`input.conf.example`]: input.conf.example |
|
33 |
+[`stow`]: https://www.gnu.org/software/stow/ |
|
34 |
+ |
|
35 |
+## Contributing |
|
36 |
+ |
|
37 |
+Lint with [`luacheck`][]. |
|
38 |
+ |
|
39 |
+[`luacheck`]: https://github.com/mpeterv/luacheck |
|
40 |
+ |
|
9 | 41 |
## License |
10 | 42 |
|
11 | 43 |
Licensed under the [ISC License][] unless otherwise noted, see the |
0 | 4 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,8 @@ |
1 |
+# Usually the default. Writes speratate shader files to change rotation angle. |
|
2 |
+# `os.tmpname()` is used to generate the filenames. On some systems this file |
|
3 |
+# is readable by other users, but it contains no user- or video-specific |
|
4 |
+# information, only the rotation angle. |
|
5 |
+vo=gpu |
|
6 |
+ |
|
7 |
+# Enable debug printing. |
|
8 |
+# msg-level=gpu_rotate=debug |
0 | 9 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,75 @@ |
1 |
+--- Require |
|
2 |
+ |
|
3 |
+local mp = require("mp") |
|
4 |
+ |
|
5 |
+--- Constants |
|
6 |
+ |
|
7 |
+local SHADER_META = [[ |
|
8 |
+//!HOOK MAINPRESUB |
|
9 |
+//!DESC GPU rotate |
|
10 |
+//!BIND HOOKED |
|
11 |
+]] |
|
12 |
+ |
|
13 |
+local SHADER_DEFINE = "#define angle" |
|
14 |
+ |
|
15 |
+local SHADER_HOOK = [[ |
|
16 |
+vec4 hook() |
|
17 |
+{ |
|
18 |
+ float rad = radians(angle); |
|
19 |
+ float c = cos(rad); |
|
20 |
+ float s = sin(rad); |
|
21 |
+ mat2 rot = mat2(c, -s, s, c); |
|
22 |
+ vec2 pos = rot * ((HOOKED_pos - 0.5) * HOOKED_size) * HOOKED_pt + 0.5; |
|
23 |
+ if (!all(equal(pos, clamp(pos, 0.0, 1.0)))) |
|
24 |
+ return vec4(0.0); |
|
25 |
+ return HOOKED_tex(pos); |
|
26 |
+} |
|
27 |
+]] |
|
28 |
+ |
|
29 |
+--- State |
|
30 |
+ |
|
31 |
+local state = { |
|
32 |
+ angle = 0.0, |
|
33 |
+ shader = nil, |
|
34 |
+} |
|
35 |
+ |
|
36 |
+--- Functions |
|
37 |
+ |
|
38 |
+local function shader_define() |
|
39 |
+ return table.concat({SHADER_DEFINE, state.angle}, " ") |
|
40 |
+end |
|
41 |
+ |
|
42 |
+local function remove() |
|
43 |
+ if state.shader then |
|
44 |
+ mp.msg.debug("Removing", state.shader) |
|
45 |
+ mp.commandv("change-list", "glsl-shaders", "remove", state.shader) |
|
46 |
+ os.remove(state.shader) |
|
47 |
+ state.shader = nil |
|
48 |
+ end |
|
49 |
+end |
|
50 |
+ |
|
51 |
+local function append(angle) |
|
52 |
+ state.angle = angle % 360 |
|
53 |
+ remove() |
|
54 |
+ state.shader = os.tmpname() |
|
55 |
+ mp.msg.debug("Writing", state.shader) |
|
56 |
+ local file = io.open(state.shader, "w") |
|
57 |
+ file:write(table.concat({ |
|
58 |
+ SHADER_META, |
|
59 |
+ shader_define(), |
|
60 |
+ SHADER_HOOK, |
|
61 |
+ }, "\n")) |
|
62 |
+ file:close() |
|
63 |
+ mp.commandv("change-list", "glsl-shaders", "append", state.shader) |
|
64 |
+end |
|
65 |
+ |
|
66 |
+--- Events |
|
67 |
+ |
|
68 |
+mp.register_event("shutdown", remove) |
|
69 |
+ |
|
70 |
+--- Script messages |
|
71 |
+ |
|
72 |
+local function set(angle) append(angle) end |
|
73 |
+local function add(angle) append(angle + state.angle) end |
|
74 |
+mp.register_script_message("set", set) |
|
75 |
+mp.register_script_message("add", add) |