Compare commits

...

7 Commits

Author SHA1 Message Date
Romain Vimont
233f8e6cc4 Rename keycode injection method
Make it explicit that it injects both "press" and "release" events.
2021-04-30 23:07:37 +02:00
Romain Vimont
9a7d351d67 Simplify non-static injectEvent() implementation
Just call the static version (having a displayId) from the non-static
version (using the displayId field).
2021-04-30 23:07:37 +02:00
Romain Vimont
d00ee640c0 Simplify Device.java
Remove useless intermediate method with a "mode" parameter (it's always
called with the same mode).

This also avoids the need for a specific injectEventOnDisplay() method,
since it does not conflict with another injectEvent() method anymore.
2021-04-30 23:07:29 +02:00
Romain Vimont
ae6ec7a194 Unref decoder AVFrame immediately
The frame can be unref immediately after it is pushed to the frame
sinks.

It was not really a memory leak because the frame was unref every time
by avcodec_receive_frame() (and freed on close), but a reference was
unnecessarily kept for too long.
2021-04-26 18:05:43 +02:00
Romain Vimont
84f17fdeab Fix v4l2 AVPacket memory leak on error
Unref v4l2 AVPacket even if writing failed.
2021-04-26 18:05:11 +02:00
Romain Vimont
1cde68a1fa Fix v4l2 AVFrame memory leak
Unref frame immediately once encoded.

Fixes #2279 <https://github.com/Genymobile/scrcpy/pull/2279>
2021-04-26 18:04:51 +02:00
Romain Vimont
45e7280148 Rename --v4l2_sink to --v4l2-sink
This was a rebase issue, the previous version in #2268 was correct.

Refs #2268 <https://github.com/Genymobile/scrcpy/pull/2268>
2021-04-26 17:59:35 +02:00
6 changed files with 21 additions and 33 deletions

View File

@@ -186,7 +186,7 @@ Enable "show touches" on start, restore the initial value on exit.
It only shows physical touches (not clicks from scrcpy). It only shows physical touches (not clicks from scrcpy).
.TP .TP
.BI "\-\-v4l2_sink " /dev/videoN .BI "\-\-v4l2-sink " /dev/videoN
Output to v4l2loopback device. Output to v4l2loopback device.
It requires to lock the video orientation (see --lock-video-orientation). It requires to lock the video orientation (see --lock-video-orientation).

View File

