Compare commits

..

2 Commits

Author SHA1 Message Date
652e210bfb cross-compile 2022-05-23 21:07:30 +02:00
a1117c58ac [WIP] build deps 2022-05-23 21:06:52 +02:00
20 changed files with 232 additions and 69 deletions

2
app/deps/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/data
/target-*

64
app/deps/src/build-ffmpeg.sh Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env bash
. init_deps
VERSION=5.0.1
FILENAME=ffmpeg-$VERSION.tar.xz
URL=http://ffmpeg.org/releases/ffmpeg-$VERSION.tar.xz
SHA256SUM=ef2efae259ce80a240de48ec85ecb062cecca26e4352ffb3fda562c21a93007b
DEP_DIR="$DATA_DIR/ffmpeg-$VERSION-$SHA256SUM"
if [[ ! -d "$DEP_DIR" ]]
then
get_file "$URL" "$FILENAME" "$SHA256SUM"
mkdir "$DEP_DIR"
cd "$DEP_DIR"
tar xvf "../$FILENAME"
else
echo "$DEP_DIR found"
cd "$DEP_DIR"
fi
cd "ffmpeg-$VERSION"
rm -rf "build-$HOST"
mkdir "build-$HOST"
cd "build-$HOST"
params=(
--prefix="$INSTALL_DIR"
--arch="$ARCH"
--disable-autodetect
--disable-programs
--disable-everything
--disable-doc
--disable-swresample
--disable-swscale
--disable-avfilter
--disable-postproc
--disable-static
--enable-shared
--enable-decoder=h264
--enable-decoder=png
--enable-muxer=mp4
--enable-muxer=matroska
)
case "$HOST_SYSTEM" in
linux)
params+=(--enable-libv4l2)
;;
windows)
params+=(--target-os=mingw32)
params+=(--cross-prefix="$HOST-")
;;
*)
fail "Unsupported platform: $HOST"
;;
esac
../configure "${params[@]}"
make -j $NJOBS
make install

56
app/deps/src/init_deps Normal file
View File

@ -0,0 +1,56 @@
set -e
# The caller must set the following environment variable
# - $HOST (e.g. "x86_64-linux-gnu")
# - $HOST_SYSTEM ("linux", "windows", "apple"), for scripts convenience
fail() {
echo "$1" >&2
exit 1
}
[[ -z "$HOST" ]] && fail '$HOST not defined'
if [[ "$HOST" == *linux* ]]
then
HOST_SYSTEM='linux'
elif [[ "$HOST" == *mingw* ]]
then
HOST_SYSTEM='windows'
else
fail "Host system could not be deduced from '$HOST'"
fi
ARCH="${HOST%%-*}"
[[ -z "$ARCH" ]] && fail "Arch could not be deduced from '$HOST'"
DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DIR"
DATA_DIR=$(realpath ../data)
INSTALL_DIR=$(realpath ../target-"$HOST")
NJOBS=$(grep -c ^processor /proc/cpuinfo)
mkdir -p "$DATA_DIR"
cd "$DATA_DIR"
checksum() {
local file="$1"
local sum="$2"
echo "$file: verifying checksum..."
echo "$sum $file" | sha256sum -c
}
get_file() {
local url="$1"
local file="$2"
local sum="$3"
if [[ -f "$file" ]]
then
echo "$file: found"
else
echo "$file: not found, downloading..."
wget "$url" -O "$file"
fi
checksum "$file" "$sum"
}

View File

@ -401,7 +401,6 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
#define BUFSIZE 65536
char *buf = malloc(BUFSIZE);
if (!buf) {
LOG_OOM();
return false;
}
@ -711,5 +710,5 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) {
// It is parsed as a NUL-terminated string
buf[r] = '\0';
return sc_adb_parse_device_ip(buf);
return sc_adb_parse_device_ip_from_output(buf);
}

View File

