diff --git a/src/org/jitsi/impl/neomedia/MediaUtils.java b/src/org/jitsi/impl/neomedia/MediaUtils.java index 32dba0be5ec2622009fb9a42fff14ced5b9dcb65..699e16668dd47f430aa491ff245966780ed2444a 100644 --- a/src/org/jitsi/impl/neomedia/MediaUtils.java +++ b/src/org/jitsi/impl/neomedia/MediaUtils.java @@ -361,17 +361,17 @@ public class MediaUtils { AudioMediaFormatImpl audioMediaFormat = (AudioMediaFormatImpl) mediaFormat; + String encoding = audioMediaFormat.getEncoding(); int channels = audioMediaFormat.getChannels(); - /* - * The opus/rtp format has 2 channels, but we don't want it to - * trigger use of 2 channels elsewhere. - */ - if ("opus".equals(audioMediaFormat.getEncoding())) - channels = 1; double sampleRate = audioMediaFormat.getClockRate(); int sampleSizeInBits = audioMediaFormat.getFormat().getSampleSizeInBits(); + // The opus/rtp format has 2 channels, but we don't want it to + // trigger use of stereo elsewhere. + if (Constants.OPUS.equalsIgnoreCase(encoding)) + channels = 1; + if (maxAudioChannels < channels) maxAudioChannels = channels; if (maxAudioSampleRate < sampleRate) @@ -419,47 +419,6 @@ private static void addMediaFormats( clockRates); } - /** - * Adds a new mapping of a specific RTP payload type to a list of - * <tt>MediaFormat</tt>s of a specific <tt>MediaType</tt>, with a specific - * JMF encoding and, optionally, with specific clock rates. - * - * @param rtpPayloadType the RTP payload type to be associated with a list - * of <tt>MediaFormat</tt>s - * @param encoding the well-known encoding (name) corresponding to - * <tt>rtpPayloadType</tt> (in contrast to the JMF-specific encoding - * specified by <tt>jmfEncoding</tt>) - * @param mediaType the <tt>MediaType</tt> of the <tt>MediaFormat</tt>s to - * be associated with <tt>rtpPayloadType</tt> - * @param jmfEncoding the JMF encoding of the <tt>MediaFormat</tt>s to be - * associated with <tt>rtpPayloadType</tt> - * @param formatParameters the set of format-specific parameters of the - * <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt> - * @param advancedAttributes the set of advanced attributes of the - * <tt>MediaFormat</tt>s to be associated with <tt>rtpPayload</tt> - * @param clockRates the optional list of clock rates of the - * <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt> - */ - private static void addMediaFormats( - byte rtpPayloadType, - String encoding, - MediaType mediaType, - String jmfEncoding, - Map<String, String> formatParameters, - Map<String, String> advancedAttributes, - double... clockRates) - { - addMediaFormats( - rtpPayloadType, - encoding, - mediaType, - jmfEncoding, - 1 /* channel */, - formatParameters, - advancedAttributes, - clockRates); - } - /** * Adds a new mapping of a specific RTP payload type to a list of * <tt>MediaFormat</tt>s of a specific <tt>MediaType</tt>, with a specific @@ -587,6 +546,47 @@ private static void addMediaFormats( } } + /** + * Adds a new mapping of a specific RTP payload type to a list of + * <tt>MediaFormat</tt>s of a specific <tt>MediaType</tt>, with a specific + * JMF encoding and, optionally, with specific clock rates. + * + * @param rtpPayloadType the RTP payload type to be associated with a list + * of <tt>MediaFormat</tt>s + * @param encoding the well-known encoding (name) corresponding to + * <tt>rtpPayloadType</tt> (in contrast to the JMF-specific encoding + * specified by <tt>jmfEncoding</tt>) + * @param mediaType the <tt>MediaType</tt> of the <tt>MediaFormat</tt>s to + * be associated with <tt>rtpPayloadType</tt> + * @param jmfEncoding the JMF encoding of the <tt>MediaFormat</tt>s to be + * associated with <tt>rtpPayloadType</tt> + * @param formatParameters the set of format-specific parameters of the + * <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt> + * @param advancedAttributes the set of advanced attributes of the + * <tt>MediaFormat</tt>s to be associated with <tt>rtpPayload</tt> + * @param clockRates the optional list of clock rates of the + * <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt> + */ + private static void addMediaFormats( + byte rtpPayloadType, + String encoding, + MediaType mediaType, + String jmfEncoding, + Map<String, String> formatParameters, + Map<String, String> advancedAttributes, + double... clockRates) + { + addMediaFormats( + rtpPayloadType, + encoding, + mediaType, + jmfEncoding, + 1 /* channel */, + formatParameters, + advancedAttributes, + clockRates); + } + /** * Creates value of an imgattr. * @@ -643,9 +643,7 @@ public static String createImageAttr( /* receive size */ if(maxRecvSize != null) { - /* basically we can receive any size up to our - * screen display size - */ + // basically we can receive any size up to our screen display size /* recv [x=[min-max],y=[min-max]] */ img.append(" recv [x=[0-"); @@ -772,7 +770,8 @@ public static int getMediaFormatIndex(MediaFormat mediaFormat) public static MediaFormat[] getMediaFormats(byte rtpPayloadType) { MediaFormat[] mediaFormats - = rtpPayloadTypeStrToMediaFormats.get(Byte.toString(rtpPayloadType)); + = rtpPayloadTypeStrToMediaFormats.get( + Byte.toString(rtpPayloadType)); return (mediaFormats == null) @@ -911,7 +910,6 @@ else if (jmfEncoding.equals(VideoFormat.H261_RTP)) return MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN; } - /** * Gets the well-known encoding (name) as defined in RFC 3551 "RTP Profile * for Audio and Video Conferences with Minimal Control" corresponding to a diff --git a/src/org/jitsi/impl/neomedia/codec/FFmpeg.java b/src/org/jitsi/impl/neomedia/codec/FFmpeg.java index 77075db0e347a87c072464e8490c09675833a459..2bfb2b78b60e5b09b8af3d4f209c432d7cebf825 100644 --- a/src/org/jitsi/impl/neomedia/codec/FFmpeg.java +++ b/src/org/jitsi/impl/neomedia/codec/FFmpeg.java @@ -332,10 +332,10 @@ public static native int avcodec_encode_video(long ctx, byte[] buff, int buf_size, long frame); /** - * Find a registered decoder with a matching ID. + * Finds a registered decoder with a matching ID. * - * @param id <tt>CodecID</tt> of the requested encoder - * @return an <tt>AVCodec</tt> encoder if one was found; <tt>0</tt>, + * @param id <tt>AVCodecID</tt> of the requested encoder + * @return an <tt>AVCodec</tt> decoder if one was found; <tt>0</tt>, * otherwise */ public static native long avcodec_find_decoder(int id); @@ -343,7 +343,7 @@ public static native int avcodec_encode_video(long ctx, byte[] buff, /** * Finds a registered encoder with a matching codec ID. * - * @param id <tt>CodecID</tt> of the requested encoder + * @param id <tt>AVCodecID</tt> of the requested encoder * @return an <tt>AVCodec</tt> encoder if one was found; <tt>0</tt>, * otherwise */ diff --git a/src/org/jitsi/impl/neomedia/codec/audio/ilbc/JavaEncoder.java b/src/org/jitsi/impl/neomedia/codec/audio/ilbc/JavaEncoder.java index 9b2364a20237ed6323c1ebd49bc75c28fff70965..71f5ce5ec0d79057bc200b31ea1ac8a312d05f44 100644 --- a/src/org/jitsi/impl/neomedia/codec/audio/ilbc/JavaEncoder.java +++ b/src/org/jitsi/impl/neomedia/codec/audio/ilbc/JavaEncoder.java @@ -26,6 +26,11 @@ public class JavaEncoder extends AbstractCodec2 implements FormatParametersAwareCodec { + /** + * The duration an output <tt>Buffer</tt> produced by this <tt>Codec</tt>. + */ + private int duration = 0; + /** * The <tt>ilbc_encoder</tt> adapted to <tt>Codec</tt> by this instance. */ @@ -34,29 +39,23 @@ public class JavaEncoder /** * The input length in bytes with which {@link #enc} has been initialized. */ - private int inputLength; + private int inLen; /** * The output length in bytes with which {@link #enc} has been initialized. */ - private int outputLength; + private int outLen; /** * The input from previous calls to {@link #doProcess(Buffer, Buffer)} which * has not been consumed yet. */ - private byte[] prevInput; + private byte[] prevIn; /** - * The number of bytes in {@link #prevInput} which have not been consumed - * yet. + * The number of bytes in {@link #prevIn} which have not been consumed yet. */ - private int prevInputLength; - - /** - * The duration an output <tt>Buffer</tt> produced by this <tt>Codec</tt>. - */ - private int duration = 0; + private int prevInLen; /** * Initializes a new iLBC <tt>JavaEncoder</tt> instance. @@ -107,10 +106,10 @@ public JavaEncoder() protected void doClose() { enc = null; - outputLength = 0; - inputLength = 0; - prevInput = null; - prevInputLength = 0; + outLen = 0; + inLen = 0; + prevIn = null; + prevInLen = 0; duration = 0; } @@ -122,120 +121,51 @@ protected void doClose() @Override protected void doOpen() { - // if not already initialised, use the constant for default value (30) + // if not already initialised, use the default value (30). if(enc == null) initEncoder(Constants.ILBC_MODE); } - /** - * Init encoder with specified mode. - * @param mode the mode to use. - */ - private void initEncoder(int mode) - { - enc = new ilbc_encoder(mode); - - switch (mode) - { - case 20: - outputLength = ilbc_constants.NO_OF_BYTES_20MS; - break; - case 30: - outputLength = ilbc_constants.NO_OF_BYTES_30MS; - break; - default: - throw new IllegalStateException("mode"); - } - /* mode is 20 or 30 ms, duration must be in nanoseconds */ - duration = mode * 1000000; - inputLength = enc.ULP_inst.blockl * 2; - prevInput = new byte[inputLength]; - prevInputLength = 0; - } - - /** - * Get the output format. - * - * @return output format - * @see net.sf.fmj.media.AbstractCodec#getOutputFormat() - */ - @Override - public Format getOutputFormat() - { - Format outputFormat = super.getOutputFormat(); - - if ((outputFormat != null) - && (outputFormat.getClass() == AudioFormat.class)) - { - AudioFormat outputAudioFormat = (AudioFormat) outputFormat; - - outputFormat = setOutputFormat( - new AudioFormat( - outputAudioFormat.getEncoding(), - outputAudioFormat.getSampleRate(), - outputAudioFormat.getSampleSizeInBits(), - outputAudioFormat.getChannels(), - outputAudioFormat.getEndian(), - outputAudioFormat.getSigned(), - outputAudioFormat.getFrameSizeInBits(), - outputAudioFormat.getFrameRate(), - outputAudioFormat.getDataType()) - { - private static final long serialVersionUID = 0L; - - @Override - public long computeDuration(long length) - { - return JavaEncoder.this.duration; - } - }); - } - return outputFormat; - } - /** * Implements {@link AbstractCodec2#doProcess(Buffer, Buffer)}. * - * @param inputBuffer the input buffer - * @param outputBuffer the output buffer + * @param inBuffer the input buffer + * @param outBuffer the output buffer * @return the status of the processing, whether buffer is consumed/filled.. * @see AbstractCodec2#doProcess(Buffer, Buffer) */ @Override - protected int doProcess(Buffer inputBuffer, Buffer outputBuffer) + protected int doProcess(Buffer inBuffer, Buffer outBuffer) { - int inputLength = inputBuffer.getLength(); - byte[] input = (byte[]) inputBuffer.getData(); - int inputOffset = inputBuffer.getOffset(); + int inLen = inBuffer.getLength(); + byte[] in = (byte[]) inBuffer.getData(); + int inOff = inBuffer.getOffset(); - if ((prevInputLength != 0) || (inputLength < this.inputLength)) + if ((prevInLen != 0) || (inLen < this.inLen)) { - int bytesToCopy = this.inputLength - prevInputLength; - - if (bytesToCopy > inputLength) - bytesToCopy = inputLength; - System.arraycopy( - input, inputOffset, - prevInput, prevInputLength, - bytesToCopy); - prevInputLength += bytesToCopy; - - inputBuffer.setLength(inputLength - bytesToCopy); - inputBuffer.setOffset(inputOffset + bytesToCopy); - - inputLength = prevInputLength; - input = prevInput; - inputOffset = 0; + int bytesToCopy = this.inLen - prevInLen; + + if (bytesToCopy > inLen) + bytesToCopy = inLen; + System.arraycopy(in, inOff, prevIn, prevInLen, bytesToCopy); + prevInLen += bytesToCopy; + + inBuffer.setLength(inLen - bytesToCopy); + inBuffer.setOffset(inOff + bytesToCopy); + + inLen = prevInLen; + in = prevIn; + inOff = 0; } else { - inputBuffer.setLength(inputLength - this.inputLength); - inputBuffer.setOffset(inputOffset + this.inputLength); + inBuffer.setLength(inLen - this.inLen); + inBuffer.setOffset(inOff + this.inLen); } int ret; - if (inputLength >= this.inputLength) + if (inLen >= this.inLen) { /* * If we are about to encode from prevInput, we already have @@ -243,31 +173,102 @@ protected int doProcess(Buffer inputBuffer, Buffer outputBuffer) * the first place and we have to make sure that we will not use the * same prevInput more than once. */ - prevInputLength = 0; + prevInLen = 0; - int outputOffset = 0; - byte[] output - = validateByteArraySize( - outputBuffer, - outputOffset + outputLength, - true); + int outOff = 0; + byte[] out + = validateByteArraySize(outBuffer, outOff + outLen, true); - enc.encode(output, outputOffset, input, inputOffset); + enc.encode(out, outOff, in, inOff); - updateOutput( - outputBuffer, - getOutputFormat(), outputLength, outputOffset); - outputBuffer.setDuration(duration); + updateOutput(outBuffer, getOutputFormat(), outLen, outOff); + outBuffer.setDuration(duration); ret = BUFFER_PROCESSED_OK; } else + { ret = OUTPUT_BUFFER_NOT_FILLED; + } - if (inputBuffer.getLength() > 0) + if (inBuffer.getLength() > 0) ret |= INPUT_BUFFER_NOT_CONSUMED; return ret; } + /** + * Implements {@link javax.media.Control#getControlComponent()}. + */ + @Override + public Component getControlComponent() + { + return null; + } + + /** + * Get the output format. + * + * @return output format + * @see net.sf.fmj.media.AbstractCodec#getOutputFormat() + */ + @Override + @SuppressWarnings("serial") + public Format getOutputFormat() + { + Format f = super.getOutputFormat(); + + if ((f != null) && (f.getClass() == AudioFormat.class)) + { + AudioFormat af = (AudioFormat) f; + + f + = setOutputFormat( + new AudioFormat( + af.getEncoding(), + af.getSampleRate(), + af.getSampleSizeInBits(), + af.getChannels(), + af.getEndian(), + af.getSigned(), + af.getFrameSizeInBits(), + af.getFrameRate(), + af.getDataType()) + { + @Override + public long computeDuration(long length) + { + return JavaEncoder.this.duration; + } + }); + } + return f; + } + + /** + * Init encoder with specified mode. + * @param mode the mode to use. + */ + private void initEncoder(int mode) + { + enc = new ilbc_encoder(mode); + + switch (mode) + { + case 20: + outLen = ilbc_constants.NO_OF_BYTES_20MS; + break; + case 30: + outLen = ilbc_constants.NO_OF_BYTES_30MS; + break; + default: + throw new IllegalStateException("mode"); + } + /* mode is 20 or 30 ms, duration must be in nanoseconds */ + duration = mode * 1000000; + inLen = enc.ULP_inst.blockl * 2; + prevIn = new byte[inLen]; + prevInLen = 0; + } + /** * Sets the format parameters to <tt>fmtps</tt> * @@ -288,16 +289,9 @@ public void setFormatParameters(Map<String, String> fmtps) if(mode == 20 || mode == 30) initEncoder(mode); } - catch(Throwable t){} + catch(Throwable t) + { + } } } - - /** - * Implements {@link javax.media.Control#getControlComponent()}. - */ - @Override - public Component getControlComponent() - { - return null; - } }