You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
13 KiB
385 lines
13 KiB
/*****************************************************************************
|
|
* utils.h: shared code between Android vout modules.
|
|
*****************************************************************************
|
|
* Copyright (C) 2014-2015 VLC authors and VideoLAN
|
|
*
|
|
* Authors: Felix Abecassis <felix.abecassis@gmail.com>
|
|
* Thomas Guillem <thomas@gllm.fr>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
|
|
#include <jni.h>
|
|
#include <android/native_window.h>
|
|
#include <android/native_window_jni.h>
|
|
#include <android/hardware_buffer.h>
|
|
#include <android/input.h>
|
|
#include <android/surface_control.h>
|
|
#include <android/hdr_metadata.h>
|
|
#include <android/data_space.h>
|
|
#include <media/NdkImageReader.h>
|
|
|
|
#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
|
|
|
|
/*
|
|
* AImageReader function pointers
|
|
*/
|
|
typedef int32_t (*pfn_AImageReader_newWithUsage)(
|
|
int32_t width, int32_t height, int32_t format, uint64_t usage,
|
|
int32_t maxImages, AImageReader **reader);
|
|
typedef void (*pfn_AImageReader_delete)(AImageReader *reader);
|
|
typedef int32_t (*pfn_AImageReader_getWindow)(
|
|
AImageReader *reader, ANativeWindow **window);
|
|
typedef int32_t (*pfn_AImageReader_acquireNextImageAsync)(
|
|
AImageReader *reader, AImage **image, int *acquireFenceFd);
|
|
typedef void (*pfn_AImage_deleteAsync)(AImage *image, int releaseFenceFd);
|
|
typedef int32_t (*pfn_AImage_getHardwareBuffer)(
|
|
const AImage *image, struct AHardwareBuffer **buffer);
|
|
typedef int32_t (*pfn_AImage_getTimestamp)(
|
|
const AImage *image, int64_t *timestampNs);
|
|
typedef int32_t (*pfn_AImage_getCropRect)(
|
|
const AImage *image, AImageCropRect *rect);
|
|
typedef int32_t (*pfn_AImage_getWidth)(
|
|
const AImage *image, int32_t *width);
|
|
typedef int32_t (*pfn_AImage_getHeight)(
|
|
const AImage *image, int32_t *height);
|
|
typedef int32_t (*pfn_AImageReader_setImageListener)(
|
|
AImageReader *reader, AImageReader_ImageListener *listener);
|
|
typedef int (*pfn_sync_merge)(const char *name, int fd1, int fd2);
|
|
|
|
typedef int32_t (*pfn_AHardwareBuffer_getId)(
|
|
const struct AHardwareBuffer *buffer, uint64_t *outId);
|
|
typedef void (*pfn_AHardwareBuffer_describe)(
|
|
const struct AHardwareBuffer *buffer, AHardwareBuffer_Desc *outDesc);
|
|
|
|
/*
|
|
* ASurfaceControl function pointers
|
|
*/
|
|
typedef ASurfaceControl* (*pfn_ASurfaceControl_createFromWindow)(
|
|
ANativeWindow *parent, const char *debug_name);
|
|
typedef void (*pfn_ASurfaceControl_release)(ASurfaceControl *surface_control);
|
|
typedef ASurfaceTransaction* (*pfn_ASurfaceTransaction_create)(void);
|
|
typedef void (*pfn_ASurfaceTransaction_delete)(ASurfaceTransaction *transaction);
|
|
typedef void (*pfn_ASurfaceTransaction_apply)(ASurfaceTransaction *transaction);
|
|
typedef void (*pfn_ASurfaceTransaction_setBuffer)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
struct AHardwareBuffer *buffer, int acquire_fence_fd);
|
|
typedef void (*pfn_ASurfaceTransaction_setVisibility)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
int8_t visibility);
|
|
typedef void (*pfn_ASurfaceTransaction_setBufferTransparency)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
int8_t transparency);
|
|
typedef void (*pfn_ASurfaceTransaction_setBufferDataSpace)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
int32_t data_space);
|
|
typedef void (*pfn_ASurfaceTransaction_setHdrMetadata_smpte2086)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
struct AHdrMetadata_smpte2086 *metadata);
|
|
typedef void (*pfn_ASurfaceTransaction_setHdrMetadata_cta861_3)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
struct AHdrMetadata_cta861_3 *metadata);
|
|
typedef void (*pfn_ASurfaceTransaction_setOnComplete)(
|
|
ASurfaceTransaction *transaction, void *context,
|
|
void (*func)(void *context, ASurfaceTransactionStats *stats));
|
|
typedef void (*pfn_ASurfaceTransaction_setCrop)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
const ARect *crop);
|
|
typedef void (*pfn_ASurfaceTransaction_setPosition)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
int32_t x, int32_t y);
|
|
typedef void (*pfn_ASurfaceTransaction_setBufferTransform)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
int32_t transform);
|
|
typedef void (*pfn_ASurfaceTransaction_setScale)(
|
|
ASurfaceTransaction *transaction, ASurfaceControl *surface_control,
|
|
float xScale, float yScale);
|
|
typedef void (*pfn_ASurfaceTransaction_setDesiredPresentTime)(
|
|
ASurfaceTransaction* transaction,
|
|
int64_t desiredPresentTime);
|
|
typedef int (*pfn_ASurfaceTransactionStats_getPreviousReleaseFenceFd)(
|
|
ASurfaceTransactionStats *stats, ASurfaceControl *surface_control);
|
|
|
|
struct aimage_reader_api
|
|
{
|
|
/* AImageReader, API 31+ (because AHardwareBuffer) */
|
|
struct {
|
|
pfn_AImageReader_newWithUsage newWithUsage;
|
|
pfn_AImageReader_delete delete;
|
|
pfn_AImageReader_getWindow getWindow;
|
|
pfn_AImageReader_acquireNextImageAsync acquireNextImageAsync;
|
|
pfn_AImageReader_setImageListener setImageListener;
|
|
} AImageReader;
|
|
struct {
|
|
pfn_AImage_deleteAsync deleteAsync;
|
|
pfn_AImage_getHardwareBuffer getHardwareBuffer;
|
|
pfn_AImage_getTimestamp getTimestamp;
|
|
pfn_AImage_getCropRect getCropRect;
|
|
pfn_AImage_getWidth getWidth;
|
|
pfn_AImage_getHeight getHeight;
|
|
} AImage;
|
|
pfn_sync_merge sync_merge;
|
|
struct {
|
|
pfn_AHardwareBuffer_getId getId;
|
|
pfn_AHardwareBuffer_describe describe;
|
|
} AHardwareBuffer;
|
|
};
|
|
|
|
struct asurface_control_api
|
|
{
|
|
struct {
|
|
pfn_ASurfaceControl_createFromWindow createFromWindow;
|
|
pfn_ASurfaceControl_release release;
|
|
} ASurfaceControl;
|
|
struct {
|
|
pfn_ASurfaceTransaction_create create;
|
|
pfn_ASurfaceTransaction_delete delete;
|
|
pfn_ASurfaceTransaction_apply apply;
|
|
pfn_ASurfaceTransaction_setBuffer setBuffer;
|
|
pfn_ASurfaceTransaction_setVisibility setVisibility;
|
|
pfn_ASurfaceTransaction_setBufferTransparency setBufferTransparency;
|
|
pfn_ASurfaceTransaction_setBufferDataSpace setBufferDataSpace;
|
|
pfn_ASurfaceTransaction_setHdrMetadata_smpte2086 setHdrMetadata_smpte2086;
|
|
pfn_ASurfaceTransaction_setHdrMetadata_cta861_3 setHdrMetadata_cta861_3;
|
|
pfn_ASurfaceTransaction_setOnComplete setOnComplete;
|
|
pfn_ASurfaceTransaction_setCrop setCrop;
|
|
pfn_ASurfaceTransaction_setPosition setPosition;
|
|
pfn_ASurfaceTransaction_setBufferTransform setBufferTransform;
|
|
pfn_ASurfaceTransaction_setScale setScale;
|
|
pfn_ASurfaceTransaction_setDesiredPresentTime setDesiredPresentTime;
|
|
} ASurfaceTransaction;
|
|
struct {
|
|
pfn_ASurfaceTransactionStats_getPreviousReleaseFenceFd getPreviousReleaseFenceFd;
|
|
} ASurfaceTransactionStats;
|
|
};
|
|
|
|
typedef struct AWindowHandler AWindowHandler;
|
|
typedef struct ASurfaceTexture ASurfaceTexture;
|
|
|
|
enum AWindow_ID {
|
|
AWindow_Video,
|
|
AWindow_Subtitles,
|
|
AWindow_Max,
|
|
};
|
|
|
|
struct awh_mouse_coords
|
|
{
|
|
int i_action;
|
|
int i_button;
|
|
int i_x;
|
|
int i_y;
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
void (*on_new_window_size)(vlc_window_t *wnd, unsigned i_width,
|
|
unsigned i_height);
|
|
void (*on_new_mouse_coords)(vlc_window_t *wnd,
|
|
const struct awh_mouse_coords *coords);
|
|
} awh_events_t;
|
|
|
|
typedef struct android_video_context_t android_video_context_t;
|
|
|
|
struct android_video_context_t
|
|
{
|
|
struct aimage_reader_api *air_api;
|
|
struct asurface_control_api *asc_api;
|
|
AImageReader *air;
|
|
|
|
struct vlc_asurfacetexture *texture;
|
|
void *dec_opaque;
|
|
bool (*render)(struct picture_context_t *ctx);
|
|
bool (*render_ts)(struct picture_context_t *ctx, vlc_tick_t ts);
|
|
|
|
struct vlc_asurfacetexture *
|
|
(*get_texture)(struct picture_context_t *ctx);
|
|
};
|
|
|
|
struct android_picture_ctx
|
|
{
|
|
picture_context_t s;
|
|
AImage *image;
|
|
int fence_fd;
|
|
int read_fence_fd;
|
|
vlc_atomic_rc_t rc;
|
|
ASurfaceControl *sc;
|
|
};
|
|
|
|
static inline int
|
|
android_picture_ctx_get_fence_fd(struct android_picture_ctx *apctx)
|
|
{
|
|
return (apctx->fence_fd >= 0) ? dup(apctx->fence_fd) : -1;
|
|
}
|
|
|
|
static inline void
|
|
android_picture_ctx_set_read_fence(struct android_picture_ctx *apctx, int fd)
|
|
{
|
|
assert(fd >= 0);
|
|
if (apctx->read_fence_fd < 0)
|
|
apctx->read_fence_fd = fd;
|
|
else
|
|
{
|
|
android_video_context_t *avctx =
|
|
vlc_video_context_GetPrivate(apctx->s.vctx, VLC_VIDEO_CONTEXT_AWINDOW);
|
|
|
|
int merged = avctx->air_api->sync_merge("vlc_read_fence", apctx->read_fence_fd, fd);
|
|
close(apctx->read_fence_fd);
|
|
close(fd);
|
|
apctx->read_fence_fd = merged;
|
|
}
|
|
}
|
|
|
|
struct vlc_asurfacetexture
|
|
{
|
|
struct ANativeWindow *window;
|
|
jobject *jsurface;
|
|
|
|
const struct vlc_asurfacetexture_operations *ops;
|
|
};
|
|
|
|
/**
|
|
* Wrapper structure for Android SurfaceTexture object.
|
|
*
|
|
* It can use either the NDK API or JNI API.
|
|
*/
|
|
struct vlc_asurfacetexture_operations
|
|
{
|
|
int (*attach_to_gl_context)(
|
|
struct vlc_asurfacetexture *surface,
|
|
uint32_t tex_name);
|
|
|
|
void (*detach_from_gl_context)(
|
|
struct vlc_asurfacetexture *surface);
|
|
|
|
int (*update_tex_image)(
|
|
struct vlc_asurfacetexture *surface,
|
|
const float **pp_transform_mtx);
|
|
|
|
void (*release_tex_image)(
|
|
struct vlc_asurfacetexture *st);
|
|
|
|
void (*destroy)(
|
|
struct vlc_asurfacetexture *surface);
|
|
};
|
|
|
|
/**
|
|
* Create new AWindowHandler
|
|
*
|
|
* This handle allow to access IAWindowNativeHandler jobject attached to the
|
|
* VLC object var.
|
|
* \return a valid AWindowHandler * or NULL. It must be released with
|
|
* AWindowHandler_destroy.
|
|
*/
|
|
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);
|
|
|
|
struct aimage_reader_api *
|
|
AWindowHandler_getAImageReaderApi(AWindowHandler *p_awh);
|
|
|
|
struct asurface_control_api *
|
|
AWindowHandler_getASurfaceControlApi(AWindowHandler *p_awh);
|
|
|
|
/**
|
|
* Get the Video or the Subtitles ANativeWindow
|
|
*
|
|
* \return a valid ANativeWindow or NULL.It should be released with
|
|
* AWindowHandler_releaseANativeWindow() or AWindowHandler_destroy.()
|
|
*/
|
|
ANativeWindow *AWindowHandler_getANativeWindow(AWindowHandler *p_awh,
|
|
enum AWindow_ID id);
|
|
|
|
/**
|
|
* Release the Video/Subtitles Surface/ANativeWindow
|
|
*/
|
|
void AWindowHandler_releaseANativeWindow(AWindowHandler *p_awh,
|
|
enum AWindow_ID id);
|
|
|
|
int AWindowHandler_getCapabilities(AWindowHandler *p_awh);
|
|
|
|
/**
|
|
* Set the video layout
|
|
*
|
|
* 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,
|
|
int i_visible_width, int i_visible_height,
|
|
int i_sar_num, int i_sar_den);
|
|
|
|
/**
|
|
* Attach a SurfaceTexture to the OpenGL ES context that is current on the
|
|
* calling thread.
|
|
*
|
|
* See SurfaceTexture Android documentation.
|
|
* \return 0 on success, -1 on error.
|
|
*/
|
|
int
|
|
SurfaceTexture_attachToGLContext(struct vlc_asurfacetexture *st, uint32_t tex_name);
|
|
|
|
/**
|
|
* Detach a SurfaceTexture from the OpenGL ES context that owns the OpenGL ES
|
|
* texture object.
|
|
*/
|
|
void
|
|
SurfaceTexture_detachFromGLContext(struct vlc_asurfacetexture *st);
|
|
|
|
/**
|
|
* Create a new SurfaceTexture object.
|
|
*
|
|
* See Android SurfaceTexture
|
|
*/
|
|
struct vlc_asurfacetexture *
|
|
vlc_asurfacetexture_New(AWindowHandler *p_awh, bool single_buffer);
|
|
|
|
/**
|
|
* Delete a SurfaceTexture object created with SurfaceTexture_New.
|
|
*/
|
|
static inline void
|
|
vlc_asurfacetexture_Delete(struct vlc_asurfacetexture *st)
|
|
{
|
|
if (st->ops->destroy)
|
|
st->ops->destroy(st);
|
|
}
|
|
|
|
/**
|
|
* Update the SurfaceTexture to the most recent frame.
|
|
*
|
|
* \param pp_transform_mtx the transform matrix fetched from
|
|
* SurfaceTexture.getTransformMatrix() after the
|
|
* SurfaceTexture.updateTexImage() call
|
|
* \return VLC_SUCCESS or a VLC error
|
|
*/
|
|
int
|
|
SurfaceTexture_updateTexImage(struct vlc_asurfacetexture *st, const float **pp_transform_mtx);
|
|
|
|
void
|
|
SurfaceTexture_releaseTexImage(struct vlc_asurfacetexture *st);
|
|
|