Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,16 @@ jobs:
libavutil-dev libswresample-dev libusb-1.0-0 libusb-1.0-0-dev \
libv4l-dev
# SDL3 is not available in Ubuntu yet
- name: Install SDL3
run: |
app/deps/sdl.sh linux native shared
- name: Test
run: release/test_client.sh
run: |
export PKG_CONFIG_PATH="$PWD"/app/deps/work/install/linux-native-shared/lib/pkgconfig
export LD_LIBRARY_PATH="$PWD"/app/deps/work/install/linux-native-shared/lib
release/test_client.sh
build-linux-x86_64:
runs-on: ubuntu-22.04
Expand Down
41 changes: 22 additions & 19 deletions app/deps/sdl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ cd "$DEPS_DIR"
. common
process_args "$@"

VERSION=2.32.8
VERSION=3.2.18
FILENAME=SDL-$VERSION.tar.gz
PROJECT_DIR=SDL-release-$VERSION
SHA256SUM=dd35e05644ae527848d02433bec24dd0ea65db59faecf1a0e5d1880c533dac2c
SHA256SUM=51539fa13e546bc50c632beed3f34257de2baa38a4c642048de56377903b4265

cd "$SOURCES_DIR"

Expand All @@ -35,45 +35,48 @@ else
cd "$DIRNAME"

conf=(
--prefix="$INSTALL_DIR/$DIRNAME"
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR/$DIRNAME"
)

if [[ "$HOST" == linux ]]
then
conf+=(
--enable-video-wayland
--enable-video-x11
-DSDL_WAYLAND=ON
-DSDL_X11=ON
)
fi

if [[ "$LINK_TYPE" == static ]]
then
conf+=(
--enable-static
--disable-shared
-DBUILD_SHARED_LIBS=OFF
)
else
conf+=(
--disable-static
--enable-shared
-DBUILD_SHARED_LIBS=ON
)
fi

if [[ "$BUILD_TYPE" == cross ]]
then
if [[ "$HOST" = win32 ]]
then
TOOLCHAIN_FILENAME="cmake-toolchain-mingw64-i686.cmake"
elif [[ "$HOST" = win64 ]]
then
TOOLCHAIN_FILENAME="cmake-toolchain-mingw64-x86_64.cmake"
else
echo "Unsupported cross-build to host: $HOST" >&2
exit 1
fi

conf+=(
--host="$HOST_TRIPLET"
-DCMAKE_TOOLCHAIN_FILE="$SOURCES_DIR/$PROJECT_DIR/build-scripts/$TOOLCHAIN_FILENAME"
)
fi

"$SOURCES_DIR/$PROJECT_DIR"/configure "${conf[@]}"
cmake "$SOURCES_DIR/$PROJECT_DIR" "${conf[@]}"
fi

make -j
# There is no "make install-strip"
make install
# Strip manually
if [[ "$LINK_TYPE" == shared && "$HOST" == win* ]]
then
${HOST_TRIPLET}-strip "$INSTALL_DIR/$DIRNAME/bin/SDL2.dll"
fi
cmake --build .
cmake --install .
3 changes: 2 additions & 1 deletion app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ src = [
'src/util/thread.c',
'src/util/tick.c',
'src/util/timeout.c',
'src/util/window.c',
]

conf = configuration_data()
Expand Down Expand Up @@ -117,7 +118,7 @@ dependencies = [
dependency('libavcodec', version: '>= 57.37', static: static),
dependency('libavutil', static: static),
dependency('libswresample', static: static),
dependency('sdl2', version: '>= 2.0.5', static: static),
dependency('sdl3', version: '>= 3.2.0', static: static),
]

if v4l2_support
Expand Down
85 changes: 68 additions & 17 deletions app/src/audio_player.c
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
#include "audio_player.h"

#include "util/log.h"
#include "SDL3/SDL_hints.h"

/** Downcast frame_sink to sc_audio_player */
#define DOWNCAST(SINK) container_of(SINK, struct sc_audio_player, frame_sink)

#define SC_SDL_SAMPLE_FMT AUDIO_F32
#define SC_SDL_SAMPLE_FMT SDL_AUDIO_F32LE

