diff --git a/lib/os-specific/linux/installer-exclude/jmf.jar b/lib/os-specific/linux/installer-exclude/jmf.jar index 2d1c303a2..f555c5b39 100644 Binary files a/lib/os-specific/linux/installer-exclude/jmf.jar and b/lib/os-specific/linux/installer-exclude/jmf.jar differ diff --git a/lib/os-specific/mac/installer-exclude/jmf.jar b/lib/os-specific/mac/installer-exclude/jmf.jar index 06069045b..3e3c185f5 100644 Binary files a/lib/os-specific/mac/installer-exclude/jmf.jar and b/lib/os-specific/mac/installer-exclude/jmf.jar differ diff --git a/lib/os-specific/solaris/installer-exclude/jmf.jar b/lib/os-specific/solaris/installer-exclude/jmf.jar index 6238a974a..efbf35c2d 100644 Binary files a/lib/os-specific/solaris/installer-exclude/jmf.jar and b/lib/os-specific/solaris/installer-exclude/jmf.jar differ diff --git a/lib/os-specific/windows/installer-exclude/jmf.jar b/lib/os-specific/windows/installer-exclude/jmf.jar index c139ca3bc..bb5014ab4 100644 Binary files a/lib/os-specific/windows/installer-exclude/jmf.jar and b/lib/os-specific/windows/installer-exclude/jmf.jar differ diff --git a/src/net/java/sip/communicator/impl/media/codec/video/h264/H264Parser.java b/src/net/java/sip/communicator/impl/media/codec/video/h264/H264Parser.java index c7682c569..be5dd1634 100644 --- a/src/net/java/sip/communicator/impl/media/codec/video/h264/H264Parser.java +++ b/src/net/java/sip/communicator/impl/media/codec/video/h264/H264Parser.java @@ -45,8 +45,7 @@ public boolean pushRTPInput(Buffer inputBuffer) // if the timestamp changes we are starting receiving a new frame if(!(currentStamp == lastTimestamp)) { - encodedFrame = new byte[MAX_FRAME_SIZE]; - encodedFrameLen = 0; + reset(); } // the new frame timestamp lastTimestamp = currentStamp; @@ -83,7 +82,8 @@ else if (type == 28) catch(Exception ex) { logger.warn("Cannot parse incoming " + ex.getMessage()); - return true; + reset(); + return false; } if(hasMarker) @@ -162,4 +162,10 @@ public int getEncodedFrameLen() { return encodedFrameLen; } + + void reset() + { + encodedFrame = new byte[MAX_FRAME_SIZE]; + encodedFrameLen = 0; + } } diff --git a/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeDecoder.java b/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeDecoder.java index d6fb25bc5..3e0a139a1 100644 --- a/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeDecoder.java +++ b/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeDecoder.java @@ -157,7 +157,7 @@ public Format setInputFormat(Format format) else return null; } - + @Override public Format setOutputFormat(Format format) { @@ -203,15 +203,20 @@ public void close() if (opened) { opened = false; - super.close(); + synchronized (AVCODEC) + { + super.close(); - AVCODEC.avcodec_close(avcontext); + AVCODEC.avcodec_close(avcontext); - AVUTIL.av_free(avpicture.getPointer()); - AVUTIL.av_free(avcontext.getPointer()); + AVUTIL.av_free(avpicture.getPointer()); + AVUTIL.av_free(avcontext.getPointer()); + } } } + long lastReceivedSeq = -1; + public int process(Buffer inputBuffer, Buffer outputBuffer) { if (!checkInputBuffer(inputBuffer)) @@ -225,65 +230,88 @@ public int process(Buffer inputBuffer, Buffer outputBuffer) return BUFFER_PROCESSED_OK; } - if(!parser.pushRTPInput(inputBuffer)) + if (inputBuffer.isDiscard()) + { + inputBuffer.setDiscard(true); + reset(); + return BUFFER_PROCESSED_OK; + } + + if(lastReceivedSeq != -1 && inputBuffer.getSequenceNumber() - lastReceivedSeq > 1) + { + lastReceivedSeq = inputBuffer.getSequenceNumber(); + + parser.reset(); + inputBuffer.setDiscard(true); + outputBuffer.setDiscard(true); + reset(); + return BUFFER_PROCESSED_OK; + } + else if(!parser.pushRTPInput(inputBuffer)) { + lastReceivedSeq = inputBuffer.getSequenceNumber(); return OUTPUT_BUFFER_NOT_FILLED; } + lastReceivedSeq = inputBuffer.getSequenceNumber(); + // fills the incoming data IntByReference got_picture = new IntByReference(); Pointer encBuf = AVUTIL.av_malloc(parser.getEncodedFrameLen()); arraycopy(parser.getEncodedFrame(), 0, encBuf, 0, parser.getEncodedFrameLen()); - // decodes the data - AVCODEC.avcodec_decode_video( - avcontext, avpicture, got_picture, encBuf, parser.getEncodedFrameLen()); - - if(currentVideoWidth != avcontext.width) + synchronized (AVCODEC) { - currentVideoWidth = avcontext.width; - VideoFormat format = getVideoFormat(currentVideoWidth); - if(format != null) + // decodes the data + AVCODEC.avcodec_decode_video( + avcontext, avpicture, got_picture, encBuf, parser.getEncodedFrameLen()); + + if(currentVideoWidth != avcontext.width) { - outputBuffer.setFormat(format); - outputFormat = format; + currentVideoWidth = avcontext.width; + VideoFormat format = getVideoFormat(currentVideoWidth); + if(format != null) + { + outputBuffer.setFormat(format); + outputFormat = format; + } } - } - if(got_picture.getValue() == 0) - { - outputBuffer.setDiscard(true); - AVUTIL.av_free(encBuf); + if(got_picture.getValue() == 0) + { + outputBuffer.setDiscard(true); + AVUTIL.av_free(encBuf); - return BUFFER_PROCESSED_OK; - } - - // convert the picture in RGB Format - int numBytes = AVCODEC.avpicture_get_size( - AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height); - Pointer buffer = AVUTIL.av_malloc(numBytes); + return BUFFER_PROCESSED_OK; + } - AVCODEC.avpicture_fill( - frameRGB, buffer, AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height); + // convert the picture in RGB Format + int numBytes = AVCODEC.avpicture_get_size( + AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height); + Pointer buffer = AVUTIL.av_malloc(numBytes); - // Convert the image from its native format to RGB - AVCODEC.img_convert(frameRGB, AVCodecLibrary.PIX_FMT_RGB32, - avpicture, avcontext.pix_fmt, avcontext.width, - avcontext.height); + AVCODEC.avpicture_fill( + frameRGB, buffer, AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height); - int[] data = - frameRGB.data0.getIntArray(0, avcontext.height * avcontext.width); - int[] outData = validateIntArraySize(outputBuffer, data.length); - System.arraycopy(data, 0, outData, 0, data.length); + // Convert the image from its native format to RGB + AVCODEC.img_convert(frameRGB, AVCodecLibrary.PIX_FMT_RGB32, + avpicture, avcontext.pix_fmt, avcontext.width, + avcontext.height); - outputBuffer.setOffset(0); - outputBuffer.setLength(outData.length); - outputBuffer.setData(outData); + int[] data = + frameRGB.data0.getIntArray(0, avcontext.height * avcontext.width); + int[] outData = validateIntArraySize(outputBuffer, data.length); + System.arraycopy(data, 0, outData, 0, data.length); - AVUTIL.av_free(encBuf); - AVUTIL.av_free(buffer); + outputBuffer.setOffset(0); + outputBuffer.setLength(outData.length); + outputBuffer.setData(outData); - return BUFFER_PROCESSED_OK; + AVUTIL.av_free(encBuf); + AVUTIL.av_free(buffer); + + return BUFFER_PROCESSED_OK; + } } /** diff --git a/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeEncoder.java b/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeEncoder.java index 270d48fcb..55186779e 100644 --- a/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeEncoder.java +++ b/src/net/java/sip/communicator/impl/media/codec/video/h264/NativeEncoder.java @@ -218,33 +218,36 @@ public int process(Buffer inBuffer, Buffer outBuffer) return BUFFER_PROCESSED_OK; } - // copy data to avpicture - rawFrameBuffer.write(0, - (byte[])inBuffer.getData(), inBuffer.getOffset(), encFrameLen); - - if(framesSinceLastIFrame >= IFRAME_INTERVAL ) - { - avpicture.key_frame = 1; - framesSinceLastIFrame = 0; - } - else + synchronized (AVCODEC) { - framesSinceLastIFrame++; - avpicture.key_frame = 0; + // copy data to avpicture + rawFrameBuffer.write(0, + (byte[])inBuffer.getData(), inBuffer.getOffset(), encFrameLen); + + if(framesSinceLastIFrame >= IFRAME_INTERVAL ) + { + avpicture.key_frame = 1; + framesSinceLastIFrame = 0; + } + else + { + framesSinceLastIFrame++; + avpicture.key_frame = 0; + } + + // encode data + int encLen = + AVCODEC.avcodec_encode_video( + avcontext, encFrameBuffer, encFrameLen, avpicture); + + byte[] r = encFrameBuffer.getByteArray(0, encLen); + + outBuffer.setData(r); + outBuffer.setLength(r.length); + outBuffer.setOffset(0); + + return BUFFER_PROCESSED_OK; } - - // encode data - int encLen = - AVCODEC.avcodec_encode_video( - avcontext, encFrameBuffer, encFrameLen, avpicture); - - byte[] r = encFrameBuffer.getByteArray(0, encLen); - - outBuffer.setData(r); - outBuffer.setLength(r.length); - outBuffer.setOffset(0); - - return BUFFER_PROCESSED_OK; } public synchronized void open() throws ResourceUnavailableException @@ -281,7 +284,7 @@ public synchronized void open() throws ResourceUnavailableException avcontext.qcompress = 1; - int _bitRate = 48000; + int _bitRate = 9600; avcontext.bit_rate = _bitRate; // average bit rate avcontext.bit_rate_tolerance = _bitRate;// so to be 1 in x264 avcontext.rc_max_rate = _bitRate; @@ -291,7 +294,7 @@ public synchronized void open() throws ResourceUnavailableException avcontext.time_base.den = 15;//25500; //??? avcontext.time_base.num = 1000; avcontext.qmin = 10; - avcontext.qmax = 22; + avcontext.qmax = 18; avcontext.max_qdiff = 4; avcontext.partitions |= 0x111; @@ -346,15 +349,18 @@ public synchronized void close() if (opened) { opened = false; - super.close(); + synchronized (AVCODEC) + { + super.close(); - AVCODEC.avcodec_close(avcontext); + AVCODEC.avcodec_close(avcontext); - AVUTIL.av_free(avpicture.getPointer()); - AVUTIL.av_free(avcontext.getPointer()); + AVUTIL.av_free(avpicture.getPointer()); + AVUTIL.av_free(avcontext.getPointer()); - AVUTIL.av_free(rawFrameBuffer); - AVUTIL.av_free(encFrameBuffer); + AVUTIL.av_free(rawFrameBuffer); + AVUTIL.av_free(encFrameBuffer); + } } }