@@ -177,7 +177,7 @@ scrcpy_print_usage(const char *arg0) {
" It only shows physical touches (not clicks from scrcpy).\n" " It only shows physical touches (not clicks from scrcpy).\n"
"\n" "\n"
#ifdef HAVE_V4L2 #ifdef HAVE_V4L2
" --v4l2_sink /dev/videoN\n" " --v4l2-sink /dev/videoN\n"
" Output to v4l2loopback device.\n" " Output to v4l2loopback device.\n"
" It requires to lock the video orientation (see\n" " It requires to lock the video orientation (see\n"
" --lock-video-orientation).\n" " --lock-video-orientation).\n"
@@ -726,7 +726,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
{"stay-awake", no_argument, NULL, 'w'}, {"stay-awake", no_argument, NULL, 'w'},
{"turn-screen-off", no_argument, NULL, 'S'}, {"turn-screen-off", no_argument, NULL, 'S'},
#ifdef HAVE_V4L2 #ifdef HAVE_V4L2
{"v4l2_sink", required_argument, NULL, OPT_V4L2_SINK}, {"v4l2-sink", required_argument, NULL, OPT_V4L2_SINK},
#endif #endif
{"verbosity", required_argument, NULL, 'V'}, {"verbosity", required_argument, NULL, 'V'},
{"version", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'v'},
@@ -926,7 +926,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
#ifdef HAVE_V4L2 #ifdef HAVE_V4L2
if (!opts->display && !opts->record_filename && !opts->v4l2_device) { if (!opts->display && !opts->record_filename && !opts->v4l2_device) {
LOGE("-N/--no-display requires either screen recording (-r/--record)" LOGE("-N/--no-display requires either screen recording (-r/--record)"
" or sink to v4l2loopback device (--v4l2_sink)"); " or sink to v4l2loopback device (--v4l2-sink)");
return false; return false;
} }

View File

@@ -111,6 +111,8 @@ decoder_push(struct decoder *decoder, const AVPacket *packet) {
// A frame lost should not make the whole pipeline fail. The error, if // A frame lost should not make the whole pipeline fail. The error, if
// any, is already logged. // any, is already logged.
(void) ok; (void) ok;
av_frame_unref(decoder->frame);
} else if (ret != AVERROR(EAGAIN)) { } else if (ret != AVERROR(EAGAIN)) {
LOGE("Could not receive video frame: %d", ret); LOGE("Could not receive video frame: %d", ret);
return false; return false;

View File

@@ -92,11 +92,11 @@ encode_and_write_frame(struct sc_v4l2_sink *vs, const AVFrame *frame) {
// A packet was received // A packet was received
bool ok = write_packet(vs, packet); bool ok = write_packet(vs, packet);
av_packet_unref(packet);
if (!ok) { if (!ok) {
LOGW("Could not send packet to v4l2 sink"); LOGW("Could not send packet to v4l2 sink");
return false; return false;
} }
av_packet_unref(packet);
} else if (ret != AVERROR(EAGAIN)) { } else if (ret != AVERROR(EAGAIN)) {
LOGE("Could not receive v4l2 video packet: %d", ret); LOGE("Could not receive v4l2 video packet: %d", ret);
return false; return false;
@@ -125,6 +125,7 @@ run_v4l2_sink(void *data) {
video_buffer_consume(&vs->vb, vs->frame); video_buffer_consume(&vs->vb, vs->frame);
bool ok = encode_and_write_frame(vs, vs->frame); bool ok = encode_and_write_frame(vs, vs->frame);
av_frame_unref(vs->frame);
if (!ok) { if (!ok) {
LOGE("Could not send frame to v4l2 sink"); LOGE("Could not send frame to v4l2 sink");
break; break;

View File

@@ -55,7 +55,7 @@ public class Controller {
public void control() throws IOException { public void control() throws IOException {
// on start, power on the device // on start, power on the device
if (!Device.isScreenOn()) { if (!Device.isScreenOn()) {
device.injectKeycode(KeyEvent.KEYCODE_POWER); device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
// dirty hack // dirty hack
// After POWER is injected, the device is powered on asynchronously. // After POWER is injected, the device is powered on asynchronously.
@@ -273,7 +273,7 @@ public class Controller {
if (keepPowerModeOff) { if (keepPowerModeOff) {
schedulePowerModeOff(); schedulePowerModeOff();
} }
return device.injectKeycode(KeyEvent.KEYCODE_POWER); return device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
} }
private boolean setClipboard(String text, boolean paste) { private boolean setClipboard(String text, boolean paste) {
@@ -284,7 +284,7 @@ public class Controller {
// On Android >= 7, also press the PASTE key if requested // On Android >= 7, also press the PASTE key if requested
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) { if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
device.injectKeycode(KeyEvent.KEYCODE_PASTE); device.pressReleaseKeycode(KeyEvent.KEYCODE_PASTE);
} }
return ok; return ok;

View File

@@ -164,54 +164,39 @@ public final class Device {
return supportsInputEvents; return supportsInputEvents;
} }
public static boolean injectEvent(InputEvent inputEvent, int mode, int displayId) { public static boolean injectEvent(InputEvent inputEvent, int displayId) {
if (!supportsInputEvents(displayId)) { if (!supportsInputEvents(displayId)) {
return false; throw new AssertionError("Could not inject input event if !supportsInputEvents()");
} }
if (displayId != 0 && !InputManager.setDisplayId(inputEvent, displayId)) { if (displayId != 0 && !InputManager.setDisplayId(inputEvent, displayId)) {
return false; return false;
} }
return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, mode); return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
public boolean injectEvent(InputEvent inputEvent, int mode) {
if (!supportsInputEvents()) {
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
}
return injectEvent(inputEvent, mode, displayId);
}
public static boolean injectEventOnDisplay(InputEvent event, int displayId) {
return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, displayId);
} }
public boolean injectEvent(InputEvent event) { public boolean injectEvent(InputEvent event) {
return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); return injectEvent(event, displayId);
} }
public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId) { public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId) {
long now = SystemClock.uptimeMillis(); long now = SystemClock.uptimeMillis();
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
InputDevice.SOURCE_KEYBOARD); InputDevice.SOURCE_KEYBOARD);
return injectEventOnDisplay(event, displayId); return injectEvent(event, displayId);
} }
public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState) { public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState) {
long now = SystemClock.uptimeMillis(); return injectKeyEvent(action, keyCode, repeat, metaState, displayId);
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
InputDevice.SOURCE_KEYBOARD);
return injectEvent(event);
} }
public static boolean injectKeycode(int keyCode, int displayId) { public static boolean pressReleaseKeycode(int keyCode, int displayId) {
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId); return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId);
} }
public boolean injectKeycode(int keyCode) { public boolean pressReleaseKeycode(int keyCode) {
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0); return pressReleaseKeycode(keyCode, displayId);
} }
public static boolean isScreenOn() { public static boolean isScreenOn() {
@@ -287,7 +272,7 @@ public final class Device {
if (!isScreenOn()) { if (!isScreenOn()) {
return true; return true;
} }
return injectKeycode(KeyEvent.KEYCODE_POWER, displayId); return pressReleaseKeycode(KeyEvent.KEYCODE_POWER, displayId);
} }
/** /**