diff --git a/.gitignore b/.gitignore index 9061e8306..6617a6379 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,6 @@ classes media-server-docs/sources-mobicents/src media-server-docs/sources-telscale/src client/jsr-309/tck/tck-run + +/**/*.iml +.idea diff --git a/bootstrap/src/main/config/mediaserver.xml b/bootstrap/src/main/config/mediaserver.xml index 994cc7b7a..ad084f7f9 100644 --- a/bootstrap/src/main/config/mediaserver.xml +++ b/bootstrap/src/main/config/mediaserver.xml @@ -54,7 +54,12 @@ - + + + 100 + false + + diff --git a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoader.java b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoader.java index adfc76d51..c51043a24 100644 --- a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoader.java +++ b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoader.java @@ -27,6 +27,7 @@ import org.apache.commons.configuration2.XMLConfiguration; import org.apache.commons.configuration2.builder.fluent.Configurations; import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.ex.ConfigurationRuntimeException; import org.apache.commons.configuration2.tree.ImmutableNode; import org.apache.log4j.Logger; import org.mobicents.media.core.configuration.DtlsConfiguration; @@ -136,6 +137,7 @@ private static void configureResource(HierarchicalConfiguration s dst.setDtmfGeneratorToneDuration(src.getInt("dtmfGenerator[@toneDuration]", ResourcesConfiguration.DTMF_GENERATOR_TONE_DURATION)); dst.setSignalDetectorCount(src.getInt("signalDetector[@poolSize]", ResourcesConfiguration.SIGNAL_DETECTOR_COUNT)); dst.setSignalGeneratorCount(src.getInt("signalGenerator[@poolSize]", ResourcesConfiguration.SIGNAL_GENERATOR_COUNT)); + configurePlayer(src, dst); } private static void configureDtls(HierarchicalConfiguration src, DtlsConfiguration dst){ @@ -147,4 +149,21 @@ private static void configureDtls(HierarchicalConfiguration src, dst.setAlgorithmCertificate(src.getString("certificate[@algorithm]", DtlsConfiguration.ALGORITHM_CERTIFICATE)); } + private static void configurePlayer(HierarchicalConfiguration src, ResourcesConfiguration dst) { + HierarchicalConfiguration player = src.configurationAt("player"); + dst.setPlayerCount(player.getInt("[@poolSize]", ResourcesConfiguration.PLAYER_COUNT)); + + HierarchicalConfiguration cache; + try { + cache = player.configurationAt("cache"); + } catch (ConfigurationRuntimeException exception) { + log.info("No cache was specified for player"); + return; + } + dst.setPlayerCache( + cache.getBoolean("cacheEnabled", ResourcesConfiguration.PLAYER_CACHE_ENABLED), + cache.getInt("cacheSize", ResourcesConfiguration.PLAYER_CACHE_SIZE) + ); + + } } diff --git a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/BootstrapModule.java b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/BootstrapModule.java index ddb3f892e..c476c5bd4 100644 --- a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/BootstrapModule.java +++ b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/BootstrapModule.java @@ -22,6 +22,7 @@ package org.mobicents.media.server.bootstrap.ioc; import org.mobicents.media.core.configuration.MediaServerConfiguration; +import org.mobicents.media.server.bootstrap.ioc.provider.DirectRemoteStreamProvider; import org.mobicents.media.server.bootstrap.ioc.provider.AudioPlayerFactoryProvider; import org.mobicents.media.server.bootstrap.ioc.provider.AudioPlayerPoolProvider; import org.mobicents.media.server.bootstrap.ioc.provider.AudioRecorderFactoryProvider; @@ -75,6 +76,8 @@ import org.mobicents.media.server.scheduler.Scheduler; import org.mobicents.media.server.spi.ServerManager; import org.mobicents.media.server.spi.dsp.DspFactory; +import org.mobicents.media.server.bootstrap.ioc.provider.CachedRemoteStreamProvider; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.RemoteStreamProvider; import com.google.inject.AbstractModule; import com.google.inject.Singleton; @@ -120,6 +123,12 @@ protected void configure() { bind(EndpointInstallerListType.INSTANCE).toProvider(EndpointInstallerListProvider.class).in(Singleton.class); bind(ServerManager.class).toProvider(MgcpControllerProvider.class).in(Singleton.class); bind(DtlsSrtpServerProvider.class).toProvider(DtlsSrtpServerProviderProvider.class).in(Singleton.class); + Class remoteStreamProvider; + if (this.config.getResourcesConfiguration().getPlayerCacheEnabled()) { + remoteStreamProvider = CachedRemoteStreamProvider.class; + } else { + remoteStreamProvider = DirectRemoteStreamProvider.class; + } + bind(RemoteStreamProvider.class).toProvider(remoteStreamProvider).in(Singleton.class); } - } diff --git a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/AudioPlayerFactoryProvider.java b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/AudioPlayerFactoryProvider.java index c7baf3ac9..7878fe95a 100644 --- a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/AudioPlayerFactoryProvider.java +++ b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/AudioPlayerFactoryProvider.java @@ -21,6 +21,7 @@ package org.mobicents.media.server.bootstrap.ioc.provider; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.RemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerImpl; import org.mobicents.media.server.scheduler.PriorityQueueScheduler; @@ -39,16 +40,18 @@ public class AudioPlayerFactoryProvider implements Provider private final PriorityQueueScheduler mediaScheduler; private final DspFactory dspFactory; + private final RemoteStreamProvider remoteStreamProvider; @Inject - public AudioPlayerFactoryProvider(PriorityQueueScheduler mediaScheduler, DspFactory dspFactory) { + public AudioPlayerFactoryProvider(PriorityQueueScheduler mediaScheduler, DspFactory dspFactory, RemoteStreamProvider remoteStreamProvider) { this.mediaScheduler = mediaScheduler; this.dspFactory = dspFactory; + this.remoteStreamProvider = remoteStreamProvider; } @Override public AudioPlayerFactory get() { - return new AudioPlayerFactory(mediaScheduler, dspFactory); + return new AudioPlayerFactory(mediaScheduler, dspFactory, remoteStreamProvider); } public static final class AudioPlayerFactoryType extends TypeLiteral> { diff --git a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/CachedRemoteStreamProvider.java b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/CachedRemoteStreamProvider.java new file mode 100644 index 000000000..9290c75f1 --- /dev/null +++ b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/CachedRemoteStreamProvider.java @@ -0,0 +1,23 @@ +package org.mobicents.media.server.bootstrap.ioc.provider; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import org.mobicents.media.core.configuration.MediaServerConfiguration; + +/** + * Created by achikin on 6/3/16. + */ +public class CachedRemoteStreamProvider implements Provider { + + private static org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider instance; + + @Inject + public CachedRemoteStreamProvider(MediaServerConfiguration config) { + instance = new org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider(config.getResourcesConfiguration().getPlayerCacheSize()); + } + + @Override + public org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider get() { + return instance; + } +} diff --git a/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/DirectRemoteStreamProvider.java b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/DirectRemoteStreamProvider.java new file mode 100644 index 000000000..2401484e3 --- /dev/null +++ b/bootstrap/src/main/java/org/mobicents/media/server/bootstrap/ioc/provider/DirectRemoteStreamProvider.java @@ -0,0 +1,20 @@ +package org.mobicents.media.server.bootstrap.ioc.provider; + +import com.google.inject.Provider; + +/** + * Created by achikin on 6/7/16. + */ +public class DirectRemoteStreamProvider implements Provider { + + private org.mobicents.media.server.impl.resource.mediaplayer.audio.DirectRemoteStreamProvider instance; + + public DirectRemoteStreamProvider() { + instance = new org.mobicents.media.server.impl.resource.mediaplayer.audio.DirectRemoteStreamProvider(); + } + + @Override + public org.mobicents.media.server.impl.resource.mediaplayer.audio.DirectRemoteStreamProvider get() { + return instance; + } +} diff --git a/bootstrap/src/test/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoaderTest.java b/bootstrap/src/test/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoaderTest.java index a2fb62409..9819a74b2 100644 --- a/bootstrap/src/test/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoaderTest.java +++ b/bootstrap/src/test/java/org/mobicents/media/server/bootstrap/configuration/XmlConfigurationLoaderTest.java @@ -93,7 +93,6 @@ public void testLoadConfiguration() throws Exception { ResourcesConfiguration resources = config.getResourcesConfiguration(); Assert.assertEquals(200, resources.getLocalConnectionCount()); Assert.assertEquals(100, resources.getRemoteConnectionCount()); - Assert.assertEquals(100, resources.getPlayerCount()); Assert.assertEquals(100, resources.getRecorderCount()); Assert.assertEquals(100, resources.getDtmfDetectorCount()); Assert.assertEquals(-25, resources.getDtmfDetectorDbi()); @@ -115,6 +114,10 @@ public void testLoadConfiguration() throws Exception { Assert.assertEquals(DtlsConfiguration.KEY_PATH, dtls.getKeyPath()); Assert.assertEquals(SignatureAlgorithm.ecdsa, dtls.getAlgorithmCertificate().getSignatureAlgorithm()); Assert.assertEquals(ClientCertificateType.ecdsa_sign, dtls.getAlgorithmCertificate().getClientCertificate()); + + Assert.assertEquals(100, resources.getPlayerCount()); + Assert.assertEquals(100, resources.getPlayerCacheSize()); + Assert.assertEquals(true, resources.getPlayerCacheEnabled()); } /** diff --git a/bootstrap/src/test/resources/mediaserver.xml b/bootstrap/src/test/resources/mediaserver.xml index 3009c588e..74f43fcb6 100644 --- a/bootstrap/src/test/resources/mediaserver.xml +++ b/bootstrap/src/test/resources/mediaserver.xml @@ -48,7 +48,12 @@ - + + + 100 + true + + diff --git a/client/pom.xml b/client/pom.xml index b9c273fae..663d161b0 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -14,7 +14,7 @@ Client - jsr-309 + mgcp diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/BridgeEndpointTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/BridgeEndpointTest.java index eccf2038e..d79389366 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/BridgeEndpointTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/BridgeEndpointTest.java @@ -39,6 +39,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -49,7 +50,6 @@ import org.mobicents.media.server.mgcp.connection.LocalConnectionPool; import org.mobicents.media.server.mgcp.connection.RtpConnectionFactory; import org.mobicents.media.server.mgcp.connection.RtpConnectionPool; -import org.mobicents.media.server.mgcp.endpoint.BridgeEndpoint; import org.mobicents.media.server.mgcp.endpoint.connection.RTPEnvironment; import org.mobicents.media.server.mgcp.resources.ResourcesPool; import org.mobicents.media.server.spi.Connection; @@ -141,7 +141,7 @@ public void setUp() throws ResourceUnavailableException, TooManyConnectionsExcep this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/LocalMediaGroupTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/LocalMediaGroupTest.java index 0a02771ee..dae3eb7d5 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/LocalMediaGroupTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/LocalMediaGroupTest.java @@ -46,6 +46,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; import org.mobicents.media.server.impl.resource.dtmf.GeneratorImpl; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -61,9 +62,6 @@ import org.mobicents.media.server.mgcp.connection.LocalConnectionPool; import org.mobicents.media.server.mgcp.connection.RtpConnectionFactory; import org.mobicents.media.server.mgcp.connection.RtpConnectionPool; -import org.mobicents.media.server.mgcp.endpoint.BaseMixerEndpointImpl; -import org.mobicents.media.server.mgcp.endpoint.BridgeEndpoint; -import org.mobicents.media.server.mgcp.endpoint.IvrEndpoint; import org.mobicents.media.server.mgcp.resources.ResourcesPool; import org.mobicents.media.server.scheduler.Clock; import org.mobicents.media.server.scheduler.PriorityQueueScheduler; @@ -156,7 +154,7 @@ public void setUp() throws ResourceUnavailableException, IOException { this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/MediaGroupTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/MediaGroupTest.java index 824dac455..34d32e778 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/MediaGroupTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/MediaGroupTest.java @@ -46,6 +46,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; import org.mobicents.media.server.impl.resource.dtmf.GeneratorImpl; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -61,8 +62,6 @@ import org.mobicents.media.server.mgcp.connection.LocalConnectionPool; import org.mobicents.media.server.mgcp.connection.RtpConnectionFactory; import org.mobicents.media.server.mgcp.connection.RtpConnectionPool; -import org.mobicents.media.server.mgcp.endpoint.BaseMixerEndpointImpl; -import org.mobicents.media.server.mgcp.endpoint.IvrEndpoint; import org.mobicents.media.server.mgcp.resources.ResourcesPool; import org.mobicents.media.server.scheduler.Clock; import org.mobicents.media.server.scheduler.Scheduler; @@ -155,7 +154,7 @@ public void setUp() throws ResourceUnavailableException, IOException, Interrupte this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSMTest1.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSMTest1.java index b96a3ec41..0f742ad4d 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSMTest1.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSMTest1.java @@ -44,6 +44,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -139,7 +140,7 @@ public void setUp() throws ResourceUnavailableException, IOException, TooManyCon this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSM_FR_Test.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSM_FR_Test.java index d7098212b..05ffba874 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSM_FR_Test.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionFSM_FR_Test.java @@ -44,6 +44,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -142,7 +143,7 @@ public void setUp() throws ResourceUnavailableException, IOException { this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionTest.java index bf3ebd8ae..e82f70579 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BaseConnectionTest.java @@ -44,6 +44,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -109,7 +110,7 @@ public class BaseConnectionTest implements ConnectionListener { private PhoneSignalDetectorPool signalDetectorPool; private PhoneSignalGeneratorFactory signalGeneratorFactory; private PhoneSignalGeneratorPool signalGeneratorPool; - + //Dtls Server Provider protected ProtocolVersion minVersion = ProtocolVersion.DTLSv10; protected ProtocolVersion maxVersion = ProtocolVersion.DTLSv12; @@ -126,6 +127,7 @@ public class BaseConnectionTest implements ConnectionListener { @Before public void setUp() throws ResourceUnavailableException, IOException, TooManyConnectionsException { //use default clock + clock = new WallClock(); //create single thread scheduler @@ -141,7 +143,7 @@ public void setUp() throws ResourceUnavailableException, IOException, TooManyCon this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BridgeTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BridgeTest.java index 6a2e8fb84..4e02548e6 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BridgeTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/BridgeTest.java @@ -43,6 +43,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -105,7 +106,7 @@ public void setUp() throws ResourceUnavailableException, TooManyConnectionsExcep this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalConnectionImplTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalConnectionImplTest.java index 3d489e0ec..0f6207afd 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalConnectionImplTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalConnectionImplTest.java @@ -40,6 +40,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -129,7 +130,7 @@ public void setUp() throws ResourceUnavailableException, TooManyConnectionsExcep this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalJoiningTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalJoiningTest.java index 549001ad3..fbd838d00 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalJoiningTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/LocalJoiningTest.java @@ -46,6 +46,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -117,7 +118,7 @@ public class LocalJoiningTest { private PhoneSignalDetectorPool signalDetectorPool; private PhoneSignalGeneratorFactory signalGeneratorFactory; private PhoneSignalGeneratorPool signalGeneratorPool; - + Component sine1,sine2; Component analyzer1,analyzer2; @@ -127,7 +128,6 @@ public class LocalJoiningTest { public void setUp() throws ResourceUnavailableException, TooManyConnectionsException, IOException { //use default clock clock = new WallClock(); - //create single thread scheduler mediaScheduler = new PriorityQueueScheduler(); mediaScheduler.setClock(clock); @@ -141,7 +141,7 @@ public void setUp() throws ResourceUnavailableException, TooManyConnectionsExcep this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RTPJoiningTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RTPJoiningTest.java index 586f98b21..aa3271bb7 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RTPJoiningTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RTPJoiningTest.java @@ -43,6 +43,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -104,7 +105,7 @@ public void setUp() throws ResourceUnavailableException, TooManyConnectionsExcep this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/ReclaimingTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/ReclaimingTest.java index 9ae663911..5f1057d90 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/ReclaimingTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/ReclaimingTest.java @@ -41,6 +41,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -131,7 +132,7 @@ public void setUp() throws ResourceUnavailableException, TooManyConnectionsExcep this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RtpConnectionImplTest.java b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RtpConnectionImplTest.java index f7a72d04c..e79db83bc 100644 --- a/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RtpConnectionImplTest.java +++ b/controls/mgcp/src/test/java/org/mobicents/media/server/mgcp/endpoint/connection/RtpConnectionImplTest.java @@ -42,6 +42,7 @@ import org.mobicents.media.server.impl.resource.dtmf.DtmfDetectorPool; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorFactory; import org.mobicents.media.server.impl.resource.dtmf.DtmfGeneratorPool; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerFactory; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerPool; import org.mobicents.media.server.impl.resource.phone.PhoneSignalDetectorFactory; @@ -132,7 +133,7 @@ public void setUp() throws ResourceUnavailableException, IOException { this.rtpConnectionPool = new RtpConnectionPool(0, rtpConnectionFactory); this.localConnectionFactory = new LocalConnectionFactory(channelsManager); this.localConnectionPool = new LocalConnectionPool(0, localConnectionFactory); - this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory); + this.playerFactory = new AudioPlayerFactory(mediaScheduler, dspFactory, new CachedRemoteStreamProvider(100)); this.playerPool = new AudioPlayerPool(0, playerFactory); this.recorderFactory = new AudioRecorderFactory(mediaScheduler); this.recorderPool = new AudioRecorderPool(0, recorderFactory); diff --git a/core/src/main/java/org/mobicents/media/core/configuration/ResourcesConfiguration.java b/core/src/main/java/org/mobicents/media/core/configuration/ResourcesConfiguration.java index 144022284..f7dd8c051 100644 --- a/core/src/main/java/org/mobicents/media/core/configuration/ResourcesConfiguration.java +++ b/core/src/main/java/org/mobicents/media/core/configuration/ResourcesConfiguration.java @@ -23,9 +23,8 @@ /** * Configuration related to Resources Pools. - * - * @author Henrique Rosa (henrique.rosa@telestax.com) * + * @author Henrique Rosa (henrique.rosa@telestax.com) */ public class ResourcesConfiguration { @@ -40,6 +39,8 @@ public class ResourcesConfiguration { public static final int DTMF_GENERATOR_TONE_DURATION = 80; public static final int SIGNAL_DETECTOR_COUNT = 0; public static final int SIGNAL_GENERATOR_COUNT = 0; + public static final int PLAYER_CACHE_SIZE = 0; + public static final boolean PLAYER_CACHE_ENABLED = false; private int localConnectionCount; private int remoteConnectionCount; @@ -52,6 +53,7 @@ public class ResourcesConfiguration { private int dtmfGeneratorToneDuration; private int signalDetectorCount; private int signalGeneratorCount; + private int playerCacheSize; public ResourcesConfiguration() { this.localConnectionCount = LOCAL_CONNECTION_COUNT; @@ -65,6 +67,7 @@ public ResourcesConfiguration() { this.dtmfGeneratorToneDuration = DTMF_GENERATOR_TONE_DURATION; this.signalDetectorCount = SIGNAL_DETECTOR_COUNT; this.signalGeneratorCount = SIGNAL_GENERATOR_COUNT; + this.playerCacheSize = PLAYER_CACHE_SIZE; } public int getLocalConnectionCount() { @@ -188,4 +191,24 @@ public void setSignalGeneratorCount(int signalGeneratorCount) { this.signalGeneratorCount = signalGeneratorCount; } + public void setPlayerCache(boolean playerCacheEnabled, int playerCacheSize) { + if (!playerCacheEnabled) { + this.playerCacheSize = 0; + return; + } + if (playerCacheSize <= 0) { + throw new IllegalArgumentException("Player cache size cannot be negative"); + } + this.playerCacheSize = playerCacheSize; + } + + + public int getPlayerCacheSize() { + return playerCacheSize; + } + + public boolean getPlayerCacheEnabled() { + return this.playerCacheSize != 0; + } + } diff --git a/pom.xml b/pom.xml index ce20e89a0..779587a62 100644 --- a/pom.xml +++ b/pom.xml @@ -103,18 +103,18 @@ 2.0.6.GA - org.mockito - mockito-all - 1.10.19 - test - + org.mockito + mockito-all + 1.10.19 + test + - - - com.google.inject - guice - 4.0 - + + + com.google.inject + guice + 4.0 + diff --git a/resources/mediaplayer/pom.xml b/resources/mediaplayer/pom.xml index 5296b7c88..ea90614aa 100644 --- a/resources/mediaplayer/pom.xml +++ b/resources/mediaplayer/pom.xml @@ -90,7 +90,21 @@ mbrola ${version.freetts} - + + org.ehcache + ehcache + 3.0.1 + + + org.slf4j + slf4j-log4j12 + 1.5.6 + + + commons-io + commons-io + 2.5 + diff --git a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerFactory.java b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerFactory.java index f70e8f296..9784eca56 100644 --- a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerFactory.java +++ b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerFactory.java @@ -42,15 +42,17 @@ public class AudioPlayerFactory implements PooledObjectFactory private final PriorityQueueScheduler scheduler; private final DspFactory dspFactory; + private final RemoteStreamProvider remoteStreamProvider; - public AudioPlayerFactory(PriorityQueueScheduler scheduler, DspFactory dspFactory) { + public AudioPlayerFactory(PriorityQueueScheduler scheduler, DspFactory dspFactory, RemoteStreamProvider remoteStreamProvider) { this.scheduler = scheduler; this.dspFactory = dspFactory; + this.remoteStreamProvider = remoteStreamProvider; } @Override public AudioPlayerImpl produce() { - AudioPlayerImpl player = new AudioPlayerImpl("player-" + ID.getAndIncrement(), scheduler); + AudioPlayerImpl player = new AudioPlayerImpl("player-" + ID.getAndIncrement(), scheduler, remoteStreamProvider); try { player.setDsp(this.dspFactory.newProcessor()); } catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) { diff --git a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerImpl.java b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerImpl.java index 9fe012b78..150ff8b9d 100644 --- a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerImpl.java +++ b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/AudioPlayerImpl.java @@ -76,6 +76,8 @@ public class AudioPlayerImpl extends AbstractSource implements Player, TTSEngine // Listeners private final Listeners listeners; + private final RemoteStreamProvider remoteStreamProvider; + /** * Creates new instance of the Audio player. * @@ -83,11 +85,12 @@ public class AudioPlayerImpl extends AbstractSource implements Player, TTSEngine * @param scheduler EDF job scheduler * @param vc the TTS voice cache. */ - public AudioPlayerImpl(String name, PriorityQueueScheduler scheduler) { + public AudioPlayerImpl(String name, PriorityQueueScheduler scheduler, RemoteStreamProvider remoteStreamProvider) { super(name, scheduler, PriorityQueueScheduler.INPUT_QUEUE); this.input = new AudioInput(ComponentType.PLAYER.getType(), packetSize); this.listeners = new Listeners(); this.connect(this.input); + this.remoteStreamProvider = remoteStreamProvider; } public AudioInput getAudioInput() { @@ -140,7 +143,7 @@ public void setURL(String passedURI) throws ResourceUnavailableException, Malfor try { // check scheme, if its file, we should try to create dirs if (ext.matches(Extension.WAV)) { - track = new WavTrackImpl(targetURL); + track = new WavTrackImpl(targetURL, remoteStreamProvider); } else if (ext.matches(Extension.GSM)) { track = new GsmTrackImpl(targetURL); } else if (ext.matches(Extension.TONE)) { diff --git a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/CachedRemoteStreamProvider.java b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/CachedRemoteStreamProvider.java new file mode 100644 index 000000000..f1100cedd --- /dev/null +++ b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/CachedRemoteStreamProvider.java @@ -0,0 +1,93 @@ +package org.mobicents.media.server.impl.resource.mediaplayer.audio; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.sizeof.annotations.IgnoreSizeOf; + +/** + * Created by achikin on 5/9/16. + */ +public class CachedRemoteStreamProvider implements RemoteStreamProvider { + + private final static Logger log = Logger.getLogger(CachedRemoteStreamProvider.class); + + private CacheManager cacheManager; + + private ByteStreamCache.ISizeChangedListener sizeChangedListener; + + public CachedRemoteStreamProvider(int size) { + log.info("Create AudioCache with size: " + size + "Mb"); + cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withCache("preConfigured", + CacheConfigurationBuilder.newCacheConfigurationBuilder(URL.class, ByteStreamCache.class, + ResourcePoolsBuilder.newResourcePoolsBuilder().heap(size, MemoryUnit.MB)) + .build()) + .build(true); + sizeChangedListener = new ByteStreamCache.ISizeChangedListener() { + @Override + public void onSizeChanged(final URL uri, final ByteStreamCache self) { + log.debug("onSizeChanged for " + uri); + getCache().put(uri, self); + } + }; + } + + private Cache getCache() { + return cacheManager.getCache("preConfigured", URL.class, ByteStreamCache.class); + } + + public InputStream getStream(URL uri) throws IOException { + Cache cache = getCache(); + + ByteStreamCache stream = cache.get(uri); + if (stream == null) { + stream = new ByteStreamCache(); + ByteStreamCache exists = cache.putIfAbsent(uri, stream); + if (exists != null) { + stream = exists; + } + } + return new ByteArrayInputStream(stream.getBytes(uri, sizeChangedListener)); + } + + private static class ByteStreamCache { + + @IgnoreSizeOf + private Lock lock = new ReentrantLock(); + + private volatile byte[] bytes; + + public byte[] getBytes(final URL uri, final ISizeChangedListener listener) throws IOException { + if (bytes == null) { + lock.lock(); + try { + //need to check twice + if (bytes == null) { + bytes = IOUtils.toByteArray(uri.openStream()); + listener.onSizeChanged(uri, this); + } + } finally { + lock.unlock(); + } + } + return bytes; + } + + interface ISizeChangedListener { + void onSizeChanged(URL uri, ByteStreamCache self); + } + } +} diff --git a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/DirectRemoteStreamProvider.java b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/DirectRemoteStreamProvider.java new file mode 100644 index 000000000..85c641945 --- /dev/null +++ b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/DirectRemoteStreamProvider.java @@ -0,0 +1,16 @@ +package org.mobicents.media.server.impl.resource.mediaplayer.audio; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * Created by achikin on 6/7/16. + */ +public class DirectRemoteStreamProvider implements RemoteStreamProvider { + + @Override + public InputStream getStream(URL uri) throws IOException { + return uri.openStream(); + } +} diff --git a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/RemoteStreamProvider.java b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/RemoteStreamProvider.java new file mode 100644 index 000000000..3327f4e12 --- /dev/null +++ b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/RemoteStreamProvider.java @@ -0,0 +1,11 @@ +package org.mobicents.media.server.impl.resource.mediaplayer.audio; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * Created by achikin on 5/9/16. + */ +public interface RemoteStreamProvider { + InputStream getStream(URL uri) throws IOException; +} diff --git a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/wav/WavTrackImpl.java b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/wav/WavTrackImpl.java index 435d6946e..7d13e1b2c 100644 --- a/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/wav/WavTrackImpl.java +++ b/resources/mediaplayer/src/main/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/wav/WavTrackImpl.java @@ -30,6 +30,7 @@ import org.apache.log4j.Logger; import org.mobicents.media.server.impl.resource.mediaplayer.Track; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.RemoteStreamProvider; import org.mobicents.media.server.spi.format.AudioFormat; import org.mobicents.media.server.spi.format.Format; import org.mobicents.media.server.spi.format.FormatFactory; @@ -64,8 +65,8 @@ public class WavTrackImpl implements Track { private final static byte[] factBytes = new byte[] { 0x66, 0x61, 0x63, 0x74 }; private byte paddingByte = PCM_PADDING_BYTE; - public WavTrackImpl(URL url) throws UnsupportedAudioFileException, IOException { - inStream = url.openStream(); + public WavTrackImpl(URL url, RemoteStreamProvider streamProvider) throws UnsupportedAudioFileException, IOException { + inStream = streamProvider.getStream(url); getFormat(inStream); if (format == null) { diff --git a/resources/mediaplayer/src/test/java/org/mobicents/media/server/impl/resource/mediaplayer/MediaPlayerImplTest.java b/resources/mediaplayer/src/test/java/org/mobicents/media/server/impl/resource/mediaplayer/MediaPlayerImplTest.java index 6a286de85..0f6e668f9 100644 --- a/resources/mediaplayer/src/test/java/org/mobicents/media/server/impl/resource/mediaplayer/MediaPlayerImplTest.java +++ b/resources/mediaplayer/src/test/java/org/mobicents/media/server/impl/resource/mediaplayer/MediaPlayerImplTest.java @@ -27,24 +27,21 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import static org.junit.Assert.*; import org.mobicents.media.server.impl.resource.mediaplayer.audio.AudioPlayerImpl; -import org.mobicents.media.server.spi.MediaType; -import org.mobicents.media.server.spi.memory.Frame; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; import org.mobicents.media.server.scheduler.PriorityQueueScheduler; -import org.mobicents.media.server.scheduler.Clock; import org.mobicents.media.server.scheduler.WallClock; /** - * * @author yulian oifa */ public class MediaPlayerImplTest { - // + // private AudioPlayerImpl audioPlayer; - + private PriorityQueueScheduler scheduler; + public MediaPlayerImplTest() { } @@ -57,27 +54,28 @@ public static void tearDownClass() throws Exception { } @Before - public void setUp() throws Exception { - scheduler = new PriorityQueueScheduler(); - scheduler.setClock(new WallClock()); + public void setUp() throws Exception { + CachedRemoteStreamProvider cache = new CachedRemoteStreamProvider(100); + scheduler = new PriorityQueueScheduler(); + scheduler.setClock(new WallClock()); scheduler.start(); - - audioPlayer = new AudioPlayerImpl("test", scheduler); + + audioPlayer = new AudioPlayerImpl("test", scheduler, cache); } @After - public void tearDown() { + public void tearDown() { // server.stop(); - scheduler.stop(); - audioPlayer = null; - + scheduler.stop(); + audioPlayer = null; + } /** * Test of getMediaTypes method, of class MediaPlayerImpl. */ @Test - public void testAudio() throws Exception { + public void testAudio() throws Exception { } /** diff --git a/resources/mediaplayer/src/test/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/wav/WavTrackCacheTest.java b/resources/mediaplayer/src/test/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/wav/WavTrackCacheTest.java new file mode 100644 index 000000000..ec5255501 --- /dev/null +++ b/resources/mediaplayer/src/test/java/org/mobicents/media/server/impl/resource/mediaplayer/audio/wav/WavTrackCacheTest.java @@ -0,0 +1,131 @@ +package org.mobicents.media.server.impl.resource.mediaplayer.audio.wav; + +import org.junit.Before; +import org.junit.Test; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.CachedRemoteStreamProvider; +import org.mobicents.media.server.impl.resource.mediaplayer.audio.DirectRemoteStreamProvider; +import org.mobicents.media.server.spi.format.EncodingName; +import org.mobicents.media.server.spi.format.Format; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.mockito.verification.VerificationMode; + +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +/** + * Created by hamsterksu on 30.06.16. + */ +public class WavTrackCacheTest { + + private long expectedDuration = 3854625000L; + private Format expectedFormat = new Format(new EncodingName("linear")); + + URLStreamHandler handler; + URLConnection mockConnection; + + @Before + public void setUp() throws IOException, UnsupportedAudioFileException { + mockConnection = mock(URLConnection.class); + + //we need use answer to return new stream each time + when(mockConnection.getInputStream()).thenAnswer(new Answer() { + @Override + public InputStream answer(InvocationOnMock invocationOnMock) throws Throwable { + return new FileInputStream(new File("src/test/resources/demo-prompt.wav")); + } + }); + + handler = new URLStreamHandler() { + @Override + protected URLConnection openConnection(final URL arg0) throws IOException { + return mockConnection; + } + }; + } + + @Test + public void testCache() throws IOException, UnsupportedAudioFileException { + CachedRemoteStreamProvider cache = new CachedRemoteStreamProvider(10); + + URL url1 = new URL(null, "http://test.wav", handler); + URL url2 = new URL(null, "http://test.wav", handler); + + WavTrackImpl track1 = new WavTrackImpl(url1, cache); + assertEquals(expectedFormat.getName(), track1.getFormat().getName()); + assertEquals(expectedDuration, track1.getDuration()); + + WavTrackImpl track2 = new WavTrackImpl(url2, cache); + assertEquals(expectedFormat.getName(), track2.getFormat().getName()); + assertEquals(expectedDuration, track2.getDuration()); + + WavTrackImpl track3 = new WavTrackImpl(url2, cache); + assertEquals(expectedFormat.getName(), track3.getFormat().getName()); + assertEquals(expectedDuration, track3.getDuration()); + + verify(mockConnection).getInputStream(); + } + + @Test + public void testCacheOverflow() throws IOException, UnsupportedAudioFileException { + //file size is 61712 bytes + //1Mb cache contains have 15 full files + int cacheSize = 1; + double fileSize = 61712d; + int iteration = (int) Math.floor(cacheSize * 1024d * 1024d / fileSize) - 1; + + CachedRemoteStreamProvider cache = new CachedRemoteStreamProvider(1); + + for (int j = 0; j < 10; j++) { + for (int i = 0; i < iteration; i++) { + URL url = new URL(null, "http://test" + i + ".wav", handler); + WavTrackImpl track = new WavTrackImpl(url, cache); + assertEquals(expectedFormat.getName(), track.getFormat().getName()); + assertEquals(expectedDuration, track.getDuration()); + } + } + verify(mockConnection, Mockito.times(iteration)).getInputStream(); + for (int i = iteration; i < 2 * iteration; i++) { + URL url = new URL(null, "http://test" + i + ".wav", handler); + WavTrackImpl track = new WavTrackImpl(url, cache); + assertEquals(expectedFormat.getName(), track.getFormat().getName()); + assertEquals(expectedDuration, track.getDuration()); + } + verify(mockConnection, Mockito.times(2 * iteration)).getInputStream(); + } + + @Test + public void testNoCache() throws IOException, UnsupportedAudioFileException { + DirectRemoteStreamProvider noCache = new DirectRemoteStreamProvider(); + + URL url1 = new URL(null, "http://test.wav", handler); + URL url2 = new URL(null, "http://test.wav", handler); + + WavTrackImpl track1 = new WavTrackImpl(url1, noCache); + assertEquals(expectedFormat.getName(), track1.getFormat().getName()); + assertEquals(expectedDuration, track1.getDuration()); + + WavTrackImpl track2 = new WavTrackImpl(url2, noCache); + assertEquals(expectedFormat.getName(), track2.getFormat().getName()); + assertEquals(expectedDuration, track2.getDuration()); + + WavTrackImpl track3 = new WavTrackImpl(url2, noCache); + assertEquals(expectedFormat.getName(), track3.getFormat().getName()); + assertEquals(expectedDuration, track3.getDuration()); + + verify(mockConnection, times(3)).getInputStream(); + } + +} diff --git a/resources/mediaplayer/src/test/resources/demo-prompt.wav b/resources/mediaplayer/src/test/resources/demo-prompt.wav new file mode 100644 index 000000000..6f59fee49 Binary files /dev/null and b/resources/mediaplayer/src/test/resources/demo-prompt.wav differ