From f1c61bba6934d497a649e17baddf36b60d07d958 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov <lyubomir.marinov@jitsi.org> Date: Sun, 23 Nov 2014 17:26:20 +0200 Subject: [PATCH] Fixes issues with JAWTRenderer on Java 7 under OS X. Base on contributions by Ingo Bauersachs. --- src/native/jawtrenderer/JAWTRenderer.h | 12 +- src/native/jawtrenderer/JAWTRenderer_MacOSX.m | 103 ++++++++++++++++-- ...jmfext_media_renderer_video_JAWTRenderer.c | 53 +++++++++ ...jmfext_media_renderer_video_JAWTRenderer.h | 16 +++ 4 files changed, 169 insertions(+), 15 deletions(-) diff --git a/src/native/jawtrenderer/JAWTRenderer.h b/src/native/jawtrenderer/JAWTRenderer.h index 53eb8b92..f4bec095 100644 --- a/src/native/jawtrenderer/JAWTRenderer.h +++ b/src/native/jawtrenderer/JAWTRenderer.h @@ -8,11 +8,11 @@ #ifndef _JAWTRENDERER_H_ #define _JAWTRENDERER_H_ -#ifndef __ANDROID__ - #include <jawt.h> -#else /* #ifndef __ANDROID__ */ +#ifdef __ANDROID__ typedef void JAWT_DrawingSurfaceInfo; -#endif /* #ifndef __ANDROID__ */ +#else /* #ifdef __ANDROID__ */ + #include <jawt.h> +#endif /* #ifdef __ANDROID__ */ #include <jni.h> #ifndef NULL @@ -23,6 +23,8 @@ extern "C" { #endif /* #ifdef __cplusplus */ +void JAWTRenderer_addNotify + (JNIEnv *env, jclass clazz, jlong handle, jobject component); void JAWTRenderer_close (JNIEnv *env, jclass clazz, jlong handle, jobject component); jlong JAWTRenderer_open(JNIEnv *env, jclass clazz, jobject component); @@ -32,6 +34,8 @@ jboolean JAWTRenderer_paint jboolean JAWTRenderer_process (JNIEnv *env, jclass clazz,jlong handle, jobject component, jint *data, jint length, jint width, jint height); +void JAWTRenderer_removeNotify + (JNIEnv *env, jclass clazz, jlong handle, jobject component); #ifdef __APPLE__ jstring JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name); diff --git a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m index 51d4e50a..62fa5f4c 100644 --- a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m +++ b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m @@ -51,22 +51,42 @@ forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp; - (id)init; +- (void)setFrameFromJAWTDrawingSurfaceInfo:(JAWT_DrawingSurfaceInfo *)dsi; @end /* JAWTRendererLayer */ +/* + * JAWT version 1.7 does not define the type JAWT_MacOSXDrawingSurfaceInfo. + */ +#ifdef JAWT_VERSION_1_7 +// Legacy NSView-based rendering +typedef struct JAWT_MacOSXDrawingSurfaceInfo { + NSView *cocoaViewRef; // the view is guaranteed to be valid only for the duration of Component.paint method +} +JAWT_MacOSXDrawingSurfaceInfo; +#endif /* #ifdef JAWT_VERSION_1_7 */ + +void +JAWTRenderer_addNotify + (JNIEnv *env, jclass clazz, jlong handle, jobject component) +{ + /* TODO Auto-generated method stub */ +} + void JAWTRenderer_close(JNIEnv *env, jclass clazz, jlong handle, jobject component) { - JAWTRendererLayer **thiz; - NSAutoreleasePool *autoreleasePool; + JAWTRendererLayer **thiz = (JAWTRendererLayer **) (intptr_t) handle; + JAWTRendererLayer *layer = *thiz; - thiz = (JAWTRendererLayer **) (intptr_t) handle; - autoreleasePool = [[NSAutoreleasePool alloc] init]; + if (layer) + { + NSAutoreleasePool *autoreleasePool; - if (*thiz) - [*thiz release]; + autoreleasePool = [[NSAutoreleasePool alloc] init]; + [layer release]; + [autoreleasePool release]; + } free(thiz); - - [autoreleasePool release]; } jlong @@ -84,6 +104,7 @@ JAWTRenderer_paint JAWTRendererLayer *thizLayer; jboolean wantsPaint = JNI_TRUE; JAWTRendererLayer **thiz; + JAWTRendererLayer *oldThizLayer; autoreleasePool = [[NSAutoreleasePool alloc] init]; @@ -98,14 +119,22 @@ JAWTRenderer_paint CALayer *layer = surfaceLayers.layer; if (layer && [layer isKindOfClass:[JAWTRendererLayer class]]) + { thizLayer = (JAWTRendererLayer *) layer; + } else { thizLayer = [JAWTRendererLayer layer]; if (thizLayer) + { + [thizLayer setFrameFromJAWTDrawingSurfaceInfo:dsi]; surfaceLayers.layer = thizLayer; + [thizLayer autorelease]; + } else + { wantsPaint = JNI_FALSE; + } } } else @@ -116,17 +145,23 @@ JAWTRenderer_paint CALayer *layer = [view layer]; if (layer && [layer isKindOfClass:[JAWTRendererLayer class]]) + { thizLayer = (JAWTRendererLayer *) layer; + } else { thizLayer = [JAWTRendererLayer layer]; if (thizLayer) { + [thizLayer setFrameFromJAWTDrawingSurfaceInfo:dsi]; [view setLayer:thizLayer]; [view setWantsLayer:YES]; + [thizLayer autorelease]; } else + { wantsPaint = JNI_FALSE; + } } } @@ -135,10 +170,11 @@ JAWTRenderer_paint * native peer of the AWT Canvas that is the component of this JAWTRenderer. */ thiz = (JAWTRendererLayer **) (intptr_t) handle; - if (*thiz != thizLayer) + oldThizLayer = *thiz; + if (oldThizLayer != thizLayer) { - if (*thiz) - [*thiz release]; + if (oldThizLayer) + [oldThizLayer release]; *thiz = thizLayer; if (thizLayer) [thizLayer retain]; @@ -250,6 +286,28 @@ JAWTRenderer_process return JNI_TRUE; } +void +JAWTRenderer_removeNotify + (JNIEnv *env, jclass clazz, jlong handle, jobject component) +{ + /* + * The AWT Comonent notifies that it is being made undisplayable by + * destroying its native screen resource. For an unknown reason, the + * JAWTRendererLayer is not automatically removed from its superlayer and + * remains visible. + */ + JAWTRendererLayer *thiz = *((JAWTRendererLayer **) (intptr_t) handle); + + if (thiz) + { + NSAutoreleasePool *autoreleasePool; + + autoreleasePool = [[NSAutoreleasePool alloc] init]; + [thiz removeFromSuperlayer]; + [autoreleasePool release]; + } +} + jstring JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name) { @@ -270,7 +328,9 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name) { if ((0 == sysctlbyname(_name, _value, &valueLength, NULL, 0)) && valueLength) + { _value[valueLength] = 0; + } else { free(_value); @@ -279,7 +339,9 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name) } } else + { _value = NULL; + } (*env)->ReleaseStringUTFChars(env, name, _name); if (_value) @@ -406,11 +468,13 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name) == CGLCreateContext(_pixelFormat, NULL, &_glContext))) { self.asynchronous = YES; + self.autoresizingMask = kCALayerNotSizable; /* * The AWT Canvas that corresponds to this CAOpenGLLayer will ensure * that the latter will be displayed on bounds changes. */ self.needsDisplayOnBoundsChange = NO; + self.opaque = YES; } else { @@ -420,4 +484,21 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name) } return self; } + +- (void)setFrameFromJAWTDrawingSurfaceInfo:(JAWT_DrawingSurfaceInfo *)dsi +{ + JAWT_Rectangle *jawtrect; + + jawtrect = &(dsi->bounds); + if (jawtrect->height > 0 && jawtrect->width > 0) + { + CGRect cgrect; + + cgrect.origin.x = jawtrect->x; + cgrect.origin.y = -(jawtrect->y); + cgrect.size.height = jawtrect->height; + cgrect.size.width = jawtrect->width; + self.frame = cgrect; + } +} @end /* JAWTRendererLayer */ diff --git a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c index 671f2ab5..90256d5d 100644 --- a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c +++ b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c @@ -8,6 +8,25 @@ #include "org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h" #include "JAWTRenderer.h" +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: addNotify + * Signature: (JLjava/awt/Component;)V + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_addNotify + (JNIEnv *env, jclass clazz, jlong handle, jobject component) +{ +#ifdef __APPLE__ + JAWTRenderer_addNotify(env, clazz, handle, component); +#endif /* #ifdef __APPLE__ */ +} + +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: close + * Signature: (JLjava/awt/Component;)V + */ JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_close (JNIEnv *env, jclass clazz, jlong handle, jobject component) @@ -15,6 +34,11 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_close JAWTRenderer_close(env, clazz, handle, component); } +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: open + * Signature: (Ljava/awt/Component;)J + */ JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_open (JNIEnv *env, jclass clazz, jobject component) @@ -22,6 +46,11 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_open return JAWTRenderer_open(env, clazz, component); } +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: paint + * Signature: (JLjava/awt/Component;Ljava/awt/Graphics;I)Z + */ JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_paint (JNIEnv *env, jclass clazz, jlong handle, jobject component, jobject g, @@ -99,6 +128,11 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_paint #endif /* #ifdef __ANDROID__ */ } +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: process + * Signature: (JLjava/awt/Component;[IIIII)Z + */ JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_process (JNIEnv *env, jclass clazz, jlong handle, jobject component, jintArray data, @@ -126,6 +160,25 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_process return processed; } +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: removeNotify + * Signature: (JLjava/awt/Component;)V + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_removeNotify + (JNIEnv *env, jclass clazz, jlong handle, jobject component) +{ +#ifdef __APPLE__ + JAWTRenderer_removeNotify(env, clazz, handle, component); +#endif /* #ifdef __APPLE__ */ +} + +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: sysctlbyname + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ JNIEXPORT jstring JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_sysctlbyname (JNIEnv *env, jclass clazz, jstring name) diff --git a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h index 29d983bb..c62658f7 100644 --- a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h +++ b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h @@ -7,6 +7,14 @@ #ifdef __cplusplus extern "C" { #endif +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: addNotify + * Signature: (JLjava/awt/Component;)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_addNotify + (JNIEnv *, jclass, jlong, jobject); + /* * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer * Method: close @@ -39,6 +47,14 @@ JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_vi JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_process (JNIEnv *, jclass, jlong, jobject, jintArray, jint, jint, jint, jint); +/* + * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer + * Method: removeNotify + * Signature: (JLjava/awt/Component;)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_removeNotify + (JNIEnv *, jclass, jlong, jobject); + /* * Class: org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer * Method: sysctlbyname -- GitLab