Skip to content

Commit

Permalink
Merge pull request #674 from RestComm/github-107
Browse files Browse the repository at this point in the history
Support for OPUS Codec. Close #107
  • Loading branch information
hrosa authored Nov 10, 2017
2 parents 2bb15ec + 9dcbace commit 76dc378
Show file tree
Hide file tree
Showing 25 changed files with 930 additions and 9 deletions.
5 changes: 5 additions & 0 deletions bootstrap/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
<artifactId>ilbc</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.restcomm.media.codecs.opus</groupId>
<artifactId>opus-java</artifactId>
<version>${project.version}</version>
</dependency>

<!-- External Dependencies -->
<dependency>
Expand Down
16 changes: 16 additions & 0 deletions bootstrap/src/main/assembly/descriptor.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@
<outputDirectory>/lib</outputDirectory>
<unpack>false</unpack>
<scope>runtime</scope>
<excludes>
<exclude>*:so</exclude>
<exclude>*:dylib</exclude>
</excludes>
</dependencySet>
<dependencySet>
<outputDirectory>lib/native</outputDirectory>
<outputFileNameMapping>${artifact.artifactId}.${artifact.extension}</outputFileNameMapping>
<unpack>false</unpack>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
<useStrictFiltering>false</useStrictFiltering>
<includes>
<include>*:so</include>
<include>*:dylib</include>
</includes>
</dependencySet>
</dependencySets>
<componentDescriptors>
Expand Down
4 changes: 2 additions & 2 deletions bootstrap/src/main/config/autoconfig/mediaserver.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ MEDIA_MAX_DURATION=14440
MEDIA_LOW_PORT=64534
MEDIA_HIGH_PORT=65534
MEDIA_JITTER_SIZE=50
MEDIA_CODECS=pcmu,pcma,telephone-event
MEDIA_CODECS=opus,pcmu,pcma,telephone-event

# Resources
AUDIO_CACHE_SIZE=100
Expand All @@ -42,4 +42,4 @@ DTLS_ALGORITHM=ecdsa
#ASR_DRIVER_SOMEPROVIDER_PROPERTY_PARAMETER2_VALUE=parameter2_value

# Java
MS_OPTS="-Xms3400m -Xmx3400m -XX:+UseG1GC -XX:ParallelGCThreads=8 -XX:ConcGCThreads=8 -XX:G1RSetUpdatingPauseTimePercent=10 -XX:+ParallelRefProcEnabled -XX:G1HeapRegionSize=4m -XX:G1HeapWastePercent=5 -XX:InitiatingHeapOccupancyPercent=85 -XX:+UnlockExperimentalVMOptions -XX:G1MixedGCLiveThresholdPercent=85 -XX:+AlwaysPreTouch -XX:+UseCompressedOops -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dhttp.keepAlive=false"
MS_OPTS="-Xms3400m -Xmx3400m -XX:+UseG1GC -XX:ParallelGCThreads=8 -XX:ConcGCThreads=8 -XX:G1RSetUpdatingPauseTimePercent=10 -XX:+ParallelRefProcEnabled -XX:G1HeapRegionSize=4m -XX:G1HeapWastePercent=5 -XX:InitiatingHeapOccupancyPercent=85 -XX:+UnlockExperimentalVMOptions -XX:G1MixedGCLiveThresholdPercent=85 -XX:+AlwaysPreTouch -XX:+UseCompressedOops -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dhttp.keepAlive=false"
3 changes: 2 additions & 1 deletion bootstrap/src/main/config/mediaserver.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<codec name="pcmu" />
<codec name="pcma" />
<codec name="gsm" />
<codec name="opus" />
<!-- RestComm Media Server ships with G.729 codec. G.729 includes patents
from several companies and is licensed by Sipro Lab Telecom. Sipro Lab Telecom
is the authorized Intellectual Property Licensing Administrator for G.729
Expand Down Expand Up @@ -80,4 +81,4 @@
-->
</subsystem>
</subsystems>
</mediaserver>
</mediaserver>
7 changes: 6 additions & 1 deletion bootstrap/src/main/config/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,14 @@ esac

# Force IPv4 on Linux systems since IPv6 doesn't work correctly with jdk5 and lower
if [ "$linux" = "true" ]; then
JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true"
JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true -Djava.library.path=/usr/lib/x86_64-linux-gnu:../lib/native -Drestcomm.opus.library=opus_jni_linux"
fi

if [ "$darwin" = "true" ]; then
JAVA_OPTS="$JAVA_OPTS -Djava.library.path=../lib/native -Drestcomm.opus.library=opus_jni_macos"
fi


# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$MMS_HOME" ] &&
Expand Down
3 changes: 2 additions & 1 deletion bootstrap/src/test/resources/mediaserver.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<codec name="pcmu" />
<codec name="pcma" />
<codec name="gsm" />
<codec name="opus" />
<codec name="g729" />
<codec name="telephone-event" />
</codecs>
Expand Down Expand Up @@ -73,4 +74,4 @@
</driver>
</subsystem>
</subsystems>
</mediaserver>
</mediaserver>
84 changes: 84 additions & 0 deletions codecs/opus/opus-java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

<parent>
<groupId>org.restcomm.media.codecs</groupId>
<artifactId>opus</artifactId>
<version>7.0.0-SNAPSHOT</version>
</parent>

<groupId>org.restcomm.media.codecs.opus</groupId>
<artifactId>opus-java</artifactId>
<name>Opus Java</name>

