From ac1f0184e70a5f24f5c3011dcfe18c61ce2d72da Mon Sep 17 00:00:00 2001 From: Iwan Timmer Date: Fri, 1 Jan 2016 13:00:14 +0100 Subject: [PATCH] SDL in single thread --- src/main.c | 8 +------- src/sdl.c | 50 +++++++++++++++++++++++++++++++++++++++++++++--- src/sdl.h | 4 +++- src/video/sdl.c | 51 ++++++++++++++++--------------------------------- 4 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/main.c b/src/main.c index d0bf777..f4f450f 100644 --- a/src/main.c +++ b/src/main.c @@ -85,18 +85,12 @@ static void stream(PSERVER_DATA server, PCONFIGURATION config, enum platform sys gs_start_app(server, &config->stream, appId, config->sops, config->localaudio); - void *context = NULL; - #ifdef HAVE_SDL - if (system == SDL) - context = sdl_window; - #endif - int drFlags = 0; if (config->fullscreen) drFlags |= DISPLAY_FULLSCREEN; printf("Stream %d x %d, %d fps, %d kbps\n", config->stream.width, config->stream.height, config->stream.fps, config->stream.bitrate); - LiStartConnection(server->address, &config->stream, &connection_callbacks, platform_get_video(system), platform_get_audio(system), context, drFlags, server->serverMajorVersion); + LiStartConnection(server->address, &config->stream, &connection_callbacks, platform_get_video(system), platform_get_audio(system), NULL, drFlags, server->serverMajorVersion); if (IS_EMBEDDED(system)) { evdev_start(); diff --git a/src/sdl.c b/src/sdl.c index 0f7d6db..b48999e 100644 --- a/src/sdl.c +++ b/src/sdl.c @@ -27,7 +27,11 @@ static bool done; static int fullscreen_flags; -SDL_Window *sdl_window; +static SDL_Window *window; +static SDL_Renderer *renderer; +static SDL_Texture *bmp; + +SDL_mutex *mutex; void sdl_init(int width, int height, bool fullscreen) { if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { @@ -36,6 +40,32 @@ void sdl_init(int width, int height, bool fullscreen) { } fullscreen_flags = fullscreen?SDL_WINDOW_FULLSCREEN:0; + window = SDL_CreateWindow("Moonlight", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL | fullscreen_flags); + if(!window) { + fprintf(stderr, "SDL: could not create window - exiting\n"); + exit(1); + } + + SDL_SetRelativeMouseMode(SDL_TRUE); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!renderer) { + printf("SDL_CreateRenderer failed: %s\n", SDL_GetError()); + exit(1); + } + + bmp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, width, height); + if (!bmp) { + fprintf(stderr, "SDL: could not create texture - exiting\n"); + exit(1); + } + + mutex = SDL_CreateMutex(); + if (!mutex) { + fprintf(stderr, "Couldn't create mutex\n"); + exit(1); + } + + sdlinput_init(); } @@ -48,7 +78,7 @@ void sdl_loop() { break; case SDL_TOGGLE_FULLSCREEN: fullscreen_flags ^= SDL_WINDOW_FULLSCREEN; - SDL_SetWindowFullscreen(sdl_window, fullscreen_flags); + SDL_SetWindowFullscreen(window, fullscreen_flags); case SDL_MOUSE_GRAB: SDL_SetRelativeMouseMode(SDL_TRUE); break; @@ -58,10 +88,24 @@ void sdl_loop() { default: if (event.type == SDL_QUIT) done = true; + else if (event.type == SDL_USEREVENT) { + if (event.user.code == SDL_CODE_FRAME) { + if (SDL_LockMutex(mutex) == 0) { + Uint8** data = ((Uint8**) event.user.data1); + int* linesize = ((int*) event.user.data2); + SDL_UpdateYUVTexture(bmp, NULL, data[0], linesize[0], data[1], linesize[1], data[2], linesize[2]); + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, bmp, NULL, NULL); + SDL_RenderPresent(renderer); + SDL_UnlockMutex(mutex); + } else + fprintf(stderr, "Couldn't lock mutex\n"); + } + } } } - SDL_DestroyWindow(sdl_window); + SDL_DestroyWindow(window); SDL_Quit(); } diff --git a/src/sdl.h b/src/sdl.h index 377737c..b670209 100644 --- a/src/sdl.h +++ b/src/sdl.h @@ -29,9 +29,11 @@ #define SDL_MOUSE_UNGRAB 3 #define SDL_TOGGLE_FULLSCREEN 4 -SDL_Window *sdl_window; +#define SDL_CODE_FRAME 0 void sdl_init(int width, int height, bool fullscreen); void sdl_loop(); +SDL_mutex *mutex; + #endif /* HAVE_SDL */ diff --git a/src/video/sdl.c b/src/video/sdl.c index 1e9d003..561edcd 100644 --- a/src/video/sdl.c +++ b/src/video/sdl.c @@ -18,6 +18,7 @@ */ #include "../video.h" +#include "../sdl.h" #include "ffmpeg.h" #include "limelight-common/Limelight.h" @@ -29,14 +30,9 @@ #define DECODER_BUFFER_SIZE 92*1024 -static SDL_Window *window; -static SDL_Renderer *renderer; -static SDL_Texture *bmp = NULL; static int screen_width, screen_height; static char* ffmpeg_buffer; -static bool fullscreen; - static void sdl_setup(int width, int height, int redrawRate, void* context, int drFlags) { int avc_flags = SLICE_THREADING; if (ffmpeg_init(width, height, avc_flags, 2) < 0) { @@ -50,8 +46,6 @@ static void sdl_setup(int width, int height, int redrawRate, void* context, int exit(1); } - fullscreen = (drFlags & DISPLAY_FULLSCREEN) == DISPLAY_FULLSCREEN; - fullscreen = false; screen_width = width; screen_height = height; } @@ -61,26 +55,6 @@ static void sdl_cleanup() { } static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) { - if (window == NULL) { - window = SDL_CreateWindow("Moonlight", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height, SDL_WINDOW_OPENGL | (fullscreen?SDL_WINDOW_FULLSCREEN:0)); - if(!window) { - fprintf(stderr, "SDL: could not create window - exiting\n"); - exit(1); - } - SDL_SetRelativeMouseMode(SDL_TRUE); - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (!renderer) { - printf("SDL_CreateRenderer failed: %s\n", SDL_GetError()); - exit(1); - } - - bmp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height); - if (!bmp) { - fprintf(stderr, "SDL: could not create texture - exiting\n"); - exit(1); - } - } - if (decodeUnit->fullLength < DECODER_BUFFER_SIZE) { PLENTRY entry = decodeUnit->bufferList; int length = 0; @@ -90,15 +64,22 @@ static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) { entry = entry->next; } - int ret = ffmpeg_decode(ffmpeg_buffer, length); - if (ret == 1) { - AVFrame* frame = ffmpeg_get_frame(); + if (SDL_LockMutex(mutex) == 0) { + int ret = ffmpeg_decode(ffmpeg_buffer, length); + if (ret == 1) { + AVFrame* frame = ffmpeg_get_frame(); - SDL_UpdateYUVTexture(bmp, NULL, frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]); - SDL_RenderClear(renderer); - SDL_RenderCopy(renderer, bmp, NULL, NULL); - SDL_RenderPresent(renderer); - } + SDL_Event event; + event.type = SDL_USEREVENT; + event.user.code = SDL_CODE_FRAME; + event.user.data1 = &frame->data; + event.user.data2 = &frame->linesize; + SDL_PushEvent(&event); + } + + SDL_UnlockMutex(mutex); + } else + fprintf(stderr, "Couldn't lock mutex\n"); } else { fprintf(stderr, "Video decode buffer too small"); exit(1);