diff --git a/lib/native/freebsd-64/libscreencapture.so b/lib/native/freebsd-64/libscreencapture.so index 28c198c61..a592d3a57 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 c17e9b022..97049f50f 100755 Binary files a/lib/native/freebsd/libscreencapture.so and b/lib/native/freebsd/libscreencapture.so differ diff --git a/lib/native/linux-64/libscreencapture.so b/lib/native/linux-64/libscreencapture.so index fe79f7029..6a593db01 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/libscreencapture.so b/lib/native/linux/libscreencapture.so index 171eb0231..521d48aa1 100755 Binary files a/lib/native/linux/libscreencapture.so and b/lib/native/linux/libscreencapture.so differ diff --git a/lib/native/windows-64/screencapture.dll b/lib/native/windows-64/screencapture.dll new file mode 100755 index 000000000..e1897bc8f Binary files /dev/null and b/lib/native/windows-64/screencapture.dll differ diff --git a/lib/native/windows/screencapture.dll b/lib/native/windows/screencapture.dll new file mode 100644 index 000000000..acd28c4b5 Binary files /dev/null and b/lib/native/windows/screencapture.dll differ diff --git a/src/native/linux/screencapture/Makefile b/src/native/linux/screencapture/Makefile index 319ec9154..1a38505e6 100644 --- a/src/native/linux/screencapture/Makefile +++ b/src/native/linux/screencapture/Makefile @@ -4,17 +4,37 @@ # \author Sebastien Vincent CC = gcc +CFLAGS = -std=c99 -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -Wall -Wextra -pedantic -Wstrict-prototypes -Wredundant-decls + +# uncomment to compile on Linux +LDFLAGS = +CFLAGS += -fPIC JNI_HEADERS = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -CFLAGS = -std=c99 -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -Wall -Wextra -pedantic -Wstrict-prototypes -Wredundant-decls $(JNI_HEADERS) +TARGET = libscreencapture.so + +# uncomment to compile on Windows +#LDFLAGS = -lgdi32 +#JNI_HEADERS = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/win32 +#CFLAGS += -Wl,--kill-at +#TARGET = screencapture.dll + +# uncomment to compile on FreeBSD +#CFLAGS += -fPIC -I/usr/local/include +#LDFLAGS = +#JNI_HEADERS = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/freebsd +#TARGET = libscreencapture.so + +CFLAGS += $(JNI_HEADERS) all: libscreencapture -libscreencapture: net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.c - $(CC) -shared -fPIC $(CFLAGS) -o libscreencapture.so -O $< +libscreencapture: net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c + $(CC) -shared $(CFLAGS) -o $(TARGET) -O $< $(LDFLAGS) # To compile 32 bit library under 64 bit system -libscreencapture-32: net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.c - $(CC) -shared -m32 $(CFLAGS) -o libscreencapture.so -O $< +# Note: On Windows, cross-compilation is supported from gcc-4.5 +libscreencapture-32: net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c + $(CC) -shared -m32 $(CFLAGS) -o $(TARGET) -O $< $(LDFLAGS) clean: - rm -f *.o *.so + rm -f *.o *.so *.dll diff --git a/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.c b/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c similarity index 53% rename from src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.c rename to src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c index 4d3e4d352..c699c646c 100644 --- a/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.c +++ b/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c @@ -6,7 +6,7 @@ */ /** - * \file net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.c + * \file net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.c * \brief X11 screen capture. * \author Sebastien Vincent * \date 2009 @@ -14,6 +14,17 @@ #include #include + +#if defined(_WIN32) || defined(_WIN64) + +#define WIN32_LEAN_AND_MEAN +#include +#include + +typedef __int32 int32_t; + +#else /* Unix */ + #include #include @@ -24,7 +35,166 @@ #include #include -#include "net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.h" +#endif + +#include "net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h" + +#if defined(_WIN32) || defined (_WIN64) + +/** + * \brief Grab Windows screen. + * \param data array that will contain screen capture + * \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(int32_t* data, int32_t x, int32_t y, int32_t w, int32_t h) +{ + static const RGBQUAD redColor = {0x00, 0x00, 0xFF, 0x00}; + static const RGBQUAD greenColor = {0x00, 0xFF, 0x00, 0x00}; + static const RGBQUAD blueColor = {0xFF, 0x00, 0x00, 0x00}; + HDC desktop = NULL; + HDC dest = NULL; + HBITMAP bitmap; + HBITMAP oldBitmap; + int width = 0; + int height = 0; + size_t size = 0; + BITMAPINFO* bitmap_info = NULL; + BITMAPINFOHEADER* bitmap_hdr = NULL; + RGBQUAD *pixels = NULL; + size_t i = 0; + + /* get handle to the entire screen of Windows */ + desktop = GetDC(NULL); + + if(!desktop) + { + fprintf(stderr, "GetDC failed!\n"); + return -1; + } + + /* get resolution */ + width = GetDeviceCaps(desktop, HORZRES); + height = GetDeviceCaps(desktop, VERTRES); + + /* check that user-defined parameters are in image */ + if((w + x) > width || (h + y) > height) + { + ReleaseDC(NULL, desktop); + return -1; + } + + size = w * h; + + /* fprintf(stderr, "Resolution: %dx%d\n", width, height); */ + + dest = CreateCompatibleDC(desktop); + + if(!dest) + { + fprintf(stderr, "CreateCompatibleDC failed!\n"); + ReleaseDC(NULL, desktop); + return -1; + } + + bitmap = CreateCompatibleBitmap(desktop, width, height); + + if(!bitmap) + { + fprintf(stderr, "CreateCompatibleBitmap failed!\n"); + ReleaseDC(NULL, desktop); + return -1; + } + + /* select bitmap to be used by DC */ + oldBitmap = SelectObject(dest, bitmap); + + if(BitBlt(dest, 0, 0, w, h, desktop, x, y, SRCCOPY | CAPTUREBLT) == FALSE) + { + fprintf(stderr, "BitBlt failed\n"); + SelectObject(dest, oldBitmap); /* restore old state before delete */ + DeleteDC(dest); + DeleteObject(bitmap); + ReleaseDC(NULL, desktop); + return -1; + } + + /* allocate memory for bitmap header, it consists + * of header size and the uncompressed pixels + * GetDiBits with BI_BITFIELDS requires array of 3 RBGQUAD + * structures and BITMAPINFO structure has just one allocated + * RGBQUAD array + */ + bitmap_info = malloc(sizeof(BITMAPINFO) + 3 * sizeof(RGBQUAD) + (size * 4)); + + if(!bitmap_info) + { + fprintf(stderr, "malloc failed\n"); + SelectObject(dest, oldBitmap); /* restore old state before delete */ + DeleteDC(dest); + DeleteObject(bitmap); + ReleaseDC(NULL, desktop); + return -1; + } + + bitmap_hdr = &bitmap_info->bmiHeader; + + bitmap_hdr->biSize = sizeof(BITMAPINFOHEADER); + bitmap_hdr->biWidth = w; + bitmap_hdr->biHeight = -h; /* otherwise inverse screen */ + bitmap_hdr->biPlanes = 1; + bitmap_hdr->biCompression = BI_BITFIELDS; + bitmap_hdr->biBitCount = 32; + bitmap_hdr->biSizeImage = 0; + bitmap_hdr->biXPelsPerMeter = 0; + bitmap_hdr->biYPelsPerMeter = 0; + bitmap_hdr->biClrImportant = 0; + bitmap_hdr->biClrUsed = 0; + + /* set up color */ + /* red */ + bitmap_info->bmiColors[0] = redColor; + /* green */ + bitmap_info->bmiColors[1] = greenColor; + /* blue */ + bitmap_info->bmiColors[2] = blueColor; + + /* first data pixel begins after the array of color mask */ + pixels = &bitmap_info->bmiColors[2]; + pixels++; + + /* get raw bytes */ + if(GetDIBits(dest, bitmap, 0, height, pixels, bitmap_info, DIB_RGB_COLORS) == 0) + { + fprintf(stderr, "GetDIBits failed!\n"); + free(bitmap_info); + SelectObject(dest, oldBitmap); /* restore old state before delete */ + DeleteDC(dest); + DeleteObject(bitmap); + ReleaseDC(NULL, desktop); + return -1; + } + + for(i = 0 ; i < size ; i++) + { + RGBQUAD* pixel = &pixels[i]; + data[i] = 0xFF000000 | pixel->rgbRed << 16 | pixel->rgbGreen << 8 | pixel->rgbBlue; + } + + /* cleanup */ + free(bitmap_info); + SelectObject(dest, oldBitmap); /* restore old state before delete */ + DeleteDC(dest); + DeleteObject(bitmap); + ReleaseDC(NULL, desktop); + + return 0; +} + +#else /* Unix */ /** * \brief Grab X11 screen. @@ -190,18 +360,20 @@ static int x11_grab_screen(const char* x11display, int32_t* data, int32_t x, int return 0; } +#endif + /** * \brief JNI native method to grab desktop screen and retrieve ARGB pixels. * \param env JVM environment - * \param obj UnixScreenCapture Java object + * \param obj NativeScreenCapture Java class * \param x x position to start capture * \param y y position to start capture * \param width capture width * \param height capture height * \return array of ARGB pixels (jint) */ -JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture_grabScreen - (JNIEnv* env, jobject obj, jint x, jint y, jint width, jint height) +JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen + (JNIEnv* env, jclass obj, jint x, jint y, jint width, jint height) { int32_t* data = NULL; /* jint is always four-bytes signed integer */ size_t size = width * height; @@ -223,7 +395,11 @@ JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstre return NULL; } +#if defined (_WIN32) || defined(_WIN64) + if(windows_grab_screen(data, x, y, width, height) == -1) +#else /* Unix */ if(x11_grab_screen(NULL, data, x, y, width, height) == -1) +#endif { (*env)->ReleaseIntArrayElements(env, ret, data, 0); return NULL; diff --git a/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.h b/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h similarity index 77% rename from src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.h rename to src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h index 7f6cce8cf..7c9d4dcde 100644 --- a/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.h +++ b/src/native/linux/screencapture/net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h @@ -1,18 +1,18 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture */ +/* Header for class net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture */ -#ifndef _Included_net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture -#define _Included_net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture +#ifndef _Included_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture +#define _Included_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture #ifdef __cplusplus extern "C" { #endif /* - * Class: net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture + * Class: net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture * Method: grabScreen * Signature: (IIII)[I */ -JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture_grabScreen +JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture_grabScreen (JNIEnv *, jclass, jint, jint, jint, jint); #ifdef __cplusplus 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 581718943..4c4a9289b 100644 --- a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteractImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/DesktopInteractImpl.java @@ -74,9 +74,9 @@ public BufferedImage captureScreen(int x, int y, int width, int height) BufferedImage img = null; Rectangle rect = null; - if(OSUtils.IS_LINUX || OSUtils.IS_FREEBSD) + if(OSUtils.IS_LINUX || OSUtils.IS_FREEBSD || OSUtils.IS_WINDOWS) { - return UnixScreenCapture.captureScreen(x, y, width, height); + return NativeScreenCapture.captureScreen(x, y, width, height); } else { diff --git a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/UnixScreenCapture.java b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/NativeScreenCapture.java similarity index 87% rename from src/net/java/sip/communicator/impl/neomedia/imgstreaming/UnixScreenCapture.java rename to src/net/java/sip/communicator/impl/neomedia/imgstreaming/NativeScreenCapture.java index 2347d43a7..9090849cf 100644 --- a/src/net/java/sip/communicator/impl/neomedia/imgstreaming/UnixScreenCapture.java +++ b/src/net/java/sip/communicator/impl/neomedia/imgstreaming/NativeScreenCapture.java @@ -10,13 +10,12 @@ /** * This class uses native code to capture - * desktop screen. - * - * It should work on all OS with underlying X11. + * desktop screen. It should work for Windows and + * X11-based Unix such as Linux and FreeBSD. * * @author Sebastien Vincent */ -public class UnixScreenCapture +public class NativeScreenCapture { static { @@ -38,8 +37,8 @@ public static BufferedImage captureScreen(int x, int height) { DirectColorModel model - = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0xFF); - int masks[] = {0xFF0000, 0xFF00, 0xFF}; + = new DirectColorModel(32, 0xFF0000, 0x00FF00, 0xFF, 0xFF000000); + int masks[] = {0xFF0000, 0xFF00, 0xFF, 0xFF000000}; WritableRaster raster = null; DataBufferInt buffer = null; BufferedImage image = null; 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 d359344d5..c938bc487 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 @@ -180,13 +180,26 @@ public void run() /* get desktop screen and resize it */ screen = desktopInteract.captureScreen(); - scaledScreen - = ImageStreamingUtils - .getScaledImage( - screen, - width, - height, - BufferedImage.TYPE_INT_ARGB); + + if(OSUtils.IS_LINUX || OSUtils.IS_FREEBSD || OSUtils.IS_WINDOWS) + { + /* with our native screencapture we + * automatically create BufferedImage in + * ARGB format so no need to rescale/convert + * to ARGB + */ + scaledScreen = screen; + } + else + { + scaledScreen + = ImageStreamingUtils + .getScaledImage( + screen, + width, + height, + BufferedImage.TYPE_INT_ARGB); + } /* get raw bytes */ data = ImageStreamingUtils.getImageBytes(scaledScreen);