diff --git a/lib/native/freebsd-64/libscreencapture.so b/lib/native/freebsd-64/libscreencapture.so index 4ee183a46..cf2fabc67 100755 Binary files a/lib/native/freebsd-64/libscreencapture.so and b/lib/native/freebsd-64/libscreencapture.so differ diff --git a/lib/native/freebsd/libscreencapture.so b/lib/native/freebsd/libscreencapture.so index 98dd3f251..368c9f688 100755 Binary files a/lib/native/freebsd/libscreencapture.so and b/lib/native/freebsd/libscreencapture.so differ diff --git a/lib/native/linux-64/libjawtrenderer.so b/lib/native/linux-64/libjawtrenderer.so index 2e389d7d8..b9ad0f7fe 100755 Binary files a/lib/native/linux-64/libjawtrenderer.so and b/lib/native/linux-64/libjawtrenderer.so differ diff --git a/lib/native/linux-64/libscreencapture.so b/lib/native/linux-64/libscreencapture.so index 98bc46aa3..a53cc7b54 100755 Binary files a/lib/native/linux-64/libscreencapture.so and b/lib/native/linux-64/libscreencapture.so differ diff --git a/lib/native/linux/libjawtrenderer.so b/lib/native/linux/libjawtrenderer.so index 1fa4fa01c..3fa0bbf0a 100755 Binary files a/lib/native/linux/libjawtrenderer.so and b/lib/native/linux/libjawtrenderer.so differ diff --git a/lib/native/linux/libscreencapture.so b/lib/native/linux/libscreencapture.so index c0caaffaa..41534b99f 100755 Binary files a/lib/native/linux/libscreencapture.so and b/lib/native/linux/libscreencapture.so differ diff --git a/lib/native/mac/libscreencapture.jnilib b/lib/native/mac/libscreencapture.jnilib index eef6a1d3e..196f3ab25 100755 Binary files a/lib/native/mac/libscreencapture.jnilib and b/lib/native/mac/libscreencapture.jnilib differ diff --git a/lib/native/windows-64/screencapture.dll b/lib/native/windows-64/screencapture.dll index 12d895772..7957762cf 100755 Binary files a/lib/native/windows-64/screencapture.dll and b/lib/native/windows-64/screencapture.dll differ diff --git a/lib/native/windows/screencapture.dll b/lib/native/windows/screencapture.dll index b0d4cf907..b395b8bec 100644 Binary files a/lib/native/windows/screencapture.dll and b/lib/native/windows/screencapture.dll differ diff --git a/src/native/jawtrenderer/JAWTRenderer_Linux.c b/src/native/jawtrenderer/JAWTRenderer_Linux.c index 65b158d9a..990d78456 100644 --- a/src/native/jawtrenderer/JAWTRenderer_Linux.c +++ b/src/native/jawtrenderer/JAWTRenderer_Linux.c @@ -293,7 +293,12 @@ _JAWTRenderer_createImage(JAWTRenderer *renderer) image = renderer->image; width = renderer->dataWidth; height = renderer->dataHeight; - if (image && ((image->width != width) || (image->height != height))) + + /* XvCreateImage is limited to 2048x2048 image so do not drop image + * if size exceed the limit + */ + if (image && ((image->width != width) || (image->height != height)) && + width < 2048 && height < 2048) { XFree(image); image = NULL; @@ -307,11 +312,16 @@ _JAWTRenderer_createImage(JAWTRenderer *renderer) renderer->imageFormatID, NULL, width, height); + /* * XvCreateImage is documented to enlarge width and height for some YUV * formats. But I don't know how to handle such a situation. */ - if (image && ((image->width != width) || (image->height != height))) + /* XvCreateImage is limited to 2048x2048 image so do not drop image + * if size exceed this limit + */ + if (image && ((image->width != width) || (image->height != height)) && + width < 2048 && height < 2048) { XFree(image); image = NULL; diff --git a/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c b/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c index 723f2786d..4d370961e 100644 --- a/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c +++ b/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c @@ -50,16 +50,83 @@ typedef unsigned __int8 uint8_t; #if defined(_WIN32) || defined (_WIN64) +/** + * \struct monitor_data + * \brief Used with monitorCallback to pass index and receive DC + */ +struct monitor_data +{ + unsigned int monitor_index; /**< Index of the specific monitor */ + unsigned int current_index; /**< Internal index of monitor in callback */ + HDC monitor_dc; /**< DC of the monitor (set by monitorCallback if any) */ +}; + +/** + * \brief Callback when using EnumDisplayMonitors function. + * \param hMonitor monitor object + * \param hdcMonitor DC passed from EnumDisplayMonitors + * \param lpcrMonitor clipping rectangle + * \param dwData additionnal data + * \return true if enumeration have to be stopped, false otherwise + */ +BOOL CALLBACK monitorCallback(HMONITOR hMonitor, HDC hdcMonitor, + LPRECT lprcMonitor, LPARAM dwData) +{ + struct monitor_data* data = (struct monitor_data*)dwData; + MONITORINFOEX info; + + /* avoid warnings */ + hdcMonitor = hdcMonitor; + lprcMonitor = lprcMonitor; + + if(data->current_index == data->monitor_index) + { + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, (LPMONITORINFO)&info); + + /* create the DC for this monitor */ + data->monitor_dc = CreateDC(info.szDevice, info.szDevice, NULL, NULL); + + /* found the right monitor, breaks */ + return FALSE; + } + + data->current_index++; + return TRUE; +} + +/** + * \brief Get DC pointer for a specific display. + * \param display display index. + * \return DC pointer or NULL if failure + */ +static HDC get_dc(unsigned int index) +{ + HDC hDC = NULL; + struct monitor_data data; + + data.monitor_index = index; + data.current_index = 0; + data.monitor_dc = NULL; + + EnumDisplayMonitors(NULL, NULL, &monitorCallback, (LPARAM)&data); + + hDC = data.monitor_dc; + + return hDC; +} + /** * \brief Grab Windows screen. * \param data array that will contain screen capture + * \param display display index * \param x x position to start capture * \param y y position to start capture * \param w capture width * \param h capture height * \return 0 if success, -1 otherwise */ -static int windows_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int32_t h) +static int windows_grab_screen(jbyte* data, unsigned int display, int x, int y, int w, int h) { static const RGBQUAD redColor = {0x00, 0x00, 0xFF, 0x00}; static const RGBQUAD greenColor = {0x00, 0xFF, 0x00, 0x00}; @@ -79,8 +146,8 @@ static int windows_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int uint32_t test = 1; int little_endian = *((uint8_t*)&test); - /* get handle to the entire screen of Windows */ - desktop = GetDC(NULL); + /* get handle corresponding to the display specified */ + desktop = get_dc(display); if(!desktop) { @@ -107,7 +174,7 @@ static int windows_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int if(!dest) { - fprintf(stderr, "CreateCompatibleDC failed!\n"); + fprintf(stderr, "CreateCompatibleDC failed!\n"); ReleaseDC(NULL, desktop); return -1; } @@ -224,13 +291,14 @@ static int windows_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int /** * \brief Grab Mac OS X screen (with Quartz API). * \param data array that will contain screen capture + * \param display display index * \param x x position to start capture * \param y y position to start capture * \param w capture width * \param h capture height * \return 0 if success, -1 otherwise */ -static int quartz_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int32_t h) +static int quartz_grab_screen(jbyte* data, unsigned int display, int x, int y, int w, int h) { CGImageRef img = NULL; CGDataProviderRef provider = NULL; @@ -242,8 +310,26 @@ static int quartz_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int3 CGRect rect; uint32_t test = 1; int little_endian = *((uint8_t*)&test); + CGDirectDisplayID displayIds[16]; + CGDisplayCount displayNb = 0; - rect = CGRectMake(x, y, w, h); + /* find display */ + if(CGGetActiveDisplayList(display + 1, displayIds, &displayNb) != kCGErrorSuccess) + { + return -1; + } + + if(displayNb < (display + 1)) + { + /* request a non existent display */ + return -1; + } + + rect = CGDisplayBounds(displayIds[display]); + rect.size.width = w; + rect.size.height = h; + rect.origin.x += x; + rect.origin.y += y; img = CGWindowListCreateImage(rect, kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageDefault); if(img == NULL) @@ -291,13 +377,14 @@ static int quartz_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int3 * \brief Grab X11 screen. * \param x11display display string (i.e. :0.0), if NULL getenv("DISPLAY") is used * \param data array that will contain screen capture + * \param displayIndex display index * \param x x position to start capture * \param y y position to start capture * \param w capture width * \param h capture height * \return 0 if success, -1 otherwise */ -static int x11_grab_screen(const char* x11display, jbyte* data, int32_t x, int32_t y, int32_t w, int32_t h) +static int x11_grab_screen(jbyte* data, unsigned int displayIndex, int x, int y, int w, int h) { const char* display_str; /* display string */ Display* display = NULL; /* X11 display */ @@ -316,14 +403,10 @@ static int x11_grab_screen(const char* x11display, jbyte* data, int32_t x, int32 size_t size = 0; uint32_t test = 1; int little_endian = *((uint8_t*)&test); + char buf[16]; - display_str = x11display ? x11display : getenv("DISPLAY"); - - if(!display_str) - { - /* fprintf(stderr, "No display!\n"); */ - return -1; - } + snprintf(buf, sizeof(buf), ":0.%u", displayIndex); + display_str = buf; /* open current X11 display */ display = XOpenDisplay(display_str); @@ -463,6 +546,7 @@ static int x11_grab_screen(const char* x11display, jbyte* data, int32_t x, int32 * \brief JNI native method to grab desktop screen and retrieve ARGB pixels. * \param env JVM environment * \param clazz NativeScreenCapture Java class + * \param display display index * \param x x position to start capture * \param y y position to start capture * \param width capture width @@ -470,8 +554,8 @@ static int x11_grab_screen(const char* x11display, jbyte* data, int32_t x, int32 * \param output output buffer, screen bytes will be stored in * \return true if success, false otherwise */ -JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen__IIII_3B - (JNIEnv* env, jclass clazz, jint x, jint y, jint width, jint height, jbyteArray output) +JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen__IIIII_3B + (JNIEnv* env, jclass clazz, jint display, jint x, jint y, jint width, jint height, jbyteArray output) { jint size = width * height * 4; jbyte* data = NULL; @@ -491,11 +575,11 @@ JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstrea } #if defined (_WIN32) || defined(_WIN64) - if(windows_grab_screen(data, x, y, width, height) == -1) + if(windows_grab_screen(data, display, x, y, width, height) == -1) #elif defined(__APPLE__) - if(quartz_grab_screen(data, x, y, width, height) == -1) + if(quartz_grab_screen(data, display, x, y, width, height) == -1) #else /* Unix */ - if(x11_grab_screen(NULL, data, x, y, width, height) == -1) + if(x11_grab_screen(data, display, x, y, width, height) == -1) #endif { (*env)->ReleasePrimitiveArrayCritical(env, output, data, 0); @@ -510,6 +594,7 @@ JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstrea * \brief JNI native method to grab desktop screen and retrieve ARGB pixels. * \param env JVM environment * \param clazz NativeScreenCapture Java class + * \param display display index * \param x x position to start capture * \param y y position to start capture * \param width capture width @@ -517,8 +602,8 @@ JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstrea * \param output native output buffer * \return true if success, false otherwise */ -JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen__IIIIJI - (JNIEnv* env, jclass clazz, jint x, jint y, jint width, jint height, jlong output, jint outputLength) +JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen__IIIIIJI + (JNIEnv* env, jclass clazz, jint display, jint x, jint y, jint width, jint height, jlong output, jint outputLength) { jint size = width * height * 4; jbyte* data = (jbyte*)output; @@ -533,11 +618,11 @@ JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstrea } #if defined (_WIN32) || defined(_WIN64) - if(windows_grab_screen(data, x, y, width, height) == -1) + if(windows_grab_screen(data, display, x, y, width, height) == -1) #elif defined(__APPLE__) - if(quartz_grab_screen(data, x, y, width, height) == -1) + if(quartz_grab_screen(data, display, x, y, width, height) == -1) #else /* Unix */ - if(x11_grab_screen(NULL, data, x, y, width, height) == -1) + if(x11_grab_screen(data, display, x, y, width, height) == -1) #endif { return JNI_FALSE; @@ -545,4 +630,4 @@ JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstrea return JNI_TRUE; } - + diff --git a/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h b/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h index d1d6581de..e550390b3 100644 --- a/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h +++ b/src/native/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h @@ -10,10 +10,10 @@ extern "C" { /* * Class: net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture * Method: grabScreen - * Signature: (IIII[B)Z + * Signature: (IIIII[B)Z */ -JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen__IIII_3B - (JNIEnv *, jclass, jint, jint, jint, jint, jbyteArray); +JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen__IIIII_3B + (JNIEnv *, jclass, jint, jint, jint, jint, jint, jbyteArray); /* * Class: net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture diff --git a/src/net/java/sip/communicator/impl/neomedia/device/ImageStreamingAuto.java b/src/net/java/sip/communicator/impl/neomedia/device/ImageStreamingAuto.java index 960bef492..0b37306a3 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/ImageStreamingAuto.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/ImageStreamingAuto.java @@ -6,8 +6,16 @@ */ package net.java.sip.communicator.impl.neomedia.device; +import java.util.List; +import java.awt.*; + import javax.media.*; +import javax.media.format.*; +import net.java.sip.communicator.service.neomedia.device.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.impl.neomedia.codec.video.*; +import net.java.sip.communicator.impl.neomedia.*; import net.java.sip.communicator.impl.neomedia.imgstreaming.*; import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.imgstreaming.*; @@ -25,16 +33,78 @@ public class ImageStreamingAuto */ public ImageStreamingAuto() throws Exception { - String name = "Desktop Streaming (Experimental)"; - CaptureDeviceInfo devInfo - = new CaptureDeviceInfo( - name, - new MediaLocator( - ImageStreamingUtils.LOCATOR_PROTOCOL + ":" + name), - DataSource.getFormats()); - - /* add to JMF device manager */ - CaptureDeviceManager.addDevice(devInfo); + String name = "Desktop Streaming"; + List screens = NeomediaActivator.getMediaServiceImpl(). + getAvailableScreenDevices(); + int i = 0; + boolean multipleMonitorOneScreen = false; + Dimension screenSize = null; + + /* on Linux, multiple monitors may result in only one + * X display (:0.0) that combine those monitors + */ + if(OSUtils.IS_LINUX) + { + Dimension size = new Dimension(0, 0); + + for(ScreenDevice screen : screens) + { + size.width += screen.getSize().width; + size.height += screen.getSize().height; + } + + try + { + screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + if(screenSize.width == size.width || + screenSize.height == size.height) + { + multipleMonitorOneScreen = true; + } + } + catch(Exception e) + { + } + } + + for(ScreenDevice screen : screens) + { + Dimension size = screenSize != null ? screenSize : screen.getSize(); + + Format formats[]= new Format[] + { + new AVFrameFormat( + size, + Format.NOT_SPECIFIED, + FFmpeg.PIX_FMT_ARGB, + Format.NOT_SPECIFIED), + new RGBFormat( + size, // size + Format.NOT_SPECIFIED, // maxDataLength + Format.byteArray, // dataType + Format.NOT_SPECIFIED, // frameRate + 32, // bitsPerPixel + 2 /* red */, 3 /* green */, 4 /* blue */) + }; + + CaptureDeviceInfo devInfo + = new CaptureDeviceInfo( + name + " " + i, + new MediaLocator( + ImageStreamingUtils.LOCATOR_PROTOCOL + ":" + i), + formats); + + /* add to JMF device manager */ + CaptureDeviceManager.addDevice(devInfo); + i++; + + if(multipleMonitorOneScreen) + { + break; + } + } + CaptureDeviceManager.commit(); } } diff --git a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteract.java b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteract.java index b271c9758..e3bbd1e07 100644 --- a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteract.java +++ b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteract.java @@ -26,11 +26,12 @@ public interface DesktopInteract * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param output output buffer to store bytes in. * Be sure that output length is sufficient * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(byte output[]); + public boolean captureScreen(int display, byte output[]); /** * Capture the full desktop screen using native grabber. @@ -42,12 +43,13 @@ public interface DesktopInteract * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param buffer native output buffer to store bytes in. * Be sure that output length is sufficient * @param bufferLength length of native buffer * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(long buffer, int bufferLength); + public boolean captureScreen(int display, long buffer, int bufferLength); /** * Capture a part of the desktop screen using native grabber. @@ -59,6 +61,7 @@ public interface DesktopInteract * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param x x position to start capture * @param y y position to start capture * @param width capture width @@ -67,7 +70,7 @@ public interface DesktopInteract * Be sure that output length is sufficient * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(int x, int y, int width, int height, + public boolean captureScreen(int display, int x, int y, int width, int height, byte output[]); /** @@ -80,6 +83,7 @@ public boolean captureScreen(int x, int y, int width, int height, * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param x x position to start capture * @param y y position to start capture * @param width capture width @@ -89,7 +93,7 @@ public boolean captureScreen(int x, int y, int width, int height, * @param bufferLength length of native buffer * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(int x, int y, int width, int height, + public boolean captureScreen(int display, int x, int y, int width, int height, long buffer, int bufferLength); /** diff --git a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteractImpl.java b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteractImpl.java index 3ee1e8aab..64f9a1ab5 100644 --- a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteractImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteractImpl.java @@ -54,15 +54,16 @@ public DesktopInteractImpl() throws AWTException, SecurityException * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param output output buffer to store bytes in. * Be sure that output length is sufficient * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(byte output[]) + public boolean captureScreen(int display, byte output[]) { Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); - return captureScreen(0, 0, dim.width, dim.height, + return captureScreen(display, 0, 0, dim.width, dim.height, output); } @@ -76,15 +77,16 @@ public boolean captureScreen(byte output[]) * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param buffer native output buffer to store bytes in. * Be sure that output length is sufficient * @param bufferLength length of native buffer * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(long buffer, int bufferLength) + public boolean captureScreen(int display, long buffer, int bufferLength) { Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); - return captureScreen(0, 0, dim.width, dim.height, buffer, bufferLength); + return captureScreen(display, 0, 0, dim.width, dim.height, buffer, bufferLength); } /** @@ -97,6 +99,7 @@ public boolean captureScreen(long buffer, int bufferLength) * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param x x position to start capture * @param y y position to start capture * @param width capture width @@ -105,14 +108,14 @@ public boolean captureScreen(long buffer, int bufferLength) * Be sure that output length is sufficient * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(int x, int y, int width, int height, + public boolean captureScreen(int display, int x, int y, int width, int height, byte output[]) { if(OSUtils.IS_LINUX || OSUtils.IS_FREEBSD || OSUtils.IS_WINDOWS || OSUtils.IS_MAC) { return NativeScreenCapture.grabScreen( - x, y, width, height, output); + display, x, y, width, height, output); } return false; @@ -128,6 +131,7 @@ public boolean captureScreen(int x, int y, int width, int height, * 9 MB of memory for grabbing and another 9 MB array for conversion * operation. * + * @param display index of display * @param x x position to start capture * @param y y position to start capture * @param width capture width @@ -137,14 +141,14 @@ public boolean captureScreen(int x, int y, int width, int height, * @param bufferLength length of native buffer * @return true if success, false if JNI error or output length too short */ - public boolean captureScreen(int x, int y, int width, int height, + public boolean captureScreen(int display, int x, int y, int width, int height, long buffer, int bufferLength) { if(OSUtils.IS_LINUX || OSUtils.IS_FREEBSD || OSUtils.IS_WINDOWS || OSUtils.IS_MAC) { return NativeScreenCapture.grabScreen( - x, y, width, height, buffer, bufferLength); + display, x, y, width, height, buffer, bufferLength); } return false; diff --git a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/NativeScreenCapture.java b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/NativeScreenCapture.java index 895600cf1..899fd1f80 100644 --- a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/NativeScreenCapture.java +++ b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/NativeScreenCapture.java @@ -24,6 +24,7 @@ public class NativeScreenCapture /** * Grab desktop screen and get raw bytes. * + * @param display index of display * @param x x position to start capture * @param y y position to start capture * @param width capture width @@ -31,12 +32,13 @@ public class NativeScreenCapture * @param output output buffer to store screen bytes * @return true if grab success, false otherwise */ - public static native boolean grabScreen(int x, int y, int width, int height, + public static native boolean grabScreen(int display, int x, int y, int width, int height, byte output[]); /** * Grab desktop screen and get raw bytes. * + * @param display index of display * @param x x position to start capture * @param y y position to start capture * @param width capture width @@ -45,6 +47,6 @@ public static native boolean grabScreen(int x, int y, int width, int height, * @param outputLength native output length * @return true if grab success, false otherwise */ - public static native boolean grabScreen(int x, int y, int width, int height, + public static native boolean grabScreen(int display, int x, int y, int width, int height, long output, int outputLength); } diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java index 00af20d8f..7fc411750 100644 --- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java @@ -26,34 +26,6 @@ public class DataSource extends AbstractPullBufferCaptureDevice { - - /** - * The list of supported formats. - */ - private static final Format[] FORMATS; - - static - { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - FORMATS - = new Format[] - { - new AVFrameFormat( - screenSize, - Format.NOT_SPECIFIED, - FFmpeg.PIX_FMT_ARGB, - Format.NOT_SPECIFIED), - new RGBFormat( - screenSize, // size - Format.NOT_SPECIFIED, // maxDataLength - Format.byteArray, // dataType - Format.NOT_SPECIFIED, // frameRate - 32, // bitsPerPixel - 2 /* red */, 3 /* green */, 4 /* blue */) - }; - } - /** * Initializes a new DataSource instance. */ @@ -92,16 +64,9 @@ protected AbstractPullBufferStream createStream( int streamIndex, FormatControl formatControl) { - return new ImageStream(formatControl); - } - - /** - * Gets the list of supported formats. - * - * @return the list of supported formats - */ - public static Format[] getFormats() - { - return FORMATS; + int index = Integer.parseInt(getLocator().getRemainder()); + ImageStream stream = new ImageStream(formatControl); + stream.setDisplayIndex(index); + return stream; } } diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java index 32ac000e8..ab431fd73 100644 --- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java @@ -54,6 +54,11 @@ public class ImageStream */ private boolean reinit = false; + /** + * Index of display that we will capture from. + */ + private int displayIndex = -1; + /** * Initializes a new ImageStream instance which is to have a * specific FormatControl @@ -126,9 +131,15 @@ public void read(Buffer buffer) data.ptr, bufferFrameFormat.getPixFmt(), bufferFrameSize.width, bufferFrameSize.height); + buffer.setData(bufferFrame); + } + else + { + /* this can happen when we disconnect a monitor from computer + * before or during grabbing + */ + throw new IOException("Failed to grab screen"); } - - buffer.setData(bufferFrame); } else { @@ -137,7 +148,8 @@ public void read(Buffer buffer) if((dataByte != null) || (dataLength != 0)) { - byte buf[] = readScreen(dataByte); + Dimension bufferFrameSize = ((VideoFormat)bufferFormat).getSize(); + byte buf[] = readScreen(dataByte, bufferFrameSize); if(buf != dataByte) { @@ -183,6 +195,16 @@ public void read(Buffer buffer) } } + /** + * Set display index. + * + * @param index display index + */ + public void setDisplayIndex(int index) + { + displayIndex = index; + } + /** * Start desktop capture stream. * @@ -202,6 +224,7 @@ public void start() logger.warn("Cannot create DesktopInteract object!"); } } + reinit = true; } @@ -247,17 +270,19 @@ else if(data.capacity < size) } /* get desktop screen via native grabber */ - return desktopInteract.captureScreen(data.ptr, data.getLength()); + return desktopInteract.captureScreen(displayIndex, 0, 0, dim.width, + dim.height, data.ptr, data.getLength()); } /** * Read screen. * * @param output output buffer for screen bytes + * @param dim dimension of the screen * @return raw bytes, it could be equal to output or not. Take care in the * caller to check if output is the returned value. */ - public byte[] readScreen(byte output[]) + public byte[] readScreen(byte output[], Dimension dim) { VideoFormat format = (VideoFormat) getFormat(); Dimension formatSize = format.getSize(); @@ -278,7 +303,8 @@ public byte[] readScreen(byte output[]) } /* get desktop screen via native grabber if available */ - if(desktopInteract.captureScreen(output)) + if(desktopInteract.captureScreen(displayIndex, 0, 0, dim.width, + dim.height, output)) { return output; } @@ -290,6 +316,7 @@ public byte[] readScreen(byte output[]) * * Note that it is very memory consuming since memory are allocated * to capture screen (via Robot) and then for converting to raw bytes + * Moreover support for multiple display has not yet been investigated * * Normally not of our supported platform (Windows (x86, x64), * Linux (x86, x86-64), Mac OS X (i386, x86-64, ppc) and