diff --git a/CMakeLists.txt b/CMakeLists.txt index dee9db7..b8f4993 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(EVDEV REQUIRED libevdev) pkg_check_modules(AVAHI REQUIRED avahi-client) pkg_check_modules(UDEV REQUIRED libudev) -pkg_check_modules(SDL sdl) +pkg_check_modules(SDL sdl2) pkg_check_modules(AVCODEC libavcodec) pkg_check_modules(AVUTIL libavutil) pkg_check_modules(SWSCALE libswscale) diff --git a/src/video/ffmpeg.c b/src/video/ffmpeg.c index 29087f5..cfd6f35 100644 --- a/src/video/ffmpeg.c +++ b/src/video/ffmpeg.c @@ -120,17 +120,21 @@ void ffmpeg_destroy(void) { } } -int ffmpeg_draw_frame(AVPicture pict) { - int err = sws_scale(scaler_ctx, (const uint8_t* const*) dec_frame->data, dec_frame->linesize, 0, decoder_ctx->height, pict.data, pict.linesize); +int ffmpeg_draw_frame(AVFrame *pict) { + int err = sws_scale(scaler_ctx, (const uint8_t* const*) dec_frame->data, dec_frame->linesize, 0, decoder_ctx->height, pict->data, pict->linesize); if (err != decoder_ctx->height) { - printf("Scaling failed"); + fprintf(stderr, "Scaling failed\n"); return 0; } return 1; } +AVFrame* ffmpeg_get_frame() { + return dec_frame; +} + // packets must be decoded in order // indata must be inlen + FF_INPUT_BUFFER_PADDING_SIZE in length int ffmpeg_decode(unsigned char* indata, int inlen) { @@ -144,7 +148,7 @@ int ffmpeg_decode(unsigned char* indata, int inlen) { got_pic = 0; err = avcodec_decode_video2(decoder_ctx, dec_frame, &got_pic, &pkt); if (err < 0) { - printf("Decode failed"); + fprintf(stderr, "Decode failed\n"); got_pic = 0; break; } @@ -153,8 +157,9 @@ int ffmpeg_decode(unsigned char* indata, int inlen) { pkt.data += err; } - if (got_pic) + if (got_pic) { return 1; + } return err < 0 ? err : 0; } diff --git a/src/video/ffmpeg.h b/src/video/ffmpeg.h index 160eab1..0afefca 100644 --- a/src/video/ffmpeg.h +++ b/src/video/ffmpeg.h @@ -35,5 +35,6 @@ int ffmpeg_init(int width, int height, int perf_lvl, int thread_count); void ffmpeg_destroy(void); -int ffmpeg_draw_frame(AVPicture pict); +int ffmpeg_draw_frame(AVFrame *pict); +AVFrame* ffmpeg_get_frame(); int ffmpeg_decode(unsigned char* indata, int inlen); diff --git a/src/video/sdl.c b/src/video/sdl.c index c00308e..b33b711 100644 --- a/src/video/sdl.c +++ b/src/video/sdl.c @@ -26,25 +26,13 @@ #define DECODER_BUFFER_SIZE 92*1024 -static SDL_Surface *screen; -static SDL_Overlay *bmp = NULL; +static SDL_Window *window; +static SDL_Renderer *renderer; +static SDL_Texture *bmp = NULL; static int screen_width, screen_height; static char* ffmpeg_buffer; static void sdl_setup(int width, int height, int redrawRate, void* context, int drFlags) { - if(SDL_Init(SDL_INIT_VIDEO)) { - fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); - exit(1); - } - - screen = SDL_SetVideoMode(width, height, 0, 0); - if(!screen) { - fprintf(stderr, "SDL: could not set video mode - exiting\n"); - exit(1); - } - - bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen); - int avc_flags = FAST_BILINEAR_FILTERING; if (ffmpeg_init(width, height, 2, avc_flags) < 0) { fprintf(stderr, "Couldn't initialize video decoding\n"); @@ -66,6 +54,31 @@ static void sdl_cleanup() { } static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) { + if (window == NULL) { + if(SDL_Init(SDL_INIT_VIDEO)) { + fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); + exit(1); + } + + window = SDL_CreateWindow("Moonlight", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height, 0); + if(!window) { + fprintf(stderr, "SDL: could not create window - exiting\n"); + exit(1); + } + + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE); + if (!renderer) { + fprintf(stderr, "SDL: could not create renderer - exiting\n"); + exit(1); + } + + bmp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_TARGET, 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; @@ -77,32 +90,20 @@ static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) { int ret = ffmpeg_decode(ffmpeg_buffer, length); if (ret == 1) { - SDL_LockYUVOverlay(bmp); + AVFrame* frame = ffmpeg_get_frame(); - AVPicture pict; - pict.data[0] = bmp->pixels[0]; - pict.data[1] = bmp->pixels[2]; - pict.data[2] = bmp->pixels[1]; - - pict.linesize[0] = bmp->pitches[0]; - pict.linesize[1] = bmp->pitches[2]; - pict.linesize[2] = bmp->pitches[1]; - - ffmpeg_draw_frame(pict); - - SDL_UnlockYUVOverlay(bmp); - - SDL_Rect rect; - rect.x = 0; - rect.y = 0; - rect.w = screen_width; - rect.h = screen_height; - SDL_DisplayYUVOverlay(bmp, &rect); + 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); } } else { fprintf(stderr, "Video decode buffer too small"); exit(1); } + + SDL_Event event; + SDL_PollEvent(&event); return DR_OK; }