Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6eabe5a8bc | ||
|
|
9988d6186e | ||
|
|
451f3ed309 | ||
|
|
5142e0e621 | ||
|
|
e9bacc196a |
75
DEVELOP.md
75
DEVELOP.md
@@ -32,7 +32,7 @@ The server is a Java application (with a [`public static void main(String...
|
||||
args)`][main] method), compiled against the Android framework, and executed as
|
||||
`shell` on the Android device.
|
||||
|
||||
[main]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/Server.java#L123
|
||||
[main]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/Server.java#L100
|
||||
|
||||
To run such a Java application, the classes must be [_dexed_][dex] (typically,
|
||||
to `classes.dex`). If `my.package.MainClass` is the main class, compiled to
|
||||
@@ -65,18 +65,18 @@ They can be called using reflection though. The communication with hidden
|
||||
components is provided by [_wrappers_ classes][wrappers] and [aidl].
|
||||
|
||||
[hidden]: https://stackoverflow.com/a/31908373/1987178
|
||||
[wrappers]: https://github.com/Genymobile/scrcpy/tree/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/wrappers
|
||||
[aidl]: https://github.com/Genymobile/scrcpy/tree/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/aidl/android/view
|
||||
[wrappers]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/wrappers
|
||||
[aidl]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/aidl/android/view
|
||||
|
||||
|
||||
### Threading
|
||||
|
||||
The server uses 3 threads:
|
||||
The server uses 2 threads:
|
||||
|
||||
- the **main** thread, encoding and streaming the video to the client;
|
||||
- the **controller** thread, listening for _control messages_ (typically,
|
||||
keyboard and mouse events) from the client;
|
||||
- the **receiver** thread (managed by the controller), sending _device messges_
|
||||
- the **controller** thread, listening for _control events_ (typically,
|
||||
keyboard and mouse events) from the client.
|
||||
- the **receiver** thread (managed by the controller), sending _device events_
|
||||
to the clients (currently, it is only used to send the device clipboard
|
||||
content).
|
||||
|
||||
@@ -92,9 +92,9 @@ The video is encoded using the [`MediaCodec`] API. The codec takes its input
|
||||
from a [surface] associated to the display, and writes the resulting H.264
|
||||
stream to the provided output stream (the socket connected to the client).
|
||||
|
||||
[`ScreenEncoder`]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java
|
||||
[`ScreenEncoder`]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java
|
||||
[`MediaCodec`]: https://developer.android.com/reference/android/media/MediaCodec.html
|
||||
[surface]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java#L68-L69
|
||||
[surface]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java#L69-L70
|
||||
|
||||
On device [rotation], the codec, surface and display are reinitialized, and a
|
||||
new video stream is produced.
|
||||
@@ -108,30 +108,31 @@ because it avoids to send unnecessary frames, but there are drawbacks:
|
||||
Both problems are [solved][repeat] by the flag
|
||||
[`KEY_REPEAT_PREVIOUS_FRAME_AFTER`][repeat-flag].
|
||||
|
||||
[rotation]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java#L90
|
||||
[repeat]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java#L147-L148
|
||||
[rotation]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java#L90
|
||||
[repeat]:
|
||||
https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java#L147-L148
|
||||
[repeat-flag]: https://developer.android.com/reference/android/media/MediaFormat.html#KEY_REPEAT_PREVIOUS_FRAME_AFTER
|
||||
|
||||
|
||||
### Input events injection
|
||||
|
||||
_Control messages_ are received from the client by the [`Controller`] (run in a
|
||||
separate thread). There are several types of input events:
|
||||
_Control events_ are received from the client by the [`EventController`] (run in
|
||||
a separate thread). There are several types of input events:
|
||||
- keycode (cf [`KeyEvent`]),
|
||||
- text (special characters may not be handled by keycodes directly),
|
||||
- mouse motion/click,
|
||||
- mouse scroll,
|
||||
- other commands (e.g. to switch the screen on or to copy the clipboard).
|
||||
|
||||
Some of them need to inject input events to the system. To do so, they use the
|
||||
_hidden_ method [`InputManager.injectInputEvent`] (exposed by our
|
||||
All of them may need to inject input events to the system. To do so, they use
|
||||
the _hidden_ method [`InputManager.injectInputEvent`] (exposed by our
|
||||
[`InputManager` wrapper][inject-wrapper]).
|
||||
|
||||
[`Controller`]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/Controller.java#L81
|
||||
[`EventController`]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/EventController.java#L66
|
||||
[`KeyEvent`]: https://developer.android.com/reference/android/view/KeyEvent.html
|
||||
[`MotionEvent`]: https://developer.android.com/reference/android/view/MotionEvent.html
|
||||
[`InputManager.injectInputEvent`]: https://android.googlesource.com/platform/frameworks/base/+/oreo-release/core/java/android/hardware/input/InputManager.java#857
|
||||
[inject-wrapper]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java#L27
|
||||
[inject-wrapper]: https://github.com/Genymobile/scrcpy/blob/v1.8/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java#L27
|
||||
|
||||
|
||||
|
||||
@@ -187,13 +188,12 @@ The client uses 4 threads:
|
||||
- the **main** thread, executing the SDL event loop,
|
||||
- the **stream** thread, receiving the video and used for decoding and
|
||||
recording,
|
||||
- the **controller** thread, sending _control messages_ to the server,
|
||||
- the **controller** thread, sending _control events_ to the server.
|
||||
- the **receiver** thread (managed by the controller), receiving _device
|
||||
messages_ from the client.
|
||||
events_ from the client.
|
||||
|
||||
In addition, another thread can be started if necessary to handle APK
|
||||
installation or file push requests (via drag&drop on the main window) or to
|
||||
print the framerate regularly in the console.
|
||||
installation or file push requests (via drag&drop on the main window).
|
||||
|
||||
|
||||
|
||||
@@ -217,10 +217,10 @@ to decode a new frame while the main thread renders the last one.
|
||||
If a [recorder] is present (i.e. `--record` is enabled), then its muxes the raw
|
||||
H.264 packet to the output video file.
|
||||
|
||||
[stream]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/stream.h
|
||||
[decoder]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/decoder.h
|
||||
[video_buffer]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/video_buffer.h
|
||||
[recorder]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/recorder.h
|
||||
[stream]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/stream.h
|
||||
[decoder]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/decoder.h
|
||||
[video_buffer]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/video_buffer.h
|
||||
[recorder]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/recorder.h
|
||||
|
||||
```
|
||||
+----------+ +----------+
|
||||
@@ -234,19 +234,19 @@ H.264 packet to the output video file.
|
||||
|
||||
### Controller
|
||||
|
||||
The [controller] is responsible to send _control messages_ to the device. It
|
||||
runs in a separate thread, to avoid I/O on the main thread.
|
||||
The [controller] is responsible to send _control events_ to the device. It runs
|
||||
in a separate thread, to avoid I/O on the main thread.
|
||||
|
||||
On SDL event, received on the main thread, the [input manager][inputmanager]
|
||||
creates appropriate [_control messages_][controlmsg]. It is responsible to
|
||||
creates appropriate [_control events_][controlevent]. It is responsible to
|
||||
convert SDL events to Android events (using [convert]). It pushes the _control
|
||||
messages_ to a queue hold by the controller. On its own thread, the controller
|
||||
takes messages from the queue, that it serializes and sends to the client.
|
||||
events_ to a queue hold by the controller. On its own thread, the controller
|
||||
takes events from the queue, that it serializes and sends to the client.
|
||||
|
||||
[controller]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/controller.h
|
||||
[controlmsg]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/control_msg.h
|
||||
[inputmanager]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/input_manager.h
|
||||
[convert]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/convert.h
|
||||
[controller]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/controller.h
|
||||
[controlevent]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/control_event.h
|
||||
[inputmanager]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/input_manager.h
|
||||
[convert]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/convert.h
|
||||
|
||||
|
||||
### UI and event loop
|
||||
@@ -257,9 +257,10 @@ thread.
|
||||
Events are handled in the [event loop], which either updates the [screen] or
|
||||
delegates to the [input manager][inputmanager].
|
||||
|
||||
[scrcpy]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/scrcpy.c
|
||||
[event loop]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/scrcpy.c#L201
|
||||
[screen]: https://github.com/Genymobile/scrcpy/blob/ffe0417228fb78ab45b7ee4e202fc06fc8875bf3/app/src/screen.h
|
||||
[scrcpy]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/scrcpy.c
|
||||
[event loop]:
|
||||
https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/scrcpy.c#L187
|
||||
[screen]: https://github.com/Genymobile/scrcpy/blob/v1.8/app/src/screen.h
|
||||
|
||||
|
||||
## Hack
|
||||
|
||||
4
FAQ.md
4
FAQ.md
@@ -19,6 +19,10 @@ Windows may need some [drivers] to detect your device.
|
||||
|
||||
[drivers]: https://developer.android.com/studio/run/oem-usb.html
|
||||
|
||||
If you still encounter problems, please see [issue 9].
|
||||
|
||||
[issue 9]: https://github.com/Genymobile/scrcpy/issues/9
|
||||
|
||||
|
||||
### Mouse clicks do not work
|
||||
|
||||
|
||||
@@ -100,29 +100,28 @@ dist-win32: build-server build-win32 build-win32-noconsole
|
||||
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp "$(WIN32_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/scrcpy-noconsole.exe"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win32-shared/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/SDL2-2.0.8/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp prebuilt-deps/SDL2-2.0.9/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
|
||||
dist-win64: build-server build-win64 build-win64-noconsole
|
||||
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
|
||||
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp "$(WIN64_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/scrcpy-noconsole.exe"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win64-shared/bin/swresample-3.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1.3-win64-shared/bin/swscale-5.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/swresample-3.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/SDL2-2.0.8/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp prebuilt-deps/SDL2-2.0.9/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
|
||||
zip-win32: dist-win32
|
||||
cd "$(DIST)"; \
|
||||
|
||||
@@ -331,8 +331,8 @@ To use a specific _adb_ binary, configure its path in the environment variable
|
||||
|
||||
ADB=/path/to/adb scrcpy
|
||||
|
||||
To override the path of the `scrcpy-server.jar` file, configure its path in
|
||||
`SCRCPY_SERVER_PATH`.
|
||||
To override the path of the `scrcpy-server.jar` file (it can be [useful] on
|
||||
Windows), configure its path in `SCRCPY_SERVER_PATH`.
|
||||
|
||||
[useful]: https://github.com/Genymobile/scrcpy/issues/278#issuecomment-429330345
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ read_packet_with_meta(void *opaque, uint8_t *buf, int buf_size) {
|
||||
|
||||
ssize_t r = net_recv(stream->socket, buf, buf_size);
|
||||
if (r == -1) {
|
||||
return errno ? AVERROR(errno) : AVERROR_EOF;
|
||||
return AVERROR(errno);
|
||||
}
|
||||
if (r == 0) {
|
||||
return AVERROR_EOF;
|
||||
@@ -130,7 +130,7 @@ read_raw_packet(void *opaque, uint8_t *buf, int buf_size) {
|
||||
struct stream *stream = opaque;
|
||||
ssize_t r = net_recv(stream->socket, buf, buf_size);
|
||||
if (r == -1) {
|
||||
return errno ? AVERROR(errno) : AVERROR_EOF;
|
||||
return AVERROR(errno);
|
||||
}
|
||||
if (r == 0) {
|
||||
return AVERROR_EOF;
|
||||
|
||||
@@ -107,8 +107,6 @@ cmd_simple_wait(pid_t pid, int *exit_code) {
|
||||
|
||||
char *
|
||||
get_executable_path(void) {
|
||||
// <https://stackoverflow.com/a/1024937/1987178>
|
||||
#ifdef __linux__
|
||||
char buf[PATH_MAX + 1]; // +1 for the null byte
|
||||
ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
|
||||
if (len == -1) {
|
||||
@@ -117,10 +115,4 @@ get_executable_path(void) {
|
||||
}
|
||||
buf[len] = '\0';
|
||||
return SDL_strdup(buf);
|
||||
#else
|
||||
// in practice, we only need this feature for portable builds, only used on
|
||||
// Windows, so we don't care implementing it for every platform
|
||||
// (it's useful to have a working version on Linux for debugging though)
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -15,6 +15,6 @@ cpu = 'i686'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
prebuilt_ffmpeg_shared = 'ffmpeg-4.1.3-win32-shared'
|
||||
prebuilt_ffmpeg_dev = 'ffmpeg-4.1.3-win32-dev'
|
||||
prebuilt_sdl2 = 'SDL2-2.0.8/i686-w64-mingw32'
|
||||
prebuilt_ffmpeg_shared = 'ffmpeg-4.1-win32-shared'
|
||||
prebuilt_ffmpeg_dev = 'ffmpeg-4.1-win32-dev'
|
||||
prebuilt_sdl2 = 'SDL2-2.0.9/i686-w64-mingw32'
|
||||
|
||||
@@ -15,6 +15,6 @@ cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
prebuilt_ffmpeg_shared = 'ffmpeg-4.1.3-win64-shared'
|
||||
prebuilt_ffmpeg_dev = 'ffmpeg-4.1.3-win64-dev'
|
||||
prebuilt_sdl2 = 'SDL2-2.0.8/x86_64-w64-mingw32'
|
||||
prebuilt_ffmpeg_shared = 'ffmpeg-4.1-win64-shared'
|
||||
prebuilt_ffmpeg_dev = 'ffmpeg-4.1-win64-dev'
|
||||
prebuilt_sdl2 = 'SDL2-2.0.9/x86_64-w64-mingw32'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
project('scrcpy', 'c',
|
||||
version: '1.9',
|
||||
version: '1.8',
|
||||
meson_version: '>= 0.37',
|
||||
default_options: 'c_std=c11')
|
||||
|
||||
|
||||
@@ -10,31 +10,31 @@ prepare-win32: prepare-sdl2 prepare-ffmpeg-shared-win32 prepare-ffmpeg-dev-win32
|
||||
prepare-win64: prepare-sdl2 prepare-ffmpeg-shared-win64 prepare-ffmpeg-dev-win64 prepare-adb
|
||||
|
||||
prepare-ffmpeg-shared-win32:
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-4.1.3-win32-shared.zip \
|
||||
8ea472d673370d5e87517a75587abfa6f189ee4f82e8da21fdbc49d0db0c1a89 \
|
||||
ffmpeg-4.1.3-win32-shared
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-4.1-win32-shared.zip \
|
||||
e692b18c01745d262c03294b382fd64df68fabe3c66aa4546a3ad3935175cde3 \
|
||||
ffmpeg-4.1-win32-shared
|
||||
|
||||
prepare-ffmpeg-dev-win32:
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-4.1.3-win32-dev.zip \
|
||||
e16d3150b6ccf0b71908f5b964cb8c051d79053c8f5cd6d777d617ab4f03613a \
|
||||
ffmpeg-4.1.3-win32-dev
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-4.1-win32-dev.zip \
|
||||
34bc5e471fb9160609abd6bc271e361050f3ff7376b1b8a0873cca02b38277c8 \
|
||||
ffmpeg-4.1-win32-dev
|
||||
|
||||
prepare-ffmpeg-shared-win64:
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-4.1.3-win64-shared.zip \
|
||||
0b974578e07d974c4bafb36c7ed0b46e46b001d38b149455089c13b57ddefe5d \
|
||||
ffmpeg-4.1.3-win64-shared
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-4.1-win64-shared.zip \
|
||||
c4908c97436c946509dc365e421159274fa4b1e66dce6fb5b63d82a6294d5357 \
|
||||
ffmpeg-4.1-win64-shared
|
||||
|
||||
prepare-ffmpeg-dev-win64:
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.1.3-win64-dev.zip \
|
||||
334b473467db096a5b74242743592a73e120a137232794508e4fc55593696a5b \
|
||||
ffmpeg-4.1.3-win64-dev
|
||||
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.1-win64-dev.zip \
|
||||
761ec79aa3dae66698c9791a2f0bb9da8794246f8356cadc741ddc0eabab0471 \
|
||||
ffmpeg-4.1-win64-dev
|
||||
|
||||
prepare-sdl2:
|
||||
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.8-mingw.tar.gz \
|
||||
ffff7305d634aff5e1df5b7bb935435c3a02c8b03ad94a1a2be9169a558a7961 \
|
||||
SDL2-2.0.8
|
||||
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.9-mingw.tar.gz \
|
||||
0f9f00d0f2a9a95dfb5cce929718210c3f85432cc2e9d4abade4adcb7f6bb39d \
|
||||
SDL2-2.0.9
|
||||
|
||||
prepare-adb:
|
||||
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r29.0.1-windows.zip \
|
||||
2334f92cf571fd2d9bf6ff7c637765bee5d8323e0bd8e051e15927d87b54b4e8 \
|
||||
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r28.0.1-windows.zip \
|
||||
db78f726d5dc653706dcd15a462ab1b946c643f598df76906c4c1858411c54df \
|
||||
platform-tools
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
compileSdkVersion 27
|
||||
defaultConfig {
|
||||
applicationId "com.genymobile.scrcpy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 10
|
||||
versionName "1.9"
|
||||
targetSdkVersion 27
|
||||
versionCode 9
|
||||
versionName "1.8"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.genymobile.scrcpy;
|
||||
|
||||
import org.junit.Assert;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -9,7 +10,7 @@ public class StringUtilsTest {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("checkstyle:MagicNumber")
|
||||
public void testUtf8Truncate() {
|
||||
public void testUtf8Trucate() {
|
||||
String s = "aÉbÔc";
|
||||
byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
|
||||
Assert.assertEquals(7, utf8.length);
|
||||
|
||||
Reference in New Issue
Block a user