[vlc-commits] [Git][videolan/vlc][master] 13 commits: vout: android: bypass canSetVideoLayout() if forced
Steve Lhomme (@robUx4)
gitlab at videolan.org
Fri Mar 21 14:52:28 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
a2acd45c by Thomas Guillem at 2025-03-21T14:21:27+00:00
vout: android: bypass canSetVideoLayout() if forced
- - - - -
c881d9e5 by Thomas Guillem at 2025-03-21T14:21:27+00:00
filter: egl_surfacetexture: add missing NULL check
- - - - -
f2294466 by Thomas Guillem at 2025-03-21T14:21:27+00:00
filter: egl_surfacetexture: fix leak on error
- - - - -
afa50f98 by Thomas Guillem at 2025-03-21T14:21:27+00:00
vout: android: utils: make jvm optional
jvm might be set to NULL in the next commit.
- - - - -
59414c6c by Thomas Guillem at 2025-03-21T14:21:27+00:00
vout: android: utils: rework capabilities
- - - - -
4982e2ea by Thomas Guillem at 2025-03-21T14:21:27+00:00
vout: android: utils: add SURFACE_VIEW capability
- - - - -
b67f72ee by Thomas Guillem at 2025-03-21T14:21:27+00:00
mediacodec: check AWH_CAPS_SURFACE_VIEW
Don't use a SurfaceTexture if not possible.
This will be used to force MediaCodec in direct rendering when a vout
callback is used (the capability will be off in that case).
- - - - -
75a2783a by Thomas Guillem at 2025-03-21T14:21:27+00:00
vout: android: utils: add AWindowHandler_newFromANWs()
This will be used for ANativeWindow support in
libvlc_video_set_output_callbacks().
- - - - -
a036c337 by Thomas Guillem at 2025-03-21T14:21:27+00:00
vout: android: window: add callback submodule
This will be used for libvlc_video_set_output_callbacks().
- - - - -
679210de by Thomas Guillem at 2025-03-21T14:21:27+00:00
libvlc: add libvlc_video_engine_anw
The ANativeWindow can com from a Java SurfaceView or a NDK
AImageReader. This allow to use libvlc on android without any Java/JNI
support.
- - - - -
17626834 by Thomas Guillem at 2025-03-21T14:21:27+00:00
libvlc: add libvlc_video_set_anw_callbacks helper
- - - - -
75bbeae1 by Thomas Guillem at 2025-03-21T14:21:27+00:00
egl: android: early return in case of error
- - - - -
61cbeec9 by Thomas Guillem at 2025-03-21T14:21:27+00:00
egl: android: call setBuffersGeometry() when needed
This allows to use libvlc_video_engine_anw callbacks with SW decoding.
We don't need to setBuffersGeometry() when using MediaCodec.
- - - - -
9 changed files:
- include/vlc/libvlc_media_player.h
- lib/media_player.c
- modules/codec/omxil/mediacodec.c
- modules/video_filter/egl_surfacetexture.c
- modules/video_output/android/display.c
- modules/video_output/android/utils.c
- modules/video_output/android/utils.h
- modules/video_output/android/window.c
- modules/video_output/opengl/egl.c
Changes:
=====================================
include/vlc/libvlc_media_player.h
=====================================
@@ -626,6 +626,14 @@ typedef struct libvlc_video_output_cfg_t
int opengl_format;
/** currently unused */
void *p_surface;
+ struct {
+ /** Pointer to an ANativeWindow, used for video rendering */
+ void *video;
+ /** Pointer to an ANativeWindow, used for subtitles rendering, if
+ * blending subtitles into the video surface is not possible (when
+ * using MediaCodec with direct hw rendering) */
+ void *subtitle;
+ } anw;
};
/** Video is full range or studio/limited range. */
bool full_range;
@@ -652,9 +660,9 @@ typedef struct libvlc_video_output_cfg_t
* uses to render. The host must set a Render target and call Present()
* when it needs the drawing from VLC to be done. This object is not valid
* anymore after Cleanup is called.
- *
- * Tone mapping, range and color conversion will be done depending on the values
- * set in the output structure.
+ * Tone mapping, range and color conversion will be done depending on the
+ * values set in the output structure. It can be ignored in the \ref
+ * libvlc_video_engine_anw case.
*/
typedef bool (*libvlc_video_update_output_cb)(void* opaque, const libvlc_video_render_cfg_t *cfg,
libvlc_video_output_cfg_t *output );
@@ -747,6 +755,23 @@ typedef enum libvlc_video_engine_t {
libvlc_video_engine_d3d11,
/** Direct3D9 rendering engine */
libvlc_video_engine_d3d9,
+
+ /**
+ * Android ANativeWindow. It can be set in \ref libvlc_video_output_cfg_t
+ * from the \ref libvlc_video_update_output_cb callback. The ANativeWindow
+ * can be created via:
+ * - 'ANativeWindow_fromSurface': from a JAVA SurfaceView
+ * - 'AImageReader_getWindow()': from an 'AImageReader' created with the
+ * following arguments: \verbatim
+ AImageReader_newWithUsage(1, 1 AIMAGE_FORMAT_PRIVATE,
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
+ maxImages, &reader);
+ \endverbatim
+ * The width and height from \ref libvlc_video_render_cfg_t should be
+ * ignored as the video size is overridden by the producer (MediaCodec or
+ * EGL vout).
+ */
+ libvlc_video_engine_anw,
} libvlc_video_engine_t;
@@ -876,9 +901,12 @@ typedef bool( *libvlc_video_output_select_plane_cb )( void *opaque, size_t plane
* \param cleanup_cb callback called to clean up user data
* \param window_cb callback called to setup the window
* \param update_output_cb callback to get the rendering format of the host (cannot be NULL)
- * \param swap_cb callback called after rendering a video frame (cannot be NULL)
- * \param makeCurrent_cb callback called to enter/leave the rendering context (cannot be NULL)
- * \param getProcAddress_cb opengl function loading callback (cannot be NULL for \ref libvlc_video_engine_opengl and for \ref libvlc_video_engine_gles2)
+ * \param swap_cb callback called after rendering a video frame (can only be
+ * NULL when using \ref libvlc_video_engine_anw)
+ * \param makeCurrent_cb callback called to enter/leave the rendering context
+ * (can only be NULL when using \ref libvlc_video_engine_anw)
+ * \param getProcAddress_cb opengl function loading callback (cannot be NULL
+ * for \ref libvlc_video_engine_opengl and for \ref libvlc_video_engine_gles2)
* \param metadata_cb callback to provide frame metadata (D3D11 only)
* \param select_plane_cb callback to select different D3D11 rendering targets
* \param opaque private pointer passed to callbacks
@@ -904,6 +932,22 @@ bool libvlc_video_set_output_callbacks( libvlc_media_player_t *mp,
libvlc_video_output_select_plane_cb select_plane_cb,
void* opaque );
+/**
+ * Helper to setup output_callbacks for \ref libvlc_video_engine_anw
+ */
+static inline bool
+libvlc_video_set_anw_callbacks( libvlc_media_player_t *mp,
+ libvlc_video_output_setup_cb setup_cb,
+ libvlc_video_output_cleanup_cb cleanup_cb,
+ libvlc_video_update_output_cb update_output_cb,
+ void *opaque )
+{
+ return libvlc_video_set_output_callbacks( mp, libvlc_video_engine_anw,
+ setup_cb, cleanup_cb, NULL,
+ update_output_cb, NULL, NULL,
+ NULL, NULL, NULL, opaque );
+}
+
/**
* Set the handler where the media player should display its video output.
*
=====================================
lib/media_player.c
=====================================
@@ -1136,6 +1136,13 @@ bool libvlc_video_set_output_callbacks(libvlc_media_player_t *mp,
var_SetString ( mp, "vout", "direct3d9" );
var_SetString ( mp, "dec-dev", "d3d9" );
}
+ else if ( engine == libvlc_video_engine_anw )
+ {
+ /* Force android-display is using MediaCodec or fallback to GL (any) */
+ var_SetString ( mp, "vout", "android-display,any" );
+ var_SetString ( mp, "dec-dev", "android" );
+ var_SetString( mp, "window", "android");
+ }
else if ( engine == libvlc_video_engine_disable )
{
// use the default display module
=====================================
modules/codec/omxil/mediacodec.c
=====================================
@@ -720,10 +720,14 @@ CreateVideoContext(decoder_t *p_dec)
* to modify its layout. */
p_sys->video.surfacetexture = NULL;
- bool use_surfacetexture =
- p_dec->fmt_out.video.projection_mode != PROJECTION_MODE_RECTANGULAR
- || (!p_sys->api.b_support_rotation && p_dec->fmt_out.video.orientation != ORIENT_NORMAL)
- || !AWindowHandler_canSetVideoLayout(awh);
+ int awh_caps = AWindowHandler_getCapabilities(awh);
+ bool can_set_video_layout = awh_caps & AWH_CAPS_SET_VIDEO_LAYOUT;
+ bool can_use_surfacetexture = awh_caps & AWH_CAPS_SURFACE_VIEW;
+
+ bool use_surfacetexture = can_use_surfacetexture
+ && (p_dec->fmt_out.video.projection_mode != PROJECTION_MODE_RECTANGULAR
+ || (!p_sys->api.b_support_rotation && p_dec->fmt_out.video.orientation != ORIENT_NORMAL)
+ || !can_set_video_layout);
if (!use_surfacetexture)
{
=====================================
modules/video_filter/egl_surfacetexture.c
=====================================
@@ -129,6 +129,8 @@ static picture_context_t *CreatePictureContext(vlc_gl_t *gl)
struct video_ctx *vctx = GetVCtx(gl);
ctx->texture = vlc_asurfacetexture_New(gl->device->opaque, false);
+ if (ctx->texture == NULL)
+ goto error;
struct ANativeWindow *window = ctx->texture->window;
native_window_api_t *api =
@@ -142,6 +144,7 @@ static picture_context_t *CreatePictureContext(vlc_gl_t *gl)
if (ctx->surface == EGL_NO_SURFACE)
{
msg_Err(gl, "cannot create EGL window surface");
+ vlc_asurfacetexture_Delete(ctx->texture);
goto error;
}
=====================================
modules/video_output/android/display.c
=====================================
@@ -62,6 +62,7 @@ struct subpicture
struct sys
{
AWindowHandler *awh;
+ bool can_set_video_layout;
android_video_context_t *avctx;
struct subpicture sub;
};
@@ -380,6 +381,8 @@ static void Display(vout_display_t *vd, picture_t *picture)
static void SetVideoLayout(vout_display_t *vd)
{
struct sys *sys = vd->sys;
+ if (!sys->can_set_video_layout)
+ return;
video_format_t rot_fmt;
video_format_ApplyRotation(&rot_fmt, vd->source);
@@ -428,7 +431,8 @@ static void Close(vout_display_t *vd)
{
struct sys *sys = vd->sys;
- AWindowHandler_setVideoLayout(sys->awh, 0, 0, 0, 0, 0, 0);
+ if (sys->can_set_video_layout)
+ AWindowHandler_setVideoLayout(sys->awh, 0, 0, 0, 0, 0, 0);
if (sys->sub.window != NULL)
subpicture_CloseDisplay(vd);
@@ -444,11 +448,14 @@ static int Open(vout_display_t *vd,
if (embed->type != VLC_WINDOW_TYPE_ANDROID_NATIVE
|| fmtp->i_chroma != VLC_CODEC_ANDROID_OPAQUE
- || context == NULL
- || !AWindowHandler_canSetVideoLayout(awh))
+ || context == NULL)
return VLC_EGENERIC;
- if (!vd->obj.force && fmtp->projection_mode != PROJECTION_MODE_RECTANGULAR)
+ bool can_set_video_layout = AWindowHandler_getCapabilities(awh)
+ & AWH_CAPS_SET_VIDEO_LAYOUT;
+ if (!vd->obj.force
+ && (fmtp->projection_mode != PROJECTION_MODE_RECTANGULAR
+ || !can_set_video_layout))
{
/* Let the gles2 vout handle projection */
return VLC_EGENERIC;
@@ -460,6 +467,7 @@ static int Open(vout_display_t *vd,
return VLC_ENOMEM;
sys->awh = awh;
+ sys->can_set_video_layout = can_set_video_layout;
sys->avctx = vlc_video_context_GetPrivate(context, VLC_VIDEO_CONTEXT_AWINDOW);
assert(sys->avctx);
if (sys->avctx->texture != NULL)
=====================================
modules/video_output/android/utils.c
=====================================
@@ -40,6 +40,7 @@
typedef ANativeWindow* (*ptr_ANativeWindow_fromSurface)(JNIEnv*, jobject);
typedef ANativeWindow* (*ptr_ANativeWindow_fromSurfaceTexture)(JNIEnv*, jobject);
+typedef void (*ptr_ANativeWindow_acquire)(ANativeWindow*);
typedef void (*ptr_ANativeWindow_release)(ANativeWindow*);
typedef void (*ptr_ASurfaceTexture_getTransformMatrix)
@@ -130,6 +131,7 @@ struct AWindowHandler
void *p_anw_dl;
ptr_ANativeWindow_fromSurface pf_winFromSurface;
+ ptr_ANativeWindow_acquire pf_winAcquire;
ptr_ANativeWindow_release pf_winRelease;
native_window_api_t anw_api;
@@ -139,7 +141,7 @@ struct AWindowHandler
struct {
awh_events_t cb;
} event;
- bool b_has_video_layout_listener;
+ int capabilities;
struct {
jfloatArray jtransform_mtx_array;
@@ -321,6 +323,7 @@ static void
LoadNativeSurfaceAPI(AWindowHandler *p_awh)
{
p_awh->pf_winFromSurface = NativeSurface_fromSurface;
+ p_awh->pf_winAcquire = NULL;
p_awh->pf_winRelease = NativeSurface_release;
p_awh->anw_api.winLock = NativeSurface_lock;
p_awh->anw_api.unlockAndPost = NativeSurface_unlockAndPost;
@@ -574,12 +577,13 @@ LoadNativeWindowAPI(AWindowHandler *p_awh)
}
p_awh->pf_winFromSurface = dlsym(p_library, "ANativeWindow_fromSurface");
+ p_awh->pf_winAcquire = dlsym(p_library, "ANativeWindow_acquire");
p_awh->pf_winRelease = dlsym(p_library, "ANativeWindow_release");
p_awh->anw_api.winLock = dlsym(p_library, "ANativeWindow_lock");
p_awh->anw_api.unlockAndPost = dlsym(p_library, "ANativeWindow_unlockAndPost");
p_awh->anw_api.setBuffersGeometry = dlsym(p_library, "ANativeWindow_setBuffersGeometry");
- if (p_awh->pf_winFromSurface && p_awh->pf_winRelease
+ if (p_awh->pf_winFromSurface && p_awh->pf_winAcquire && p_awh->pf_winRelease
&& p_awh->anw_api.winLock && p_awh->anw_api.unlockAndPost
&& p_awh->anw_api.setBuffersGeometry)
{
@@ -744,6 +748,8 @@ error:
static JNIEnv*
AWindowHandler_getEnv(AWindowHandler *p_awh)
{
+ if (p_awh->p_jvm == NULL)
+ return NULL;
return android_getEnvCommon(NULL, p_awh->p_jvm, "AWindowHandler");
}
@@ -820,10 +826,12 @@ AWindowHandler_new(vlc_object_t *obj, vlc_window_t *wnd, awh_events_t *p_events)
}
LoadNativeWindowAPI(p_awh);
- p_awh->b_has_video_layout_listener =
- wnd && flags & AWINDOW_REGISTER_FLAGS_HAS_VIDEO_LAYOUT_LISTENER;
+ p_awh->capabilities = 0;
+
+ if (wnd && flags & AWINDOW_REGISTER_FLAGS_HAS_VIDEO_LAYOUT_LISTENER)
+ p_awh->capabilities |= AWH_CAPS_SET_VIDEO_LAYOUT;
- if (p_awh->b_has_video_layout_listener && p_events != NULL)
+ if (p_awh->capabilities & AWH_CAPS_SET_VIDEO_LAYOUT && p_events != NULL)
{
/* XXX: HACK: force mediacodec to setup an OpenGL surface when the vout
* is forced to gles2. Indeed, setting b_has_video_layout_listener to
@@ -833,13 +841,47 @@ AWindowHandler_new(vlc_object_t *obj, vlc_window_t *wnd, awh_events_t *p_events)
if (vout_modules
&& (strncmp(vout_modules, "gles2", sizeof("gles2") - 1) == 0
|| strncmp(vout_modules, "opengles2", sizeof("opengles2") - 1) == 0))
- p_awh->b_has_video_layout_listener = false;
+ p_awh->capabilities &= ~AWH_CAPS_SET_VIDEO_LAYOUT;
free(vout_modules);
}
+ p_awh->capabilities |= AWH_CAPS_SURFACE_VIEW;
+
return p_awh;
}
+AWindowHandler *
+AWindowHandler_newFromANWs(vlc_object_t *obj, ANativeWindow *video,
+ ANativeWindow *subtitle)
+{
+ (void) obj;
+ AWindowHandler *awh = calloc(1, sizeof(AWindowHandler));
+ if (!awh)
+ return NULL;
+
+ awh->p_jvm = NULL;
+ awh->jobj = NULL;
+ awh->jfields = (struct vlc_android_jfields) { .AWindow.clazz = NULL };
+ awh->wnd = NULL;
+
+ LoadNativeWindowAPI(awh);
+ if (awh->pf_winAcquire == NULL)
+ {
+ free(awh);
+ return NULL;
+ }
+
+ awh->views[AWindow_Video].p_anw = video;
+ awh->pf_winAcquire(video);
+ awh->capabilities = 0;
+
+ awh->views[AWindow_Subtitles].p_anw = subtitle;
+ if (subtitle != NULL)
+ awh->pf_winAcquire(subtitle);
+
+ return awh;
+}
+
static void
AWindowHandler_releaseANativeWindowEnv(AWindowHandler *p_awh, JNIEnv *p_env,
enum AWindow_ID id)
@@ -852,7 +894,7 @@ AWindowHandler_releaseANativeWindowEnv(AWindowHandler *p_awh, JNIEnv *p_env,
p_awh->views[id].p_anw = NULL;
}
- if (p_awh->views[id].jsurface)
+ if (p_env != NULL && p_awh->views[id].jsurface)
{
(*p_env)->DeleteGlobalRef(p_env, p_awh->views[id].jsurface);
p_awh->views[id].jsurface = NULL;
@@ -874,16 +916,20 @@ AWindowHandler_destroy(AWindowHandler *p_awh)
if (p_awh->jobj)
JNI_ANWCALL(CallVoidMethod, unregisterNative);
- AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_Video);
- AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_Subtitles);
+ }
+
+ AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_Video);
+ AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_Subtitles);
+
+ if (p_env != NULL)
+ {
if (p_awh->jobj)
(*p_env)->DeleteGlobalRef(p_env, p_awh->jobj);
+ (*p_env)->DeleteGlobalRef(p_env, p_awh->stex.jtransform_mtx_array);
}
if (p_awh->p_anw_dl)
dlclose(p_awh->p_anw_dl);
-
- (*p_env)->DeleteGlobalRef(p_env, p_awh->stex.jtransform_mtx_array);
free(p_awh);
}
@@ -1108,6 +1154,8 @@ error:
struct vlc_asurfacetexture *
vlc_asurfacetexture_New(AWindowHandler *p_awh, bool single_buffer)
{
+ if (p_awh->p_jvm == NULL)
+ return NULL;
JNIEnv *p_env = android_getEnvCommon(NULL, p_awh->p_jvm, "SurfaceTexture");
struct vlc_asurfacetexture_priv *surfacetexture =
CreateSurfaceTexture(p_awh, p_env, single_buffer);
@@ -1150,12 +1198,10 @@ AWindowHandler_getANativeWindow(AWindowHandler *p_awh, enum AWindow_ID id)
{
assert(id < AWindow_Max);
- JNIEnv *p_env;
-
if (p_awh->views[id].p_anw)
return p_awh->views[id].p_anw;
- p_env = AWindowHandler_getEnv(p_awh);
+ JNIEnv *p_env = AWindowHandler_getEnv(p_awh);
if (!p_env)
return NULL;
@@ -1187,8 +1233,7 @@ void AWindowHandler_releaseANativeWindow(AWindowHandler *p_awh,
enum AWindow_ID id)
{
JNIEnv *p_env = AWindowHandler_getEnv(p_awh);
- if (p_env)
- AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, id);
+ AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, id);
}
static inline AWindowHandler *jlong_AWindowHandler(jlong handle)
@@ -1218,10 +1263,10 @@ AndroidNativeWindow_onWindowSize(JNIEnv* env, jobject clazz, jlong handle,
p_awh->event.cb.on_new_window_size(p_awh->wnd, width, height);
}
-bool
-AWindowHandler_canSetVideoLayout(AWindowHandler *p_awh)
+int
+AWindowHandler_getCapabilities(AWindowHandler *p_awh)
{
- return p_awh->b_has_video_layout_listener && p_awh->wnd != NULL;
+ return p_awh->capabilities;
}
int
@@ -1230,7 +1275,7 @@ AWindowHandler_setVideoLayout(AWindowHandler *p_awh,
int i_visible_width, int i_visible_height,
int i_sar_num, int i_sar_den)
{
- assert(p_awh->b_has_video_layout_listener);
+ assert(p_awh->capabilities & AWH_CAPS_SET_VIDEO_LAYOUT);
JNIEnv *p_env = AWindowHandler_getEnv(p_awh);
if (!p_env)
return VLC_EGENERIC;
=====================================
modules/video_output/android/utils.h
=====================================
@@ -33,6 +33,11 @@
#include <vlc_vout_display.h>
#include <vlc_common.h>
+/* AWH using a VideoLAN AWindow helpers */
+#define AWH_CAPS_SET_VIDEO_LAYOUT 0x1
+/* AWH backed by a Android SurfaceView */
+#define AWH_CAPS_SURFACE_VIEW 0x2
+
typedef struct AWindowHandler AWindowHandler;
typedef struct ASurfaceTexture ASurfaceTexture;
@@ -125,6 +130,10 @@ struct vlc_asurfacetexture_operations
AWindowHandler *AWindowHandler_new(vlc_object_t *obj, vlc_window_t *wnd, awh_events_t *p_events);
void AWindowHandler_destroy(AWindowHandler *p_awh);
+AWindowHandler *
+AWindowHandler_newFromANWs(vlc_object_t *obj, ANativeWindow *video,
+ ANativeWindow *subtitle);
+
/**
* Get the public native window API
*
@@ -156,15 +165,12 @@ ANativeWindow *AWindowHandler_getANativeWindow(AWindowHandler *p_awh,
void AWindowHandler_releaseANativeWindow(AWindowHandler *p_awh,
enum AWindow_ID id);
-/**
- * Returns true if the video layout can be changed
- */
-bool AWindowHandler_canSetVideoLayout(AWindowHandler *p_awh);
+int AWindowHandler_getCapabilities(AWindowHandler *p_awh);
/**
* Set the video layout
*
- * Should be called only if AWindowHandler_canSetVideoLayout() returned true
+ * Should be called only if AWindowHandler_getCapabilities() has AWH_CAPS_SET_VIDEO_LAYOUT
*/
int AWindowHandler_setVideoLayout(AWindowHandler *p_awh,
int i_width, int i_height,
=====================================
modules/video_output/android/window.c
=====================================
@@ -33,6 +33,9 @@
#include <vlc_window.h>
#include <vlc_codec.h>
+#include <vlc/libvlc.h>
+#include <vlc/libvlc_media_player.h>
+
#include <dlfcn.h>
#include <jni.h>
@@ -44,6 +47,12 @@ typedef struct
vlc_wasync_resize_compressor_t compressor;
} vout_window_sys_t;
+struct vout_window_sys_cb
+{
+ void *opaque;
+ libvlc_video_output_cleanup_cb cleanup_cb;
+};
+
static void OnNewWindowSize(vlc_window_t *wnd,
unsigned i_width, unsigned i_height)
{
@@ -108,6 +117,76 @@ static int Open(vlc_window_t *wnd)
return VLC_SUCCESS;
}
+static void DestroyCallback(vlc_window_t *wnd)
+{
+ struct vout_window_sys_cb *sys = wnd->sys;
+ if (sys->cleanup_cb != NULL)
+ sys->cleanup_cb(sys->opaque);
+}
+
+static int OpenCallback(vlc_window_t *wnd)
+{
+ static const struct vlc_window_operations ops = {
+ .destroy = DestroyCallback,
+ };
+
+ libvlc_video_engine_t engine = var_InheritInteger(wnd, "vout-cb-type");
+ if (engine != libvlc_video_engine_anw)
+ return VLC_EGENERIC;
+
+ struct vout_window_sys_cb *sys = vlc_obj_malloc(VLC_OBJECT(wnd), sizeof (*sys));
+ if (sys == NULL)
+ return VLC_ENOMEM;
+
+ sys->opaque = var_InheritAddress(wnd, "vout-cb-opaque");
+ libvlc_video_output_setup_cb setup_cb = var_InheritAddress(wnd, "vout-cb-setup");
+ libvlc_video_update_output_cb update_cb = var_InheritAddress(wnd, "vout-cb-update-output");
+ sys->cleanup_cb = var_InheritAddress(wnd, "vout-cb-cleanup");
+
+ if (update_cb == NULL)
+ return VLC_EGENERIC;
+
+ if (setup_cb != NULL)
+ {
+ const libvlc_video_setup_device_cfg_t cfg = {
+ .hardware_decoding = true,
+ };
+ libvlc_video_setup_device_info_t out;
+ bool success = setup_cb(&sys->opaque, &cfg, &out);
+ if (!success)
+ return VLC_EGENERIC;
+ (void) out; /* Ignored on Android */
+ }
+
+ /* Default values, parameters are overridden by the producer */
+ const libvlc_video_render_cfg_t render_cfg = {
+ .width = 1,
+ .height = 1,
+ };
+ libvlc_video_output_cfg_t out = { .anw = { NULL, NULL } };
+ bool success = update_cb(sys->opaque, &render_cfg, &out);
+ if (!success)
+ goto error;
+ assert(out.anw.video != NULL);
+
+ AWindowHandler *awh =
+ AWindowHandler_newFromANWs(VLC_OBJECT(wnd), out.anw.video, out.anw.subtitle);
+ if (awh == NULL)
+ goto error;
+
+ wnd->sys = sys;
+ wnd->type = VLC_WINDOW_TYPE_ANDROID_NATIVE;
+ wnd->display.anativewindow = awh;
+ wnd->handle.android_id = AWindow_Video;
+ wnd->ops = &ops;
+
+ return VLC_SUCCESS;
+error:
+ if (sys->cleanup_cb != NULL)
+ sys->cleanup_cb(sys->opaque);
+ return VLC_EGENERIC;
+}
+
static int
OpenDecDevice(vlc_decoder_device *device, vlc_window_t *window)
{
@@ -140,6 +219,9 @@ vlc_module_begin()
set_subcategory(SUBCAT_VIDEO_VOUT)
set_capability("vout window", 10)
set_callback(Open)
+ add_submodule ()
+ set_capability("vout window", 11)
+ set_callback(OpenCallback)
add_submodule ()
set_callback_dec_device(OpenDecDevice, 1)
add_shortcut("android")
=====================================
modules/video_output/opengl/egl.c
=====================================
@@ -521,9 +521,18 @@ static EGLSurface CreateSurface(vlc_gl_t *gl, EGLDisplay dpy, EGLConfig config,
AWindowHandler_getANativeWindow(gl->surface->display.anativewindow,
gl->surface->handle.android_id);
- (void) width; (void) height;
- return (anw != NULL) ? eglCreateWindowSurface(dpy, config, anw, NULL)
- : EGL_NO_SURFACE;
+ if (anw == NULL)
+ return EGL_NO_SURFACE;
+
+ int awh_caps = AWindowHandler_getCapabilities(gl->surface->display.anativewindow);
+ if ((awh_caps & AWH_CAPS_SURFACE_VIEW) == 0)
+ {
+ native_window_api_t *api =
+ AWindowHandler_getANativeWindowAPI(gl->surface->display.anativewindow);
+ api->setBuffersGeometry(anw, width, height, AHARDWAREBUFFER_FORMAT_BLOB);
+ }
+
+ return eglCreateWindowSurface(dpy, config, anw, NULL);
}
static void ReleaseDisplay(vlc_gl_t *gl)
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f1f05aa2b98901f77f947f5aed39ee79eba3fcaa...61cbeec966d2220929d80f3df9d3b444f9593cf8
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f1f05aa2b98901f77f947f5aed39ee79eba3fcaa...61cbeec966d2220929d80f3df9d3b444f9593cf8
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list