|
|
|
|
@@ -198,19 +198,30 @@ sc_screen_update_content_rect(struct sc_screen *screen) {
|
|
|
|
|
// changed, so that the content rectangle is recomputed
|
|
|
|
|
static void
|
|
|
|
|
sc_screen_render(struct sc_screen *screen, bool update_content_rect) {
|
|
|
|
|
assert(!screen->video || screen->has_video_window);
|
|
|
|
|
assert(screen->window_shown);
|
|
|
|
|
|
|
|
|
|
if (update_content_rect) {
|
|
|
|
|
sc_screen_update_content_rect(screen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_Renderer *renderer = screen->renderer;
|
|
|
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
|
|
|
|
sc_sdl_render_clear(renderer);
|
|
|
|
|
|
|
|
|
|
bool ok = false;
|
|
|
|
|
SDL_Texture *texture = screen->tex.texture;
|
|
|
|
|
if (!texture) {
|
|
|
|
|
LOGW("No texture to render");
|
|
|
|
|
// Draw a dark 10x10 square in the top-right corner to distinguish a
|
|
|
|
|
// black frame from the absence of a frame
|
|
|
|
|
struct sc_size render_size = sc_sdl_get_render_output_size(renderer);
|
|
|
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0x33, 0xff);
|
|
|
|
|
SDL_FRect rect = {
|
|
|
|
|
.x = render_size.width - 20,
|
|
|
|
|
.y = 10,
|
|
|
|
|
.w = 10,
|
|
|
|
|
.h = 10,
|
|
|
|
|
};
|
|
|
|
|
SDL_RenderFillRect(renderer, &rect);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -280,11 +291,8 @@ sc_screen_frame_sink_open(struct sc_frame_sink *sink,
|
|
|
|
|
const AVCodecContext *ctx,
|
|
|
|
|
const struct sc_stream_session *session) {
|
|
|
|
|
assert(ctx->pix_fmt == AV_PIX_FMT_YUV420P);
|
|
|
|
|
(void) ctx;
|
|
|
|
|
(void) session;
|
|
|
|
|
|
|
|
|
|
struct sc_screen *screen = DOWNCAST(sink);
|
|
|
|
|
(void) screen;
|
|
|
|
|
|
|
|
|
|
if (ctx->width <= 0 || ctx->width > 0xFFFF
|
|
|
|
|
|| ctx->height <= 0 || ctx->height > 0xFFFF) {
|
|
|
|
|
@@ -292,6 +300,19 @@ sc_screen_frame_sink_open(struct sc_frame_sink *sink,
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// content_size can be written from this thread, because it is never read
|
|
|
|
|
// from the main thread before handling SC_EVENT_OPEN_WINDOW (which acts as
|
|
|
|
|
// a synchronization point) when video is enabled
|
|
|
|
|
screen->frame_size.width = session->video.width;
|
|
|
|
|
screen->frame_size.height = session->video.height;
|
|
|
|
|
screen->content_size = get_oriented_size(screen->frame_size,
|
|
|
|
|
screen->orientation);
|
|
|
|
|
|
|
|
|
|
bool ok = sc_push_event(SC_EVENT_OPEN_WINDOW);
|
|
|
|
|
if (!ok) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
screen->open = true;
|
|
|
|
|
#endif
|
|
|
|
|
@@ -341,8 +362,7 @@ bool
|
|
|
|
|
sc_screen_init(struct sc_screen *screen,
|
|
|
|
|
const struct sc_screen_params *params) {
|
|
|
|
|
screen->resize_pending = false;
|
|
|
|
|
screen->has_frame = false;
|
|
|
|
|
screen->has_video_window = false;
|
|
|
|
|
screen->window_shown = false;
|
|
|
|
|
screen->paused = false;
|
|
|
|
|
screen->resume_frame = NULL;
|
|
|
|
|
screen->orientation = SC_ORIENTATION_0;
|
|
|
|
|
@@ -533,6 +553,7 @@ sc_screen_init(struct sc_screen *screen,
|
|
|
|
|
|
|
|
|
|
if (!screen->video) {
|
|
|
|
|
// Show the window immediately
|
|
|
|
|
screen->window_shown = true;
|
|
|
|
|
sc_sdl_show_window(screen->window);
|
|
|
|
|
|
|
|
|
|
if (sc_screen_is_relative_mode(screen)) {
|
|
|
|
|
@@ -589,6 +610,7 @@ sc_screen_show_initial_window(struct sc_screen *screen) {
|
|
|
|
|
sc_fps_counter_start(&screen->fps_counter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
screen->window_shown = true;
|
|
|
|
|
sc_sdl_show_window(screen->window);
|
|
|
|
|
sc_screen_update_content_rect(screen);
|
|
|
|
|
}
|
|
|
|
|
@@ -596,6 +618,7 @@ sc_screen_show_initial_window(struct sc_screen *screen) {
|
|
|
|
|
void
|
|
|
|
|
sc_screen_hide_window(struct sc_screen *screen) {
|
|
|
|
|
sc_sdl_hide_window(screen->window);
|
|
|
|
|
screen->window_shown = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
@@ -692,14 +715,14 @@ sc_screen_set_orientation(struct sc_screen *screen,
|
|
|
|
|
static bool
|
|
|
|
|
sc_screen_apply_frame(struct sc_screen *screen) {
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
assert(screen->window_shown);
|
|
|
|
|
|
|
|
|
|
sc_fps_counter_add_rendered_frame(&screen->fps_counter);
|
|
|
|
|
|
|
|
|
|
AVFrame *frame = screen->frame;
|
|
|
|
|
struct sc_size new_frame_size = {frame->width, frame->height};
|
|
|
|
|
|
|
|
|
|
if (!screen->has_frame
|
|
|
|
|
|| screen->frame_size.width != new_frame_size.width
|
|
|
|
|
if (screen->frame_size.width != new_frame_size.width
|
|
|
|
|
|| screen->frame_size.height != new_frame_size.height) {
|
|
|
|
|
|
|
|
|
|
// frame dimension changed
|
|
|
|
|
@@ -707,14 +730,8 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
|
|
|
|
|
|
|
|
|
struct sc_size new_content_size =
|
|
|
|
|
get_oriented_size(new_frame_size, screen->orientation);
|
|
|
|
|
if (screen->has_frame) {
|
|
|
|
|
set_content_size(screen, new_content_size);
|
|
|
|
|
sc_screen_update_content_rect(screen);
|
|
|
|
|
} else {
|
|
|
|
|
// This is the first frame
|
|
|
|
|
screen->has_frame = true;
|
|
|
|
|
screen->content_size = new_content_size;
|
|
|
|
|
}
|
|
|
|
|
set_content_size(screen, new_content_size);
|
|
|
|
|
sc_screen_update_content_rect(screen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ok = sc_texture_set_from_frame(&screen->tex, frame);
|
|
|
|
|
@@ -722,18 +739,6 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(screen->has_frame);
|
|
|
|
|
if (!screen->has_video_window) {
|
|
|
|
|
screen->has_video_window = true;
|
|
|
|
|
// this is the very first frame, show the window
|
|
|
|
|
sc_screen_show_initial_window(screen);
|
|
|
|
|
|
|
|
|
|
if (sc_screen_is_relative_mode(screen)) {
|
|
|
|
|
// Capture mouse on start
|
|
|
|
|
sc_mouse_capture_set_active(&screen->mc, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_screen_render(screen, false);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
@@ -854,9 +859,17 @@ sc_screen_resize_to_pixel_perfect(struct sc_screen *screen) {
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|
|
|
|
// !video implies !has_video_window
|
|
|
|
|
assert(screen->video || !screen->has_video_window);
|
|
|
|
|
switch (event->type) {
|
|
|
|
|
case SC_EVENT_OPEN_WINDOW:
|
|
|
|
|
sc_screen_show_initial_window(screen);
|
|
|
|
|
|
|
|
|
|
if (sc_screen_is_relative_mode(screen)) {
|
|
|
|
|
// Capture mouse on start
|
|
|
|
|
sc_mouse_capture_set_active(&screen->mc, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_screen_render(screen, false);
|
|
|
|
|
return;
|
|
|
|
|
case SC_EVENT_NEW_FRAME: {
|
|
|
|
|
bool ok = sc_screen_update_frame(screen);
|
|
|
|
|
if (!ok) {
|
|
|
|
|
@@ -865,28 +878,27 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case SDL_EVENT_WINDOW_EXPOSED:
|
|
|
|
|
if (!screen->video || screen->has_video_window) {
|
|
|
|
|
sc_screen_render(screen, true);
|
|
|
|
|
}
|
|
|
|
|
sc_screen_render(screen, true);
|
|
|
|
|
return;
|
|
|
|
|
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
|
|
|
|
if (screen->has_video_window) {
|
|
|
|
|
// This event can be triggered before the window is shown
|
|
|
|
|
if (screen->window_shown) {
|
|
|
|
|
sc_screen_render(screen, true);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDL_EVENT_WINDOW_RESTORED:
|
|
|
|
|
if (screen->has_video_window && is_windowed(screen)) {
|
|
|
|
|
if (screen->video && is_windowed(screen)) {
|
|
|
|
|
apply_pending_resize(screen);
|
|
|
|
|
sc_screen_render(screen, true);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
|
|
|
|
|
LOGD("Switched to fullscreen mode");
|
|
|
|
|
assert(screen->has_video_window);
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
return;
|
|
|
|
|
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
|
|
|
|
|
LOGD("Switched to windowed mode");
|
|
|
|
|
assert(screen->has_video_window);
|
|
|
|
|
assert(screen->video);
|
|
|
|
|
if (is_windowed(screen)) {
|
|
|
|
|
apply_pending_resize(screen);
|
|
|
|
|
sc_screen_render(screen, true);
|
|
|
|
|
|