1 /*
2 * This file is part of Moonlight Embedded.
3 *
4 * Copyright (C) 2015-2017 Iwan Timmer
5 *
6 * Moonlight is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Moonlight is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #define _GNU_SOURCE
21
22 #include "platform.h"
23
24 #include "util.h"
25
26 #include "audio/audio.h"
27 #include "video/video.h"
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <dlfcn.h>
33
34 typedef bool(*ImxInit)();
35
platform_check(char * name)36 enum platform platform_check(char* name) {
37 bool std = strcmp(name, "auto") == 0;
38 #ifdef HAVE_IMX
39 if (std || strcmp(name, "imx") == 0) {
40 void *handle = dlopen("libmoonlight-imx.so", RTLD_NOW | RTLD_GLOBAL);
41 ImxInit video_imx_init = (ImxInit) dlsym(RTLD_DEFAULT, "video_imx_init");
42 if (handle != NULL) {
43 if (video_imx_init())
44 return IMX;
45 }
46 }
47 #endif
48 #ifdef HAVE_PI
49 if (std || strcmp(name, "pi") == 0) {
50 void *handle = dlopen("libmoonlight-pi.so", RTLD_NOW | RTLD_GLOBAL);
51 if (handle != NULL && dlsym(RTLD_DEFAULT, "bcm_host_init") != NULL)
52 return PI;
53 }
54 #endif
55 #ifdef HAVE_AML
56 if (std || strcmp(name, "aml") == 0) {
57 void *handle = dlopen("libmoonlight-aml.so", RTLD_NOW | RTLD_GLOBAL);
58 if (handle != NULL && access("/dev/amvideo", F_OK) != -1)
59 return AML;
60 }
61 #endif
62 #ifdef HAVE_ROCKCHIP
63 if (std || strcmp(name, "rk") == 0) {
64 void *handle = dlopen("libmoonlight-rk.so", RTLD_NOW | RTLD_GLOBAL);
65 if (handle != NULL && dlsym(RTLD_DEFAULT, "mpp_init") != NULL)
66 return RK;
67 }
68 #endif
69 #ifdef HAVE_X11
70 bool x11 = strcmp(name, "x11") == 0;
71 bool vdpau = strcmp(name, "x11_vdpau") == 0;
72 bool vaapi = strcmp(name, "x11_vaapi") == 0;
73 if (std || x11 || vdpau || vaapi) {
74 int init = x11_init(std || vdpau, std || vaapi);
75 #ifdef HAVE_VAAPI
76 if (init == INIT_VAAPI)
77 return X11_VAAPI;
78 #endif
79 #ifdef HAVE_VDPAU
80 if (init == INIT_VDPAU)
81 return X11_VDPAU;
82 #endif
83 return X11;
84 }
85 #endif
86 #ifdef HAVE_SDL
87 if (std || strcmp(name, "sdl") == 0)
88 return SDL;
89 #endif
90 if (strcmp(name, "fake") == 0)
91 return FAKE;
92
93 return 0;
94 }
95
platform_start(enum platform system)96 void platform_start(enum platform system) {
97 switch (system) {
98 #ifdef HAVE_AML
99 case AML:
100 blank_fb("/sys/class/graphics/fb0/blank", true);
101 blank_fb("/sys/class/graphics/fb1/blank", true);
102 break;
103 #endif
104 #ifdef HAVE_PI
105 case PI:
106 blank_fb("/sys/class/graphics/fb0/blank", true);
107 break;
108 #endif
109 }
110 }
111
platform_stop(enum platform system)112 void platform_stop(enum platform system) {
113 switch (system) {
114 #ifdef HAVE_AML
115 case AML:
116 blank_fb("/sys/class/graphics/fb0/blank", false);
117 blank_fb("/sys/class/graphics/fb1/blank", false);
118 break;
119 #endif
120 #ifdef HAVE_PI
121 case PI:
122 blank_fb("/sys/class/graphics/fb0/blank", false);
123 break;
124 #endif
125 }
126 }
127
platform_get_video(enum platform system)128 DECODER_RENDERER_CALLBACKS* platform_get_video(enum platform system) {
129 switch (system) {
130 #ifdef HAVE_X11
131 case X11:
132 return &decoder_callbacks_x11;
133 #ifdef HAVE_VAAPI
134 case X11_VAAPI:
135 return &decoder_callbacks_x11_vaapi;
136 #endif
137 #ifdef HAVE_VDPAU
138 case X11_VDPAU:
139 return &decoder_callbacks_x11_vdpau;
140 #endif
141 #endif
142 #ifdef HAVE_SDL
143 case SDL:
144 return &decoder_callbacks_sdl;
145 #endif
146 #ifdef HAVE_IMX
147 case IMX:
148 return (PDECODER_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "decoder_callbacks_imx");
149 #endif
150 #ifdef HAVE_PI
151 case PI:
152 return (PDECODER_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "decoder_callbacks_pi");
153 #endif
154 #ifdef HAVE_AML
155 case AML:
156 return (PDECODER_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "decoder_callbacks_aml");
157 #endif
158 #ifdef HAVE_ROCKCHIP
159 case RK:
160 return (PDECODER_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "decoder_callbacks_rk");
161 #endif
162 }
163 return NULL;
164 }
165
platform_get_audio(enum platform system,char * audio_device)166 AUDIO_RENDERER_CALLBACKS* platform_get_audio(enum platform system, char* audio_device) {
167 switch (system) {
168 #ifdef HAVE_SDL
169 case SDL:
170 return &audio_callbacks_sdl;
171 #endif
172 #ifdef HAVE_PI
173 case PI:
174 if (audio_device == NULL || strcmp(audio_device, "local") == 0 || strcmp(audio_device, "hdmi") == 0)
175 return (PAUDIO_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "audio_callbacks_omx");
176 #endif
177 }
178 return NULL;
179 }
180
platform_supports_hevc(enum platform system)181 bool platform_supports_hevc(enum platform system) {
182 switch (system) {
183 case AML:
184 case RK:
185 return true;
186 }
187 return false;
188 }
189
platform_name(enum platform system)190 char* platform_name(enum platform system) {
191 switch(system) {
192 case PI:
193 return "Raspberry Pi (Broadcom)";
194 case IMX:
195 return "i.MX6 (MXC Vivante)";
196 case AML:
197 return "AMLogic VPU";
198 case RK:
199 return "Rockchip VPU";
200 case X11:
201 return "X Window System (software decoding)";
202 case X11_VAAPI:
203 return "X Window System (VAAPI)";
204 case X11_VDPAU:
205 return "X Window System (VDPAU)";
206 case SDL:
207 return "SDL2 (software decoding)";
208 case FAKE:
209 return "Fake (no a/v output)";
210 default:
211 return "Unknown";
212 }
213 }
214