Compare commits

...

18 Commits

Author SHA1 Message Date
Romain Vimont
3582592d2c Split workarounds to fix audio on some devices
There were several workarounds applied in a single method. Some of them
are specific to Meizu phones, but cause issues on other devices.

Split the method to be able to only fill the app context for audio
capture without applying the Meizu workarounds.

Fixes #3801 <https://github.com/Genymobile/scrcpy/issues/3801>
2023-03-14 22:54:27 +01:00
Romain Vimont
337d6c2fd3 Fail on empty AudioRecord read()
If read() returns 0, then there is no data. According to the
documentation, it happens if the buffer is not a direct buffer:
<https://developer.android.com/reference/android/media/AudioRecord#read(java.nio.ByteBuffer,%20int)>

Refs #3812 <https://github.com/Genymobile/scrcpy/issues/3812>
2023-03-14 19:27:11 +01:00
Romain Vimont
2eced46a37 Update broken link in documentation
The Android documentation has been updated.
2023-03-14 19:21:43 +01:00
Romain Vimont
1a80333747 Replace link to enable USB debugging in README
Link to a more relevant page in the official documentation to enable USB
debugging.
2023-03-13 10:19:22 +01:00
Romain Vimont
fb61b779a6 Add references to prerequisites
Users sometimes only read the OS-specific instructions, they must be
aware of the prerequisites.
2023-03-13 08:43:54 +01:00
Romain Vimont
5899af6a2f Add blogpost link about scrcpy 2.0 2023-03-12 21:08:51 +01:00
Romain Vimont
cbca79b95b Fix v4l2 sink
The codec id to write as codec parameters is the one from the v4l2
encoder, not from the decoder.

Regression introduced by be985b8242.

Fixes #3795 <https://github.com/Genymobile/scrcpy/issues/3795>
2023-03-12 12:45:49 +01:00
Romain Vimont
02586cf21f Fix build issue on FFmpeg < 5.1
An include was missing.

