diff --git a/lib/native/mac/libjquicktime.jnilib b/lib/native/mac/libjquicktime.jnilib index 14d355bf3..fbdea623f 100755 Binary files a/lib/native/mac/libjquicktime.jnilib and b/lib/native/mac/libjquicktime.jnilib differ diff --git a/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.h b/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.h index 434bc3215..89b7450f4 100644 --- a/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.h +++ b/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.h @@ -15,6 +15,22 @@ extern "C" { JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer_getBytes (JNIEnv *, jclass, jlong); +/* + * Class: net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer + * Method: getHeight + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer_getHeight + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer + * Method: getWidth + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer_getWidth + (JNIEnv *, jclass, jlong); + #ifdef __cplusplus } #endif diff --git a/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.m b/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.m index 4d27bca8d..865effb5a 100644 --- a/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.m +++ b/src/native/macosx/quicktime/net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer.m @@ -29,3 +29,17 @@ Java_net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer_getBytes } return bytes; } + +JNIEXPORT jint JNICALL +Java_net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer_getHeight + (JNIEnv *jniEnv, jclass clazz, jlong ptr) +{ + return (jint) CVPixelBufferGetHeight((CVPixelBufferRef) ptr); +} + +JNIEXPORT jint JNICALL +Java_net_java_sip_communicator_impl_neomedia_quicktime_CVPixelBuffer_getWidth + (JNIEnv *jniEnv, jclass clazz, jlong ptr) +{ + return (jint) CVPixelBufferGetWidth((CVPixelBufferRef) ptr); +} diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/quicktime/QuickTimeStream.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/quicktime/QuickTimeStream.java index 971d4dafc..7606a36ff 100644 --- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/quicktime/QuickTimeStream.java +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/quicktime/QuickTimeStream.java @@ -37,6 +37,13 @@ public class QuickTimeStream */ private byte[] data; + /** + * The Format of {@link #data} if known. If possible, determined by + * the CVPixelBuffer video frame from which data is + * acquired. + */ + private Format dataFormat; + /** * The Object which synchronizes the access to the * {@link #data}-related fields of this instance. @@ -121,13 +128,17 @@ private void captureOutputDidOutputVideoFrameWithSampleBuffer( CVImageBuffer videoFrame, QTSampleBuffer sampleBuffer) { + CVPixelBuffer pixelBuffer = (CVPixelBuffer) videoFrame; boolean transferData; synchronized (dataSyncRoot) { - data = ((CVPixelBuffer) videoFrame).getBytes(); + data = pixelBuffer.getBytes(); dataTimeStamp = System.nanoTime(); transferData = (data != null); + + if (dataFormat == null) + dataFormat = getVideoFrameFormat(pixelBuffer); } if (transferData) @@ -167,9 +178,34 @@ public void close() @Override protected Format doGetFormat() { - if (format == null) + Format format; + + if (this.format == null) + { format = getCaptureOutputFormat(); - return (format == null) ? super.doGetFormat() : format; + if (format == null) + format = super.doGetFormat(); + else + { + VideoFormat videoFormat = (VideoFormat) format; + + if (videoFormat.getSize() != null) + this.format = format; + else + format + = videoFormat + .intersects( + new VideoFormat( + null, + new Dimension(640, 480), + Format.NOT_SPECIFIED, + Format.byteArray, + Format.NOT_SPECIFIED)); + } + } + else + format = this.format; + return format; } /** @@ -202,7 +238,9 @@ private Format getCaptureOutputFormat() return new RGBFormat( - new Dimension(width, height), + ((width == 0) && (height == 0) + ? null + : new Dimension(width, height)), Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED, @@ -214,6 +252,38 @@ private Format getCaptureOutputFormat() return null; } + /** + * Gets the Format of the media data made available by this + * PushBufferStream as indicated by a specific + * CVPixelBuffer. + * + * @param videoFrame the CVPixelBuffer which provides details about + * the Format of the media data made available by this + * PushBufferStream + * @return the Format of the media data made available by this + * PushBufferStream as indicated by the specified + * CVPixelBuffer + */ + private Format getVideoFrameFormat(CVPixelBuffer videoFrame) + { + Format format = getFormat(); + Dimension size = ((VideoFormat) format).getSize(); + + if ((size == null) || ((size.width == 0) && (size.height == 0))) + format + = format + .intersects( + new VideoFormat( + null, + new Dimension( + videoFrame.getWidth(), + videoFrame.getHeight()), + Format.NOT_SPECIFIED, + Format.byteArray, + Format.NOT_SPECIFIED)); + return format; + } + /** * Reads media data from this PushBufferStream into a specific * Buffer without blocking. @@ -235,6 +305,8 @@ public void read(Buffer buffer) buffer.setData(data); buffer .setFlags(Buffer.FLAG_LIVE_DATA | Buffer.FLAG_SYSTEM_TIME); + if (dataFormat != null) + buffer.setFormat(dataFormat); buffer.setLength(data.length); buffer.setOffset(0); buffer.setTimeStamp(dataTimeStamp); @@ -255,6 +327,15 @@ private void setCaptureOutputFormat(Format format) { VideoFormat videoFormat = (VideoFormat) format; Dimension size = videoFormat.getSize(); + + /* + * FIXME Mac OS X Leopard does not seem to report the size of the + * QTCaptureDevice in its formatDescriptions early in its creation. + * The workaround presented here is to just force a specific size. + */ + if (size == null) + size = new Dimension(640, 480); + NSMutableDictionary pixelBufferAttributes = null; if (size != null) @@ -300,6 +381,7 @@ public void stop() synchronized (dataSyncRoot) { data = null; + dataFormat = null; } } } diff --git a/src/net/java/sip/communicator/impl/neomedia/quicktime/CVPixelBuffer.java b/src/net/java/sip/communicator/impl/neomedia/quicktime/CVPixelBuffer.java index 26a6a3cf8..3e5da5cc3 100644 --- a/src/net/java/sip/communicator/impl/neomedia/quicktime/CVPixelBuffer.java +++ b/src/net/java/sip/communicator/impl/neomedia/quicktime/CVPixelBuffer.java @@ -48,4 +48,46 @@ public byte[] getBytes() * specified CoreVideo CVPixelBufferRef */ private static native byte[] getBytes(long ptr); + + /** + * Gets the height in pixels of this CVPixelBuffer. + * + * @return the height in pixels of this CVPixelBuffer + */ + public int getHeight() + { + return getHeight(getPtr()); + } + + /** + * Gets the height in pixels of a specific CoreVideo + * CVPixelBufferRef. + * + * @param ptr the CoreVideo CVPixelBufferRef to get the height in + * pixels of + * @return the height in pixels of the specified CoreVideo + * CVPixelBufferRef + */ + private static native int getHeight(long ptr); + + /** + * Gets the width in pixels of this CVPixelBuffer. + * + * @return the width in pixels of this CVPixelBuffer + */ + public int getWidth() + { + return getWidth(getPtr()); + } + + /** + * Gets the width in pixels of a specific CoreVideo + * CVPixelBufferRef. + * + * @param ptr the CoreVideo CVPixelBufferRef to get the width in + * pixels of + * @return the width in pixels of the specified CoreVideo + * CVPixelBufferRef + */ + private static native int getWidth(long ptr); }