Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show text after file pushed #1484

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ sudo apt install ffmpeg libsdl2-2.0-0 adb
# client build dependencies
sudo apt install gcc git pkg-config meson ninja-build \
libavcodec-dev libavformat-dev libavutil-dev \
libsdl2-dev
libsdl2-dev libsdl2-ttf-dev

# server build dependencies
sudo apt install openjdk-8-jdk
Expand Down
2 changes: 2 additions & 0 deletions Makefile.CrossWindows
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ dist-win32: build-server build-win32 build-win32-noconsole
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.12/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/SDL2_ttf-2.0.15/i686-w64-mingw32/bin/SDL2_ttf.dll "$(DIST)/$(WIN32_TARGET_DIR)/"

dist-win64: build-server build-win64 build-win64-noconsole
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
Expand All @@ -124,6 +125,7 @@ dist-win64: build-server build-win64 build-win64-noconsole
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.12/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/SDL2_ttf-2.0.15/x86_64-w64-mingw32/bin/SDL2_ttf.dll "$(DIST)/$(WIN64_TARGET_DIR)/"

zip-win32: dist-win32
cd "$(DIST)/$(WIN32_TARGET_DIR)"; \
Expand Down
17 changes: 16 additions & 1 deletion app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ src = [
'src/fps_counter.c',
'src/input_manager.c',
'src/opengl.c',
'src/open_sans_font.c',
'src/receiver.c',
'src/recorder.c',
'src/scrcpy.c',
Expand All @@ -32,6 +33,7 @@ if not get_option('crossbuild_windows')
dependency('libavcodec'),
dependency('libavutil'),
dependency('sdl2'),
dependency('SDL2_ttf'),
]

else
Expand All @@ -43,7 +45,6 @@ else
sdl2_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_sdl2 + '/bin'
sdl2_lib_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_sdl2 + '/lib'
sdl2_include_dir = '../prebuilt-deps/' + prebuilt_sdl2 + '/include'

