diff --git a/lib/native/freebsd-64/libffmpeg.so b/lib/native/freebsd-64/libffmpeg.so index 077ddb5cb..f22011059 100755 Binary files a/lib/native/freebsd-64/libffmpeg.so and b/lib/native/freebsd-64/libffmpeg.so differ diff --git a/lib/native/freebsd-64/libscreencapture.so b/lib/native/freebsd-64/libscreencapture.so index cc172d350..751deb6e8 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/libffmpeg.so b/lib/native/freebsd/libffmpeg.so index 8610d8059..7f70660a1 100755 Binary files a/lib/native/freebsd/libffmpeg.so and b/lib/native/freebsd/libffmpeg.so differ diff --git a/lib/native/freebsd/libscreencapture.so b/lib/native/freebsd/libscreencapture.so index 8c1b59cd1..9e97c57d5 100755 Binary files a/lib/native/freebsd/libscreencapture.so and b/lib/native/freebsd/libscreencapture.so differ diff --git a/lib/native/linux-64/libffmpeg.so b/lib/native/linux-64/libffmpeg.so index 1b9b5c049..cfcfb3ef1 100755 Binary files a/lib/native/linux-64/libffmpeg.so and b/lib/native/linux-64/libffmpeg.so differ diff --git a/lib/native/linux-64/libscreencapture.so b/lib/native/linux-64/libscreencapture.so index 4a8b768c7..bb1190199 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/libffmpeg.so b/lib/native/linux/libffmpeg.so index 90b7cd8aa..fd62185c2 100755 Binary files a/lib/native/linux/libffmpeg.so and b/lib/native/linux/libffmpeg.so differ diff --git a/lib/native/linux/libscreencapture.so b/lib/native/linux/libscreencapture.so index c289f09f8..9e92ac535 100755 Binary files a/lib/native/linux/libscreencapture.so and b/lib/native/linux/libscreencapture.so differ diff --git a/lib/native/mac/libffmpeg.jnilib b/lib/native/mac/libffmpeg.jnilib index 569a55c3f..82a783837 100755 Binary files a/lib/native/mac/libffmpeg.jnilib and b/lib/native/mac/libffmpeg.jnilib differ diff --git a/lib/native/mac/libscreencapture.jnilib b/lib/native/mac/libscreencapture.jnilib index 1e00a5344..f400e7b1b 100755 Binary files a/lib/native/mac/libscreencapture.jnilib and b/lib/native/mac/libscreencapture.jnilib differ diff --git a/lib/native/windows-64/ffmpeg.dll b/lib/native/windows-64/ffmpeg.dll index 8ffac89e8..b35d7b5ab 100644 Binary files a/lib/native/windows-64/ffmpeg.dll and b/lib/native/windows-64/ffmpeg.dll differ diff --git a/lib/native/windows-64/screencapture.dll b/lib/native/windows-64/screencapture.dll index e22c9ea0e..e5798fbe9 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/ffmpeg.dll b/lib/native/windows/ffmpeg.dll index 276aa59c9..2b66c1774 100644 Binary files a/lib/native/windows/ffmpeg.dll and b/lib/native/windows/ffmpeg.dll differ diff --git a/lib/native/windows/screencapture.dll b/lib/native/windows/screencapture.dll index 98f715b2c..1ca86f887 100644 Binary files a/lib/native/windows/screencapture.dll and b/lib/native/windows/screencapture.dll differ diff --git a/src/native/ffmpeg/README b/src/native/ffmpeg/README index 181d30e81..4b8b490ae 100644 --- a/src/native/ffmpeg/README +++ b/src/native/ffmpeg/README @@ -10,7 +10,14 @@ make ./configure --disable-pthread --disable-avs-input --disable-asm make -- Linux, Mac OS X, FreeBSD +- FreeBSD + +Apply x264_bsd.diff patch first and compile: +patch -p1 < /path/to/x264_bsd.diff +./configure --enable-pic +gmake + +- Linux, Mac OS X ./configure --enable-pic make diff --git a/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.c b/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.c index 515a7a036..39ffe8fcd 100644 --- a/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.c +++ b/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.c @@ -4,6 +4,7 @@ * Distributable under LGPL license. * See terms of license at gnu.org. */ + #include "net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.h" #include @@ -59,7 +60,6 @@ Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_avcodec_1decode_ if (buf) { jbyte *buf_ptr = (*jniEnv)->GetByteArrayElements (jniEnv, buf, NULL); - if (buf_ptr) { AVPacket avpkt; @@ -434,11 +434,9 @@ Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_avpicture_1get_1 return (jint) avpicture_get_size ((int) pix_fmt, (int) width, (int) height); } - - static int image_convert( AVPicture* dst, int dst_pix_fmt, -const AVPicture* src, int pix_fmt, int width, int height, jint newWidth, jint newHeight) +const AVPicture* src, int pix_fmt, int width, int height, int newWidth, int newHeight) { struct SwsContext *img_convert_ctx = sws_getContext( @@ -471,44 +469,35 @@ Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_img_1convert__JI } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_img_1convert___3BI_3BIIIII - (JNIEnv *jniEnv, jclass clazz, jbyteArray dst, jint dst_pix_fmt, - jbyteArray src, jint pix_fmt, jint width, jint height, jint newWidth, jint newHeight) +Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_img_1convert__Ljava_lang_Object_2ILjava_lang_Object_2IIIII + (JNIEnv *jniEnv, jclass clazz, jobject dst, jint dst_pix_fmt, + jobject src, jint pix_fmt, jint width, jint height, jint newWidth, jint newHeight) { - AVPicture dst_dummy; - AVPicture src_dummy; - int size = width * height; - jint ret = 0; -/* - uint8_t* dst_buf = (*jniEnv)->GetPrimitiveArrayCritical(jniEnv, dst, 0); - uint8_t* src_buf = (*jniEnv)->GetPrimitiveArrayCritical(jniEnv, src, 0); -*/ - uint8_t* dst_buf = (*jniEnv)->GetByteArrayElements(jniEnv, dst, 0); - uint8_t* src_buf = (*jniEnv)->GetByteArrayElements(jniEnv, src, 0); - - if(!src || !dst) - { - return -1; - } - - /* assign AVPicture with buffer */ - avpicture_fill(&dst_dummy, dst_buf, (int)dst_pix_fmt, newWidth, newHeight); - avpicture_fill(&src_dummy, src_buf, (int)pix_fmt, width, height); - - ret = image_convert(&dst_dummy, (int)dst_pix_fmt, &src_dummy, (int)pix_fmt, - (int)width, (int)height, (int)newWidth, (int)newHeight); - - /* release pointers */ -/* - (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, dst, dst_buf, 0); - (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, src, src_buf, 0); -*/ - (*jniEnv)->ReleaseByteArrayElements(jniEnv, dst, dst_buf, 0); - (*jniEnv)->ReleaseByteArrayElements(jniEnv, src, src_buf, 0); - return ret; + uint8_t* src_buf = (*jniEnv)->GetPrimitiveArrayCritical(jniEnv, (jarray)src, 0); + uint8_t* dst_buf = (*jniEnv)->GetPrimitiveArrayCritical(jniEnv, (jarray)dst, 0); + AVPicture dst_dummy; + AVPicture src_dummy; + int size = width * height; + jint ret = 0; + + if(!src_buf || !dst_buf) + { + return -1; + } + + /* assign AVPicture with buffer */ + avpicture_fill(&dst_dummy, dst_buf, (int)dst_pix_fmt, newWidth, newHeight); + avpicture_fill(&src_dummy, src_buf, (int)pix_fmt, width, height); + + ret = image_convert(&dst_dummy, (int)dst_pix_fmt, &src_dummy, (int)pix_fmt, + (int)width, (int)height, (int)newWidth, (int)newHeight); + + /* release pointers */ + (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, dst, dst_buf, 0); + (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, src, src_buf, 0); + return ret; } - JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_memcpy___3IIIJ ( JNIEnv *jniEnv, jclass clazz, jintArray dst, jint dst_offset, @@ -526,10 +515,20 @@ Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_memcpy__J_3BII ( } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_getRGB32Format - (JNIEnv *env, jclass clazz) +Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_getRGB24Format + (JNIEnv *jniEnv, jclass clazz) { - return PIX_FMT_RGB32; + uint32_t test = 1; + int little_endian = *((uint8_t*)&test); + + if(little_endian) + { + return PIX_FMT_RGB24; + } + else /* big endian */ + { + return PIX_FMT_BGR24; + } } JNIEXPORT jint JNICALL diff --git a/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.h b/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.h index d5825f176..47ee2e08b 100644 --- a/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.h +++ b/src/native/ffmpeg/net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG.h @@ -23,18 +23,18 @@ extern "C" { #define net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_X264_RC_ABR 2L /* * Class: net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG - * Method: getRGB32Format + * Method: getRGBAFormat * Signature: ()I */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_getRGB32Format +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_getRGBAFormat (JNIEnv *, jclass); /* * Class: net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG - * Method: getRGBAFormat + * Method: getRGB24Format * Signature: ()I */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_getRGBAFormat +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_getRGB24Format (JNIEnv *, jclass); /* @@ -472,10 +472,10 @@ JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_ /* * Class: net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG * Method: img_convert - * Signature: ([BI[BIIIII)I + * Signature: (Ljava/lang/Object;ILjava/lang/Object;IIIII)I */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_img_1convert___3BI_3BIIIII - (JNIEnv *, jclass, jbyteArray, jint, jbyteArray, jint, jint, jint, jint, jint); +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG_img_1convert__Ljava_lang_Object_2ILjava_lang_Object_2IIIII + (JNIEnv *, jclass, jobject, jint, jobject, jint, jint, jint, jint, jint); /* * Class: net_java_sip_communicator_impl_neomedia_codec_video_FFMPEG diff --git a/src/native/ffmpeg/x264_bsd.diff b/src/native/ffmpeg/x264_bsd.diff new file mode 100644 index 000000000..390a7eaf9 --- /dev/null +++ b/src/native/ffmpeg/x264_bsd.diff @@ -0,0 +1,270 @@ +diff -Nru a/version.sh b/version.sh +--- a/version.sh 2009-12-08 22:45:08.000000000 +0100 ++++ b/version.sh 2010-01-19 19:10:23.000000000 +0100 +@@ -1,4 +1,4 @@ +-#!/bin/bash ++#!/usr/local/bin/bash + git rev-list HEAD | sort > config.git-hash + LOCALVER=`wc -l config.git-hash | awk '{print $1}'` + if [ $LOCALVER \> 1 ] ; then +diff -Nru a/Makefile b/Makefile +--- a/Makefile 2009-12-08 22:45:08.000000000 +0100 ++++ b/Makefile 2010-01-19 19:10:40.000000000 +0100 +@@ -10,7 +10,8 @@ + common/quant.c common/vlc.c \ + encoder/analyse.c encoder/me.c encoder/ratecontrol.c \ + encoder/set.c encoder/macroblock.c encoder/cabac.c \ +- encoder/cavlc.c encoder/encoder.c encoder/lookahead.c ++ encoder/cavlc.c encoder/encoder.c encoder/lookahead.c \ ++ bsdlogf.c + + SRCCLI = x264.c input/yuv.c input/y4m.c output/raw.c \ + output/matroska.c output/matroska_ebml.c \ +diff -Nru a/bsdlog.h b/bsdlog.h +--- a/bsdlog.h 1970-01-01 01:00:00.000000000 +0100 ++++ b/bsdlog.h 2010-01-19 19:08:07.000000000 +0100 +@@ -0,0 +1,143 @@ ++/* ++ * ==================================================== ++ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. ++ * ++ * Developed at SunSoft, a Sun Microsystems, Inc. business. ++ * Permission to use, copy, modify, and distribute this ++ * software is freely granted, provided that this notice ++ * is preserved. ++ * ==================================================== ++ */ ++ ++#ifndef bsdlog_headerfile ++#define bsdlog_headerfile ++ ++#include ++#include ++ ++ ++float log2f(float); ++ ++ ++ ++ ++#if (__BYTE_ORDER == __LITTLE_ENDIAN) && !defined(__arm__) ++ ++typedef union ++{ ++double value; ++struct ++{ ++u_int32_t lsw; ++u_int32_t msw; ++} parts; ++} ieee_double_shape_type; ++ ++#endif ++ ++ ++ ++ ++#if (__BYTE_ORDER == __BIG_ENDIAN) || defined(__arm__) ++ ++/* this should be on a BIG ENDIAN platform instead of the previous code */ ++/* I commented this because my compiler have a mess with macros *_ENDIAN */ ++ ++/* ++typedef union ++{ ++double value; ++struct ++{ ++u_int32_t msw; ++u_int32_t lsw; ++} parts; ++} ieee_double_shape_type; ++*/ ++ ++#endif ++ ++ ++ ++ ++ ++#define EXTRACT_WORDS(ix0,ix1,d) \ ++do { \ ++ieee_double_shape_type ew_u; \ ++ew_u.value = (d); \ ++(ix0) = ew_u.parts.msw; \ ++(ix1) = ew_u.parts.lsw; \ ++} while (0) ++/* Get the more significant 32 bit int from a double. */ ++ ++#define GET_HIGH_WORD(i,d) \ ++do { \ ++ieee_double_shape_type gh_u; \ ++gh_u.value = (d); \ ++(i) = gh_u.parts.msw; \ ++} while (0) ++ ++/* Get the less significant 32 bit int from a double. */ ++ ++#define GET_LOW_WORD(i,d) \ ++do { \ ++ieee_double_shape_type gl_u; \ ++gl_u.value = (d); \ ++(i) = gl_u.parts.lsw; \ ++} while (0) ++ ++/* Set a double from two 32 bit ints. */ ++ ++ ++/* Set the more significant 32 bits of a double from an int. */ ++ ++#define SET_HIGH_WORD(d,v) \ ++do { \ ++ieee_double_shape_type sh_u; \ ++sh_u.value = (d); \ ++sh_u.parts.msw = (v); \ ++(d) = sh_u.value; \ ++} while (0) ++ ++/* Set the less significant 32 bits of a double from an int. */ ++ ++#define SET_LOW_WORD(d,v) \ ++do { \ ++ieee_double_shape_type sl_u; \ ++sl_u.value = (d); \ ++sl_u.parts.lsw = (v); \ ++(d) = sl_u.value; \ ++} while (0) ++ ++ ++ ++/* A union which permits us to convert between a float and a 32 bit ++int. */ ++ ++typedef union ++{ ++float value; ++u_int32_t word; ++} ieee_float_shape_type; ++ ++/* Get a 32 bit int from a float. */ ++ ++#define GET_FLOAT_WORD(i,d) \ ++do { \ ++ieee_float_shape_type gf_u; \ ++gf_u.value = (d); \ ++(i) = gf_u.word; \ ++} while (0) ++ ++/* Set a float from a 32 bit int. */ ++ ++#define SET_FLOAT_WORD(d,i) \ ++do { \ ++ieee_float_shape_type sf_u; \ ++sf_u.word = (i); \ ++(d) = sf_u.value; \ ++} while (0) ++ ++ ++ ++#endif +diff -Nru a/bsdlogf.c b/bsdlogf.c +--- a/bsdlogf.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/bsdlogf.c 2010-01-19 19:08:07.000000000 +0100 +@@ -0,0 +1,77 @@ ++/* ++ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@xxxxxxxxxxx ++ */ ++ ++/* ++ * ==================================================== ++ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. ++ * ++ * Developed at SunPro, a Sun Microsystems, Inc. business. ++ * Permission to use, copy, modify, and distribute this ++ * software is freely granted, provided that this notice ++ * is preserved. ++ * ==================================================== ++ */ ++ ++#include "bsdlog.h" ++ ++ ++static const float ++ln2 = 0.6931471805599452862268, ++two25 = 3.355443200e+07, /* 0x4c000000 */ ++Lg1 = 6.6666668653e-01, /* 3F2AAAAB */ ++Lg2 = 4.0000000596e-01, /* 3ECCCCCD */ ++Lg3 = 2.8571429849e-01, /* 3E924925 */ ++Lg4 = 2.2222198546e-01, /* 3E638E29 */ ++Lg5 = 1.8183572590e-01, /* 3E3A3325 */ ++Lg6 = 1.5313838422e-01, /* 3E1CD04F */ ++Lg7 = 1.4798198640e-01; /* 3E178897 */ ++ ++static const float zero = 0.0; ++ ++ ++ ++float log2f(float x) ++{ ++ float hfsq,f,s,z,R,w,t1,t2,dk; ++ int32_t k,ix,i,j; ++ ++ GET_FLOAT_WORD(ix,x); ++ ++ k=0; ++ if (ix < 0x00800000) { /* x < 2**-126 */ ++ if ((ix&0x7fffffff)==0) ++ return -two25/zero; /* log(+-0)=-inf */ ++ if (ix<0) return (x-x)/zero; /* log(-#) = NaN */ ++ k -= 25; x *= two25; /* subnormal number, scale up x */ ++ GET_FLOAT_WORD(ix,x); ++ } ++ if (ix >= 0x7f800000) return x+x; ++ k += (ix>>23)-127; ++ ix &= 0x007fffff; ++ i = (ix+(0x95f64<<3))&0x800000; ++ SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */ ++ k += (i>>23); ++ dk = (float)k; ++ f = x-(float)1.0; ++ if((0x007fffff&(15+ix))<16) { /* |f| < 2**-20 */ ++ if (f==zero) ++ return (dk); ++ R = f*f*((float)0.5-(float)0.33333333333333333*f); ++ return (dk-(R-f)/ln2); ++ } ++ s = f/((float)2.0+f); ++ z = s*s; ++ i = ix-(0x6147a<<3); ++ w = z*z; ++ j = (0x6b851<<3)-ix; ++ t1= w*(Lg2+w*(Lg4+w*Lg6)); ++ t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); ++ i |= j; ++ R = t2+t1; ++ if(i>0) { ++ hfsq=(float)0.5*f*f; ++ return (dk-(hfsq-s*(hfsq+R)-f)/ln2); ++ } else ++ return (dk-((s*(f-R))-f)/ln2); ++} +diff -Nru a/configure b/configure +--- a/configure 2009-12-08 22:45:08.000000000 +0100 ++++ b/configure 2010-01-19 19:10:14.000000000 +0100 +@@ -1,4 +1,4 @@ +-#!/bin/bash ++#!/usr/local/bin/bash + + if test x"$1" = x"-h" -o x"$1" = x"--help" ; then + +diff -Nru a/encoder/analyse.c b/encoder/analyse.c +--- a/encoder/analyse.c 2009-12-08 22:45:08.000000000 +0100 ++++ b/encoder/analyse.c 2010-01-19 19:08:07.000000000 +0100 +@@ -33,6 +33,7 @@ + #include "ratecontrol.h" + #include "analyse.h" + #include "rdo.c" ++#include "../bsdlog.h" + + typedef struct + { 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 a80e54a85..3c6965de2 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 @@ -76,8 +76,6 @@ static int windows_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int RGBQUAD *pixels = NULL; size_t i = 0; size_t off = 0; - uint32_t test = 1; - int little_endian = *((uint8_t*)&test); /* get handle to the entire screen of Windows */ desktop = GetDC(NULL); @@ -194,16 +192,8 @@ static int windows_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int { RGBQUAD* quad = &pixels[i]; uint32_t pixel = 0xFF000000 | quad->rgbRed << 16 | quad->rgbGreen << 8 | quad->rgbBlue; - - if(little_endian) - { - uint8_t r = (pixel >> 16) & 0xff; - uint8_t g = (pixel >> 8) & 0xff; - uint8_t b = pixel & 0xff; - - pixel = 0xff << 24 | b << 16 | g << 8 | r; - } - + + /* Java int is always big endian so output as ARGB */ memcpy(data + off, &pixel, 4); off += 4; } @@ -239,8 +229,6 @@ static int quartz_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int3 size_t off = 0; size_t i = 0; CGRect rect; - uint32_t test_endian = 1; - int little_endian = *((uint8_t*)&test_endian); rect = CGRectMake(x, y, w, h); img = CGWindowListCreateImage(rect, kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageDefault); @@ -261,16 +249,12 @@ static int quartz_grab_screen(jbyte* data, int32_t x, int32_t y, int32_t w, int3 for(i = 0 ; i < len ; i+=4) { uint32_t pixel = *((uint32_t*)&pixels[i]); + uint8_t r = (pixel >> 16) & 0xff; + uint8_t g = (pixel >> 8) & 0xff; + uint8_t b = pixel & 0xff; - if(little_endian) - { - uint8_t r = (pixel >> 16) & 0xff; - uint8_t g = (pixel >> 8) & 0xff; - uint8_t b = pixel & 0xff; - - pixel = 0xff << 24 | b << 16 | g << 8 | r; - } - + /* Java int is always big endian so output as ARGB */ + pixel = 0xff << 24 | r << 16 | g << 8 | b; memcpy(data + off, &pixel, 4); off += 4; } @@ -310,8 +294,6 @@ static int x11_grab_screen(const char* x11display, jbyte* data, int32_t x, int32 int i = 0; int j = 0; size_t size = 0; - uint32_t test_endian = 1; - int little_endian = *((uint8_t*)&test_endian); display_str = x11display ? x11display : getenv("DISPLAY"); @@ -418,20 +400,16 @@ static int x11_grab_screen(const char* x11display, jbyte* data, int32_t x, int32 { for(i = 0 ; i < w ; i++) { - /* do not care about hight 32-bit for Linux 64 bit + /* do not care about high 32-bit for Linux 64 bit * machine (sizeof(unsigned long) = 8) */ uint32_t pixel = (uint32_t)XGetPixel(img, i, j); + uint8_t r = (pixel >> 16) & 0xff; + uint8_t g = (pixel >> 8) & 0xff; + uint8_t b = pixel & 0xff; - if(little_endian) - { - uint8_t r = (pixel >> 16) & 0xff; - uint8_t g = (pixel >> 8) & 0xff; - uint8_t b = pixel & 0xff; - - pixel = 0xff << 24 | b << 16 | g << 8 | r; - } - + /* Java int is always big endian so output as ARGB */ + pixel = 0xff << 24 | r << 16 | g << 8 | b; memcpy(data + off, &pixel, 4); off += 4; } diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java b/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java index ef87ec6c4..bee18658a 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java @@ -331,6 +331,7 @@ public void registerCustomCodecs() /* remove JavaRGBToYUV */ PlugInManager.removePlugIn("com.sun.media.codec.video.colorspace.JavaRGBToYUV", PlugInManager.CODEC); + PlugInManager.removePlugIn("com.sun.media.codec.video.colorspace.JavaRGBConverter", PlugInManager.CODEC); for (String className : CUSTOM_CODECS) { diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/video/FFMPEG.java b/src/net/java/sip/communicator/impl/neomedia/codec/video/FFMPEG.java index 27c702fbe..a21636f22 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/video/FFMPEG.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/video/FFMPEG.java @@ -23,18 +23,18 @@ public class FFMPEG public static final int FF_MB_DECISION_SIMPLE = 0; - public static final int PIX_FMT_RGB32; - public static final int PIX_FMT_RGBA; + public static final int PIX_FMT_RGB24; + public static final int PIX_FMT_YUV420P; public static final int X264_RC_ABR = 2; - public static native int getRGB32Format(); - public static native int getRGBAFormat(); + public static native int getRGB24Format(); + public static native int getYUV420PFormat(); public static native void av_free(long ptr); @@ -177,10 +177,22 @@ public static native int avpicture_get_size(int pix_fmt, int width, public static native int img_convert(long dst, int dst_pix_fmt, long src, int pix_fmt, int width, int height); - public static native int img_convert(byte dst[], int dst_pix_fmt, - byte src[], int pix_fmt, int width, int height, int newWidth, + /** + * Convert image bytes (scale/format). + * + * @param dst destination image. Its type must be an array (int[], byte[] + * or short[]) + * @param dst_pix_fmt destination format + * @param src source image. Its type must be an array (int[], byte[] or short[]) + * @param width original width + * @param height original height + * @param newWidth new width + * @param newHeight new height + */ + public static native int img_convert(Object dst, int dst_pix_fmt, + Object src, int pix_fmt, int width, int height, int newWidth, int newHeight); - + public static native void memcpy(int[] dst, int dst_offset, int dst_length, long src); @@ -193,8 +205,8 @@ public static native void memcpy(long dst, byte[] src, int src_offset, av_register_all(); avcodec_init(); - PIX_FMT_RGB32 = getRGB32Format(); /* for decoding */ - PIX_FMT_RGBA = getRGBAFormat(); /* for encoding */ + PIX_FMT_RGB24 = getRGB24Format(); + PIX_FMT_RGBA = getRGBAFormat(); PIX_FMT_YUV420P = getYUV420PFormat(); } } diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/video/SwScaler.java b/src/net/java/sip/communicator/impl/neomedia/codec/video/SwScaler.java index 81913191a..f267ba635 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/video/SwScaler.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/video/SwScaler.java @@ -28,14 +28,36 @@ public class SwScaler * Supported input formats. */ private final Format[] supportedInputFormats = new Format[] { - new RGBFormat(null, -1, Format.byteArray, -1.0f, 32, -1, -1, -1) + new RGBFormat(null, -1, Format.byteArray, -1.0f, 32, -1, -1, -1), + new RGBFormat(null, -1, Format.intArray, -1.0f, 32, -1, -1, -1), + new RGBFormat(null, -1, Format.shortArray, -1.0f, 32, -1, -1, -1), + new RGBFormat(null, -1, Format.byteArray, -1.0f, 24, -1, -1, -1), + new RGBFormat(null, -1, Format.intArray, -1.0f, 24, -1, -1, -1), + new RGBFormat(null, -1, Format.shortArray, -1.0f, 24, -1, -1, -1), + new YUVFormat(null, -1, Format.byteArray, -1.0f, YUVFormat.YUV_420, + -1, -1, 0, -1, -1), + new YUVFormat(null, -1, Format.intArray, -1.0f, YUVFormat.YUV_420, + -1, -1, 0, -1, -1), + new YUVFormat(null, -1, Format.shortArray, -1.0f, YUVFormat.YUV_420, + -1, -1, 0, -1, -1), }; /** * Supported output formats. */ private Format[] supportedOutputFormats = new Format[] { - new YUVFormat(null, -1, Format.byteArray, -1.0f, YUVFormat.YUV_420, -1, -1, 0, -1, -1) + new YUVFormat(null, -1, Format.byteArray, -1.0f, YUVFormat.YUV_420, + -1, -1, 0, -1, -1), + new YUVFormat(null, -1, Format.intArray, -1.0f, YUVFormat.YUV_420, + -1, -1, 0, -1, -1), + new YUVFormat(null, -1, Format.shortArray, -1.0f, YUVFormat.YUV_420, + -1, -1, 0, -1, -1), + new RGBFormat(null, -1, Format.byteArray, -1.0f, 32, -1, -1, -1), + new RGBFormat(null, -1, Format.intArray, -1.0f, 32, -1, -1, -1), + new RGBFormat(null, -1, Format.shortArray, -1.0f, 32, -1, -1, -1), + new RGBFormat(null, -1, Format.byteArray, -1.0f, 24, -1, -1, -1), + new RGBFormat(null, -1, Format.intArray, -1.0f, 24, -1, -1, -1), + new RGBFormat(null, -1, Format.shortArray, -1.0f, 24, -1, -1, -1), }; /** @@ -50,8 +72,24 @@ public void setOutputSize(Dimension size) size = new Dimension(640, 480); } - Format newFormat = new YUVFormat(size, -1, Format.byteArray, -1.0f, YUVFormat.YUV_420, -1, -1, 0, -1, -1); - supportedOutputFormats[0] = newFormat; + supportedOutputFormats[0] = new YUVFormat(size, -1, Format.byteArray, + -1.0f, YUVFormat.YUV_420, -1, -1, 0, -1, -1); + supportedOutputFormats[1] = new YUVFormat(size, -1, Format.intArray, + -1.0f, YUVFormat.YUV_420, -1, -1, 0, -1, -1); + supportedOutputFormats[2] = new YUVFormat(size, -1, Format.shortArray, + -1.0f, YUVFormat.YUV_420, -1, -1, 0, -1, -1); + supportedOutputFormats[3] = new RGBFormat(size, -1, Format.byteArray, + -1.0f, 32, -1, -1, -1); + supportedOutputFormats[4] = new RGBFormat(size, -1, Format.intArray, + -1.0f, 32, -1, -1, -1); + supportedOutputFormats[5] = new RGBFormat(size, -1, Format.shortArray, + -1.0f, 32, -1, -1, -1); + supportedOutputFormats[6] = new RGBFormat(size, -1, Format.byteArray, + -1.0f, 24, -1, -1, -1); + supportedOutputFormats[7] = new RGBFormat(size, -1, Format.intArray, + -1.0f, 24, -1, -1, -1); + supportedOutputFormats[8] = new RGBFormat(size, -1, Format.shortArray, + -1.0f, 24, -1, -1, -1); } /** @@ -74,18 +112,49 @@ public Format[] getSupportedInputFormats() @Override public Format[] getSupportedOutputFormats(Format input) { + Dimension size = null; + if(input == null) { return supportedOutputFormats; } + + /* if size is set for element 0 (YUVFormat), it is also set + * for element 1 (RGBFormat) and so on... + */ + size = ((VideoFormat)supportedOutputFormats[0]).getSize(); //System.out.println("input: " + ((VideoFormat)input).getSize()); - if(((VideoFormat)supportedOutputFormats[0]).getSize() != null) + if(size != null) { return supportedOutputFormats; } - return new Format[] { new YUVFormat(((VideoFormat)input).getSize(), -1, Format.byteArray, -1.0f, YUVFormat.YUV_420, -1, -1, 0, -1, -1)}; + /* no specified size set so return the same size as input + * in output format supported + */ + size = ((VideoFormat)input).getSize(); + + return new Format[] { + new YUVFormat(size, -1, Format.byteArray, -1.0f, + YUVFormat.YUV_420, -1, -1, 0, -1, -1), + new YUVFormat(size, -1, Format.intArray, -1.0f, + YUVFormat.YUV_420, -1, -1, 0, -1, -1), + new YUVFormat(size, -1, Format.shortArray, -1.0f, + YUVFormat.YUV_420, -1, -1, 0, -1, -1), + new RGBFormat(size, -1, Format.byteArray, -1.0f, + 32, -1, -1, -1), + new RGBFormat(size, -1, Format.intArray, -1.0f, + 32, -1, -1, -1), + new RGBFormat(size, -1, Format.shortArray, -1.0f, + 32, -1, -1, -1), + new RGBFormat(size, -1, Format.byteArray, -1.0f, + 24, -1, -1, -1), + new RGBFormat(size, -1, Format.intArray, -1.0f, + 24, -1, -1, -1), + new RGBFormat(size, -1, Format.shortArray, -1.0f, + 24, -1, -1, -1), + }; } /** @@ -135,14 +204,27 @@ public int process(Buffer input, Buffer output) VideoFormat voutput = (VideoFormat)output.getFormat(); int inputWidth = (int)vinput.getSize().getWidth(); int inputHeight = (int)vinput.getSize().getHeight(); - int outputWidth = (int)voutput.getSize().getWidth(); - int outputHeight = (int)voutput.getSize().getHeight(); - byte src[] = (byte[])input.getData(); - byte dst[] = (byte[])output.getData(); + /* input's data type can be byte[], int[] or short[] + * so we used Object type to store it + */ + Object src = input.getData(); + Object dst = output.getData(); int outputSize = 0; + int outputWidth = 0; + int outputHeight = 0; int infmt = 0; int outfmt = 0; + /* first buffer has no output format set */ + if(voutput == null) + { + voutput = (VideoFormat)outputFormat; + return BUFFER_PROCESSED_FAILED; + } + + outputWidth = (int)voutput.getSize().getWidth(); + outputHeight = (int)voutput.getSize().getHeight(); + if (!checkInputBuffer(input)) { return BUFFER_PROCESSED_FAILED; @@ -164,7 +246,14 @@ public int process(Buffer input, Buffer output) else /* RGB format */ { outputSize = (outputWidth * outputHeight * 4); - outfmt = FFMPEG.PIX_FMT_RGBA; + if(((RGBFormat)voutput).getBitsPerPixel() == 32) + { + outfmt = FFMPEG.PIX_FMT_RGBA; + } + else + { + outfmt = FFMPEG.PIX_FMT_RGB24; + } } /* determine input format */ @@ -174,20 +263,59 @@ public int process(Buffer input, Buffer output) } else /* RGBFormat */ { - infmt = FFMPEG.PIX_FMT_RGBA; + if(((RGBFormat)vinput).getBitsPerPixel() == 32) + { + infmt = FFMPEG.PIX_FMT_RGBA; + } + else + { + infmt = FFMPEG.PIX_FMT_RGB24; + } + } + + if(voutput.getDataType() == Format.byteArray) + { + if(dst == null || ((byte[])dst).length < outputSize) + { + dst = new byte[outputSize]; + } + } + else if(voutput.getDataType() == Format.intArray) + { + /* Java int is always 4 bytes */ + outputSize = (outputSize % 4) + outputSize / 4; + if(dst == null || ((int[])dst).length < outputSize) + { + dst = new int[outputSize]; + } + } + else if(voutput.getDataType() == Format.shortArray) + { + /* Java short is always 2 bytes */ + outputSize = (outputSize % 2) + outputSize / 2; + if(dst == null || ((short[])dst).length < outputSize) + { + dst = new short[outputSize]; + } + } + else + { + System.out.println("Unknown data type!"); + return BUFFER_PROCESSED_FAILED; } - if(dst == null || dst.length < outputSize) + synchronized(src) { - dst = new byte[outputSize]; + /* conversion! */ + FFMPEG.img_convert(dst, outfmt, src, infmt, inputWidth, inputHeight, + outputWidth, outputHeight); } - /* conversion! */ - //System.out.println("Convert: " + inputWidth + "x" + inputHeight + " to " + outputWidth + "x" + outputHeight); - FFMPEG.img_convert(dst, outfmt, src, infmt, inputWidth, inputHeight, outputWidth, outputHeight); + //System.out.println("Converted: " + inputWidth + "x" + inputHeight + + //" to " + outputWidth + "x" + outputHeight); output.setData(dst); - output.setLength(dst.length); + output.setLength(outputSize); output.setOffset(0); return BUFFER_PROCESSED_OK; diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIDecoder.java b/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIDecoder.java index d40052934..d66460f26 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIDecoder.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIDecoder.java @@ -267,15 +267,15 @@ else if (!parser.pushRTPInput(inputBuffer)) // convert the picture in RGB Format int numBytes = - FFMPEG.avpicture_get_size(FFMPEG.PIX_FMT_RGB32, avctxWidth, + FFMPEG.avpicture_get_size(FFMPEG.PIX_FMT_RGBA, avctxWidth, avctxHeight); long buffer = FFMPEG.av_malloc(numBytes); - FFMPEG.avpicture_fill(frameRGB, buffer, FFMPEG.PIX_FMT_RGB32, + FFMPEG.avpicture_fill(frameRGB, buffer, FFMPEG.PIX_FMT_RGBA, avctxWidth, avctxHeight); // Convert the image from its native format to RGB - FFMPEG.img_convert(frameRGB, FFMPEG.PIX_FMT_RGB32, avframe, FFMPEG + FFMPEG.img_convert(frameRGB, FFMPEG.PIX_FMT_RGBA, avframe, FFMPEG .avcodeccontext_get_pix_fmt(avcontext), avctxWidth, avctxHeight); Object outData = outputBuffer.getData();