diff --git a/build.xml b/build.xml index 3a0154407..873c816bd 100644 --- a/build.xml +++ b/build.xml @@ -907,6 +907,11 @@ + + + + + @@ -1343,7 +1359,7 @@ javax.swing.event, javax.swing.border"/> prefix="net/java/sip/communicator/plugin/sipaccregwizz"/> - + FU-A */ + tmp[0] |= nri; + tmp[1] = buf[bufOfset]; + tmp[1] |= 1 << 7; + bufOfset += 1; + size -= 1; + int currentSIx = 0; + while (size + 2 > MAX_PAYLOAD_SIZE) + { + System.arraycopy(buf, bufOfset, tmp, 2, MAX_PAYLOAD_SIZE - 2); + + nals.add(currentSIx++, tmp.clone()); + + bufOfset += MAX_PAYLOAD_SIZE - 2; + size -= MAX_PAYLOAD_SIZE - 2; + tmp[1] &= ~(1 << 7); + } + + byte[] tmp2 = new byte[size + 2]; + tmp2[0] = tmp[0]; + tmp2[1] = tmp[1]; + tmp2[1] |= 1 << 6; + System.arraycopy(buf, bufOfset, tmp2, 2, size); + nals.add(currentSIx++, tmp2); + + return INPUT_BUFFER_NOT_CONSUMED | OUTPUT_BUFFER_NOT_FILLED; + } + + // size is ok lets send it + outBuffer.setData(buf); + outBuffer.setLength(buf.length); + outBuffer.setOffset(0); + outBuffer.setTimeStamp(lastTimeStamp); + outBuffer.setSequenceNumber(seq++); + + // if more nals exist process them + if(nals.size() > 0) + { + return BUFFER_PROCESSED_OK | INPUT_BUFFER_NOT_CONSUMED; + } + else + { + // its the last one from current frame, mark it + outBuffer.setFlags(outBuffer.getFlags() | Buffer.FLAG_RTP_MARKER); + return BUFFER_PROCESSED_OK; + } + } + + if (isEOM(inBuffer)) + { + propagateEOM(outBuffer); + reset(); + return BUFFER_PROCESSED_OK; + } + + if (inBuffer.isDiscard()) + { + outBuffer.setDiscard(true); + reset(); + return BUFFER_PROCESSED_OK; + } + + Format inFormat = inBuffer.getFormat(); + if (inFormat != inputFormat && !(inFormat.matches(inputFormat))) + { + setInputFormat(inFormat); + } + + if (inBuffer.getLength() < 10) + { + outBuffer.setDiscard(true); + reset(); + return BUFFER_PROCESSED_OK; + } + + // copy data to avpicture + rawFrameBuffer.write(0, + (byte[])inBuffer.getData(), inBuffer.getOffset(), encFrameLen); + + // encode data + int encLen = + AVCODEC.avcodec_encode_video( + avcontext, encFrameBuffer, encFrameLen, avpicture); + + byte[] r = encFrameBuffer.getByteArray(0, encLen); + + // split encoded data to nals + // we know it starts with 00 00 01 + int ix = 3; + int prevIx = 1; + while((ix = ff_avc_find_startcode(r, ix, r.length)) < r.length) + { + int len = ix - prevIx; + byte[] b = new byte[len -4]; + System.arraycopy(r, prevIx+ 3, b, 0, len-4); + nals.add(b); + + prevIx = ix; + ix = prevIx + 3; + } + + int len = ix - prevIx; + byte[] b = new byte[len - 3]; + System.arraycopy(r, prevIx+ 3, b, 0, len-3); + nals.add(b); + + lastTimeStamp = inBuffer.getTimeStamp(); + + return INPUT_BUFFER_NOT_CONSUMED | OUTPUT_BUFFER_NOT_FILLED; + } + + /** + * Find a NAL in the encoded data. + * @param buff the encoded data + * @param startIx starting index + * @param endIx end index + * @return starting position of the NAL + */ + private int ff_avc_find_startcode(byte[] buff, int startIx, int endIx) + { + while(startIx < (endIx - 3)) + { + if(buff[startIx] == 0 && + buff[startIx + 1] == 0 && + buff[startIx + 2] == 1) + return startIx; + + startIx++; + } + return endIx; + } + + public synchronized void open() throws ResourceUnavailableException + { + if (!opened) + { + super.open(); + + if (inputFormat == null) + throw new ResourceUnavailableException( + "No input format selected"); + if (outputFormat == null) + throw new ResourceUnavailableException( + "No output format selected"); + + AVCODEC.avcodec_init(); + + avcodec = AVCODEC.avcodec_find_encoder(AVCodecLibrary.CODEC_ID_H264); + avcontext = AVCODEC.avcodec_alloc_context(); + avpicture = AVCODEC.avcodec_alloc_frame(); + + avcontext.pix_fmt = AVFormatLibrary.PIX_FMT_YUV420P; + avcontext.width = DEF_WIDTH; + avcontext.height = DEF_HEIGHT; + + avcontext.time_base = new FFMPEGLibrary.AVRational(1, TARGET_FRAME_RATE); + + avpicture.linesize[0] = DEF_WIDTH; + avpicture.linesize[1] = DEF_WIDTH / 2; + avpicture.linesize[2] = DEF_WIDTH / 2; + //avpicture.quality = (int)10; + + avcontext.qcompress = 1; + + //int _bitRate = 267000; + //avcontext.bit_rate = (_bitRate * 3) >> 2; // average bit rate + + AVUTIL.av_log_set_callback(new AVUtilLibrary.LogCallback(){ + + public void callback(Pointer p, int l, String fmtS, + Pointer va_list) + { + logger.info("encoder: " + fmtS); + }}); + + if (AVCODEC.avcodec_open(avcontext, avcodec) < 0) + throw new RuntimeException("Could not open codec "); + + opened = true; + + encFrameLen = (DEF_WIDTH * DEF_HEIGHT * 3) / 2; + + rawFrameBuffer = AVUTIL.av_malloc(encFrameLen); + encFrameBuffer = AVUTIL.av_malloc(encFrameLen); + + int size = DEF_WIDTH * DEF_HEIGHT; + avpicture.data0 = rawFrameBuffer; + avpicture.data1 = avpicture.data0.share(size); + avpicture.data2 = avpicture.data1.share(size/4); + } + } + + public synchronized void close() + { + if (opened) + { + super.close(); + + AVCODEC.avcodec_close(avcontext); + + AVUTIL.av_free(avpicture.getPointer()); + AVUTIL.av_free(avcontext.getPointer()); + + AVUTIL.av_free(rawFrameBuffer); + AVUTIL.av_free(encFrameBuffer); + } + } + + public String getName() + { + return PLUGIN_NAME; + } + + public java.lang.Object[] getControls() + { + if (controls == null) + { + controls = + new Control[0]; + } + + return (Object[]) controls; + } +} diff --git a/src/net/java/sip/communicator/impl/media/device/JmfDeviceDetector.java b/src/net/java/sip/communicator/impl/media/device/JmfDeviceDetector.java index 0a4ab91b4..bb9a9f1e0 100644 --- a/src/net/java/sip/communicator/impl/media/device/JmfDeviceDetector.java +++ b/src/net/java/sip/communicator/impl/media/device/JmfDeviceDetector.java @@ -12,6 +12,7 @@ import java.io.*; import java.util.*; + import javax.media.*; import javax.media.format.*; @@ -174,7 +175,7 @@ private void detectCaptureDevices() //those that do not apply will silently fail. logger.info("Looking for video capture devices"); int nDevices = 0; - //Windows +/* //Windows try { VFWAuto vfwAuto = new VFWAuto(); @@ -231,19 +232,18 @@ private void detectCaptureDevices() { logger.debug("No V4l video detected: " + exc.getMessage()); } - +*/ //FMJ -// try -// { -// new FMJCivilVideoAuto(); -// } -// catch (Throwable exc) -// { -// logger.debug("No FMJ CIVIL video detected: " + exc.getMessage()); -// } - + try + { + new FMJCivilVideoAuto(); + } + catch (Throwable exc) + { + logger.debug("No FMJ CIVIL video detected: " + exc.getMessage(), exc); + } } /** diff --git a/src/net/java/sip/communicator/impl/media/media.manifest.mf b/src/net/java/sip/communicator/impl/media/media.manifest.mf index 5a85efe24..7f195c9bb 100644 --- a/src/net/java/sip/communicator/impl/media/media.manifest.mf +++ b/src/net/java/sip/communicator/impl/media/media.manifest.mf @@ -19,6 +19,11 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.resources, javax.sound, javax.sound.sampled, + quicktime, + quicktime.std.sg, + quicktime.qd, + quicktime.util, + quicktime.std.image, javax.crypto, javax.crypto.spec, javax.crypto.interfaces,