static void SDLCALL
sc_audio_player_sdl_callback(void *userdata, uint8_t *stream, int len_int) {
struct sc_audio_player *ap = userdata;
sc_audio_player_stream_callback(void *userdata, SDL_AudioStream *stream,
int additional_amount, int total_amount) {
(void) total_amount;

assert(len_int > 0);
size_t len = len_int;
struct sc_audio_player *ap = userdata;

size_t len = additional_amount;
assert(len % ap->audioreg.sample_size == 0);
uint32_t out_samples = len / ap->audioreg.sample_size;

sc_audio_regulator_pull(&ap->audioreg, stream, out_samples);
// The requested amount may exceed the internal aout_buffer size.
// In this (unlikely) case, send the data to the stream in multiple chunks.
while (len) {
size_t chunk_size = MIN(ap->aout_buffer_size, len);
uint32_t out_samples = chunk_size / ap->audioreg.sample_size;
sc_audio_regulator_pull(&ap->audioreg, ap->aout_buffer,
out_samples);

assert(chunk_size <= len);
len -= chunk_size;
bool ok =
SDL_PutAudioStreamData(stream, ap->aout_buffer, chunk_size);
if (!ok) {
LOGW("Audio stream error: %s", SDL_GetError());
return;
}
}
}

static bool
Expand Down Expand Up @@ -61,23 +78,45 @@ sc_audio_player_frame_sink_open(struct sc_frame_sink *sink,
/ SC_TICK_FREQ;
assert(aout_samples <= 0xFFFF);

SDL_AudioSpec desired = {
char str[5 + 1]; // max 65535
int r = snprintf(str, sizeof(str), "%" PRIu16, (uint16_t) aout_samples);
assert(r >= 0 && (size_t) r < sizeof(str));
(void) r;
if (!SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, str)) {
LOGE("Could not set audio output buffer");
sc_audio_regulator_destroy(&ap->audioreg);
return false;
}

// Make the buffer at least 1024 samples long (the hint is not always
// honored)
uint64_t aout_buffer_samples = MAX(1024, aout_samples);
ap->aout_buffer_size = aout_buffer_samples * sample_size;
ap->aout_buffer = malloc(ap->aout_buffer_size);
if (!ap->aout_buffer) {
sc_audio_regulator_destroy(&ap->audioreg);
return false;
}

SDL_AudioSpec spec = {
.freq = ctx->sample_rate,
.format = SC_SDL_SAMPLE_FMT,
.channels = nb_channels,
.samples = aout_samples,
.callback = sc_audio_player_sdl_callback,
.userdata = ap,
};
SDL_AudioSpec obtained;

ap->device = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
if (!ap->device) {
ap->stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
&spec,
sc_audio_player_stream_callback, ap);
if (!ap->stream) {
LOGE("Could not open audio device: %s", SDL_GetError());
free(ap->aout_buffer);
sc_audio_regulator_destroy(&ap->audioreg);
return false;
}

ap->device = SDL_GetAudioStreamDevice(ap->stream);
assert(ap->device);

// The thread calling open() is the thread calling push(), which fills the
// audio buffer consumed by the SDL audio thread.
ok = sc_thread_set_priority(SC_THREAD_PRIORITY_TIME_CRITICAL);
Expand All @@ -86,7 +125,14 @@ sc_audio_player_frame_sink_open(struct sc_frame_sink *sink,
(void) ok; // We don't care if it worked, at least we tried
}

SDL_PauseAudioDevice(ap->device, 0);
ok = SDL_ResumeAudioDevice(ap->device);
if (!ok) {
LOGE("Could not resume audio device: %s", SDL_GetError());
SDL_DestroyAudioStream(ap->stream);
free(ap->aout_buffer);
sc_audio_regulator_destroy(&ap->audioreg);
return false;
}

return true;
}
Expand All @@ -95,11 +141,16 @@ static void
sc_audio_player_frame_sink_close(struct sc_frame_sink *sink) {
struct sc_audio_player *ap = DOWNCAST(sink);

assert(ap->stream);
assert(ap->device);
SDL_PauseAudioDevice(ap->device, 1);
SDL_CloseAudioDevice(ap->device);
SDL_PauseAudioDevice(ap->device);

// ap->device is owned by ap->stream
SDL_DestroyAudioStream(ap->stream);

sc_audio_regulator_destroy(&ap->audioreg);

free(ap->aout_buffer);
}

void
Expand Down
8 changes: 6 additions & 2 deletions app/src/audio_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include "common.h"

#include <SDL2/SDL_audio.h>
#include <SDL3/SDL_audio.h>

#include "audio_regulator.h"
#include "trait/frame_sink.h"
Expand All @@ -22,7 +22,11 @@ struct sc_audio_player {
// SDL audio output buffer size
sc_tick output_buffer_duration;

SDL_AudioDeviceID device;
uint8_t *aout_buffer;
size_t aout_buffer_size;

SDL_AudioStream *stream;
SDL_AudioDeviceID device; // owned by the audio stream
struct sc_audio_regulator audioreg;
};

Expand Down
24 changes: 1 addition & 23 deletions app/src/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <libavcodec/version.h>
#include <libavformat/version.h>
#include <libavutil/version.h>
#include <SDL2/SDL_version.h>
#include <SDL3/SDL_version.h>

#ifndef _WIN32
# define PRIu64_ PRIu64
Expand Down Expand Up @@ -61,28 +61,6 @@
# define SCRCPY_LAVC_HAS_CODECPAR_CODEC_SIDEDATA
#endif

#if SDL_VERSION_ATLEAST(2, 0, 6)
// <https://github.com/libsdl-org/SDL/commit/d7a318de563125e5bb465b1000d6bc9576fbc6fc>
# define SCRCPY_SDL_HAS_HINT_TOUCH_MOUSE_EVENTS
#endif

#if SDL_VERSION_ATLEAST(2, 0, 8)
// <https://hg.libsdl.org/SDL/rev/dfde5d3f9781>
# define SCRCPY_SDL_HAS_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
#endif

#if SDL_VERSION_ATLEAST(2, 0, 16)
# define SCRCPY_SDL_HAS_THREAD_PRIORITY_TIME_CRITICAL
#endif

#if SDL_VERSION_ATLEAST(2, 0, 18)
# define SCRCPY_SDL_HAS_HINT_APP_NAME
#endif

#if SDL_VERSION_ATLEAST(2, 0, 14)
# define SCRCPY_SDL_HAS_HINT_AUDIO_DEVICE_APP_NAME
#endif

#ifndef HAVE_STRDUP
char *strdup(const char *s);
#endif
Expand Down
Loading