mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2025-07-01 23:35:47 +00:00
Add X11 VAAPI decoder
This commit is contained in:
parent
2c35e70cc0
commit
4415836579
@ -21,20 +21,26 @@ pkg_check_modules(SDL sdl2>=2.0.4)
|
||||
pkg_check_modules(AVCODEC libavcodec)
|
||||
pkg_check_modules(AVUTIL libavutil)
|
||||
pkg_check_modules(XLIB x11)
|
||||
pkg_check_modules(LIBVA vdpau)
|
||||
pkg_check_modules(VDPAU vdpau)
|
||||
pkg_check_modules(LIBVA libva)
|
||||
pkg_check_modules(LIBVA_X11 libva-x11)
|
||||
pkg_check_modules(PULSE libpulse-simple)
|
||||
pkg_check_modules(CEC libcec>=3.0.0)
|
||||
pkg_check_modules(EGL egl)
|
||||
pkg_check_modules(GLES glesv2)
|
||||
|
||||
set(VDPAU_FOUND FALSE)
|
||||
set(VDPAU_ACCEL_FOUND FALSE)
|
||||
set(VA_ACCEL_FOUND FALSE)
|
||||
set(SOFTWARE_FOUND FALSE)
|
||||
|
||||
if(AVCODEC_FOUND AND AVUTIL_FOUND)
|
||||
if(EGL_FOUND AND GLES_FOUND AND XLIB_FOUND)
|
||||
set(X11_FOUND TRUE)
|
||||
if(XLIB_FOUND AND LIBVA_FOUND)
|
||||
set(VDPAU_FOUND TRUE)
|
||||
if(VDPAU_FOUND)
|
||||
set(VDPAU_ACCEL_FOUND TRUE)
|
||||
endif()
|
||||
if (LIBVA_FOUND AND LIBVA_X11_FOUND)
|
||||
set(VA_ACCEL_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
if(SDL_FOUND OR X11_FOUND)
|
||||
@ -61,11 +67,16 @@ if (SOFTWARE_FOUND)
|
||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_X11)
|
||||
list(APPEND MOONLIGHT_OPTIONS X11)
|
||||
endif()
|
||||
if(VDPAU_FOUND)
|
||||
if(VDPAU_ACCEL_FOUND)
|
||||
list(APPEND SRC_LIST ./src/video/ffmpeg_vdpau.c)
|
||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VDPAU)
|
||||
list(APPEND MOONLIGHT_OPTIONS VDPAU)
|
||||
endif()
|
||||
if(VA_ACCEL_FOUND)
|
||||
list(APPEND SRC_LIST ./src/video/ffmpeg_vaapi.c)
|
||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VAAPI)
|
||||
list(APPEND MOONLIGHT_OPTIONS VAAPI)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (AMLOGIC_FOUND OR BROADCOM_FOUND OR FREESCALE_FOUND OR X11_FOUND)
|
||||
@ -147,9 +158,13 @@ endif()
|
||||
if (SOFTWARE_FOUND)
|
||||
target_include_directories(moonlight PRIVATE ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS})
|
||||
target_link_libraries(moonlight ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES})
|
||||
if(VDPAU_FOUND)
|
||||
target_include_directories(moonlight PRIVATE ${XLIB_INCLUDE_DIRS} ${LIBVA_INCLUDE_DIRS})
|
||||
target_link_libraries(moonlight ${XLIB_LIBRARIES} ${LIBVA_LIBRARIES})
|
||||
if(VDPAU_ACCEL_FOUND)
|
||||
target_include_directories(moonlight PRIVATE ${VDPAU_INCLUDE_DIRS})
|
||||
target_link_libraries(moonlight ${VDPAU_LIBRARIES})
|
||||
endif()
|
||||
if(VA_ACCEL_FOUND)
|
||||
target_include_directories(moonlight PRIVATE ${LIBVA_INCLUDE_DIRS} ${LIBVA_X11_INCLUDE_DIRS})
|
||||
target_link_libraries(moonlight ${LIBVA_LIBRARIES} ${LIBVA_X11_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -60,10 +60,17 @@ enum platform platform_check(char* name) {
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
if (std || strcmp(name, "x11") == 0 || strcmp(name, "x11_vdpau") == 0) {
|
||||
int x11 = x11_init(strcmp(name, "x11") != 0);
|
||||
bool x11 = strcmp(name, "x11") == 0;
|
||||
bool vdpau = strcmp(name, "x11_vdpau") == 0;
|
||||
bool vaapi = strcmp(name, "x11_vaapi") == 0;
|
||||
if (std || x11 || vdpau || vaapi) {
|
||||
int init = x11_init(std || vdpau, std || vaapi);
|
||||
#ifdef HAVE_VAAPI
|
||||
if (init == INIT_VAAPI)
|
||||
return X11_VAAPI;
|
||||
#endif
|
||||
#ifdef HAVE_VDPAU
|
||||
if (strcmp(name, "x11") != 0 && x11 == 0)
|
||||
if (init == INIT_VDPAU)
|
||||
return X11_VDPAU;
|
||||
#endif
|
||||
return X11;
|
||||
@ -182,6 +189,8 @@ char* platform_name(enum platform system) {
|
||||
return "AMLogic VPU";
|
||||
case X11:
|
||||
return "X Window System (software decoding)";
|
||||
case X11_VAAPI:
|
||||
return "X Window System (VAAPI)";
|
||||
case X11_VDPAU:
|
||||
return "X Window System (VDPAU)";
|
||||
case SDL:
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#define IS_EMBEDDED(SYSTEM) SYSTEM != SDL
|
||||
|
||||
enum platform { NONE, SDL, X11, X11_VDPAU, PI, IMX, AML, FAKE };
|
||||
enum platform { NONE, SDL, X11, X11_VDPAU, X11_VAAPI, PI, IMX, AML, FAKE };
|
||||
|
||||
enum platform platform_check(char*);
|
||||
PDECODER_RENDERER_CALLBACKS platform_get_video(enum platform system);
|
||||
|
@ -22,6 +22,9 @@
|
||||
#ifdef HAVE_VDPAU
|
||||
#include "ffmpeg_vdpau.h"
|
||||
#endif
|
||||
#ifdef HAVE_VAAPI
|
||||
#include "ffmpeg_vaapi.h"
|
||||
#endif
|
||||
|
||||
#include <Limelight.h>
|
||||
|
||||
@ -53,8 +56,7 @@ int ffmpeg_init(int videoFormat, int width, int height, int perf_lvl, int buffer
|
||||
|
||||
av_init_packet(&pkt);
|
||||
|
||||
#ifdef HAVE_VDPAU
|
||||
if (perf_lvl & HARDWARE_ACCELERATION) {
|
||||
if (perf_lvl & VDPAU_ACCELERATION) {
|
||||
switch (videoFormat) {
|
||||
case VIDEO_FORMAT_H264:
|
||||
decoder = avcodec_find_decoder_by_name("h264_vdpau");
|
||||
@ -64,13 +66,9 @@ int ffmpeg_init(int videoFormat, int width, int height, int perf_lvl, int buffer
|
||||
break;
|
||||
}
|
||||
|
||||
if (decoder != NULL)
|
||||
ffmpeg_decoder = VDPAU;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (decoder == NULL) {
|
||||
ffmpeg_decoder = SOFTWARE;
|
||||
ffmpeg_decoder = VDPAU;
|
||||
} else {
|
||||
ffmpeg_decoder = perf_lvl & VAAPI_ACCELERATION ? VAAPI : SOFTWARE;
|
||||
switch (videoFormat) {
|
||||
case VIDEO_FORMAT_H264:
|
||||
decoder = avcodec_find_decoder_by_name("h264");
|
||||
@ -79,10 +77,11 @@ int ffmpeg_init(int videoFormat, int width, int height, int perf_lvl, int buffer
|
||||
decoder = avcodec_find_decoder_by_name("hevc");
|
||||
break;
|
||||
}
|
||||
if (decoder == NULL) {
|
||||
printf("Couldn't find decoder\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (decoder == NULL) {
|
||||
printf("Couldn't find decoder\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
decoder_ctx = avcodec_alloc_context3(decoder);
|
||||
@ -131,6 +130,11 @@ int ffmpeg_init(int videoFormat, int width, int height, int perf_lvl, int buffer
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_VAAPI
|
||||
if (ffmpeg_decoder == VAAPI)
|
||||
vaapi_init(decoder_ctx);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VDPAU
|
||||
if (ffmpeg_decoder == VDPAU)
|
||||
vdpau_init(decoder_ctx, width, height);
|
||||
|
@ -34,9 +34,10 @@
|
||||
// Uses a faster bilinear filtering with lower image quality
|
||||
#define FAST_BILINEAR_FILTERING 0x20
|
||||
// Uses hardware acceleration
|
||||
#define HARDWARE_ACCELERATION 0x40
|
||||
#define VDPAU_ACCELERATION 0x40
|
||||
#define VAAPI_ACCELERATION 0x80
|
||||
|
||||
enum decoders {SOFTWARE, VDPAU};
|
||||
enum decoders {SOFTWARE, VDPAU, VAAPI};
|
||||
extern enum decoders ffmpeg_decoder;
|
||||
|
||||
int ffmpeg_init(int videoFormat, int width, int height, int perf_lvl, int buffer_count, int thread_count);
|
||||
|
75
src/video/ffmpeg_vaapi.c
Normal file
75
src/video/ffmpeg_vaapi.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Moonlight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <va/va.h>
|
||||
#include <va/va_x11.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavutil/hwcontext_vaapi.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#define MAX_SURFACES 16
|
||||
|
||||
static AVBufferRef* device_ref;
|
||||
|
||||
static enum AVPixelFormat va_get_format(AVCodecContext* context, const enum AVPixelFormat* pixel_format) {
|
||||
AVBufferRef* hw_ctx = av_hwframe_ctx_alloc(device_ref);
|
||||
if (hw_ctx == NULL) {
|
||||
fprintf(stderr, "Failed to initialize Vaapi buffer\n");
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
AVHWFramesContext* fr_ctx = (AVHWFramesContext*) hw_ctx->data;
|
||||
fr_ctx->format = AV_PIX_FMT_VAAPI;
|
||||
fr_ctx->sw_format = AV_PIX_FMT_NV12;
|
||||
fr_ctx->width = context->coded_width;
|
||||
fr_ctx->height = context->coded_height;
|
||||
fr_ctx->initial_pool_size = MAX_SURFACES + 1;
|
||||
|
||||
if (av_hwframe_ctx_init(hw_ctx) < 0) {
|
||||
fprintf(stderr, "Failed to initialize VAAPI frame context");
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
context->pix_fmt = AV_PIX_FMT_VAAPI;
|
||||
context->hw_device_ctx = device_ref;
|
||||
context->hw_frames_ctx = hw_ctx;
|
||||
context->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
|
||||
return AV_PIX_FMT_VAAPI;
|
||||
}
|
||||
|
||||
static int va_get_buffer(AVCodecContext* context, AVFrame* frame, int flags) {
|
||||
return av_hwframe_get_buffer(context->hw_frames_ctx, frame, 0);
|
||||
}
|
||||
|
||||
int vaapi_init_lib() {
|
||||
return av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_VAAPI, ":0", NULL, 0);
|
||||
}
|
||||
|
||||
int vaapi_init(AVCodecContext* decoder_ctx) {
|
||||
decoder_ctx->get_format = va_get_format;
|
||||
decoder_ctx->get_buffer2 = va_get_buffer;
|
||||
}
|
||||
|
||||
void vaapi_queue(AVFrame* dec_frame, Window win, int width, int height) {
|
||||
VASurfaceID surface = (VASurfaceID)(uintptr_t)dec_frame->data[3];
|
||||
AVHWDeviceContext* device = (AVHWDeviceContext*) device_ref->data;
|
||||
AVVAAPIDeviceContext *va_ctx = device->hwctx;
|
||||
vaPutSurface(va_ctx->display, surface, win, 0, 0, dec_frame->width, dec_frame->height, 0, 0, width, height, NULL, 0, 0);
|
||||
}
|
24
src/video/ffmpeg_vaapi.h
Normal file
24
src/video/ffmpeg_vaapi.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Moonlight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <va/va.h>
|
||||
|
||||
int vaapi_init_lib();
|
||||
int vaapi_init(AVCodecContext* decoder_ctx);
|
||||
void vaapi_queue(AVFrame* dec_frame, Window win, int width, int height);
|
@ -22,11 +22,19 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#define DISPLAY_FULLSCREEN 1
|
||||
#define ENABLE_HARDWARE_ACCELERATION 2
|
||||
#define ENABLE_HARDWARE_ACCELERATION_1 2
|
||||
#define ENABLE_HARDWARE_ACCELERATION_2 4
|
||||
|
||||
#define INIT_EGL 1
|
||||
#define INIT_VDPAU 2
|
||||
#define INIT_VAAPI 3
|
||||
|
||||
#ifdef HAVE_X11
|
||||
int x11_init(bool vdpau);
|
||||
int x11_init(bool vdpau, bool vaapi);
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11;
|
||||
#ifdef HAVE_VAAPI
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vaapi;
|
||||
#endif
|
||||
#ifdef HAVE_VDPAU
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vdpau;
|
||||
#endif
|
||||
|
@ -23,6 +23,9 @@
|
||||
#ifdef HAVE_VDPAU
|
||||
#include "ffmpeg_vdpau.h"
|
||||
#endif
|
||||
#ifdef HAVE_VAAPI
|
||||
#include "ffmpeg_vaapi.h"
|
||||
#endif
|
||||
|
||||
#include "../input/x11.h"
|
||||
#include "../loop.h"
|
||||
@ -36,13 +39,19 @@
|
||||
#include <poll.h>
|
||||
|
||||
#define DECODER_BUFFER_SIZE 92*1024
|
||||
#define X11_VDPAU_ACCELERATION ENABLE_HARDWARE_ACCELERATION_1
|
||||
#define X11_VAAPI_ACCELERATION ENABLE_HARDWARE_ACCELERATION_2
|
||||
|
||||
static char* ffmpeg_buffer = NULL;
|
||||
|
||||
static Display *display = NULL;
|
||||
static Window window;
|
||||
|
||||
static int pipefd[2];
|
||||
|
||||
static int display_width;
|
||||
static int display_height;
|
||||
|
||||
static int frame_handle(int pipefd) {
|
||||
AVFrame* frame = NULL;
|
||||
while (read(pipefd, &frame, sizeof(void*)) > 0);
|
||||
@ -52,18 +61,23 @@ static int frame_handle(int pipefd) {
|
||||
return LOOP_OK;
|
||||
}
|
||||
|
||||
int x11_init(bool vdpau) {
|
||||
int x11_init(bool vdpau, bool vaapi) {
|
||||
XInitThreads();
|
||||
display = XOpenDisplay(NULL);
|
||||
if (!display)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_VDPAU
|
||||
if (vdpau && vdpau_init_lib(display) != 0)
|
||||
return -2;
|
||||
#ifdef HAVE_VAAPI
|
||||
if (vaapi && vaapi_init_lib(display) == 0)
|
||||
return INIT_VAAPI;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
#ifdef HAVE_VDPAU
|
||||
if (vdpau && vdpau_init_lib(display) == 0)
|
||||
return INIT_VDPAU;
|
||||
#endif
|
||||
|
||||
return INIT_EGL;
|
||||
}
|
||||
|
||||
int x11_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
@ -78,8 +92,6 @@ int x11_setup(int videoFormat, int width, int height, int redrawRate, void* cont
|
||||
return -1;
|
||||
}
|
||||
|
||||
int display_width;
|
||||
int display_height;
|
||||
if (drFlags & DISPLAY_FULLSCREEN) {
|
||||
Screen* screen = DefaultScreenOfDisplay(display);
|
||||
display_width = WidthOfScreen(screen);
|
||||
@ -91,7 +103,7 @@ int x11_setup(int videoFormat, int width, int height, int redrawRate, void* cont
|
||||
|
||||
Window root = DefaultRootWindow(display);
|
||||
XSetWindowAttributes winattr = { .event_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask };
|
||||
Window window = XCreateWindow(display, root, 0, 0, display_width, display_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &winattr);
|
||||
window = XCreateWindow(display, root, 0, 0, display_width, display_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &winattr);
|
||||
XMapWindow(display, window);
|
||||
XStoreName(display, window, "Moonlight");
|
||||
|
||||
@ -113,10 +125,10 @@ int x11_setup(int videoFormat, int width, int height, int redrawRate, void* cont
|
||||
XFlush(display);
|
||||
|
||||
int avc_flags = SLICE_THREADING;
|
||||
#ifdef HAVE_VDPAU
|
||||
if (drFlags & ENABLE_HARDWARE_ACCELERATION)
|
||||
avc_flags |= HARDWARE_ACCELERATION;
|
||||
#endif
|
||||
if (drFlags & X11_VDPAU_ACCELERATION)
|
||||
avc_flags |= VDPAU_ACCELERATION;
|
||||
else if (drFlags & X11_VAAPI_ACCELERATION)
|
||||
avc_flags |= VAAPI_ACCELERATION;
|
||||
|
||||
if (ffmpeg_init(videoFormat, width, height, avc_flags, 2, 2) < 0) {
|
||||
fprintf(stderr, "Couldn't initialize video decoding\n");
|
||||
@ -143,7 +155,11 @@ int x11_setup(int videoFormat, int width, int height, int redrawRate, void* cont
|
||||
}
|
||||
|
||||
int x11_setup_vdpau(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
return x11_setup(videoFormat, width, height, redrawRate, context, drFlags | ENABLE_HARDWARE_ACCELERATION);
|
||||
return x11_setup(videoFormat, width, height, redrawRate, context, drFlags | X11_VDPAU_ACCELERATION);
|
||||
}
|
||||
|
||||
int x11_setup_vaapi(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
return x11_setup(videoFormat, width, height, redrawRate, context, drFlags | X11_VAAPI_ACCELERATION);
|
||||
}
|
||||
|
||||
void x11_cleanup() {
|
||||
@ -167,6 +183,8 @@ int x11_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
write(pipefd[1], &frame, sizeof(void*));
|
||||
else if (ffmpeg_decoder == VDPAU)
|
||||
vdpau_queue(frame);
|
||||
else if (ffmpeg_decoder == VAAPI)
|
||||
vaapi_queue(frame, window, display_width, display_height);
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,3 +204,10 @@ DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vdpau = {
|
||||
.submitDecodeUnit = x11_submit_decode_unit,
|
||||
.capabilities = CAPABILITY_DIRECT_SUBMIT,
|
||||
};
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vaapi = {
|
||||
.setup = x11_setup_vaapi,
|
||||
.cleanup = x11_cleanup,
|
||||
.submitDecodeUnit = x11_submit_decode_unit,
|
||||
.capabilities = CAPABILITY_SLICES_PER_FRAME(4) | CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC | CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC | CAPABILITY_DIRECT_SUBMIT,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user