diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/codec/ffmpeg/resampler.c | 2 | ||||
| -rw-r--r-- | src/codec/meson.build | 1 | ||||
| -rw-r--r-- | src/fruits/ctv/ctv.c | 102 | ||||
| -rw-r--r-- | src/fruits/ctv/meson.build | 4 | ||||
| -rw-r--r-- | src/fruits/droid/ctv/.gitignore | 3 | ||||
| -rw-r--r-- | src/fruits/droid/ctv/app/src/main/AndroidManifest.xml | 2 | ||||
| -rw-r--r-- | src/fruits/droid/ctv/app/src/main/jniLibs/arm64-v8a/.gitignore | 1 | ||||
| -rw-r--r-- | src/fruits/droid/ctv/app/src/main/jniLibs/armeabi-v7a/.gitignore | 1 | ||||
| -rw-r--r-- | src/fruits/droid/ctv/app/src/main/jniLibs/x86/.gitignore | 1 | ||||
| -rw-r--r-- | src/libsink/sink.c | 8 | ||||
| -rw-r--r-- | src/mixer/audio_miniaudio.c | 4 | ||||
| -rw-r--r-- | src/mixer/meson.build | 4 | ||||
| -rw-r--r-- | src/screen/screen.c | 4 | ||||
| -rw-r--r-- | src/screen/screen.h | 2 | ||||
| -rw-r--r-- | src/sink/common.h | 87 | ||||
| -rw-r--r-- | src/sink/desktop.c | 77 |
16 files changed, 209 insertions, 94 deletions
diff --git a/src/codec/ffmpeg/resampler.c b/src/codec/ffmpeg/resampler.c index 00418e6..4f5a2ab 100644 --- a/src/codec/ffmpeg/resampler.c +++ b/src/codec/ffmpeg/resampler.c @@ -23,7 +23,7 @@ static bool ff_resampler_init(struct camu_resampler *resamp, struct camu_resampl return false; } -#ifndef _WIN32 +#ifdef CAMU_HAVE_SOXR // Slower but more accurate resampler. av_opt_set_int(av->resample_context, "resampler", SWR_ENGINE_SOXR, 0); #endif diff --git a/src/codec/meson.build b/src/codec/meson.build index 32a942e..fa5ff9a 100644 --- a/src/codec/meson.build +++ b/src/codec/meson.build @@ -43,6 +43,7 @@ if get_option('codecs').contains('ffmpeg') soxr = compiler.find_library('soxr', required: false) if soxr.found() ffmpeg_deps += [soxr] + ffmpeg_args += ['-DCAMU_HAVE_SOXR'] endif endif endif diff --git a/src/fruits/ctv/ctv.c b/src/fruits/ctv/ctv.c index 9c45637..75936eb 100644 --- a/src/fruits/ctv/ctv.c +++ b/src/fruits/ctv/ctv.c @@ -1,26 +1,116 @@ #include <stl/window.h> #include <stl/platform.h> -#include "../../sink/desktop.h" +#include "../../screen/screen.h" +#include "../../render/renderer_libplacebo.h" +#include "../../mixer/mixer.h" +#include "../../libsink/sink.h" +#include "../../mixer/audio_null.h" +#include "../../mixer/audio_miniaudio.h" +#include "../../sink/common.h" +#include "../../server/common.c" struct ctv { struct aki_event_loop loop; - struct camu_desktop desktop; + struct camu_screen scr; + struct camu_renderer *renderer; + struct camu_mixer mixer; + struct camu_sink sink; + struct aki_thread thread; + bool created; }; -static void onSurfaceDestroyed(GLFMDisplay *display) { +static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque) +{ + struct ctv *c = (struct ctv *)userdata; + if (!camu_default_sink_callback(&c->scr, &c->mixer, op, type, opaque)) { + camu_sink_close(&c->sink); + } + return CAMU_SINK_OK; } -static void onDraw(GLFMDisplay *display) { +static void screen_callback(void *userdata, u8 op, void *opaque) +{ + struct ctv *c = (struct ctv *)userdata; + (void)c; + (void)op; + (void)opaque; } -void glfmMain(GLFMDisplay *display) { +static aki_thread_result AKI_THREADCALL event_loop_thread(void *userdata) +{ + struct ctv *c = (struct ctv *)userdata; + aki_event_loop_run(&c->loop); + return 0; +} + +static void onSurfaceCreated(GLFMDisplay *display, s32 width, s32 height) +{ + struct ctv *c = (struct ctv *)glfmGetUserData(display); + (void)width; + (void)height; + if (!c->created) { + c->scr.callback = screen_callback; + c->scr.userdata = c; + camu_screen_init(&c->scr, display); + camu_screen_create_window(&c->scr, "ctv"); + c->renderer = camu_renderer_lp_create(); + camu_screen_create_renderer(&c->scr, c->renderer); + + camu_mixer_init(&c->mixer, camu_audio_miniaudio_create()); + c->mixer.audio->configure_stream(c->mixer.audio, NULL); + camu_mixer_pick_format(&c->mixer, &c->mixer.fmt); + + aki_event_loop_init(&c->loop); + + camu_sink_init(&c->sink, &c->loop, &c->mixer, c->renderer); + c->sink.callback = sink_callback; + c->sink.userdata = c; + camu_sink_connect(&c->sink, AKI_SOCKET_TCP, CAMU_SERVER_IP, CAMU_PORT, al_str_c("ctv")); + + aki_thread_create(&c->thread, event_loop_thread, c); + + c->created = true; + } +} + +static void onSurfaceDestroyed(GLFMDisplay *display) +{ + (void)display; +} + +static void onDraw(GLFMDisplay *display) +{ + struct ctv *c = (struct ctv *)glfmGetUserData(display); + if (camu_screen_tick(&c->scr)) { + c->renderer->render(c->renderer, &c->scr); + } +} + +static s32 log_callback(void *userdata, char *message) +{ + (void)userdata; + __android_log_print(ANDROID_LOG_DEBUG, "CTV", "%s", message); + s32 ret = al_strlen(message); + al_free(message); + return ret; +} + +void glfmMain(GLFMDisplay *display) +{ + struct ctv *c = al_alloc_object(struct ctv); + c->created = false; + + al_set_print(log_callback, c); + + glfmSetUserData(display, c); glfmSetDisplayConfig(display, GLFMRenderingAPIOpenGLES2, GLFMColorFormatRGBA8888, GLFMDepthFormatNone, GLFMStencilFormatNone, GLFMMultisampleNone); - glfmSetRenderFunc(display, onDraw); + glfmSetSurfaceCreatedFunc(display, onSurfaceCreated); glfmSetSurfaceDestroyedFunc(display, onSurfaceDestroyed); + glfmSetRenderFunc(display, onDraw); } diff --git a/src/fruits/ctv/meson.build b/src/fruits/ctv/meson.build index 768f9e1..c06cec3 100644 --- a/src/fruits/ctv/meson.build +++ b/src/fruits/ctv/meson.build @@ -1,6 +1,6 @@ ctv_src = ['ctv.c'] -ctv_deps = [desktop] -ctv_args = [] +ctv_deps = [common_deps, buffer, render, screen, mixer, libsink] +ctv_args = ['-DCAMU_MIXER_THREADED', '-DCAMU_SCREEN_THREADED'] # https://github.com/google/ExoPlayer/issues/9933#issuecomment-1029775358 shared_library('ctv', ctv_src, dependencies: ctv_deps, c_args: ctv_args, link_args: ['-Wl,-Bsymbolic', '-static-libstdc++']) diff --git a/src/fruits/droid/ctv/.gitignore b/src/fruits/droid/ctv/.gitignore index 9c951ae..565a541 100644 --- a/src/fruits/droid/ctv/.gitignore +++ b/src/fruits/droid/ctv/.gitignore @@ -14,6 +14,3 @@ .externalNativeBuild .cxx local.properties -app/src/main/jniLibs/arm64-v8a/* -app/src/main/jniLibs/armeabi-v7a/* -app/src/main/jniLibs/x86/* diff --git a/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml b/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml index be6971b..4393ee9 100644 --- a/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml +++ b/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> - + <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" diff --git a/src/fruits/droid/ctv/app/src/main/jniLibs/arm64-v8a/.gitignore b/src/fruits/droid/ctv/app/src/main/jniLibs/arm64-v8a/.gitignore new file mode 100644 index 0000000..64b29ac --- /dev/null +++ b/src/fruits/droid/ctv/app/src/main/jniLibs/arm64-v8a/.gitignore @@ -0,0 +1 @@ +libctv.so diff --git a/src/fruits/droid/ctv/app/src/main/jniLibs/armeabi-v7a/.gitignore b/src/fruits/droid/ctv/app/src/main/jniLibs/armeabi-v7a/.gitignore new file mode 100644 index 0000000..64b29ac --- /dev/null +++ b/src/fruits/droid/ctv/app/src/main/jniLibs/armeabi-v7a/.gitignore @@ -0,0 +1 @@ +libctv.so diff --git a/src/fruits/droid/ctv/app/src/main/jniLibs/x86/.gitignore b/src/fruits/droid/ctv/app/src/main/jniLibs/x86/.gitignore new file mode 100644 index 0000000..64b29ac --- /dev/null +++ b/src/fruits/droid/ctv/app/src/main/jniLibs/x86/.gitignore @@ -0,0 +1 @@ +libctv.so diff --git a/src/libsink/sink.c b/src/libsink/sink.c index 894dc40..538515a 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -537,7 +537,9 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str } else { entry->audio.state = BUFFER_CONFIGURED; } - evaluate_latency(sink, entry); + if (VIDEO_READY_OR_EMPTY(entry)) { + evaluate_latency(sink, entry); + } aki_mutex_unlock(&sink->mutex); break; #ifndef CAMU_SINK_NO_VIDEO @@ -552,7 +554,9 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str } else { entry->video.state = BUFFER_CONFIGURED; } - evaluate_latency(sink, entry); + if (AUDIO_READY_OR_EMPTY(entry)) { + evaluate_latency(sink, entry); + } aki_mutex_unlock(&sink->mutex); break; #endif diff --git a/src/mixer/audio_miniaudio.c b/src/mixer/audio_miniaudio.c index 2f98335..4cb67de 100644 --- a/src/mixer/audio_miniaudio.c +++ b/src/mixer/audio_miniaudio.c @@ -188,6 +188,10 @@ static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opa static u64 audio_miniaudio_get_latency(struct camu_audio *audio) { struct camu_audio_miniaudio *ma = (struct camu_audio_miniaudio *)audio; + al_log_debug("audio_miniaudio", "periods: %u, period_size_in_frames: %u, sample_rate: %u.", + ma->device.playback.internalPeriods, + ma->device.playback.internalPeriodSizeInFrames, + ma->device.playback.internalSampleRate); u32 periods = ma->device.playback.internalPeriods; return (ma->device.playback.internalPeriodSizeInFrames * periods) / (ma->device.playback.internalSampleRate / 1000000.0); diff --git a/src/mixer/meson.build b/src/mixer/meson.build index 0a2e9d7..7adc75c 100644 --- a/src/mixer/meson.build +++ b/src/mixer/meson.build @@ -1,4 +1,4 @@ -mixer_src = ['mixer.c'] +mixer_src = ['mixer.c', 'audio_null.c'] mixer_deps = [common_deps] mixer_args = [] @@ -26,8 +26,6 @@ if use_miniaudio elif is_android mixer_args += ['-DMA_ENABLE_AAUDIO'] endif -else - mixer_src += ['audio_null.c'] endif mixer = declare_dependency(sources: mixer_src, dependencies: mixer_deps, compile_args: mixer_args) diff --git a/src/screen/screen.c b/src/screen/screen.c index aa61ba6..bd6547f 100644 --- a/src/screen/screen.c +++ b/src/screen/screen.c @@ -259,12 +259,12 @@ static void key_immediate_callback(void *userdata, u8 state, u8 button) } } -bool camu_screen_init(struct camu_screen *scr) +bool camu_screen_init(struct camu_screen *scr, void *context) { al_atomic_store(s32)(&scr->state, CAMU_SCREEN_PAUSED, AL_ATOMIC_RELAXED); al_array_init(scr->videos); scr->renderer = NULL; - scr->window = stl_window_create(); + scr->window = stl_window_create(context); scr->window->pointer_pos_callback = pointer_pos_callback; scr->window->scroll_callback = scroll_callback; scr->window->mouse_button_callback = mouse_button_callback; diff --git a/src/screen/screen.h b/src/screen/screen.h index 0c56cf9..bfb2dd3 100644 --- a/src/screen/screen.h +++ b/src/screen/screen.h @@ -67,7 +67,7 @@ struct camu_screen { void *userdata; }; -bool camu_screen_init(struct camu_screen *scr); +bool camu_screen_init(struct camu_screen *scr, void *context); bool camu_screen_create_window(struct camu_screen *scr, const char *name); bool camu_screen_create_renderer(struct camu_screen *scr, struct camu_renderer *renderer); void camu_screen_add_buffer(struct camu_screen *scr, struct camu_video_buffer *buf); diff --git a/src/sink/common.h b/src/sink/common.h new file mode 100644 index 0000000..ed84c39 --- /dev/null +++ b/src/sink/common.h @@ -0,0 +1,87 @@ +#include <al/log.h> + +#include "../screen/screen.h" +#include "../mixer/mixer.h" +#include "../libsink/sink.h" + +AL_UNUSED_FUNCTION_PUSH + +static bool camu_default_sink_callback(struct camu_screen *scr, struct camu_mixer *mixer, u8 op, u8 type, void *opaque) +{ + switch (op) { + case CAMU_SINK_ADD_BUFFER: + switch (type) { + case CAMU_SINK_AUDIO: { + struct camu_audio_buffer *buf = (struct camu_audio_buffer *)opaque; + camu_mixer_add_buffer(mixer, buf); + al_log_debug("camu_desktop", "Audio buffer added."); + break; + } + case CAMU_SINK_VIDEO: { + struct camu_video_buffer *buf = (struct camu_video_buffer *)opaque; + camu_screen_add_buffer(scr, buf); + al_log_debug("camu_desktop", "Video buffer added."); + break; + } + } + break; + case CAMU_SINK_REMOVE_BUFFER: + switch (type) { + case CAMU_SINK_AUDIO: { + struct camu_audio_buffer *buf = (struct camu_audio_buffer *)opaque; + camu_mixer_remove_buffer(mixer, buf); + al_log_debug("camu_desktop", "Audio buffer removed."); + break; + } + case CAMU_SINK_VIDEO: { + struct camu_video_buffer *buf = (struct camu_video_buffer *)opaque; + camu_screen_remove_buffer(scr, buf); + al_log_debug("camu_desktop", "Video buffer removed."); + break; + } + } + break; + case CAMU_SINK_SWAP_BUFFER: + switch (type) { + case CAMU_SINK_AUDIO: { + break; + } + } + break; + case CAMU_SINK_START: + switch (type) { + case CAMU_SINK_AUDIO: { + camu_mixer_resume(mixer); + al_log_info("camu_desktop", "Audio started."); + break; + } + case CAMU_SINK_VIDEO: { + camu_screen_set_state(scr, CAMU_SCREEN_PLAYING); + camu_screen_wake(scr); + al_log_info("camu_desktop", "Video started."); + break; + } + } + break; + case CAMU_SINK_STOP: + switch (type) { + case CAMU_SINK_AUDIO: { + camu_mixer_pause(mixer); + al_log_info("camu_desktop", "Audio stopped."); + break; + } + case CAMU_SINK_VIDEO: { + camu_screen_set_state(scr, CAMU_SCREEN_PAUSED); + al_log_info("camu_desktop", "Video stopped."); + break; + } + } + break; + case CAMU_SINK_EXIT: + return false; + + } + return true; +} + +AL_UNUSED_FUNCTION_POP diff --git a/src/sink/desktop.c b/src/sink/desktop.c index 2e2863f..efe835e 100644 --- a/src/sink/desktop.c +++ b/src/sink/desktop.c @@ -1,7 +1,7 @@ #include <al/log.h> +#include "../mixer/audio_null.h" #include "../mixer/audio_miniaudio.h" -//#include "../mixer/audio_null.h" #if defined CAMU_RENDERER_TIGER #include "../render/renderer_tiger.h" #elif defined CAMU_RENDERER_LIBPLACEBO @@ -9,85 +9,16 @@ #endif #include "desktop.h" +#include "common.h" static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque) { struct camu_desktop *c = (struct camu_desktop *)userdata; - switch (op) { - case CAMU_SINK_ADD_BUFFER: - switch (type) { - case CAMU_SINK_AUDIO: { - struct camu_audio_buffer *buf = (struct camu_audio_buffer *)opaque; - camu_mixer_add_buffer(&c->mixer, buf); - al_log_debug("camu_desktop", "Audio buffer added."); - break; - } - case CAMU_SINK_VIDEO: { - struct camu_video_buffer *buf = (struct camu_video_buffer *)opaque; - camu_screen_add_buffer(&c->scr, buf); - al_log_debug("camu_desktop", "Video buffer added."); - break; - } - } - break; - case CAMU_SINK_REMOVE_BUFFER: - switch (type) { - case CAMU_SINK_AUDIO: { - struct camu_audio_buffer *buf = (struct camu_audio_buffer *)opaque; - camu_mixer_remove_buffer(&c->mixer, buf); - al_log_debug("camu_desktop", "Audio buffer removed."); - break; - } - case CAMU_SINK_VIDEO: { - struct camu_video_buffer *buf = (struct camu_video_buffer *)opaque; - camu_screen_remove_buffer(&c->scr, buf); - al_log_debug("camu_desktop", "Video buffer removed."); - break; - } - } - break; - case CAMU_SINK_SWAP_BUFFER: - switch (type) { - case CAMU_SINK_AUDIO: { - break; - } - } - break; - case CAMU_SINK_START: - switch (type) { - case CAMU_SINK_AUDIO: { - camu_mixer_resume(&c->mixer); - al_log_info("camu_desktop", "Audio started."); - break; - } - case CAMU_SINK_VIDEO: { - camu_screen_set_state(&c->scr, CAMU_SCREEN_PLAYING); - camu_screen_wake(&c->scr); - al_log_info("camu_desktop", "Video started."); - break; - } - } - break; - case CAMU_SINK_STOP: - switch (type) { - case CAMU_SINK_AUDIO: { - camu_mixer_pause(&c->mixer); - al_log_info("camu_desktop", "Audio stopped."); - break; - } - case CAMU_SINK_VIDEO: { - camu_screen_set_state(&c->scr, CAMU_SCREEN_PAUSED); - al_log_info("camu_desktop", "Video stopped."); - break; - } - } - break; - case CAMU_SINK_EXIT: + if (!camu_default_sink_callback(&c->scr, &c->mixer, op, type, opaque)) { camu_sink_close(&c->sink); if (c->exit_callback) { c->exit_callback(c->userdata, c); } - break; } return CAMU_SINK_OK; } @@ -131,7 +62,7 @@ bool camu_desktop_init(struct camu_desktop *c, const char *name) { c->scr.callback = screen_callback; c->scr.userdata = c; - if (!camu_screen_init(&c->scr) || !camu_screen_create_window(&c->scr, name)) { + if (!camu_screen_init(&c->scr, NULL) || !camu_screen_create_window(&c->scr, name)) { return false; } #if defined CAMU_RENDERER_TIGER |