<profiles>
<profile>
<id>linux-profile</id>
<activation>
<os>
<name>Linux</name>
<family>unix</family>
</os>
</activation>
<properties>
<libopus.artifactId>libopus_jni_linux</libopus.artifactId>
<libopus.packaging>so</libopus.packaging>
<libopus.distro>linux</libopus.distro>
<libopus.libName>opus_jni_linux</libopus.libName>
</properties>
</profile>

<profile>
<id>macosx-profile</id>
<activation>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<libopus.artifactId>libopus_jni_macos</libopus.artifactId>
<libopus.packaging>dylib</libopus.packaging>
<libopus.distro>macosx</libopus.distro>
<libopus.libName>opus_jni_macos</libopus.libName>
</properties>
</profile>
</profiles>

<dependencies>
<dependency>
<groupId>org.restcomm.media</groupId>
<artifactId>spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.restcomm.media.codecs.opus</groupId>
<artifactId>${libopus.artifactId}</artifactId>
<version>${project.version}</version>
<type>${libopus.packaging}</type>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Djava.library.path=../opus-native/${libopus.distro}/target -Drestcomm.opus.library=${libopus.libName}</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<finalName>restcomm-mediaserver-codecs-opus-${project.version}</finalName>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* TeleStax, Open Source Cloud Communications
* Copyright 2011-2017, Telestax Inc and individual contributors
* by the @authors tag.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.restcomm.media.codec.opus;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.apache.log4j.Logger;
import org.restcomm.media.spi.dsp.Codec;
import org.restcomm.media.spi.format.Format;
import org.restcomm.media.spi.format.FormatFactory;
import org.restcomm.media.spi.memory.Frame;
import org.restcomm.media.spi.memory.Memory;

/**
* Implements Opus decoder.
*
* @author Vladimir Morosev (vladimir.morosev@telestax.com)
*
*/
public class Decoder implements Codec {

private final static Logger log = Logger.getLogger(Encoder.class);

private final static Format opus = FormatFactory.createAudioFormat("opus", 48000, 8, 2);
private final static Format linear = FormatFactory.createAudioFormat("linear", 8000, 16, 1);

private long decoderAddress;

private final int OPUS_SAMPLE_RATE = 8000;

public Decoder() {
decoderAddress = OpusJni.createDecoderNative(OPUS_SAMPLE_RATE, 1);
}

@Override
protected void finalize() throws Throwable {
if (decoderAddress != 0) OpusJni.releaseDecoderNative(decoderAddress);
super.finalize();
}

@Override
public Format getSupportedInputFormat() {
return opus;
}

@Override
public Format getSupportedOutputFormat() {
return linear;
}

@Override
public Frame process(Frame frame) {

short[] decodedData = OpusJni.decodeNative(decoderAddress, frame.getData());
byte[] output = new byte[2 * decodedData.length];
ByteBuffer.wrap(output).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(decodedData);

Frame res = Memory.allocate(output.length);
System.arraycopy(output, 0, res.getData(), 0, output.length);

res.setOffset(0);
res.setLength(output.length);
res.setTimestamp(frame.getTimestamp());
res.setDuration(frame.getDuration());
res.setSequenceNumber(frame.getSequenceNumber());
res.setEOM(frame.isEOM());
res.setFormat(linear);
res.setHeader(frame.getHeader());
return res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* TeleStax, Open Source Cloud Communications
* Copyright 2011-2017, Telestax Inc and individual contributors
* by the @authors tag.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.restcomm.media.codec.opus;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.apache.log4j.Logger;
import org.restcomm.media.spi.dsp.Codec;
import org.restcomm.media.spi.format.Format;
import org.restcomm.media.spi.format.FormatFactory;
import org.restcomm.media.spi.memory.Frame;
import org.restcomm.media.spi.memory.Memory;

/**
* Implements Opus encoder.
*
* @author Vladimir Morosev (vladimir.morosev@telestax.com)
*
*/
public class Encoder implements Codec {

private final static Logger log = Logger.getLogger(Encoder.class);

private final static Format opus = FormatFactory.createAudioFormat("opus", 48000, 8, 2);
private final static Format linear = FormatFactory.createAudioFormat("linear", 8000, 16, 1);

private long encoderAddress;

private final int OPUS_SAMPLE_RATE = 8000;
private final int OPUS_BITRATE = 20000;

public Encoder() {
encoderAddress = OpusJni.createEncoderNative(OPUS_SAMPLE_RATE, 1, OpusJni.OPUS_APPLICATION_VOIP, OPUS_BITRATE);
}

@Override
protected void finalize() throws Throwable {
OpusJni.releaseEncoderNative(encoderAddress);
super.finalize();
}

@Override
public Format getSupportedInputFormat() {
return linear;
}

@Override
public Format getSupportedOutputFormat() {
return opus;
}

@Override
public Frame process(Frame frame) {

byte[] input = frame.getData();
short[] inputData = new short[frame.getLength() / 2];
ByteBuffer.wrap(input).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(inputData);
byte[] encodedData = OpusJni.encodeNative(encoderAddress, inputData);

Frame res = Memory.allocate(encodedData.length);
System.arraycopy(encodedData, 0, res.getData(), 0, encodedData.length);

res.setOffset(0);
res.setLength(encodedData.length);
res.setFormat(opus);
res.setTimestamp(frame.getTimestamp());
res.setDuration(frame.getDuration());
res.setEOM(frame.isEOM());
res.setSequenceNumber(frame.getSequenceNumber());

return res;
}
}
Loading

0 comments on commit 76dc378

Please sign in to comment.