aboutsummaryrefslogtreecommitdiffstats
path: root/src/native
diff options
context:
space:
mode:
authorLyubomir Marinov <lyubomir.marinov@jitsi.org>2010-05-01 00:02:36 +0000
committerLyubomir Marinov <lyubomir.marinov@jitsi.org>2010-05-01 00:02:36 +0000
commit7b39a3d5564fe6f17e9ce9bfecac4f7fe525a379 (patch)
treeedd2cc35aa321f5800d21b19a4e67180bb0daa09 /src/native
parentb8d1fe3ceb438d27c9061aff931adb74eaadc44b (diff)
downloadjitsi-7b39a3d5564fe6f17e9ce9bfecac4f7fe525a379.zip
jitsi-7b39a3d5564fe6f17e9ce9bfecac4f7fe525a379.tar.gz
jitsi-7b39a3d5564fe6f17e9ce9bfecac4f7fe525a379.tar.bz2
Modifies the native VideoRender on Mac OS X (which is still not being enabled in this commit) (1) to spare a copying of the frame to be rendered and (2) to be somewhat more responsive.
Diffstat (limited to 'src/native')
-rw-r--r--src/native/jawtrenderer/JAWTRenderer.h2
-rw-r--r--src/native/jawtrenderer/JAWTRenderer_MacOSX.m435
-rw-r--r--src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c7
-rw-r--r--src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h4
4 files changed, 303 insertions, 145 deletions
diff --git a/src/native/jawtrenderer/JAWTRenderer.h b/src/native/jawtrenderer/JAWTRenderer.h
index 0a73259..afb87af 100644
--- a/src/native/jawtrenderer/JAWTRenderer.h
+++ b/src/native/jawtrenderer/JAWTRenderer.h
@@ -7,7 +7,7 @@
void JAWTRenderer_close
(JNIEnv *jniEnv, jclass clazz, jlong handle, jobject component);
jlong JAWTRenderer_open(JNIEnv *jniEnv, jclass clazz, jobject component);
-void JAWTRenderer_paint
+jboolean JAWTRenderer_paint
(JAWT_DrawingSurfaceInfo *dsi, jclass clazz, jlong handle, jobject g);
jboolean JAWTRenderer_process
(JNIEnv *jniEnv, jclass clazz,
diff --git a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m
index b6442e8..1a60f6c 100644
--- a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m
+++ b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m
@@ -13,6 +13,8 @@
#define JAWT_RENDERER_TEXTURE_FORMAT GL_BGRA
#define JAWT_RENDERER_TEXTURE_TYPE GL_UNSIGNED_BYTE
+@class JAWTRenderer, JAWTRendererOpenGLTexture, JAWTRendererOpenGLView;
+
@interface JAWTRenderer : NSObject
{
@public
@@ -21,22 +23,38 @@
jint dataHeight;
jint dataLength;
jint dataWidth;
+
+ JAWTRendererOpenGLTexture *texture;
+
+ JAWTRendererOpenGLView *view;
+ NSOpenGLContext *glContext;
+ BOOL glContextIsPrepared;
}
- (void)dealloc;
- (id)init;
@end /* JAWTRenderer */
+@interface JAWTRendererOpenGLTexture : NSObject
+{
+@public
+ GLuint texture;
+ jint width;
+ jint height;
+ BOOL filled;
+}
+
+- (id)init;
+- (BOOL)setDataFromRenderer:(JAWTRenderer *)renderer;
+@end /* JAWTRendererOpenGLTexture */
+
@interface JAWTRendererOpenGLView : NSOpenGLView
{
@private
JAWTRenderer *renderer;
- GLuint texture;
- jint textureWidth;
- jint textureHeight;
+ JAWTRendererOpenGLTexture *texture;
}
-- (void)clearGLContext;
- (void)dealloc;
- (void)drawRect:(NSRect)rect;
- (id)initWithFrame:(NSRect)frameRect;
@@ -46,6 +64,8 @@
- (void)setRenderer:(JAWTRenderer *)renderer;
@end /* JAWTRendererOpenGLView */
+static void JAWTRenderer_prepareOpenGL();
+
void
JAWTRenderer_close
(JNIEnv *jniEnv, jclass clazz, jlong handle, jobject component)
@@ -75,11 +95,12 @@ JAWTRenderer_open(JNIEnv *jniEnv, jclass clazz, jobject component)
return (jlong) renderer;
}
-void
+jboolean
JAWTRenderer_paint
(JAWT_DrawingSurfaceInfo *dsi, jclass clazz, jlong handle, jobject g)
{
NSView *component;
+ jboolean wantsPaint;
component
= ((JAWT_MacOSXDrawingSurfaceInfo *) (dsi->platformInfo))->cocoaViewRef;
@@ -87,40 +108,56 @@ JAWTRenderer_paint
{
JAWTRenderer *renderer;
NSAutoreleasePool *autoreleasePool;
- NSArray *subviews;
JAWTRendererOpenGLView *rendererView;
renderer = (JAWTRenderer *) handle;
autoreleasePool = [[NSAutoreleasePool alloc] init];
- subviews = [component subviews];
- if ([subviews count])
- rendererView = [subviews objectAtIndex:0];
- else
+ @synchronized(renderer)
{
+ rendererView = renderer->view;
+ if (!rendererView)
+ {
+ rendererView
+ = [[JAWTRendererOpenGLView alloc]
+ initWithFrame:[component bounds]];
+ [rendererView setRenderer:renderer];
- rendererView
- = [[JAWTRendererOpenGLView alloc]
- initWithFrame:[component bounds]];
-
- [component addSubview:rendererView];
- [rendererView release];
-
- /*
- * Have the rendererView autosized by the component which contains
- * it. And since the rendererView has just been created to fill the
- * current bounds of the component, it will always fill it this way.
- */
- [component setAutoresizesSubviews:YES];
- [rendererView
- setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [component addSubview:rendererView];
+ [rendererView release];
- [rendererView setRenderer:renderer];
+ /*
+ * Have the rendererView autosized by the component which
+ * contains it. And since the rendererView has just been created
+ * to fill the current bounds of the component, it will always
+ * fill it this way.
+ */
+ [component setAutoresizesSubviews:YES];
+ [rendererView
+ setAutoresizingMask:
+ (NSViewWidthSizable | NSViewHeightSizable)];
+ }
}
+ wantsPaint = JNI_FALSE;
+
[rendererView display];
[autoreleasePool release];
}
+ else
+ wantsPaint = JNI_TRUE;
+ return wantsPaint;
+}
+
+static void
+JAWTRenderer_prepareOpenGL()
+{
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_CULL_FACE);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
}
jboolean
@@ -131,42 +168,87 @@ JAWTRenderer_process
jint width, jint height)
{
JAWTRenderer *renderer;
+ NSAutoreleasePool *autoreleasePool;
size_t dataSize;
jint *rendererData;
jboolean processed;
renderer = (JAWTRenderer *) handle;
+ autoreleasePool = [[NSAutoreleasePool alloc] init];
@synchronized(renderer)
{
- dataSize = sizeof(jint) * length;
- if (renderer->dataCapacity < length)
+ if (renderer->glContext)
{
- jint newRendererDataCapacity;
- jint *newRendererData;
- newRendererData = realloc(renderer->data, dataSize);
- if (newRendererData)
+ /*
+ * Once we've started processing the specified data directly into
+ * the OpenGL texture, it's unlikely that we'll need the data
+ * copy/field of the renderer.
+ */
+ if (renderer->data)
{
- renderer->data = rendererData = newRendererData;
- renderer->dataCapacity = length;
+ free(renderer->data);
+ renderer->dataCapacity = 0;
}
- else
- rendererData = NULL;
- }
- else
- rendererData = renderer->data;
- if (rendererData)
- {
- memcpy(rendererData, data, dataSize);
+ renderer->data = data;
renderer->dataHeight = height;
renderer->dataLength = length;
renderer->dataWidth = width;
+
+ [renderer->glContext makeCurrentContext];
+ if (!(renderer->glContextIsPrepared))
+ {
+ renderer->glContextIsPrepared = YES;
+ JAWTRenderer_prepareOpenGL();
+ }
+ [renderer->texture setDataFromRenderer:renderer];
+
+ renderer->data = NULL;
+ renderer->dataLength = 0;
+
processed = JNI_TRUE;
}
else
- processed = JNI_FALSE;
+ {
+ dataSize = sizeof(jint) * length;
+ if (renderer->dataCapacity < length)
+ {
+ jint newRendererDataCapacity;
+ jint *newRendererData;
+
+ newRendererData = realloc(renderer->data, dataSize);
+ if (newRendererData)
+ {
+ renderer->data = rendererData = newRendererData;
+ renderer->dataCapacity = length;
+ }
+ else
+ rendererData = NULL;
+ }
+ else
+ rendererData = renderer->data;
+ if (rendererData)
+ {
+ memcpy(rendererData, data, dataSize);
+ renderer->dataHeight = height;
+ renderer->dataLength = length;
+ renderer->dataWidth = width;
+ processed = JNI_TRUE;
+ }
+ else
+ processed = JNI_FALSE;
+ }
+ if (renderer->view)
+ {
+ [renderer->view
+ performSelectorOnMainThread:@selector(display)
+ withObject:nil
+ waitUntilDone:NO];
+ }
}
+
+ [autoreleasePool release];
return processed;
}
@@ -175,6 +257,7 @@ JAWTRenderer_process
{
if (data)
free(data);
+ [texture release];
/*
* Do not release the view because no reference to it has been previously
@@ -194,20 +277,114 @@ JAWTRenderer_process
dataHeight = 0;
dataLength = 0;
dataWidth = 0;
+
+ texture = [[JAWTRendererOpenGLTexture alloc] init];
+
+ view = nil;
+ glContext = nil;
+ glContextIsPrepared = NO;
}
return self;
}
@end /* JAWTRenderer */
-@implementation JAWTRendererOpenGLView
-- (void)clearGLContext
+@implementation JAWTRendererOpenGLTexture
+- (id)init
+{
+ self = [super init];
+ if (self)
+ {
+ texture = 0;
+ width = 0;
+ height = 0;
+ filled = NO;
+ }
+ return self;
+}
+
+- (BOOL)setDataFromRenderer:(JAWTRenderer *)renderer
{
- [super clearGLContext];
+ if (renderer->data && renderer->dataLength)
+ {
+ if (texture
+ && ((width != renderer->dataWidth))
+ || (height != renderer->dataHeight))
+ {
+ glDeleteTextures(1, &texture);
+ texture = 0;
+ }
+ if (texture)
+ {
+ glBindTexture(JAWT_RENDERER_TEXTURE, texture);
+ glTexSubImage2D(
+ JAWT_RENDERER_TEXTURE,
+ 0,
+ 0, 0,
+ renderer->dataWidth, renderer->dataHeight,
+ JAWT_RENDERER_TEXTURE_FORMAT,
+ JAWT_RENDERER_TEXTURE_TYPE,
+ renderer->data);
+ }
+ else
+ {
+ glGenTextures(1, &texture);
+ glBindTexture(JAWT_RENDERER_TEXTURE, texture);
+ glTexParameterf(JAWT_RENDERER_TEXTURE, GL_TEXTURE_PRIORITY, 1.0);
+ glTexParameteri(
+ JAWT_RENDERER_TEXTURE,
+ GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+ glTexParameteri(
+ JAWT_RENDERER_TEXTURE,
+ GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+ glTexParameteri(
+ JAWT_RENDERER_TEXTURE,
+ GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ glTexParameteri(
+ JAWT_RENDERER_TEXTURE,
+ GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ glTexParameteri(
+ JAWT_RENDERER_TEXTURE,
+ GL_TEXTURE_STORAGE_HINT_APPLE,
+ GL_STORAGE_SHARED_APPLE);
+
+ glTexImage2D(
+ JAWT_RENDERER_TEXTURE,
+ 0,
+ 4,
+ renderer->dataWidth, renderer->dataHeight,
+ 0,
+ JAWT_RENDERER_TEXTURE_FORMAT,
+ JAWT_RENDERER_TEXTURE_TYPE,
+ renderer->data);
+ }
+ width = renderer->dataWidth;
+ height = renderer->dataHeight;
+ filled = YES;
+
+ /*
+ * We've just created the texture from the data so we don't want
+ * to do it again.
+ */
+ renderer->dataLength = 0;
+ }
+ else
+ filled = NO;
+ return filled;
}
+@end /* JAWTRendererOpenGLTexture */
+@implementation JAWTRendererOpenGLView
- (void)dealloc
{
[self setRenderer:nil];
+ [texture release];
[super dealloc];
}
@@ -218,98 +395,46 @@ JAWTRenderer_process
{
@synchronized(renderer)
{
- if (renderer->data && renderer->dataLength)
+ if (renderer->texture->filled)
{
- if (texture
- && ((textureWidth != renderer->dataWidth))
- || (textureHeight != renderer->dataHeight))
- {
- glDeleteTextures(1, &texture);
- texture = 0;
- }
- if (texture)
- {
- glBindTexture(JAWT_RENDERER_TEXTURE, texture);
- glTexSubImage2D(
- JAWT_RENDERER_TEXTURE,
- 0,
- 0, 0,
- renderer->dataWidth, renderer->dataHeight,
- JAWT_RENDERER_TEXTURE_FORMAT,
- JAWT_RENDERER_TEXTURE_TYPE,
- renderer->data);
- }
- else
- {
- glGenTextures(1, &texture);
- glBindTexture(JAWT_RENDERER_TEXTURE, texture);
- glTexParameterf(
- JAWT_RENDERER_TEXTURE, GL_TEXTURE_PRIORITY, 1.0);
- glTexParameteri(
- JAWT_RENDERER_TEXTURE,
- GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_EDGE);
- glTexParameteri(
- JAWT_RENDERER_TEXTURE,
- GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_EDGE);
- glTexParameteri(
- JAWT_RENDERER_TEXTURE,
- GL_TEXTURE_MAG_FILTER,
- GL_LINEAR);
- glTexParameteri(
- JAWT_RENDERER_TEXTURE,
- GL_TEXTURE_MIN_FILTER,
- GL_LINEAR);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glTexParameteri(
- JAWT_RENDERER_TEXTURE,
- GL_TEXTURE_STORAGE_HINT_APPLE,
- GL_STORAGE_SHARED_APPLE);
-
- glTexImage2D(
- JAWT_RENDERER_TEXTURE,
- 0,
- 4,
- renderer->dataWidth, renderer->dataHeight,
- 0,
- JAWT_RENDERER_TEXTURE_FORMAT,
- JAWT_RENDERER_TEXTURE_TYPE,
- renderer->data);
- }
- textureWidth = renderer->dataWidth;
- textureHeight = renderer->dataHeight;
+ JAWTRendererOpenGLTexture *swap;
- /*
- * We've just created the texture from the data so we don't want
- * to do it again.
- */
- renderer->dataLength = 0;
+ swap = texture;
+ texture = renderer->texture;
+ renderer->texture = swap;
+
+ renderer->texture->filled = NO;
}
- }
- }
+ else
+ [texture setDataFromRenderer:renderer];
- glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT);
- if (texture)
+ if (texture->texture)
+ {
+ glBindTexture(JAWT_RENDERER_TEXTURE, texture->texture);
+ glEnable(JAWT_RENDERER_TEXTURE);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex2f(-1.0, 1.0);
+ glTexCoord2f(texture->width, 0);
+ glVertex2f(1.0, 1.0);
+ glTexCoord2f(texture->width, texture->height);
+ glVertex2f(1.0, -1.0);
+ glTexCoord2f(0, texture->height);
+ glVertex2f(-1.0, -1.0);
+ glEnd();
+ glDisable(JAWT_RENDERER_TEXTURE);
+ }
+
+ glFlush();
+ }
+ }
+ else
{
- glEnable(JAWT_RENDERER_TEXTURE);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(-1.0, 1.0);
- glTexCoord2f(textureWidth, 0);
- glVertex2f(1.0, 1.0);
- glTexCoord2f(textureWidth, textureHeight);
- glVertex2f(1.0, -1.0);
- glTexCoord2f(0, textureHeight);
- glVertex2f(-1.0, -1.0);
- glEnd();
- glDisable(JAWT_RENDERER_TEXTURE);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glFlush();
}
-
- glFlush();
}
- (id)initWithFrame:(NSRect)frameRect
@@ -321,9 +446,7 @@ JAWTRenderer_process
if (self)
{
renderer = nil;
- texture = 0;
- textureWidth = 0;
- textureHeight = 0;
+ texture = [[JAWTRendererOpenGLTexture alloc] init];
}
return self;
}
@@ -337,12 +460,7 @@ JAWTRenderer_process
{
[super prepareOpenGL];
- glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
- glDepthMask(GL_FALSE);
- glDisable(GL_CULL_FACE);
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ JAWTRenderer_prepareOpenGL();
}
- (void)reshape
@@ -375,10 +493,47 @@ JAWTRenderer_process
if (renderer != aRenderer)
{
if (renderer)
+ {
+ @synchronized(renderer)
+ {
+ if (renderer->view == self)
+ renderer->view = nil;
+ if (renderer->glContext)
+ {
+ [renderer->glContext release];
+ renderer->glContext = nil;
+ renderer->glContextIsPrepared = NO;
+ }
+ }
[renderer release];
+ }
renderer = aRenderer;
if (renderer)
+ {
[renderer retain];
+ @synchronized(renderer)
+ {
+ NSOpenGLContext *glContext;
+
+ renderer->view = self;
+
+ glContext = [self openGLContext];
+ if (glContext)
+ {
+ if (renderer->glContext)
+ {
+ [renderer->glContext release];
+ renderer->glContext = nil;
+ renderer->glContextIsPrepared = NO;
+ }
+
+ renderer->glContext
+ = [[NSOpenGLContext alloc]
+ initWithFormat:[NSOpenGLView defaultPixelFormat]
+ shareContext:glContext];
+ }
+ }
+ }
}
}
@end /* JAWTRendererOpenGLView */
diff --git a/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c b/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c
index abc4e35..8cd8330 100644
--- a/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c
+++ b/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c
@@ -15,14 +15,16 @@ Java_net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRen
return JAWTRenderer_open(jniEnv, clazz, component);
}
-JNIEXPORT void JNICALL
+JNIEXPORT jboolean JNICALL
Java_net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_paint
(JNIEnv *jniEnv, jclass clazz, jlong handle, jobject component, jobject g)
{
JAWT awt;
+ jboolean wantsPaint;
awt.version = JAWT_VERSION_1_3;
+ wantsPaint = JNI_TRUE;
if (JAWT_GetAWT(jniEnv, &awt) != JNI_FALSE)
{
JAWT_DrawingSurface *ds;
@@ -46,7 +48,7 @@ Java_net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRen
* the JAWT_DrawingSurface which is itself the value of the
* field ds of the JAWT_DrawingSurfaceInfo.
*/
- JAWTRenderer_paint(dsi, clazz, handle, g);
+ wantsPaint = JAWTRenderer_paint(dsi, clazz, handle, g);
ds->FreeDrawingSurfaceInfo(dsi);
}
ds->Unlock(ds);
@@ -54,6 +56,7 @@ Java_net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRen
awt.FreeDrawingSurface(ds);
}
}
+ return wantsPaint;
}
JNIEXPORT jboolean JNICALL
diff --git a/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h b/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h
index 8c70c47..9af6d62 100644
--- a/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h
+++ b/src/native/jawtrenderer/net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h
@@ -26,9 +26,9 @@ JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_jmfext_medi
/*
* Class: net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
* Method: paint
- * Signature: (JLjava/awt/Component;Ljava/awt/Graphics;)V
+ * Signature: (JLjava/awt/Component;Ljava/awt/Graphics;)Z
*/
-JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_paint
+JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_paint
(JNIEnv *, jclass, jlong, jobject, jobject);
/*