Commit 8a709642 authored by Thomas Guillem's avatar Thomas Guillem Committed by Jean-Baptiste Kempf

modules: add android_window vout

 - used for direct and non direct rendering (replace opaque.c)

 - use nativewindowpriv: more control than the public api, since you can set
   orientation, crop, cancel a buffer without displaying it and allocate more
   than one buffers.

 - fallback to nativewindow if nativewindowpriv fails (with only one buffer in
   the pool then).

 - Only one way to display subtitles: use a seperate android surface.

 - Fix subtiles display in case or source aspect != 1.
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 646639aa
...@@ -3364,7 +3364,7 @@ AC_ARG_ENABLE(android-surface, ...@@ -3364,7 +3364,7 @@ AC_ARG_ENABLE(android-surface,
[ --enable-android-surface Android Surface video output module (default disabled)]) [ --enable-android-surface Android Surface video output module (default disabled)])
if test "${enable_android_surface}" = "yes"; then if test "${enable_android_surface}" = "yes"; then
VLC_ADD_PLUGIN([android_surface]) VLC_ADD_PLUGIN([android_surface])
VLC_ADD_PLUGIN([android_opaque]) VLC_ADD_PLUGIN([android_window])
fi fi
dnl dnl
......
...@@ -33,8 +33,8 @@ $Id$ ...@@ -33,8 +33,8 @@ $Id$
* anaglyph: anaglyph 3d video filter * anaglyph: anaglyph 3d video filter
* android_audiotrack: audio output for Android, based on AudioTrack * android_audiotrack: audio output for Android, based on AudioTrack
* android_native_window: Android native window provider module * android_native_window: Android native window provider module
* android_opaque: Android direct GPU rendering video output
* android_surface: video output for Android, based on Surface * android_surface: video output for Android, based on Surface
* android_window: Android direct/undirect rendering video output
* antiflicker: anti-flicker video filter * antiflicker: anti-flicker video filter
* araw: Pseudo audio decoder for raw PCM * araw: Pseudo audio decoder for raw PCM
* aribcam: ARIB STD-B25 decoder/virtual CAM * aribcam: ARIB STD-B25 decoder/virtual CAM
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <OMX_Component.h> #include <OMX_Component.h>
#include "omxil_utils.h" #include "omxil_utils.h"
#include "android_opaque.h" #include "android_opaque.h"
#include "../../video_output/android/android_window.h"
#define INFO_OUTPUT_BUFFERS_CHANGED -3 #define INFO_OUTPUT_BUFFERS_CHANGED -3
#define INFO_OUTPUT_FORMAT_CHANGED -2 #define INFO_OUTPUT_FORMAT_CHANGED -2
...@@ -617,23 +618,25 @@ static void CloseDecoder(vlc_object_t *p_this) ...@@ -617,23 +618,25 @@ static void CloseDecoder(vlc_object_t *p_this)
/***************************************************************************** /*****************************************************************************
* vout callbacks * vout callbacks
*****************************************************************************/ *****************************************************************************/
static void DisplayBuffer(picture_sys_t* p_picsys, bool b_render) static void UnlockPicture(picture_t* p_pic)
{ {
decoder_t *p_dec = p_picsys->p_dec; picture_sys_t *p_picsys = p_pic->p_sys;
decoder_t *p_dec = p_picsys->priv.hw.p_dec;
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
if (!p_picsys->b_valid) if (!p_picsys->priv.hw.b_valid)
return; return;
vlc_mutex_lock(get_android_opaque_mutex()); vlc_mutex_lock(get_android_opaque_mutex());
/* Picture might have been invalidated while waiting on the mutex. */ /* Picture might have been invalidated while waiting on the mutex. */
if (!p_picsys->b_valid) { if (!p_picsys->priv.hw.b_valid) {
vlc_mutex_unlock(get_android_opaque_mutex()); vlc_mutex_unlock(get_android_opaque_mutex());
return; return;
} }
uint32_t i_index = p_picsys->i_index; uint32_t i_index = p_picsys->priv.hw.i_index;
bool b_render = p_picsys->b_render;
p_sys->inflight_picture[i_index] = NULL; p_sys->inflight_picture[i_index] = NULL;
/* Release the MediaCodec buffer. */ /* Release the MediaCodec buffer. */
...@@ -646,21 +649,11 @@ static void DisplayBuffer(picture_sys_t* p_picsys, bool b_render) ...@@ -646,21 +649,11 @@ static void DisplayBuffer(picture_sys_t* p_picsys, bool b_render)
} }
jni_detach_thread(); jni_detach_thread();
p_picsys->b_valid = false; p_picsys->priv.hw.b_valid = false;
vlc_mutex_unlock(get_android_opaque_mutex()); vlc_mutex_unlock(get_android_opaque_mutex());
} }
static void UnlockCallback(picture_sys_t* p_picsys)
{
DisplayBuffer(p_picsys, false);
}
static void DisplayCallback(picture_sys_t* p_picsys)
{
DisplayBuffer(p_picsys, true);
}
static void InvalidateAllPictures(decoder_t *p_dec) static void InvalidateAllPictures(decoder_t *p_dec)
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
...@@ -669,7 +662,7 @@ static void InvalidateAllPictures(decoder_t *p_dec) ...@@ -669,7 +662,7 @@ static void InvalidateAllPictures(decoder_t *p_dec)
for (int i = 0; i < p_sys->i_output_buffers; ++i) { for (int i = 0; i < p_sys->i_output_buffers; ++i) {
picture_t *p_pic = p_sys->inflight_picture[i]; picture_t *p_pic = p_sys->inflight_picture[i];
if (p_pic) { if (p_pic) {
p_pic->p_sys->b_valid = false; p_pic->p_sys->priv.hw.b_valid = false;
p_sys->inflight_picture[i] = NULL; p_sys->inflight_picture[i] = NULL;
} }
} }
...@@ -707,7 +700,7 @@ static void GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong t ...@@ -707,7 +700,7 @@ static void GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong t
} else if (p_sys->direct_rendering) { } else if (p_sys->direct_rendering) {
picture_t *p_pic = *pp_pic; picture_t *p_pic = *pp_pic;
picture_sys_t *p_picsys = p_pic->p_sys; picture_sys_t *p_picsys = p_pic->p_sys;
int i_prev_index = p_picsys->i_index; int i_prev_index = p_picsys->priv.hw.i_index;
(*env)->CallVoidMethod(env, p_sys->codec, p_sys->release_output_buffer, i_prev_index, false); (*env)->CallVoidMethod(env, p_sys->codec, p_sys->release_output_buffer, i_prev_index, false);
if ((*env)->ExceptionOccurred(env)) { if ((*env)->ExceptionOccurred(env)) {
msg_Err(p_dec, "Exception in MediaCodec.releaseOutputBuffer " \ msg_Err(p_dec, "Exception in MediaCodec.releaseOutputBuffer " \
...@@ -738,11 +731,11 @@ static void GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong t ...@@ -738,11 +731,11 @@ static void GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong t
if (p_sys->direct_rendering) { if (p_sys->direct_rendering) {
picture_sys_t *p_picsys = p_pic->p_sys; picture_sys_t *p_picsys = p_pic->p_sys;
p_picsys->pf_display_callback = DisplayCallback; p_picsys->pf_lock_pic = NULL;
p_picsys->pf_unlock_callback = UnlockCallback; p_picsys->pf_unlock_pic = UnlockPicture;
p_picsys->p_dec = p_dec; p_picsys->priv.hw.p_dec = p_dec;
p_picsys->i_index = index; p_picsys->priv.hw.i_index = index;
p_picsys->b_valid = true; p_picsys->priv.hw.b_valid = true;
p_sys->inflight_picture[index] = p_pic; p_sys->inflight_picture[index] = p_pic;
} else { } else {
...@@ -974,11 +967,11 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block) ...@@ -974,11 +967,11 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
if (invalid_picture) { if (invalid_picture) {
invalid_picture->date = VLC_TS_INVALID; invalid_picture->date = VLC_TS_INVALID;
picture_sys_t *p_picsys = invalid_picture->p_sys; picture_sys_t *p_picsys = invalid_picture->p_sys;
p_picsys->pf_display_callback = NULL; p_picsys->pf_lock_pic = NULL;
p_picsys->pf_unlock_callback = NULL; p_picsys->pf_unlock_pic = NULL;
p_picsys->p_dec = NULL; p_picsys->priv.hw.p_dec = NULL;
p_picsys->i_index = -1; p_picsys->priv.hw.i_index = -1;
p_picsys->b_valid = false; p_picsys->priv.hw.b_valid = false;
} }
else { else {
/* If we cannot return a picture we must free the /* If we cannot return a picture we must free the
......
...@@ -30,15 +30,6 @@ ...@@ -30,15 +30,6 @@
#include <vlc_common.h> #include <vlc_common.h>
struct picture_sys_t
{
void (*pf_display_callback)(picture_sys_t*);
void (*pf_unlock_callback)(picture_sys_t*);
decoder_t *p_dec;
uint32_t i_index;
int b_valid;
};
vlc_mutex_t* get_android_opaque_mutex(void); vlc_mutex_t* get_android_opaque_mutex(void);
#endif #endif
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <jni.h> #include <jni.h>
#include "android_opaque.h" #include "android_opaque.h"
#include "../../video_output/android/android_window.h"
#endif #endif
#ifndef NDEBUG #ifndef NDEBUG
...@@ -96,8 +97,7 @@ static OMX_ERRORTYPE OmxFillBufferDone( OMX_HANDLETYPE, OMX_PTR, ...@@ -96,8 +97,7 @@ static OMX_ERRORTYPE OmxFillBufferDone( OMX_HANDLETYPE, OMX_PTR,
#if defined(USE_IOMX) #if defined(USE_IOMX)
static void *DequeueThread( void *data ); static void *DequeueThread( void *data );
static void DisplayCallback( picture_sys_t* p_picsys ); static void UnlockPicture( picture_t* p_pic );
static void UnlockCallback( picture_sys_t* p_picsys );
static void HwBuffer_Init( decoder_t *p_dec, OmxPort *p_port ); static void HwBuffer_Init( decoder_t *p_dec, OmxPort *p_port );
static void HwBuffer_Destroy( decoder_t *p_dec, OmxPort *p_port ); static void HwBuffer_Destroy( decoder_t *p_dec, OmxPort *p_port );
static int HwBuffer_AllocateBuffers( decoder_t *p_dec, OmxPort *p_port ); static int HwBuffer_AllocateBuffers( decoder_t *p_dec, OmxPort *p_port );
...@@ -1635,11 +1635,11 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -1635,11 +1635,11 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
if (invalid_picture) { if (invalid_picture) {
invalid_picture->date = VLC_TS_INVALID; invalid_picture->date = VLC_TS_INVALID;
picture_sys_t *p_picsys = invalid_picture->p_sys; picture_sys_t *p_picsys = invalid_picture->p_sys;
p_picsys->pf_display_callback = NULL; p_picsys->pf_lock_pic = NULL;
p_picsys->pf_unlock_callback = NULL; p_picsys->pf_unlock_pic = NULL;
p_picsys->p_dec = NULL; p_picsys->priv.hw.p_dec = NULL;
p_picsys->i_index = -1; p_picsys->priv.hw.i_index = -1;
p_picsys->b_valid = false; p_picsys->priv.hw.b_valid = false;
} else { } else {
/* If we cannot return a picture we must free the /* If we cannot return a picture we must free the
block since the decoder will proceed with the block since the decoder will proceed with the
...@@ -2418,14 +2418,14 @@ static int HwBuffer_Stop( decoder_t *p_dec, OmxPort *p_port ) ...@@ -2418,14 +2418,14 @@ static int HwBuffer_Stop( decoder_t *p_dec, OmxPort *p_port )
if( p_pic ) { if( p_pic ) {
picture_sys_t *p_picsys = p_pic->p_sys; picture_sys_t *p_picsys = p_pic->p_sys;
if( p_picsys ) { if( p_picsys ) {
void *p_handle = p_port->pp_buffers[p_picsys->i_index]->pBuffer; void *p_handle = p_port->pp_buffers[p_picsys->priv.hw.i_index]->pBuffer;
if( p_handle ) if( p_handle )
{ {
p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle ); p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle );
HwBuffer_ChangeState( p_dec, p_port, p_picsys->i_index, HwBuffer_ChangeState( p_dec, p_port, p_picsys->priv.hw.i_index,
BUF_STATE_NOT_OWNED ); BUF_STATE_NOT_OWNED );
} }
p_picsys->b_valid = false; p_picsys->priv.hw.b_valid = false;
} }
p_port->p_hwbuf->inflight_picture[i] = NULL; p_port->p_hwbuf->inflight_picture[i] = NULL;
} }
...@@ -2493,11 +2493,11 @@ static int HwBuffer_GetPic( decoder_t *p_dec, OmxPort *p_port, ...@@ -2493,11 +2493,11 @@ static int HwBuffer_GetPic( decoder_t *p_dec, OmxPort *p_port,
p_pic->date = FromOmxTicks( p_header->nTimeStamp ); p_pic->date = FromOmxTicks( p_header->nTimeStamp );
p_picsys = p_pic->p_sys; p_picsys = p_pic->p_sys;
p_picsys->pf_display_callback = DisplayCallback; p_picsys->pf_lock_pic = NULL;
p_picsys->pf_unlock_callback = UnlockCallback; p_picsys->pf_unlock_pic = UnlockPicture;
p_picsys->p_dec = p_dec; p_picsys->priv.hw.p_dec = p_dec;
p_picsys->i_index = i_index; p_picsys->priv.hw.i_index = i_index;
p_picsys->b_valid = true; p_picsys->priv.hw.b_valid = true;
HWBUFFER_LOCK(); HWBUFFER_LOCK();
p_port->p_hwbuf->inflight_picture[i_index] = p_pic; p_port->p_hwbuf->inflight_picture[i_index] = p_pic;
...@@ -2600,27 +2600,28 @@ static void *DequeueThread( void *data ) ...@@ -2600,27 +2600,28 @@ static void *DequeueThread( void *data )
/***************************************************************************** /*****************************************************************************
* vout callbacks * vout callbacks
*****************************************************************************/ *****************************************************************************/
static void DisplayBuffer( picture_sys_t* p_picsys, bool b_render ) static void UnlockPicture( picture_t* p_pic )
{ {
decoder_t *p_dec = p_picsys->p_dec; picture_sys_t *p_picsys = p_pic->p_sys;
decoder_t *p_dec = p_picsys->priv.hw.p_dec;
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
OmxPort *p_port = &p_sys->out; OmxPort *p_port = &p_sys->out;
void *p_handle; void *p_handle;
if( !p_picsys->b_valid ) return; if( !p_picsys->priv.hw.b_valid ) return;
HWBUFFER_LOCK(); HWBUFFER_LOCK();
/* Picture might have been invalidated while waiting on the mutex. */ /* Picture might have been invalidated while waiting on the mutex. */
if (!p_picsys->b_valid) { if (!p_picsys->priv.hw.b_valid) {
HWBUFFER_UNLOCK(); HWBUFFER_UNLOCK();
return; return;
} }
p_handle = p_port->pp_buffers[p_picsys->i_index]->pBuffer; p_handle = p_port->pp_buffers[p_picsys->priv.hw.i_index]->pBuffer;
OMX_DBG( "DisplayBuffer: %s %p", OMX_DBG( "DisplayBuffer: %s %p",
b_render ? "render" : "cancel", p_handle ); p_picsys->b_render ? "render" : "cancel", p_handle );
if( !p_handle ) if( !p_handle )
{ {
...@@ -2628,31 +2629,21 @@ static void DisplayBuffer( picture_sys_t* p_picsys, bool b_render ) ...@@ -2628,31 +2629,21 @@ static void DisplayBuffer( picture_sys_t* p_picsys, bool b_render )
goto end; goto end;
} }
if( b_render ) if( p_picsys->b_render )
p_port->p_hwbuf->anwpriv.queue( p_port->p_hwbuf->window_priv, p_handle ); p_port->p_hwbuf->anwpriv.queue( p_port->p_hwbuf->window_priv, p_handle );
else else
p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle ); p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle );
HwBuffer_ChangeState( p_dec, p_port, p_picsys->i_index, BUF_STATE_NOT_OWNED ); HwBuffer_ChangeState( p_dec, p_port, p_picsys->priv.hw.i_index, BUF_STATE_NOT_OWNED );
HWBUFFER_BROADCAST( p_port ); HWBUFFER_BROADCAST( p_port );
p_port->p_hwbuf->inflight_picture[p_picsys->i_index] = NULL; p_port->p_hwbuf->inflight_picture[p_picsys->priv.hw.i_index] = NULL;
end: end:
p_picsys->b_valid = false; p_picsys->priv.hw.b_valid = false;
p_picsys->i_index = -1; p_picsys->priv.hw.i_index = -1;
HWBUFFER_UNLOCK(); HWBUFFER_UNLOCK();
} }
static void UnlockCallback( picture_sys_t* p_picsys )
{
DisplayBuffer( p_picsys, false );
}
static void DisplayCallback( picture_sys_t* p_picsys )
{
DisplayBuffer( p_picsys, true );
}
#endif // USE_IOMX #endif // USE_IOMX
...@@ -250,11 +250,11 @@ libandroid_native_window_plugin_la_SOURCES = video_output/android/nativewindow.c ...@@ -250,11 +250,11 @@ libandroid_native_window_plugin_la_SOURCES = video_output/android/nativewindow.c
libandroid_native_window_plugin_la_CFLAGS = $(AM_CFLAGS) libandroid_native_window_plugin_la_CFLAGS = $(AM_CFLAGS)
libandroid_native_window_plugin_la_LIBADD = $(LIBDL) libandroid_native_window_plugin_la_LIBADD = $(LIBDL)
libandroid_opaque_plugin_la_SOURCES = video_output/android/opaque.c video_output/android/utils.c video_output/android/utils.h libandroid_window_plugin_la_SOURCES = video_output/android/android_window.c video_output/android/android_window.h video_output/android/utils.c video_output/android/utils.h
libandroid_opaque_plugin_la_CFLAGS = $(AM_CFLAGS) libandroid_window_plugin_la_CFLAGS = $(AM_CFLAGS)
libandroid_opaque_plugin_la_LIBADD = $(LIBDL) libandroid_window_plugin_la_LIBADD = $(LIBDL)
libandroid_opaque_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' libandroid_window_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
EXTRA_LTLIBRARIES += libandroid_opaque_plugin.la EXTRA_LTLIBRARIES += libandroid_window_plugin.la
libandroid_surface_plugin_la_SOURCES = video_output/android/surface.c video_output/android/utils.c video_output/android/utils.h libandroid_surface_plugin_la_SOURCES = video_output/android/surface.c video_output/android/utils.c video_output/android/utils.h
libandroid_surface_plugin_la_CFLAGS = $(AM_CFLAGS) libandroid_surface_plugin_la_CFLAGS = $(AM_CFLAGS)
...@@ -264,7 +264,7 @@ EXTRA_LTLIBRARIES += libandroid_surface_plugin.la ...@@ -264,7 +264,7 @@ EXTRA_LTLIBRARIES += libandroid_surface_plugin.la
if HAVE_ANDROID if HAVE_ANDROID
vout_LTLIBRARIES += libandroid_native_window_plugin.la vout_LTLIBRARIES += libandroid_native_window_plugin.la
vout_LTLIBRARIES += $(LTLIBandroid_opaque) vout_LTLIBRARIES += $(LTLIBandroid_window)
vout_LTLIBRARIES += $(LTLIBandroid_surface) vout_LTLIBRARIES += $(LTLIBandroid_surface)
if HAVE_EGL if HAVE_EGL
vout_LTLIBRARIES += libegl_android_plugin.la vout_LTLIBRARIES += libegl_android_plugin.la
......
This diff is collapsed.
/*****************************************************************************
* android_window.c: Android video output module
*****************************************************************************
* Copyright (C) 2014 VLC authors and VideoLAN
*
* Authors: Thomas Guillem <thomas@gllm.fr>
* Felix Abecassis <felix.abecassis@gmail.com>
* Ming Hu <tewilove@gmail.com>
* Ludovic Fauvet <etix@l0cal.com>
* Sébastien Toque <xilasz@gmail.com>
*
* 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.
*****************************************************************************/
#ifndef ANDROID_WINDOW_H_
#define ANDROID_WINDOW_H_
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_vout_display.h>
#include <android/native_window.h>
struct picture_sys_t
{
vout_display_sys_t *p_vd_sys;
int (*pf_lock_pic)(picture_t *);
void (*pf_unlock_pic)(picture_t *);
union {
struct {
decoder_t *p_dec;
uint32_t i_index;
bool b_valid;
} hw;
struct {
void *p_handle;
ANativeWindow_Buffer buf;
} sw;
} priv;
bool b_render;
};
#endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment