diff --git a/lib/native/freebsd-64/libffmpeg.so b/lib/native/freebsd-64/libffmpeg.so index 5321c6fd2..d352331b6 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/libffmpeg.so b/lib/native/freebsd/libffmpeg.so index e00036c64..7d2fdb63b 100755 Binary files a/lib/native/freebsd/libffmpeg.so and b/lib/native/freebsd/libffmpeg.so differ diff --git a/lib/native/linux-64/libffmpeg.so b/lib/native/linux-64/libffmpeg.so index e9ee3d2c9..344560ab2 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/libffmpeg.so b/lib/native/linux/libffmpeg.so index 1687f81d2..ef3ac092b 100755 Binary files a/lib/native/linux/libffmpeg.so and b/lib/native/linux/libffmpeg.so differ diff --git a/lib/native/mac/libffmpeg.jnilib b/lib/native/mac/libffmpeg.jnilib index f1c74bd6b..dc953d516 100755 Binary files a/lib/native/mac/libffmpeg.jnilib and b/lib/native/mac/libffmpeg.jnilib differ diff --git a/lib/native/windows-64/ffmpeg.dll b/lib/native/windows-64/ffmpeg.dll index 4f7aa9f54..e1fbf25cb 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/ffmpeg.dll b/lib/native/windows/ffmpeg.dll index 361558942..54072fe8d 100644 Binary files a/lib/native/windows/ffmpeg.dll and b/lib/native/windows/ffmpeg.dll differ diff --git a/src/native/ffmpeg/README b/src/native/ffmpeg/README index 794c0ae07..e399fbf4b 100644 --- a/src/native/ffmpeg/README +++ b/src/native/ffmpeg/README @@ -1,15 +1,13 @@ -1. x264-snapshot-20091208-2245 +1. x264-snapshot-20100518-2245 - Windows -32-bit +Download yasm for Windows (32-bit or 64-bit) at http://www.tortall.net/projects/yasm/wiki/Download +and copy it to C:\MinGW\bin (or in a directory registered in the PATH environment variable). + ./configure --disable-pthread make -64-bit -./configure --disable-pthread --disable-avs-input --disable-asm -make - - FreeBSD Apply x264_bsd.diff patch first and compile: @@ -22,14 +20,14 @@ gmake ./configure --enable-pic make -2. ffmpeg-r20783 +2. ffmpeg-r23181 -First patch ffmpeg with ffmpeg-libx264-keyframe.diff: -$ patch -p0 < ffmpeg-libx264-keyframe.diff +First patch ffmpeg with ffmpeg-23181.diff +patch -p0 < ffmpeg-23181.diff - Windows -32-bit +32-bit: ./configure \ --target-os=mingw32 \ --enable-memalign-hack \ @@ -44,10 +42,10 @@ $ patch -p0 < ffmpeg-libx264-keyframe.diff --disable-ffserver --disable-ffplay --disable-ffmpeg \ --disable-pthreads --enable-w32threads -64-bit -Edit configure script and remove the following lines: -check_cpp_condition _mingw.h "(__MINGW32_MAJOR_VERSION > 3) || (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION >= 15)" || - die "ERROR: MinGW runtime version must be >= 3.15." +64-bit: + +Patch again ffmpeg with ffmpeg-win64.diff +patch -p0 < ffmpeg-win64.diff Then run: ./configure \ @@ -109,12 +107,3 @@ Be careful to correctly set X264_HOME, FFMPEG_HOME and JAVA_HOME variables. Then run: make (gmake on FreeBSD) -Note: -If compilation errors related to "relocation" occured, you -have to patch ffmpeg, libswscale and x264. - -Apply the following patches in the relevant directory: -- x264-20091208-visibility-hidden.patch -- ffmpeg-visibility-hidden.patch -- ffmpeg-libswcale-visibility-hidden.patch - diff --git a/src/native/ffmpeg/ffmpeg-23181.diff b/src/native/ffmpeg/ffmpeg-23181.diff new file mode 100644 index 000000000..664c093ef --- /dev/null +++ b/src/native/ffmpeg/ffmpeg-23181.diff @@ -0,0 +1,73 @@ +Index: libavcodec/libx264.c +=================================================================== +--- libavcodec/libx264.c (revision 23181) ++++ libavcodec/libx264.c (working copy) +@@ -99,15 +99,17 @@ + } + + x4->pic.i_pts = frame->pts; +- x4->pic.i_type = X264_TYPE_AUTO; ++ x4->pic.i_type = frame->key_frame ? X264_TYPE_IDR : X264_TYPE_AUTO; + } + ++ do { + if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0) + return -1; + + bufsize = encode_nals(ctx, buf, bufsize, nal, nnal, 0); + if (bufsize < 0) + return -1; ++ } while(!bufsize && !frame && x264_encoder_delayed_frames(x4->enc)); + + /* FIXME: libx264 now provides DTS, but AVFrame doesn't have a field for it. */ + x4->out_pic.pts = pic_out.i_pts; +@@ -156,7 +158,7 @@ + x4->params.p_log_private = avctx; + + x4->params.i_keyint_max = avctx->gop_size; +- x4->params.b_intra_refresh = avctx->flags2 & CODEC_FLAG2_INTRA_REFRESH; ++ x4->params.b_intra_refresh = 1; /* avctx->flags2 & CODEC_FLAG2_INTRA_REFRESH; */ + x4->params.rc.i_bitrate = avctx->bit_rate / 1000; + x4->params.rc.i_vbv_buffer_size = avctx->rc_buffer_size / 1000; + x4->params.rc.i_vbv_max_bitrate = avctx->rc_max_rate / 1000; +@@ -173,7 +175,7 @@ + x4->params.rc.i_qp_constant = avctx->cqp; + } + } +- ++ + // if neither crf nor cqp modes are selected we have to enable the RC + // we do it this way because we cannot check if the bitrate has been set + if (!(avctx->crf || (avctx->cqp > -1))) +@@ -186,7 +188,7 @@ + x4->params.i_bframe_pyramid = avctx->flags2 & CODEC_FLAG2_BPYRAMID ? X264_B_PYRAMID_NORMAL : X264_B_PYRAMID_NONE; + avctx->has_b_frames = avctx->flags2 & CODEC_FLAG2_BPYRAMID ? 2 : !!avctx->max_b_frames; + +- x4->params.i_keyint_min = avctx->keyint_min; ++ x4->params.i_keyint_min = 0; /* avctx->keyint_min; */ + if (x4->params.i_keyint_min > x4->params.i_keyint_max) + x4->params.i_keyint_min = x4->params.i_keyint_max; + +@@ -293,6 +295,13 @@ + + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) + x4->params.b_repeat_headers = 0; ++ ++ /* zero latency */ ++ x4->params.rc.i_lookahead = 0; ++ x4->params.i_sync_lookahead = 0; ++ x4->params.i_bframe = 0; ++ x4->params.b_sliced_threads = 1; ++ x4->params.b_vfr_input = 0; + + x4->enc = x264_encoder_open(&x4->params); + if (!x4->enc) +@@ -313,7 +322,7 @@ + avctx->extradata = av_malloc(s); + avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1); + } +- ++ + return 0; + } + diff --git a/src/native/ffmpeg/ffmpeg-libx264-keyframe.diff b/src/native/ffmpeg/ffmpeg-libx264-keyframe.diff deleted file mode 100644 index 84a7772eb..000000000 --- a/src/native/ffmpeg/ffmpeg-libx264-keyframe.diff +++ /dev/null @@ -1,13 +0,0 @@ -Index: libavcodec/libx264.c -=================================================================== ---- libavcodec/libx264.c (révision 20783) -+++ libavcodec/libx264.c (copie de travail) -@@ -99,7 +99,7 @@ - } - - x4->pic.i_pts = frame->pts; -- x4->pic.i_type = X264_TYPE_AUTO; -+ x4->pic.i_type = frame->key_frame ? X264_TYPE_IDR : X264_TYPE_AUTO; - } - - if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0) diff --git a/src/native/ffmpeg/ffmpeg-win64.diff b/src/native/ffmpeg/ffmpeg-win64.diff new file mode 100644 index 000000000..0b4c849c1 --- /dev/null +++ b/src/native/ffmpeg/ffmpeg-win64.diff @@ -0,0 +1,22 @@ +Index: libswscale/swscale_template.c +=================================================================== +--- libswscale/swscale_template.c (révision 31187) ++++ libswscale/swscale_template.c (copie de travail) +@@ -2252,7 +2252,7 @@ + "shrl $9, %%esi \n\t" \ + + static inline void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst, +- long dstWidth, const uint8_t *src, int srcW, ++ x86_reg dstWidth, const uint8_t *src, int srcW, + int xInc) + { + #if ARCH_X86 +@@ -2401,7 +2401,7 @@ + } + + static inline void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst, +- long dstWidth, const uint8_t *src1, ++ x86_reg dstWidth, const uint8_t *src1, + const uint8_t *src2, int srcW, int xInc) + { + #if ARCH_X86 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 35da65131..67d2742ff 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 @@ -527,7 +527,7 @@ JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_ ret = sws_scale ( (struct SwsContext *) context, - (uint8_t **) srcPicture->data, (int *) srcPicture->linesize, + (const uint8_t * const *) srcPicture->data, (int *) srcPicture->linesize, (int) srcSliceY, (int) srcSliceH, (uint8_t **) dstPicture.data, (int *) dstPicture.linesize); diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java b/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java index 29ad44b35..fb6bc4d53 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaUtils.java @@ -158,7 +158,10 @@ public class MediaUtils = new HashMap(); h264FormatParams.put("packetization-mode", "1"); - h264AdvancedAttributes.put("rtcp-fb", "nack pli"); + /* disable PLI since we use periodic intra-refresh feature + * of ffmpeg/x264 + */ + //h264AdvancedAttributes.put("rtcp-fb", "nack pli"); ScreenDevice screen = NeomediaActivator.getMediaServiceImpl(). getDefaultScreenDevice(); diff --git a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java index 8c0e9471c..b936b7d9f 100644 --- a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java @@ -284,7 +284,7 @@ protected void configureDataOutputStream( { super.configureDataOutputStream(dataOutputStream); - dataOutputStream.setMaxPacketsPerMillis(1, 10); + dataOutputStream.setMaxPacketsPerMillis(-1, 10); } /** diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIEncoder.java b/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIEncoder.java index 26c8fa37a..27c4e5238 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIEncoder.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/JNIEncoder.java @@ -35,9 +35,9 @@ public class JNIEncoder = { new VideoFormat(Constants.H264) }; /** - * Key frame every 300 frames. + * Key frame every 45 frames. */ - private static final int IFRAME_INTERVAL = 300; + private static final int IFRAME_INTERVAL = 45; /** * Padding size. @@ -91,8 +91,19 @@ public class JNIEncoder /** * Force encoder to send a key frame. + * First frame have to be a keyframe. */ - private boolean forceKeyFrame = false; + private boolean forceKeyFrame = true; + + /** + * Peer that receive stream from latest ffmpeg/x264 aware peer does not + * manage to decode the first keyframe and must wait for the next periodic + * intra refresh to display the video to the user. + * + * Temporary solution for this probolem: send the two first frames as + * keyframe to display video stream. + */ + private boolean secondKeyFrame = true; /** * Last keyframe request time. @@ -233,7 +244,7 @@ public synchronized void open() FFmpeg.avcodeccontext_set_bit_rate(avcontext, _bitRate); // so to be 1 in x264 FFmpeg.avcodeccontext_set_bit_rate_tolerance(avcontext, _bitRate); - FFmpeg.avcodeccontext_set_rc_max_rate(avcontext, _bitRate); + //FFmpeg.avcodeccontext_set_rc_max_rate(avcontext, 0); FFmpeg.avcodeccontext_set_sample_aspect_ratio(avcontext, 0, 0); FFmpeg.avcodeccontext_set_thread_count(avcontext, 1); // time_base should be 1 / frame rate @@ -265,7 +276,7 @@ public synchronized void open() FFmpeg.avcodeccontext_set_gop_size(avcontext, IFRAME_INTERVAL); FFmpeg.avcodeccontext_set_i_quant_factor(avcontext, 1f / 1.4f); - FFmpeg.avcodeccontext_set_refs(avcontext, 4); + FFmpeg.avcodeccontext_set_refs(avcontext, 1); FFmpeg.avcodeccontext_set_trellis(avcontext, 2); /* @@ -343,11 +354,21 @@ public synchronized int process(Buffer inBuffer, Buffer outBuffer) (byte[]) inBuffer.getData(), inBuffer.getOffset(), encFrameLen); - if (framesSinceLastIFrame >= IFRAME_INTERVAL || forceKeyFrame) + if (/* framesSinceLastIFrame >= IFRAME_INTERVAL || */ forceKeyFrame) { FFmpeg.avframe_set_key_frame(avframe, true); framesSinceLastIFrame = 0; - forceKeyFrame = false; + + /* send keyframe for the first two frames */ + if(secondKeyFrame) + { + secondKeyFrame = false; + forceKeyFrame = true; + } + else + { + forceKeyFrame = false; + } } else { @@ -518,7 +539,8 @@ public void feedbackReceived(RTCPFeedbackEvent event) + PLI_INTERVAL) { lastKeyframeRequestTime = System.currentTimeMillis(); - forceKeyFrame = true; + /* disable PLI */ + //forceKeyFrame = true; } break; default: