summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-03-03 12:53:14 -0500
committerAndrew Opalach <andrew@akon.city> 2025-03-03 12:53:14 -0500
commit1224a43bbde9ef2297c7ee638b1928a07488cc3d (patch)
tree8cfb0ffe2f35c9c12bc20ab65185f08946eda243
parent000ce1f671d1f05b76202fd128e272e4ac9da683 (diff)
downloadcamu-1224a43bbde9ef2297c7ee638b1928a07488cc3d.tar.gz
camu-1224a43bbde9ef2297c7ee638b1928a07488cc3d.tar.bz2
camu-1224a43bbde9ef2297c7ee638b1928a07488cc3d.zip
Fix vcr memory leak, subtitle upload/render sync
- Some sink behavior fixes. - Fix clock sync when seeking. - Add relative seek bind. Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--env/msys2_clang.sh4
-rw-r--r--flake.lock30
-rw-r--r--flake.nix2
-rw-r--r--meson.build4
-rw-r--r--src/buffer/clock.c3
-rw-r--r--src/buffer/video.c6
-rw-r--r--src/codec/ffmpeg/decoder.c14
-rw-r--r--src/codec/ffmpeg/decoder.h2
-rw-r--r--src/codec/ffmpeg/meson.build28
-rw-r--r--src/codec/ffmpeg/resampler.c1
-rw-r--r--src/fruits/cmc/ui/pane_search.c2
-rw-r--r--src/fruits/cmv/cmv.c2
-rw-r--r--src/liana/client.c8
-rw-r--r--src/liana/handlers/codec_client.c2
-rw-r--r--src/liana/list.h2
-rw-r--r--src/liana/vcr.c8
-rw-r--r--src/libsink/sink.c61
-rw-r--r--src/libsink/sink.h1
-rw-r--r--src/render/meson.build22
-rw-r--r--src/render/queue_libplacebo.c24
-rw-r--r--src/render/queue_libplacebo.h1
-rw-r--r--src/render/renderer.h1
-rw-r--r--src/render/renderer_libplacebo.c27
-rw-r--r--src/screen/screen.c76
-rw-r--r--src/screen/screen.h2
-rw-r--r--src/server/server.c1
-rw-r--r--src/sink/desktop.c5
-rw-r--r--subprojects/ffmpeg.wrap12
-rw-r--r--subprojects/libalabaster.wrap2
-rw-r--r--subprojects/libnaunet.wrap2
-rw-r--r--subprojects/packagefiles/ffmpeg/meson.build18
-rw-r--r--subprojects/stela.wrap2
32 files changed, 256 insertions, 119 deletions
diff --git a/env/msys2_clang.sh b/env/msys2_clang.sh
new file mode 100644
index 0000000..fd6ced6
--- /dev/null
+++ b/env/msys2_clang.sh
@@ -0,0 +1,4 @@
+#! /usr/bin/env sh
+export PATH="$PATH:C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\bin"
+export CC=clang-cl
+export CXX=clang-cl
diff --git a/flake.lock b/flake.lock
index 1e1611e..a44a7d9 100644
--- a/flake.lock
+++ b/flake.lock
@@ -23,11 +23,11 @@
]
},
"locked": {
- "lastModified": 1739992710,
- "narHash": "sha256-9kEscmGnXHjSgcqyJR4TzzHhska4yz1inSQs6HuO9qU=",
+ "lastModified": 1740845322,
+ "narHash": "sha256-AXEgFj3C0YJhu9k1OhbRhiA6FnDr81dQZ65U3DhaWpw=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "1c189f011447810af939a886ba7bee33532bb1f9",
+ "rev": "fcac3d6d88302a5e64f6cb8014ac785e08874c8d",
"type": "github"
},
"original": {
@@ -39,11 +39,11 @@
},
"nixos-hardware": {
"locked": {
- "lastModified": 1739798439,
- "narHash": "sha256-GyipmjbbQEaosel/+wq1xihCKbv0/e1LU00x/8b/fP4=",
+ "lastModified": 1740646007,
+ "narHash": "sha256-dMReDQobS3kqoiUCQIYI9c0imPXRZnBubX20yX/G5LE=",
"owner": "NixOS",
"repo": "nixos-hardware",
- "rev": "3e2ea8a49d4d76276b0f4e2041df8ca5c0771371",
+ "rev": "009b764ac98a3602d41fc68072eeec5d24fc0e49",
"type": "github"
},
"original": {
@@ -59,11 +59,11 @@
"nixpkgs": "nixpkgs"
},
"locked": {
- "lastModified": 1739782332,
- "narHash": "sha256-bPZKuual2WKfyHv7Wq+Owcj9R+i/qFzOWByqSS9rlxI=",
+ "lastModified": 1740567864,
+ "narHash": "sha256-eTS2wrC1jKR6PKXC9jZqQy5PwqbIOBLSLF3dwLiFJ8M=",
"owner": "nix-community",
"repo": "NixOS-WSL",
- "rev": "59bdbb1e75232bf1dd6d2a9313b9b6ddc5049ba2",
+ "rev": "1f40b43d01626ce994eb47150afa0d7215f396ca",
"type": "github"
},
"original": {
@@ -75,11 +75,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1739624908,
- "narHash": "sha256-f84lBmLl4tkDp1ZU5LBTSFzlxXP4926DVW3KnXrke10=",
+ "lastModified": 1740463929,
+ "narHash": "sha256-4Xhu/3aUdCKeLfdteEHMegx5ooKQvwPHNkOgNCXQrvc=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "a60651b217d2e529729cbc7d989c19f3941b9250",
+ "rev": "5d7db4668d7a0c6cc5fc8cf6ef33b008b2b1ed8b",
"type": "github"
},
"original": {
@@ -91,11 +91,11 @@
},
"nixpkgs_2": {
"locked": {
- "lastModified": 1739866667,
- "narHash": "sha256-EO1ygNKZlsAC9avfcwHkKGMsmipUk1Uc0TbrEZpkn64=",
+ "lastModified": 1740828860,
+ "narHash": "sha256-cjbHI+zUzK5CPsQZqMhE3npTyYFt9tJ3+ohcfaOF/WM=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "73cf49b8ad837ade2de76f87eb53fc85ed5d4680",
+ "rev": "303bd8071377433a2d8f76e684ec773d70c5b642",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index f50790c..954a2f9 100644
--- a/flake.nix
+++ b/flake.nix
@@ -168,7 +168,7 @@
ruff-lsp
perf-tools
valgrind
- kcachegrind
+ kdePackages.kcachegrind
perl
asciidoctor
pandoc
diff --git a/meson.build b/meson.build
index e27d8b2..94a8d08 100644
--- a/meson.build
+++ b/meson.build
@@ -4,8 +4,8 @@ project('camu', ['c', 'cpp'], version: '0.01',
compiler = meson.get_compiler('c')
cmake = import('cmake')
-is_debug = get_option('buildtype').startswith('debug')
-is_minsize = get_option('buildtype') == 'minsize'
+is_debug = get_option('debug')
+is_minsize = get_option('optimization') == 's'
is_linux = host_machine.system() == 'linux'
is_windows = host_machine.system() == 'windows'
is_android = host_machine.system() == 'android'
diff --git a/src/buffer/clock.c b/src/buffer/clock.c
index b0b4ac9..1ca2a49 100644
--- a/src/buffer/clock.c
+++ b/src/buffer/clock.c
@@ -44,7 +44,8 @@ void camu_clock_seek(struct camu_clock *clock, f64 base, u64 target)
al_atomic_store(f64)(&clock->tick, tick, AL_ATOMIC_RELAXED);
}
} else {
- al_atomic_store(f64)(&clock->pause, PAUSED, AL_ATOMIC_RELAXED);
+ // The value of clock->pause cannot be touched here. A reconnecting entry
+ // may still be relying on a clock paused callback for sync.
clock->paused_at = 0.0;
}
}
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 1f2aa3c..ab1503a 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -12,9 +12,9 @@
#include "../codec/ffmpeg/scaler.h"
#endif
-#define BUFFER_MARK_LOW ((1.0 / 30.0) * 4)
-#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 6) // Must be >1.
-#define BUFFER_MARK_HIGH ((1.0 / 30.0) * 8)
+#define BUFFER_MARK_LOW ((1.0 / 24.0) * 3)
+#define BUFFER_MARK_BUFFERED ((1.0 / 24.0) * 4) // Must be >1.
+#define BUFFER_MARK_HIGH ((1.0 / 24.0) * 6)
#define BUFFER_MARK_RESET (BUFFER_MARK_HIGH * 2.0)
bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock)
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index 47b5b01..5f4de67 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -90,7 +90,8 @@ static s32 init_hwdevice_context(struct camu_ff_decoder *av, AVCodecContext *con
}
context->hw_device_ctx = av_buffer_ref(av->hw_context);
- context->extra_hw_frames = 40;
+ // Note that context->extra_hw_frames has the ability to cause corruption.
+ context->extra_hw_frames = 18;
al_log_info("ff_decoder", "Using %s hardware decoding.", av_hwdevice_get_type_name(av->hw_device_type));
@@ -237,13 +238,14 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
#ifdef CAMU_FF_DECODER_HWACCEL
if (attempt_hwdec && av->hw_device_type != AV_HWDEVICE_TYPE_NONE) {
//av->codec_context->codec_id = codec->id;
- if (init_hwdevice_context(av, av->codec_context) < 0) {
+ if (init_hwdevice_context(av, av->codec_context) == 0) {
+ av->renderer = renderer;
+ av->codec_context->opaque = av;
+ av->codec_context->get_buffer2 = get_buffer2;
+ av->codec_context->get_format = get_hw_format;
+ } else {
av->hw_device_type = AV_HWDEVICE_TYPE_NONE;
}
- av->renderer = renderer;
- av->codec_context->opaque = av;
- av->codec_context->get_buffer2 = get_buffer2;
- av->codec_context->get_format = get_hw_format;
}
#else
(void)renderer;
diff --git a/src/codec/ffmpeg/decoder.h b/src/codec/ffmpeg/decoder.h
index 4aa3d32..f698a6d 100644
--- a/src/codec/ffmpeg/decoder.h
+++ b/src/codec/ffmpeg/decoder.h
@@ -13,12 +13,14 @@ struct camu_ff_decoder {
struct camu_decoder dec;
AVCodecContext *codec_context;
struct camu_renderer *renderer;
+#ifdef CAMU_FF_DECODER_HWACCEL
array(const AVCodec *) supported_hw_codecs;
array(enum AVHWDeviceType) supported_hw_devices;
AVBufferRef *hw_context;
enum AVHWDeviceType hw_device_type;
enum AVPixelFormat hw_pix_fmt;
bool use_frames_context;
+#endif
void (*callback)(void *, struct camu_codec_frame *);
void *userdata;
};
diff --git a/src/codec/ffmpeg/meson.build b/src/codec/ffmpeg/meson.build
index cd6c7d3..dfbf624 100644
--- a/src/codec/ffmpeg/meson.build
+++ b/src/codec/ffmpeg/meson.build
@@ -27,16 +27,16 @@ ffmpeg_client_deps = []
libavutil = dependency('libavutil', required: false)
libavformat = dependency('libavformat', required: false)
libavcodec = dependency('libavcodec', required: false)
-libavdevice = dependency('libavdevice', required: false)
+#libavdevice = dependency('libavdevice', required: false)
libswresample = dependency('libswresample', required: false)
libswscale = dependency('libswscale', required: false)
-if not (libavutil.found() and libavformat.found() and libavcodec.found() and libavdevice.found() and libswresample.found() and libswscale.found())
+if not (libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found())
ffmpeg_proj = subproject('ffmpeg', required: false)
if ffmpeg_proj.found()
libavutil = ffmpeg_proj.get_variable('avutil')
libavformat = ffmpeg_proj.get_variable('avformat')
libavcodec = ffmpeg_proj.get_variable('avcodec')
- libavdevice = ffmpeg_proj.get_variable('avdevice')
+ #libavdevice = ffmpeg_proj.get_variable('avdevice')
libswresample = ffmpeg_proj.get_variable('swresample')
libswscale = ffmpeg_proj.get_variable('swscale')
# Only used to set include dirs for FFmpeg.
@@ -56,18 +56,16 @@ else
ffmpeg_version_string = run_command('sh', join_paths(meson.current_source_dir(), 'version.sh'), check: true).stdout().strip()
endif
-# This is probably meaningless compared to libav* versions, it's just something I wanted.
-ffmpeg_args += ['-DFFMPEG_VERSION="' + ffmpeg_version_string + '"']
-
-soxr = compiler.find_library('soxr', required: false)
-if soxr.found()
- ffmpeg_client_deps += [soxr]
- ffmpeg_args += ['-DCAMU_HAVE_SOXR']
-endif
-
-if libavutil.found() and libavformat.found() and libavcodec.found() and libavdevice.found() and libswresample.found() and libswscale.found()
- ffmpeg_server_deps += [libavutil, libavformat, libavcodec, libavdevice]
- ffmpeg_client_deps += [libavutil, libavformat, libavcodec, libavdevice, libswresample, libswscale]
+if libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found()
+ # This is probably meaningless compared to libav* versions, it's just something I wanted.
+ ffmpeg_args += ['-DFFMPEG_VERSION="' + ffmpeg_version_string + '"']
+ ffmpeg_server_deps += [libavutil, libavformat, libavcodec]
+ ffmpeg_client_deps += [libavutil, libavformat, libavcodec, libswresample, libswscale]
+ soxr = compiler.find_library('soxr', required: false)
+ if soxr.found()
+ ffmpeg_client_deps += [soxr]
+ ffmpeg_args += ['-DCAMU_HAVE_SOXR']
+ endif
codec_server_deps += [
declare_dependency(sources: ffmpeg_server_src,
dependencies: [ffmpeg_deps, ffmpeg_server_deps], compile_args: ffmpeg_args)
diff --git a/src/codec/ffmpeg/resampler.c b/src/codec/ffmpeg/resampler.c
index d2c8f62..61e8c9e 100644
--- a/src/codec/ffmpeg/resampler.c
+++ b/src/codec/ffmpeg/resampler.c
@@ -26,6 +26,7 @@ static bool ff_resampler_init(struct camu_resampler *resamp, struct camu_resampl
#ifdef CAMU_HAVE_SOXR
// Slower but more accurate resampler.
av_opt_set_int(av->resample_context, "resampler", SWR_ENGINE_SOXR, 0);
+ al_log_info("ff_resampler", "Using SoX resampler.");
#endif
if (swr_init(av->resample_context) != 0) {
diff --git a/src/fruits/cmc/ui/pane_search.c b/src/fruits/cmc/ui/pane_search.c
index c1b47ed..e75caa5 100644
--- a/src/fruits/cmc/ui/pane_search.c
+++ b/src/fruits/cmc/ui/pane_search.c
@@ -127,7 +127,7 @@ bool cmc_sp_handle_input(struct cmc_ui *ui, struct ncinput *input)
if (handle_text_input(tab, input)) {
notcurses_cursor_disable(ui->nc);
str query;
- al_wstr_to_str(&tab->input_text, &query);
+ al_str_from_wstr(&query, &tab->input_text);
camu_client_create_search(&ui->c->client, &al_str_c("youtube"), &query);
al_str_free(&query);
}
diff --git a/src/fruits/cmv/cmv.c b/src/fruits/cmv/cmv.c
index f9c3b82..6285c39 100644
--- a/src/fruits/cmv/cmv.c
+++ b/src/fruits/cmv/cmv.c
@@ -246,7 +246,7 @@ s32 main(s32 argc, char *cargv[])
for (s32 i = 0; i < argc; i++) {
str arg;
#ifdef NAUNET_ON_WINDOWS
- if (!al_wstr_to_str(&al_wstr_cr(wargv[i]), &arg)) {
+ if (!al_str_from_wstr(&arg, &al_wstr_cr(wargv[i]))) {
al_log_error("cmv", "Failed to parse argument #%i.", i);
continue;
}
diff --git a/src/liana/client.c b/src/liana/client.c
index d83ef48..54b5584 100644
--- a/src/liana/client.c
+++ b/src/liana/client.c
@@ -23,6 +23,11 @@ static void data_packet_callback(void *userdata, struct nn_packet_stream *stream
lia_vcr_push_packet(&client->vcr, packet);
}
+static s32 stream_compare(const void *a, const void *b)
+{
+ return (s32)((struct camu_codec_stream *)a)->type - (s32)((struct camu_codec_stream *)b)->type;
+}
+
static void parse_info_packet(struct lia_client *client, struct nn_packet *packet)
{
str liana;
@@ -90,6 +95,9 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe
al_array_push(client->streams, stream);
}
+ // Video streams have to come before subtitle streams.
+ al_array_sort(client->streams, struct camu_codec_stream, stream_compare);
+
bool have_audio = false;
bool have_video = false;
bool have_subs = false;
diff --git a/src/liana/handlers/codec_client.c b/src/liana/handlers/codec_client.c
index 8a86799..6f7e9f4 100644
--- a/src/liana/handlers/codec_client.c
+++ b/src/liana/handlers/codec_client.c
@@ -127,7 +127,7 @@ static bool codec_client_handle_packet(struct lia_client_handler *handler, struc
AVRational time_base = stream->av.stream->time;
pkt->pts += av_rescale_q(stream->duration, AV_TIME_BASE_Q, time_base);
#else
- av_packet_unref(pkt);
+ av_packet_free_side_data(pkt);
av_packet_free(&pkt);
#endif
break;
diff --git a/src/liana/list.h b/src/liana/list.h
index 86064af..a60790a 100644
--- a/src/liana/list.h
+++ b/src/liana/list.h
@@ -7,7 +7,7 @@
#define LIANA_SEQUENCE_ANY -1
#define LIANA_TIMESTAMP_INVALID ((u64)-1)
-#define LIANA_BASE_DELAY 450000Lu // 450ms
+#define LIANA_BASE_DELAY 500000Lu // 500ms
#define LIANA_BASE_PING 125000Lu // 125ms
#define LIANA_PAUSE_DELAY LIANA_BASE_PING
#define LIANA_DELAY_IGNORE 0Lu
diff --git a/src/liana/vcr.c b/src/liana/vcr.c
index 70fb7b6..e06ff8e 100644
--- a/src/liana/vcr.c
+++ b/src/liana/vcr.c
@@ -3,7 +3,7 @@
#include "vcr.h"
#include "handler.h"
-#define VCR_BUFFER_BUFFERED MB(24)
+#define VCR_BUFFER_BUFFERED MB(8)
enum {
VCR_EXPAND_UNTOUCHED = 0,
@@ -124,6 +124,10 @@ static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata)
continue;
}
+ index++; // Count of packets consumed.
+ nn_packet_stream_return_packets(vcr->data, al_array_offset(track->cache.cache, 0), index);
+ al_array_remove_range(track->cache.cache, 0, index);
+
nn_packet_cache_unlock(&track->cache);
// Wait for uncork.
@@ -147,7 +151,7 @@ static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata)
if (corked) {
// The cache is already unlocked here.
- index++;
+ index = 0;
} else {
#ifndef VCR_BUFFER_WHOLE_FILE
al_assert(index == packets);
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index 62bb941..3528e6b 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -308,8 +308,6 @@ static void handle_sink_cmd(struct camu_sink *sink, struct camu_sink_cmd *cmd)
if (sink->video.state == SINK_PLAYING) {
sink->callback(sink->userdata, CAMU_SINK_STOP, CAMU_SINK_VIDEO, NULL);
sink->video.state = SINK_PAUSED;
- } else {
- sink->callback(sink->userdata, CAMU_SINK_REFRESH_VIDEO, 0, NULL);
}
break;
#endif
@@ -641,6 +639,12 @@ void add_audio_if_set_and_buffered(struct camu_sink_entry *entry)
.op = VIDEO_EMPTY(entry) || entry->buffers_paused ? STOP : START,
.value.i = CAMU_SINK_VIDEO
});
+ // This is the only place to clear the screen if skipping from a video
+ // to an audio-only entry.
+ if (VIDEO_EMPTY(entry)) {
+ struct camu_sink *sink = entry->sink;
+ sink->callback(sink->userdata, CAMU_SINK_REFRESH_VIDEO, 0, NULL);
+ }
}
#endif
queue_cmd(entry->sink, (struct camu_sink_cmd){
@@ -654,6 +658,7 @@ void add_audio_if_set_and_buffered(struct camu_sink_entry *entry)
#ifndef CAMU_SINK_NO_VIDEO
void add_video_if_set_and_buffered(struct camu_sink_entry *entry)
{
+ // Single frames will be added/removed with ended set.
al_assert(entry->video.state != BUFFER_INIT &&
(entry->video.state != BUFFER_QUEUED) &&
(entry->video.state != BUFFER_ADDED));
@@ -676,7 +681,7 @@ void add_video_if_set_and_buffered(struct camu_sink_entry *entry)
add_entry_audio_buffer(entry);
}
- // This entry could be in previous.
+ // This entry could be in previous, see note in add_audio_if_set_and_buffered().
maybe_remove_previous(entry->sink);
queue_cmd(entry->sink, (struct camu_sink_cmd){
@@ -753,6 +758,9 @@ static void switch_to(struct camu_sink *sink, struct camu_sink_entry *target)
static void pause_and_swap_to(struct camu_sink *sink, struct camu_sink_entry *target, u64 at)
{
struct camu_sink_entry *current = sink->current;
+#ifdef CAMU_SINK_TRACE
+ al_log_info("sink", "pause_and_swap_to(%llx, %llu), current: %llx", target, at, current);
+#endif
al_assert(target != current);
if (!current || current->ended) {
switch_to(sink, target);
@@ -875,12 +883,13 @@ static void video_buffer_callback(void *userdata, u8 op)
break;
case CAMU_BUFFER_EOF: {
bool swapped = false;
+ bool single_frame = VIDEO_IS_SINGLE_FRAME(entry);
nn_mutex_lock(&sink->mutex);
al_log_info("sink", "Video EOF.");
if (!AUDIO_EMPTY(entry)) {
camu_audio_buffer_set_no_video(&entry->audio.buf, true);
}
- if (!VIDEO_IS_SINGLE_FRAME(entry)) {
+ if (!single_frame) {
if (entry->video.state == BUFFER_ADDED) {
remove_entry_video_buffer(sink, entry);
}
@@ -891,7 +900,7 @@ static void video_buffer_callback(void *userdata, u8 op)
}
}
nn_mutex_unlock(&sink->mutex);
- if (!swapped) {
+ if (!swapped && !single_frame) {
queue_cmd(sink, (struct camu_sink_cmd){
.op = STOP,
.value.i = CAMU_SINK_VIDEO
@@ -1086,6 +1095,10 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
nn_mutex_lock(&sink->mutex);
+#ifdef CAMU_SINK_TRACE
+ al_log_info("sink", "remove_buffers(%s), entry == current: %s", BOOLSTR(reconnect), BOOLSTR(entry == sink->current));
+#endif
+
if (reconnect) {
if (entry == sink->current) {
sink->reconnecting = entry;
@@ -1177,6 +1190,9 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
case LIANA_CLIENT_RESUME_AT: {
struct lia_timing *time = (struct lia_timing *)opaque;
nn_mutex_lock(&sink->mutex);
+#ifdef CAMU_SINK_TRACE
+ al_log_info("sink", "resume_at(%llu, %llu)", time->seek_pos, time->at);
+#endif
#if defined LIANA_LIST_SCUFFED_LOOP && !defined CAMU_SINK_NO_VIDEO
struct camu_video_buffer *buf = &entry->video.buf;
if (time->seek_pos == 0 && buf->last_pts >= 0.0) {
@@ -1704,11 +1720,39 @@ void camu_sink_seek(struct camu_sink *sink, f64 precent)
});
}
+// @TODO: We need at standard way to get the entries pts even when paused.
+static f64 tmp_get_entry_pts(struct camu_sink_entry *entry)
+{
+ f64 pts = camu_clock_get_pts(&entry->clock, 0.0, false);
+ if (pts == -1.0) {
+#ifndef CAMU_SINK_NO_VIDEO
+ pts = al_atomic_load(f64)(&entry->video.buf.pts, AL_ATOMIC_RELAXED);
+#endif
+ }
+ return pts;
+}
+
+void camu_sink_relative_seek(struct camu_sink *sink, f64 offset)
+{
+ nn_mutex_lock(&sink->mutex);
+ struct camu_sink_entry *current = sink->current;
+ nn_mutex_unlock(&sink->mutex);
+ if (!current) return;
+ f64 pts = tmp_get_entry_pts(current) + offset;
+ f64 duration = current->client.duration / 1000000.0;
+ queue_cmd(sink, (struct camu_sink_cmd){
+ .op = SEEK,
+ .value.f = pts / duration,
+ .opaque = current
+ });
+}
+
void camu_sink_reseek(struct camu_sink *sink)
{
nn_mutex_lock(&sink->mutex);
struct camu_sink_entry *current = sink->current;
nn_mutex_unlock(&sink->mutex);
+ if (!current) return;
queue_cmd(sink, (struct camu_sink_cmd){
.op = RESEEK,
.opaque = current
@@ -1743,12 +1787,7 @@ void camu_sink_status(struct camu_sink *sink)
al_log_info("sink", "Nothing playing.");
return;
}
- f64 pts = camu_clock_get_pts(&current->clock, 0.0, false);
- if (pts == -1.0) {
-#ifndef CAMU_SINK_NO_VIDEO
- pts = al_atomic_load(f64)(&current->video.buf.pts, AL_ATOMIC_RELAXED);
-#endif
- }
+ f64 pts = tmp_get_entry_pts(current);
f64 duration = current->client.duration / 1000000.0;
s32 text = 0;
u32 minute = (u32)(pts / 60);
diff --git a/src/libsink/sink.h b/src/libsink/sink.h
index 86c6a04..4e97f3a 100644
--- a/src/libsink/sink.h
+++ b/src/libsink/sink.h
@@ -119,6 +119,7 @@ void camu_sink_skip(struct camu_sink *sink, s32 n);
void camu_sink_shuffle(struct camu_sink *sink);
void camu_sink_toggle_pause(struct camu_sink *sink);
void camu_sink_seek(struct camu_sink *sink, f64 pos);
+void camu_sink_relative_seek(struct camu_sink *sink, f64 offset);
void camu_sink_reseek(struct camu_sink *sink);
void camu_sink_unset(struct camu_sink *sink);
void camu_sink_set_volume(struct camu_sink *sink, f32 volume);
diff --git a/src/render/meson.build b/src/render/meson.build
index f0fd2fd..1dd2dce 100644
--- a/src/render/meson.build
+++ b/src/render/meson.build
@@ -95,7 +95,7 @@ elif get_option('renderer') == 'libplacebo'
spirv_cross_c_shared
]
meson.override_dependency('spirv-cross-c-shared', spirv_cross_c_shared)
- libplacebo_opts += ['shaderc=enabled', 'd3d11=enabled', 'vulkan=enabled', 'opengl=disabled']
+ libplacebo_opts += ['shaderc=enabled', 'd3d11=enabled', 'vulkan=disabled', 'opengl=disabled']
else
libplacebo_opts += ['shaderc=disabled', 'opengl=enabled', 'vulkan=disabled', 'd3d11=disabled']
endif
@@ -122,6 +122,13 @@ if not libass.found()
'cache-build=disabled'
])
endif
+ # libass(e46aede):meson.build:84
+ # fontconfig(72b9a48):meson.build:28
+ freetype = dependency('freetype2',
+ version: '>=9.17.3',
+ default_options: [
+ 'harfbuzz=disabled'
+ ])
# libass(e46aede):meson.build:90
fribidi = dependency('fribidi',
version: '>=0.19.1',
@@ -130,13 +137,6 @@ if not libass.found()
'tests=false',
'bin=false'
])
- # libass(e46aede):meson.build:84
- # fontconfig(72b9a48):meson.build:28
- freetype = dependency('freetype2',
- version: '>=9.17.3',
- default_options: [
- 'harfbuzz=disabled'
- ])
# freetype2(42608f7):meson.build:346
harfbuz = dependency('harfbuzz',
version: '>=2.0.0',
@@ -145,7 +145,11 @@ if not libass.found()
'tests=disabled',
'introspection=disabled',
'docs=disabled',
- 'utilities=disabled'
+ 'utilities=disabled',
+ 'glib=disabled',
+ 'gobject=disabled',
+ 'cairo=disabled',
+ 'chafa=disabled'
])
libass = dependency('libass', default_options: libass_opts)
endif
diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c
index d078cbc..65a713e 100644
--- a/src/render/queue_libplacebo.c
+++ b/src/render/queue_libplacebo.c
@@ -31,6 +31,7 @@ static bool queue_lp_configure_subtitiles(struct camu_frame_queue *queue, u32 wi
AVCodecParameters *codecpar = stream->av.stream->codecpar;
ass_process_codec_private(lq->ass_track, (const char *)codecpar->extradata,
codecpar->extradata_size);
+ nn_mutex_init(&lq->subtitle_lock);
lq->have_subtitles = true;
return true;
}
@@ -130,6 +131,7 @@ static void queue_lp_push(struct camu_frame_queue *queue, struct camu_codec_fram
static struct camu_overlay_lp *create_subtitle_overlay(pl_gpu gpu, ASS_Image *ass_frame)
{
struct camu_overlay_lp *overlay = al_alloc_object(struct camu_overlay_lp);
+
for (; ass_frame; ass_frame = ass_frame->next) {
pl_tex tex = pl_tex_create(gpu, pl_tex_params(
.w = ass_frame->w,
@@ -196,6 +198,7 @@ static struct camu_overlay_lp *create_subtitle_overlay(pl_gpu gpu, ASS_Image *as
current->coords = PL_OVERLAY_COORDS_SRC_FRAME;
current->num_parts = 1;
}
+
return overlay;
}
@@ -215,6 +218,8 @@ static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *
));
}
+ // https://github.com/streetpea/chiaki-ng/blob/dd145ec2c802814e98fb833d3a9692169aa67315/gui/src/qmlmainwindow.cpp#L860
+ // https://github.com/streetpea/chiaki-ng/blob/dd145ec2c802814e98fb833d3a9692169aa67315/gui/src/qmlbackend.cpp#L786
if (!ok && frame->hw_frames_ctx) {
if (!lq->copy_frame_fallback) {
al_log_warn("frame_queue_libplacebo", "Falling back to software copy.");
@@ -225,7 +230,8 @@ static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *
lq->swframe->format = fmts[0];
av_free(fmts);
}
- ok = av_hwframe_transfer_data(lq->swframe, frame, 0) == 0;
+ s32 ret = av_hwframe_transfer_data(lq->swframe, frame, 0);
+ ok = ret == 0;
if (ok) {
av_frame_copy_props(lq->swframe, frame);
ok = pl_map_avframe_ex(gpu, out_frame, pl_avframe_params(
@@ -233,6 +239,8 @@ static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *
.tex = tex
));
av_frame_unref(lq->swframe);
+ } else {
+ al_log_error("frame_queue_libplacebo", "Failed to transfer hwframe from the device (%s).", av_err2str(ret));
}
}
@@ -240,13 +248,12 @@ static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *
if (ok && lq->have_subtitles) {
s64 now = av_rescale_q(frame->best_effort_timestamp, stream->time_base, (AVRational){ 1, 1000 });
- s32 change;
+ nn_mutex_lock(&lq->subtitle_lock);
+ s32 change; // 1 = different position, 2 = different content.
ASS_Image *ass_frame = ass_render_frame(lq->ass_renderer, lq->ass_track, now, &change);
if (ass_frame) {
struct camu_overlay_lp *overlay = NULL;
- if (lq->overlays.count > 0) {
- overlay = al_array_last(lq->overlays);
- }
+ if (lq->overlays.count > 0) overlay = al_array_last(lq->overlays);
if (!overlay || change > 0) {
overlay = create_subtitle_overlay(gpu, ass_frame);
overlay->lq = lq;
@@ -257,6 +264,7 @@ static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *
out_frame->num_overlays = overlay->num;
((struct pl_source_frame *)src)->frame_data = overlay;
}
+ nn_mutex_unlock(&lq->subtitle_lock);
}
av_frame_free(&frame);
@@ -284,6 +292,7 @@ static void unmap_av_frame(pl_gpu gpu, struct pl_frame *frame, const struct pl_s
}
al_free((struct pl_overlay_part *)current->parts);
}
+ al_free(overlay->overlays);
al_array_remove(lq->overlays, overlay);
al_free(overlay);
}
@@ -318,9 +327,11 @@ static void queue_lp_push_av_frame(struct camu_frame_queue *queue, AVFrame *fram
static void queue_lp_push_subtitle(struct camu_frame_queue *queue, struct camu_codec_packet *packet)
{
struct camu_frame_queue_lp *lq = (struct camu_frame_queue_lp *)queue;
- al_assert(lq->ass_track && lq->ass_renderer);
AVPacket *pkt = packet->av.pkt;
+ nn_mutex_lock(&lq->subtitle_lock);
+ al_assert(lq->ass_track && lq->ass_renderer);
ass_process_chunk(lq->ass_track, (const char *)pkt->data, pkt->size, pkt->pts, pkt->duration);
+ nn_mutex_unlock(&lq->subtitle_lock);
}
static void queue_lp_flush(struct camu_frame_queue *queue)
@@ -367,6 +378,7 @@ static void queue_lp_free(struct camu_frame_queue **queue)
if (lq->have_subtitles) {
ass_free_track(lq->ass_track);
ass_renderer_done(lq->ass_renderer);
+ nn_mutex_destroy(&lq->subtitle_lock);
}
if (lq->copy_frame_fallback) {
av_frame_free(&lq->swframe);
diff --git a/src/render/queue_libplacebo.h b/src/render/queue_libplacebo.h
index f87a34d..67d2479 100644
--- a/src/render/queue_libplacebo.h
+++ b/src/render/queue_libplacebo.h
@@ -24,6 +24,7 @@ struct camu_frame_queue_lp {
ASS_Library *ass;
ASS_Renderer *ass_renderer;
ASS_Track *ass_track;
+ struct nn_mutex subtitle_lock;
bool have_subtitles;
};
diff --git a/src/render/renderer.h b/src/render/renderer.h
index a4d3a53..b4863a0 100644
--- a/src/render/renderer.h
+++ b/src/render/renderer.h
@@ -47,6 +47,7 @@ struct camu_renderer {
void (*add_font)(struct camu_renderer *, struct camu_codec_stream *);
u32 (*get_latency)(struct camu_renderer *);
void (*resize)(struct camu_renderer *, u32 *, u32 *);
+ void (*set_fullscreen)(struct camu_renderer *, bool);
void (*render)(struct camu_renderer *, struct camu_screen *, bool);
#ifdef CAMU_HAVE_FFMPEG
s32 (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, s32 flags);
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index 8ff718e..a3a3109 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -8,6 +8,12 @@
#include "../screen/screen.h"
#include "../util/color_palette.h"
+#ifdef CAMU_RENDERER_DX11
+#include <nnwt/windows.h>
+#define COBJMACROS
+#include <libplacebo/d3d11.h>
+#endif
+
#include "renderer_libplacebo.h"
#include "queue_libplacebo.h"
@@ -35,6 +41,16 @@ static void renderer_lp_resize(struct camu_renderer *renderer, u32 *width, u32 *
}
}
+#ifdef CAMU_RENDERER_DX11
+static void renderer_lp_set_fullscreen(struct camu_renderer *renderer, bool fullscreen)
+{
+ struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
+ IDXGISwapChain *d3d_swapchain = pl_d3d11_swapchain_unwrap(lr->swapchain);
+ IDXGISwapChain1_SetFullscreenState(d3d_swapchain, fullscreen, NULL);
+ IDXGISwapChain1_Release(d3d_swapchain);
+}
+#endif
+
static void log_callback(void *userdata, enum pl_log_level level, const char *message)
{
(void)userdata;
@@ -123,6 +139,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
al_log_info("render_libplacebo", "Using Vulkan.");
#elif defined CAMU_RENDERER_DX11
+ (void)priv;
lr->d3d11 = pl_d3d11_create(lr->logger, pl_d3d11_params(
.debug = false
));
@@ -188,6 +205,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->params = pl_render_default_params;
//lr->params = pl_render_high_quality_params;
lr->params.deband_params = NULL;
+ //lr->params.frame_mixer = NULL;
// Clear manually so we can draw multiple images per frame.
lr->params.border = PL_CLEAR_SKIP;
@@ -232,7 +250,7 @@ static struct camu_frame_queue *renderer_lp_create_queue(struct camu_renderer *r
al_memset(&lq->params, 0, sizeof(struct pl_queue_params));
lq->params.interpolation_threshold = 0.01f;
lq->params.radius = pl_frame_mix_radius(&lr->params);
- lq->params.timeout = 0uL; // vsync
+ lq->params.timeout = 0;
lq->copy_frame_fallback = false;
lq->ass = lr->ass;
return queue;
@@ -347,7 +365,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
f64 tick = nn_get_tick();
f64 frame_time = tick - lr->last_render_tick;
if (frame_time > (1.0 / 24.0)) { // 24fps is totally arbitrary.
- al_log_info("render_libplacebo", "FRAME_TIME: %fs", frame_time);
+ al_log_info("render_libplacebo", "FRAME_TIME: %fs (%.2ffps)", frame_time, 1.0 / frame_time);
}
lr->last_render_tick = tick;
#endif
@@ -376,6 +394,11 @@ struct camu_renderer *camu_renderer_lp_create(void)
lr->r.add_font = renderer_lp_add_font;
lr->r.get_latency = renderer_lp_get_latency;
lr->r.resize = renderer_lp_resize;
+#ifdef CAMU_RENDERER_DX11
+ lr->r.set_fullscreen = renderer_lp_set_fullscreen;
+#else
+ lr->r.set_fullscreen = NULL;
+#endif
lr->r.render = renderer_lp_render;
lr->r.free = renderer_lp_free;
return (struct camu_renderer *)lr;
diff --git a/src/screen/screen.c b/src/screen/screen.c
index eb68278..d0926da 100644
--- a/src/screen/screen.c
+++ b/src/screen/screen.c
@@ -169,58 +169,68 @@ static bool scroll_callback(void *userdata, f64 y)
return false;
}
-static bool key_callback(void *userdata, u8 state, u8 button)
+static bool key_callback(void *userdata, u8 state, u16 button)
{
struct camu_screen *scr = (struct camu_screen *)userdata;
switch (state) {
case STELA_BUTTON_PRESSED:
- //al_printf("%x\n", button);
switch (button) {
- case 0x2a: // shift
+ case STELA_KEY_LEFT_SHIFT:
+ case STELA_KEY_RIGHT_SHIFT:
scr->flags |= CAMU_SCREEN_MOD_SHIFT;
break;
- case 0x1d: // control
+ case STELA_KEY_LEFT_CONTROL:
+ case STELA_KEY_RIGHT_CONTROL:
scr->flags |= CAMU_SCREEN_MOD_CONTROL;
break;
- case 0x10: // q
+ case STELA_KEY_Q:
scr->callback(scr->userdata, CAMU_SCREEN_CLOSE, NULL);
break;
- case 0x31: // n
- case 0x20: // d
- case 0x6a: // right arrow
- case 0x4d: // right arrow (wine?)
+ case STELA_KEY_RIGHT:
+ if (scr->flags & CAMU_SCREEN_MOD_CONTROL) {
+ f64 plus_ten = 10.0;
+ scr->callback(scr->userdata, CAMU_SCREEN_RELATIVE_SEEK, &plus_ten);
+ break;
+ }
+ // fallthrough
+ case STELA_KEY_D:
+ case STELA_KEY_N:
scr->callback(scr->userdata, CAMU_SCREEN_NEXT, NULL);
break;
- case 0x30: // b
- case 0x1e: // a
- case 0x69: // left arrow
- case 0x4b: // left arrow (wine?)
+ case STELA_KEY_LEFT:
+ if (scr->flags & CAMU_SCREEN_MOD_CONTROL) {
+ f64 minus_ten = -10.0;
+ scr->callback(scr->userdata, CAMU_SCREEN_RELATIVE_SEEK, &minus_ten);
+ break;
+ }
+ // fallthrough
+ case STELA_KEY_B:
+ case STELA_KEY_A:
scr->callback(scr->userdata, CAMU_SCREEN_PREVIOUS, NULL);
break;
- case 0x39: // spacebar
+ case STELA_KEY_SPACE:
scr->callback(scr->userdata, CAMU_SCREEN_TOGGLE_PAUSE, NULL);
break;
- case 0x1f: // s
+ case STELA_KEY_S:
scr->callback(scr->userdata, CAMU_SCREEN_SHUFFLE, NULL);
break;
- case 0x12: // e
+ case STELA_KEY_E:
scr->callback(scr->userdata, CAMU_SCREEN_RESEEK, NULL);
break;
- case 0x2f: { // v
+ case STELA_KEY_V: {
f32 volume = 1.0;
scr->callback(scr->userdata, CAMU_SCREEN_SET_VOLUME, &volume);
break;
- case 0xb: {
+ }
+ case STELA_KEY_0:
scr->callback(scr->userdata, CAMU_SCREEN_STATUS, NULL);
break;
- }
- }
#ifdef CAMU_SCREEN_DEBUG_KEY
- case 0x19: // p
+ case STELA_KEY_P:
scr->callback(scr->userdata, CAMU_SCREEN_DEBUG, NULL);
break;
#endif
- case 0x13: { // r
+ case STELA_KEY_R: {
struct camu_view *view = get_view_from_mouse_pos(scr);
if (view) {
if (scr->flags & CAMU_SCREEN_MOD_SHIFT) {
@@ -263,7 +273,7 @@ static bool key_callback(void *userdata, u8 state, u8 button)
}
break;
}
- case 0xd: { // +
+ case STELA_KEY_EQUAL: {
struct camu_view *view = get_view_from_mouse_pos(scr);
if (view) {
camu_view_zoom_simple(view, scr->width, scr->height, scr->width / 2.0, scr->height / 2.0, 0.05);
@@ -271,7 +281,7 @@ static bool key_callback(void *userdata, u8 state, u8 button)
}
break;
}
- case 0xc: { // -
+ case STELA_KEY_MINUS: {
struct camu_view *view = get_view_from_mouse_pos(scr);
if (view) {
camu_view_zoom_simple(view, scr->width, scr->height, scr->width / 2.0, scr->height / 2.0, -0.05);
@@ -285,10 +295,12 @@ static bool key_callback(void *userdata, u8 state, u8 button)
break;
case STELA_BUTTON_RELEASED:
switch (button) {
- case 0x2a: // shift
+ case STELA_KEY_LEFT_SHIFT:
+ case STELA_KEY_RIGHT_SHIFT:
scr->flags &= ~CAMU_SCREEN_MOD_SHIFT;
break;
- case 0x1d: // control
+ case STELA_KEY_LEFT_CONTROL:
+ case STELA_KEY_RIGHT_CONTROL:
scr->flags &= ~CAMU_SCREEN_MOD_CONTROL;
break;
}
@@ -298,14 +310,19 @@ static bool key_callback(void *userdata, u8 state, u8 button)
return false;
}
-static void key_immediate_callback(void *userdata, u8 state, u8 button)
+static void key_immediate_callback(void *userdata, u8 state, u16 button)
{
struct camu_screen *scr = (struct camu_screen *)userdata;
switch (state) {
case STELA_BUTTON_PRESSED:
switch (button) {
- case 0x21: { // f
- scr->window->toggle_fullscreen(scr->window);
+ case STELA_KEY_F: {
+ scr->fullscreen = !scr->fullscreen;
+ if (scr->renderer->set_fullscreen) {
+ scr->renderer->set_fullscreen(scr->renderer, scr->fullscreen);
+ } else {
+ scr->window->toggle_fullscreen(scr->window);
+ }
break;
}
}
@@ -364,6 +381,7 @@ bool camu_screen_create_window(struct camu_screen *scr, const char *name)
}
scr->width = scr->window->width;
scr->height = scr->window->height;
+ scr->fullscreen = false;
#ifdef STELA_EVENT_BUFFER
nn_thread_create(&scr->thread, event_thread, scr);
#endif
diff --git a/src/screen/screen.h b/src/screen/screen.h
index 2050d78..4b2e4c0 100644
--- a/src/screen/screen.h
+++ b/src/screen/screen.h
@@ -36,6 +36,7 @@ enum {
CAMU_SCREEN_SHUFFLE,
CAMU_SCREEN_TOGGLE_PAUSE,
CAMU_SCREEN_SEEK,
+ CAMU_SCREEN_RELATIVE_SEEK,
CAMU_SCREEN_RESEEK,
CAMU_SCREEN_SET_VOLUME,
CAMU_SCREEN_OFFSET_VOLUME,
@@ -62,6 +63,7 @@ struct camu_screen {
u32 flags;
u32 width;
u32 height;
+ bool fullscreen;
u64 last_click_ts;
f64 last_mouse_y;
f64 last_mouse_x;
diff --git a/src/server/server.c b/src/server/server.c
index d85d82c..10204df 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -684,6 +684,7 @@ static bool list_action_callback(void *userdata, struct nn_rpc_connection *conn,
s32 sequence = nn_packet_read_s32(packet);
u32 id = nn_packet_read_u32(packet);
f64 percent = nn_packet_read_f64(packet);
+ percent = CLAMP(percent, 0.0, 100.0);
lia_list_seek(list, sequence, id, percent);
break;
}
diff --git a/src/sink/desktop.c b/src/sink/desktop.c
index 61cad77..73a1667 100644
--- a/src/sink/desktop.c
+++ b/src/sink/desktop.c
@@ -55,6 +55,11 @@ static void screen_callback(void *userdata, u8 op, void *opaque)
camu_sink_seek(&c->sink, percent);
break;
}
+ case CAMU_SCREEN_RELATIVE_SEEK: {
+ f64 offset = *(f64 *)opaque;
+ camu_sink_relative_seek(&c->sink, offset);
+ break;
+ }
case CAMU_SCREEN_RESEEK:
camu_sink_reseek(&c->sink);
break;
diff --git a/subprojects/ffmpeg.wrap b/subprojects/ffmpeg.wrap
index 602ebad..e6f7abf 100644
--- a/subprojects/ffmpeg.wrap
+++ b/subprojects/ffmpeg.wrap
@@ -1,26 +1,30 @@
[wrap-file]
-directory = ffmpeg-7.1
+directory = ffmpeg-7.1.1
+#directory = ffmpeg-7.1
#directory = ffmpeg-5.1.6
#directory = ffmpeg-7.0.2
#directory = ffmpeg-7.0.1
#directory = ffmpeg-7.0
#directory = ffmpeg-6.1.1
#directory = ffmpeg-5.1.4
-source_url = https://ffmpeg.org/releases/ffmpeg-7.1.tar.gz
+source_url = https://ffmpeg.org/releases/ffmpeg-7.1.1.tar.gz
+#source_url = https://ffmpeg.org/releases/ffmpeg-7.1.tar.gz
#source_url = https://www.ffmpeg.org/releases/ffmpeg-5.1.6.tar.gz
#source_url = https://ffmpeg.org/releases/ffmpeg-7.0.2.tar.gz
#source_url = https://ffmpeg.org/releases/ffmpeg-7.0.1.tar.gz
#source_url = https://www.ffmpeg.org/releases/ffmpeg-7.0.tar.gz
#source_url = https://www.ffmpeg.org/releases/ffmpeg-6.1.1.tar.gz
#source_url = https://www.ffmpeg.org/releases/ffmpeg-5.1.4.tar.gz
-source_filename = ffmpeg-7.1.tar.gz
+source_filename = ffmpeg-7.1.1.tar.gz
+#source_filename = ffmpeg-7.1.tar.gz
#source_filename = ffmpeg-5.1.6.tar.gz
#source_filename = ffmpeg-7.0.2.tar.gz
#source_filename = ffmpeg-7.0.1.tar.gz
#source_filename = ffmpeg-7.0.tar.gz
#source_filename = ffmpeg-6.1.1.tar.gz
#source_filename = ffmpeg-5.1.4.tar.gz
-source_hash = 42a7dc0d1583885d1b8f6559fa7ce28f97acafea6803de6a8f73e3ba229348bd
+source_hash = 9a6e57a446b671012612aaeb9df5126794d5ac8f2015ca220934f99a6a4e0601
+#source_hash = 42a7dc0d1583885d1b8f6559fa7ce28f97acafea6803de6a8f73e3ba229348bd
#source_hash = 2a963f9f627dc55cac7ce4d2bb2e063ce52c8ab57185d2b592a631c36be56fda
#source_hash = 1233b3a93dd7517cc3c56b72a67f64041c044848d981e3deff4bebffa25f1054
#source_hash = e273eae00b4f833595654c1ee2b2349240e0332f9dbf3c4cadd39df9819ff052
diff --git a/subprojects/libalabaster.wrap b/subprojects/libalabaster.wrap
index 5977202..adaec6a 100644
--- a/subprojects/libalabaster.wrap
+++ b/subprojects/libalabaster.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libalabaster
-revision = 5f80381cc8d2875d27d14288b6f11c31a72fb3cf
+revision = 31715673a5b98991ef276decbd90f026559eaf4b
depth = 1
diff --git a/subprojects/libnaunet.wrap b/subprojects/libnaunet.wrap
index 0fb98e4..a869e82 100644
--- a/subprojects/libnaunet.wrap
+++ b/subprojects/libnaunet.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libnaunet
-revision = c4023623b89d7518c92f675f44355f5ae1196264
+revision = ce102493f377d0452e44c3a4bb6e6e15ab0c819d
depth = 1
diff --git a/subprojects/packagefiles/ffmpeg/meson.build b/subprojects/packagefiles/ffmpeg/meson.build
index 04533f8..8aa2f02 100644
--- a/subprojects/packagefiles/ffmpeg/meson.build
+++ b/subprojects/packagefiles/ffmpeg/meson.build
@@ -1,4 +1,4 @@
-project('ffmpeg', 'c', version: '7.1', meson_version: '>=0.57.0')
+project('ffmpeg', 'c', version: '7.1.1', meson_version: '>=0.57.0')
ffmpeg_version_string = meson.project_version()
@@ -6,8 +6,8 @@ compiler = meson.get_compiler('c')
cpu = target_machine.cpu_family()
is_64bit = (cpu == 'x86_64' or cpu == 'aarch64')
-is_debug = get_option('buildtype').startswith('debug')
-is_minsize = get_option('buildtype') == 'minsize'
+is_debug = get_option('debug')
+is_minsize = get_option('optimization') == 's'
is_linux = host_machine.system() == 'linux'
is_windows = host_machine.system() == 'windows'
is_msvc = compiler.get_id() == 'msvc' or compiler.get_id() == 'clang-cl'
@@ -20,10 +20,16 @@ if not is_debug
extra_options += ['--disable-debug']
endif
+if is_minsize
+ extra_options += ['--enable-small']
+endif
+
extra_options += ['--cc=' + compiler.cmd_array()[0]]
extra_options += ['--arch=' + cpu]
-extra_options += ['--nm=' + meson.get_external_property('nm', 'nm')]
-extra_options += ['--ar=' + meson.get_external_property('ar', 'ar')]
+if meson.is_cross_build()
+ extra_options += ['--nm=' + meson.get_external_property('nm', 'nm')]
+ extra_options += ['--ar=' + meson.get_external_property('ar', 'ar')]
+endif
if cpu == 'x86_64' or cpu == 'x86'
extra_options += ['--enable-x86asm']
@@ -90,7 +96,7 @@ endif
protocols = 'file,cache'
-if not is_android
+if is_linux or is_mingw
extra_options += ['--enable-libsoxr']
endif
diff --git a/subprojects/stela.wrap b/subprojects/stela.wrap
index b164d5f..004179f 100644
--- a/subprojects/stela.wrap
+++ b/subprojects/stela.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/stela
-revision = 1993433dc36dfae6a6c4b32f613e64ba213fdc23
+revision = 95e41dbad47f6c5d3868143b46938ec25582b6f1
depth = 1