@ -199,7 +199,7 @@ sc_adb_parse_device_ip_from_line(char *line) {
}
char *
sc_adb_parse_device_ip(char *str) {
sc_adb_parse_device_ip_from_output(char *str) {
size_t idx_line = 0;
while (str[idx_line] != '\0') {
char *line = &str[idx_line];

View File

@ -25,6 +25,6 @@ sc_adb_parse_devices(char *str, struct sc_vec_adb_devices *out_vec);
* Warning: this function modifies the buffer for optimization purposes.
*/
char *
sc_adb_parse_device_ip(char *str);
sc_adb_parse_device_ip_from_output(char *str);
#endif

View File

@ -98,7 +98,7 @@ sc_clock_update(struct sc_clock *clock, sc_tick system, sc_tick stream) {
sc_clock_estimate(clock, &clock->slope, &clock->offset);
#ifndef SC_CLOCK_NDEBUG
LOGD("Clock estimation: %f * pts + %" PRItick,
LOGD("Clock estimation: %g * pts + %" PRItick,
clock->slope, clock->offset);
#endif
}

View File

@ -170,7 +170,7 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
if (id == POINTER_ID_MOUSE || id == POINTER_ID_VIRTUAL_FINGER) {
// string pointer id
LOG_CMSG("touch [id=%s] %-4s position=%" PRIi32 ",%" PRIi32
" pressure=%f buttons=%06lx",
" pressure=%g buttons=%06lx",
id == POINTER_ID_MOUSE ? "mouse" : "vfinger",
MOTIONEVENT_ACTION_LABEL(action),
msg->inject_touch_event.position.point.x,
@ -180,7 +180,7 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
} else {
// numeric pointer id
LOG_CMSG("touch [id=%" PRIu64_ "] %-4s position=%" PRIi32 ",%"
PRIi32 " pressure=%f buttons=%06lx",
PRIi32 " pressure=%g buttons=%06lx",
id,
MOTIONEVENT_ACTION_LABEL(action),
msg->inject_touch_event.position.point.x,

View File

@ -37,8 +37,8 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
// CK...... ........ ........ ........ ........ ........ ........ ........
// ^^<------------------------------------------------------------------->
// || PTS
// | `- key frame
// `-- config packet
// | `- config packet
// `-- key frame
uint8_t header[SC_PACKET_HEADER_SIZE];
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);

51
app/src/stream.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef STREAM_H
#define STREAM_H
#include "common.h"
#include <stdbool.h>
#include <stdint.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include "trait/packet_sink.h"
#include "util/net.h"
#include "util/thread.h"
#define STREAM_MAX_SINKS 2
struct stream {
sc_socket socket;
sc_thread thread;
struct sc_packet_sink *sinks[STREAM_MAX_SINKS];
unsigned sink_count;
AVCodecContext *codec_ctx;
AVCodecParserContext *parser;
// successive packets may need to be concatenated, until a non-config
// packet is available
AVPacket *pending;
const struct stream_callbacks *cbs;
void *cbs_userdata;
};
struct stream_callbacks {
void (*on_eos)(struct stream *stream, void *userdata);
};
void
stream_init(struct stream *stream, sc_socket socket,
const struct stream_callbacks *cbs, void *cbs_userdata);
void
stream_add_sink(struct stream *stream, struct sc_packet_sink *sink);
bool
stream_start(struct stream *stream);
void
stream_join(struct stream *stream);
#endif

View File

@ -23,11 +23,6 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) {
// When non-negative, 'result' contains the number of bytes written
char *s = malloc(result + 1);
if (!s) {
LOG_OOM();
return NULL;
}
memcpy(s, buffer, result);
s[result] = '\0';
return s;

View File

@ -3,10 +3,11 @@
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <SDL2/SDL_platform.h>
#include "log.h"
#ifdef _WIN32
#ifdef __WINDOWS__
# include <ws2tcpip.h>
typedef int socklen_t;
typedef SOCKET sc_raw_socket;
@ -28,7 +29,7 @@
bool
net_init(void) {
#ifdef _WIN32
#ifdef __WINDOWS__
WSADATA wsa;
int res = WSAStartup(MAKEWORD(2, 2), &wsa) < 0;
if (res < 0) {
@ -41,14 +42,14 @@ net_init(void) {
void
net_cleanup(void) {
#ifdef _WIN32
#ifdef __WINDOWS__
WSACleanup();
#endif
}
static inline sc_socket
wrap(sc_raw_socket sock) {
#ifdef _WIN32
#ifdef __WINDOWS__
if (sock == INVALID_SOCKET) {
return SC_SOCKET_NONE;
}
@ -71,7 +72,7 @@ wrap(sc_raw_socket sock) {
static inline sc_raw_socket
unwrap(sc_socket socket) {
#ifdef _WIN32
#ifdef __WINDOWS__
if (socket == SC_SOCKET_NONE) {
return INVALID_SOCKET;
}
@ -159,8 +160,8 @@ net_connect(sc_socket socket, uint32_t addr, uint16_t port) {
}
bool
net_listen(sc_socket server_socket, uint32_t addr, uint16_t port, int backlog) {
sc_raw_socket raw_sock = unwrap(server_socket);
net_listen(sc_socket socket, uint32_t addr, uint16_t port, int backlog) {
sc_raw_socket raw_sock = unwrap(socket);
int reuse = 1;
if (setsockopt(raw_sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse,
@ -247,7 +248,7 @@ net_interrupt(sc_socket socket) {
sc_raw_socket raw_sock = unwrap(socket);
#ifdef _WIN32
#ifdef __WINDOWS__
if (!atomic_flag_test_and_set(&socket->closed)) {
return !closesocket(raw_sock);
}
@ -261,7 +262,7 @@ bool
net_close(sc_socket socket) {
sc_raw_socket raw_sock = unwrap(socket);
#ifdef _WIN32
#ifdef __WINDOWS__
bool ret = true;
if (!atomic_flag_test_and_set(&socket->closed)) {
ret = !closesocket(raw_sock);

View File

@ -5,8 +5,9 @@
#include <stdbool.h>
#include <stdint.h>
#include <SDL2/SDL_platform.h>
#ifdef _WIN32
#ifdef __WINDOWS__
# include <winsock2.h>
# include <stdatomic.h>
@ -16,7 +17,7 @@
atomic_flag closed;
} *sc_socket;
#else // not _WIN32
#else // not __WINDOWS__
# include <sys/socket.h>
# define SC_SOCKET_NONE -1
@ -39,7 +40,7 @@ bool
net_connect(sc_socket socket, uint32_t addr, uint16_t port);
bool
net_listen(sc_socket server_socket, uint32_t addr, uint16_t port, int backlog);
net_listen(sc_socket socket, uint32_t addr, uint16_t port, int backlog);
sc_socket
net_accept(sc_socket server_socket);

View File

@ -15,14 +15,14 @@ net_connect_intr(struct sc_intr *intr, sc_socket socket, uint32_t addr,
}
bool
net_listen_intr(struct sc_intr *intr, sc_socket server_socket, uint32_t addr,
net_listen_intr(struct sc_intr *intr, sc_socket socket, uint32_t addr,
uint16_t port, int backlog) {
if (!sc_intr_set_socket(intr, server_socket)) {
if (!sc_intr_set_socket(intr, socket)) {
// Already interrupted
return false;
}
bool ret = net_listen(server_socket, addr, port, backlog);
bool ret = net_listen(socket, addr, port, backlog);
sc_intr_set_socket(intr, SC_SOCKET_NONE);
return ret;

View File

@ -11,7 +11,7 @@ net_connect_intr(struct sc_intr *intr, sc_socket socket, uint32_t addr,
uint16_t port);
bool
net_listen_intr(struct sc_intr *intr, sc_socket server_socket, uint32_t addr,
net_listen_intr(struct sc_intr *intr, sc_socket socket, uint32_t addr,
uint16_t port, int backlog);
sc_socket

View File

@ -5,7 +5,7 @@
#include "adb/adb_device.h"
#include "adb/adb_parser.h"
static void test_adb_devices(void) {
static void test_adb_devices() {
char output[] =
"List of devices attached\n"
"0123456789abcdef device usb:2-1 product:MyProduct model:MyModel "
@ -31,7 +31,7 @@ static void test_adb_devices(void) {
sc_adb_devices_destroy(&vec);
}
static void test_adb_devices_cr(void) {
static void test_adb_devices_cr() {
char output[] =
"List of devices attached\r\n"
"0123456789abcdef device usb:2-1 product:MyProduct model:MyModel "
@ -57,7 +57,7 @@ static void test_adb_devices_cr(void) {
sc_adb_devices_destroy(&vec);
}
static void test_adb_devices_daemon_start(void) {
static void test_adb_devices_daemon_start() {
char output[] =
"* daemon not running; starting now at tcp:5037\n"
"* daemon started successfully\n"
@ -78,7 +78,7 @@ static void test_adb_devices_daemon_start(void) {
sc_adb_devices_destroy(&vec);
}
static void test_adb_devices_daemon_start_mixed(void) {
static void test_adb_devices_daemon_start_mixed() {
char output[] =
"List of devices attached\n"
"adb server version (41) doesn't match this client (39); killing...\n"
@ -105,7 +105,7 @@ static void test_adb_devices_daemon_start_mixed(void) {
sc_adb_devices_destroy(&vec);
}
static void test_adb_devices_without_eol(void) {
static void test_adb_devices_without_eol() {
char output[] =
"List of devices attached\n"
"0123456789abcdef device usb:2-1 product:MyProduct model:MyModel "
@ -124,7 +124,7 @@ static void test_adb_devices_without_eol(void) {
sc_adb_devices_destroy(&vec);
}
static void test_adb_devices_without_header(void) {
static void test_adb_devices_without_header() {
char output[] =
"0123456789abcdef device usb:2-1 product:MyProduct model:MyModel "
"device:MyDevice transport_id:1\n";
@ -134,7 +134,7 @@ static void test_adb_devices_without_header(void) {
assert(!ok);
}
static void test_adb_devices_corrupted(void) {
static void test_adb_devices_corrupted() {
char output[] =
"List of devices attached\n"
"corrupted_garbage\n";
@ -145,7 +145,7 @@ static void test_adb_devices_corrupted(void) {
assert(vec.size == 0);
}
static void test_adb_devices_spaces(void) {
static void test_adb_devices_spaces() {
char output[] =
"List of devices attached\n"
"0123456789abcdef unauthorized usb:1-4 transport_id:3\n";
@ -163,81 +163,81 @@ static void test_adb_devices_spaces(void) {
sc_adb_devices_destroy(&vec);
}
static void test_get_ip_single_line(void) {
static void test_get_ip_single_line() {
char ip_route[] = "192.168.1.0/24 dev wlan0 proto kernel scope link src "
"192.168.12.34\r\r\n";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(ip);
assert(!strcmp(ip, "192.168.12.34"));
free(ip);
}
static void test_get_ip_single_line_without_eol(void) {
static void test_get_ip_single_line_without_eol() {
char ip_route[] = "192.168.1.0/24 dev wlan0 proto kernel scope link src "
"192.168.12.34";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(ip);
assert(!strcmp(ip, "192.168.12.34"));
free(ip);
}
static void test_get_ip_single_line_with_trailing_space(void) {
static void test_get_ip_single_line_with_trailing_space() {
char ip_route[] = "192.168.1.0/24 dev wlan0 proto kernel scope link src "
"192.168.12.34 \n";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(ip);
assert(!strcmp(ip, "192.168.12.34"));
free(ip);
}
static void test_get_ip_multiline_first_ok(void) {
static void test_get_ip_multiline_first_ok() {
char ip_route[] = "192.168.1.0/24 dev wlan0 proto kernel scope link src "
"192.168.1.2\r\n"
"10.0.0.0/24 dev rmnet proto kernel scope link src "
"10.0.0.2\r\n";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(ip);
assert(!strcmp(ip, "192.168.1.2"));
free(ip);
}
static void test_get_ip_multiline_second_ok(void) {
static void test_get_ip_multiline_second_ok() {
char ip_route[] = "10.0.0.0/24 dev rmnet proto kernel scope link src "
"10.0.0.3\r\n"
"192.168.1.0/24 dev wlan0 proto kernel scope link src "
"192.168.1.3\r\n";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(ip);
assert(!strcmp(ip, "192.168.1.3"));
free(ip);
}
static void test_get_ip_no_wlan(void) {
static void test_get_ip_no_wlan() {
char ip_route[] = "192.168.1.0/24 dev rmnet proto kernel scope link src "
"192.168.12.34\r\r\n";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(!ip);
}
static void test_get_ip_no_wlan_without_eol(void) {
static void test_get_ip_no_wlan_without_eol() {
char ip_route[] = "192.168.1.0/24 dev rmnet proto kernel scope link src "
"192.168.12.34";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(!ip);
}
static void test_get_ip_truncated(void) {
static void test_get_ip_truncated() {
char ip_route[] = "192.168.1.0/24 dev rmnet proto kernel scope link src "
"\n";
char *ip = sc_adb_parse_device_ip(ip_route);
char *ip = sc_adb_parse_device_ip_from_output(ip_route);
assert(!ip);
}
@ -262,6 +262,4 @@ int main(int argc, char *argv[]) {
test_get_ip_no_wlan();
test_get_ip_no_wlan_without_eol();
test_get_ip_truncated();
return 0;
}

View File

@ -19,6 +19,7 @@ android {
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13.1'
}

View File

@ -13,8 +13,8 @@ if prebuilt_server == ''
install_dir: 'share/scrcpy')
else
if not prebuilt_server.startswith('/')
# prebuilt server path is relative to the root scrcpy directory
prebuilt_server = '../' + prebuilt_server
# relative path needs some trick
prebuilt_server = meson.source_root() + '/' + prebuilt_server
endif
custom_target('scrcpy-server-prebuilt',
input: prebuilt_server,

View File

@ -3,10 +3,12 @@ package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.DisplayInfo;
import com.genymobile.scrcpy.Size;
public final class DisplayManager {
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
import android.os.IInterface;
public DisplayManager(Object manager) {
public final class DisplayManager {
private final IInterface manager;
public DisplayManager(IInterface manager) {
this.manager = manager;
}

View File

@ -50,14 +50,7 @@ public final class ServiceManager {
public DisplayManager getDisplayManager() {
if (displayManager == null) {
try {
Class<?> clazz = Class.forName("android.hardware.display.DisplayManagerGlobal");
Method getInstanceMethod = clazz.getDeclaredMethod("getInstance");
Object dmg = getInstanceMethod.invoke(null);
displayManager = new DisplayManager(dmg);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new AssertionError(e);
}
displayManager = new DisplayManager(getService("display", "android.hardware.display.IDisplayManager"));
}
return displayManager;
}