Fixes #3783 <https://github.com/Genymobile/scrcpy/issues/3783>
2023-03-12 08:54:42 +01:00
Romain Vimont
80a6fa7a01 Fix comparison warning
An int was compared with an unsigned:

    ../app/src/audio_player.c:290:27: warning: comparison of integers of
    different signs: 'int' and 'unsigned int' [-Wsign-compare]
                if (abs(diff) < ap->sample_rate / 1000) {
                    ~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~
2023-03-12 08:37:08 +01:00
Ruoyu Zhong
6b769675fa Fix an "expected expression" error
In C, a label can only be followed by a statement, not a declaration.
An error in `app/src/screen.c` violated this, and led to a build error
with an error message similar to the one below:

    ../app/src/screen.c:821:13: error: expected expression
                bool ok = sc_screen_init_size(screen);
                ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include/stdbool.h:15:14: note: expanded from macro 'bool'
    #define bool _Bool
                 ^
    ../app/src/screen.c:822:18: error: use of undeclared identifier 'ok'
                if (!ok) {
                     ^
    2 errors generated.

This could be fixed by introducing a new block (or compound statement;
as is already being done in the next `case`). That is a statement.

Fixes #3785 <https://github.com/Genymobile/scrcpy/issues/3785>
PR #3787 <https://github.com/Genymobile/scrcpy/pull/3787>

Signed-off-by: Ruoyu Zhong <zhongruoyu@outlook.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-03-12 08:26:17 +01:00
Romain Vimont
e5aa2ce01f Fix broken link in Windows download page 2023-03-12 02:59:44 +01:00
Romain Vimont
cbc638c6ba Fix broken link in shortcuts documentation 2023-03-12 02:50:10 +01:00
Romain Vimont
abc1be4872 Update links to v2.0 2023-03-12 02:49:28 +01:00
Romain Vimont
f1b2d6bbbb Bump version to 2.0 2023-03-12 02:05:37 +01:00
Romain Vimont
90926d40ad Merge branch 'master' into dev 2023-03-12 02:05:24 +01:00
Kartik Kushwaha
b4caa483dd Add Fedora instructions in README
Add the command to install the scrcpy package for Fedora directly.

PR #3715 <https://github.com/Genymobile/scrcpy/pull/3715>

Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-02-06 11:13:18 +01:00
Romain Vimont
87da137238 Remove "on Linux" in FAQ
HID now works on all platforms.
2023-01-18 14:37:55 +01:00
Romain Vimont
b3f626feee Add FAQ section about HID/OTG on Windows
Refs #3654 <https://github.com/Genymobile/scrcpy/issues/3654>
2023-01-03 08:48:46 +01:00
21 changed files with 90 additions and 40 deletions

20
FAQ.md
View File

@@ -7,7 +7,7 @@ Here are the common reported problems and their status.
If you encounter any error, the first step is to upgrade to the latest version.
## `adb` issues
## `adb` and USB issues
`scrcpy` execute `adb` commands to initialize the connection with the device. If
`adb` fails, then scrcpy will not work.
@@ -133,6 +133,21 @@ Try with another USB cable or plug it into another USB port. See [#281] and
[#283]: https://github.com/Genymobile/scrcpy/issues/283
## HID/OTG issues on Windows
On Windows, if `scrcpy --otg` (or `--hid-keyboard`/`--hid-mouse`) results in:
> ERROR: Could not find any USB device
(or if only unrelated USB devices are detected), there might be drivers issues.
Please read [#3654], in particular [this comment][#3654-comment1] and [the next
one][#3654-comment2].
[#3654]: https://github.com/Genymobile/scrcpy/issues/3654
[#3654-comment1]: https://github.com/Genymobile/scrcpy/issues/3654#issuecomment-1369278232
[#3654-comment2]: https://github.com/Genymobile/scrcpy/issues/3654#issuecomment-1369295011
## Control issues
@@ -153,8 +168,7 @@ The default text injection method is [limited to ASCII characters][text-input].
A trick allows to also inject some [accented characters][accented-characters],
but that's all. See [#37].
Since scrcpy v1.20 on Linux, it is possible to simulate a [physical
keyboard][hid] (HID).
Since scrcpy v1.20, it is possible to simulate a [physical keyboard][hid] (HID).
[text-input]: https://github.com/Genymobile/scrcpy/issues?q=is%3Aopen+is%3Aissue+label%3Aunicode
[accented-characters]: https://blog.rom1v.com/2018/03/introducing-scrcpy/#handle-accented-characters

View File

@@ -1,4 +1,4 @@
# scrcpy (v1.25)
# scrcpy (v2.0)
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />
@@ -35,15 +35,15 @@ Its features include:
- [OTG mode](doc/hid-otg.md#otg)
- and more…
## Requirements
## Prerequisites
The Android device requires at least API 21 (Android 5.0).
[Audio forwarding](doc/audio.md) is supported from API 30 (Android 11).
Make sure you [enabled adb debugging][enable-adb] on your device(s).
Make sure you [enabled USB debugging][enable-adb] on your device(s).
[enable-adb]: https://developer.android.com/studio/command-line/adb.html#Enabling
[enable-adb]: https://developer.android.com/studio/debug/dev-options#enable
On some devices, you also need to enable [an additional option][control] `USB
debugging (Security Settings)` (this is an item different from `USB debugging`)
@@ -90,10 +90,11 @@ documented in the following pages:
- [Introducing scrcpy][article-intro]
- [Scrcpy now works wirelessly][article-tcpip]
- [Scrcpy 2.0, with audio][article-scrcpy2]
[article-intro]: https://blog.rom1v.com/2018/03/introducing-scrcpy/
[article-tcpip]: https://www.genymotion.com/blog/open-source-project-scrcpy-now-works-wirelessly/
[article-scrcpy2]: https://blog.rom1v.com/2023/03/scrcpy-2-0-with-audio/
## Contact

View File

@@ -13,7 +13,7 @@ BEGIN
VALUE "LegalCopyright", "Romain Vimont, Genymobile"
VALUE "OriginalFilename", "scrcpy.exe"
VALUE "ProductName", "scrcpy"
VALUE "ProductVersion", "1.25"
VALUE "ProductVersion", "2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -287,7 +287,7 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink,
float avg = sc_average_get(&ap->avg_buffering);
int diff = ap->target_buffering - avg;
if (abs(diff) < ap->sample_rate / 1000) {
if (abs(diff) < (int) ap->sample_rate / 1000) {
// Do not compensate for less than 1ms, the error is just noise
diff = 0;
} else if (diff < 0 && buffered_samples < ap->target_buffering) {

View File

@@ -1,6 +1,7 @@
#include "demuxer.h"
#include <assert.h>
#include <libavutil/channel_layout.h>
#include <libavutil/time.h>
#include <unistd.h>

View File

@@ -816,7 +816,7 @@ sc_screen_handle_event(struct sc_screen *screen, SDL_Event *event) {
bool relative_mode = sc_screen_is_relative_mode(screen);
switch (event->type) {
case SC_EVENT_SCREEN_INIT_SIZE:
case SC_EVENT_SCREEN_INIT_SIZE: {
// The initial size is passed via screen->frame_size
bool ok = sc_screen_init_size(screen);
if (!ok) {
@@ -824,6 +824,7 @@ sc_screen_handle_event(struct sc_screen *screen, SDL_Event *event) {
return false;
}
return true;
}
case SC_EVENT_NEW_FRAME: {
bool ok = sc_screen_update_frame(screen);
if (!ok) {

View File

@@ -210,6 +210,9 @@ sc_v4l2_sink_open(struct sc_v4l2_sink *vs, const AVCodecContext *ctx) {
goto error_avformat_free_context;
}
// The codec is from the v4l2 encoder, not from the decoder
ostream->codecpar->codec_id = encoder->id;
int ret = avio_open(&vs->format_ctx->pb, vs->device_name, AVIO_FLAG_WRITE);
if (ret < 0) {
LOGE("Failed to open output device: %s", vs->device_name);

View File

@@ -233,10 +233,10 @@ install` must be run as root)._
#### Option 2: Use prebuilt server
- [`scrcpy-server-v1.25`][direct-scrcpy-server]
<sub>SHA-256: `ce0306c7bbd06ae72f6d06f7ec0ee33774995a65de71e0a83813ecb67aec9bdb`</sub>
- [`scrcpy-server-v2.0`][direct-scrcpy-server]
<sub>SHA-256: `9e241615f578cd690bb43311000debdecf6a9c50a7082b001952f18f6f21ddc2`</sub>
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.25/scrcpy-server-v1.25
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v2.0/scrcpy-server-v2.0
Download the prebuilt server somewhere, and specify its path during the Meson
configuration:

View File

@@ -107,10 +107,10 @@ with the device IP address you found)_.
7. Run `scrcpy` as usual.
8. Run `adb disconnect` once you're done.
Since Android 11, a [Wireless debugging option][adb-wireless] allows to bypass
Since Android 11, a [wireless debugging option][adb-wireless] allows to bypass
having to physically connect your device directly to your computer.
[adb-wireless]: https://developer.android.com/studio/command-line/adb#connect-to-a-device-over-wi-fi-android-11+
[adb-wireless]: https://developer.android.com/studio/command-line/adb#wireless-android11-command-line
## Autostart

View File

@@ -61,6 +61,8 @@ _See [build.md](build.md) to build and install the app manually._
## Run
_Make sure that your device meets the [prerequisites](/README.md#prerequisites)._
Once installed, run from a terminal:
```bash

View File

@@ -29,6 +29,8 @@ _See [build.md](build.md) to build and install the app manually._
## Run
_Make sure that your device meets the [prerequisites](/README.md#prerequisites)._
Once installed, run from a terminal:
```bash

View File

@@ -49,7 +49,7 @@ _<kbd>[Super]</kbd> is typically the <kbd>Windows</kbd> or <kbd>Cmd</kbd> key._
| Enable/disable FPS counter (on stdout) | <kbd>MOD</kbd>+<kbd>i</kbd>
| Pinch-to-zoom | <kbd>Ctrl</kbd>+_click-and-move_
| Drag & drop APK file | Install APK from computer
| Drag & drop non-APK file | [Push file to device](#push-file-to-device)
| Drag & drop non-APK file | [Push file to device](control.md#push-file-to-device)
_¹Double-click on black borders to remove them._
_²Right-click turns the screen on if it was off, presses BACK otherwise._

View File

@@ -4,11 +4,14 @@
Download the [latest release]:
- [`scrcpy-win64-v1.25.zip`][direct-win64]
<sub>SHA-256: `db65125e9c65acd00359efb7cea9c05f63cc7ccd5833000cd243cc92f5053028`</sub>
- [`scrcpy-win64-v2.0.zip`][direct-win64] (64-bit)
<sub>SHA-256: `ae4c8d37a496b43f8974ba8f07f708e22a9570ba0cddc3dc3a36edbccd4d2a20`</sub>
- [`scrcpy-win32-v2.0.zip`][direct-win32] (32-bit)
<sub>SHA-256: `15d98c02cb0e0bbd84f8b5d54991e0f6925569b1286a86a40743944fcb1c2d8c`</sub>
[release]: https://github.com/Genymobile/scrcpy/releases/latest
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.25/scrcpy-win64-v1.25.zip
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v2.0/scrcpy-win64-v2.0.zip
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v2.0/scrcpy-win32-v2.0.zip
and extract it.
@@ -35,6 +38,8 @@ _See [build.md](build.md) to build and install the app manually._
## Run
_Make sure that your device meets the [prerequisites](/README.md#prerequisites)._
Scrcpy is a command line application: it is mainly intended to be executed from
a terminal with command line arguments.

View File

@@ -2,8 +2,8 @@
set -e
BUILDDIR=build-auto
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v1.25/scrcpy-server-v1.25
PREBUILT_SERVER_SHA256=ce0306c7bbd06ae72f6d06f7ec0ee33774995a65de71e0a83813ecb67aec9bdb
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v2.0/scrcpy-server-v2.0
PREBUILT_SERVER_SHA256=9e241615f578cd690bb43311000debdecf6a9c50a7082b001952f18f6f21ddc2
echo "[scrcpy] Downloading prebuilt server..."
wget "$PREBUILT_SERVER_URL" -O scrcpy-server

View File

@@ -1,5 +1,5 @@
project('scrcpy', 'c',
version: '1.25',
version: '2.0',
meson_version: '>= 0.48',
default_options: [
'c_std=c11',

View File

@@ -7,8 +7,8 @@ android {
applicationId "com.genymobile.scrcpy"
minSdkVersion 21
targetSdkVersion 33
versionCode 12500
versionName "1.25"
versionCode 20000
versionName "2.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {

View File

@@ -12,7 +12,7 @@
set -e
SCRCPY_DEBUG=false
SCRCPY_VERSION_NAME=1.25
SCRCPY_VERSION_NAME=2.0
PLATFORM=${ANDROID_PLATFORM:-33}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-33.0.0}

View File

@@ -111,7 +111,7 @@ public final class AudioCapture {
@TargetApi(Build.VERSION_CODES.N)
public int read(ByteBuffer directBuffer, int size, MediaCodec.BufferInfo outBufferInfo) {
int r = recorder.read(directBuffer, size);
if (r < 0) {
if (r <= 0) {
return r;
}

View File

@@ -92,7 +92,7 @@ public final class AudioEncoder implements AsyncProcessor {
InputTask task = inputTasks.take();
ByteBuffer buffer = mediaCodec.getInputBuffer(task.index);
int r = capture.read(buffer, READ_SIZE, bufferInfo);
if (r < 0) {
if (r <= 0) {
throw new IOException("Could not read audio: " + r);
}

View File

@@ -81,15 +81,15 @@ public final class Server {
// But only apply when strictly necessary, since workarounds can cause other issues:
// - <https://github.com/Genymobile/scrcpy/issues/940>
// - <https://github.com/Genymobile/scrcpy/issues/994>
boolean mustFillAppInfo = Build.BRAND.equalsIgnoreCase("meizu");
if (Build.BRAND.equalsIgnoreCase("meizu")) {
Workarounds.fillAppInfo();
}
// Before Android 11, audio is not supported.
// Since Android 12, we can properly set a context on the AudioRecord.
// Only on Android 11 we must fill app info for the AudioRecord to work.
mustFillAppInfo |= audio && Build.VERSION.SDK_INT == Build.VERSION_CODES.R;
if (mustFillAppInfo) {
Workarounds.fillAppInfo();
// Only on Android 11 we must fill the application context for the AudioRecord to work.
if (audio && Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
Workarounds.fillAppContext();
}
List<AsyncProcessor> asyncProcessors = new ArrayList<>();

View File

@@ -10,6 +10,10 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public final class Workarounds {
private static Class<?> activityThreadClass;
private static Object activityThread;
private Workarounds() {
// not instantiable
}
@@ -28,18 +32,25 @@ public final class Workarounds {
}
@SuppressLint("PrivateApi,DiscouragedPrivateApi")
public static void fillAppInfo() {
try {
private static void fillActivityThread() throws Exception {
if (activityThread == null) {
// ActivityThread activityThread = new ActivityThread();
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
activityThreadClass = Class.forName("android.app.ActivityThread");
Constructor<?> activityThreadConstructor = activityThreadClass.getDeclaredConstructor();
activityThreadConstructor.setAccessible(true);
Object activityThread = activityThreadConstructor.newInstance();
activityThread = activityThreadConstructor.newInstance();
// ActivityThread.sCurrentActivityThread = activityThread;
Field sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
sCurrentActivityThreadField.setAccessible(true);
sCurrentActivityThreadField.set(null, activityThread);
}
}
@SuppressLint("PrivateApi,DiscouragedPrivateApi")
public static void fillAppInfo() {
try {
fillActivityThread();
// ActivityThread.AppBindData appBindData = new ActivityThread.AppBindData();
Class<?> appBindDataClass = Class.forName("android.app.ActivityThread$AppBindData");
@@ -59,6 +70,16 @@ public final class Workarounds {
Field mBoundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication");
mBoundApplicationField.setAccessible(true);
mBoundApplicationField.set(activityThread, appBindData);
} catch (Throwable throwable) {
// this is a workaround, so failing is not an error
Ln.d("Could not fill app info: " + throwable.getMessage());
}
}
@SuppressLint("PrivateApi,DiscouragedPrivateApi")
public static void fillAppContext() {
try {
fillActivityThread();
Application app = Application.class.newInstance();
Field baseField = ContextWrapper.class.getDeclaredField("mBase");
@@ -71,7 +92,7 @@ public final class Workarounds {
mInitialApplicationField.set(activityThread, app);
} catch (Throwable throwable) {
// this is a workaround, so failing is not an error
Ln.d("Could not fill app info: " + throwable.getMessage());
Ln.d("Could not fill app context: " + throwable.getMessage());
}
}
}