|
|
|
@ -690,23 +690,24 @@ GetPictureContext(decoder_t *p_dec, unsigned index) |
|
|
|
} |
|
|
|
|
|
|
|
static int |
|
|
|
CreateSurface(decoder_t *p_dec, AWindowHandler *awh) |
|
|
|
CreateSurface(decoder_t *p_dec, vlc_decoder_device *dec_dev, |
|
|
|
AWindowHandler *awh, bool use_surfacetexture) |
|
|
|
{ |
|
|
|
decoder_sys_t *p_sys = p_dec->p_sys; |
|
|
|
|
|
|
|
/* Force OpenGL interop (via AWindow_SurfaceTexture) if there is a
|
|
|
|
* projection or an orientation to handle, if the Surface owner is not able |
|
|
|
* to modify its layout. */ |
|
|
|
static const struct vlc_video_context_operations ops = |
|
|
|
{ |
|
|
|
.destroy = CleanFromVideoContext, |
|
|
|
}; |
|
|
|
p_sys->video.ctx = |
|
|
|
vlc_video_context_Create(dec_dev, VLC_VIDEO_CONTEXT_AWINDOW, |
|
|
|
sizeof(android_video_context_t), &ops); |
|
|
|
|
|
|
|
p_sys->video.surfacetexture = NULL; |
|
|
|
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; |
|
|
|
if (!p_sys->video.ctx) |
|
|
|
return VLC_EGENERIC; |
|
|
|
|
|
|
|
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); |
|
|
|
android_video_context_t *avctx = |
|
|
|
vlc_video_context_GetPrivate(p_sys->video.ctx, VLC_VIDEO_CONTEXT_AWINDOW); |
|
|
|
|
|
|
|
if (!use_surfacetexture) |
|
|
|
{ |
|
|
|
@ -715,20 +716,45 @@ CreateSurface(decoder_t *p_dec, AWindowHandler *awh) |
|
|
|
if (!p_sys->video.p_surface) |
|
|
|
{ |
|
|
|
msg_Err(p_dec, "Could not find a valid ANativeWindow"); |
|
|
|
return VLC_EGENERIC; |
|
|
|
goto error; |
|
|
|
} |
|
|
|
return VLC_SUCCESS; |
|
|
|
goto end; |
|
|
|
} |
|
|
|
|
|
|
|
p_sys->video.surfacetexture = vlc_asurfacetexture_New(awh, false); |
|
|
|
assert(p_sys->video.surfacetexture); |
|
|
|
if (p_sys->video.surfacetexture == NULL) |
|
|
|
return VLC_EGENERIC; |
|
|
|
goto error; |
|
|
|
|
|
|
|
p_sys->video.p_surface = p_sys->video.surfacetexture->window; |
|
|
|
assert(p_sys->video.p_surface); |
|
|
|
|
|
|
|
end: |
|
|
|
avctx->dec_opaque = p_dec->p_sys; |
|
|
|
|
|
|
|
avctx->render = PictureContextRenderPic; |
|
|
|
avctx->render_ts = p_sys->api.release_out_ts ? PictureContextRenderPicTs : NULL; |
|
|
|
avctx->get_texture = p_sys->video.surfacetexture ? PictureContextGetTexture : NULL; |
|
|
|
avctx->texture = NULL; |
|
|
|
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(p_sys->video.apic_ctxs); ++i) |
|
|
|
{ |
|
|
|
struct android_picture_ctx *apctx = &p_sys->video.apic_ctxs[i]; |
|
|
|
|
|
|
|
apctx->s = (picture_context_t) { |
|
|
|
PictureContextDestroy, PictureContextCopy, |
|
|
|
p_sys->video.ctx, |
|
|
|
}; |
|
|
|
atomic_init(&apctx->index, -1); |
|
|
|
atomic_init(&apctx->refs, 0); |
|
|
|
} |
|
|
|
|
|
|
|
return VLC_SUCCESS; |
|
|
|
|
|
|
|
error: |
|
|
|
vlc_video_context_Release(p_sys->video.ctx); |
|
|
|
p_sys->video.ctx = NULL; |
|
|
|
return VLC_EGENERIC; |
|
|
|
} |
|
|
|
|
|
|
|
static int |
|
|
|
@ -746,46 +772,24 @@ CreateVideoContext(decoder_t *p_dec) |
|
|
|
assert(dec_dev->opaque); |
|
|
|
AWindowHandler *awh = dec_dev->opaque; |
|
|
|
|
|
|
|
int ret = CreateSurface(p_dec, awh); |
|
|
|
if (ret != VLC_SUCCESS) |
|
|
|
{ |
|
|
|
vlc_decoder_device_Release(dec_dev); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static const struct vlc_video_context_operations ops = |
|
|
|
{ |
|
|
|
.destroy = CleanFromVideoContext, |
|
|
|
}; |
|
|
|
p_sys->video.ctx = |
|
|
|
vlc_video_context_Create(dec_dev, VLC_VIDEO_CONTEXT_AWINDOW, |
|
|
|
sizeof(android_video_context_t), &ops); |
|
|
|
vlc_decoder_device_Release(dec_dev); |
|
|
|
|
|
|
|
if (!p_sys->video.ctx) |
|
|
|
return VLC_EGENERIC; |
|
|
|
|
|
|
|
android_video_context_t *avctx = |
|
|
|
vlc_video_context_GetPrivate(p_sys->video.ctx, VLC_VIDEO_CONTEXT_AWINDOW); |
|
|
|
avctx->dec_opaque = p_dec->p_sys; |
|
|
|
avctx->render = PictureContextRenderPic; |
|
|
|
avctx->render_ts = p_sys->api.release_out_ts ? PictureContextRenderPicTs : NULL; |
|
|
|
avctx->get_texture = p_sys->video.surfacetexture ? PictureContextGetTexture : NULL; |
|
|
|
avctx->texture = NULL; |
|
|
|
/* Force OpenGL interop (via AWindow_SurfaceTexture) if there is a
|
|
|
|
* projection or an orientation to handle, if the Surface owner is not able |
|
|
|
* to modify its layout. */ |
|
|
|
p_sys->video.surfacetexture = NULL; |
|
|
|
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; |
|
|
|
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(p_sys->video.apic_ctxs); ++i) |
|
|
|
{ |
|
|
|
struct android_picture_ctx *apctx = &p_sys->video.apic_ctxs[i]; |
|
|
|
bool need_gpu_transform = |
|
|
|
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; |
|
|
|
bool use_surfacetexture = need_gpu_transform && can_use_surfacetexture; |
|
|
|
|
|
|
|
apctx->s = (picture_context_t) { |
|
|
|
PictureContextDestroy, PictureContextCopy, |
|
|
|
p_sys->video.ctx, |
|
|
|
}; |
|
|
|
atomic_init(&apctx->index, -1); |
|
|
|
atomic_init(&apctx->refs, 0); |
|
|
|
} |
|
|
|
int ret = CreateSurface(p_dec, dec_dev, awh, use_surfacetexture); |
|
|
|
vlc_decoder_device_Release(dec_dev); |
|
|
|
|
|
|
|
return VLC_SUCCESS; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static void CleanInputVideo(decoder_t *p_dec) |
|
|
|
|