summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flake.lock104
-rw-r--r--flake.nix18
-rw-r--r--meson_options.txt2
-rwxr-xr-xscripts/line_count.sh5
-rw-r--r--scripts/screenrc2
-rw-r--r--src/buffer/video.c2
-rw-r--r--src/cache/entry.c9
-rw-r--r--src/cache/entry.h5
-rw-r--r--src/cache/handler.h3
-rw-r--r--src/cache/handlers/cdio.c4
-rw-r--r--src/cache/handlers/file.c22
-rw-r--r--src/cache/handlers/file.h2
-rw-r--r--src/cache/handlers/http.c4
-rw-r--r--src/codec/codec.h52
-rw-r--r--src/codec/codecs.c96
-rw-r--r--src/codec/codecs.h15
-rw-r--r--src/codec/ffmpeg/decoder.c10
-rw-r--r--src/codec/meson.build2
-rw-r--r--src/codec/spng/meson.build7
-rw-r--r--src/codec/spng/server.c7
-rw-r--r--src/codec/stb_image/meson.build7
-rw-r--r--src/codec/wuffs/client.c100
-rw-r--r--src/codec/wuffs/impl.c204
-rw-r--r--src/codec/wuffs/inc.h12
-rw-r--r--src/codec/wuffs/meson.build7
-rw-r--r--src/codec/wuffs/server.c102
-rw-r--r--src/liana/client.c18
-rw-r--r--src/liana/handlers.h2
-rw-r--r--src/liana/handlers/cdio.h2
-rw-r--r--src/liana/handlers/codec.h4
-rw-r--r--src/liana/handlers/codec_client.c11
-rw-r--r--src/liana/handlers/codec_server.c42
-rw-r--r--src/liana/handlers/dvd.h2
-rw-r--r--src/liana/handlers/handler.h (renamed from src/liana/handler.h)6
-rw-r--r--src/liana/server.c7
-rw-r--r--src/liana/vcr.c3
-rw-r--r--src/libsink/sink.c2
-rw-r--r--src/portal/py/modules/youtube.py3
-rw-r--r--src/render/queue_libplacebo.c2
-rw-r--r--src/render/renderer.h1
-rw-r--r--src/render/renderer_libplacebo.c15
-rw-r--r--src/render/renderer_libplacebo.h1
-rw-r--r--src/screen/screen.c1
-rw-r--r--subprojects/libalabaster.wrap4
-rw-r--r--subprojects/libnaunet.wrap4
-rw-r--r--subprojects/stela.wrap4
46 files changed, 615 insertions, 322 deletions
diff --git a/flake.lock b/flake.lock
index 4fc758c..b2649b4 100644
--- a/flake.lock
+++ b/flake.lock
@@ -16,6 +16,24 @@
"type": "github"
}
},
+ "flake-utils": {
+ "inputs": {
+ "systems": "systems"
+ },
+ "locked": {
+ "lastModified": 1731533236,
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
"home-manager": {
"inputs": {
"nixpkgs": [
@@ -23,11 +41,11 @@
]
},
"locked": {
- "lastModified": 1753294394,
- "narHash": "sha256-1Dfgq09lHZ8AdYB2Deu/mYP1pMNpob8CgqT5Mzo44eI=",
+ "lastModified": 1754842705,
+ "narHash": "sha256-2vvncPLsBWV6dRM5LfGHMGYZ+vzqRDqSPBzxPAS0R/A=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "1fde6fb1be6cd5dc513dc1c287d69e4eb2de973e",
+ "rev": "91586008a23c01cc32894ee187dca8c0a7bd20a4",
"type": "github"
},
"original": {
@@ -37,13 +55,32 @@
"type": "github"
}
},
+ "nixgl": {
+ "inputs": {
+ "flake-utils": "flake-utils",
+ "nixpkgs": "nixpkgs"
+ },
+ "locked": {
+ "lastModified": 1752054764,
+ "narHash": "sha256-Ob/HuUhANoDs+nvYqyTKrkcPXf4ZgXoqMTQoCK0RFgQ=",
+ "owner": "nix-community",
+ "repo": "nixGL",
+ "rev": "a8e1ce7d49a149ed70df676785b07f63288f53c5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "nixGL",
+ "type": "github"
+ }
+ },
"nixos-hardware": {
"locked": {
- "lastModified": 1753122741,
- "narHash": "sha256-nFxE8lk9JvGelxClCmwuJYftbHqwnc01dRN4DVLUroM=",
+ "lastModified": 1754564048,
+ "narHash": "sha256-dz303vGuzWjzOPOaYkS9xSW+B93PSAJxvBd6CambXVA=",
"owner": "NixOS",
"repo": "nixos-hardware",
- "rev": "cc66fddc6cb04ab479a1bb062f4d4da27c936a22",
+ "rev": "26ed7a0d4b8741fe1ef1ee6fa64453ca056ce113",
"type": "github"
},
"original": {
@@ -56,14 +93,14 @@
"nixos-wsl": {
"inputs": {
"flake-compat": "flake-compat",
- "nixpkgs": "nixpkgs"
+ "nixpkgs": "nixpkgs_2"
},
"locked": {
- "lastModified": 1752682362,
- "narHash": "sha256-ZNIpqCG/CfhmV+TgIeyO/XbhDjSWpwWokHM44j0Mn0w=",
+ "lastModified": 1754326498,
+ "narHash": "sha256-3ynDaygIzQYlBZFHGDeQzXmPkX2ILeZ0wWJ84FR4g7E=",
"owner": "nix-community",
"repo": "NixOS-WSL",
- "rev": "20001f9bf0aaf2b1c307e43a5eec8cf8f800fe14",
+ "rev": "ca55236cd9ef3cdea29b51a0b52a9402c60e9a27",
"type": "github"
},
"original": {
@@ -75,11 +112,26 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1751792365,
- "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=",
+ "lastModified": 1746378225,
+ "narHash": "sha256-OeRSuL8PUjIfL3Q0fTbNJD/fmv1R+K2JAOqWJd3Oceg=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "93e8cdce7afc64297cfec447c311470788131cd9",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_2": {
+ "locked": {
+ "lastModified": 1754214453,
+ "narHash": "sha256-Q/I2xJn/j1wpkGhWkQnm20nShYnG7TI99foDBpXm1SY=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb",
+ "rev": "5b09dc45f24cf32316283e62aec81ffee3c3e376",
"type": "github"
},
"original": {
@@ -89,13 +141,13 @@
"type": "github"
}
},
- "nixpkgs_2": {
+ "nixpkgs_3": {
"locked": {
- "lastModified": 1752950548,
- "narHash": "sha256-NS6BLD0lxOrnCiEOcvQCDVPXafX1/ek1dfJHX1nUIzc=",
+ "lastModified": 1754725699,
+ "narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "c87b95e25065c028d31a94f06a62927d18763fdf",
+ "rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054",
"type": "github"
},
"original": {
@@ -108,9 +160,25 @@
"root": {
"inputs": {
"home-manager": "home-manager",
+ "nixgl": "nixgl",
"nixos-hardware": "nixos-hardware",
"nixos-wsl": "nixos-wsl",
- "nixpkgs": "nixpkgs_2"
+ "nixpkgs": "nixpkgs_3"
+ }
+ },
+ "systems": {
+ "locked": {
+ "lastModified": 1681028828,
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+ "owner": "nix-systems",
+ "repo": "default",
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-systems",
+ "repo": "default",
+ "type": "github"
}
}
},
diff --git a/flake.nix b/flake.nix
index 72331f7..5217ebb 100644
--- a/flake.nix
+++ b/flake.nix
@@ -3,6 +3,9 @@
nixpkgs = {
url = "github:NixOS/nixpkgs/nixos-unstable";
};
+ nixgl = {
+ url = "github:nix-community/nixGL";
+ };
nixos-hardware = {
url = "github:NixOS/nixos-hardware/master";
};
@@ -15,7 +18,7 @@
};
};
- outputs = { self, nixpkgs, nixos-hardware, nixos-wsl, home-manager }: let
+ outputs = { self, nixpkgs, nixgl, nixos-hardware, nixos-wsl, home-manager }: let
overlays = [
(self: super: {
libplacebo = super.libplacebo.overrideAttrs (oldAttrs: {
@@ -40,6 +43,7 @@
];
});
})
+ nixgl.overlays.default
];
forAllSupportedSystems = function:
nixpkgs.lib.genAttrs [
@@ -82,8 +86,8 @@
name = "camu";
version = "0.01";
src = fetchgit {
- url = "https://git.akon.city/camu";
- rev = "0b13cf2a3bbd105fe4326e8e005536da43684df6";
+ url = "https://git.akon.city/camu.git";
+ rev = "2cc385b71e161eae39915bf24de53d5b704e7ea0";
postFetch = ''
export NIX_SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
@@ -101,7 +105,7 @@
find subprojects -type d -name .git -prune -execdir rm -r {} +
'';
- sha256 = "y7hz0nA2krkNvcNo57p1mqCEz8ebZ9bNtW4Qa0tA5dc=";
+ sha256 = "LyW2Y/o4mPAA5x9wmjh4DEKFRGwbEjHp1eurEs1Xwl0=";
};
outputs = [ "out" "dev" ];
nativeBuildInputs = [
@@ -149,6 +153,7 @@
lcms
shaderc
libGL
+ vulkan-loader
vulkan-headers
vulkan-validation-layers
libxkbcommon
@@ -242,6 +247,7 @@
export SHELL="${pkgs.bashInteractive}/bin/bash"
# Vulkan ICDs
export XDG_DATA_DIRS="${pkgs.mesa}/share:$XDG_DATA_DIRS"
+ # EGL from Nix
export __EGL_VENDOR_LIBRARY_DIRS="${pkgs.mesa}/share/glvnd/egl_vendor.d:$__EGL_VENDOR_LIBRARY_DIRS"
export NIX_BUILD_SHELL=$SHELL
export NIX_SHELL="camu-${system}+dev"
@@ -292,6 +298,9 @@
cmake
gdb
wineWowPackages.staging
+ # Use nixGLIntel to run wine
+ pkgs.nixgl.nixGLIntel
+ pkgs.nixgl.nixVulkanIntel
# clang-cl
clang
msitools
@@ -332,6 +341,7 @@
shellHook = ''
export SHELL="${pkgs.bashInteractive}/bin/bash"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.stdenv.cc.cc.lib}/lib"
+ export XDG_DATA_DIRS="${pkgs.mesa}/share:$XDG_DATA_DIRS"
export NIX_BUILD_SHELL=$SHELL
export NIX_SHELL="camu-mingw64"
export PS1="(\$NIX_SHELL)"$PS1
diff --git a/meson_options.txt b/meson_options.txt
index 4a52f07..b179bb5 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,5 +1,5 @@
# Options
-option('codecs', type: 'array', choices: ['ffmpeg', 'stb_image', 'spng', 'wuffs'], value: ['ffmpeg'])
+option('codecs', type: 'array', choices: ['ffmpeg', 'stb_image', 'wuffs', 'spng'], value: ['ffmpeg'])
option('codec-hwaccel', type: 'feature', value: 'disabled', yield: true)
option('renderer', type: 'combo', choices: ['libplacebo', 'momo'], value: 'libplacebo')
option('renderer-api', type: 'combo', choices: ['vulkan', 'dx11', 'gl', 'gl-rpi'], value: 'vulkan', yield: true)
diff --git a/scripts/line_count.sh b/scripts/line_count.sh
index b7e8439..2ff0e9c 100755
--- a/scripts/line_count.sh
+++ b/scripts/line_count.sh
@@ -1,13 +1,14 @@
#! /usr/bin/env sh
export LC_ALL="C"
-find ./src -type f \
+find ./src ./scripts ./env -type f \
-not -path "*__pycache__*" \
-not -path "./src/fruits/droid/*" \
-not -path "./src/portal/cpy/portal.c" \
-not -path "./src/portal/cpy/portal.h" \
-not -path "./src/portal/patches/*" \
+ -not -path "./src/portal/py/.mypy_cache/*" \
-not -path "./src/portal/py/tests/*" \
-not -path "./src/portal/vendor/*" \
- -exec loccount {} +
+ -exec sloccount {} +
#-exec sed -i 's///g' {} +
diff --git a/scripts/screenrc b/scripts/screenrc
index 6381a9e..24bc58d 100644
--- a/scripts/screenrc
+++ b/scripts/screenrc
@@ -6,5 +6,5 @@ screen -t 'cmsrv' ./src/fruits/cmsrv/cmsrv
split
resize -v 75%
focus
-screen -t 'cmsrv_debug'
+screen -t 'cmsrv_debug' $SHELL
stuff 'sleep 1 && gdb -p $(pgrep cmsrv) -ex cont '
diff --git a/src/buffer/video.c b/src/buffer/video.c
index ab61c2a..7874615 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -87,7 +87,7 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code
#ifdef CAMU_HAVE_FFMPEG
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((enum AVPixelFormat)fmt->format);
bool has_alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0;
- req->format = has_alpha ? CAMU_PIXEL_FORMAT_RGB32 : CAMU_PIXEL_FORMAT_RGB24;
+ req->format = has_alpha ? CAMU_PIXEL_FORMAT_RGBA : CAMU_PIXEL_FORMAT_RGB24;
buf->scaler = camu_ff_scaler_create();
if (!buf->scaler->init(buf->scaler, &buf->fmt)) {
// Scaler will be freed in video_buffer_free().
diff --git a/src/cache/entry.c b/src/cache/entry.c
index 183278a..0f50462 100644
--- a/src/cache/entry.c
+++ b/src/cache/entry.c
@@ -12,9 +12,14 @@ bool cch_entry_get_handle(struct cch_entry *entry, struct cch_handle *handle)
return true;
}
-str *cch_entry_get_liana(struct cch_entry *entry)
+str *cch_entry_get_handler(struct cch_entry *entry)
{
- return &entry->handler->liana;
+ return &entry->handler->handler;
+}
+
+s32 cch_entry_guess_format(struct cch_entry *entry)
+{
+ return entry->handler->guess_format(entry->handler);
}
void cch_entry_return_handle(struct cch_entry *entry, struct cch_handle *handle)
diff --git a/src/cache/entry.h b/src/cache/entry.h
index d6eb86a..693e68b 100644
--- a/src/cache/entry.h
+++ b/src/cache/entry.h
@@ -80,7 +80,7 @@
[ ] On creation, the handler can create multiple backings and chapters.
[ ] Chapters include index into array of backings.
[ ] Method of requesting a unique file backing.
- */
+*/
struct cch_chapter {
off_t start;
@@ -95,6 +95,7 @@ struct cch_entry {
};
bool cch_entry_get_handle(struct cch_entry *entry, struct cch_handle *handle);
-str *cch_entry_get_liana(struct cch_entry *entry);
+str *cch_entry_get_handler(struct cch_entry *entry);
+s32 cch_entry_guess_format(struct cch_entry *entry);
void cch_entry_return_handle(struct cch_entry *entry, struct cch_handle *handle);
void cch_entry_free(struct cch_entry **entry);
diff --git a/src/cache/handler.h b/src/cache/handler.h
index 4051449..fec7f0a 100644
--- a/src/cache/handler.h
+++ b/src/cache/handler.h
@@ -9,7 +9,8 @@ struct cch_handler {
bool (*can_seek)(struct cch_handler *);
void (*maybe_spawn_worker)(struct cch_handler *, size_t);
bool (*wait_for_range)(struct cch_handler *, struct cch_wait *);
+ s32 (*guess_format)(struct cch_handler *);
void (*free)(struct cch_handler **);
struct cch_entry *entry;
- str liana;
+ str handler;
};
diff --git a/src/cache/handlers/cdio.c b/src/cache/handlers/cdio.c
index 7c83523..abebeb0 100644
--- a/src/cache/handlers/cdio.c
+++ b/src/cache/handlers/cdio.c
@@ -119,7 +119,7 @@ static void handler_cdio_free(struct cch_handler **handler)
cdio_cddap_close(cdio->drive);
}
cch_threaded_waits_close(&cdio->waits);
- al_str_free(&cdio->handler.liana);
+ al_str_free(&cdio->handler.handler);
al_free(cdio);
*handler = NULL;
}
@@ -198,7 +198,7 @@ struct cch_entry *cch_handler_cdio_create(void)
entry->handler->wait_for_range = handler_cdio_wait_for_range;
entry->handler->free = handler_cdio_free;
entry->handler->entry = entry;
- al_str_from(&entry->handler->liana, "cdio");
+ al_str_from(&entry->handler->handler, "cdio");
if (!open_cd_drive(cdio)) {
return NULL;
}
diff --git a/src/cache/handlers/file.c b/src/cache/handlers/file.c
index 345cdca..dba5649 100644
--- a/src/cache/handlers/file.c
+++ b/src/cache/handlers/file.c
@@ -1,3 +1,5 @@
+#include "../../codec/codec.h"
+
#include "../backings/file.h"
#include "file.h"
@@ -22,15 +24,28 @@ static bool handler_file_wait_for_range(struct cch_handler *handler, struct cch_
return true;
}
+static s32 handler_file_guess_format(struct cch_handler *handler)
+{
+ struct cch_handler_file *file = (struct cch_handler_file *)handler;
+ struct cch_backing_file *backing = (struct cch_backing_file *)file->backing;
+ str *path = &backing->file.path;
+ u32 dot = al_str_rfind(path, '.');
+ if (dot != AL_STR_NPOS) {
+ str ext = al_str_substr(path, dot, path->length);
+ return camu_guess_format(NULL, &ext, NULL);
+ }
+ return -1;
+}
+
static void handler_file_free(struct cch_handler **handler)
{
struct cch_handler_file *file = (struct cch_handler_file *)*handler;
- al_str_free(&file->handler.liana);
+ al_str_free(&file->handler.handler);
al_free(file);
*handler = NULL;
}
-struct cch_entry *cch_handler_file_create(str *path, str *liana)
+struct cch_entry *cch_handler_file_create(str *path, str *handler)
{
struct cch_backing *backing = cch_backing_file_create(path, 0);
if (!backing) return NULL;
@@ -42,8 +57,9 @@ struct cch_entry *cch_handler_file_create(str *path, str *liana)
entry->handler->can_seek = handler_file_can_seek;
entry->handler->maybe_spawn_worker = handler_file_maybe_spawn_worker;
entry->handler->wait_for_range = handler_file_wait_for_range;
+ entry->handler->guess_format = handler_file_guess_format;
entry->handler->free = handler_file_free;
entry->handler->entry = entry;
- al_str_clone(&entry->handler->liana, liana);
+ al_str_clone(&entry->handler->handler, handler);
return entry;
}
diff --git a/src/cache/handlers/file.h b/src/cache/handlers/file.h
index 4704387..f883498 100644
--- a/src/cache/handlers/file.h
+++ b/src/cache/handlers/file.h
@@ -10,4 +10,4 @@ struct cch_handler_file {
struct cch_backing *backing;
};
-struct cch_entry *cch_handler_file_create(str *path, str *liana);
+struct cch_entry *cch_handler_file_create(str *path, str *handler);
diff --git a/src/cache/handlers/http.c b/src/cache/handlers/http.c
index e48490b..1691ea9 100644
--- a/src/cache/handlers/http.c
+++ b/src/cache/handlers/http.c
@@ -102,7 +102,7 @@ static void handler_http_free(struct cch_handler **handler)
cch_threaded_waits_close(&http->waits);
al_array_free(http->requests);
al_str_free(&http->url);
- al_str_free(&http->handler.liana);
+ al_str_free(&http->handler.handler);
al_free(http);
*handler = NULL;
}
@@ -121,7 +121,7 @@ struct cch_entry *cch_handler_http_create(str *url, struct nn_event_loop *loop)
entry->handler->wait_for_range = handler_http_wait_for_range;
entry->handler->free = handler_http_free;
entry->handler->entry = entry;
- al_str_from(&entry->handler->liana, "codec");
+ al_str_from(&entry->handler->handler, "codec");
http->loop = loop;
al_str_clone(&http->url, url);
http->pointer = 0;
diff --git a/src/codec/codec.h b/src/codec/codec.h
index 25ec73e..701ef16 100644
--- a/src/codec/codec.h
+++ b/src/codec/codec.h
@@ -1,6 +1,7 @@
#pragma once
#include <al/array.h>
+#include <al/str.h>
#include <nnwt/common.h>
#ifdef CAMU_HAVE_FFMPEG
#include <libavutil/pixdesc.h>
@@ -9,6 +10,8 @@
#include "../cache/handle.h"
+#include "codecs.h"
+
enum {
CAMU_LANG_UNKNOWN = 0,
CAMU_LANG_ENGLISH,
@@ -59,7 +62,6 @@ enum {
enum {
CAMU_PIXEL_FORMAT_RGBA = AV_PIX_FMT_RGBA,
- CAMU_PIXEL_FORMAT_RGB8 = AV_PIX_FMT_RGB8,
CAMU_PIXEL_FORMAT_RGB24 = AV_PIX_FMT_RGB24,
CAMU_PIXEL_FORMAT_RGB32 = AV_PIX_FMT_RGB32,
CAMU_PIXEL_FORMAT_GREYA = AV_PIX_FMT_GRAY8A,
@@ -67,6 +69,13 @@ enum {
CAMU_PIXEL_FORMAT_PAL8 = AV_PIX_FMT_PAL8
};
+enum {
+ CAMU_CODEC_FALLBACK = -1,
+ CAMU_CODEC_NONE = AV_CODEC_ID_NONE,
+ CAMU_CODEC_PNG = AV_CODEC_ID_PNG,
+ CAMU_CODEC_JPEG = AV_CODEC_ID_MJPEG
+};
+
#define CAMU_PLANAR_DATA_POINTERS AV_NUM_DATA_POINTERS
#else
enum {
@@ -107,9 +116,18 @@ enum {
enum {
CAMU_PIXEL_FORMAT_RGBA = 0,
- CAMU_PIXEL_FORMAT_RGB,
+ CAMU_PIXEL_FORMAT_RGB24,
+ CAMU_PIXEL_FORMAT_RGB32,
CAMU_PIXEL_FORMAT_GREYA,
- CAMU_PIXEL_FORMAT_GREY
+ CAMU_PIXEL_FORMAT_GREY,
+ CAMU_PIXEL_FORMAT_PAL8
+};
+
+enum {
+ CAMU_CODEC_FALLBACK = -1,
+ CAMU_CODEC_NONE,
+ CAMU_CODEC_PNG,
+ CAMU_CODEC_JPEG
};
#define CAMU_PLANAR_DATA_POINTERS 8
@@ -150,6 +168,7 @@ struct camu_codec_stream {
u8 type;
s32 index;
u64 duration;
+ struct camu_codec_info *codec_info;
struct {
struct camu_video_format fmt;
} video;
@@ -256,6 +275,7 @@ static inline bool camu_resampler_format_matches(struct camu_resampler_format *f
&& fmt->in.channel_count == fmt->req.channel_count;
}
+#ifdef CAMU_HAVE_FFMPEG
#ifndef CAMU_OLD_FFMPEG
#define AV_CODECPAR_CHANNEL_LAYOUT(codecpar) ((codecpar)->ch_layout)
#define AV_CODECPAR_CHANNELS(codecpar) ((codecpar)->ch_layout.nb_channels)
@@ -279,6 +299,7 @@ static inline void camu_copy_channel_layout(u64 *dest, u64 *src)
*dest = *src;
}
#endif
+#endif
static inline void camu_audio_format_copy(struct camu_audio_format *dest, struct camu_audio_format *src)
{
@@ -408,3 +429,28 @@ static inline void camu_codec_frame_discard(struct camu_codec_frame *frame)
if (frame->mode == CAMU_NORMAL && frame->data) al_free(frame->data);
al_free(frame);
}
+
+static inline s32 camu_guess_format(str *short_name, str *ext, str *mime_type)
+{
+ if (al_str_eq(ext, &al_str_c(".png"))) {
+ return CAMU_CODEC_PNG;
+ } else if (al_str_eq(ext, &al_str_c(".jpeg")) || al_str_eq(ext, &al_str_c(".jpg"))) {
+ return CAMU_CODEC_JPEG;
+ }
+#ifdef CAMU_HAVE_FFMPEG
+ char *c_short_name = short_name ? al_str_to_c_str(short_name) : NULL;
+ char *c_ext = ext ? al_str_to_c_str(ext) : NULL;
+ char *c_mime_type = mime_type ? al_str_to_c_str(mime_type) : NULL;
+ // Empty short_name to attempt avoiding image2 probing.
+ const AVOutputFormat *fmt = av_guess_format(c_short_name ? c_short_name : "", c_ext, c_mime_type);
+ if (c_short_name) al_free(c_short_name);
+ if (c_ext) al_free(c_ext);
+ if (c_mime_type) al_free(c_mime_type);
+ // In FFmpeg AV_CODEC_ID_MJPEG also means "image2".
+ if (fmt) return (fmt->audio_codec != AV_CODEC_ID_NONE) ? fmt->audio_codec : fmt->video_codec;
+#else
+ (void)short_name;
+ (void)mime_type;
+#endif
+ return -1;
+}
diff --git a/src/codec/codecs.c b/src/codec/codecs.c
new file mode 100644
index 0000000..7374517
--- /dev/null
+++ b/src/codec/codecs.c
@@ -0,0 +1,96 @@
+#include "codecs.h"
+#include "codec.h"
+
+#ifdef LIANA_SERVER
+#include "../../codec/wuffs/demuxer.h"
+#include "../../codec/stb_image/demuxer.h"
+#include "../../codec/spng/demuxer.h"
+#ifdef CAMU_HAVE_FFMPEG
+#include "../../codec/ffmpeg/demuxer.h"
+#endif
+#endif
+
+#ifdef LIANA_CLIENT
+#include "../../codec/wuffs/decoder.h"
+#include "../../codec/stb_image/decoder.h"
+#include "../../codec/spng/decoder.h"
+#ifdef CAMU_HAVE_FFMPEG
+#include "../../codec/ffmpeg/decoder.h"
+#endif
+#endif
+
+struct camu_codec_info codec_information[] = {
+#ifdef CAMU_HAVE_WUFFS
+ {
+ .name = al_str_c("wuffs"),
+ .supported = (s32[]){ CAMU_CODEC_PNG, CAMU_CODEC_NONE },
+#ifdef LIANA_SERVER
+ .create_demuxer = camu_wuffs_demuxer_create,
+#endif
+#ifdef LIANA_CLIENT
+ .create_decoder = camu_wuffs_decoder_create
+#endif
+ },
+#endif
+#ifdef CAMU_HAVE_STB_IMAGE
+ {
+ .name = al_str_c("stb_image"),
+ .supported = (s32[]){ CAMU_CODEC_PNG, CAMU_CODEC_JPEG, CAMU_CODEC_NONE },
+#ifdef LIANA_SERVER
+ .create_demuxer = camu_stbi_demuxer_create,
+#endif
+#ifdef LIANA_CLIENT
+ .create_decoder = camu_stbi_decoder_create
+#endif
+ },
+#endif
+#ifdef CAMU_HAVE_SPNG
+ {
+ .name = al_str_c("spng"),
+ .supported = (s32[]){ CAMU_CODEC_PNG, CAMU_CODEC_NONE },
+#ifdef LIANA_SERVER
+ .create_demuxer = camu_spng_demuxer_create,
+#endif
+#ifdef LIANA_CLIENT
+ .create_decoder = camu_spng_decoder_create
+#endif
+ },
+#endif
+#ifdef CAMU_HAVE_FFMPEG
+ {
+ .name = al_str_c("FFmpeg"),
+ .supported = (s32[]){ CAMU_CODEC_FALLBACK },
+#ifdef LIANA_SERVER
+ .create_demuxer = camu_ff_demuxer_create,
+#endif
+#ifdef LIANA_CLIENT
+ .create_decoder = camu_ff_decoder_create
+#endif
+ },
+#endif
+};
+
+struct camu_codec_info *camu_codec_info_by_type(s32 type)
+{
+ for (u32 i = 0; i < ARRAY_SIZE(codec_information); i++) {
+ struct camu_codec_info *info = &codec_information[i];
+ s32 *supported = info->supported;
+ while (*supported != CAMU_CODEC_NONE) {
+ if (type == (*supported) || (*supported) == CAMU_CODEC_FALLBACK) {
+ return info;
+ }
+ supported++;
+ }
+ }
+ return NULL;
+}
+
+struct camu_codec_info *camu_codec_info_by_name(str *name)
+{
+ for (u32 i = 0; i < ARRAY_SIZE(codec_information); i++) {
+ if (al_str_eq(&codec_information[i].name, name)) {
+ return &codec_information[i];
+ }
+ }
+ return NULL;
+}
diff --git a/src/codec/codecs.h b/src/codec/codecs.h
new file mode 100644
index 0000000..d383eec
--- /dev/null
+++ b/src/codec/codecs.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <al/str.h>
+
+struct camu_codec_info {
+ str name;
+ s32 *supported;
+ struct camu_demuxer *(*create_demuxer)(void);
+ struct camu_decoder *(*create_decoder)(void);
+};
+
+extern struct camu_codec_info codec_information[];
+
+struct camu_codec_info *camu_codec_info_by_type(s32 type);
+struct camu_codec_info *camu_codec_info_by_name(str *name);
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index cfa1dc2..7be21a2 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -151,11 +151,11 @@ static bool hw_device_supported_by_type(struct camu_ff_decoder *av, enum AVHWDev
}
*/
-static enum AVHWDeviceType hw_device_supported_by_name(struct camu_ff_decoder *av, const char *name)
+static enum AVHWDeviceType hw_device_supported_by_name(struct camu_ff_decoder *av, const char *name, size_t length)
{
enum AVHWDeviceType supported_type;
al_array_foreach(av->supported_hw_devices, i, supported_type) {
- if (strcmp(av_hwdevice_get_type_name(supported_type), name) == 0) {
+ if (al_strncmp(av_hwdevice_get_type_name(supported_type), name, length) == 0) {
return supported_type;
}
}
@@ -236,7 +236,8 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
av->hw_device_type = AV_HWDEVICE_TYPE_NONE;
av->hw_pix_fmt = AV_PIX_FMT_NONE;
for (u32 i = 0; i < ARRAY_SIZE(hwdevces); i++) {
- av->hw_device_type = hw_device_supported_by_name(av, hwdevces[i]);
+ size_t length = sizeof(hwdevces[i]) - 1;
+ av->hw_device_type = hw_device_supported_by_name(av, hwdevces[i], length);
if (!get_hwdevice_config(av, codec, av->hw_device_type)) {
av->hw_device_type = AV_HWDEVICE_TYPE_NONE;
} else {
@@ -247,7 +248,8 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
const AVCodec *hw_codec;
al_array_foreach(av->supported_hw_codecs, i, hw_codec) {
if (hw_codec->id == codecpar->codec_id) {
- av->hw_device_type = hw_device_supported_by_name(av, hw_codec->wrapper_name);
+ size_t length = al_strlen(hw_codec->wrapper_name);
+ av->hw_device_type = hw_device_supported_by_name(av, hw_codec->wrapper_name, length);
if (get_hwdevice_config(av, hw_codec, av->hw_device_type)) {
codec = hw_codec;
break;
diff --git a/src/codec/meson.build b/src/codec/meson.build
index 9401b0b..851a72a 100644
--- a/src/codec/meson.build
+++ b/src/codec/meson.build
@@ -1,4 +1,4 @@
-codec_src = ['packet_ext.c']
+codec_src = ['packet_ext.c', 'codecs.c']
codec_server_deps = []
codec_client_deps = []
diff --git a/src/codec/spng/meson.build b/src/codec/spng/meson.build
index d8af781..f99a885 100644
--- a/src/codec/spng/meson.build
+++ b/src/codec/spng/meson.build
@@ -1,3 +1,6 @@
spng = dependency('spng')
-codec_server_deps += [declare_dependency(sources: ['server.c'], dependencies: spng)]
-codec_client_deps += [declare_dependency(sources: ['client.c'], dependencies: spng)]
+spng_args = ['-DCAMU_HAVE_SPNG']
+codec_server_deps += declare_dependency(sources: ['server.c'],
+ dependencies: spng, compile_args: spng_args)
+codec_client_deps += declare_dependency(sources: ['client.c'],
+ dependencies: spng, compile_args: spng_args)
diff --git a/src/codec/spng/server.c b/src/codec/spng/server.c
index 8eb941b..1bb2ca8 100644
--- a/src/codec/spng/server.c
+++ b/src/codec/spng/server.c
@@ -13,7 +13,8 @@ static bool spng_demuxer_init(struct camu_demuxer *demux, struct cch_handle *han
spng->eof = false;
cch_handle_seek(spng->handle, 0, SEEK_SET);
- off_t size = cch_entry_get_size(spng->handle->entry);
+ struct cch_backing *backing = spng->handle->entry->backing;
+ off_t size = backing->get_size_if_known(backing);
nn_buffer_ensure_space(&spng->buffer, size);
cch_handle_read(spng->handle, nn_buffer_get_ptr(&spng->buffer, 0), size);
spng->buffer.size = size;
@@ -59,10 +60,11 @@ static u64 spng_demuxer_get_duration(struct camu_demuxer *demux)
return 0;
}
-static bool spng_demuxer_seek(struct camu_demuxer *demux, u64 pos)
+static bool spng_demuxer_seek(struct camu_demuxer *demux, u64 pos, bool bytes)
{
(void)demux;
(void)pos;
+ (void)bytes;
return true;
}
@@ -75,7 +77,6 @@ static void spng_demuxer_free(struct camu_demuxer **demux)
*demux = NULL;
}
-
struct camu_demuxer *camu_spng_demuxer_create(void)
{
struct camu_spng_demuxer *spng = al_alloc_object(struct camu_spng_demuxer);
diff --git a/src/codec/stb_image/meson.build b/src/codec/stb_image/meson.build
index fea86ff..e6faa21 100644
--- a/src/codec/stb_image/meson.build
+++ b/src/codec/stb_image/meson.build
@@ -1,3 +1,6 @@
stb = subproject('stb').get_variable('stb')
-codec_server_deps += declare_dependency(sources: ['server.c', 'impl.c'], dependencies: stb)
-codec_client_deps += declare_dependency(sources: ['client.c', 'impl.c'], dependencies: stb)
+stb_args = ['-DCAMU_HAVE_STB_IMAGE']
+codec_server_deps += declare_dependency(sources: ['server.c', 'impl.c'],
+ dependencies: stb, compile_args: stb_args)
+codec_client_deps += declare_dependency(sources: ['client.c', 'impl.c'],
+ dependencies: stb, compile_args: stb_args)
diff --git a/src/codec/wuffs/client.c b/src/codec/wuffs/client.c
new file mode 100644
index 0000000..c57e506
--- /dev/null
+++ b/src/codec/wuffs/client.c
@@ -0,0 +1,100 @@
+#include "decoder.h"
+#include "inc.h"
+
+static bool wuffs_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_codec_stream *stream,
+ void (*callback)(void *, struct camu_codec_frame *), void *userdata)
+{
+ struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec;
+ (void)renderer;
+ wfs->stream = stream;
+ wfs->callback = callback;
+ wfs->userdata = userdata;
+ return true;
+}
+
+static s32 wuffs_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet)
+{
+ struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec;
+ if (!packet) return CAMU_OK;
+
+ struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame);
+ frame->mode = CAMU_NORMAL;
+ frame->flags = 0;
+ frame->data = NULL;
+ struct camu_video_format *fmt = &wfs->stream->video.fmt;
+ frame->video.width = fmt->width;
+ frame->video.height = fmt->height;
+ frame->format = CAMU_PIXEL_FORMAT_RGBA;
+
+ wuffs_png__decoder *wf_dec = wuffs_png__decoder__alloc();
+ if (!wf_dec) goto err;
+
+ wuffs_png__decoder__set_quirk(wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true);
+
+ wuffs_base__io_buffer src = { 0 };
+ src.data.ptr = nn_buffer_get_ptr(packet->buffer, 0);
+ src.data.len = packet->buffer->size;
+ src.meta.wi = packet->buffer->size;
+ src.meta.closed = true;
+
+ wuffs_base__image_config ic = { 0 };
+ wuffs_base__status status = wuffs_png__decoder__decode_image_config(wf_dec, &ic, &src);
+ if (!wuffs_base__status__is_ok(&status)) goto err;
+ if (!wuffs_base__image_config__is_valid(&ic)) goto err;
+
+ u32 pixsub = WUFFS_BASE__PIXEL_SUBSAMPLING__NONE;
+ u32 pixfmt = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL;
+ wuffs_base__pixel_config__set(&ic.pixcfg, pixfmt, pixsub, fmt->width, fmt->height);
+
+ wuffs_base__pixel_buffer pb = { 0 };
+ size_t dst_size = fmt->width * fmt->height * 4;
+ size_t wrk_size = wuffs_png__decoder__workbuf_len(wf_dec).max_incl;
+ frame->data = camu_page_alloc(dst_size + wrk_size);
+ status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, wuffs_base__make_slice_u8(frame->data, dst_size));
+ if (!wuffs_base__status__is_ok(&status)) goto err;
+ wuffs_base__slice_u8 wrk = wuffs_base__make_slice_u8(frame->data + dst_size, wrk_size);
+
+ status = wuffs_png__decoder__decode_frame(wf_dec, &pb, &src, 0, wrk, NULL);
+ if (!wuffs_base__status__is_ok(&status)) goto err;
+
+ wfs->callback(wfs->userdata, frame);
+
+ free(wf_dec);
+
+ return CAMU_OK;
+err:
+ if (wf_dec) free(wf_dec);
+ camu_codec_frame_discard(frame);
+
+ return CAMU_ERR_ERROR;
+}
+
+static void wuffs_decoder_flush(struct camu_decoder *dec)
+{
+ (void)dec;
+}
+
+static s32 wuffs_decoder_process(struct camu_decoder *dec)
+{
+ (void)dec;
+ return CAMU_ERR_EOF;
+}
+
+static void wuffs_decoder_free(struct camu_decoder **dec)
+{
+ struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)*dec;
+ al_free(wfs);
+ *dec = NULL;
+}
+
+struct camu_decoder *camu_wuffs_decoder_create(void)
+{
+ struct camu_wuffs_decoder *wfs = al_alloc_object(struct camu_wuffs_decoder);
+ wfs->dec.mode = CAMU_NORMAL;
+ wfs->dec.init = wuffs_decoder_init;
+ wfs->dec.push = wuffs_decoder_push;
+ wfs->dec.process = wuffs_decoder_process;
+ wfs->dec.flush = wuffs_decoder_flush;
+ wfs->dec.free = wuffs_decoder_free;
+ return (struct camu_decoder *)wfs;
+}
diff --git a/src/codec/wuffs/impl.c b/src/codec/wuffs/impl.c
index 2c8f162..ab291cb 100644
--- a/src/codec/wuffs/impl.c
+++ b/src/codec/wuffs/impl.c
@@ -1,204 +1,2 @@
-#include <nnwt/common.h>
#define WUFFS_IMPLEMENTATION
-#define WUFFS_CONFIG__STATIC_FUNCTIONS
-#define WUFFS_CONFIG__MODULES
-#define WUFFS_CONFIG__MODULE__BASE
-#define WUFFS_CONFIG__MODULE__ADLER32
-#define WUFFS_CONFIG__MODULE__DEFLATE
-#define WUFFS_CONFIG__MODULE__ZLIB
-#define WUFFS_CONFIG__MODULE__CRC32
-#define WUFFS_CONFIG__MODULE__PNG
-#define WUFFS_CONFIG__MODULE__JPEG
-#define WUFFS_CONFIG__MODULE__IMAGE
-#include <wuffs-unsupported-snapshot.c>
-
-#include "../../cache/entry.h"
-
-#include "demuxer.h"
-#include "decoder.h"
-
-static bool wuffs_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle)
-{
- struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux;
-
- wfs->handle = handle;
- nn_buffer_init(&wfs->buffer);
- wfs->eof = false;
-
- cch_handle_seek(wfs->handle, 0, SEEK_SET);
- off_t size = cch_entry_get_size(wfs->handle->entry);
- nn_buffer_ensure_space(&wfs->buffer, size);
- cch_handle_read(wfs->handle, nn_buffer_get_ptr(&wfs->buffer, 0), size);
- wfs->buffer.size = size;
-
- wuffs_png__decoder wf_dec = { 0 };
- wuffs_base__status status = wuffs_png__decoder__initialize(&wf_dec, sizeof(wf_dec), WUFFS_VERSION, 0);
- if (!wuffs_base__status__is_ok(&status)) goto err;
-
- wuffs_png__decoder__set_quirk(&wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true);
-
- wuffs_base__io_buffer src = { 0 };
- src.data.ptr = nn_buffer_get_ptr(&wfs->buffer, 0);
- src.data.len = wfs->buffer.size;
- src.meta.wi = wfs->buffer.size;
- src.meta.closed = true;
-
- wuffs_base__image_config ic = { 0 };
- status = wuffs_png__decoder__decode_image_config(&wf_dec, &ic, &src);
- if (!wuffs_base__status__is_ok(&status)) goto err;
- if (!wuffs_base__image_config__is_valid(&ic)) goto err;
-
- struct camu_codec_stream stream;
- stream.mode = CAMU_NORMAL;
- stream.type = CAMU_STREAM_VIDEO;
- stream.video.width = wuffs_base__pixel_config__width(&ic.pixcfg);
- stream.video.height = wuffs_base__pixel_config__height(&ic.pixcfg);
- stream.video.format = CAMU_PIXEL_FORMAT_RGBA;
-
- al_array_push(wfs->demux.streams, stream);
-
- return true;
-err:
- return false;
-}
-
-static s32 wuffs_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet)
-{
- struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux;
- if (!wfs->eof) {
- packet->mode = CAMU_NORMAL;
- packet->buffer = &wfs->buffer;
- wfs->eof = true;
- return CAMU_OK;
- }
- return CAMU_ERR_EOF;
-}
-
-static u64 wuffs_demuxer_get_duration(struct camu_demuxer *demux)
-{
- (void)demux;
- return 0;
-}
-
-static bool wuffs_demuxer_seek(struct camu_demuxer *demux, u64 pos)
-{
- (void)demux;
- (void)pos;
- return true;
-}
-
-static void wuffs_demuxer_free(struct camu_demuxer **demux)
-{
- struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)*demux;
- nn_buffer_free(&wfs->buffer);
- al_array_free(wfs->demux.streams);
- al_free(wfs);
- *demux = NULL;
-}
-
-static bool wuffs_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_codec_stream *stream,
- void (*callback)(void *, struct camu_codec_frame *), void *userdata)
-{
- struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec;
- (void)renderer;
- wfs->stream = stream;
- wfs->callback = callback;
- wfs->userdata = userdata;
- return true;
-}
-
-static s32 wuffs_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet)
-{
- struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec;
- if (!packet) return CAMU_OK;
-
- struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame);
- frame->mode = CAMU_NORMAL;
- frame->data = NULL;
- frame->flags = 0;
- frame->width = wfs->stream->video.width;
- frame->height = wfs->stream->video.height;
- frame->format = CAMU_PIXEL_FMT_RGBA;
-
- wuffs_png__decoder wf_dec = { 0 };
- wuffs_base__status status = wuffs_png__decoder__initialize(&wf_dec, sizeof(wf_dec), WUFFS_VERSION, 0);
- if (!wuffs_base__status__is_ok(&status)) goto err;
-
- wuffs_png__decoder__set_quirk(&wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true);
-
- wuffs_base__io_buffer src = { 0 };
- src.data.ptr = nn_buffer_get_ptr(packet->buffer, 0);
- src.data.len = packet->buffer->size;
- src.meta.wi = packet->buffer->size;
- src.meta.closed = true;
-
- wuffs_base__image_config ic = { 0 };
- status = wuffs_png__decoder__decode_image_config(&wf_dec, &ic, &src);
- if (!wuffs_base__status__is_ok(&status)) goto err;
- if (!wuffs_base__image_config__is_valid(&ic)) goto err;
-
- u32 pixsub = WUFFS_BASE__PIXEL_SUBSAMPLING__NONE;
- u32 pixfmt = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL;
- wuffs_base__pixel_config__set(&ic.pixcfg, pixfmt, pixsub, frame->width, frame->height);
-
- wuffs_base__pixel_buffer pb = { 0 };
- size_t dst_size = frame->width * frame->height * 4;
- size_t wrk_size = wuffs_png__decoder__workbuf_len(&wf_dec).max_incl;
- frame->data = camu_page_alloc(dst_size + wrk_size);
- status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, wuffs_base__make_slice_u8(frame->data, dst_size));
- if (!wuffs_base__status__is_ok(&status)) goto err;
- wuffs_base__slice_u8 wrk = wuffs_base__make_slice_u8(frame->data + dst_size, wrk_size);
-
- status = wuffs_png__decoder__decode_frame(&wf_dec, &pb, &src, 0, wrk, NULL);
- if (!wuffs_base__status__is_ok(&status)) goto err;
-
- wfs->callback(wfs->userdata, frame);
-
- return CAMU_OK;
-err:
- camu_codec_frame_discard(frame);
- return CAMU_ERR_ERROR;
-}
-
-static void wuffs_decoder_flush(struct camu_decoder *dec)
-{
- (void)dec;
-}
-
-static s32 wuffs_decoder_process(struct camu_decoder *dec)
-{
- (void)dec;
- return CAMU_ERR_EOF;
-}
-
-static void wuffs_decoder_free(struct camu_decoder **dec)
-{
- struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)*dec;
- al_free(wfs);
- *dec = NULL;
-}
-
-struct camu_demuxer *camu_wuffs_demuxer_create(void)
-{
- struct camu_wuffs_demuxer *wfs = al_alloc_object(struct camu_wuffs_demuxer);
- wfs->demux.mode = CAMU_NORMAL;
- al_array_init(wfs->demux.streams);
- wfs->demux.init = wuffs_demuxer_init;
- wfs->demux.get_packet = wuffs_demuxer_get_packet;
- wfs->demux.get_duration = wuffs_demuxer_get_duration;
- wfs->demux.seek = wuffs_demuxer_seek;
- wfs->demux.free = wuffs_demuxer_free;
- return (struct camu_demuxer *)wfs;
-}
-
-struct camu_decoder *camu_wuffs_decoder_create(void)
-{
- struct camu_wuffs_decoder *wfs = al_alloc_object(struct camu_wuffs_decoder);
- wfs->dec.mode = CAMU_NORMAL;
- wfs->dec.init = wuffs_decoder_init;
- wfs->dec.push = wuffs_decoder_push;
- wfs->dec.process = wuffs_decoder_process;
- wfs->dec.flush = wuffs_decoder_flush;
- wfs->dec.free = wuffs_decoder_free;
- return (struct camu_decoder *)wfs;
-}
+#include "inc.h"
diff --git a/src/codec/wuffs/inc.h b/src/codec/wuffs/inc.h
new file mode 100644
index 0000000..51e3743
--- /dev/null
+++ b/src/codec/wuffs/inc.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#define WUFFS_CONFIG__MODULES
+#define WUFFS_CONFIG__MODULE__BASE
+#define WUFFS_CONFIG__MODULE__ADLER32
+#define WUFFS_CONFIG__MODULE__DEFLATE
+#define WUFFS_CONFIG__MODULE__ZLIB
+#define WUFFS_CONFIG__MODULE__CRC32
+#define WUFFS_CONFIG__MODULE__PNG
+#define WUFFS_CONFIG__MODULE__JPEG
+#define WUFFS_CONFIG__MODULE__IMAGE
+#include <wuffs-unsupported-snapshot.c>
diff --git a/src/codec/wuffs/meson.build b/src/codec/wuffs/meson.build
index bb5007a..5e5c398 100644
--- a/src/codec/wuffs/meson.build
+++ b/src/codec/wuffs/meson.build
@@ -1,3 +1,6 @@
wuffs = subproject('wuffs').get_variable('wuffs')
-#codec_server_deps += declare_dependency(sources: ['server.c'], dependencies: wuffs)
-#codec_client_deps += declare_dependency(sources: ['client.c'], dependencies: wuffs)
+wuffs_args = ['-DCAMU_HAVE_WUFFS']
+codec_server_deps += declare_dependency(sources: ['server.c', 'impl.c'],
+ dependencies: wuffs, compile_args: wuffs_args)
+codec_client_deps += declare_dependency(sources: ['client.c', 'impl.c'],
+ dependencies: wuffs, compile_args: wuffs_args)
diff --git a/src/codec/wuffs/server.c b/src/codec/wuffs/server.c
new file mode 100644
index 0000000..5e7e885
--- /dev/null
+++ b/src/codec/wuffs/server.c
@@ -0,0 +1,102 @@
+#include "../../cache/entry.h"
+
+#include "demuxer.h"
+#include "inc.h"
+
+static bool wuffs_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle)
+{
+ struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux;
+
+ wfs->handle = handle;
+ nn_buffer_init(&wfs->buffer);
+ wfs->eof = false;
+
+ cch_handle_seek(wfs->handle, 0, SEEK_SET);
+ struct cch_backing *backing = wfs->handle->entry->backing;
+ off_t size = backing->get_size_if_known(backing);
+ nn_buffer_ensure_space(&wfs->buffer, size);
+ cch_handle_read(wfs->handle, nn_buffer_get_ptr(&wfs->buffer, 0), size);
+ wfs->buffer.size = size;
+
+ wuffs_png__decoder *wf_dec = wuffs_png__decoder__alloc();
+ if (!wf_dec) goto err;
+
+ wuffs_png__decoder__set_quirk(wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true);
+
+ wuffs_base__io_buffer src = { 0 };
+ src.data.ptr = nn_buffer_get_ptr(&wfs->buffer, 0);
+ src.data.len = size;
+ src.meta.wi = size;
+ src.meta.closed = true;
+
+ wuffs_base__image_config ic = { 0 };
+ wuffs_base__status status = wuffs_png__decoder__decode_image_config(wf_dec, &ic, &src);
+ if (!wuffs_base__status__is_ok(&status)) goto err;
+ if (!wuffs_base__image_config__is_valid(&ic)) goto err;
+
+ struct camu_codec_stream stream = { 0 };
+ stream.mode = CAMU_NORMAL;
+ stream.type = CAMU_STREAM_VIDEO;
+ struct camu_video_format *fmt = &stream.video.fmt;
+ fmt->width = wuffs_base__pixel_config__width(&ic.pixcfg);
+ fmt->height = wuffs_base__pixel_config__height(&ic.pixcfg);
+ fmt->format = CAMU_PIXEL_FORMAT_RGBA;
+
+ al_array_push(wfs->demux.streams, stream);
+
+ free(wf_dec);
+
+ return true;
+err:
+ if (wf_dec) free(wf_dec);
+
+ return false;
+}
+
+static s32 wuffs_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet)
+{
+ struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux;
+ if (!wfs->eof) {
+ packet->mode = CAMU_NORMAL;
+ packet->buffer = &wfs->buffer;
+ wfs->eof = true;
+ return CAMU_OK;
+ }
+ return CAMU_ERR_EOF;
+}
+
+static u64 wuffs_demuxer_get_duration(struct camu_demuxer *demux)
+{
+ (void)demux;
+ return 0;
+}
+
+static bool wuffs_demuxer_seek(struct camu_demuxer *demux, u64 pos, bool bytes)
+{
+ (void)demux;
+ (void)pos;
+ (void)bytes;
+ return true;
+}
+
+static void wuffs_demuxer_free(struct camu_demuxer **demux)
+{
+ struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)*demux;
+ nn_buffer_free(&wfs->buffer);
+ al_array_free(wfs->demux.streams);
+ al_free(wfs);
+ *demux = NULL;
+}
+
+struct camu_demuxer *camu_wuffs_demuxer_create(void)
+{
+ struct camu_wuffs_demuxer *wfs = al_alloc_object(struct camu_wuffs_demuxer);
+ wfs->demux.mode = CAMU_NORMAL;
+ al_array_init(wfs->demux.streams);
+ wfs->demux.init = wuffs_demuxer_init;
+ wfs->demux.get_packet = wuffs_demuxer_get_packet;
+ wfs->demux.get_duration = wuffs_demuxer_get_duration;
+ wfs->demux.seek = wuffs_demuxer_seek;
+ wfs->demux.free = wuffs_demuxer_free;
+ return (struct camu_demuxer *)wfs;
+}
diff --git a/src/liana/client.c b/src/liana/client.c
index 5222d7a..d853acf 100644
--- a/src/liana/client.c
+++ b/src/liana/client.c
@@ -41,6 +41,10 @@ static void collect_streams(struct lia_client *client, struct nn_packet *packet)
for (u32 i = 0; i < count; i++) {
// Very important zero-initialization.
struct camu_codec_stream stream = { 0 };
+ str codec;
+ nn_packet_read_str(packet, &codec);
+ // @TODO: NULL unhandled.
+ stream.codec_info = camu_codec_info_by_name(&codec);
u8 mode = nn_packet_read_u8(packet);
u8 type = nn_packet_read_u8(packet);
u64 duration = nn_packet_read_u64(packet);
@@ -125,8 +129,8 @@ static const char *type_to_str[] = {
static void parse_info_packet(struct lia_client *client, struct nn_packet *packet)
{
- str liana;
- nn_packet_read_str(packet, &liana);
+ str handler;
+ nn_packet_read_str(packet, &handler);
client->duration = nn_packet_read_u64(packet);
collect_streams(client, packet);
struct lia_prefs *prefs = &client->prefs;
@@ -146,11 +150,9 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe
const AVDictionaryEntry *lang_entry = av_dict_get(metadata, "language", NULL, 0);
if (lang_entry && !accept_defaults) {
u8 lang = CAMU_LANG_UNKNOWN;
- if (strcmp(lang_entry->value, "eng") == 0) {
- lang = CAMU_LANG_ENGLISH;
- } else if (strcmp(lang_entry->value, "jpn") == 0) {
- lang = CAMU_LANG_JAPANESE;
- }
+ str lang_str = al_str_cr(lang_entry->value);
+ if (al_str_eq(&lang_str, &al_str_c("eng"))) lang = CAMU_LANG_ENGLISH;
+ else if (al_str_eq(&lang_str, &al_str_c("jpn"))) lang = CAMU_LANG_JAPANESE;
switch (stream->type) {
case CAMU_STREAM_AUDIO:
if (prefs->audio_lang != lang) continue;
@@ -173,7 +175,7 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe
client->mask |= 1 << stream->index;
struct lia_vcr_track *track = al_alloc_object(struct lia_vcr_track);
track->stream = stream;
- track->client = lia_handler_by_name(&liana)->create_client_handler();
+ track->client = lia_handler_by_name(&handler)->create_client_handler();
track->client->callback = client->callback;
track->client->userdata = client->userdata;
if (!track->client->init(track->client, client->renderer, track->stream)) {
diff --git a/src/liana/handlers.h b/src/liana/handlers.h
index 223ead5..a72bdb9 100644
--- a/src/liana/handlers.h
+++ b/src/liana/handlers.h
@@ -1,6 +1,6 @@
#pragma once
-#include "handler.h"
+#include "handlers/handler.h"
struct lia_handler_entry {
str name;
diff --git a/src/liana/handlers/cdio.h b/src/liana/handlers/cdio.h
index 3b0e991..7fa0caf 100644
--- a/src/liana/handlers/cdio.h
+++ b/src/liana/handlers/cdio.h
@@ -1,6 +1,6 @@
#pragma once
-#include "../handler.h"
+#include "handler.h"
#ifdef LIANA_SERVER
struct lia_cdio_server {
diff --git a/src/liana/handlers/codec.h b/src/liana/handlers/codec.h
index be43f63..f179190 100644
--- a/src/liana/handlers/codec.h
+++ b/src/liana/handlers/codec.h
@@ -3,7 +3,8 @@
#include "../../codec/codec.h"
#include "../server.h"
-#include "../handler.h"
+
+#include "handler.h"
// FFmpeg Independence:
// - [ ] CAMU_CODEC_* only for explicitly non-ffmpeg codecs.
@@ -14,6 +15,7 @@
#ifdef LIANA_SERVER
struct lia_codec_server {
struct lia_server_handler handler;
+ struct camu_codec_info *codec_info;
struct camu_demuxer *demux;
#ifdef LIANA_SERVER_LOOP
u64 pts_offset;
diff --git a/src/liana/handlers/codec_client.c b/src/liana/handlers/codec_client.c
index 267187f..a3614bf 100644
--- a/src/liana/handlers/codec_client.c
+++ b/src/liana/handlers/codec_client.c
@@ -1,12 +1,8 @@
#include "../../codec/codec.h"
-
+#include "../../codec/codecs.h"
#ifdef CAMU_HAVE_FFMPEG
-#include "../../codec/ffmpeg/decoder.h"
#include "../../codec/ffmpeg/packet_ext.h"
#endif
-#include "../../codec/stb_image/decoder.h"
-#include "../../codec/spng/decoder.h"
-#include "../../codec/wuffs/decoder.h"
#include "../vcr.h"
#include "../client.h"
@@ -25,10 +21,7 @@ static bool codec_client_init(struct lia_client_handler *handler, struct camu_re
struct lia_codec_client *codec = (struct lia_codec_client *)handler;
codec->handler.stream = stream;
if (stream->type == CAMU_STREAM_AUDIO || stream->type == CAMU_STREAM_VIDEO) {
- codec->dec = camu_ff_decoder_create();
- //codec->dec = camu_stbi_decoder_create();
- //codec->dec = camu_spng_decoder_create();
- //codec->dec = camu_wuffs_decoder_create();
+ codec->dec = stream->codec_info->create_decoder();
if (!codec->dec->init(codec->dec, renderer, stream, data_callback, codec)) {
return false;
}
diff --git a/src/liana/handlers/codec_server.c b/src/liana/handlers/codec_server.c
index c324481..801a3e1 100644
--- a/src/liana/handlers/codec_server.c
+++ b/src/liana/handlers/codec_server.c
@@ -1,15 +1,12 @@
-#include "../../codec/codec.h"
-#include "../../server/common.h"
+#define AL_LOG_SECTION "codec_server"
+#include <al/log.h>
+#include "../../server/common.h"
+#include "../../codec/codec.h"
+#include "../../codec/codecs.h"
#ifdef CAMU_HAVE_FFMPEG
-#include "../../codec/ffmpeg/demuxer.h"
#include "../../codec/ffmpeg/packet_ext.h"
#endif
-#include "../../codec/stb_image/demuxer.h"
-#include "../../codec/spng/demuxer.h"
-#include "../../codec/wuffs/demuxer.h"
-
-#include "../handler.h"
#include "codec.h"
@@ -17,11 +14,13 @@ static bool codec_server_init(struct lia_server_handler *handler, struct cch_han
{
struct lia_codec_server *codec = (struct lia_codec_server *)handler;
- codec->demux = camu_ff_demuxer_create();
- //codec->demux = camu_stbi_demuxer_create();
- //codec->demux = camu_spng_demuxer_create();
- //codec->demux = camu_wuffs_demuxer_create();
-
+ codec->demux = NULL;
+ codec->codec_info = camu_codec_info_by_type(cch_entry_guess_format(handle->entry));
+ if (!codec->codec_info) {
+ return false;
+ }
+ log_info("Selected demuxer: %.*s.", al_str_x(&codec->codec_info->name));
+ codec->demux = codec->codec_info->create_demuxer();
if (!codec->demux->init(codec->demux, handle)) {
return false;
}
@@ -55,6 +54,7 @@ static void codec_server_write_info(struct lia_server_handler *handler, struct n
nn_packet_write_u32(packet, codec->demux->streams.count);
struct camu_codec_stream *stream;
al_array_foreach_ptr(codec->demux->streams, i, stream) {
+ nn_packet_write_str(packet, &codec->codec_info->name);
nn_packet_write_u8(packet, stream->mode);
nn_packet_write_u8(packet, stream->type);
nn_packet_write_u64(packet, stream->duration);
@@ -159,18 +159,20 @@ static void codec_server_write_packet(struct lia_server_handler *handler, struct
static void codec_server_free(struct lia_server_handler **handler)
{
struct lia_codec_server *codec = (struct lia_codec_server *)*handler;
- switch (codec->demux->mode) {
- case CAMU_NORMAL:
- break;
+ if (codec->demux) {
+ switch (codec->demux->mode) {
+ case CAMU_NORMAL:
+ break;
#ifdef CAMU_HAVE_FFMPEG
- case CAMU_FFMPEG_COMPAT:
+ case CAMU_FFMPEG_COMPAT:
#ifndef CAMU_DIRECT_MODE
- av_packet_free(&codec->packet.av.pkt);
+ av_packet_free(&codec->packet.av.pkt);
#endif
- break;
+ break;
#endif
+ }
+ codec->demux->free(&codec->demux);
}
- codec->demux->free(&codec->demux);
al_free(codec);
*handler = NULL;
}
diff --git a/src/liana/handlers/dvd.h b/src/liana/handlers/dvd.h
index dd5ac0a..c0f0544 100644
--- a/src/liana/handlers/dvd.h
+++ b/src/liana/handlers/dvd.h
@@ -1,6 +1,6 @@
#pragma once
-#include "../handler.h"
+#include "handler.h"
#ifdef LIANA_SERVER
#include <dvdnav/dvdnav.h>
diff --git a/src/liana/handler.h b/src/liana/handlers/handler.h
index 1fa77a0..48fcef3 100644
--- a/src/liana/handler.h
+++ b/src/liana/handlers/handler.h
@@ -1,9 +1,9 @@
#pragma once
-#include <nnwt/packet_pool.h>
+#include <nnwt/packet.h>
-#include "../codec/codec.h"
-#include "../cache/handle.h"
+#include "../../cache/handle.h"
+#include "../../codec/codec.h"
enum {
LIANA_PACKET_DATA = 0,
diff --git a/src/liana/server.c b/src/liana/server.c
index d07cb8d..db61e20 100644
--- a/src/liana/server.c
+++ b/src/liana/server.c
@@ -1,5 +1,4 @@
#include "server.h"
-#include "handler.h"
#include "handlers.h"
#include "list.h"
@@ -217,7 +216,7 @@ static void handle_connection(struct lia_node_connection *conn, struct nn_packet
if (mask == 0) {
struct nn_packet *rpacket = nn_packet_create();
nn_packet_write_u32(rpacket, conn->id);
- nn_packet_write_str(rpacket, cch_entry_get_liana(conn->node->entry));
+ nn_packet_write_str(rpacket, cch_entry_get_handler(conn->node->entry));
conn->handler->write_info(conn->handler, rpacket);
stream->packet_callback = subscribe_packet_callback;
stream->packet_sent_callback = subscribe_packet_sent_callback;
@@ -363,7 +362,7 @@ static void packet_callback(void *userdata, struct nn_packet_stream *stream, str
nn_signal_init(&conn->signal, server->loop, signal_callback, conn);
nn_signal_start(&conn->signal);
cch_entry_get_handle(node->entry, &conn->handle);
- conn->handler = lia_handler_by_name(cch_entry_get_liana(node->entry))->create_server_handler();
+ conn->handler = lia_handler_by_name(cch_entry_get_handler(node->entry))->create_server_handler();
conn->errored = false;
conn->disconnected = false;
conn->ref = false;
@@ -468,7 +467,7 @@ void lia_node_get_duration(struct lia_node *node)
nn_signal_init(&node->signal, node->server->loop, duration_signal_callback, node);
nn_signal_start(&node->signal);
cch_entry_get_handle(node->entry, &node->handle);
- node->handler = lia_handler_by_name(cch_entry_get_liana(node->entry))->create_server_handler();
+ node->handler = lia_handler_by_name(cch_entry_get_handler(node->entry))->create_server_handler();
nn_thread_create(&node->thread, init_duration_thread, node);
}
diff --git a/src/liana/vcr.c b/src/liana/vcr.c
index 518311a..d2c6b33 100644
--- a/src/liana/vcr.c
+++ b/src/liana/vcr.c
@@ -1,8 +1,9 @@
#define AL_LOG_SECTION "vcr"
#include <al/log.h>
+#include "handlers/handler.h"
+
#include "vcr.h"
-#include "handler.h"
#define VCR_BUFFER_BUFFERED MB(2)
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index 2bcc943..ff91a51 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -1548,7 +1548,7 @@ static void identify_callback(void *userdata, struct nn_rpc_connection *conn, st
}
#else
(void)sink;
- log_info("Sink locally bridged to server.");
+ log_info("Sink directly bridged to server.");
#endif
nn_packet_stream_return_packet(conn->stream, packet);
}
diff --git a/src/portal/py/modules/youtube.py b/src/portal/py/modules/youtube.py
index 77e17b3..9783127 100644
--- a/src/portal/py/modules/youtube.py
+++ b/src/portal/py/modules/youtube.py
@@ -28,7 +28,8 @@ ydl_opts = {
'logger': YDLLogger(),
'cachedir': False,
'socket_timeout': 10,
- 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['tv', 'ios']}} # 'android_vr',
+ 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['android_vr']}}
+# 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['tv', 'ios']}}
# 'cookiefile': ''
}
diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c
index 1864607..01cd366 100644
--- a/src/render/queue_libplacebo.c
+++ b/src/render/queue_libplacebo.c
@@ -62,7 +62,7 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src
masks[3] = 0xff000000;
pixel_stride = 4;
break;
- case CAMU_PIXEL_FORMAT_RGB8:
+ case CAMU_PIXEL_FORMAT_RGB24:
masks[0] = 0x000000ff;
masks[1] = 0x0000ff00;
masks[2] = 0x00ff0000;
diff --git a/src/render/renderer.h b/src/render/renderer.h
index 8e80696..bbb7b70 100644
--- a/src/render/renderer.h
+++ b/src/render/renderer.h
@@ -38,6 +38,7 @@ struct camu_renderer {
#if defined STELA_API_VULKAN
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
+ VkResult (*vk_destroy_surface)(VkInstance, VkSurfaceKHR),
const char *const *(*vk_get_extensions)(u32 *),
#elif defined STELA_API_DX11
HWND win32_window,
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index c5f4de8..cdf09bf 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -119,6 +119,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
#if defined STELA_API_VULKAN
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
+ VkResult (*vk_destroy_surface)(VkInstance, VkSurfaceKHR),
const char *const *(*vk_get_extensions)(u32 *),
#elif defined STELA_API_DX11
HWND win32_window,
@@ -159,7 +160,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
));
#if defined STELA_API_VULKAN
- VkResult err;
+ lr->vk_destroy_surface = vk_destroy_surface;
u32 num;
const char *const *extensions = vk_get_extensions(&num);
@@ -174,8 +175,8 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
goto err;
}
- err = vk_create_surface(priv, lr->vk_inst->instance, &lr->surface);
- if (err != VK_SUCCESS) {
+ VkResult ret = vk_create_surface(priv, lr->vk_inst->instance, &lr->surface);
+ if (ret != VK_SUCCESS) {
log_error("Failed to create vulkan surface.");
goto err;
}
@@ -333,6 +334,7 @@ static struct camu_frame_queue *renderer_lp_create_queue(struct camu_renderer *r
static void renderer_lp_add_font(struct camu_renderer *renderer, struct camu_codec_stream *attachment)
{
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
+ // @TODO: No FFmpeg + HAVE_SUBTITLES (no usecase yet).
#ifdef CAMU_HAVE_SUBTITLES
AVStream *stream = attachment->av.stream;
AVDictionaryEntry *entry = av_dict_get(stream->metadata, "filename", NULL, 0);
@@ -463,7 +465,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
}
if (!pl_swapchain_submit_frame(lr->swapchain)) {
- log_error("Failed to submit frame, likely fatal.");
+ log_error("Failed to submit frame, possibly fatal.");
}
lr->have_frame = false;
@@ -490,6 +492,11 @@ void renderer_lp_free(struct camu_renderer **renderer)
if (lr->renderer) pl_renderer_destroy(&lr->renderer);
if (lr->swapchain) pl_swapchain_destroy(&lr->swapchain);
#if defined STELA_API_VULKAN
+ if (lr->vk) pl_vulkan_destroy(&lr->vk);
+ lr->vk_destroy_surface(lr->vk_inst->instance, lr->surface);
+ if (lr->vk_inst) pl_vk_inst_destroy(&lr->vk_inst);
+#elif defined STELA_API_DX11
+ if (lr->d3d11) pl_d3d11_destroy(&lr->d3d11);
#elif defined STELA_API_OPENGL
if (lr->gl) pl_opengl_destroy(&lr->gl);
#endif
diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h
index c8962d2..fd34f7a 100644
--- a/src/render/renderer_libplacebo.h
+++ b/src/render/renderer_libplacebo.h
@@ -24,6 +24,7 @@ struct camu_renderer_lp {
VkSurfaceKHR surface;
pl_vulkan vk;
pl_vk_inst vk_inst;
+ VkResult (*vk_destroy_surface)(VkInstance, VkSurfaceKHR);
#elif defined STELA_API_DX11
pl_d3d11 d3d11;
#elif defined STELA_API_OPENGL
diff --git a/src/screen/screen.c b/src/screen/screen.c
index bed1a26..d0d78e2 100644
--- a/src/screen/screen.c
+++ b/src/screen/screen.c
@@ -517,6 +517,7 @@ bool camu_screen_create_renderer(struct camu_screen *scr, struct camu_renderer *
#if defined STELA_API_VULKAN
scr->window->get_vk_proc_address,
scr->window->vk_create_surface,
+ scr->window->vk_destroy_surface,
scr->window->vk_get_extensions,
#elif defined STELA_API_DX11
scr->window->win32_window,
diff --git a/subprojects/libalabaster.wrap b/subprojects/libalabaster.wrap
index 425ed78..5457b48 100644
--- a/subprojects/libalabaster.wrap
+++ b/subprojects/libalabaster.wrap
@@ -1,4 +1,4 @@
[wrap-git]
-url = https://git.akon.city/libalabaster
-revision = 1aa0177d1eb3767f1a7840115c3afeb93e8c858e
+url = https://git.akon.city/libalabaster.git
+revision = 492f4a38f7b7f32727ab678f333eff840d968d74
depth = 1
diff --git a/subprojects/libnaunet.wrap b/subprojects/libnaunet.wrap
index a069af9..57a13ac 100644
--- a/subprojects/libnaunet.wrap
+++ b/subprojects/libnaunet.wrap
@@ -1,4 +1,4 @@
[wrap-git]
-url = https://git.akon.city/libnaunet
-revision = eaf84a7850f2af70b16fb417cd002f5e39df5db2
+url = https://git.akon.city/libnaunet.git
+revision = ab75884371a3545f7548498549e2faebbc465ed6
depth = 1
diff --git a/subprojects/stela.wrap b/subprojects/stela.wrap
index da7a1c0..f91a1ce 100644
--- a/subprojects/stela.wrap
+++ b/subprojects/stela.wrap
@@ -1,4 +1,4 @@
[wrap-git]
-url = https://git.akon.city/stela
-revision = f595bcadb2305d5bbc5ea945935a42bcfbf6bdb1
+url = https://git.akon.city/stela.git
+revision = 88d24e4caa0211b78d3d86d9fab5ec9e11d9b66d
depth = 1