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);
}