1 /*****************************************************************************
2  * utils.h: shared code between Android vout modules.
3  *****************************************************************************
4  * Copyright (C) 2014-2015 VLC authors and VideoLAN
5  *
6  * Authors: Felix Abecassis <felix.abecassis@gmail.com>
7  *          Thomas Guillem <thomas@gllm.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23 
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 
28 #include <jni.h>
29 #include <android/native_window.h>
30 #include <android/native_window_jni.h>
31 #include <android/input.h>
32 
33 #include <vlc_vout_display.h>
34 #include <vlc_common.h>
35 
36 typedef struct AWindowHandler AWindowHandler;
37 
38 enum AWindow_ID {
39     AWindow_Video,
40     AWindow_Subtitles,
41     AWindow_SurfaceTexture,
42     AWindow_Max,
43 };
44 
45 /**
46  * native_window_api_t. See android/native_window.h in NDK
47  */
48 typedef struct
49 {
50     int32_t (*winLock)(ANativeWindow*, ANativeWindow_Buffer*, ARect*);
51     void (*unlockAndPost)(ANativeWindow*);
52     int32_t (*setBuffersGeometry)(ANativeWindow*, int32_t, int32_t, int32_t); /* can be NULL */
53 } native_window_api_t;
54 
55 /**
56  * native_window_priv_api_t. See system/core/include/system/window.h in AOSP.
57  */
58 typedef struct native_window_priv native_window_priv;
59 typedef struct
60 {
61     native_window_priv *(*connect)(ANativeWindow *);
62     int (*disconnect) (native_window_priv *);
63     int (*setUsage) (native_window_priv *, bool, int );
64     int (*setBuffersGeometry) (native_window_priv *, int, int, int );
65     int (*getMinUndequeued) (native_window_priv *, unsigned int *);
66     int (*getMaxBufferCount) (native_window_priv *, unsigned int *);
67     int (*setBufferCount) (native_window_priv *, unsigned int );
68     int (*setCrop) (native_window_priv *, int, int, int, int);
69     int (*dequeue) (native_window_priv *, void **);
70     int (*lock) (native_window_priv *, void *);
71     int (*queue) (native_window_priv *, void *);
72     int (*cancel) (native_window_priv *, void *);
73     int (*lockData) (native_window_priv *, void **, ANativeWindow_Buffer *);
74     int (*unlockData) (native_window_priv *, void *, bool b_render);
75     int (*setOrientation) (native_window_priv *, int);
76 } native_window_priv_api_t;
77 
78 struct awh_mouse_coords
79 {
80     int i_action;
81     int i_button;
82     int i_x;
83     int i_y;
84 };
85 
86 typedef struct
87 {
88     void (*on_new_window_size)(vout_window_t *wnd, unsigned i_width,
89                                unsigned i_height);
90     void (*on_new_mouse_coords)(vout_window_t *wnd,
91                                 const struct awh_mouse_coords *coords);
92 } awh_events_t;
93 
94 /**
95  * Load a private native window API
96  *
97  * This can be used to access the private ANativeWindow API.
98  * \param api doesn't need to be released
99  * \return 0 on success, -1 on error.
100  */
101 int android_loadNativeWindowPrivApi(native_window_priv_api_t *api);
102 
103 /**
104  * Attach or get a JNIEnv*
105  *
106  * The returned JNIEnv* is created from the android JavaVM attached to the VLC
107  * object var.
108  * \return a valid JNIEnv * or NULL. It doesn't need to be released.
109  */
110 JNIEnv *android_getEnv(vlc_object_t *p_obj, const char *psz_thread_name);
111 
112 /**
113  * Create new AWindowHandler
114  *
115  * This handle allow to access IAWindowNativeHandler jobject attached to the
116  * VLC object var.
117  * \return a valid AWindowHandler * or NULL. It must be released with
118  * AWindowHandler_destroy.
119  */
120 AWindowHandler *AWindowHandler_new(vout_window_t *wnd, awh_events_t *p_events);
121 void AWindowHandler_destroy(AWindowHandler *p_awh);
122 
123 /**
124  * Get the public native window API
125  *
126  * Used to access the public ANativeWindow API.
127  * \return a valid native_window_api_t. It doesn't need to be released.
128  */
129 native_window_api_t *AWindowHandler_getANativeWindowAPI(AWindowHandler *p_awh);
130 
131 /**
132  * Get the Video or the Subtitles Android Surface
133  *
134  * \return the surface in a jobject, or NULL. It should be released with
135  * AWindowHandler_releaseANativeWindow() or AWindowHandler_destroy().
136  */
137 jobject AWindowHandler_getSurface(AWindowHandler *p_awh, enum AWindow_ID id);
138 
139 /**
140  * Get the Video or the Subtitles ANativeWindow
141  *
142  * \return a valid ANativeWindow or NULL.It should be released with
143  * AWindowHandler_releaseANativeWindow() or AWindowHandler_destroy.()
144  */
145 ANativeWindow *AWindowHandler_getANativeWindow(AWindowHandler *p_awh,
146                                                enum AWindow_ID id);
147 
148 /**
149  * Release the Video/Subtitles Surface/ANativeWindow
150  */
151 void AWindowHandler_releaseANativeWindow(AWindowHandler *p_awh,
152                                          enum AWindow_ID id);
153 /**
154  * Pre-ICS hack of ANativeWindow_setBuffersGeometry
155  *
156  * This function is a fix up of ANativeWindow_setBuffersGeometry that doesn't
157  * work before Android ICS. It configures the Surface from the Android
158  * MainThread via a SurfaceHolder. It returns VLC_SUCCESS if the Surface was
159  * configured (it returns VLC_EGENERIC after Android ICS).
160  */
161 int AWindowHandler_setBuffersGeometry(AWindowHandler *p_awh, enum AWindow_ID id,
162                                       int i_width, int i_height, int i_format);
163 
164 /**
165  * Returns true if the video layout can be changed
166  */
167 bool AWindowHandler_canSetVideoLayout(AWindowHandler *p_awh);
168 
169 /**
170  * Set the video layout
171  *
172  * Should be called only if AWindowHandler_canSetVideoLayout() returned true
173  */
174 int AWindowHandler_setVideoLayout(AWindowHandler *p_awh,
175                                   int i_width, int i_height,
176                                   int i_visible_width, int i_visible_height,
177                                   int i_sar_num, int i_sar_den);
178 
179 /**
180  * Attach a SurfaceTexture to the OpenGL ES context that is current on the
181  * calling thread.
182  *
183  * See SurfaceTexture Android documentation.
184  * \return 0 on success, -1 on error.
185  */
186 int
187 SurfaceTexture_attachToGLContext(AWindowHandler *p_awh, int tex_name);
188 
189 /**
190  * Detach a SurfaceTexture from the OpenGL ES context that owns the OpenGL ES
191  * texture object.
192  */
193 void
194 SurfaceTexture_detachFromGLContext(AWindowHandler *p_awh);
195 
196 /**
197  * Get a Java Surface from the attached SurfaceTexture
198  *
199  * This object can be used with mediacodec_jni.
200  */
201 static inline jobject
SurfaceTexture_getSurface(AWindowHandler * p_awh)202 SurfaceTexture_getSurface(AWindowHandler *p_awh)
203 {
204     return AWindowHandler_getSurface(p_awh, AWindow_SurfaceTexture);
205 }
206 
207 /**
208  * Get a ANativeWindow from the attached SurfaceTexture
209  *
210  * This pointer can be used with mediacodec_ndk.
211  */
212 static inline ANativeWindow *
SurfaceTexture_getANativeWindow(AWindowHandler * p_awh)213 SurfaceTexture_getANativeWindow(AWindowHandler *p_awh)
214 {
215     return AWindowHandler_getANativeWindow(p_awh, AWindow_SurfaceTexture);
216 }
217 
218 /**
219  * Wait for a new frame and update it
220  *
221  * This function must be called from the OpenGL thread. This is an helper that
222  * waits for a new frame via the Java SurfaceTexture.OnFrameAvailableListener
223  * listener and update the frame via the SurfaceTexture.updateTexImage()
224  * method.
225  *
226  * \param pp_transform_mtx the transform matrix fetched from
227  * SurfaceTexture.getTransformMatrix() after the
228  * SurfaceTexture.updateTexImage() call
229  * \return VLC_SUCCESS or a VLC error
230  */
231 int
232 SurfaceTexture_waitAndUpdateTexImage(AWindowHandler *p_awh,
233                                      const float **pp_transform_mtx);
234