Revision: 16681
Author: oleg.kulikoff
Date: Tue Jan 25 08:39:03 2011
Log: Issue 2293:SDP parsing worst time
http://code.google.com/p/mobicents/source/detail?r=16681
Added:
/trunk/servers/media/spi/src/test/java/org/mobicents/media/server/spi/format/AudioFormatTest.java
/trunk/servers/media/spi/src/test/java/org/mobicents/media/server/spi/format/VideoFormatTest.java
Modified:
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/AudioFormat.java
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/EncodingName.java
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/Format.java
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/VideoFormat.java
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/utils/Text.java
/trunk/servers/media/spi/src/test/java/org/mobicents/media/server/utils/TextTest.java
=======================================
--- /dev/null
+++
/trunk/servers/media/spi/src/test/java/org/mobicents/media/server/spi/format/AudioFormatTest.java
Tue Jan 25 08:39:03 2011
@@ -0,0 +1,70 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.mobicents.media.server.spi.format;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author kulikov
+ */
+public class AudioFormatTest {
+
+ public AudioFormatTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ /**
+ * Test of getSampleRate method, of class AudioFormat.
+ */
+ @Test
+ public void testCloneExecutionTime() {
+ AudioFormat f = new AudioFormat("pcmu", 8000, 8, 1);
+
+ long s = System.currentTimeMillis();
+ for (int i = 0; i < 1000; i++) {
+ f.clone();
+ }
+ long duration = System.currentTimeMillis() - s;
+ System.out.println("Execution time: " + duration);
+ assertTrue("To slow", 3000000L > duration);
+ }
+
+ @Test
+ public void testImmutable() {
+ AudioFormat f = new AudioFormat("pcmu", 8000, 8, 1);
+ AudioFormat fc = f.clone();
+
+ //changing encoding name of the clone, original name must remains
same
+ fc.setName(new EncodingName("pcma"));
+ assertEquals("pcmu", f.getName().toString());
+
+ //changing source and checking again
+ f.setName(new EncodingName("speex"));
+ assertEquals("pcma", fc.getName().toString());
+ }
+
+}
=======================================
--- /dev/null
+++
/trunk/servers/media/spi/src/test/java/org/mobicents/media/server/spi/format/VideoFormatTest.java
Tue Jan 25 08:39:03 2011
@@ -0,0 +1,68 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.mobicents.media.server.spi.format;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author kulikov
+ */
+public class VideoFormatTest {
+
+ public VideoFormatTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void testCloneExecutionTime() {
+ VideoFormat f = new VideoFormat("h261", 15);
+
+ long s = System.currentTimeMillis();
+ for (int i = 0; i < 1000; i++) {
+ f.clone();
+ }
+
+ long duration = System.currentTimeMillis() - s;
+ System.out.println("Execution time: " + duration);
+ assertTrue("To slow", 3000000L > duration);
+ }
+
+ @Test
+ public void testImmutable() {
+ VideoFormat f = new VideoFormat("h261", 15);
+ VideoFormat fc = f.clone();
+
+ //changing encoding name of the clone, original name must remains
same
+ fc.setName(new EncodingName("h263"));
+ assertEquals("h261", f.getName().toString());
+
+ //changing source and checking again
+ f.setName(new EncodingName("mp4v-es"));
+ assertEquals("h263", fc.getName().toString());
+ }
+
+}
=======================================
---
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/AudioFormat.java
Mon Jan 24 05:31:11 2011
+++
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/AudioFormat.java
Tue Jan 25 08:39:03 2011
@@ -23,11 +23,11 @@
*
* @author kulikov
*/
-public class AudioFormat extends Format {
+public class AudioFormat extends Format implements Cloneable {
//sampling frequency
private int sampleRate;
//bits per sample
- private int sampleSize;
+ private int sampleSize = -1;
//number of channels
private int channels = 1;
@@ -39,6 +39,47 @@
public AudioFormat(EncodingName name) {
super(name);
}
+
+ /**
+ * Creates new format descriptor
+ *
+ * @param name the encoding
+ * @param sampleRate sample rate value in Hertz
+ * @param sampleSize sample size in bits
+ * @param channels number of channels
+ */
+ public AudioFormat(EncodingName name, int sampleRate, int sampleSize,
int channels) {
+ super(name);
+ this.sampleRate = sampleRate;
+ this.sampleSize = sampleSize;
+ this.channels = channels;
+ }
+
+ /**
+ * Creates new format descriptor
+ *
+ * @param name the encoding
+ * @param sampleRate sample rate value in Hertz
+ * @param sampleSize sample size in bits
+ * @param channels number of channels
+ */
+ public AudioFormat(String name, int sampleRate, int sampleSize, int
channels) {
+ super(new EncodingName(name));
+ this.sampleRate = sampleRate;
+ this.sampleSize = sampleSize;
+ this.channels = channels;
+ }
+
+ /**
+ * Creates new format descriptor
+ *
+ * @param name the encoding
+ * @param sampleRate sample rate value in Hertz
+ */
+ public AudioFormat(String name, int sampleRate) {
+ super(new EncodingName(name));
+ this.sampleRate = sampleRate;
+ }
/**
* Gets the sampling rate.
@@ -96,4 +137,8 @@
this.channels = channels;
}
-}
+ @Override
+ protected AudioFormat clone() {
+ return new AudioFormat(getName(), sampleRate, sampleSize,
channels);
+ }
+}
=======================================
---
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/EncodingName.java
Mon Jan 24 05:31:11 2011
+++
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/EncodingName.java
Tue Jan 25 08:39:03 2011
@@ -29,7 +29,11 @@
public EncodingName() {
super();
}
-
+
+ public EncodingName(Text text) {
+ super(text);
+ }
+
public EncodingName(String s) {
super(s);
}
=======================================
---
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/Format.java
Mon Jan 24 05:31:11 2011
+++
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/Format.java
Tue Jan 25 08:39:03 2011
@@ -18,17 +18,19 @@
package org.mobicents.media.server.spi.format;
+import org.mobicents.media.server.utils.Text;
+
/**
* Media format descriptor.
*
* @author kulikov
*/
-public class Format {
+public class Format implements Cloneable {
//encoding name
private EncodingName name;
//any specific options
- private String options;
+ private Text options;
/**
* Creates new descriptor.
@@ -63,7 +65,7 @@
*
* @return options as text.
*/
- public String getOptions() {
+ public Text getOptions() {
return options;
}
@@ -72,7 +74,7 @@
*
* @param options new options.
*/
- public void setOptions(String options) {
+ public void setOptions(Text options) {
this.options = options;
}
=======================================
---
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/VideoFormat.java
Mon Jan 24 05:31:11 2011
+++
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/spi/format/VideoFormat.java
Tue Jan 25 08:39:03 2011
@@ -21,7 +21,7 @@
*
* @author kulikov
*/
-public class VideoFormat extends Format {
+public class VideoFormat extends Format implements Cloneable {
//number of frames per second
private int frameRate;
@@ -33,6 +33,37 @@
public VideoFormat(EncodingName name) {
super(name);
}
+
+ /**
+ * Creates new format descriptor.
+ *
+ * @param name format encoding name.
+ * @param frameRate the number of frames per second.
+ */
+ public VideoFormat(EncodingName name, int frameRate) {
+ super(name);
+ this.frameRate = frameRate;
+ }
+
+ /**
+ * Creates new format descriptor.
+ *
+ * @param name format encoding name.
+ */
+ public VideoFormat(String name) {
+ super(new EncodingName(name));
+ }
+
+ /**
+ * Creates new format descriptor.
+ *
+ * @param name format encoding name.
+ * @param frameRate the number of frames per second.
+ */
+ public VideoFormat(String name, int frameRate) {
+ super(new EncodingName(name));
+ this.frameRate = frameRate;
+ }
/**
* Gets the frame rate.
@@ -51,4 +82,10 @@
public void setFrameRate(int frameRate) {
this.frameRate = frameRate;
}
-}
+
+ @Override
+ protected VideoFormat clone() {
+ return new VideoFormat(getName(), frameRate);
+ }
+
+}
=======================================
---
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/utils/Text.java
Mon Jan 24 05:31:11 2011
+++
/trunk/servers/media/spi/src/main/java/org/mobicents/media/server/utils/Text.java
Tue Jan 25 08:39:03 2011
@@ -17,10 +17,12 @@
*/
package org.mobicents.media.server.utils;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
/**
- * Case insensitive character string representation.
+ * Case insensitive text block representation.
*
* This class provides time deterministic and fast methods for creating
* and comparing short character strings like format names, attribute
values, etc.
@@ -29,13 +31,16 @@
*/
public class Text implements CharSequence {
//reference on the local buffer
- private byte[] chars;
+ protected byte[] chars;
//the start position
- private int pos;
+ protected int pos;
//the length of the string
- private int len;
+ protected int len;
+
+ /** points to the line separator */
+ private int linePointer;
/**
* Create an empty text object.
@@ -45,6 +50,17 @@
public Text() {
}
+ /**
+ * Creates new object with specified text.
+ *
+ * @param another the text object.
+ */
+ protected Text(Text another) {
+ this.chars = another.chars;
+ this.pos = another.pos;
+ this.len = another.len;
+ }
+
/**
* Creates new instance with specified text.
*
@@ -94,7 +110,7 @@
* @see java.lang.CharSequence#charAt(int)
*/
public char charAt(int index) {
- return (char) chars[index];
+ return (char) chars[pos + index];
}
/**
@@ -104,6 +120,78 @@
public CharSequence subSequence(int start, int end) {
return new Text(chars, start, end - start);
}
+
+ /**
+ * Splits text into partitions.
+ *
+ * @param separator character used for partitioning
+ * @return array of text strings.
+ */
+ public Collection<Text> split(char separator) {
+ int pointer = pos;
+ int limit = pos + len;
+ int mark = pointer;
+
+ ArrayList<Text> tokens = new ArrayList();
+ while (pointer < limit) {
+ if (chars[pointer] == separator) {
+ tokens.add(new Text(chars, mark, pointer - mark));
+ mark = pointer + 1;
+ }
+ pointer++;
+ }
+
+ tokens.add(new Text(chars, mark, limit - mark));
+ return tokens;
+ }
+
+ /**
+ * Removes whitespaces from the head and tail of the string.
+ *
+ */
+ public void trim() {
+ //cut white spaces from the head
+ while (chars[pos] == ' ') {
+ pos++;
+ len--;
+ }
+
+ //cut from the end
+ while (chars[pos + len - 1] == ' ') {
+ len--;
+ }
+ }
+
+ /**
+ * Extracts next line from this text.
+ *
+ * @return
+ */
+ public Text nextLine() {
+ if (linePointer == 0) {
+ linePointer = pos;
+ } else {
+ linePointer++;
+ }
+
+ int mark = linePointer;
+ int limit = pos + len;
+
+ while (linePointer < limit && chars[linePointer] != '\n') {
+ linePointer++;
+ }
+
+ return new Text(chars, mark, linePointer - mark);
+ }
+
+ /**
+ * Shows is this text contains more lines.
+ *
+ * @return true if there are more lines
+ */
+ public boolean hasMoreLines() {
+ return linePointer < pos + len;
+ }
@Override
public boolean equals(Object other) {
@@ -116,7 +204,11 @@
}
Text t = (Text) other;
- return compareChars(t.chars);
+ if (this.len != t.len) {
+ return false;
+ }
+
+ return compareChars(t.chars, t.pos);
}
@Override
@@ -126,16 +218,27 @@
return hash;
}
- private boolean compareChars(byte[] chars) {
- if (this.chars.length != chars.length) {
- return false;
- }
- for (int i = 0; i < this.chars.length; i++) {
- if (differentChars((char) this.chars[i], (char) chars[i]))
return false;
+ /**
+ * Compares specified character string with current string.
+ * The upper and lower case charactes are considered as equals.
+ *
+ * @param chars the string to be compared
+ * @return true if specified string equals to current
+ */
+ private boolean compareChars(byte[] chars, int pos) {
+ for (int i = 0; i < len; i++) {
+ if (differentChars((char) this.chars[i + this.pos], (char)
chars[i + pos])) return false;
}
return true;
}
+ /**
+ * Compares two chars.
+ *
+ * @param c1 the first char
+ * @param c2 the second char
+ * @return tru if first and second chars are different.
+ */
private boolean differentChars(char c1, char c2) {
if (65 <= c1 && c1 <= 97) {
c1 +=32;
@@ -152,4 +255,39 @@
return new String(chars, pos, len);
}
-}
+ /**
+ * Converts string value to integer
+ * @return ineger value
+ */
+ public int toInteger() {
+ int res = 0;
+ for (int i = 0; i < len; i++) {
+ res += digit(pos + i) * pow(len - i - 1);
+ }
+ return res;
+ }
+
+ /**
+ * 10^a
+ *
+ * @param a the power
+ * @return the value of 10^a
+ */
+ private int pow(int a) {
+ int res = 1;
+ for (int i = 0; i < a; i++) {
+ res *= 10;
+ }
+ return res;
+ }
+
+ /**
+ * Converts character to digit.
+ *
+ * @param pos the position of the character
+ * @return the digit value
+ */
+ private int digit(int pos) {
+ return chars[pos] - 48;
+ }
+}
=======================================
---
/trunk/servers/media/spi/src/test/java/org/mobicents/media/server/utils/TextTest.java
Mon Jan 24 05:31:11 2011
+++
/trunk/servers/media/spi/src/test/java/org/mobicents/media/server/utils/TextTest.java
Tue Jan 25 08:39:03 2011
@@ -5,6 +5,8 @@
package org.mobicents.media.server.utils;
+import java.util.Iterator;
+import java.util.Collection;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -73,6 +75,16 @@
assertEquals(s.charAt(i), t.charAt(i));
}
}
+
+ @Test
+ public void testCharAtWithShifting() {
+ String s = "12345 One two three";
+ byte[] data = s.getBytes();
+ Text t = new Text();
+ t.strain(data, 6, data.length -6);
+
+ assertEquals('O', t.charAt(0));
+ }
/**
* Test of subSequence method, of class Text.
@@ -104,6 +116,20 @@
Text t2 = new Text("test");
assertTrue("Must be equals", t1.equals(t2));
}
+
+ @Test
+ public void testEqualsDifferentBackground() {
+ Text t1 = new Text("test");
+
+ String s = "12345678test";
+
+ Text t2 = new Text();
+ t2.strain(s.getBytes(), 8, 4);
+
+ boolean res = t1.equals(t2);
+
+ assertTrue("Must be equals", res);
+ }
@Test
public void testEqualsWithDifferentCase() {
@@ -112,6 +138,83 @@
assertTrue("Must be equals", t1.equals(t2));
}
+ @Test
+ public void testSplit() {
+ Text t1 = new Text("test test1 test2");
+
+ Collection<Text> tokens = t1.split(' ');
+ assertEquals(3, tokens.size());
+
+ Iterator<Text> i = tokens.iterator();
+
+ Text t = i.next();
+ assertEquals("test", t.toString());
+
+ t = i.next();
+ assertEquals("test1", t.toString());
+
+ t = i.next();
+ assertEquals("test2", t.toString());
+ }
+
+ @Test
+ public void testSplitExecutionTime() {
+ Text t1 = new Text("test test1 test2");
+
+ long s = System.nanoTime();
+ for (int i = 0; i < 1000; i++) {
+ Collection<Text> tokens = t1.split(' ');
+ }
+
+ long f = System.nanoTime();
+ System.out.println("Split execution time=" + (f-s));
+ assertTrue("Too slow", 3000000 > (f-s));
+ }
+
+ @Test
+ public void testTrim() {
+ Text t1 = new Text(" test ");
+ t1.trim();
+ assertEquals("test", t1.toString());
+ }
+
+ @Test
+ public void testToInteger() {
+ Text t1 = new Text("1234");
+ assertEquals(1234, t1.toInteger());
+ }
+
+ @Test
+ public void testLineSplit() {
+ Text t1 = new Text("test\ntest1\ntest2");
+
+ Text t = t1.nextLine();
+ assertEquals("test", t.toString());
+
+ t = t1.nextLine();
+ assertEquals("test1", t.toString());
+
+ t = t1.nextLine();
+ assertEquals("test2", t.toString());
+ }
+
+ @Test
+ public void testMoreLines() {
+ Text t1 = new Text("test\ntest1\ntest2");
+
+ assertTrue(t1.hasMoreLines());
+ Text t = t1.nextLine();
+ assertEquals("test", t.toString());
+
+ t = t1.nextLine();
+ assertEquals("test1", t.toString());
+
+ t = t1.nextLine();
+ assertEquals("test2", t.toString());
+
+ assertFalse(t1.hasMoreLines());
+ }
+
@Test
public void perfTests() {
byte[] data = "name1".getBytes();