sdl2 = declare_dependency(
dependencies: [
cc.find_library('SDL2', dirs: sdl2_bin_dir),
Expand All @@ -52,6 +53,19 @@ else
include_directories: include_directories(sdl2_include_dir)
)

prebuilt_sdl2_ttf = meson.get_cross_property('prebuilt_sdl2_ttf')
sdl2_include_sdl2_dir = '../prebuilt-deps/' + prebuilt_sdl2 + '/include/SDL2'
sdl2_ttf_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_sdl2_ttf + '/bin'
sdl2_ttf_lib_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_sdl2_ttf + '/lib'
sdl2_ttf_include_dir = '../prebuilt-deps/' + prebuilt_sdl2_ttf + '/include'
sdl2_ttf = declare_dependency(
dependencies: [
cc.find_library('SDL2_ttf', dirs: sdl2_ttf_lib_dir),
cc.find_library('SDL2_ttf', dirs: sdl2_ttf_bin_dir),
],
include_directories: include_directories(sdl2_include_sdl2_dir, sdl2_ttf_include_dir)
)

prebuilt_ffmpeg_shared = meson.get_cross_property('prebuilt_ffmpeg_shared')
prebuilt_ffmpeg_dev = meson.get_cross_property('prebuilt_ffmpeg_dev')
ffmpeg_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_ffmpeg_shared + '/bin'
Expand All @@ -67,6 +81,7 @@ else

dependencies = [
ffmpeg,
sdl2_ttf,
sdl2,
cc.find_library('mingw32')
]
Expand Down
2 changes: 2 additions & 0 deletions app/src/events.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#define EVENT_NEW_SESSION SDL_USEREVENT
#define EVENT_NEW_FRAME (SDL_USEREVENT + 1)
#define EVENT_STREAM_STOPPED (SDL_USEREVENT + 2)
#define EVENT_SCREEN_RENDER (SDL_USEREVENT + 3)
#define EVENT_RENDER_TEXT (SDL_USEREVENT + 4)
2 changes: 2 additions & 0 deletions app/src/file_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "config.h"
#include "command.h"
#include "screen.h"
#include "util/lock.h"
#include "util/log.h"

Expand Down Expand Up @@ -145,6 +146,7 @@ run_file_handler(void *data) {
if (process_check_success(process, "adb push")) {
LOGI("%s successfully pushed to %s", req.file,
file_handler->push_target);
screen_add_text_event("File successfully pushed");
} else {
LOGE("Failed to push %s to %s", req.file,
file_handler->push_target);
Expand Down
8,091 changes: 8,091 additions & 0 deletions app/src/open_sans_font.c

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions app/src/open_sans_font.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef OPEN_SANS_FONT_H
#define OPEN_SANS_FONT_H

#include <SDL2/SDL.h>

SDL_RWops *
open_sans_font_raw();

#endif
21 changes: 20 additions & 1 deletion app/src/scrcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <libavformat/avformat.h>
#include <sys/time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

#ifdef _WIN32
# include <windows.h>
Expand Down Expand Up @@ -61,15 +62,26 @@ BOOL WINAPI windows_ctrl_handler(DWORD ctrl_type) {
}
#endif // _WIN32

static void
ttf_destroy() {
TTF_Quit();
}

// init SDL and set appropriate hints
static bool
sdl_init_and_configure(bool display, const char *render_driver) {
uint32_t flags = display ? SDL_INIT_VIDEO : SDL_INIT_EVENTS;
if (SDL_Init(flags)) {
if (SDL_Init(flags | SDL_INIT_TIMER)) {
LOGC("Could not initialize SDL: %s", SDL_GetError());
return false;
}

if (0 > TTF_Init()) {
LOGC("Could not initialize TTF: %s", TTF_GetError());
return false;
}

atexit(ttf_destroy);
atexit(SDL_Quit);

#ifdef _WIN32
Expand Down Expand Up @@ -163,6 +175,13 @@ handle_event(SDL_Event *event, bool control) {
case SDL_QUIT:
LOGD("User requested to quit");
return EVENT_RESULT_STOPPED_BY_USER;
case EVENT_SCREEN_RENDER:
screen_render(&screen, false);
break;
case EVENT_RENDER_TEXT:
screen_add_text_to_render_queue(&screen, event->user.data1);
screen_render(&screen, false);
break;
case EVENT_NEW_FRAME:
if (!screen.has_frame) {
screen.has_frame = true;
Expand Down
148 changes: 148 additions & 0 deletions app/src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
#include <assert.h>
#include <string.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

#include "config.h"
#include "common.h"
#include "compat.h"
#include "events.h"
#include "icon.xpm"
#include "open_sans_font.h"
#include "tiny_xpm.h"
#include "video_buffer.h"
#include "util/lock.h"
#include "util/log.h"

#define DISPLAY_MARGINS 96
#define OSD_TEXT_TIME 5

static inline struct size
get_rotated_size(struct size size, int rotation) {
Expand Down Expand Up @@ -330,6 +334,21 @@ screen_init_rendering(struct screen *screen, const char *window_title,
// different HiDPI scaling are connected
SDL_SetWindowSize(screen->window, window_size.width, window_size.height);

if (!(screen->mutex = SDL_CreateMutex())) {
LOGC("Could not create mutex: %s", SDL_GetError());
screen_destroy(screen);
return false;
}

SDL_RWops *raw_font = open_sans_font_raw();

screen->font = TTF_OpenFontRW(raw_font, 1, 25);
if (!screen->font) {
LOGW("Init font failed: %s", SDL_GetError());
screen_destroy(screen);
return false;
}

screen_update_content_rect(screen);

return true;
Expand All @@ -342,6 +361,18 @@ screen_show_window(struct screen *screen) {

void
screen_destroy(struct screen *screen) {
if (screen->text_texture) {
SDL_DestroyTexture(screen->text_texture);
}
if (screen->surface) {
SDL_FreeSurface(screen->surface);
}
if (screen->font) {
TTF_CloseFont(screen->font);
}
if (screen->mutex) {
SDL_DestroyMutex(screen->mutex);
}
if (screen->texture) {
SDL_DestroyTexture(screen->texture);
}
Expand Down Expand Up @@ -454,6 +485,87 @@ update_texture(struct screen *screen, const AVFrame *frame) {
}
}

static uint32_t
screen_text_timer_callback(uint32_t interval __attribute__((unused)), void *param __attribute__((unused))) {
static SDL_Event render_event;

render_event.type = EVENT_SCREEN_RENDER;

SDL_PushEvent(&render_event);

return 0;
}

bool
screen_render_text(struct screen *screen) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This opens the font and draws the glyphs on every frame :/

IMO, it should create the texture and render the text the first time, then cache it (to be invalidated on resize though).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree.

struct render_text_request req;

if (time(NULL) >= screen->expired_time) {
if (screen->text_texture) {
SDL_DestroyTexture(screen->text_texture);
screen->text_texture = NULL;
}
if (screen->surface) {
SDL_FreeSurface(screen->surface);
screen->surface = NULL;
}
}

if (screen->surface == NULL || screen->text_texture == NULL) {
mutex_lock(screen->mutex);
if (cbuf_is_empty(&screen->queue)) {
mutex_unlock(screen->mutex);
return true;
}
cbuf_take(&screen->queue, &req);
mutex_unlock(screen->mutex);

SDL_Color text_color = {0, 0, 0, 255};
SDL_Color bg_color = {255, 255, 255, 50};
int width = 0;
int height = 0;

screen->expired_time = req.expired_time;
screen->surface = TTF_RenderText_Shaded(screen->font, req.text, text_color, bg_color);
if (!screen->surface) {
LOGW("Init surface failed: %s", SDL_GetError());
SDL_free(req.text);
return false;
}

screen->text_texture = SDL_CreateTextureFromSurface(screen->renderer, screen->surface);
if (!screen->text_texture) {
LOGW("Init text texture failed: %s", SDL_GetError());
SDL_free(req.text);
SDL_FreeSurface(screen->surface);
return false;
}

if (TTF_SizeText(screen->font, req.text, &width, &height)) {
LOGW("Could not get the size of TTF: %s", TTF_GetError());
SDL_free(req.text);
SDL_DestroyTexture(screen->text_texture);
SDL_FreeSurface(screen->surface);
return false;
}

screen->text_rect.x = screen->rect.w / 2 - width / 2;
screen->text_rect.y = screen->rect.h / 3 * 2;
screen->text_rect.w = width;
screen->text_rect.h = height;

SDL_free(req.text);

if (!SDL_AddTimer((OSD_TEXT_TIME + 1) * 1000, screen_text_timer_callback, NULL)) {
LOGW("Failed to add render timer callback, err: %s", SDL_GetError());
}
}

SDL_RenderCopy(screen->renderer, screen->text_texture, NULL, &(screen->text_rect));

return true;
}

bool
screen_update_frame(struct screen *screen, struct video_buffer *vb) {
mutex_lock(vb->mutex);
Expand Down Expand Up @@ -501,6 +613,7 @@ screen_render(struct screen *screen, bool update_content_rect) {
SDL_RenderCopyEx(screen->renderer, screen->texture, NULL, dstrect,
angle, NULL, 0);
}
screen_render_text(screen);
SDL_RenderPresent(screen->renderer);
}

Expand Down Expand Up @@ -578,6 +691,41 @@ screen_handle_window_event(struct screen *screen,
}
}

bool
screen_add_text_event(const char *text) {
char *t = SDL_malloc(strlen(text) + 1);

if (!t) {
LOGW("Failed to allocate memory");
return false;
}

memset(t, 0, strlen(text) + 1);
strncpy(t, text, strlen(text));
static SDL_Event text_event;

text_event.type = EVENT_RENDER_TEXT;
text_event.user.data1 = t;

SDL_PushEvent(&text_event);

return true;
}

void
screen_add_text_to_render_queue(struct screen *screen, char *text) {
struct render_text_request req = {
.text = text,
.expired_time = time(NULL) + OSD_TEXT_TIME,
};

mutex_lock(screen->mutex);
if (!cbuf_push(&screen->queue, req)) {
LOGW("Failed to push request to queue");
}
mutex_unlock(screen->mutex);
}

struct point
screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y) {
unsigned rotation = screen->rotation;
Expand Down
Loading