case XA_DATALOCATOR_NATIVEDISPLAY:
pDataLocator->mNativeDisplay = *(XADataLocator_NativeDisplay *)pLocator;
- // if hDisplay is NULL, then hWindow is NDK C ANativeWindow *
- // if hDisplay is non-NULL, then:
- // hWindow is JNI jobject Surface or SurfaceTexture
- // hDisplay is JNIENV *
+ // hWindow is NDK C ANativeWindow * and hDisplay must be NULL
if (pDataLocator->mNativeDisplay.hWindow == NULL) {
- SL_LOGE("%s: hWindow must be non-NULL", name);
+ SL_LOGE("%s: hWindow must be non-NULL ANativeWindow *", name);
+ result = SL_RESULT_PARAMETER_INVALID;
+ }
+ if (pDataLocator->mNativeDisplay.hDisplay != NULL) {
+ SL_LOGE("%s: hDisplay must be NULL, but is %p", name,
+ pDataLocator->mNativeDisplay.hDisplay);
result = SL_RESULT_PARAMETER_INVALID;
}
break;
#include <media/IMediaPlayerService.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
+#include <gui/SurfaceTextureClient.h>
#include <fcntl.h>
#endif
// if there is a video sink
if (XA_DATALOCATOR_NATIVEDISPLAY ==
thiz->mImageVideoSink.mLocator.mLocatorType) {
- JNIEnv *env = (JNIEnv *) thiz->mImageVideoSink.mLocator.mNativeDisplay.hDisplay;
- if (env != NULL) {
- // FIXME this is a temporary hack because ANativeWindow is not Binderable yet
- jobject object = (jobject) thiz->mImageVideoSink.mLocator.mNativeDisplay.hWindow;
- assert(object != NULL);
- jclass surfaceClass = env->FindClass("android/view/Surface");
- jclass surfaceTextureClass = env->FindClass("android/graphics/SurfaceTexture");
- jclass objectClass = env->GetObjectClass(object);
- if (thiz->mAVPlayer != 0) {
- // initialize display surface
- android::GenericMediaPlayer* avp =
- (android::GenericMediaPlayer*)(thiz->mAVPlayer.get());
- if (objectClass == surfaceClass) {
- sp<Surface> nativeSurface((Surface *) env->GetIntField(object,
- env->GetFieldID(surfaceClass, "mNativeSurface", "I")));
- result = android_Player_setVideoSurface(avp, nativeSurface);
- } else if (objectClass == surfaceTextureClass) {
- sp<ISurfaceTexture> nativeSurfaceTexture((ISurfaceTexture *)
- env->GetIntField(object, env->GetFieldID(surfaceTextureClass,
- "mSurfaceTexture", "I")));
- result = android_Player_setVideoSurfaceTexture(avp, nativeSurfaceTexture);
- }
- }
+ ANativeWindow *nativeWindow = (ANativeWindow *)
+ thiz->mImageVideoSink.mLocator.mNativeDisplay.hWindow;
+ // we already verified earlier that hWindow is non-NULL
+ assert(nativeWindow != NULL);
+ int err;
+ int value;
+ // this could crash if app passes in a bad parameter, but that's OK
+ err = (*nativeWindow->query)(nativeWindow, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+ if (0 != err) {
+ SL_LOGE("Query NATIVE_WINDOW_CONCRETE_TYPE on ANativeWindow * %p failed; "
+ "errno %d", nativeWindow, err);
} else {
- ANativeWindow *nativeWindow = (ANativeWindow *)
- thiz->mImageVideoSink.mLocator.mNativeDisplay.hWindow;
- assert(nativeWindow != NULL);
- // FIXME here is where to implement ANativeWindow support
+ android::GenericMediaPlayer* avp =
+ static_cast<android::GenericMediaPlayer *>(thiz->mAVPlayer.get());
+ switch (value) {
+ case NATIVE_WINDOW_SURFACE: { // Surface
+ sp<Surface> nativeSurface(static_cast<Surface *>(nativeWindow));
+ result = android_Player_setVideoSurface(avp, nativeSurface);
+ } break;
+ case NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT: { // SurfaceTextureClient
+ sp<SurfaceTextureClient> surfaceTextureClient(
+ static_cast<SurfaceTextureClient *>(nativeWindow));
+ sp<ISurfaceTexture> nativeSurfaceTexture(
+ surfaceTextureClient->getISurfaceTexture());
+ result = android_Player_setVideoSurfaceTexture(avp, nativeSurfaceTexture);
+ } break;
+ case NATIVE_WINDOW_FRAMEBUFFER: // FramebufferNativeWindow
+ // fall through
+ default:
+ SL_LOGE("ANativeWindow * %p has unknown or unsupported concrete type %d",
+ nativeWindow, value);
+ break;
+ }
}
}
}
#include <android/native_window_jni.h>
-// define as 1 if ANativeWindow * is not supported as a video sink
-#define NO_NATIVE_WINDOW 1
-
// engine interfaces
static XAObjectItf engineObject = NULL;
static XAEngineItf engineEngine;
// number of required interfaces for the MediaPlayer creation
#define NB_MAXAL_INTERFACES 3 // XAAndroidBufferQueueItf, XAStreamInformationItf and XAPlayItf
-// cached surface where the video display happens
-#if NO_NATIVE_WINDOW
-static jobject theSurfaceOrSurfaceTexture;
-#else
+// video sink for the player
static ANativeWindow* theNativeWindow;
-#endif
// number of buffers in our buffer queue
#define NB_BUFFERS 16
// configure image video sink
XADataLocator_NativeDisplay loc_nd = {
XA_DATALOCATOR_NATIVEDISPLAY, // locatorType
-#if NO_NATIVE_WINDOW
- (void *) theSurfaceOrSurfaceTexture, // jobject
- (void *) env // JNIEnv *env
-#else
- // later the video sink can be an ANativeWindow created from a Surface or SurfaceTexture
+ // the video sink must be an ANativeWindow created from a Surface or SurfaceTexture
(void*)theNativeWindow, // hWindow
// must be NULL
NULL // hDisplay
-#endif
};
XADataSink imageVideoSink = {&loc_nd, NULL};
file = NULL;
}
-#if !NO_NATIVE_WINDOW
// make sure we don't leak native windows
if (theNativeWindow != NULL) {
ANativeWindow_release(theNativeWindow);
theNativeWindow = NULL;
}
-#endif
}
// set the surface
void Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface)
{
-#if NO_NATIVE_WINDOW
- theSurfaceOrSurfaceTexture = surface;
-#else
// obtain a native window from a Java surface
theNativeWindow = ANativeWindow_fromSurface(env, surface);
-#endif
}
void Java_com_example_nativemedia_NativeMedia_setSurfaceTexture(JNIEnv *env, jclass clazz,
jobject surfaceTexture)
{
-#if NO_NATIVE_WINDOW
- theSurfaceOrSurfaceTexture = surfaceTexture;
-#else
// obtain a native window from a Java surface texture
theNativeWindow = ANativeWindow_fromSurfaceTexture(env, surfaceTexture);
-#endif
}