mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2026-04-18 14:30:17 +00:00
Merge tag 'v2.4.1' into raspbian/jessie
This commit is contained in:
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -2,9 +2,11 @@ Please provide the following info.
|
|||||||
|
|
||||||
**_NVidia Geforce Experience version:_**
|
**_NVidia Geforce Experience version:_**
|
||||||
**Moonlight Embedded version:**
|
**Moonlight Embedded version:**
|
||||||
|
**Moonlight Embedded source:** _repository/included in distribution/compiled from source/..._
|
||||||
**Moonlight Embedded running on:** _Raspberry Pi/Cubox-i/Hummingboard/Other linux device/..._
|
**Moonlight Embedded running on:** _Raspberry Pi/Cubox-i/Hummingboard/Other linux device/..._
|
||||||
|
**Moonlight Embedded running on distribution:** _Arch Linux/Raspbian/OpenELEC/..._
|
||||||
|
|
||||||
**Output of Moonlight Embedded:**
|
**Verbose output `-verbose` of Moonlight Embedded:**
|
||||||
|
|
||||||
**What is the expected result?**
|
**What is the expected result?**
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
project(moonlight-embedded VERSION 2.4.0 LANGUAGES C)
|
project(moonlight-embedded VERSION 2.4.1 LANGUAGES C)
|
||||||
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
|
include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
|
||||||
|
|
||||||
@@ -21,20 +21,26 @@ pkg_check_modules(SDL sdl2>=2.0.4)
|
|||||||
pkg_check_modules(AVCODEC libavcodec)
|
pkg_check_modules(AVCODEC libavcodec)
|
||||||
pkg_check_modules(AVUTIL libavutil)
|
pkg_check_modules(AVUTIL libavutil)
|
||||||
pkg_check_modules(XLIB x11)
|
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(PULSE libpulse-simple)
|
||||||
pkg_check_modules(CEC libcec>=3.0.0)
|
pkg_check_modules(CEC libcec>=3.0.0)
|
||||||
pkg_check_modules(EGL egl)
|
pkg_check_modules(EGL egl)
|
||||||
pkg_check_modules(GLES glesv2)
|
pkg_check_modules(GLES glesv2)
|
||||||
|
|
||||||
set(VDPAU_FOUND FALSE)
|
set(VDPAU_ACCEL_FOUND FALSE)
|
||||||
|
set(VA_ACCEL_FOUND FALSE)
|
||||||
set(SOFTWARE_FOUND FALSE)
|
set(SOFTWARE_FOUND FALSE)
|
||||||
|
|
||||||
if(AVCODEC_FOUND AND AVUTIL_FOUND)
|
if(AVCODEC_FOUND AND AVUTIL_FOUND)
|
||||||
if(EGL_FOUND AND GLES_FOUND AND XLIB_FOUND)
|
if(EGL_FOUND AND GLES_FOUND AND XLIB_FOUND)
|
||||||
set(X11_FOUND TRUE)
|
set(X11_FOUND TRUE)
|
||||||
if(XLIB_FOUND AND LIBVA_FOUND)
|
if(VDPAU_FOUND)
|
||||||
set(VDPAU_FOUND TRUE)
|
set(VDPAU_ACCEL_FOUND TRUE)
|
||||||
|
endif()
|
||||||
|
if (LIBVA_FOUND AND LIBVA_X11_FOUND)
|
||||||
|
set(VA_ACCEL_FOUND TRUE)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(SDL_FOUND OR X11_FOUND)
|
if(SDL_FOUND OR X11_FOUND)
|
||||||
@@ -61,11 +67,16 @@ if (SOFTWARE_FOUND)
|
|||||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_X11)
|
list(APPEND MOONLIGHT_DEFINITIONS HAVE_X11)
|
||||||
list(APPEND MOONLIGHT_OPTIONS X11)
|
list(APPEND MOONLIGHT_OPTIONS X11)
|
||||||
endif()
|
endif()
|
||||||
if(VDPAU_FOUND)
|
if(VDPAU_ACCEL_FOUND)
|
||||||
list(APPEND SRC_LIST ./src/video/ffmpeg_vdpau.c)
|
list(APPEND SRC_LIST ./src/video/ffmpeg_vdpau.c)
|
||||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VDPAU)
|
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VDPAU)
|
||||||
list(APPEND MOONLIGHT_OPTIONS VDPAU)
|
list(APPEND MOONLIGHT_OPTIONS VDPAU)
|
||||||
endif()
|
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()
|
endif()
|
||||||
|
|
||||||
if (AMLOGIC_FOUND OR BROADCOM_FOUND OR FREESCALE_FOUND OR X11_FOUND)
|
if (AMLOGIC_FOUND OR BROADCOM_FOUND OR FREESCALE_FOUND OR X11_FOUND)
|
||||||
@@ -147,9 +158,13 @@ endif()
|
|||||||
if (SOFTWARE_FOUND)
|
if (SOFTWARE_FOUND)
|
||||||
target_include_directories(moonlight PRIVATE ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS})
|
target_include_directories(moonlight PRIVATE ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS})
|
||||||
target_link_libraries(moonlight ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES})
|
target_link_libraries(moonlight ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES})
|
||||||
if(VDPAU_FOUND)
|
if(VDPAU_ACCEL_FOUND)
|
||||||
target_include_directories(moonlight PRIVATE ${XLIB_INCLUDE_DIRS} ${LIBVA_INCLUDE_DIRS})
|
target_include_directories(moonlight PRIVATE ${VDPAU_INCLUDE_DIRS})
|
||||||
target_link_libraries(moonlight ${XLIB_LIBRARIES} ${LIBVA_LIBRARIES})
|
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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
set(SO_VERSION 1)
|
set(SO_VERSION 2)
|
||||||
|
|
||||||
find_package(LibUUID REQUIRED)
|
find_package(LibUUID REQUIRED)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
find_package(CURL REQUIRED)
|
find_package(CURL REQUIRED)
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL 1.0.2 REQUIRED)
|
||||||
find_package(EXPAT REQUIRED)
|
find_package(EXPAT REQUIRED)
|
||||||
|
|
||||||
pkg_check_modules(AVAHI REQUIRED avahi-client)
|
pkg_check_modules(AVAHI REQUIRED avahi-client)
|
||||||
@@ -16,6 +16,7 @@ aux_source_directory(../third_party/moonlight-common-c/src MOONLIGHT_COMMON_SRC_
|
|||||||
aux_source_directory(../third_party/moonlight-common-c/reedsolomon MOONLIGHT_COMMON_SRC_LIST)
|
aux_source_directory(../third_party/moonlight-common-c/reedsolomon MOONLIGHT_COMMON_SRC_LIST)
|
||||||
|
|
||||||
add_library(moonlight-common SHARED ${MOONLIGHT_COMMON_SRC_LIST})
|
add_library(moonlight-common SHARED ${MOONLIGHT_COMMON_SRC_LIST})
|
||||||
|
set_property(TARGET moonlight-common PROPERTY C_STANDARD 99)
|
||||||
|
|
||||||
add_library(gamestream SHARED ${GAMESTREAM_SRC_LIST})
|
add_library(gamestream SHARED ${GAMESTREAM_SRC_LIST})
|
||||||
set_property(TARGET gamestream PROPERTY C_STANDARD 99)
|
set_property(TARGET gamestream PROPERTY C_STANDARD 99)
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ static int load_server_status(PSERVER_DATA server) {
|
|||||||
i++;
|
i++;
|
||||||
} while (ret != GS_OK && i < 2);
|
} while (ret != GS_OK && i < 2);
|
||||||
|
|
||||||
if (ret == GS_OK) {
|
if (ret == GS_OK && !server->unsupported) {
|
||||||
if (server->serverMajorVersion > MAX_SUPPORTED_GFE_VERSION) {
|
if (server->serverMajorVersion > MAX_SUPPORTED_GFE_VERSION) {
|
||||||
gs_error = "Ensure you're running the latest version of Moonlight Embedded or downgrade GeForce Experience and try again";
|
gs_error = "Ensure you're running the latest version of Moonlight Embedded or downgrade GeForce Experience and try again";
|
||||||
ret = GS_UNSUPPORTED_VERSION;
|
ret = GS_UNSUPPORTED_VERSION;
|
||||||
@@ -646,7 +646,7 @@ int gs_start_app(PSERVER_DATA server, STREAM_CONFIGURATION *config, int appId, b
|
|||||||
mode = mode->next;
|
mode = mode->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!correct_mode)
|
if (!correct_mode && !server->unsupported)
|
||||||
return GS_NOT_SUPPORTED_MODE;
|
return GS_NOT_SUPPORTED_MODE;
|
||||||
|
|
||||||
if (config->height >= 2160 && !server->supports4K)
|
if (config->height >= 2160 && !server->supports4K)
|
||||||
@@ -727,7 +727,7 @@ int gs_quit_app(PSERVER_DATA server) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gs_init(PSERVER_DATA server, char *address, const char *keyDirectory, int log_level) {
|
int gs_init(PSERVER_DATA server, char *address, const char *keyDirectory, int log_level, bool unsupported) {
|
||||||
mkdirtree(keyDirectory);
|
mkdirtree(keyDirectory);
|
||||||
if (load_unique_id(keyDirectory) != GS_OK)
|
if (load_unique_id(keyDirectory) != GS_OK)
|
||||||
return GS_FAILED;
|
return GS_FAILED;
|
||||||
@@ -739,5 +739,6 @@ int gs_init(PSERVER_DATA server, char *address, const char *keyDirectory, int lo
|
|||||||
|
|
||||||
LiInitializeServerInformation(&server->serverInfo);
|
LiInitializeServerInformation(&server->serverInfo);
|
||||||
server->serverInfo.address = address;
|
server->serverInfo.address = address;
|
||||||
|
server->unsupported = unsupported;
|
||||||
return load_server_status(server);
|
return load_server_status(server);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ typedef struct _SERVER_DATA {
|
|||||||
char* gpuType;
|
char* gpuType;
|
||||||
bool paired;
|
bool paired;
|
||||||
bool supports4K;
|
bool supports4K;
|
||||||
|
bool unsupported;
|
||||||
int currentGame;
|
int currentGame;
|
||||||
int serverMajorVersion;
|
int serverMajorVersion;
|
||||||
char* gsVersion;
|
char* gsVersion;
|
||||||
@@ -40,7 +41,7 @@ typedef struct _SERVER_DATA {
|
|||||||
SERVER_INFORMATION serverInfo;
|
SERVER_INFORMATION serverInfo;
|
||||||
} SERVER_DATA, *PSERVER_DATA;
|
} SERVER_DATA, *PSERVER_DATA;
|
||||||
|
|
||||||
int gs_init(PSERVER_DATA server, char* address, const char *keyDirectory, int logLevel);
|
int gs_init(PSERVER_DATA server, char* address, const char *keyDirectory, int logLevel, bool unsupported);
|
||||||
int gs_start_app(PSERVER_DATA server, PSTREAM_CONFIGURATION config, int appId, bool sops, bool localaudio);
|
int gs_start_app(PSERVER_DATA server, PSTREAM_CONFIGURATION config, int appId, bool sops, bool localaudio);
|
||||||
int gs_applist(PSERVER_DATA server, PAPP_LIST *app_list);
|
int gs_applist(PSERVER_DATA server, PAPP_LIST *app_list);
|
||||||
int gs_unpair(PSERVER_DATA server);
|
int gs_unpair(PSERVER_DATA server);
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ static void parse_argument(int c, char* value, PCONFIGURATION config) {
|
|||||||
config->codec = CODEC_HEVC;
|
config->codec = CODEC_HEVC;
|
||||||
break;
|
break;
|
||||||
case 'y':
|
case 'y':
|
||||||
config->unsupported_version = true;
|
config->unsupported = true;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
config->debug_level = 1;
|
config->debug_level = 1;
|
||||||
@@ -307,7 +307,7 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) {
|
|||||||
config->sops = true;
|
config->sops = true;
|
||||||
config->localaudio = false;
|
config->localaudio = false;
|
||||||
config->fullscreen = true;
|
config->fullscreen = true;
|
||||||
config->unsupported_version = false;
|
config->unsupported = false;
|
||||||
config->codec = CODEC_UNSPECIFIED;
|
config->codec = CODEC_UNSPECIFIED;
|
||||||
|
|
||||||
config->inputsCount = 0;
|
config->inputsCount = 0;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ typedef struct _CONFIGURATION {
|
|||||||
bool sops;
|
bool sops;
|
||||||
bool localaudio;
|
bool localaudio;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool unsupported_version;
|
bool unsupported;
|
||||||
char* inputs[MAX_INPUTS];
|
char* inputs[MAX_INPUTS];
|
||||||
int inputsCount;
|
int inputsCount;
|
||||||
enum codecs codec;
|
enum codecs codec;
|
||||||
|
|||||||
@@ -217,7 +217,9 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
|
|||||||
mouseCode = BUTTON_RIGHT;
|
mouseCode = BUTTON_RIGHT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (index == dev->map->btn_a)
|
if (dev->map == NULL)
|
||||||
|
break;
|
||||||
|
else if (index == dev->map->btn_a)
|
||||||
gamepadCode = A_FLAG;
|
gamepadCode = A_FLAG;
|
||||||
else if (index == dev->map->btn_x)
|
else if (index == dev->map->btn_x)
|
||||||
gamepadCode = X_FLAG;
|
gamepadCode = X_FLAG;
|
||||||
@@ -251,22 +253,20 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
|
|||||||
|
|
||||||
if (mouseCode != 0) {
|
if (mouseCode != 0) {
|
||||||
LiSendMouseButtonEvent(ev->value?BUTTON_ACTION_PRESS:BUTTON_ACTION_RELEASE, mouseCode);
|
LiSendMouseButtonEvent(ev->value?BUTTON_ACTION_PRESS:BUTTON_ACTION_RELEASE, mouseCode);
|
||||||
} else {
|
} else if (gamepadCode != 0) {
|
||||||
gamepadModified = true;
|
gamepadModified = true;
|
||||||
|
|
||||||
if (gamepadCode != 0) {
|
if (ev->value)
|
||||||
if (ev->value)
|
dev->buttonFlags |= gamepadCode;
|
||||||
dev->buttonFlags |= gamepadCode;
|
else
|
||||||
else
|
dev->buttonFlags &= ~gamepadCode;
|
||||||
dev->buttonFlags &= ~gamepadCode;
|
} else if (index == dev->map->btn_lefttrigger)
|
||||||
} else if (index == dev->map->btn_lefttrigger)
|
dev->leftTrigger = ev->value ? UCHAR_MAX : 0;
|
||||||
dev->leftTrigger = ev->value?UCHAR_MAX:0;
|
else if (index == dev->map->btn_righttrigger)
|
||||||
else if (index == dev->map->btn_righttrigger)
|
dev->rightTrigger = ev->value ? UCHAR_MAX : 0;
|
||||||
dev->rightTrigger = ev->value?UCHAR_MAX:0;
|
else {
|
||||||
else {
|
fprintf(stderr, "Unmapped button: %d\n", ev->code);
|
||||||
fprintf(stderr, "Unmapped button: %d\n", ev->code);
|
gamepadModified = false;
|
||||||
gamepadModified = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -284,6 +284,9 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EV_ABS:
|
case EV_ABS:
|
||||||
|
if (dev->map == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
gamepadModified = true;
|
gamepadModified = true;
|
||||||
int index = dev->abs_map[ev->code];
|
int index = dev->abs_map[ev->code];
|
||||||
int hat_index = (ev->code - ABS_HAT0X) / 2;
|
int hat_index = (ev->code - ABS_HAT0X) / 2;
|
||||||
@@ -394,7 +397,7 @@ static int evdev_handle(int fd) {
|
|||||||
return LOOP_OK;
|
return LOOP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void evdev_create(const char* device, struct mapping* mappings) {
|
void evdev_create(const char* device, struct mapping* mappings, bool verbose) {
|
||||||
int fd = open(device, O_RDONLY|O_NONBLOCK);
|
int fd = open(device, O_RDONLY|O_NONBLOCK);
|
||||||
if (fd <= 0) {
|
if (fd <= 0) {
|
||||||
fprintf(stderr, "Failed to open device %s\n", device);
|
fprintf(stderr, "Failed to open device %s\n", device);
|
||||||
@@ -416,17 +419,22 @@ void evdev_create(const char* device, struct mapping* mappings) {
|
|||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
buf += sprintf(buf, "%02x", ((unsigned char*) guid)[i]);
|
buf += sprintf(buf, "%02x", ((unsigned char*) guid)[i]);
|
||||||
|
|
||||||
while (mappings != NULL && strncmp(str_guid, mappings->guid, 32) != 0)
|
while (mappings != NULL) {
|
||||||
mappings = mappings->next;
|
if (strncmp(str_guid, mappings->guid, 32) == 0) {
|
||||||
|
if (verbose)
|
||||||
|
printf("Detected %s (%s) on %s\n", mappings->name, str_guid, device);
|
||||||
|
|
||||||
if (mappings == NULL) {
|
break;
|
||||||
fprintf(stderr, "No mapping available for %s\n", device);
|
}
|
||||||
fflush(stderr);
|
mappings = mappings->next;
|
||||||
close(fd);
|
|
||||||
libevdev_free(evdev);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_keyboard = libevdev_has_event_code(evdev, EV_KEY, KEY_Q);
|
||||||
|
bool is_mouse = libevdev_has_event_type(evdev, EV_REL) || libevdev_has_event_code(evdev, EV_KEY, BTN_LEFT);
|
||||||
|
|
||||||
|
if (mappings == NULL && !(is_keyboard || is_mouse))
|
||||||
|
fprintf(stderr, "No mapping available for %s (%s)\n", device, str_guid);
|
||||||
|
|
||||||
int dev = numDevices;
|
int dev = numDevices;
|
||||||
numDevices++;
|
numDevices++;
|
||||||
|
|
||||||
@@ -466,12 +474,15 @@ void evdev_create(const char* device, struct mapping* mappings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
devices[dev].controllerId = -1;
|
devices[dev].controllerId = -1;
|
||||||
evdev_init_parms(&devices[dev], &(devices[dev].xParms), devices[dev].map->abs_leftx);
|
|
||||||
evdev_init_parms(&devices[dev], &(devices[dev].yParms), devices[dev].map->abs_lefty);
|
if (devices[dev].map != NULL) {
|
||||||
evdev_init_parms(&devices[dev], &(devices[dev].zParms), devices[dev].map->abs_lefttrigger);
|
evdev_init_parms(&devices[dev], &(devices[dev].xParms), devices[dev].map->abs_leftx);
|
||||||
evdev_init_parms(&devices[dev], &(devices[dev].rxParms), devices[dev].map->abs_rightx);
|
evdev_init_parms(&devices[dev], &(devices[dev].yParms), devices[dev].map->abs_lefty);
|
||||||
evdev_init_parms(&devices[dev], &(devices[dev].ryParms), devices[dev].map->abs_righty);
|
evdev_init_parms(&devices[dev], &(devices[dev].zParms), devices[dev].map->abs_lefttrigger);
|
||||||
evdev_init_parms(&devices[dev], &(devices[dev].rzParms), devices[dev].map->abs_righttrigger);
|
evdev_init_parms(&devices[dev], &(devices[dev].rxParms), devices[dev].map->abs_rightx);
|
||||||
|
evdev_init_parms(&devices[dev], &(devices[dev].ryParms), devices[dev].map->abs_righty);
|
||||||
|
evdev_init_parms(&devices[dev], &(devices[dev].rzParms), devices[dev].map->abs_righttrigger);
|
||||||
|
}
|
||||||
|
|
||||||
if (grabbingDevices) {
|
if (grabbingDevices) {
|
||||||
if (ioctl(fd, EVIOCGRAB, 1) < 0) {
|
if (ioctl(fd, EVIOCGRAB, 1) < 0) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "mapping.h"
|
#include "mapping.h"
|
||||||
|
|
||||||
void evdev_create(const char* device, struct mapping* mappings);
|
void evdev_create(const char* device, struct mapping* mappings, bool verbose);
|
||||||
void evdev_loop();
|
void evdev_loop();
|
||||||
|
|
||||||
void evdev_init();
|
void evdev_init();
|
||||||
|
|||||||
@@ -21,129 +21,134 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct mapping* mapping_load(char* fileName) {
|
struct mapping* mapping_parse(char* mapping) {
|
||||||
|
char* strpoint;
|
||||||
|
char* guid = strtok_r(mapping, ",", &strpoint);
|
||||||
|
char* name = strtok_r(NULL, ",", &strpoint);
|
||||||
|
if (guid == NULL || name == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct mapping* map = malloc(sizeof(struct mapping));
|
||||||
|
if (map == NULL) {
|
||||||
|
fprintf(stderr, "Not enough memory");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(map->guid, guid, sizeof(map->guid));
|
||||||
|
strncpy(map->name, name, sizeof(map->name));
|
||||||
|
|
||||||
|
char* option;
|
||||||
|
while ((option = strtok_r(NULL, ",", &strpoint)) != NULL) {
|
||||||
|
char *key = NULL, *value = NULL;
|
||||||
|
int ret;
|
||||||
|
if ((ret = sscanf(option, "%m[^:]:%ms", &key, &value)) == 2) {
|
||||||
|
int int_value, direction_value;
|
||||||
|
char flag = 0;
|
||||||
|
if (strcmp("platform", key) == 0)
|
||||||
|
strncpy(map->platform, value, sizeof(map->platform));
|
||||||
|
else if (sscanf(value, "b%d", &int_value) == 1) {
|
||||||
|
if (strcmp("a", key) == 0)
|
||||||
|
map->btn_a = int_value;
|
||||||
|
else if (strcmp("y", key) == 0)
|
||||||
|
map->btn_y = int_value;
|
||||||
|
else if (strcmp("x", key) == 0)
|
||||||
|
map->btn_x = int_value;
|
||||||
|
else if (strcmp("b", key) == 0)
|
||||||
|
map->btn_b = int_value;
|
||||||
|
else if (strcmp("back", key) == 0)
|
||||||
|
map->btn_back = int_value;
|
||||||
|
else if (strcmp("start", key) == 0)
|
||||||
|
map->btn_start = int_value;
|
||||||
|
else if (strcmp("guide", key) == 0)
|
||||||
|
map->btn_guide = int_value;
|
||||||
|
else if (strcmp("dpup", key) == 0)
|
||||||
|
map->btn_dpup = int_value;
|
||||||
|
else if (strcmp("dpdown", key) == 0)
|
||||||
|
map->btn_dpdown = int_value;
|
||||||
|
else if (strcmp("dpleft", key) == 0)
|
||||||
|
map->btn_dpleft = int_value;
|
||||||
|
else if (strcmp("dpright", key) == 0)
|
||||||
|
map->btn_dpright = int_value;
|
||||||
|
else if (strcmp("leftstick", key) == 0)
|
||||||
|
map->btn_leftstick = int_value;
|
||||||
|
else if (strcmp("rightstick", key) == 0)
|
||||||
|
map->btn_rightstick = int_value;
|
||||||
|
else if (strcmp("leftshoulder", key) == 0)
|
||||||
|
map->btn_leftshoulder = int_value;
|
||||||
|
else if (strcmp("rightshoulder", key) == 0)
|
||||||
|
map->btn_rightshoulder = int_value;
|
||||||
|
else if (strcmp("lefttrigger", key) == 0)
|
||||||
|
map->btn_lefttrigger = int_value;
|
||||||
|
else if (strcmp("righttrigger", key) == 0)
|
||||||
|
map->btn_righttrigger = int_value;
|
||||||
|
} else if (sscanf(value, "a%d%c", &int_value, &flag) >= 1) {
|
||||||
|
if (strcmp("leftx", key) == 0) {
|
||||||
|
map->abs_leftx = int_value;
|
||||||
|
map->reverse_leftx = flag == '~';
|
||||||
|
} else if (strcmp("lefty", key) == 0) {
|
||||||
|
map->abs_lefty = int_value;
|
||||||
|
map->reverse_lefty = flag == '~';
|
||||||
|
} else if (strcmp("rightx", key) == 0) {
|
||||||
|
map->abs_rightx = int_value;
|
||||||
|
map->reverse_rightx = flag == '~';
|
||||||
|
} else if (strcmp("righty", key) == 0) {
|
||||||
|
map->abs_righty = int_value;
|
||||||
|
map->reverse_righty = flag == '~';
|
||||||
|
} else if (strcmp("lefttrigger", key) == 0)
|
||||||
|
map->abs_lefttrigger = int_value;
|
||||||
|
else if (strcmp("righttrigger", key) == 0)
|
||||||
|
map->abs_righttrigger = int_value;
|
||||||
|
} else if (sscanf(value, "h%d.%d", &int_value, &direction_value) == 2) {
|
||||||
|
if (strcmp("dpright", key) == 0) {
|
||||||
|
map->hat_dpright = int_value;
|
||||||
|
map->hat_dir_dpright = direction_value;
|
||||||
|
} else if (strcmp("dpleft", key) == 0) {
|
||||||
|
map->hat_dpleft = int_value;
|
||||||
|
map->hat_dir_dpleft = direction_value;
|
||||||
|
} else if (strcmp("dpup", key) == 0) {
|
||||||
|
map->hat_dpup = int_value;
|
||||||
|
map->hat_dir_dpup = direction_value;
|
||||||
|
} else if (strcmp("dpdown", key) == 0) {
|
||||||
|
map->hat_dpdown = int_value;
|
||||||
|
map->hat_dir_dpdown = direction_value;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
fprintf(stderr, "Can't map (%s)\n", option);
|
||||||
|
} else if (ret == 0 && option[0] != '\n')
|
||||||
|
fprintf(stderr, "Can't map (%s)\n", option);
|
||||||
|
|
||||||
|
if (key != NULL)
|
||||||
|
free(key);
|
||||||
|
|
||||||
|
if (value != NULL)
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
map->guid[32] = '\0';
|
||||||
|
map->name[256] = '\0';
|
||||||
|
map->platform[32] = '\0';
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mapping* mapping_load(char* fileName, bool verbose) {
|
||||||
struct mapping* mappings = NULL;
|
struct mapping* mappings = NULL;
|
||||||
struct mapping* map = NULL;
|
|
||||||
FILE* fd = fopen(fileName, "r");
|
FILE* fd = fopen(fileName, "r");
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
fprintf(stderr, "Can't open mapping file: %s\n", fileName);
|
fprintf(stderr, "Can't open mapping file: %s\n", fileName);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
} else if (verbose)
|
||||||
|
printf("Loading mappingfile %s\n", fileName);
|
||||||
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
while (getline(&line, &len, fd) != -1) {
|
while (getline(&line, &len, fd) != -1) {
|
||||||
char* strpoint;
|
struct mapping* map = mapping_parse(line);
|
||||||
char* guid = strtok_r(line, ",", &strpoint);
|
if (map) {
|
||||||
char* name = strtok_r(NULL, ",", &strpoint);
|
map->next = mappings;
|
||||||
if (guid == NULL || name == NULL)
|
mappings = map;
|
||||||
continue;
|
|
||||||
|
|
||||||
struct mapping* newmap = malloc(sizeof(struct mapping));
|
|
||||||
if (newmap == NULL) {
|
|
||||||
fprintf(stderr, "Not enough memory");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else if (mappings == NULL)
|
|
||||||
mappings = newmap;
|
|
||||||
else
|
|
||||||
map->next = newmap;
|
|
||||||
|
|
||||||
map = newmap;
|
|
||||||
|
|
||||||
strncpy(map->guid, guid, sizeof(map->guid));
|
|
||||||
strncpy(map->name, name, sizeof(map->name));
|
|
||||||
|
|
||||||
char* option;
|
|
||||||
while ((option = strtok_r(NULL, ",", &strpoint)) != NULL) {
|
|
||||||
char *key = NULL, *value = NULL;
|
|
||||||
int ret;
|
|
||||||
if ((ret = sscanf(option, "%m[^:]:%ms", &key, &value)) == 2) {
|
|
||||||
int int_value, direction_value;
|
|
||||||
char flag = 0;
|
|
||||||
if (strcmp("platform", key) == 0)
|
|
||||||
strncpy(map->platform, value, sizeof(map->platform));
|
|
||||||
else if (sscanf(value, "b%d", &int_value) == 1) {
|
|
||||||
if (strcmp("a", key) == 0)
|
|
||||||
map->btn_a = int_value;
|
|
||||||
else if (strcmp("y", key) == 0)
|
|
||||||
map->btn_y = int_value;
|
|
||||||
else if (strcmp("x", key) == 0)
|
|
||||||
map->btn_x = int_value;
|
|
||||||
else if (strcmp("b", key) == 0)
|
|
||||||
map->btn_b = int_value;
|
|
||||||
else if (strcmp("back", key) == 0)
|
|
||||||
map->btn_back = int_value;
|
|
||||||
else if (strcmp("start", key) == 0)
|
|
||||||
map->btn_start = int_value;
|
|
||||||
else if (strcmp("guide", key) == 0)
|
|
||||||
map->btn_guide = int_value;
|
|
||||||
else if (strcmp("dpup", key) == 0)
|
|
||||||
map->btn_dpup = int_value;
|
|
||||||
else if (strcmp("dpdown", key) == 0)
|
|
||||||
map->btn_dpdown = int_value;
|
|
||||||
else if (strcmp("dpleft", key) == 0)
|
|
||||||
map->btn_dpleft = int_value;
|
|
||||||
else if (strcmp("dpright", key) == 0)
|
|
||||||
map->btn_dpright = int_value;
|
|
||||||
else if (strcmp("leftstick", key) == 0)
|
|
||||||
map->btn_leftstick = int_value;
|
|
||||||
else if (strcmp("rightstick", key) == 0)
|
|
||||||
map->btn_rightstick = int_value;
|
|
||||||
else if (strcmp("leftshoulder", key) == 0)
|
|
||||||
map->btn_leftshoulder = int_value;
|
|
||||||
else if (strcmp("rightshoulder", key) == 0)
|
|
||||||
map->btn_rightshoulder = int_value;
|
|
||||||
else if (strcmp("lefttrigger", key) == 0)
|
|
||||||
map->btn_lefttrigger = int_value;
|
|
||||||
else if (strcmp("righttrigger", key) == 0)
|
|
||||||
map->btn_righttrigger = int_value;
|
|
||||||
} else if (sscanf(value, "a%d%c", &int_value, &flag) >= 1) {
|
|
||||||
if (strcmp("leftx", key) == 0) {
|
|
||||||
map->abs_leftx = int_value;
|
|
||||||
map->reverse_leftx = flag == '~';
|
|
||||||
} else if (strcmp("lefty", key) == 0) {
|
|
||||||
map->abs_lefty = int_value;
|
|
||||||
map->reverse_lefty = flag == '~';
|
|
||||||
} else if (strcmp("rightx", key) == 0) {
|
|
||||||
map->abs_rightx = int_value;
|
|
||||||
map->reverse_rightx = flag == '~';
|
|
||||||
} else if (strcmp("righty", key) == 0) {
|
|
||||||
map->abs_righty = int_value;
|
|
||||||
map->reverse_righty = flag == '~';
|
|
||||||
} else if (strcmp("lefttrigger", key) == 0)
|
|
||||||
map->abs_lefttrigger = int_value;
|
|
||||||
else if (strcmp("righttrigger", key) == 0)
|
|
||||||
map->abs_righttrigger = int_value;
|
|
||||||
} else if (sscanf(value, "h%d.%d", &int_value, &direction_value) == 2) {
|
|
||||||
if (strcmp("dpright", key) == 0) {
|
|
||||||
map->hat_dpright = int_value;
|
|
||||||
map->hat_dir_dpright = direction_value;
|
|
||||||
} else if (strcmp("dpleft", key) == 0) {
|
|
||||||
map->hat_dpleft = int_value;
|
|
||||||
map->hat_dir_dpleft = direction_value;
|
|
||||||
} else if (strcmp("dpup", key) == 0) {
|
|
||||||
map->hat_dpup = int_value;
|
|
||||||
map->hat_dir_dpup = direction_value;
|
|
||||||
} else if (strcmp("dpdown", key) == 0) {
|
|
||||||
map->hat_dpdown = int_value;
|
|
||||||
map->hat_dir_dpdown = direction_value;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
fprintf(stderr, "Can't map (%s)\n", option);
|
|
||||||
} else if (ret == 0 && option[0] != '\n')
|
|
||||||
fprintf(stderr, "Can't map (%s)\n", option);
|
|
||||||
|
|
||||||
if (key != NULL)
|
|
||||||
free(key);
|
|
||||||
|
|
||||||
if (value != NULL)
|
|
||||||
free(value);
|
|
||||||
}
|
}
|
||||||
map->guid[32] = '\0';
|
|
||||||
map->name[256] = '\0';
|
|
||||||
map->platform[32] = '\0';
|
|
||||||
}
|
}
|
||||||
free(line);
|
free(line);
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,5 @@ struct mapping {
|
|||||||
struct mapping* next;
|
struct mapping* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mapping* mapping_load(char* fileName);
|
struct mapping* mapping_parse(char* mapping);
|
||||||
|
struct mapping* mapping_load(char* fileName, bool verbose);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
static bool autoadd;
|
static bool autoadd, debug;
|
||||||
static struct mapping* defaultMappings;
|
static struct mapping* defaultMappings;
|
||||||
|
|
||||||
static struct udev *udev;
|
static struct udev *udev;
|
||||||
@@ -46,7 +46,7 @@ static int udev_handle(int fd) {
|
|||||||
const char *devnode = udev_device_get_devnode(dev);
|
const char *devnode = udev_device_get_devnode(dev);
|
||||||
int id;
|
int id;
|
||||||
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
|
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
|
||||||
evdev_create(devnode, defaultMappings);
|
evdev_create(devnode, defaultMappings, debug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
udev_device_unref(dev);
|
udev_device_unref(dev);
|
||||||
@@ -54,8 +54,9 @@ static int udev_handle(int fd) {
|
|||||||
return LOOP_OK;
|
return LOOP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void udev_init(bool autoload, struct mapping* mappings) {
|
void udev_init(bool autoload, struct mapping* mappings, bool verbose) {
|
||||||
udev = udev_new();
|
udev = udev_new();
|
||||||
|
debug = verbose;
|
||||||
if (!udev) {
|
if (!udev) {
|
||||||
fprintf(stderr, "Can't create udev\n");
|
fprintf(stderr, "Can't create udev\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -75,7 +76,7 @@ void udev_init(bool autoload, struct mapping* mappings) {
|
|||||||
const char *devnode = udev_device_get_devnode(dev);
|
const char *devnode = udev_device_get_devnode(dev);
|
||||||
int id;
|
int id;
|
||||||
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
|
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
|
||||||
evdev_create(devnode, mappings);
|
evdev_create(devnode, mappings, verbose);
|
||||||
}
|
}
|
||||||
udev_device_unref(dev);
|
udev_device_unref(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,5 +19,5 @@
|
|||||||
|
|
||||||
#include "mapping.h"
|
#include "mapping.h"
|
||||||
|
|
||||||
void udev_init(bool autoload, struct mapping* mappings);
|
void udev_init(bool autoload, struct mapping* mappings, bool verbose);
|
||||||
void evdev_destroy();
|
void evdev_destroy();
|
||||||
|
|||||||
30
src/main.c
30
src/main.c
@@ -95,7 +95,7 @@ static void stream(PSERVER_DATA server, PCONFIGURATION config, enum platform sys
|
|||||||
if (ret == GS_NOT_SUPPORTED_4K)
|
if (ret == GS_NOT_SUPPORTED_4K)
|
||||||
fprintf(stderr, "Server doesn't support 4K\n");
|
fprintf(stderr, "Server doesn't support 4K\n");
|
||||||
else if (ret == GS_NOT_SUPPORTED_MODE)
|
else if (ret == GS_NOT_SUPPORTED_MODE)
|
||||||
fprintf(stderr, "Server doesn't support %dx%d (%d fps)\n", config->stream.width, config->stream.height, config->stream.fps);
|
fprintf(stderr, "Server doesn't support %dx%d (%d fps) or try --unsupported option\n", config->stream.width, config->stream.height, config->stream.fps);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Errorcode starting app: %d\n", ret);
|
fprintf(stderr, "Errorcode starting app: %d\n", ret);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@@ -161,7 +161,7 @@ static void help() {
|
|||||||
printf("\t-keydir <directory>\tLoad encryption keys from directory\n");
|
printf("\t-keydir <directory>\tLoad encryption keys from directory\n");
|
||||||
printf("\t-mapping <file>\t\tUse <file> as gamepad mappings configuration file\n");
|
printf("\t-mapping <file>\t\tUse <file> as gamepad mappings configuration file\n");
|
||||||
printf("\t-platform <system>\tSpecify system used for audio, video and input: pi/imx/aml/x11/x11_vdpau/sdl/fake (default auto)\n");
|
printf("\t-platform <system>\tSpecify system used for audio, video and input: pi/imx/aml/x11/x11_vdpau/sdl/fake (default auto)\n");
|
||||||
printf("\t-unsupported\t\tTry streaming if GFE version is unsupported\n");
|
printf("\t-unsupported\t\tTry streaming if GFE version or options are unsupported\n");
|
||||||
#if defined(HAVE_SDL) || defined(HAVE_X11)
|
#if defined(HAVE_SDL) || defined(HAVE_X11)
|
||||||
printf("\n WM options (SDL and X11 only)\n\n");
|
printf("\n WM options (SDL and X11 only)\n\n");
|
||||||
printf("\t-windowed\t\tDisplay screen in a window\n");
|
printf("\t-windowed\t\tDisplay screen in a window\n");
|
||||||
@@ -216,17 +216,15 @@ int main(int argc, char* argv[]) {
|
|||||||
printf("Connect to %s...\n", config.address);
|
printf("Connect to %s...\n", config.address);
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
if ((ret = gs_init(&server, config.address, config.key_dir, config.debug_level)) == GS_OUT_OF_MEMORY) {
|
if ((ret = gs_init(&server, config.address, config.key_dir, config.debug_level, config.unsupported)) == GS_OUT_OF_MEMORY) {
|
||||||
fprintf(stderr, "Not enough memory\n");
|
fprintf(stderr, "Not enough memory\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
} else if (ret == GS_INVALID) {
|
} else if (ret == GS_INVALID) {
|
||||||
fprintf(stderr, "Invalid data received from server: %s\n", config.address, gs_error);
|
fprintf(stderr, "Invalid data received from server: %s\n", config.address, gs_error);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
} else if (ret == GS_UNSUPPORTED_VERSION) {
|
} else if (ret == GS_UNSUPPORTED_VERSION) {
|
||||||
if (!config.unsupported_version) {
|
fprintf(stderr, "Unsupported version: %s\n", gs_error);
|
||||||
fprintf(stderr, "Unsupported version: %s\n", gs_error);
|
exit(-1);
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
} else if (ret != GS_OK) {
|
} else if (ret != GS_OK) {
|
||||||
fprintf(stderr, "Can't connect to server %s\n", config.address);
|
fprintf(stderr, "Can't connect to server %s\n", config.address);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@@ -254,20 +252,30 @@ int main(int argc, char* argv[]) {
|
|||||||
config.stream.supportsHevc = config.codec != CODEC_H264 && (config.codec == CODEC_HEVC || platform_supports_hevc(system));
|
config.stream.supportsHevc = config.codec != CODEC_H264 && (config.codec == CODEC_HEVC || platform_supports_hevc(system));
|
||||||
|
|
||||||
if (IS_EMBEDDED(system)) {
|
if (IS_EMBEDDED(system)) {
|
||||||
if (config.mapping == NULL) {
|
char* mapping_env = getenv("SDL_GAMECONTROLLERCONFIG");
|
||||||
|
if (config.mapping == NULL && mapping_env == NULL) {
|
||||||
fprintf(stderr, "Please specify mapping file as default mapping could not be found.\n");
|
fprintf(stderr, "Please specify mapping file as default mapping could not be found.\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
struct mapping* mappings = mapping_load(config.mapping);
|
|
||||||
|
struct mapping* mappings;
|
||||||
|
if (config.mapping != NULL)
|
||||||
|
mappings = mapping_load(config.mapping, config.debug_level > 0);
|
||||||
|
|
||||||
|
if (mapping_env != NULL) {
|
||||||
|
struct mapping* map = mapping_parse(mapping_env);
|
||||||
|
map->next = mappings;
|
||||||
|
mappings = map;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0;i<config.inputsCount;i++) {
|
for (int i=0;i<config.inputsCount;i++) {
|
||||||
if (config.debug_level > 0)
|
if (config.debug_level > 0)
|
||||||
printf("Add input %s...\n", config.inputs[i]);
|
printf("Add input %s...\n", config.inputs[i]);
|
||||||
|
|
||||||
evdev_create(config.inputs[i], mappings);
|
evdev_create(config.inputs[i], mappings, config.debug_level > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
udev_init(!inputAdded, mappings);
|
udev_init(!inputAdded, mappings, config.debug_level > 0);
|
||||||
evdev_init();
|
evdev_init();
|
||||||
#ifdef HAVE_LIBCEC
|
#ifdef HAVE_LIBCEC
|
||||||
cec_init();
|
cec_init();
|
||||||
|
|||||||
@@ -60,10 +60,17 @@ enum platform platform_check(char* name) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_X11
|
#ifdef HAVE_X11
|
||||||
if (std || strcmp(name, "x11") == 0 || strcmp(name, "x11_vdpau") == 0) {
|
bool x11 = strcmp(name, "x11") == 0;
|
||||||
int x11 = x11_init(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
|
#ifdef HAVE_VDPAU
|
||||||
if (strcmp(name, "x11") != 0 && x11 == 0)
|
if (init == INIT_VDPAU)
|
||||||
return X11_VDPAU;
|
return X11_VDPAU;
|
||||||
#endif
|
#endif
|
||||||
return X11;
|
return X11;
|
||||||
@@ -116,6 +123,10 @@ DECODER_RENDERER_CALLBACKS* platform_get_video(enum platform system) {
|
|||||||
#ifdef HAVE_X11
|
#ifdef HAVE_X11
|
||||||
case X11:
|
case X11:
|
||||||
return &decoder_callbacks_x11;
|
return &decoder_callbacks_x11;
|
||||||
|
#ifdef HAVE_VAAPI
|
||||||
|
case X11_VAAPI:
|
||||||
|
return &decoder_callbacks_x11_vaapi;
|
||||||
|
#endif
|
||||||
#ifdef HAVE_VDPAU
|
#ifdef HAVE_VDPAU
|
||||||
case X11_VDPAU:
|
case X11_VDPAU:
|
||||||
return &decoder_callbacks_x11_vdpau;
|
return &decoder_callbacks_x11_vdpau;
|
||||||
@@ -182,6 +193,8 @@ char* platform_name(enum platform system) {
|
|||||||
return "AMLogic VPU";
|
return "AMLogic VPU";
|
||||||
case X11:
|
case X11:
|
||||||
return "X Window System (software decoding)";
|
return "X Window System (software decoding)";
|
||||||
|
case X11_VAAPI:
|
||||||
|
return "X Window System (VAAPI)";
|
||||||
case X11_VDPAU:
|
case X11_VDPAU:
|
||||||
return "X Window System (VDPAU)";
|
return "X Window System (VDPAU)";
|
||||||
case SDL:
|
case SDL:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#define IS_EMBEDDED(SYSTEM) SYSTEM != SDL
|
#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*);
|
enum platform platform_check(char*);
|
||||||
PDECODER_RENDERER_CALLBACKS platform_get_video(enum platform system);
|
PDECODER_RENDERER_CALLBACKS platform_get_video(enum platform system);
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
#ifdef HAVE_VDPAU
|
#ifdef HAVE_VDPAU
|
||||||
#include "ffmpeg_vdpau.h"
|
#include "ffmpeg_vdpau.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_VAAPI
|
||||||
|
#include "ffmpeg_vaapi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <Limelight.h>
|
#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);
|
av_init_packet(&pkt);
|
||||||
|
|
||||||
#ifdef HAVE_VDPAU
|
if (perf_lvl & VDPAU_ACCELERATION) {
|
||||||
if (perf_lvl & HARDWARE_ACCELERATION) {
|
|
||||||
switch (videoFormat) {
|
switch (videoFormat) {
|
||||||
case VIDEO_FORMAT_H264:
|
case VIDEO_FORMAT_H264:
|
||||||
decoder = avcodec_find_decoder_by_name("h264_vdpau");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decoder != NULL)
|
ffmpeg_decoder = VDPAU;
|
||||||
ffmpeg_decoder = VDPAU;
|
} else {
|
||||||
}
|
ffmpeg_decoder = perf_lvl & VAAPI_ACCELERATION ? VAAPI : SOFTWARE;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (decoder == NULL) {
|
|
||||||
ffmpeg_decoder = SOFTWARE;
|
|
||||||
switch (videoFormat) {
|
switch (videoFormat) {
|
||||||
case VIDEO_FORMAT_H264:
|
case VIDEO_FORMAT_H264:
|
||||||
decoder = avcodec_find_decoder_by_name("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");
|
decoder = avcodec_find_decoder_by_name("hevc");
|
||||||
break;
|
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);
|
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
|
#ifdef HAVE_VDPAU
|
||||||
if (ffmpeg_decoder == VDPAU)
|
if (ffmpeg_decoder == VDPAU)
|
||||||
vdpau_init(decoder_ctx, width, height);
|
vdpau_init(decoder_ctx, width, height);
|
||||||
|
|||||||
@@ -34,9 +34,10 @@
|
|||||||
// Uses a faster bilinear filtering with lower image quality
|
// Uses a faster bilinear filtering with lower image quality
|
||||||
#define FAST_BILINEAR_FILTERING 0x20
|
#define FAST_BILINEAR_FILTERING 0x20
|
||||||
// Uses hardware acceleration
|
// 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;
|
extern enum decoders ffmpeg_decoder;
|
||||||
|
|
||||||
int ffmpeg_init(int videoFormat, int width, int height, int perf_lvl, int buffer_count, int thread_count);
|
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);
|
||||||
@@ -115,7 +115,7 @@ static int frame_handle(int pipefd) {
|
|||||||
return LOOP_OK;
|
return LOOP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decoder_renderer_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
static int decoder_renderer_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||||
if (videoFormat != VIDEO_FORMAT_H264) {
|
if (videoFormat != VIDEO_FORMAT_H264) {
|
||||||
fprintf(stderr, "Video format not supported\n");
|
fprintf(stderr, "Video format not supported\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static unsigned char *dest;
|
|||||||
static int port_settings_changed;
|
static int port_settings_changed;
|
||||||
static int first_packet;
|
static int first_packet;
|
||||||
|
|
||||||
int decoder_renderer_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
static int decoder_renderer_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||||
if (videoFormat != VIDEO_FORMAT_H264) {
|
if (videoFormat != VIDEO_FORMAT_H264) {
|
||||||
fprintf(stderr, "Video format not supported\n");
|
fprintf(stderr, "Video format not supported\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -22,11 +22,19 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define DISPLAY_FULLSCREEN 1
|
#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
|
#ifdef HAVE_X11
|
||||||
int x11_init(bool vdpau);
|
int x11_init(bool vdpau, bool vaapi);
|
||||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11;
|
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11;
|
||||||
|
#ifdef HAVE_VAAPI
|
||||||
|
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vaapi;
|
||||||
|
#endif
|
||||||
#ifdef HAVE_VDPAU
|
#ifdef HAVE_VDPAU
|
||||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vdpau;
|
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vdpau;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
#ifdef HAVE_VDPAU
|
#ifdef HAVE_VDPAU
|
||||||
#include "ffmpeg_vdpau.h"
|
#include "ffmpeg_vdpau.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_VAAPI
|
||||||
|
#include "ffmpeg_vaapi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../input/x11.h"
|
#include "../input/x11.h"
|
||||||
#include "../loop.h"
|
#include "../loop.h"
|
||||||
@@ -36,34 +39,51 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
#define DECODER_BUFFER_SIZE 92*1024
|
#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 char* ffmpeg_buffer = NULL;
|
||||||
|
|
||||||
static Display *display = NULL;
|
static Display *display = NULL;
|
||||||
|
static Window window;
|
||||||
|
|
||||||
static int pipefd[2];
|
static int pipefd[2];
|
||||||
|
|
||||||
|
static int display_width;
|
||||||
|
static int display_height;
|
||||||
|
|
||||||
static int frame_handle(int pipefd) {
|
static int frame_handle(int pipefd) {
|
||||||
AVFrame* frame = NULL;
|
AVFrame* frame = NULL;
|
||||||
while (read(pipefd, &frame, sizeof(void*)) > 0);
|
while (read(pipefd, &frame, sizeof(void*)) > 0);
|
||||||
if (frame)
|
if (frame) {
|
||||||
egl_draw(frame->data);
|
if (ffmpeg_decoder == SOFTWARE)
|
||||||
|
egl_draw(frame->data);
|
||||||
|
else if (ffmpeg_decoder == VAAPI)
|
||||||
|
vaapi_queue(frame, window, display_width, display_height);
|
||||||
|
else if (ffmpeg_decoder == VDPAU)
|
||||||
|
vdpau_queue(frame);
|
||||||
|
}
|
||||||
|
|
||||||
return LOOP_OK;
|
return LOOP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x11_init(bool vdpau) {
|
int x11_init(bool vdpau, bool vaapi) {
|
||||||
XInitThreads();
|
XInitThreads();
|
||||||
display = XOpenDisplay(NULL);
|
display = XOpenDisplay(NULL);
|
||||||
if (!display)
|
if (!display)
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
#ifdef HAVE_VDPAU
|
#ifdef HAVE_VAAPI
|
||||||
if (vdpau && vdpau_init_lib(display) != 0)
|
if (vaapi && vaapi_init_lib(display) == 0)
|
||||||
return -2;
|
return INIT_VAAPI;
|
||||||
#endif
|
#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) {
|
int x11_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||||
@@ -78,8 +98,6 @@ int x11_setup(int videoFormat, int width, int height, int redrawRate, void* cont
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int display_width;
|
|
||||||
int display_height;
|
|
||||||
if (drFlags & DISPLAY_FULLSCREEN) {
|
if (drFlags & DISPLAY_FULLSCREEN) {
|
||||||
Screen* screen = DefaultScreenOfDisplay(display);
|
Screen* screen = DefaultScreenOfDisplay(display);
|
||||||
display_width = WidthOfScreen(screen);
|
display_width = WidthOfScreen(screen);
|
||||||
@@ -91,7 +109,7 @@ int x11_setup(int videoFormat, int width, int height, int redrawRate, void* cont
|
|||||||
|
|
||||||
Window root = DefaultRootWindow(display);
|
Window root = DefaultRootWindow(display);
|
||||||
XSetWindowAttributes winattr = { .event_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask };
|
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);
|
XMapWindow(display, window);
|
||||||
XStoreName(display, window, "Moonlight");
|
XStoreName(display, window, "Moonlight");
|
||||||
|
|
||||||
@@ -113,37 +131,42 @@ int x11_setup(int videoFormat, int width, int height, int redrawRate, void* cont
|
|||||||
XFlush(display);
|
XFlush(display);
|
||||||
|
|
||||||
int avc_flags = SLICE_THREADING;
|
int avc_flags = SLICE_THREADING;
|
||||||
#ifdef HAVE_VDPAU
|
if (drFlags & X11_VDPAU_ACCELERATION)
|
||||||
if (drFlags & ENABLE_HARDWARE_ACCELERATION)
|
avc_flags |= VDPAU_ACCELERATION;
|
||||||
avc_flags |= HARDWARE_ACCELERATION;
|
else if (drFlags & X11_VAAPI_ACCELERATION)
|
||||||
#endif
|
avc_flags |= VAAPI_ACCELERATION;
|
||||||
|
|
||||||
if (ffmpeg_init(videoFormat, width, height, avc_flags, 2, 2) < 0) {
|
if (ffmpeg_init(videoFormat, width, height, avc_flags, 2, 2) < 0) {
|
||||||
fprintf(stderr, "Couldn't initialize video decoding\n");
|
fprintf(stderr, "Couldn't initialize video decoding\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ffmpeg_decoder == SOFTWARE) {
|
if (ffmpeg_decoder == SOFTWARE)
|
||||||
egl_init(display, window, width, height);
|
egl_init(display, window, width, height);
|
||||||
if (pipe(pipefd) == -1) {
|
|
||||||
fprintf(stderr, "Can't create communication channel between threads\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
loop_add_fd(pipefd[0], &frame_handle, POLLIN);
|
|
||||||
fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_VDPAU
|
#ifdef HAVE_VDPAU
|
||||||
else if (ffmpeg_decoder == VDPAU)
|
if (ffmpeg_decoder == VDPAU)
|
||||||
vdpau_init_presentation(window, width, height, display_width, display_height);
|
vdpau_init_presentation(window, width, height, display_width, display_height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (pipe(pipefd) == -1) {
|
||||||
|
fprintf(stderr, "Can't create communication channel between threads\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
loop_add_fd(pipefd[0], &frame_handle, POLLIN);
|
||||||
|
fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
x11_input_init(display, window);
|
x11_input_init(display, window);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x11_setup_vdpau(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
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() {
|
void x11_cleanup() {
|
||||||
@@ -162,12 +185,8 @@ int x11_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
|||||||
}
|
}
|
||||||
ffmpeg_decode(ffmpeg_buffer, length);
|
ffmpeg_decode(ffmpeg_buffer, length);
|
||||||
AVFrame* frame = ffmpeg_get_frame(true);
|
AVFrame* frame = ffmpeg_get_frame(true);
|
||||||
if (frame != NULL) {
|
if (frame != NULL)
|
||||||
if (ffmpeg_decoder == SOFTWARE)
|
write(pipefd[1], &frame, sizeof(void*));
|
||||||
write(pipefd[1], &frame, sizeof(void*));
|
|
||||||
else if (ffmpeg_decoder == VDPAU)
|
|
||||||
vdpau_queue(frame);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DR_OK;
|
return DR_OK;
|
||||||
@@ -186,3 +205,10 @@ DECODER_RENDERER_CALLBACKS decoder_callbacks_x11_vdpau = {
|
|||||||
.submitDecodeUnit = x11_submit_decode_unit,
|
.submitDecodeUnit = x11_submit_decode_unit,
|
||||||
.capabilities = CAPABILITY_DIRECT_SUBMIT,
|
.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,
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user