Compare commits
13 Commits
android12_
...
filter.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e306bffbc0 | ||
|
|
2512c53227 | ||
|
|
3cdbd00430 | ||
|
|
93a8ef20a6 | ||
|
|
8c845efe9a | ||
|
|
bf38331c76 | ||
|
|
7f6069213d | ||
|
|
5c4462ce70 | ||
|
|
c894a0b937 | ||
|
|
569e188254 | ||
|
|
152fb0f915 | ||
|
|
de3c1a7b4c | ||
|
|
e44714d2d1 |
@@ -99,6 +99,9 @@ foreach f : check_functions
|
||||
endif
|
||||
endforeach
|
||||
|
||||
# expose the build type
|
||||
conf.set('NDEBUG', get_option('buildtype') != 'debug')
|
||||
|
||||
# the version, updated on release
|
||||
conf.set_quoted('SCRCPY_VERSION', meson.project_version())
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
# define SCRCPY_SDL_HAS_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
#ifdef HAVE_STRDUP
|
||||
char *strdup(const char *s);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/time.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "events.h"
|
||||
@@ -18,18 +17,22 @@ push_frame(struct decoder *decoder) {
|
||||
video_buffer_offer_decoded_frame(decoder->video_buffer,
|
||||
&previous_frame_skipped);
|
||||
if (previous_frame_skipped) {
|
||||
// the previous EVENT_NEW_FRAME will consume this frame
|
||||
// the previous callback will consume this frame
|
||||
return;
|
||||
}
|
||||
static SDL_Event new_frame_event = {
|
||||
.type = EVENT_NEW_FRAME,
|
||||
};
|
||||
SDL_PushEvent(&new_frame_event);
|
||||
|
||||
decoder->cbs->on_new_frame(decoder, decoder->cbs_userdata);
|
||||
}
|
||||
|
||||
void
|
||||
decoder_init(struct decoder *decoder, struct video_buffer *vb) {
|
||||
decoder_init(struct decoder *decoder, struct video_buffer *vb,
|
||||
const struct decoder_callbacks *cbs, void *cbs_userdata) {
|
||||
decoder->video_buffer = vb;
|
||||
|
||||
assert(cbs);
|
||||
assert(cbs->on_new_frame);
|
||||
decoder->cbs = cbs;
|
||||
decoder->cbs_userdata = cbs_userdata;
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -11,10 +11,20 @@ struct video_buffer;
|
||||
struct decoder {
|
||||
struct video_buffer *video_buffer;
|
||||
AVCodecContext *codec_ctx;
|
||||
|
||||
const struct decoder_callbacks *cbs;
|
||||
void *cbs_userdata;
|
||||
};
|
||||
|
||||
struct decoder_callbacks {
|
||||
// Called when a new frame can be consumed by
|
||||
// video_buffer_take_rendering_frame(decoder->video_buffer).
|
||||
void (*on_new_frame)(struct decoder *decoder, void *userdata);
|
||||
};
|
||||
|
||||
void
|
||||
decoder_init(struct decoder *decoder, struct video_buffer *vb);
|
||||
decoder_init(struct decoder *decoder, struct video_buffer *vb,
|
||||
const struct decoder_callbacks *cbs, void *cbs_userdata);
|
||||
|
||||
bool
|
||||
decoder_open(struct decoder *decoder, const AVCodec *codec);
|
||||
|
||||
@@ -286,7 +286,7 @@ rotate_client_right(struct screen *screen) {
|
||||
screen_set_rotation(screen, new_rotation);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
input_manager_process_text_input(struct input_manager *im,
|
||||
const SDL_TextInputEvent *event) {
|
||||
if (is_shortcut_mod(im, SDL_GetModState())) {
|
||||
@@ -366,7 +366,7 @@ convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
input_manager_process_key(struct input_manager *im,
|
||||
const SDL_KeyboardEvent *event) {
|
||||
// control: indicates the state of the command-line option --no-control
|
||||
@@ -551,7 +551,7 @@ convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
input_manager_process_mouse_motion(struct input_manager *im,
|
||||
const SDL_MouseMotionEvent *event) {
|
||||
if (!event->state) {
|
||||
@@ -605,7 +605,7 @@ convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
input_manager_process_touch(struct input_manager *im,
|
||||
const SDL_TouchFingerEvent *event) {
|
||||
struct control_msg msg;
|
||||
@@ -637,7 +637,7 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
input_manager_process_mouse_button(struct input_manager *im,
|
||||
const SDL_MouseButtonEvent *event) {
|
||||
bool control = im->control;
|
||||
@@ -736,7 +736,7 @@ convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
input_manager_process_mouse_wheel(struct input_manager *im,
|
||||
const SDL_MouseWheelEvent *event) {
|
||||
struct control_msg msg;
|
||||
@@ -746,46 +746,3 @@ input_manager_process_mouse_wheel(struct input_manager *im,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
input_manager_handle_event(struct input_manager *im, SDL_Event *event) {
|
||||
switch (event->type) {
|
||||
case SDL_TEXTINPUT:
|
||||
if (!im->control) {
|
||||
return true;
|
||||
}
|
||||
input_manager_process_text_input(im, &event->text);
|
||||
return true;
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
// some key events do not interact with the device, so process the
|
||||
// event even if control is disabled
|
||||
input_manager_process_key(im, &event->key);
|
||||
return true;
|
||||
case SDL_MOUSEMOTION:
|
||||
if (!im->control) {
|
||||
break;
|
||||
}
|
||||
input_manager_process_mouse_motion(im, &event->motion);
|
||||
return true;
|
||||
case SDL_MOUSEWHEEL:
|
||||
if (!im->control) {
|
||||
break;
|
||||
}
|
||||
input_manager_process_mouse_wheel(im, &event->wheel);
|
||||
return true;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
// some mouse events do not interact with the device, so process
|
||||
// the event even if control is disabled
|
||||
input_manager_process_mouse_button(im, &event->button);
|
||||
return true;
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERUP:
|
||||
input_manager_process_touch(im, &event->tfinger);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,28 @@ void
|
||||
input_manager_init(struct input_manager *im,
|
||||
const struct scrcpy_options *options);
|
||||
|
||||
bool
|
||||
input_manager_handle_event(struct input_manager *im, SDL_Event *event);
|
||||
void
|
||||
input_manager_process_text_input(struct input_manager *im,
|
||||
const SDL_TextInputEvent *event);
|
||||
|
||||
void
|
||||
input_manager_process_key(struct input_manager *im,
|
||||
const SDL_KeyboardEvent *event);
|
||||
|
||||
void
|
||||
input_manager_process_mouse_motion(struct input_manager *im,
|
||||
const SDL_MouseMotionEvent *event);
|
||||
|
||||
void
|
||||
input_manager_process_touch(struct input_manager *im,
|
||||
const SDL_TouchFingerEvent *event);
|
||||
|
||||
void
|
||||
input_manager_process_mouse_button(struct input_manager *im,
|
||||
const SDL_MouseButtonEvent *event);
|
||||
|
||||
void
|
||||
input_manager_process_mouse_wheel(struct input_manager *im,
|
||||
const SDL_MouseWheelEvent *event);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "util/net.h"
|
||||
|
||||
static struct server server;
|
||||
static struct screen screen;
|
||||
static struct screen screen = SCREEN_INITIALIZER;
|
||||
static struct fps_counter fps_counter;
|
||||
static struct video_buffer video_buffer;
|
||||
static struct stream stream;
|
||||
@@ -173,6 +173,56 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
|
||||
case SDL_QUIT:
|
||||
LOGD("User requested to quit");
|
||||
return EVENT_RESULT_STOPPED_BY_USER;
|
||||
case EVENT_NEW_FRAME:
|
||||
if (!screen.has_frame) {
|
||||
screen.has_frame = true;
|
||||
// this is the very first frame, show the window
|
||||
screen_show_window(&screen);
|
||||
}
|
||||
if (!screen_update_frame(&screen, &video_buffer)) {
|
||||
return EVENT_RESULT_CONTINUE;
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
if (screen.has_frame) {
|
||||
screen_handle_window_event(&screen, &event->window);
|
||||
}
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
if (!options->control) {
|
||||
break;
|
||||
}
|
||||
input_manager_process_text_input(&input_manager, &event->text);
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
// some key events do not interact with the device, so process the
|
||||
// event even if control is disabled
|
||||
input_manager_process_key(&input_manager, &event->key);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
if (!options->control) {
|
||||
break;
|
||||
}
|
||||
input_manager_process_mouse_motion(&input_manager, &event->motion);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
if (!options->control) {
|
||||
break;
|
||||
}
|
||||
input_manager_process_mouse_wheel(&input_manager, &event->wheel);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
// some mouse events do not interact with the device, so process
|
||||
// the event even if control is disabled
|
||||
input_manager_process_mouse_button(&input_manager, &event->button);
|
||||
break;
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERUP:
|
||||
input_manager_process_touch(&input_manager, &event->tfinger);
|
||||
break;
|
||||
case SDL_DROPFILE: {
|
||||
if (!options->control) {
|
||||
break;
|
||||
@@ -194,16 +244,6 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool consumed = screen_handle_event(&screen, event);
|
||||
if (consumed) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
consumed = input_manager_handle_event(&input_manager, event);
|
||||
(void) consumed;
|
||||
|
||||
end:
|
||||
return EVENT_RESULT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -266,6 +306,17 @@ av_log_callback(void *avcl, int level, const char *fmt, va_list vl) {
|
||||
free(local_fmt);
|
||||
}
|
||||
|
||||
static void
|
||||
decoder_on_new_frame(struct decoder *decoder, void *userdata) {
|
||||
(void) decoder;
|
||||
(void) userdata;
|
||||
|
||||
static SDL_Event new_frame_event = {
|
||||
.type = EVENT_NEW_FRAME,
|
||||
};
|
||||
SDL_PushEvent(&new_frame_event);
|
||||
}
|
||||
|
||||
bool
|
||||
scrcpy(const struct scrcpy_options *options) {
|
||||
if (!server_init(&server)) {
|
||||
@@ -346,7 +397,11 @@ scrcpy(const struct scrcpy_options *options) {
|
||||
file_handler_initialized = true;
|
||||
}
|
||||
|
||||
decoder_init(&decoder, &video_buffer);
|
||||
static const struct decoder_callbacks decoder_cbs = {
|
||||
.on_new_frame = decoder_on_new_frame,
|
||||
};
|
||||
|
||||
decoder_init(&decoder, &video_buffer, &decoder_cbs, NULL);
|
||||
dec = &decoder;
|
||||
}
|
||||
|
||||
@@ -389,8 +444,6 @@ scrcpy(const struct scrcpy_options *options) {
|
||||
const char *window_title =
|
||||
options->window_title ? options->window_title : device_name;
|
||||
|
||||
screen_init(&screen, &video_buffer);
|
||||
|
||||
if (!screen_init_rendering(&screen, window_title, frame_size,
|
||||
options->always_on_top, options->window_x,
|
||||
options->window_y, options->window_width,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "events.h"
|
||||
#include "icon.xpm"
|
||||
#include "scrcpy.h"
|
||||
#include "tiny_xpm.h"
|
||||
@@ -192,9 +191,8 @@ screen_update_content_rect(struct screen *screen) {
|
||||
}
|
||||
|
||||
void
|
||||
screen_init(struct screen *screen, struct video_buffer *vb) {
|
||||
screen_init(struct screen *screen) {
|
||||
*screen = (struct screen) SCREEN_INITIALIZER;
|
||||
screen->vb = vb;
|
||||
}
|
||||
|
||||
static inline SDL_Texture *
|
||||
@@ -450,9 +448,9 @@ update_texture(struct screen *screen, const AVFrame *frame) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
screen_update_frame(struct screen *screen) {
|
||||
const AVFrame *frame = video_buffer_take_rendering_frame(screen->vb);
|
||||
bool
|
||||
screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
||||
const AVFrame *frame = video_buffer_take_rendering_frame(vb);
|
||||
struct size new_frame_size = {frame->width, frame->height};
|
||||
if (!prepare_for_frame(screen, new_frame_size)) {
|
||||
return false;
|
||||
@@ -544,52 +542,31 @@ screen_resize_to_pixel_perfect(struct screen *screen) {
|
||||
content_size.height);
|
||||
}
|
||||
|
||||
bool
|
||||
screen_handle_event(struct screen *screen, SDL_Event *event) {
|
||||
switch (event->type) {
|
||||
case EVENT_NEW_FRAME:
|
||||
if (!screen->has_frame) {
|
||||
screen->has_frame = true;
|
||||
// this is the very first frame, show the window
|
||||
screen_show_window(screen);
|
||||
void
|
||||
screen_handle_window_event(struct screen *screen,
|
||||
const SDL_WindowEvent *event) {
|
||||
switch (event->event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
screen_render(screen, true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
screen_render(screen, true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
screen->maximized = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
if (screen->fullscreen) {
|
||||
// On Windows, in maximized+fullscreen, disabling fullscreen
|
||||
// mode unexpectedly triggers the "restored" then "maximized"
|
||||
// events, leaving the window in a weird state (maximized
|
||||
// according to the events, but not maximized visually).
|
||||
break;
|
||||
}
|
||||
bool ok = screen_update_frame(screen);
|
||||
if (!ok) {
|
||||
LOGW("Frame update failed\n");
|
||||
}
|
||||
return true;
|
||||
case SDL_WINDOWEVENT:
|
||||
if (!screen->has_frame) {
|
||||
// Do nothing
|
||||
return true;
|
||||
}
|
||||
switch (event->window.event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
screen_render(screen, true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
screen_render(screen, true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
screen->maximized = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
if (screen->fullscreen) {
|
||||
// On Windows, in maximized+fullscreen, disabling
|
||||
// fullscreen mode unexpectedly triggers the "restored"
|
||||
// then "maximized" events, leaving the window in a
|
||||
// weird state (maximized according to the events, but
|
||||
// not maximized visually).
|
||||
break;
|
||||
}
|
||||
screen->maximized = false;
|
||||
apply_pending_resize(screen);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
screen->maximized = false;
|
||||
apply_pending_resize(screen);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct point
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
struct video_buffer;
|
||||
|
||||
struct screen {
|
||||
struct video_buffer *vb;
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
@@ -38,7 +37,6 @@ struct screen {
|
||||
};
|
||||
|
||||
#define SCREEN_INITIALIZER { \
|
||||
.vb = NULL, \
|
||||
.window = NULL, \
|
||||
.renderer = NULL, \
|
||||
.texture = NULL, \
|
||||
@@ -72,7 +70,7 @@ struct screen {
|
||||
|
||||
// initialize default values
|
||||
void
|
||||
screen_init(struct screen *screen, struct video_buffer *vb);
|
||||
screen_init(struct screen *screen);
|
||||
|
||||
// initialize screen, create window, renderer and texture (window is hidden)
|
||||
// window_x and window_y accept SC_WINDOW_POSITION_UNDEFINED
|
||||
@@ -91,6 +89,10 @@ screen_show_window(struct screen *screen);
|
||||
void
|
||||
screen_destroy(struct screen *screen);
|
||||
|
||||
// resize if necessary and write the rendered frame into the texture
|
||||
bool
|
||||
screen_update_frame(struct screen *screen, struct video_buffer *vb);
|
||||
|
||||
// render the texture to the renderer
|
||||
//
|
||||
// Set the update_content_rect flag if the window or content size may have
|
||||
@@ -114,9 +116,9 @@ screen_resize_to_pixel_perfect(struct screen *screen);
|
||||
void
|
||||
screen_set_rotation(struct screen *screen, unsigned rotation);
|
||||
|
||||
// react to SDL events
|
||||
bool
|
||||
screen_handle_event(struct screen *screen, SDL_Event *event);
|
||||
// react to window events
|
||||
void
|
||||
screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event);
|
||||
|
||||
// convert point from window coordinates to frame coordinates
|
||||
// x and y are expressed in pixels
|
||||
|
||||
@@ -4,7 +4,6 @@ project('scrcpy', 'c',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
'warning_level=2',
|
||||
'b_ndebug=if-release',
|
||||
])
|
||||
|
||||
if get_option('compile_app')
|
||||
|
||||
@@ -7,7 +7,6 @@ import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo;
|
||||
import android.media.MediaCodecList;
|
||||
import android.media.MediaFormat;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.view.Surface;
|
||||
|
||||
@@ -226,9 +225,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||
}
|
||||
|
||||
private static IBinder createDisplay() {
|
||||
// Since Android 12, secure displays could not be created with shell permissions anymore
|
||||
boolean secure = Build.VERSION.SDK_INT <= Build.VERSION_CODES.R;
|
||||
return SurfaceControl.createDisplay("scrcpy", secure);
|
||||
return SurfaceControl.createDisplay("scrcpy", true);
|
||||
}
|
||||
|
||||
private static void configure(MediaCodec codec, MediaFormat format) {
|
||||
|
||||
Reference in New Issue
Block a user