package org.red5.app.sip.codecs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zoolu.sdp.AttributeField; import org.zoolu.sdp.SessionDescriptor; /** * A utility class for determine, instantiate and configure SIP codec, * based on payload, local and remote SDP packets */ public class CodecUtils { protected static Logger log = LoggerFactory.getLogger( CodecUtils.class ); public static Codec initSipAudioCodec( Codec audioCodec, int defaultEncodePacketization, int defaultDecodePacketization, SessionDescriptor localSDP, SessionDescriptor remoteSDP ) { AttributeField remotePtimeAttribute = remoteSDP.getMediaDescriptor( Codec.MEDIA_TYPE_AUDIO ). getAttribute( Codec.ATTRIBUTE_PTIME ); if ( remotePtimeAttribute != null ) { audioCodec.setRemotePtime( Integer.valueOf( remotePtimeAttribute.getAttributeValue() ) ); } AttributeField localPtimeAttribute = localSDP.getMediaDescriptor( Codec.MEDIA_TYPE_AUDIO ). getAttribute( Codec.ATTRIBUTE_PTIME ); if ( localPtimeAttribute != null ) { audioCodec.setLocalPtime(Integer.valueOf( localPtimeAttribute.getAttributeValue() ) ); } printLog( "initSipAudioCodec", "Codec id = [" + audioCodec.getCodecId() + "], codec name = [" + audioCodec.getCodecName() + "], sampleRate = [" + audioCodec.getSampleRate() + "], incomingEndodedFrameSize = [" + audioCodec.getIncomingEncodedFrameSize() + "], incomingDedodedFrameSize = [" + audioCodec.getIncomingDecodedFrameSize() + "], incomingPacketization = [" + audioCodec.getIncomingPacketization() + "], outgoingEndodedFrameSize = [" + audioCodec.getOutgoingEncodedFrameSize() + "], outgoingDedodedFrameSize = [" + audioCodec.getOutgoingDecodedFrameSize() + "], outgoingPacketization = [" + audioCodec.getOutgoingPacketization() + "]." ); // Initialize encode and decode codec. audioCodec.encodeInit( defaultEncodePacketization ); audioCodec.decodeInit( defaultDecodePacketization ); return audioCodec; } /** * Converts a byte array into a short array. Since a byte is 8-bits, * and a short is 16-bits, the returned short array will be half in * length than the byte array. If the length of the byte array is odd, * the length of the short array will be * <code>(byteArray.length - 1)/2</code>, i.e., the last byte is * discarded. * * @param byteArray a byte array * @param offset which byte to start from * @param length how many bytes to convert * @param little specifies whether the result should be using little endian * order or not. * * @return a short array, or <code>null</code> if byteArray is of zero * length * * @throws java.lang.ArrayIndexOutOfBoundsException * @author Damian Minkov */ public static short[] byteToShortArray (byte[] byteArray, int offset, int length, boolean little) throws ArrayIndexOutOfBoundsException { if (0 < length && (offset + length) <= byteArray.length) { int shortLength = length / 2; short[] shortArray = new short[shortLength]; int temp; for (int i = offset, j = 0; j < shortLength; j++, temp = 0x00000000) { if(little) { temp = byteArray[i++] & 0x000000FF; temp |= 0x0000FF00 & (byteArray[i++] << 8); } else { temp = byteArray[i++] << 8; temp |= 0x000000FF & byteArray[i++]; } shortArray[j] = (short) temp; } return shortArray; } else { throw new ArrayIndexOutOfBoundsException ("offset: " + offset + ", length: " + length + ", array length: " + byteArray.length); } } /** * The result array must be twice as the input one. Since a byte is 8-bits, * and a short is 16-bits. * @param in the short[] array that we'll be transforming. * @param res the byte[] arrays where we'll be setting the converted short * values. * @param little specifies whether the result should be using little endian * order or not. * @author Damian Minkov */ public static void shortArrToByteArr(short[] in, byte[] res, boolean little) { int resIx = 0; byte[] tmp = null; for (int i = 0; i < in.length; i++) { tmp = shortToBytes(in[i], little); res[resIx++] = tmp[0]; res[resIx++] = tmp[1]; } } /** * Get a pair of bytes representing a short value. * @param v the short value to convert. * @param little specifies whether the result should be using little endian * order or no. * @return a byte[] array containing the result. * @author Damian Minkov */ public static byte[] shortToBytes(short v, boolean little) { byte[] rtn = new byte[2]; if (little) { rtn[0] = (byte) (v & 0xff); rtn[1] = (byte) ( (v >>> 8) & 0xff); } else { rtn[0] = (byte) ( (v >>> 8) & 0xff); rtn[1] = (byte) (v & 0xff); } return rtn; } private static void printLog( String method, String message ) { log.debug( "SIPCodecUtils - " + method + " -> " + message ); System.out.println( "SIPCodecUtils - " + method + " -> " + message ); } }